[KMTESTS]
[reactos.git] / rostests / kmtests / ntos_ke / KeDevQueue.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite for Device Queues
5 * PROGRAMMERS: Pavel Batusov, Moscow State Technical University
6 * Denis Volhonsky, Moscow State Technical University
7 * Alexandra Safonova, Moscow State Technical University
8 */
9
10 #include <kmt_test.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #define NUMBER 255
16 #define INSERT_COUNT 5
17
18 int Check_mem(void* a, int n, int size)
19 {
20 int i;
21 for (i = 0; i < size; i++) {
22 if (*((unsigned char*)a + i) != n) {
23 return 0;
24 }
25 }
26 return 1;
27 }
28
29 void Test_Initialize()
30 {
31 PKDEVICE_QUEUE testing_queue;
32 void* double_queue;
33
34 trace("******* Testing KeInitializeDeviceQueue ************\n");
35 DPRINT1("\nStart test for KeInitializeDeviceQueue function\n");
36
37 testing_queue = ExAllocatePool(NonPagedPool, sizeof(KDEVICE_QUEUE));
38
39 testing_queue->Busy = TRUE;
40 testing_queue->Size = 0;
41
42 KeInitializeDeviceQueue(testing_queue);
43
44 /* Check for properly setting up fields */
45 ok(!testing_queue->Busy, "(Initialize testing) Test 1:\tExpected 'not busy' status\n");
46 DPRINT1("Test 1 completed\n");
47
48 ok(testing_queue->Size == sizeof(KDEVICE_QUEUE), "(Initialize testing) Test 2:\tExpected another size for KDEVICE_QUEUE\n");
49 DPRINT1("Test 2 completed\n");
50
51 ok(testing_queue->Type == DeviceQueueObject, "(Initialize testing) Test 3:\tExpected type == DeviceQueueObject\n");
52 DPRINT1("Test 3 completed\n");
53
54 /* Make sure it does not write outside allocated buffer */
55 double_queue = ExAllocatePool(NonPagedPool, sizeof(KDEVICE_QUEUE) * 2);
56
57 memset(double_queue, NUMBER, sizeof(KDEVICE_QUEUE) * 2);
58 KeInitializeDeviceQueue(double_queue);
59
60 ok(Check_mem((void*)((char*)double_queue + sizeof(KDEVICE_QUEUE)), NUMBER, sizeof(KDEVICE_QUEUE)), "(Initialize testing) Test 4:\tFunction uses someone else's memory \n");
61 DPRINT1("Test 4 completed\n");
62
63 //====================================================================
64
65 ExFreePool(testing_queue);
66 ExFreePool(double_queue);
67
68 DPRINT1("KeInitializeDeviceQueue test finished\n");
69 }
70
71 void Tests_Insert_And_Delete()
72 {
73 ULONG i, j;
74 PKDEVICE_QUEUE testing_queue;
75 PKDEVICE_QUEUE_ENTRY element;
76 KIRQL OldIrql;
77 PKDEVICE_QUEUE_ENTRY* elem_array;
78 PKDEVICE_QUEUE_ENTRY return_value;
79 PLIST_ENTRY next;
80 ULONG key;
81
82 trace("******* Testing KeInsertDeviceQueue **************** \n");
83 DPRINT1("\nStart KeInsertDeviceQueue test\n");
84
85 testing_queue = ExAllocatePool(NonPagedPool, sizeof(KDEVICE_QUEUE));
86 KeInitializeDeviceQueue(testing_queue);
87
88 element = ExAllocatePool(NonPagedPool, sizeof(KDEVICE_QUEUE_ENTRY));
89
90 /* Raise to dispatch level */
91 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
92
93 KeInsertDeviceQueue(testing_queue, element);
94 ok(!element->Inserted, "Wrong 'Inserted' status\n");
95 DPRINT1("Test 1 completed\n");
96
97 /* Fill the queue*/
98 elem_array = ExAllocatePool(NonPagedPool, sizeof(PKDEVICE_QUEUE_ENTRY) * INSERT_COUNT);
99
100 DPRINT1("Arrow of tests starting\n");
101 for (i = 0; i < INSERT_COUNT; i++) {
102 elem_array[i] = ExAllocatePool(NonPagedPool, sizeof(KDEVICE_QUEUE_ENTRY));
103 elem_array[i]->Inserted = FALSE;
104 elem_array[i]->SortKey = i;
105 KeInsertDeviceQueue(testing_queue, elem_array[i]);
106 ok(elem_array[i]->Inserted, "Element was not inserted\n");
107 }
108 DPRINT1("Arrow of tests complete\n");
109
110 ok(testing_queue->Size == sizeof(KDEVICE_QUEUE), "Wrong size of queue\n");
111
112 /* Check how the queue was filled */
113 next = &testing_queue->DeviceListHead;
114
115 DPRINT1("Bunch of tests starting\n");
116 for (i = 0; i < INSERT_COUNT; i++) {
117 next = next->Flink;
118 key = CONTAINING_RECORD(next, KDEVICE_QUEUE_ENTRY, DeviceListEntry)->SortKey;
119 ok(key == i, "Sort key was changed\n");
120 }
121 DPRINT1("Bunch of tests completed\n");
122
123 trace("****************************************************\n\n");
124 DPRINT1("KeInsertDeviceQueue test finish\n");
125
126 /* Test deletion */
127 trace("******* Testing KeRemoveDeviceQueue **************** \n");
128 DPRINT1("\nStart KeRemoveDeviceQueue test\n");
129
130 DPRINT1("Start deleting elements from queue\n");
131 for (i = 0; i < INSERT_COUNT; i++) {
132 return_value = KeRemoveDeviceQueue(testing_queue);
133 ok(return_value == elem_array[i], "Returning element != head element\n");
134 ok(return_value->Inserted == FALSE, "Returning element is still in queue\n");
135 next = &testing_queue->DeviceListHead;
136 for (j = i + 1; j < INSERT_COUNT; j++) {
137 next = next->Flink;
138 ok(CONTAINING_RECORD(next, KDEVICE_QUEUE_ENTRY, DeviceListEntry)->SortKey == j, "Queue was damaged\n");
139 }
140 }
141 DPRINT1("Deleting finish. Queue must be empty\n");
142
143 ok(KeRemoveDeviceQueue(testing_queue) == NULL, "Queue is not empty\n");
144 ok(testing_queue->Busy == FALSE, "Queue is busy\n");
145
146 trace("****************************************************\n\n");
147 DPRINT1("Finish KeRemoveDeviceQueue test\n");
148
149 trace("******* Testing KeRemoveEntryDeviceQueue *********** \n");
150 DPRINT1("\nStart KeRemoveEntryDeviceQueue test\n");
151
152 DPRINT1("Filling queue\n");
153 for (i = 0; i < INSERT_COUNT; i++) {
154 elem_array[i]->SortKey = i;
155 elem_array[i]->Inserted = FALSE;
156 KeInsertDeviceQueue(testing_queue, elem_array[i]);
157 }
158
159 /* Delete half of all elements in the queue */
160 DPRINT1("Deleting elements\n");
161 for (i = 0; i < INSERT_COUNT / 2; i++) {
162 ok(KeRemoveEntryDeviceQueue(testing_queue, elem_array[i * 2 + 1]), "Element is not deleted\n");
163 }
164
165 /* Checking queue */
166 DPRINT1("Checking\n");
167 next = &testing_queue->DeviceListHead;
168 for (i = 0; i < INSERT_COUNT / 2 + 1; i++) {
169 ok(CONTAINING_RECORD(next, KDEVICE_QUEUE_ENTRY, DeviceListEntry)->SortKey == i * 2, "Queue was damaged\n");
170 next = next->Flink;
171 }
172
173 /* Trying delete elements, which are not in this queue */
174 DPRINT1("Trying delete nonexistent elements\n");
175 for (i = 0; i < INSERT_COUNT / 2; i++) {
176 ok(!KeRemoveEntryDeviceQueue(testing_queue, elem_array[i * 2 + 1]), "Wrong remove operation\n");
177 }
178
179 trace("****************************************************\n\n");
180 /* Freeing memory */
181 for (i = 0; i < INSERT_COUNT; i++) {
182 ExFreePool(elem_array[i]);
183 }
184
185 /* Return back to previous IRQL */
186 KeLowerIrql(OldIrql);
187
188 ExFreePool(testing_queue);
189 ExFreePool(element);
190 }
191
192 START_TEST(KeDeviceQueue)
193 {
194 Test_Initialize();
195 Tests_Insert_And_Delete();
196 }
197