2 * Unit test suite for directory functions.
4 * Copyright 2002 Geoffrey Hausheer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
26 #include "wine/test.h"
32 /* Specify the number of simultaneous threads to test */
34 /* Specify whether to test the extended priorities for Win2k/XP */
35 #define USE_EXTENDED_PRIORITIES 0
36 /* Specify whether to test the stack allocation in CreateThread */
39 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
40 CreateThread. So far I have been unable to make this work, and
41 I am in doubt as to how portable it is. Also, according to MSDN,
42 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
43 Anyhow, the check is currently commented out
48 #define __EXCEPT __except
51 #include "wine/exception.h"
55 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
56 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
58 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
59 static OpenThread_t pOpenThread=NULL;
61 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
62 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
64 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
65 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
67 /* Functions not tested yet:
73 In addition there are no checks that the inheritance works properly in
85 /* Basic test that simulatneous threads can access shared memory,
86 that the thread local storage routines work correctly, and that
87 threads actually run concurrently
89 VOID WINAPI threadFunc1(t1Struct *tstruct)
92 /* write our thread # into shared memory */
93 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
94 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
95 "TlsSetValue failed\n");
96 /* The threads synchronize before terminating. This is done by
97 Signaling an event, and waiting for all events to occur
99 SetEvent(tstruct->event[tstruct->threadnum]);
100 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
101 /* Double check that all threads really did run by validating that
102 they have all written to the shared memory. There should be no race
103 here, since all threads were synchronized after the write.*/
104 for(i=0;i<NUM_THREADS;i++) {
105 while(tstruct->threadmem[i]==0) ;
107 /* Check that noone cahnged our tls memory */
108 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
109 "TlsGetValue failed\n");
110 ExitThread(NUM_THREADS+tstruct->threadnum);
113 VOID WINAPI threadFunc2()
118 VOID WINAPI threadFunc3()
121 thread=GetCurrentThread();
122 SuspendThread(thread);
126 VOID WINAPI threadFunc4(HANDLE event)
136 VOID WINAPI threadFunc5(DWORD *exitCode)
139 sysInfo.dwPageSize=0;
140 GetSystemInfo(&sysInfo);
144 alloca(2*sysInfo.dwPageSize);
154 /* Check basic funcationality of CreateThread and Tls* functions */
155 VOID test_CreateThread_basic()
157 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
158 DWORD threadid[NUM_THREADS],curthreadId;
159 DWORD threadmem[NUM_THREADS];
161 t1Struct tstruct[NUM_THREADS];
164 /* Retrieve current Thread ID for later comparisons */
165 curthreadId=GetCurrentThreadId();
166 /* Allocate some local storage */
167 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
168 /* Create events for thread synchronization */
169 for(i=0;i<NUM_THREADS;i++) {
171 /* Note that it doesn't matter what type of event we chose here. This
172 test isn't trying to thoroughly test events
174 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
175 tstruct[i].threadnum=i;
176 tstruct[i].threadmem=threadmem;
177 tstruct[i].event=event;
180 /* Test that passing arguments to threads works okay */
181 for(i=0;i<NUM_THREADS;i++) {
182 thread[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadFunc1,
183 &tstruct[i],0,&threadid[i]);
184 ok(thread[i]!=NULL,"Create Thread failed\n");
186 /* Test that the threads actually complete */
187 for(i=0;i<NUM_THREADS;i++) {
188 error=WaitForSingleObject(thread[i],5000);
189 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
190 if(error!=WAIT_OBJECT_0) {
191 TerminateThread(thread[i],i+NUM_THREADS);
193 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
194 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
196 /* Test that each thread executed in its parent's address space
197 (it was able to change threadmem and pass that change back to its parent)
198 and that each thread id was independant). Note that we prove that the
199 threads actually execute concurrently by having them block on each other
202 for(i=0;i<NUM_THREADS;i++) {
204 for(j=i+1;j<NUM_THREADS;j++) {
205 if (threadmem[i]==threadmem[j]) {
209 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
210 "Thread did not execute successfully\n");
211 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
213 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
216 /* Check that using the CREATE_SUSPENDED flag works */
217 VOID test_CreateThread_suspended()
223 thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadFunc2,NULL,
224 CREATE_SUSPENDED,&threadId);
225 ok(thread!=NULL,"Create Thread failed\n");
226 /* Check that the thread is suspended */
227 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
228 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
229 /* Check that resume thread didn't actually start the thread. I can't think
230 of a better way of checking this than just waiting. I am not sure if this
231 will work on slow computers.
233 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
234 "ResumeThread should not have actually started the thread\n");
235 /* Now actually resume the thread and make sure that it actually completes*/
236 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
237 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
238 "Thread did not resume\n");
239 if(error!=WAIT_OBJECT_0) {
240 TerminateThread(thread,1);
242 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
245 /* Check that SuspendThread and ResumeThread work */
246 VOID test_SuspendThread()
248 HANDLE thread,access_thread;
249 DWORD threadId,exitCode;
252 thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadFunc3,NULL,
254 ok(thread!=NULL,"Create Thread failed\n");
255 /* Check that the thread is suspended */
256 /* Note that this is a polling method, and there is a race between
257 SuspendThread being called (in the child, and the loop below timing out,
258 so the test could fail on a heavily loaded or slow computer.
261 for(i=0;error==0 && i<100;i++) {
262 error=SuspendThread(thread);
263 ResumeThread(thread);
269 ok(error==1,"SuspendThread did not work\n");
270 /* check that access restrictions are obeyed */
272 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
274 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
275 if (access_thread!=NULL) {
276 ok(SuspendThread(access_thread)==-1,
277 "SuspendThread did not obey access restrictions\n");
278 ok(ResumeThread(access_thread)==-1,
279 "ResumeThread did not obey access restrictions\n");
280 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
283 /* Double check that the thread really is suspended */
284 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
285 "Thread did not really suspend\n");
286 /* Resume the thread, and make sure it actually completes */
287 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
288 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
289 "Thread did not resume\n");
290 if(error!=WAIT_OBJECT_0) {
291 TerminateThread(thread,1);
293 /* Trying to suspend a terminated thread should fail */
294 error=SuspendThread(thread);
295 ok(error==0xffffffff, "wrong return code: %d\n", error);
296 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %ld\n", GetLastError());
298 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
301 /* Check that TerminateThread works properly
303 VOID test_TerminateThread()
305 HANDLE thread,access_thread,event;
306 DWORD threadId,exitCode;
309 event=CreateEventA(NULL,TRUE,FALSE,NULL);
310 thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadFunc4,
311 (LPVOID)event, 0,&threadId);
312 ok(thread!=NULL,"Create Thread failed\n");
313 /* Terminate thread has a race condition in Wine. If the thread is terminated
314 before it starts, it leaves a process behind. Therefore, we wait for the
315 thread to signal that it has started. There is no easy way to force the
316 race to occur, so we don't try to find it.
318 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
319 "TerminateThread didn't work\n");
320 /* check that access restrictions are obeyed */
322 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
324 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
325 if (access_thread!=NULL) {
326 ok(TerminateThread(access_thread,99)==0,
327 "TerminateThread did not obey access restrictions\n");
328 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
331 /* terminate a job and make sure it terminates */
332 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
333 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
334 "TerminateThread didn't work\n");
335 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
336 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
337 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
338 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
341 /* Check if CreateThread obeys the specified stack size. This code does
342 not work properly, and is currently disabled
344 VOID test_CreateThread_stack()
347 /* The only way I know of to test the stack size is to use alloca
348 and __try/__except. However, this is probably not portable,
349 and I couldn't get it to work under Wine anyhow. However, here
350 is the code which should allow for testing that CreateThread
351 respects the stack-size limit
354 DWORD threadId,exitCode;
357 sysInfo.dwPageSize=0;
358 GetSystemInfo(&sysInfo);
359 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
360 thread = CreateThread(NULL,sysInfo.dwPageSize,
361 (LPTHREAD_START_ROUTINE)threadFunc5,&exitCode,
363 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
364 "TerminateThread didn't work\n");
365 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
366 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
370 /* Check whether setting/retrieving thread priorities works */
371 VOID test_thread_priority()
373 HANDLE curthread,access_thread;
374 DWORD curthreadId,exitCode;
375 int min_priority=-2,max_priority=2;
379 curthread=GetCurrentThread();
380 curthreadId=GetCurrentThreadId();
381 /* Check thread priority */
382 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
383 is -2 to 2. However, even on a real Win2k system, using thread
384 priorities beyond the -2 to 2 range does not work. If you want to try
385 anyway, enable USE_EXTENDED_PRIORITIES
387 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
388 "GetThreadPriority Failed\n");
391 /* check that access control is obeyed */
392 access_thread=pOpenThread(THREAD_ALL_ACCESS &
393 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
395 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
396 if (access_thread!=NULL) {
397 ok(SetThreadPriority(access_thread,1)==0,
398 "SetThreadPriority did not obey access restrictions\n");
399 ok(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN,
400 "GetThreadPriority did not obey access restrictions\n");
401 if (pSetThreadPriorityBoost)
402 ok(pSetThreadPriorityBoost(access_thread,1)==0,
403 "SetThreadPriorityBoost did not obey access restrictions\n");
404 if (pGetThreadPriorityBoost)
405 ok(pGetThreadPriorityBoost(access_thread,&disabled)==0,
406 "GetThreadPriorityBoost did not obey access restrictions\n");
407 ok(GetExitCodeThread(access_thread,&exitCode)==0,
408 "GetExitCodeThread did not obey access restrictions\n");
409 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
411 #if USE_EXTENDED_PRIORITIES
412 min_priority=-7; max_priority=6;
415 for(i=min_priority;i<=max_priority;i++) {
416 ok(SetThreadPriority(curthread,i)!=0,
417 "SetThreadPriority Failed for priority: %d\n",i);
418 ok(GetThreadPriority(curthread)==i,
419 "GetThreadPriority Failed for priority: %d\n",i);
421 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
422 "SetThreadPriority Failed\n");
423 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
424 "GetThreadPriority Failed\n");
425 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
426 "SetThreadPriority Failed\n");
427 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
428 "GetThreadPriority Failed\n");
429 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
431 /* Check thread priority boost */
432 if (pGetThreadPriorityBoost && pSetThreadPriorityBoost) {
436 rc=pGetThreadPriorityBoost(curthread,&disabled);
437 if (rc!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
438 ok(rc!=0,"error=%ld\n",GetLastError());
440 ok(pSetThreadPriorityBoost(curthread,1)!=0,
441 "error=%ld\n",GetLastError());
442 rc=pGetThreadPriorityBoost(curthread,&disabled);
443 ok(rc!=0 && disabled==1,
444 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
446 ok(pSetThreadPriorityBoost(curthread,0)!=0,
447 "error=%ld\n",GetLastError());
448 rc=pGetThreadPriorityBoost(curthread,&disabled);
449 ok(rc!=0 && disabled==0,
450 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
456 /* check the GetThreadTimes function */
457 VOID test_GetThreadTimes()
459 HANDLE thread,access_thread=NULL;
460 FILETIME creationTime,exitTime,kernelTime,userTime;
464 thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadFunc2,NULL,
465 CREATE_SUSPENDED,&threadId);
467 ok(thread!=NULL,"Create Thread failed\n");
468 /* check that access control is obeyed */
470 access_thread=pOpenThread(THREAD_ALL_ACCESS &
471 (~THREAD_QUERY_INFORMATION), 0,threadId);
472 ok(access_thread!=NULL,
473 "OpenThread returned an invalid handle\n");
475 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
476 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
477 "ResumeThread didn't work\n");
478 if(access_thread!=NULL) {
479 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
480 &kernelTime,&userTime);
481 ok(error==0, "GetThreadTimes did not obey access restrictions\n");
482 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
484 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
485 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
486 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
487 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
488 /* GetThreadTimes should set all of the parameters passed to it */
489 error=GetThreadTimes(thread,&creationTime,&exitTime,
490 &kernelTime,&userTime);
491 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
492 ok(error!=0,"GetThreadTimes failed\n");
493 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
494 "creationTime was invalid\n");
495 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
496 "exitTime was invalid\n");
497 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
498 "kernelTimewas invalid\n");
499 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
500 "userTime was invalid\n");
501 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
505 /* Check the processor affinity functions */
506 /* NOTE: These functions should also be checked that they obey access control
508 VOID test_thread_processor()
510 HANDLE curthread,curproc;
511 DWORD processMask,systemMask;
515 sysInfo.dwNumberOfProcessors=0;
516 GetSystemInfo(&sysInfo);
517 ok(sysInfo.dwNumberOfProcessors>0,
518 "GetSystemInfo failed to return a valid # of processors\n");
519 /* Use the current Thread/process for all tests */
520 curthread=GetCurrentThread();
521 ok(curthread!=NULL,"GetCurrentThread failed\n");
522 curproc=GetCurrentProcess();
523 ok(curproc!=NULL,"GetCurrentProcess failed\n");
524 /* Check the Affinity Mask functions */
525 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
526 "GetProcessAffinityMask failed\n");
527 ok(SetThreadAffinityMask(curthread,processMask)==1,
528 "SetThreadAffinityMask failed\n");
529 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
530 "SetThreadAffinityMask passed for an illegal processor\n");
531 /* NOTE: This only works on WinNT/2000/XP) */
532 if (pSetThreadIdealProcessor) {
535 error=pSetThreadIdealProcessor(curthread,0);
536 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
537 ok(error!=-1, "SetThreadIdealProcessor failed\n");
540 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
541 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
543 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
545 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
546 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
555 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
556 so that the compile passes
558 lib=LoadLibraryA("kernel32");
559 ok(lib!=NULL,"Couldn't load kernel32.dll\n");
560 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
561 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
562 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
563 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
564 test_CreateThread_basic();
565 test_CreateThread_suspended();
566 test_SuspendThread();
567 test_TerminateThread();
568 test_CreateThread_stack();
569 test_thread_priority();
570 test_GetThreadTimes();
571 test_thread_processor();