[PATCH 9/9] ntdll/tests: Change bad test & add random test order

Daniel Santos daniel.santos at pobox.com
Sun Sep 13 17:16:06 CDT 2015


The test on line 244 can fail if scheduling happens to preempt the
main thread at just the right time, especially if a page fault is hit
and I/O is needed or the semaphore implementation is faster than it was
when this test was originally written.
---
 dlls/ntdll/tests/threadpool.c | 62 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index 7be3f0d..5397419 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -18,6 +18,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <stdio.h>
+#include <sys/time.h>
+
 #include "ntdll_test.h"
 
 static HMODULE hntdll = 0;
@@ -238,7 +241,7 @@ static void test_tp_simple(void)
         ok(!status, "TpSimpleTryPost failed with status %x\n", status);
     }
     pTpReleaseCleanupGroupMembers(group, TRUE, NULL);
-    ok(userdata < 100, "expected userdata < 100, got %u\n", userdata);
+    ok(userdata <= 100, "expected userdata <= 100, got %u\n", userdata);
 
     /* cleanup */
     pTpReleaseCleanupGroup(group);
@@ -1235,11 +1238,15 @@ static void CALLBACK multi_wait_cb(TP_CALLBACK_INSTANCE *instance, void *userdat
     ReleaseSemaphore(multi_wait_info.semaphore, 1, NULL);
 }
 
+#define TP_TEST_SIZE 512
 static void test_tp_multi_wait(void)
 {
     TP_CALLBACK_ENVIRON environment;
-    HANDLE semaphores[512];
-    TP_WAIT *waits[512];
+    HANDLE semaphores[TP_TEST_SIZE];
+    TP_WAIT *waits[TP_TEST_SIZE];
+    int rand_order[TP_TEST_SIZE];
+    struct timeval now;
+    unsigned int seed;
     LARGE_INTEGER when;
     HANDLE semaphore;
     NTSTATUS status;
@@ -1247,7 +1254,7 @@ static void test_tp_multi_wait(void)
     DWORD result;
     int i;
 
-    semaphore = CreateSemaphoreW(NULL, 0, 512, NULL);
+    semaphore = CreateSemaphoreW(NULL, 0, TP_TEST_SIZE, NULL);
     ok(semaphore != NULL, "failed to create semaphore\n");
     multi_wait_info.semaphore = semaphore;
 
@@ -1261,8 +1268,27 @@ static void test_tp_multi_wait(void)
     environment.Version = 1;
     environment.Pool = pool;
 
+    /* init a randomized index */
+    if (gettimeofday (&now, NULL))
+        perror("gettimeofday");
+    seed = now.tv_sec ^ now.tv_usec;
+
+    memset(&rand_order, 0, TP_TEST_SIZE * sizeof(rand_order[0]));
+    for (i = 1; i < TP_TEST_SIZE; i++)
+    {
+        int j;
+        for (j = rand_r(&seed) % TP_TEST_SIZE; ; j = (j + 1) % TP_TEST_SIZE)
+        {
+            if (!rand_order[j])
+            {
+                rand_order[j] = i;
+                break;
+            }
+        }
+    }
+
     /* create semaphores and corresponding wait objects */
-    for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+    for (i = 0; i < TP_TEST_SIZE; i++)
     {
         semaphores[i] = CreateSemaphoreW(NULL, 0, 1, NULL);
         ok(semaphores[i] != NULL, "failed to create semaphore %i\n", i);
@@ -1276,7 +1302,7 @@ static void test_tp_multi_wait(void)
     }
 
     /* release all semaphores and wait for callback */
-    for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+    for (i = 0; i < TP_TEST_SIZE; i++)
     {
         multi_wait_info.result = 0;
         ReleaseSemaphore(semaphores[i], 1, NULL);
@@ -1289,7 +1315,7 @@ static void test_tp_multi_wait(void)
     }
 
     /* repeat the same test in reverse order */
-    for (i = sizeof(semaphores)/sizeof(semaphores[0]) - 1; i >= 0; i--)
+    for (i = TP_TEST_SIZE - 1; i >= 0; i--)
     {
         multi_wait_info.result = 0;
         ReleaseSemaphore(semaphores[i], 1, NULL);
@@ -1301,15 +1327,29 @@ static void test_tp_multi_wait(void)
         pTpSetWait(waits[i], semaphores[i], NULL);
     }
 
+    /* repeat again in random order */
+    for (i = 0; i < TP_TEST_SIZE; i++)
+    {
+        int j = rand_order[i];
+        multi_wait_info.result = 0;
+        ReleaseSemaphore(semaphores[j], 1, NULL);
+
+        result = WaitForSingleObject(semaphore, 100);
+        ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+        ok(multi_wait_info.result == j, "expected result %d, got %u\n", j, multi_wait_info.result);
+
+        pTpSetWait(waits[j], semaphores[j], NULL);
+    }
+
     /* test timeout of wait objects */
     multi_wait_info.result = 0;
-    for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+    for (i = 0; i < TP_TEST_SIZE; i++)
     {
         when.QuadPart = (ULONGLONG)50 * -10000;
         pTpSetWait(waits[i], semaphores[i], &when);
     }
 
-    for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+    for (i = 0; i < TP_TEST_SIZE; i++)
     {
         result = WaitForSingleObject(semaphore, 150);
         ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
@@ -1318,14 +1358,14 @@ static void test_tp_multi_wait(void)
     ok(multi_wait_info.result >> 16, "expected multi_wait_info.result >> 16 != 0\n");
 
     /* destroy the wait objects and semaphores while waiting */
-    for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+    for (i = 0; i < TP_TEST_SIZE; i++)
     {
         pTpSetWait(waits[i], semaphores[i], NULL);
     }
 
     Sleep(50);
 
-    for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+    for (i = 0; i < TP_TEST_SIZE; i++)
     {
         pTpReleaseWait(waits[i]);
         NtClose(semaphores[i]);
-- 
2.4.6




More information about the wine-devel mailing list