[KMTESTS]
authorThomas Faber <thomas.faber@reactos.org>
Fri, 5 Aug 2011 21:07:52 +0000 (21:07 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Fri, 5 Aug 2011 21:07:52 +0000 (21:07 +0000)
- add KeEvent test (part 1/x)
- add ExFastMutex test (part 1/2)

svn path=/branches/GSoC_2011/KMTestSuite/; revision=53090

kmtests/CMakeLists.txt
kmtests/kmtest_drv.rbuild
kmtests/kmtest_drv/testlist.c
kmtests/ntos_ex/ExFastMutex.c [new file with mode: 0644]
kmtests/ntos_ke/KeEvent.c [new file with mode: 0644]

index 37e8ddb..1ab1719 100644 (file)
@@ -17,6 +17,7 @@ list(APPEND KMTEST_DRV_SOURCE
     example/Example.c
     example/KernelType.c
     ntos_ex/ExDoubleList.c
+    ntos_ex/ExFastMutex.c
     ntos_ex/ExHardError.c
     ntos_ex/ExInterlocked.c
     ntos_ex/ExPools.c
@@ -29,6 +30,7 @@ list(APPEND KMTEST_DRV_SOURCE
     ntos_io/IoMdl.c
     ntos_ke/KeApc.c
     ntos_ke/KeDpc.c
+    ntos_ke/KeEvent.c
     ntos_ke/KeIrql.c
     ntos_ke/KeProcessor.c
     ntos_ke/KeSpinLock.c
index 66def9b..3586454 100644 (file)
@@ -16,6 +16,7 @@
        </directory>
        <directory name="ntos_ex">
                <file>ExDoubleList.c</file>
+               <file>ExFastMutex.c</file>
                <file>ExHardError.c</file>
                <file>ExInterlocked.c</file>
                <file>ExPools.c</file>
@@ -34,6 +35,7 @@
        <directory name="ntos_ke">
                <file>KeApc.c</file>
                <file>KeDpc.c</file>
+               <file>KeEvent.c</file>
                <file>KeIrql.c</file>
                <file>KeProcessor.c</file>
                <file>KeSpinLock.c</file>
index 330eb05..2c208fb 100644 (file)
@@ -9,6 +9,7 @@
 
 KMT_TESTFUNC Test_Example;
 KMT_TESTFUNC Test_ExDoubleList;
+KMT_TESTFUNC Test_ExFastMutex;
 KMT_TESTFUNC Test_ExHardError;
 KMT_TESTFUNC Test_ExHardErrorInteractive;
 KMT_TESTFUNC Test_ExInterlocked;
@@ -22,6 +23,7 @@ KMT_TESTFUNC Test_IoIrp;
 KMT_TESTFUNC Test_IoMdl;
 KMT_TESTFUNC Test_KeApc;
 KMT_TESTFUNC Test_KeDpc;
+KMT_TESTFUNC Test_KeEvent;
 KMT_TESTFUNC Test_KeIrql;
 KMT_TESTFUNC Test_KeProcessor;
 KMT_TESTFUNC Test_KernelType;
@@ -33,6 +35,7 @@ KMT_TESTFUNC Test_RtlSplayTree;
 const KMT_TEST TestList[] =
 {
     { "ExDoubleList",                       Test_ExDoubleList },
+    { "ExFastMutex",                        Test_ExFastMutex },
     { "ExHardError",                        Test_ExHardError },
     { "-ExHardErrorInteractive",            Test_ExHardErrorInteractive },
     { "ExInterlocked",                      Test_ExInterlocked },
@@ -47,6 +50,7 @@ const KMT_TEST TestList[] =
     { "IoMdl",                              Test_IoMdl },
     { "KeApc",                              Test_KeApc },
     { "KeDpc",                              Test_KeDpc },
+    { "KeEvent",                            Test_KeEvent },
     { "KeIrql",                             Test_KeIrql },
     { "KeProcessor",                        Test_KeProcessor },
     { "-KernelType",                        Test_KernelType },
diff --git a/kmtests/ntos_ex/ExFastMutex.c b/kmtests/ntos_ex/ExFastMutex.c
new file mode 100644 (file)
index 0000000..ab013c3
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * PROJECT:         ReactOS kernel-mode tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Kernel-Mode Test Suite Fast Mutex test
+ * PROGRAMMER:      Thomas Faber <thfabba@gmx.de>
+ */
+
+#include <kmt_test.h>
+
+//#define NDEBUG
+#include <debug.h>
+
+NTKERNELAPI VOID    FASTCALL ExiAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex);
+NTKERNELAPI VOID    FASTCALL ExiReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex);
+NTKERNELAPI BOOLEAN FASTCALL ExiTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex);
+
+#define CheckMutex(Mutex, ExpectedCount, ExpectedOwner,                 \
+                   ExpectedContention, ExpectedOldIrql,                 \
+                   ExpectedIrql) do                                     \
+{                                                                       \
+    ok_eq_long((Mutex)->Count, ExpectedCount);                          \
+    ok_eq_pointer((Mutex)->Owner, ExpectedOwner);                       \
+    ok_eq_ulong((Mutex)->Contention, ExpectedContention);               \
+    ok_eq_ulong((Mutex)->OldIrql, (ULONG)ExpectedOldIrql);              \
+    ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");   \
+    ok_irql(ExpectedIrql);                                              \
+} while (0)
+
+static
+VOID
+TestFastMutex(
+    PFAST_MUTEX Mutex,
+    KIRQL OriginalIrql)
+{
+    PKTHREAD Thread = KeGetCurrentThread();
+
+    ok_irql(OriginalIrql);
+
+    /* acquire/release normally */
+    ExAcquireFastMutex(Mutex);
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL);
+    ok_bool_false(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned");
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL);
+    ExReleaseFastMutex(Mutex);
+    CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql);
+
+    /* ntoskrnl's fastcall version */
+    ExiAcquireFastMutex(Mutex);
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL);
+    ok_bool_false(ExiTryToAcquireFastMutex(Mutex), "ExiTryToAcquireFastMutex returned");
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL);
+    ExiReleaseFastMutex(Mutex);
+    CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql);
+
+    /* acquire/release unsafe */
+    ExAcquireFastMutexUnsafe(Mutex);
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, OriginalIrql);
+    ExReleaseFastMutexUnsafe(Mutex);
+    CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql);
+
+    /* try to acquire */
+    ok_bool_true(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned");
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL);
+    ExReleaseFastMutex(Mutex);
+    CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql);
+
+    /* shortcut functions with critical region */
+    ExEnterCriticalRegionAndAcquireFastMutexUnsafe(Mutex);
+    ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
+    ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(Mutex);
+
+    /* mismatched acquire/release */
+    ExAcquireFastMutex(Mutex);
+    CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL);
+    ExReleaseFastMutexUnsafe(Mutex);
+    CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, APC_LEVEL);
+    KmtSetIrql(OriginalIrql);
+    CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql);
+
+    Mutex->OldIrql = 0x55555555LU;
+    ExAcquireFastMutexUnsafe(Mutex);
+    CheckMutex(Mutex, 0L, Thread, 0LU, 0x55555555LU, OriginalIrql);
+    Mutex->OldIrql = PASSIVE_LEVEL;
+    ExReleaseFastMutex(Mutex);
+    CheckMutex(Mutex, 1L, NULL, 0LU, PASSIVE_LEVEL, PASSIVE_LEVEL);
+    KmtSetIrql(OriginalIrql);
+    CheckMutex(Mutex, 1L, NULL, 0LU, PASSIVE_LEVEL, OriginalIrql);
+
+    /* release without acquire */
+    ExReleaseFastMutexUnsafe(Mutex);
+    CheckMutex(Mutex, 2L, NULL, 0LU, PASSIVE_LEVEL, OriginalIrql);
+    --Mutex->Count;
+    Mutex->OldIrql = OriginalIrql;
+    ExReleaseFastMutex(Mutex);
+    CheckMutex(Mutex, 2L, NULL, 0LU, OriginalIrql, OriginalIrql);
+    ExReleaseFastMutex(Mutex);
+    CheckMutex(Mutex, 3L, NULL, 0LU, OriginalIrql, OriginalIrql);
+    Mutex->Count -= 2;
+
+    /* make sure we survive this in case of error */
+    ok_eq_long(Mutex->Count, 1L);
+    Mutex->Count = 1;
+    ok_irql(OriginalIrql);
+    KmtSetIrql(OriginalIrql);
+}
+
+START_TEST(ExFastMutex)
+{
+    FAST_MUTEX Mutex;
+    KIRQL Irql;
+
+    memset(&Mutex, 0x55, sizeof Mutex);
+    ExInitializeFastMutex(&Mutex);
+    CheckMutex(&Mutex, 1L, NULL, 0LU, 0x55555555LU, PASSIVE_LEVEL);
+
+    TestFastMutex(&Mutex, PASSIVE_LEVEL);
+    KeRaiseIrql(APC_LEVEL, &Irql);
+    TestFastMutex(&Mutex, APC_LEVEL);
+    if (!KmtIsCheckedBuild)
+    {
+        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+        TestFastMutex(&Mutex, DISPATCH_LEVEL);
+        KeRaiseIrql(HIGH_LEVEL, &Irql);
+        TestFastMutex(&Mutex, HIGH_LEVEL);
+    }
+    KeLowerIrql(PASSIVE_LEVEL);
+}
diff --git a/kmtests/ntos_ke/KeEvent.c b/kmtests/ntos_ke/KeEvent.c
new file mode 100644 (file)
index 0000000..a5cdcb7
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * PROJECT:         ReactOS kernel-mode tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Kernel-Mode Test Suite Event test
+ * PROGRAMMER:      Thomas Faber <thfabba@gmx.de>
+ */
+
+#include <kmt_test.h>
+
+/* TODO: thread testing, exports vs macros */
+
+#define CheckEvent(Event, ExpectedType, State, ExpectedWaitNext, Irql) do       \
+{                                                                               \
+    ok_eq_uint((Event)->Header.Type, ExpectedType);                             \
+    ok_eq_uint((Event)->Header.Hand, sizeof *(Event) / sizeof(ULONG));          \
+    ok_eq_long((Event)->Header.Lock & 0xFF00FF00L, 0x55005500L);                \
+    ok_eq_long((Event)->Header.SignalState, State);                             \
+    ok_eq_pointer((Event)->Header.WaitListHead.Flink,                           \
+                    &(Event)->Header.WaitListHead);                             \
+    ok_eq_pointer((Event)->Header.WaitListHead.Blink,                           \
+                    &(Event)->Header.WaitListHead);                             \
+    ok_eq_long(KeReadStateEvent(Event), State);                                 \
+    ok_eq_bool(Thread->WaitNext, ExpectedWaitNext);                             \
+    ok_irql(Irql);                                                              \
+} while (0)
+
+static
+VOID
+TestEventFunctional(
+    IN PKEVENT Event,
+    IN EVENT_TYPE Type,
+    IN KIRQL OriginalIrql)
+{
+    LONG State;
+    PKTHREAD Thread = KeGetCurrentThread();
+
+    memset(Event, 0x55, sizeof *Event);
+    KeInitializeEvent(Event, Type, FALSE);
+    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql);
+
+    memset(Event, 0x55, sizeof *Event);
+    KeInitializeEvent(Event, Type, TRUE);
+    CheckEvent(Event, Type, 1L, FALSE, OriginalIrql);
+
+    Event->Header.SignalState = 0x12345678L;
+    CheckEvent(Event, Type, 0x12345678L, FALSE, OriginalIrql);
+
+    State = KePulseEvent(Event, 0, FALSE);
+    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql);
+    ok_eq_long(State, 0x12345678L);
+
+    Event->Header.SignalState = 0x12345678L;
+    KeClearEvent(Event);
+    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql);
+
+    State = KeSetEvent(Event, 0, FALSE);
+    CheckEvent(Event, Type, 1L, FALSE, OriginalIrql);
+    ok_eq_long(State, 0L);
+
+    State = KeResetEvent(Event);
+    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql);
+    ok_eq_long(State, 1L);
+
+    Event->Header.SignalState = 0x23456789L;
+    State = KeSetEvent(Event, 0, FALSE);
+    CheckEvent(Event, Type, 1L, FALSE, OriginalIrql);
+    ok_eq_long(State, 0x23456789L);
+
+    Event->Header.SignalState = 0x3456789AL;
+    State = KeResetEvent(Event);
+    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql);
+    ok_eq_long(State, 0x3456789AL);
+
+    if (OriginalIrql <= DISPATCH_LEVEL || !KmtIsCheckedBuild)
+    {
+        Event->Header.SignalState = 0x456789ABL;
+        State = KeSetEvent(Event, 0, TRUE);
+        CheckEvent(Event, Type, 1L, TRUE, DISPATCH_LEVEL);
+        ok_eq_long(State, 0x456789ABL);
+        ok_eq_uint(Thread->WaitIrql, OriginalIrql);
+        /* repair the "damage" */
+        Thread->WaitNext = FALSE;
+        KmtSetIrql(OriginalIrql);
+
+        Event->Header.SignalState = 0x56789ABCL;
+        State = KePulseEvent(Event, 0, TRUE);
+        CheckEvent(Event, Type, 0L, TRUE, DISPATCH_LEVEL);
+        ok_eq_long(State, 0x56789ABCL);
+        ok_eq_uint(Thread->WaitIrql, OriginalIrql);
+        /* repair the "damage" */
+        Thread->WaitNext = FALSE;
+        KmtSetIrql(OriginalIrql);
+    }
+
+    ok_irql(OriginalIrql);
+    KmtSetIrql(OriginalIrql);
+}
+
+START_TEST(KeEvent)
+{
+    KEVENT Event;
+    KIRQL Irql;
+    KIRQL Irqls[] = { PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL, HIGH_LEVEL };
+    int i;
+
+    for (i = 0; i < sizeof Irqls / sizeof Irqls[0]; ++i)
+    {
+        KeRaiseIrql(Irqls[i], &Irql);
+        TestEventFunctional(&Event, NotificationEvent, Irqls[i]);
+        TestEventFunctional(&Event, SynchronizationEvent, Irqls[i]);
+        KeLowerIrql(Irql);
+    }
+
+    ok_irql(PASSIVE_LEVEL);
+    KmtSetIrql(PASSIVE_LEVEL);
+}