1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * PROJECT:         ReactOS kernel-mode tests
3*c2c66affSColin Finck  * LICENSE:         LGPLv2+ - See COPYING.LIB in the top level directory
4*c2c66affSColin Finck  * PURPOSE:         Kernel-Mode Test Suite RtlGenericTable
5*c2c66affSColin Finck  * PROGRAMMER:      arty
6*c2c66affSColin Finck  */
7*c2c66affSColin Finck 
8*c2c66affSColin Finck #define KMT_EMULATE_KERNEL
9*c2c66affSColin Finck #include <kmt_test.h>
10*c2c66affSColin Finck 
11*c2c66affSColin Finck #define NDEBUG
12*c2c66affSColin Finck #include <debug.h>
13*c2c66affSColin Finck 
14*c2c66affSColin Finck static LIST_ENTRY Allocations;
15*c2c66affSColin Finck 
16*c2c66affSColin Finck static RTL_GENERIC_COMPARE_RESULTS NTAPI
CompareCharTable(PRTL_GENERIC_TABLE Table,PVOID A,PVOID B)17*c2c66affSColin Finck CompareCharTable(PRTL_GENERIC_TABLE Table, PVOID A, PVOID B)
18*c2c66affSColin Finck {
19*c2c66affSColin Finck     RTL_GENERIC_COMPARE_RESULTS Result = (*((PCHAR)A) < *((PCHAR)B)) ? GenericLessThan :
20*c2c66affSColin Finck         (*((PCHAR)A) > *((PCHAR)B)) ? GenericGreaterThan :
21*c2c66affSColin Finck         GenericEqual;
22*c2c66affSColin Finck     return Result;
23*c2c66affSColin Finck }
24*c2c66affSColin Finck 
25*c2c66affSColin Finck static PVOID NTAPI
AllocRoutine(PRTL_GENERIC_TABLE Table,CLONG ByteSize)26*c2c66affSColin Finck AllocRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize)
27*c2c66affSColin Finck {
28*c2c66affSColin Finck     PLIST_ENTRY Entry = ExAllocatePool
29*c2c66affSColin Finck         (NonPagedPool, sizeof(LIST_ENTRY) + ByteSize);
30*c2c66affSColin Finck     InsertTailList(&Allocations, Entry);
31*c2c66affSColin Finck     return &Entry[1];
32*c2c66affSColin Finck }
33*c2c66affSColin Finck 
34*c2c66affSColin Finck static VOID NTAPI
FreeRoutine(PRTL_GENERIC_TABLE Table,PVOID Buffer)35*c2c66affSColin Finck FreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer)
36*c2c66affSColin Finck {
37*c2c66affSColin Finck     PLIST_ENTRY Entry = (PLIST_ENTRY)(((PCHAR)Buffer) - sizeof(LIST_ENTRY));
38*c2c66affSColin Finck     RemoveEntryList(Entry);
39*c2c66affSColin Finck     ExFreePool(Entry);
40*c2c66affSColin Finck }
41*c2c66affSColin Finck 
RtlSplayTreeTest()42*c2c66affSColin Finck static void RtlSplayTreeTest()
43*c2c66affSColin Finck {
44*c2c66affSColin Finck     ULONG i, del;
45*c2c66affSColin Finck     PCHAR Ch;
46*c2c66affSColin Finck     CHAR Text[] = "the quick_brown!fOx-jUmp3d/0vER+THe^lazy.D@g";
47*c2c66affSColin Finck     CHAR NewE[] = "11111111111111111111111111111111110111111111";
48*c2c66affSColin Finck     RTL_GENERIC_TABLE Table;
49*c2c66affSColin Finck     RtlInitializeGenericTable
50*c2c66affSColin Finck         (&Table,
51*c2c66affSColin Finck          CompareCharTable,
52*c2c66affSColin Finck          AllocRoutine,
53*c2c66affSColin Finck          FreeRoutine,
54*c2c66affSColin Finck          NULL);
55*c2c66affSColin Finck     for (i = 0; Text[i]; i++) {
56*c2c66affSColin Finck         BOOLEAN WasNew;
57*c2c66affSColin Finck         Ch = (PCHAR)RtlInsertElementGenericTable
58*c2c66affSColin Finck             (&Table,
59*c2c66affSColin Finck              &Text[i],
60*c2c66affSColin Finck              sizeof(Text[i]),
61*c2c66affSColin Finck              &WasNew);
62*c2c66affSColin Finck         ok(Ch && *Ch == Text[i], "Copy character into node\n");
63*c2c66affSColin Finck         ok(WasNew == (NewE[i] == '1'),
64*c2c66affSColin Finck            "Character newness didn't match for char %u: '%c'\n",
65*c2c66affSColin Finck            i, Text[i]);
66*c2c66affSColin Finck     }
67*c2c66affSColin Finck     for (Ch = (PCHAR)RtlEnumerateGenericTable(&Table, TRUE), i = 0;
68*c2c66affSColin Finck          Ch;
69*c2c66affSColin Finck          Ch = (PCHAR)RtlEnumerateGenericTable(&Table, FALSE), i++) {
70*c2c66affSColin Finck         ok(strchr(Text, *Ch) != NULL, "Nonexistent character\n");
71*c2c66affSColin Finck     }
72*c2c66affSColin Finck     ok(RtlNumberGenericTableElements(&Table) == strlen(Text) - 1, "Not the right number of elements\n");
73*c2c66affSColin Finck     ok(RtlLookupElementGenericTable(&Table, "q") != NULL, "Could not lookup q\n");
74*c2c66affSColin Finck     ok(!RtlLookupElementGenericTable(&Table, "#"), "Found a character that shouldn't appear\n");
75*c2c66affSColin Finck     ok(strlen(Text) == i + 1, "Didn't enumerate enough characters\n");
76*c2c66affSColin Finck     del = 0;
77*c2c66affSColin Finck     for (i = 0; Text[i]; i++) {
78*c2c66affSColin Finck         if (NewE[i] == '1') {
79*c2c66affSColin Finck             BOOLEAN WasDeleted;
80*c2c66affSColin Finck             WasDeleted = RtlDeleteElementGenericTable(&Table, &Text[i]);
81*c2c66affSColin Finck             del += WasDeleted;
82*c2c66affSColin Finck         }
83*c2c66affSColin Finck     }
84*c2c66affSColin Finck     ok(!RtlNumberGenericTableElements(&Table), "Not zero elements\n");
85*c2c66affSColin Finck     ok(!RtlGetElementGenericTable(&Table, 0), "Elements left when we removed them all\n");
86*c2c66affSColin Finck     ok(strlen(Text) == del + 1, "Deleted too many times\n");
87*c2c66affSColin Finck     ok(IsListEmpty(&Allocations), "Didn't free all memory\n");
88*c2c66affSColin Finck }
89*c2c66affSColin Finck 
START_TEST(RtlSplayTree)90*c2c66affSColin Finck START_TEST(RtlSplayTree)
91*c2c66affSColin Finck {
92*c2c66affSColin Finck     InitializeListHead(&Allocations);
93*c2c66affSColin Finck     RtlSplayTreeTest();
94*c2c66affSColin Finck }
95