1 krisbash 1.1 #ifdef _MSC_VER
2 #include <windows.h>
3 #endif
4
5 #include <cassert>
6 #include <cstdio>
7 #include <string>
8 #include <vector>
9 #include <list>
10 #include <algorithm>
11 #include <ut/ut.h>
12 #include <pal/atomic.h>
13 #include <pal/thread.h>
14 #include <pal/tls.h>
15 #include <pal/sleep.h>
16 #include <pal/once.h>
17 #include <pal/lock.h>
18 #include <pal/cpu.h>
19 #include <pal/shlib.h>
20 #include <pal/slist.h>
21 #include <pal/sem.h>
22 krisbash 1.1 #include <pal/shmem.h>
23 #include <pal/strings.h>
24 #include <pal/dir.h>
25 #include <pal/file.h>
26 #include <pal/hashmap.h>
27 #include <pal/format.h>
28 #include "test_pal_strings.h"
29
30
31 using namespace std;
32
33 //==============================================================================
34 //
35 // TestSemSize()
36 //
37 //==============================================================================
38
39 NitsTest(TestSemSize)
40 {
41 /* Validate that Sem fits in a ptrdiff_t. Otherwise, the semaphore pool in
42 * CondLock will have problems. */
43 krisbash 1.1 NitsAssert(sizeof(Sem) <= sizeof(ptrdiff_t), PAL_T("Check Sem size"));
44 }
45 NitsEndTest
46
47 //==============================================================================
48 //
49 // TestPal32Bit()
50 //
51 //==============================================================================
52
53 #ifdef PAL_32BIT
54 NitsTest(TestPal32Bit)
55 {
56 NitsAssert(sizeof(void*) == 4, PAL_T("Check 32-bit pointer size"));
57 }
58 NitsEndTest
59 #endif
60
61 //==============================================================================
62 //
63 // TestPal64Bit()
64 krisbash 1.1 //
65 //==============================================================================
66
67 #ifdef PAL_64BIT
68 NitsTest(TestPal64Bit)
69 {
70 NitsAssert(sizeof(void*) == 8, PAL_T("Check 64-bit pointer size"));
71 }
72 NitsEndTest
73 #endif
74
75 //==============================================================================
76 //
77 // TestAtomic()
78 //
79 //==============================================================================
80
81 NitsTest(TestAtomic)
82 // Atomic_Inc()
83 {
84 volatile ptrdiff_t x = 0;
85 krisbash 1.1 ptrdiff_t r = Atomic_Inc(&x);
86 TEST_ASSERT(r == 1);
87 TEST_ASSERT(x == 1);
88 r = Atomic_Inc(&x);
89 TEST_ASSERT(r == 2);
90 TEST_ASSERT(x == 2);
91 }
92
93 // Atomic_Dec()
94 {
95 volatile ptrdiff_t x = 2;
96 ptrdiff_t r = Atomic_Dec(&x);
97 TEST_ASSERT(r == 1);
98 TEST_ASSERT(x == 1);
99 r = Atomic_Dec(&x);
100 TEST_ASSERT(r == 0);
101 TEST_ASSERT(x == 0);
102 }
103
104 // Atomic_CompareAndSwap()
105 {
106 krisbash 1.1 volatile ptrdiff_t x = 2;
107 ptrdiff_t r = Atomic_CompareAndSwap(&x, 2, 10);
108 TEST_ASSERT(r == 2);
109 TEST_ASSERT(x == 10);
110 }
111
112 // Atomic_CompareAndSwap()
113 {
114 volatile ptrdiff_t x = 2;
115 ptrdiff_t r = Atomic_CompareAndSwap(&x, 500, 10);
116 TEST_ASSERT(r == 2);
117 TEST_ASSERT(x == 2);
118 }
119
120 // Atomic_Swap()
121 {
122 volatile ptrdiff_t x = 100;
123 ptrdiff_t r = Atomic_Swap(&x, 200);
124 TEST_ASSERT(r == 100);
125 TEST_ASSERT(x == 200);
126 }
127 krisbash 1.1 NitsEndTest
128
129 //==============================================================================
130 //
131 // TestThread()
132 //
133 //==============================================================================
134
135 NITS_EXTERN_C PAL_Uint32 THREAD_API TestThread1(void* arg)
136 {
137 const char* name = (const char*)arg;
138 TEST_ASSERT(strcmp(name, "TestThread1") == 0);
139
140 return 1001;
141 }
142
143 NITS_EXTERN_C PAL_Uint32 THREAD_API TestThread2(void* arg)
144 {
145 const char* name = (const char*)arg;
146 TEST_ASSERT(strcmp(name, "TestThread2") == 0);
147
148 krisbash 1.1 return 1002;
149 }
150
151 NitsTest(TestThread)
152 Thread t1;
153 int t1_created = PAL_FALSE;
154
155 t1_created = (Thread_CreateJoinable(&t1, TestThread1, NULL, (char*)"TestThread1") == 0);
156 TEST_ASSERT(t1_created);
157
158 Thread t2;
159 int t2_created = PAL_FALSE;
160
161 t2_created = (Thread_CreateJoinable(&t2, TestThread2, NULL, (char*)"TestThread2") == 0);
162 TEST_ASSERT(t2_created);
163
164 if (t1_created)
165 {
166 PAL_Uint32 arg1;
167 Thread_Join(&t1, &arg1);
168 Thread_Destroy(&t1);
169 krisbash 1.1 TEST_ASSERT(arg1 == 1001);
170 }
171
172 if (t2_created)
173 {
174 PAL_Uint32 arg2;
175 Thread_Join(&t2, &arg2);
176 Thread_Destroy(&t2);
177 TEST_ASSERT(arg2 == 1002);
178 }
179
180 NitsEndTest
181
182 //==============================================================================
183 //
184 // TestTLS()
185 //
186 //==============================================================================
187
188 NITS_EXTERN_C PAL_Uint32 THREAD_API TestTLS1(void* arg)
189 {
190 krisbash 1.1 TLS* tls = (TLS*)arg;
191
192 for (ptrdiff_t i = 0; i < 100; i++)
193 {
194 TLS_Set(tls, i);
195 Sleep_Milliseconds(5);
196 ptrdiff_t x = TLS_Get(tls);
197 TEST_ASSERT(x == i);
198 }
199
200 return 0;
201 }
202
203 NITS_EXTERN_C PAL_Uint32 THREAD_API TestTLS2(void* arg)
204 {
205 TLS* tls = (TLS*)arg;
206
207 for (ptrdiff_t i = 100; i < 200; i++)
208 {
209 TLS_Set(tls, i);
210 Sleep_Milliseconds(5);
211 krisbash 1.1 ptrdiff_t x = TLS_Get(tls);
212 TEST_ASSERT(x == i);
213 }
214
215 return 0;
216 }
217
218 NitsTest(TestTLS)
219 Thread t1;
220 int t1_created = PAL_FALSE;
221 TLS tls;
222
223 int r = TLS_Init(&tls);
224 TEST_ASSERT(r == 0);
225 if (r != 0)
226 return;
227
228 t1_created = (Thread_CreateJoinable(&t1, TestTLS1, NULL, &tls) == 0);
229 TEST_ASSERT(t1_created);
230
231 Thread t2;
232 krisbash 1.1 int t2_created = PAL_FALSE;
233
234 t2_created = (Thread_CreateJoinable(&t2, TestTLS2, NULL, &tls) == 0);
235 TEST_ASSERT(t2_created);
236
237 Sleep_Milliseconds(10);
238
239 if (t1_created)
240 {
241 PAL_Uint32 arg1;
242 Thread_Join(&t1, &arg1);
243 Thread_Destroy(&t1);
244 }
245
246 if (t2_created)
247 {
248 PAL_Uint32 arg2;
249 Thread_Join(&t2, &arg2);
250 Thread_Destroy(&t2);
251 }
252
253 krisbash 1.1 TLS_Destroy(&tls);
254 NitsEndTest
255
256 //==============================================================================
257 //
258 // TestOnce()
259 //
260 //==============================================================================
261
262 typedef struct _TestOnce_Data
263 {
264 Once once;
265 int count;
266 } TestOnce_Data;
267
268 _Success_(return == 0) NITS_EXTERN_C int IncrementCount(_In_ void* arg, _Outptr_result_maybenull_ void** value)
269 {
270 TestOnce_Data* data = (TestOnce_Data*) arg;
271 data->count++;
272 *value = NULL;
273 return 0;
274 krisbash 1.1 }
275
276 NITS_EXTERN_C PAL_Uint32 THREAD_API TestOnce1(void* arg)
277 {
278 TestOnce_Data* data = (TestOnce_Data*) arg;
279
280 for (ptrdiff_t i = 0; i < 100; i++)
281 {
282 Sleep_Milliseconds(5);
283 Once_Invoke(&data->once, IncrementCount, data);
284 }
285
286 return 0;
287 }
288
289 NITS_EXTERN_C PAL_Uint32 THREAD_API TestOnce2(void* arg)
290 {
291 TestOnce_Data* data = (TestOnce_Data*) arg;
292
293 for (ptrdiff_t i = 0; i < 100; i++)
294 {
295 krisbash 1.1 Sleep_Milliseconds(5);
296 Once_Invoke(&data->once, IncrementCount, data);
297 }
298
299 return 0;
300 }
301
302 NitsTest(TestOnce)
303 Thread t1;
304 int t1_created = PAL_FALSE;
305 TestOnce_Data data = { ONCE_INITIALIZER, 0 };
306
307 t1_created = (Thread_CreateJoinable(&t1, TestOnce1, NULL, &data) == 0);
308 TEST_ASSERT(t1_created);
309
310 Thread t2;
311 int t2_created = PAL_FALSE;
312
313 t2_created = (Thread_CreateJoinable(&t2, TestOnce2, NULL, &data) == 0);
314 TEST_ASSERT(t2_created);
315
316 krisbash 1.1 Sleep_Milliseconds(10);
317
318 if (t1_created)
319 {
320 PAL_Uint32 arg1;
321 Thread_Join(&t1, &arg1);
322 Thread_Destroy(&t1);
323 }
324
325 if (t2_created)
326 {
327 PAL_Uint32 arg2;
328 Thread_Join(&t2, &arg2);
329 Thread_Destroy(&t2);
330 }
331
332 TEST_ASSERT(data.count == 1);
333 NitsEndTest
334
335 _Success_(return == 0) NITS_EXTERN_C int IncrementCount_FailIfCountIsZero(
336 _In_ void* arg,
337 krisbash 1.1 _Outptr_result_maybenull_ void** value)
338 {
339 TestOnce_Data* data = (TestOnce_Data*) arg;
340 *value = NULL;
341 if ((data->count++) == 0)
342 {
343 return 1;
344 }
345 else
346 {
347 return 0;
348 }
349 }
350
351 NitsTest(TestOnce_ReturnValueTest)
352 TestOnce_Data data = { ONCE_INITIALIZER, 0 };
353 int ret;
354
355 ret = Once_Invoke(&data.once, IncrementCount_FailIfCountIsZero, &data);
356 NitsCompare(ret, 1, PAL_T("1st Once_Invoke should return 1"));
357 NitsCompare(data.count, 1, PAL_T("1st Once_Invoke should set count=1"));
358 krisbash 1.1
359 ret = Once_Invoke(&data.once, IncrementCount_FailIfCountIsZero, &data);
360 NitsCompare(ret, 0, PAL_T("2nd Once_Invoke should return 0"));
361 NitsCompare(data.count, 2, PAL_T("2nd Once_Invoke should set count=2"));
362
363 ret = Once_Invoke(&data.once, IncrementCount_FailIfCountIsZero, &data);
364 NitsCompare(ret, 0, PAL_T("subsequent Once_Invoke(s) should keep returning 0"));
365 NitsCompare(data.count, 2, PAL_T("subsequent Once_Invoke(s) should not increment count"));
366 NitsEndTest
367
368 _Success_(return == 0) NITS_EXTERN_C int IncrementCount_SlowFailIfCountIsZero(
369 _In_ void* arg,
370 _Outptr_result_maybenull_ void** value)
371 {
372 TestOnce_Data* data = (TestOnce_Data*) arg;
373 *value = NULL;
374 Sleep_Milliseconds(1);
375 if ((data->count++) == 0)
376 {
377 return 1;
378 }
379 krisbash 1.1 else
380 {
381 return 0;
382 }
383 }
384
385 NITS_EXTERN_C PAL_Uint32 THREAD_API TestOnce_FailureRaceTest_Thread(void* arg)
386 {
387 TestOnce_Data* data = (TestOnce_Data*)arg;
388 int ret;
389
390 ret = Once_Invoke(&data->once, IncrementCount_SlowFailIfCountIsZero, data);
391 NitsAssert((data->count == 1) || (data->count == 2), PAL_T("At most one failure and one success"));
392
393 return (PAL_Uint32)ret;
394 }
395
396 NitsTest(TestOnce_FailureRaceTest)
397 TestOnce_Data data = { ONCE_INITIALIZER, 0 };
398
399 Thread t1;
400 krisbash 1.1 PAL_Uint32 t1_created = PAL_FALSE;
401 PAL_Uint32 t1_result = 0;
402
403 t1_created = (Thread_CreateJoinable(&t1, TestOnce_FailureRaceTest_Thread, NULL, &data) == 0);
404 TEST_ASSERT(t1_created);
405
406 Thread t2;
407 PAL_Uint32 t2_created = PAL_FALSE;
408 PAL_Uint32 t2_result = 0;
409
410 t2_created = (Thread_CreateJoinable(&t2, TestOnce_FailureRaceTest_Thread, NULL, &data) == 0);
411 TEST_ASSERT(t2_created);
412
413 if (t1_created)
414 {
415 Thread_Join(&t1, &t1_result);
416 Thread_Destroy(&t1);
417 }
418
419 if (t2_created)
420 {
421 krisbash 1.1 Thread_Join(&t2, &t2_result);
422 Thread_Destroy(&t2);
423 }
424
425 if (t1_created && t2_created)
426 {
427 NitsAssert(
428 ((t1_result == 0) && (t2_result == 1)) ||
429 ((t2_result == 0) && (t1_result == 1)),
430 PAL_T("One thread should fail and the other should succeed"));
431 }
432 NitsEndTest
433
434 //==============================================================================
435 //
436 // TestMutex()
437 //
438 //==============================================================================
439
440 static Lock s_mutex = LOCK_INITIALIZER;
441
442 krisbash 1.1 NITS_EXTERN_C PAL_Uint32 THREAD_API TestMutex1(void* arg)
443 {
444 size_t* countPtr = (size_t*)arg;
445
446 for (ptrdiff_t i = 0; i < 100; i++)
447 {
448 Lock_Acquire(&s_mutex);
449 size_t count = *countPtr;
450 Sleep_Milliseconds(1);
451 count++;
452 Sleep_Milliseconds(1);
453 *countPtr = count;
454 Lock_Release(&s_mutex);
455 }
456
457 return 0;
458 }
459
460 NITS_EXTERN_C PAL_Uint32 THREAD_API TestMutex2(void* arg)
461 {
462 size_t* countPtr = (size_t*)arg;
463 krisbash 1.1
464 for (ptrdiff_t i = 0; i < 100; i++)
465 {
466 Lock_Acquire(&s_mutex);
467 size_t count = *countPtr;
468 Sleep_Milliseconds(1);
469 count++;
470 Sleep_Milliseconds(1);
471 *countPtr = count;
472 Lock_Release(&s_mutex);
473 }
474
475 return 0;
476 }
477
478 NitsTest(TestMutex)
479 {
480 Thread t1;
481 int t1_created = PAL_FALSE;
482 size_t count = 0;
483
484 krisbash 1.1 t1_created = (Thread_CreateJoinable(&t1, TestMutex1, NULL, &count) == 0);
485 TEST_ASSERT(t1_created);
486
487 Thread t2;
488 int t2_created = PAL_FALSE;
489
490 t2_created = (Thread_CreateJoinable(&t2, TestMutex2, NULL, &count) == 0);
491 TEST_ASSERT(t2_created);
492
493 Sleep_Milliseconds(10);
494
495 if (t1_created)
496 {
497 PAL_Uint32 arg1;
498 Thread_Join(&t1, &arg1);
499 Thread_Destroy(&t1);
500 }
501
502 if (t2_created)
503 {
504 PAL_Uint32 arg2;
505 krisbash 1.1 Thread_Join(&t2, &arg2);
506 Thread_Destroy(&t2);
507 }
508
509 TEST_ASSERT(count == 200);
510 }
511 NitsEndTest
512
513 NITS_EXTERN_C PAL_Uint32 THREAD_API TestLockMiniStressWorker(void* param)
514 {
515 static char buf1[10000];
516 static char buf2[10000];
517
518 Lock* lock = (Lock*)param;
519 int i, j;
520 for (i = -25; i < 50; i++)
521 {
522 for (j = -25; j < 50; j++)
523 {
524 Lock_Acquire(lock);
525 if (i > 0) memcpy(buf1, buf2, i);
526 krisbash 1.1 Lock_Release(lock);
527 if (j > 0) memcpy(buf1, buf2, j);
528 }
529 }
530 return 0;
531 }
532
533 /*
534 * This is a regression test for Win Blue Bugs #562349
535 * (lock corruption leading to a hang)
536 */
537 NitsTest(TestLockMiniStress)
538 {
539 Lock lock;
540 Thread t[10];
541 int r[10];
542 int i;
543
544 Lock_Init(&lock);
545
546 for (i = 0; i < 10; i++)
547 krisbash 1.1 {
548 r[i] = Thread_CreateJoinable(
549 t + i,
550 TestLockMiniStressWorker,
551 NULL, /* no thread destructor */
552 &lock); /* no thread parameter */
553 NitsCompare(r[i], 0, MI_T("Thread_CreateJoinable"));
554 }
555
556 for (i = 0; i < 10; i++)
557 {
558 if (r[i] == 0)
559 {
560 MI_Uint32 threadRet;
561 MI_Uint32 joinRet;
562 joinRet = Thread_Join(t + i, &threadRet);
563 NitsCompare(joinRet, 0, MI_T("Thread_Join"));
564 NitsCompare(threadRet, 0, MI_T("TestLockMiniStressWorker"));
565
566 Thread_Destroy(t + i);
567 }
568 krisbash 1.1 }
569 }
570 NitsEndTest
571
572 //==============================================================================
573 //
574 // TestReadWriteLock()
575 //
576 //==============================================================================
577
578 /* ATTN: broken */
579
580 #if 0
581
582 static ReadWriteLock s_readWriteLock = READWRITELOCK_INITIALIZER;
583 static unsigned long s_readWriteLockData = 0;
584
585 NITS_EXTERN_C PAL_Uint32 THREAD_API TestReadWriteLock_Writer(void* arg)
586 {
587 for (ptrdiff_t i = 0; i < 100; i++)
588 {
589 krisbash 1.1 ReadWriteLock_AcquireWrite(&s_readWriteLock);
590 s_readWriteLockData = 1;
591 Thread_Yield();
592 Sleep_Milliseconds(10);
593 s_readWriteLockData = 0;
594 ReadWriteLock_ReleaseWrite(&s_readWriteLock);
595 }
596
597 return 0;
598 }
599
600 NITS_EXTERN_C PAL_Uint32 THREAD_API TestReadWriteLock_Reader(void* arg)
601 {
602 for (ptrdiff_t i = 0; i < 100; i++)
603 {
604 ReadWriteLock_AcquireRead(&s_readWriteLock);
605 TEST_ASSERT(s_readWriteLockData == 0);
606 ReadWriteLock_ReleaseRead(&s_readWriteLock);
607 }
608
609 return 0;
610 krisbash 1.1 }
611
612 NitsTest(TestReadWriteLock)
613 {
614 Thread t1;
615
616 if (Thread_CreateJoinable(&t1, TestReadWriteLock_Writer, NULL) != 0)
617 TEST_ASSERT(false);
618
619 Thread t2;
620
621 if (Thread_CreateJoinable(&t2, TestReadWriteLock_Reader, NULL) != 0)
622 TEST_ASSERT(false);
623
624 Sleep_Milliseconds(10);
625
626 PAL_Uint32 arg1;
627 Thread_Join(&t1, &arg1);
628 Thread_Destroy(&t1);
629
630 PAL_Uint32 arg2;
631 krisbash 1.1 Thread_Join(&t2, &arg2);
632 Thread_Destroy(&t2);
633 }
634 NitsEndTest
635
636 #endif
637
638 //==============================================================================
639 //
640 // TestCachedLock()
641 //
642 //==============================================================================
643
644 /* ATTN: broken */
645
646 #if 0
647
648 static CachedLock s_cachedLock;
649
650 NITS_EXTERN_C PAL_Uint32 THREAD_API TestCachedLock1(void* arg)
651 {
652 krisbash 1.1 size_t* countPtr = (size_t*)arg;
653
654 for (ptrdiff_t i = 0; i < 100; i++)
655 {
656 CachedLock_AcquireWrite(&s_cachedLock);
657 size_t count = *countPtr;
658 Sleep_Milliseconds(1);
659 count++;
660 Sleep_Milliseconds(1);
661 *countPtr = count;
662 CachedLock_ReleaseWrite(&s_cachedLock);
663 }
664
665 return 0;
666 }
667
668 NITS_EXTERN_C PAL_Uint32 THREAD_API TestCachedLock2(void* arg)
669 {
670 size_t* countPtr = (size_t*)arg;
671
672 for (ptrdiff_t i = 0; i < 100; i++)
673 krisbash 1.1 {
674 CachedLock_AcquireWrite(&s_cachedLock);
675 size_t count = *countPtr;
676 Sleep_Milliseconds(1);
677 count++;
678 Sleep_Milliseconds(1);
679 *countPtr = count;
680 CachedLock_ReleaseWrite(&s_cachedLock);
681 }
682
683 return 0;
684 }
685
686 NitsTest(TestCachedLock)
687 {
688 Thread t1;
689 size_t count = 0;
690
691 CachedLock_Init(&s_cachedLock, 0);
692
693 if (Thread_CreateJoinable(&t1, TestCachedLock1, &count) != 0)
694 krisbash 1.1 TEST_ASSERT(false);
695
696 Thread t2;
697
698 if (Thread_CreateJoinable(&t2, TestCachedLock2, &count) != 0)
699 TEST_ASSERT(false);
700
701 Sleep_Milliseconds(10);
702
703 PAL_Uint32 arg1;
704 Thread_Join(&t1, &arg1);
705 Thread_Destroy(&t1);
706
707 PAL_Uint32 arg2;
708 Thread_Join(&t2, &arg2);
709 Thread_Destroy(&t2);
710
711 TEST_ASSERT(count == 200);
712
713 CachedLock_Destroy(&s_cachedLock);
714 }
715 krisbash 1.1 NitsEndTest
716
717 #endif
718
719 //==============================================================================
720 //
721 // TestRecursiveLock()
722 //
723 //==============================================================================
724
725 static RecursiveLock s_recursiveLock = RECURSIVELOCK_INITIALIZER;
726
727 NITS_EXTERN_C PAL_Uint32 THREAD_API TestRecursiveLock1(void* arg)
728 {
729 size_t* countPtr = (size_t*)arg;
730
731 for (ptrdiff_t i = 0; i < 100; i++)
732 {
733 RecursiveLock_Acquire(&s_recursiveLock);
734 size_t count = *countPtr;
735 Sleep_Milliseconds(1);
736 krisbash 1.1 count++;
737 Sleep_Milliseconds(1);
738 *countPtr = count;
739 RecursiveLock_Release(&s_recursiveLock);
740 }
741
742 return 0;
743 }
744
745 NITS_EXTERN_C PAL_Uint32 THREAD_API TestRecursiveLock2(void* arg)
746 {
747 size_t* countPtr = (size_t*)arg;
748
749 for (ptrdiff_t i = 0; i < 100; i++)
750 {
751 RecursiveLock_Acquire(&s_recursiveLock);
752 size_t count = *countPtr;
753 Sleep_Milliseconds(1);
754 count++;
755 Sleep_Milliseconds(1);
756 *countPtr = count;
757 krisbash 1.1 RecursiveLock_Release(&s_recursiveLock);
758 }
759
760 return 0;
761 }
762
763 NitsTest(TestRecursiveLock)
764 {
765 Thread t1;
766 int t1_created = PAL_FALSE;
767 size_t count = 0;
768
769 t1_created = (Thread_CreateJoinable(&t1, TestRecursiveLock1, NULL, &count) == 0);
770 TEST_ASSERT(t1_created);
771
772 Thread t2;
773 int t2_created = PAL_FALSE;
774
775 t2_created = (Thread_CreateJoinable(&t2, TestRecursiveLock2, NULL, &count) == 0);
776 TEST_ASSERT(t2_created);
777
778 krisbash 1.1 Sleep_Milliseconds(10);
779
780 if (t1_created)
781 {
782 PAL_Uint32 arg1;
783 Thread_Join(&t1, &arg1);
784 Thread_Destroy(&t1);
785 }
786
787 if (t2_created)
788 {
789 PAL_Uint32 arg2;
790 Thread_Join(&t2, &arg2);
791 Thread_Destroy(&t2);
792 }
793
794 TEST_ASSERT(count == 200);
795 }
796 NitsEndTest
797
798 //==============================================================================
799 krisbash 1.1 //
800 // TestCond()
801 //
802 //==============================================================================
803
804 /* ATTN: broken */
805
806 #if 0
807
808 class Queue
809 {
810 public:
811
812 Queue()
813 {
814 Lock_Init(&m_lock);
815 m_size = 0;
816 m_notEmpty = 0xDEADBEEF;
817 m_notFull = 0xF00DFACE;
818 }
819
820 krisbash 1.1 ~Queue()
821 {
822 }
823
824 void Put(unsigned int x)
825 {
826 // Wait for size != SIZE (not full):
827
828 for (;;)
829 {
830 CondLock_Wait(m_notFull, &m_size, SIZE, SPINCOUNT);
831
832 Lock_Acquire(&m_lock);
833
834 if (m_size == SIZE)
835 {
836 Lock_Release(&m_lock);
837 continue;
838 }
839 else
840 {
841 krisbash 1.1 m_data.push_back(x);
842 m_size++;
843 Lock_Release(&m_lock);
844 CondLock_Signal(m_notEmpty);
845 break;
846 }
847 }
848 }
849
850 void Get(unsigned int& x)
851 {
852 // Wait for size != 0 (not empty):
853
854 for (;;)
855 {
856 CondLock_Wait(m_notEmpty, &m_size, 0, SPINCOUNT);
857
858 Lock_Acquire(&m_lock);
859
860 if (m_size == 0)
861 {
862 krisbash 1.1 Lock_Release(&m_lock);
863 continue;
864 }
865 else
866 {
867 x = m_data.front();
868 m_data.pop_front();
869 m_size--;
870 Lock_Release(&m_lock);
871 CondLock_Signal(m_notFull);
872 break;
873 }
874 }
875 }
876
877 private:
878
879 enum { SIZE = 100 };
880 Lock m_lock;
881 ptrdiff_t m_notEmpty;
882 ptrdiff_t m_notFull;
883 krisbash 1.1 ptrdiff_t m_size;
884 static const size_t SPINCOUNT;
885 list<unsigned int> m_data;
886 };
887
888 const size_t Queue::SPINCOUNT = CONDLOCK_DEFAULT_SPINCOUNT;
889
890 static const size_t NREADERS = 20;
891 static const size_t NPUTS = 10000;
892
893 static ptrdiff_t s_sum = 0;
894 static Lock s_sumLock = 0;
895
896 NITS_EXTERN_C PAL_Uint32 THREAD_API TestCondReader(void* arg)
897 {
898 Queue* queue = (Queue*)arg;
899
900 for (;;)
901 {
902 unsigned int x;
903
904 krisbash 1.1 queue->Get(x);
905
906 if (x == 0)
907 break;
908
909 Lock_Acquire(&s_sumLock);
910 s_sum += x;
911 Lock_Release(&s_sumLock);
912 }
913
914 printf("TestCondReader() done\n");
915
916 return 0;
917 }
918
919 NITS_EXTERN_C PAL_Uint32 THREAD_API TestCondWriter(void* arg)
920 {
921 Queue* queue = (Queue*)arg;
922
923 for (unsigned int i = 1; i <= NPUTS; i++)
924 {
925 krisbash 1.1 queue->Put(i);
926 }
927
928 printf("TestCondWriter() closing down readers\n");
929
930 for (size_t i = 0; i < NREADERS; i++)
931 {
932 queue->Put(0);
933 }
934
935 printf("TestCondWriter() done\n");
936
937 return 0;
938 }
939
940 NitsTest(TestCond)
941 {
942 // Create the queue:
943
944 Queue queue;
945
946 krisbash 1.1
947 // Calculate the expected sum:
948
949 static ptrdiff_t expectedSum = 0;
950
951 for (unsigned int i = 1; i <= NPUTS; i++)
952 expectedSum += i;
953
954 // Create writer thread:
955
956 Thread t1;
957
958 if (Thread_CreateJoinable(&t1, TestCondWriter, &queue) != 0)
959 TEST_ASSERT(false);
960
961 // Create reader threads:
962
963 vector<Thread> readers;
964
965 for (size_t i = 0; i < NREADERS; i++)
966 {
967 krisbash 1.1 Thread t;
968
969 if (Thread_CreateJoinable(&t, TestCondReader, &queue) != 0)
970 TEST_ASSERT(false);
971
972 readers.push_back(t);
973 }
974
975 // Join with writer:
976
977 PAL_Uint32 arg1;
978 Thread_Join(&t1, &arg1);
979 Thread_Destroy(&t1);
980
981 // Join with readers:
982
983 for (size_t i = 0; i < NREADERS; i++)
984 {
985 PAL_Uint32 arg2;
986 Thread_Join(&readers[i], &arg2);
987 Thread_Destroy(&readers[i]);
988 krisbash 1.1 }
989
990 // Verify that the sum is right:
991
992 TEST_ASSERT(s_sum == expectedSum);
993 }
994 NitsEndTest
995
996 #endif
997
998 //==============================================================================
999 //
1000 // TestCPU()
1001 //
1002 //==============================================================================
1003
1004 NitsTest(TestCPU)
1005 int count = CPU_GetCount();
1006 TEST_ASSERT(count >= 1);
1007
1008 int current = CPU_GetCurrent();
1009 krisbash 1.1 TEST_ASSERT(current >= 0);
1010
1011 if (count == 1)
1012 TEST_ASSERT(current == 0);
1013
1014 PAL_Datetime now;
1015 int result = CPU_GetLocalTimestamp(&now);
1016 TEST_ASSERT(result == 0);
1017 TEST_ASSERT(now.isTimestamp == PAL_TRUE);
1018 TEST_ASSERT(now.u.timestamp.year >= 2012);
1019 TEST_ASSERT(now.u.timestamp.month >= 1);
1020 TEST_ASSERT(now.u.timestamp.month <= 12);
1021 TEST_ASSERT(now.u.timestamp.day <= 31);
1022 TEST_ASSERT(now.u.timestamp.day >= 1);
1023 NitsEndTest
1024
1025 //==============================================================================
1026 //
1027 // TestShlib()
1028 //
1029 //==============================================================================
1030 krisbash 1.1
1031 /* ATTN: fix this test */
1032
1033 #if 0
1034 static void TestShlib()
1035 {
1036 // ATTN:
1037 Shlib* shlib = Shlib_Open(CONFIG_LIBDIR "/libtestshlib.so");
1038 TEST_ASSERT(shlib != NULL);
1039
1040 typedef const char* (*Function)();
1041 Function func = (Function)Shlib_Sym(shlib, "TestShlib");
1042 TEST_ASSERT(func != NULL);
1043
1044 const char* str = (*func)();
1045 TEST_ASSERT(strcmp(str, "TestShlib") == 0);
1046 }
1047 #endif
1048
1049 //==============================================================================
1050 //
1051 krisbash 1.1 // TestSList()
1052 //
1053 //==============================================================================
1054
1055 static const int NINTEGERS = 10000;
1056
1057 struct IntegerEntry
1058 {
1059 SListEntry entry;
1060 int x;
1061 };
1062
1063 NITS_EXTERN_C PAL_Uint32 THREAD_API TestListPush(void* arg)
1064 {
1065 SListHead* head = (SListHead*)arg;
1066
1067 for (int i = 0; i < NINTEGERS; i++)
1068 {
1069 IntegerEntry* p = new IntegerEntry;
1070 p->x = i;
1071 SList_PushAtomic(head, &p->entry);
1072 krisbash 1.1 }
1073
1074 return 0;
1075 }
1076
1077 NITS_EXTERN_C PAL_Uint32 THREAD_API TestListPop(void* arg)
1078 {
1079 SListHead* head = (SListHead*)arg;
1080
1081 for (int i = 0; i < NINTEGERS; i++)
1082 {
1083 IntegerEntry* p = (IntegerEntry*)SList_PopAtomic(head);
1084 TEST_ASSERT(p != NULL);
1085 if (p)
1086 delete p;
1087 }
1088
1089 return 0;
1090 }
1091
1092 NitsTest(TestSList)
1093 krisbash 1.1 /* Test push */
1094 {
1095 Thread t1;
1096 int t1_created = PAL_FALSE;
1097 SListHead head;
1098
1099 SList_Init(&head);
1100
1101 t1_created = (Thread_CreateJoinable(&t1, TestListPush, NULL, &head) == 0);
1102 TEST_ASSERT(t1_created);
1103
1104 Thread t2;
1105 int t2_created = PAL_FALSE;
1106
1107 t2_created = (Thread_CreateJoinable(&t2, TestListPush, NULL, &head) == 0);
1108 TEST_ASSERT(t2_created);
1109
1110 if (t1_created)
1111 {
1112 PAL_Uint32 arg1;
1113 Thread_Join(&t1, &arg1);
1114 krisbash 1.1 Thread_Destroy(&t1);
1115 }
1116
1117 if (t2_created)
1118 {
1119 PAL_Uint32 arg2;
1120 Thread_Join(&t2, &arg2);
1121 Thread_Destroy(&t2);
1122 }
1123
1124 // Check the list:
1125
1126 int expect = 0;
1127
1128 for (int i = 0; i < NINTEGERS; i++)
1129 {
1130 expect += i;
1131 expect += i;
1132 }
1133
1134 SListEntry* first = SList_FlushAtomic(&head);
1135 krisbash 1.1
1136 int total = 0;
1137 size_t size = 0;
1138
1139 for (SListEntry* p = first; p; )
1140 {
1141 SListEntry* next = SList_Next(p);
1142 IntegerEntry* entry = (IntegerEntry*)p;
1143 total += entry->x;
1144 delete entry;
1145 p = next;
1146 size++;
1147 }
1148
1149 TEST_ASSERT(size == 2 * NINTEGERS);
1150 TEST_ASSERT(expect == total);
1151 }
1152
1153 /* Test pop */
1154 {
1155 SListHead head;
1156 krisbash 1.1 SList_Init(&head);
1157
1158 // Push phase:
1159 {
1160 Thread t1;
1161 int t1_created = PAL_FALSE;
1162
1163 t1_created = (Thread_CreateJoinable(&t1, TestListPush, NULL, &head) == 0);
1164 TEST_ASSERT(t1_created);
1165
1166 Thread t2;
1167 int t2_created = PAL_FALSE;
1168
1169 t2_created = (Thread_CreateJoinable(&t2, TestListPush, NULL, &head) == 0);
1170 TEST_ASSERT(t2_created);
1171
1172 if (t1_created)
1173 {
1174 PAL_Uint32 arg1;
1175 Thread_Join(&t1, &arg1);
1176 Thread_Destroy(&t1);
1177 krisbash 1.1 }
1178
1179 if (t2_created)
1180 {
1181 PAL_Uint32 arg2;
1182 Thread_Join(&t2, &arg2);
1183 Thread_Destroy(&t2);
1184 }
1185 }
1186
1187 // Pop phase:
1188 {
1189 Thread t1;
1190 int t1_created = PAL_FALSE;
1191
1192 t1_created = (Thread_CreateJoinable(&t1, TestListPop, NULL, &head) == 0);
1193 TEST_ASSERT(t1_created);
1194
1195 Thread t2;
1196 int t2_created = PAL_FALSE;
1197
1198 krisbash 1.1 t2_created = (Thread_CreateJoinable(&t2, TestListPop, NULL, &head) == 0);
1199 TEST_ASSERT(t2_created);
1200
1201 if (t1_created)
1202 {
1203 PAL_Uint32 arg1;
1204 Thread_Join(&t1, &arg1);
1205 Thread_Destroy(&t1);
1206 }
1207
1208 if (t2_created)
1209 {
1210 PAL_Uint32 arg2;
1211 Thread_Join(&t2, &arg2);
1212 Thread_Destroy(&t2);
1213 }
1214 }
1215
1216 // Check that the list is empty:
1217 SListEntry* first = SList_FlushAtomic(&head);
1218 TEST_ASSERT(first == NULL);
1219 krisbash 1.1 }
1220 NitsEndTest
1221
1222 //==============================================================================
1223 //
1224 // TestSem()
1225 //
1226 //==============================================================================
1227
1228 struct TestSemData
1229 {
1230 Sem sem;
1231 unsigned int sum;
1232 unsigned int count;
1233 };
1234
1235 NITS_EXTERN_C PAL_Uint32 THREAD_API TestSemThread(void* arg)
1236 {
1237 TestSemData* data = (TestSemData*)arg;
1238
1239 for (unsigned int i = 0; i < data->count; i++)
1240 krisbash 1.1 {
1241 Sem_Wait(&data->sem);
1242 size_t tmp = data->sum;
1243 Sleep_Milliseconds(1);
1244 tmp++;
1245 Sleep_Milliseconds(1);
1246 data->sum = (unsigned int)tmp;
1247 Sleep_Milliseconds(1);
1248 Sem_Post(&data->sem, 1);
1249 }
1250
1251 return 0;
1252 }
1253
1254 NitsTest(TestSem)
1255 {
1256 Thread t1;
1257 int t1_created = PAL_FALSE;
1258 TestSemData data;
1259
1260 data.sum = 0;
1261 krisbash 1.1 data.count = 0;
1262
1263 int r = Sem_Init(&data.sem, SEM_USER_ACCESS_DEFAULT, 1);
1264 if(!TEST_ASSERT(r == 0))
1265 NitsReturn;
1266
1267 t1_created = (Thread_CreateJoinable(&t1, TestSemThread, NULL, &data) == 0);
1268 TEST_ASSERT(t1_created);
1269
1270 Thread t2;
1271 int t2_created = PAL_FALSE;
1272
1273 t2_created = (Thread_CreateJoinable(&t2, TestSemThread, NULL, &data) == 0);
1274 TEST_ASSERT(t2_created);
1275
1276 if (t1_created)
1277 {
1278 PAL_Uint32 arg1;
1279 Thread_Join(&t1, &arg1);
1280 Thread_Destroy(&t1);
1281 }
1282 krisbash 1.1
1283 if (t2_created)
1284 {
1285 PAL_Uint32 arg2;
1286 Thread_Join(&t2, &arg2);
1287 Thread_Destroy(&t2);
1288 }
1289
1290 Sem_Destroy(&data.sem);
1291
1292 // Check the result:
1293
1294 TEST_ASSERT(data.sum == 2 * data.count);
1295 }
1296 NitsEndTest
1297
1298 //==============================================================================
1299 //
1300 // TestNamedSem()
1301 //
1302 //==============================================================================
1303 krisbash 1.1
1304
1305 #if defined(_MSC_VER)
1306 # define SEMAPHORE_NAME PAL_T("/PALTestSem")
1307 #else
1308 # define SEMAPHORE_NAME PAL_T(CONFIG_SHMNAMELOCALPREFIX) PAL_T("PALTestSem")
1309 #endif
1310
1311 struct TestNamedSemData
1312 {
1313 unsigned int sum;
1314 unsigned int count;
1315 };
1316
1317 NITS_EXTERN_C PAL_Uint32 THREAD_API TestNamedSemThread(void* arg)
1318 {
1319 TestNamedSemData* data = (TestNamedSemData*)arg;
1320
1321 // Open or create the name semaphore:
1322
1323 NamedSem sem;
1324 krisbash 1.1 const PAL_Char *semaphoreName = SEMAPHORE_NAME;
1325
1326 int r = NamedSem_Open(&sem, SEM_USER_ACCESS_DEFAULT, 1, semaphoreName, NAMEDSEM_FLAG_CREATE);
1327
1328 TEST_ASSERT(r == 0);
1329 if (r != 0)
1330 return 0;
1331
1332 for (unsigned int i = 0; i < data->count; i++)
1333 {
1334 NamedSem_Wait(&sem);
1335 size_t tmp = data->sum;
1336 Sleep_Milliseconds(1);
1337 tmp++;
1338 Sleep_Milliseconds(1);
1339 data->sum = (unsigned int)tmp;
1340 Sleep_Milliseconds(1);
1341 NamedSem_Post(&sem, 1);
1342 }
1343
1344 NamedSem_Close(&sem);
1345 krisbash 1.1 NamedSem_Destroy(&sem);
1346 return 0;
1347 }
1348
1349 NitsTest(TestNamedSem)
1350 {
1351 Thread t1;
1352 int t1_created = PAL_FALSE;
1353 TestNamedSemData data;
1354
1355 data.sum = 0;
1356 data.count = 0;
1357
1358 t1_created = (Thread_CreateJoinable(&t1, TestNamedSemThread, NULL, &data) == 0);
1359 TEST_ASSERT(t1_created);
1360
1361 Thread t2;
1362 int t2_created = PAL_FALSE;
1363
1364 t2_created = (Thread_CreateJoinable(&t2, TestNamedSemThread, NULL, &data) == 0);
1365 TEST_ASSERT(t2_created);
1366 krisbash 1.1
1367 if (t1_created)
1368 {
1369 PAL_Uint32 arg1;
1370 Thread_Join(&t1, &arg1);
1371 Thread_Destroy(&t1);
1372 }
1373
1374 if (t2_created)
1375 {
1376 PAL_Uint32 arg2;
1377 Thread_Join(&t2, &arg2);
1378 Thread_Destroy(&t2);
1379 }
1380
1381 // Check the result:
1382
1383 TEST_ASSERT(data.sum == 2 * data.count);
1384 }
1385 NitsEndTest
1386
1387 krisbash 1.1 //==============================================================================
1388 //
1389 // TestShmem()
1390 //
1391 //==============================================================================
1392
1393
1394 #if defined(_MSC_VER)
1395 # define SHMEM_NAME PAL_T("/PALTestShmem")
1396 #else
1397 # define SHMEM_NAME PAL_T(CONFIG_SHMNAMELOCALPREFIX "PALTestShmem")
1398 #endif
1399
1400 typedef struct _TestShmemData
1401 {
1402 unsigned long sum;
1403 }
1404 TestShmemData;
1405
1406 NITS_EXTERN_C PAL_Uint32 THREAD_API TestShmemThread(void* arg)
1407 {
1408 krisbash 1.1 TestShmemData* data = (TestShmemData*)arg;
1409 Shmem shmem;
1410
1411 const PAL_Char *shmemName = SHMEM_NAME;
1412
1413 // Get the size size of the shared memory:
1414
1415 size_t size = 16 * Shmem_Granularity();
1416
1417 // Open the shared memory segment:
1418
1419 int r = Shmem_Open(&shmem,
1420 shmemName,
1421 SHMEM_ACCESS_READWRITE,
1422 SHMEM_USER_ACCESS_DEFAULT,
1423 size);
1424
1425 TEST_ASSERT(r == 0);
1426
1427 // Map a shared memory region:
1428
1429 krisbash 1.1 unsigned char* p = (unsigned char*)Shmem_Map(
1430 &shmem,
1431 SHMEM_ACCESS_READWRITE,
1432 0,
1433 size);
1434
1435 TEST_ASSERT(p != NULL);
1436
1437 // Write some data to the shared memory:
1438
1439 for (size_t i = 0; i < size; i++)
1440 {
1441 TEST_ASSERT(p[i] == i % 256);
1442 data->sum += p[i];
1443 p[i] = 0xDD;
1444 }
1445
1446 // Unmap the shared memory:
1447
1448 Shmem_Unmap(&shmem, p, size);
1449
1450 krisbash 1.1 // Close the shared memory:
1451
1452 Shmem_Close(&shmem);
1453
1454 return 0;
1455 }
1456
1457 NitsTest(TestShmem)
1458 {
1459 Thread t;
1460 int t_created = PAL_FALSE;
1461 Shmem shmem;
1462 const PAL_Char *shmemName = SHMEM_NAME;
1463
1464 size_t size = 16 * Shmem_Granularity();
1465
1466 // Open the shared memory segment:
1467
1468 int r = Shmem_Open(&shmem,
1469 shmemName,
1470 SHMEM_ACCESS_READWRITE,
1471 krisbash 1.1 SHMEM_USER_ACCESS_DEFAULT,
1472 size);
1473
1474 TEST_ASSERT(r == 0);
1475
1476 // Map a shared memory region:
1477
1478 unsigned char* p = (unsigned char*)Shmem_Map(
1479 &shmem,
1480 SHMEM_ACCESS_READWRITE,
1481 0,
1482 size);
1483
1484 TEST_ASSERT(p != NULL);
1485
1486 memset(p, 0xAA, size);
1487
1488 // Write some data to the shared memory:
1489
1490 unsigned long sum = 0;
1491
1492 krisbash 1.1 for (size_t i = 0; i < size; i++)
1493 {
1494 p[i] = i % 256;
1495 sum += p[i];
1496 }
1497
1498 // Unmap the shared memory:
1499
1500 Shmem_Unmap(&shmem, p, size);
1501
1502 // Create the other thread:
1503
1504 TestShmemData data;
1505 data.sum = 0;
1506
1507 t_created = (Thread_CreateJoinable(&t, TestShmemThread, NULL, &data) == 0);
1508 TEST_ASSERT(t_created);
1509
1510 // Join with the other thread:
1511
1512 if (t_created)
1513 krisbash 1.1 {
1514 PAL_Uint32 arg1;
1515 Thread_Join(&t, &arg1);
1516 Thread_Destroy(&t);
1517 }
1518
1519 p = (unsigned char*)Shmem_Map(
1520 &shmem,
1521 SHMEM_ACCESS_READWRITE,
1522 0,
1523 size);
1524
1525 TEST_ASSERT(p != NULL);
1526
1527 // Compare the sums:
1528
1529 TEST_ASSERT(data.sum == sum);
1530
1531 // The other thread should have cleared the memory (to 0xDD's):
1532
1533 for (size_t i = 0; i < size; i++)
1534 krisbash 1.1 {
1535 TEST_ASSERT(p[i] == 0xDD);
1536 }
1537
1538 // Unmap the shared memory:
1539
1540 Shmem_Unmap(&shmem, p, size);
1541
1542 // Close the shared memory:
1543
1544 Shmem_Close(&shmem);
1545 }
1546 NitsEndTest
1547
1548 //==============================================================================
1549 //
1550 // TestStrings()
1551 //
1552 //==============================================================================
1553
1554 #define FUNCTION TestStringsStr
1555 krisbash 1.1 #define CHAR char
1556 #define STRCMP Strcmp
1557 #define STRLCPY Strlcpy
1558 #define STRLCAT Strlcat
1559 #define LIT(STR) STR
1560 #include "TestStringsAux.h"
1561 #undef FUNCTION
1562 #undef CHAR
1563 #undef STRCMP
1564 #undef STRLCPY
1565 #undef STRLCAT
1566 #undef LIT
1567
1568 #define FUNCTION TestStringsWcs
1569 #define CHAR wchar_t
1570 #define STRCMP Wcscmp
1571 #define STRLCPY Wcslcpy
1572 #define STRLCAT Wcslcat
1573 #define LIT(STR) L##STR
1574 #include "TestStringsAux.h"
1575 #undef FUNCTION
1576 krisbash 1.1 #undef CHAR
1577 #undef STRCMP
1578 #undef STRLCPY
1579 #undef STRLCAT
1580 #undef LIT
1581
1582 #define FUNCTION TestStringsTcs
1583 #define CHAR TChar
1584 #define STRCMP Tcscmp
1585 #define STRLCPY Tcslcpy
1586 #define STRLCAT Tcslcat
1587 #define LIT(STR) PAL_T(STR)
1588 #include "TestStringsAux.h"
1589 #undef FUNCTION
1590 #undef CHAR
1591 #undef STRCMP
1592 #undef STRLCPY
1593 #undef STRLCAT
1594 #undef LIT
1595
1596 NitsTest(TestStrings)
1597 krisbash 1.1 {
1598 TestStringsStr();
1599 TestStringsWcs();
1600 TestStringsTcs();
1601 }
1602 NitsEndTest
1603
1604 NitsTest(TestStrings_ToUpper)
1605 {
1606 TEST_ASSERT(PAL_tolower(PAL_T('a')) == PAL_T('a'));
1607 TEST_ASSERT(PAL_tolower(PAL_T('A')) == PAL_T('a'));
1608
1609 TEST_ASSERT(PAL_tolower(PAL_T('z')) == PAL_T('z'));
1610 TEST_ASSERT(PAL_tolower(PAL_T('Z')) == PAL_T('z'));
1611
1612 /* characters before 'a','A' and after 'z','Z' */
1613 TEST_ASSERT(PAL_tolower(PAL_T('`')) == PAL_T('`'));
1614 TEST_ASSERT(PAL_tolower(PAL_T('@')) == PAL_T('@'));
1615 TEST_ASSERT(PAL_tolower(PAL_T('{')) == PAL_T('{'));
1616 TEST_ASSERT(PAL_tolower(PAL_T('[')) == PAL_T('['));
1617 }
1618 krisbash 1.1 NitsEndTest
1619
1620 //==============================================================================
1621 //
1622 // TestDir()
1623 //
1624 //==============================================================================
1625
1626 const char* TmpName(
1627 _Pre_writable_size_(PAL_MAX_PATH_SIZE) char buf[PAL_MAX_PATH_SIZE],
1628 const char* suffix)
1629 {
1630 #if defined(_MSC_VER)
1631 const char TMPDIR[] = "C:/Temp";
1632 #else
1633 const char TMPDIR[] = "/tmp";
1634 #endif
1635 Strlcpy(buf, TMPDIR, PAL_MAX_PATH_SIZE);
1636 Strlcat(buf, suffix, PAL_MAX_PATH_SIZE);
1637 return buf;
1638 }
1639 krisbash 1.1
1640 static void EnsureTmpExists()
1641 {
1642 #if defined(_MSC_VER)
1643 Mkdir("C:/Temp", 0700);
1644 #endif
1645 }
1646
1647 static void TestDirCleanup()
1648 {
1649 char buf[PAL_MAX_PATH_SIZE];
1650
1651 Rmdir(TmpName(buf, "/pal/TestDir/dir1"));
1652 Rmdir(TmpName(buf, "/pal/TestDir/dir2"));
1653 File_Remove(TmpName(buf, "/pal/TestDir/file1"));
1654 File_Remove(TmpName(buf, "/pal/TestDir/file2"));
1655 File_Remove(TmpName(buf, "/pal/TestDir/file3"));
1656 Rmdir(TmpName(buf, "/pal/TestDir"));
1657 Rmdir(TmpName(buf, "/pal"));
1658 }
1659
1660 krisbash 1.1 NitsTest(TestDir)
1661 {
1662 char buf[PAL_MAX_PATH_SIZE];
1663
1664 EnsureTmpExists();
1665 TestDirCleanup();
1666
1667 // Create directories and files:
1668
1669 TEST_ASSERT(Mkdir(TmpName(buf, "/pal/"), 0700) == 0);
1670 TEST_ASSERT(Mkdir(TmpName(buf, "/pal/TestDir"), 0700) == 0);
1671 TEST_ASSERT(Mkdir(TmpName(buf, "/pal/TestDir/dir1"), 0700) == 0);
1672 TEST_ASSERT(Mkdir(TmpName(buf, "/pal/TestDir/dir2"), 0700) == 0);
1673 TEST_ASSERT(File_Touch(TmpName(buf, "/pal/TestDir/file1")) == 0);
1674 TEST_ASSERT(File_Touch(TmpName(buf, "/pal/TestDir/file2")) == 0);
1675 TEST_ASSERT(File_Touch(TmpName(buf, "/pal/TestDir/file3")) == 0);
1676
1677 Dir* dir = Dir_Open(TmpName(buf, "/pal/TestDir"));
1678 TEST_ASSERT(dir != NULL);
1679
1680 if (dir != NULL)
1681 krisbash 1.1 {
1682 vector<string> names1;
1683
1684 for (;;)
1685 {
1686 DirEnt* ent = Dir_Read(dir);
1687 if (!ent)
1688 break;
1689
1690 if (strcmp(ent->name, "..") == 0 || strcmp(ent->name, ".") == 0)
1691 continue;
1692
1693 names1.push_back(ent->name);
1694 }
1695
1696 sort(names1.begin(), names1.end());
1697
1698 vector<string> names2;
1699 names2.push_back("dir1");
1700 names2.push_back("dir2");
1701 names2.push_back("file1");
1702 krisbash 1.1 names2.push_back("file2");
1703 names2.push_back("file3");
1704
1705 TEST_ASSERT(names1.size() == 5);
1706 TEST_ASSERT(names2.size() == 5);
1707 TEST_ASSERT(names1 == names2);
1708
1709 Dir_Close(dir);
1710 }
1711
1712 TestDirCleanup();
1713 }
1714 NitsEndTest
1715
1716 //==============================================================================
1717 //
1718 // TestFile()
1719 //
1720 //==============================================================================
1721
1722 NitsTest(TestFile)
1723 krisbash 1.1 {
1724 const char* FILENAME = "/PalTestFile.txt";
1725 char buf[PAL_MAX_PATH_SIZE];
1726
1727 EnsureTmpExists();
1728 File_Remove(TmpName(buf, FILENAME));
1729
1730 // Create a file with the contents "hello"
1731 {
1732 FILE* fp = File_Open(TmpName(buf, FILENAME), "w");
1733 TEST_ASSERT(fp != NULL);
1734
1735 size_t n = fwrite("hello", 1, 5, fp);
1736 TEST_ASSERT(n == 5);
1737
1738 File_Close(fp);
1739 }
1740
1741 // Open file and read contents:
1742 {
1743 FILE* fp = File_Open(TmpName(buf, FILENAME), "r");
1744 krisbash 1.1 TEST_ASSERT(fp != NULL);
1745
1746 char data[1024];
1747
1748 size_t n = fread(data, 1, sizeof(data), fp);
1749
1750 TEST_ASSERT(n == 5);
1751 TEST_ASSERT(memcmp(data, "hello", 5) == 0);
1752
1753 File_Close(fp);
1754 }
1755
1756 // Clean up:
1757
1758 File_Remove(TmpName(buf, FILENAME));
1759 }
1760 NitsEndTest
1761
1762 //==============================================================================
1763 //
1764 // TestHashMap()
1765 krisbash 1.1 //
1766 //==============================================================================
1767
1768 typedef struct _TestBucket /* derives from HashBucket */
1769 {
1770 struct _TestBucket* next;
1771 PAL_Char* key;
1772 long data;
1773 }
1774 TestBucket;
1775
1776 NITS_EXTERN_C size_t TestHash(
1777 const HashBucket* bucket_)
1778 {
1779 /* Note: this algorithm has a poor distribution */
1780 TestBucket* bucket = (TestBucket*)bucket_;
1781 size_t h = 0;
1782 PAL_Char* key = bucket->key;
1783
1784 while (*key)
1785 {
1786 krisbash 1.1 h += 5 * *key++;
1787 }
1788
1789 return h;
1790 }
1791
1792 NITS_EXTERN_C int TestEqual(
1793 const HashBucket* bucket1_,
1794 const HashBucket* bucket2_)
1795 {
1796 TestBucket* bucket1 = (TestBucket*)bucket1_;
1797 TestBucket* bucket2 = (TestBucket*)bucket2_;
1798 return Tcscmp(bucket1->key, bucket2->key) == 0;
1799 }
1800
1801 NITS_EXTERN_C void TestRelease(
1802 HashBucket* bucket_)
1803 {
1804 TestBucket* bucket = (TestBucket*)bucket_;
1805
1806 PAL_Free(bucket->key);
1807 krisbash 1.1 PAL_Free(bucket);
1808 }
1809
1810 NitsTest(TestHashMap1)
1811 {
1812 HashMap map;
1813 int r;
1814 TestBucket* b;
1815
1816 r = HashMap_Init(&map, 1, TestHash, TestEqual, TestRelease);
1817 TEST_ASSERT(r == 0);
1818
1819 /* Insert some buckets */
1820 {
1821 /* Insert RED=1 */
1822 {
1823 b = (TestBucket*)PAL_Calloc(1, sizeof(TestBucket));
1824 if(TEST_ASSERT(b != 0))
1825 {
1826 b->key = PAL_Tcsdup(PAL_T("RED"));
1827 b->data = 1;
1828 krisbash 1.1 r = HashMap_Insert(&map, (HashBucket*)b);
1829 TEST_ASSERT(r == 0);
1830 }
1831 }
1832
1833 /* Insert GREEN=2 */
1834 {
1835 b = (TestBucket*)PAL_Calloc(1, sizeof(TestBucket));
1836 if(TEST_ASSERT(b != 0))
1837 {
1838 b->key = PAL_Tcsdup(PAL_T("GREEN"));
1839 b->data = 2;
1840 r = HashMap_Insert(&map, (HashBucket*)b);
1841 TEST_ASSERT(r == 0);
1842 }
1843 }
1844
1845 /* Insert BLUE=3 */
1846 {
1847 b = (TestBucket*)PAL_Calloc(1, sizeof(TestBucket));
1848 if(TEST_ASSERT(b != 0))
1849 krisbash 1.1 {
1850 b->key = PAL_Tcsdup(PAL_T("BLUE"));
1851 b->data = 3;
1852 r = HashMap_Insert(&map, (HashBucket*)b);
1853 TEST_ASSERT(r == 0);
1854
1855 /* Insert BLUE=3 again (should fail) */
1856 r = HashMap_Insert(&map, (HashBucket*)b);
1857 TEST_ASSERT(r == 1);
1858 }
1859 }
1860
1861
1862 /* Find RED=1 */
1863 {
1864 TestBucket key;
1865 key.key = (PAL_Char*)PAL_T("RED");
1866 b = (TestBucket*)HashMap_Find(&map, (const HashBucket*)&key);
1867 if(TEST_ASSERT(b != 0))
1868 {
1869 TEST_ASSERT(Tcscmp(b->key, PAL_T("RED")) == 0);
1870 krisbash 1.1 TEST_ASSERT(b->data == 1);
1871 }
1872 }
1873
1874 /* Find GREEN=2 */
1875 {
1876 TestBucket key;
1877 key.key = (PAL_Char*)PAL_T("GREEN");
1878 b = (TestBucket*)HashMap_Find(&map, (const HashBucket*)&key);
1879 if(TEST_ASSERT(b != 0))
1880 {
1881 TEST_ASSERT(Tcscmp(b->key, PAL_T("GREEN")) == 0);
1882 TEST_ASSERT(b->data == 2);
1883 }
1884 }
1885
1886 /* Find BLUE=3 */
1887 {
1888 TestBucket key;
1889 key.key = (PAL_Char*)PAL_T("BLUE");
1890 b = (TestBucket*)HashMap_Find(&map, (const HashBucket*)&key);
1891 krisbash 1.1 if(TEST_ASSERT(b != 0))
1892 {
1893 TEST_ASSERT(Tcscmp(b->key, PAL_T("BLUE")) == 0);
1894 TEST_ASSERT(b->data == 3);
1895 }
1896 }
1897
1898 /* Find YELLOW=4 (should fail) */
1899 {
1900 TestBucket key;
1901 key.key = (PAL_Char*)PAL_T("YELLOW");
1902 b = (TestBucket*)HashMap_Find(&map, (const HashBucket*)&key);
1903 TEST_ASSERT(b == 0);
1904 }
1905
1906 /* Remove RED */
1907 {
1908 TestBucket key;
1909 key.key = (PAL_Char*)PAL_T("RED");
1910 r = HashMap_Remove(&map, (const HashBucket*)&key);
1911 TEST_ASSERT(r == 0);
1912 krisbash 1.1
1913 /* Remove should fail now */
1914 r = HashMap_Remove(&map, (const HashBucket*)&key);
1915 TEST_ASSERT(r == -1);
1916 }
1917
1918 /* Remove GREEN */
1919 {
1920 TestBucket key;
1921 key.key = (PAL_Char*)PAL_T("GREEN");
1922 r = HashMap_Remove(&map, (const HashBucket*)&key);
1923 TEST_ASSERT(r == 0);
1924
1925 /* Remove should fail now */
1926 r = HashMap_Remove(&map, (const HashBucket*)&key);
1927 TEST_ASSERT(r == -1);
1928 }
1929
1930 /* Remove BLUE */
1931 {
1932 TestBucket key;
1933 krisbash 1.1 key.key = (PAL_Char*)PAL_T("BLUE");
1934 r = HashMap_Remove(&map, (const HashBucket*)&key);
1935 TEST_ASSERT(r == 0);
1936
1937 /* Remove should fail now */
1938 r = HashMap_Remove(&map, (const HashBucket*)&key);
1939 TEST_ASSERT(r == -1);
1940 }
1941
1942 /* Remove YELLOW (should fail) */
1943 {
1944 TestBucket key;
1945 key.key = (PAL_Char*)PAL_T("YELLOW");
1946 r = HashMap_Remove(&map, (const HashBucket*)&key);
1947 TEST_ASSERT(r == -1);
1948 }
1949 }
1950
1951 /* Release all the memroy */
1952 HashMap_Destroy(&map);
1953 }
1954 krisbash 1.1 NitsEndTest
1955
1956 NitsTest(TestHashMap2)
1957 {
1958 HashMap map;
1959 int r;
1960 size_t i;
1961 const size_t N = 10000;
1962
1963 /* Create the hash map */
1964
1965 r = HashMap_Init(&map, 63, TestHash, TestEqual, TestRelease);
1966 TEST_ASSERT(r == 0);
1967
1968 /* Insert N buckets into hash map */
1969
1970 for (i = 0; i < N; i++)
1971 {
1972 PAL_Char buf[32];
1973 TestBucket* b;
1974
1975 krisbash 1.1 Stprintf(buf, PAL_COUNT(buf), PAL_T("%u"), (unsigned int)i);
1976 b = (TestBucket*)PAL_Calloc(1, sizeof(TestBucket));
1977 TEST_ASSERT(b != 0);
1978 if (b == 0) NitsReturn;
1979 b->key = PAL_Tcsdup(buf);
1980 b->data = (long)i;
1981 r = HashMap_Insert(&map, (HashBucket*)b);
1982 TEST_ASSERT(r == 0);
1983 }
1984
1985 /* Verify that each number is in the hash map */
1986
1987 for (i = 0; i < N; i++)
1988 {
1989 PAL_Char buf[32];
1990 TestBucket* b;
1991 TestBucket kb;
1992 kb.key = buf;
1993 Stprintf(buf, PAL_COUNT(buf), PAL_T("%u"), (unsigned int)i);
1994
1995 /* Find it */
1996 krisbash 1.1
1997 b = (TestBucket*)HashMap_Find(&map, (const HashBucket*)&kb);
1998 TEST_ASSERT(b != 0);
1999
2000 /* Check it */
2001 TEST_ASSERT(Tcscmp(b->key, buf) == 0);
2002 }
2003
2004 /* Delete all the buckets */
2005
2006 for (i = 0; i < N; i++)
2007 {
2008 PAL_Char buf[32];
2009 TestBucket kb;
2010 int r;
2011
2012 kb.key = buf;
2013 Stprintf(buf, PAL_COUNT(buf), PAL_T("%u"), (unsigned int)i);
2014
2015 /* Find it */
2016
2017 krisbash 1.1 r = HashMap_Remove(&map, (const HashBucket*)&kb);
2018 TEST_ASSERT(r == 0);
2019 }
2020
2021 /* Release all the memroy */
2022 HashMap_Destroy(&map);
2023 }
2024 NitsEndTest
2025
2026 NitsTest(TestHashMap2_preallocated)
2027 {
2028 HashMap map;
2029 int r;
2030 size_t i;
2031 const size_t N = 10000;
2032 void* hashMapBuckets[63];
2033
2034 /* Create the hash map */
2035
2036 HashMap_Construct(&map, 63, hashMapBuckets, TestHash, TestEqual, TestRelease);
2037
2038 krisbash 1.1 /* Insert N buckets into hash map */
2039
2040 for (i = 0; i < N; i++)
2041 {
2042 PAL_Char buf[32];
2043 TestBucket* b;
2044
2045 Stprintf(buf, PAL_COUNT(buf), PAL_T("%u"), (unsigned int)i);
2046 b = (TestBucket*)PAL_Calloc(1, sizeof(TestBucket));
2047 TEST_ASSERT(b != 0);
2048 if (b == 0) NitsReturn;
2049 b->key = PAL_Tcsdup(buf);
2050 b->data = (long)i;
2051 r = HashMap_Insert(&map, (HashBucket*)b);
2052 TEST_ASSERT(r == 0);
2053 }
2054
2055 /* Verify that each number is in the hash map */
2056
2057 for (i = 0; i < N; i++)
2058 {
2059 krisbash 1.1 PAL_Char buf[32];
2060 TestBucket* b;
2061 TestBucket kb;
2062 kb.key = buf;
2063 Stprintf(buf, PAL_COUNT(buf), PAL_T("%u"), (unsigned int)i);
2064
2065 /* Find it */
2066
2067 b = (TestBucket*)HashMap_Find(&map, (const HashBucket*)&kb);
2068 TEST_ASSERT(b != 0);
2069
2070 /* Check it */
2071 TEST_ASSERT(Tcscmp(b->key, buf) == 0);
2072 }
2073
2074 /* Delete all the buckets */
2075
2076 for (i = 0; i < N; i++)
2077 {
2078 PAL_Char buf[32];
2079 TestBucket kb;
2080 krisbash 1.1 int r;
2081
2082 kb.key = buf;
2083 Stprintf(buf, PAL_COUNT(buf), PAL_T("%u"), (unsigned int)i);
2084
2085 /* Find it */
2086
2087 r = HashMap_Remove(&map, (const HashBucket*)&kb);
2088 TEST_ASSERT(r == 0);
2089 }
2090
2091 /* Release all the memroy */
2092 HashMap_Destroy(&map);
2093 }
2094 NitsEndTest
2095
2096 NitsTest(TestHashMap_HashProc_PalStringCaseInsensitive)
2097 {
2098 TEST_ASSERT( HashMap_HashProc_PalStringCaseInsensitive(PAL_T("")) == HashMap_HashProc_PalStringCaseInsensitive(PAL_T("")));
2099 TEST_ASSERT( HashMap_HashProc_PalStringCaseInsensitive(PAL_T("foo")) == HashMap_HashProc_PalStringCaseInsensitive(PAL_T("foo")));
2100 TEST_ASSERT( HashMap_HashProc_PalStringCaseInsensitive(PAL_T("fooBARbaz")) == HashMap_HashProc_PalStringCaseInsensitive(PAL_T("FOObarBAZ")));
2101 krisbash 1.1 TEST_ASSERT( HashMap_HashProc_PalStringCaseInsensitive(PAL_T("foo")) != HashMap_HashProc_PalStringCaseInsensitive(PAL_T("bar")));
2102 }
2103 NitsEndTest
2104
2105 NitsTest(TestHashMap_HashProc_AnsiString)
2106 {
2107 TEST_ASSERT( HashMap_HashProc_AnsiString("") == HashMap_HashProc_AnsiString(""));
2108 TEST_ASSERT( HashMap_HashProc_AnsiString("foo") == HashMap_HashProc_AnsiString("foo"));
2109 TEST_ASSERT( HashMap_HashProc_AnsiString("fooBARbaz") != HashMap_HashProc_AnsiString("FOObarBAZ"));
2110 TEST_ASSERT( HashMap_HashProc_AnsiString("foo") != HashMap_HashProc_AnsiString("bar"));
2111 }
2112 NitsEndTest
2113
2114 //==============================================================================
2115 //
2116 // Tests for format.placeholders.h
2117 // - PAL_PRItstr
2118 // - PAL_PRI64d
2119 //
2120 //==============================================================================
2121
2122 krisbash 1.1 NitsTest(TestFormat_64bitFormatQualifiers_d)
2123 {
2124 TChar buf[1024] = {0};
2125
2126 Stprintf(
2127 buf,
2128 PAL_COUNT(buf),
2129 PAL_T("%") PAL_T(PAL_PRId64),
2130 PAL_SINT64_MIN);
2131
2132 TEST_ASSERT(Tcscmp(buf, PAL_T("-9223372036854775808")) == 0);
2133 }
2134 NitsEndTest
2135
2136 NitsTest(TestFormat_64bitFormatQualifiers_u)
2137 {
2138 TChar buf[1024] = {0};
2139
2140 Stprintf(
2141 buf,
2142 PAL_COUNT(buf),
2143 krisbash 1.1 PAL_T("%") PAL_T(PAL_PRIu64),
2144 PAL_UINT64_MAX);
2145
2146 TEST_ASSERT(Tcscmp(buf, PAL_T("18446744073709551615")) == 0);
2147 }
2148 NitsEndTest
2149
2150 NitsTest(TestFormat_PalCharSpecifier)
2151 {
2152 TChar buf[1024] = {0};
2153
2154 Stprintf(
2155 buf,
2156 PAL_COUNT(buf),
2157 PAL_T("foo=%") PAL_T(PAL_PRItstr),
2158 PAL_T("bar"));
2159
2160 TEST_ASSERT(Tcscmp(buf, PAL_T("foo=bar")) == 0);
2161 }
2162 NitsEndTest
2163
2164 krisbash 1.1 //==============================================================================
2165 //
2166 // Tests for format.c / format.h
2167 // - Stprintf
2168 // - Stprintf_StrDup
2169 // - Stprintf_CultureInvariant
2170 // - Stscanf
2171 //
2172 //==============================================================================
2173
2174 NitsTest(TestFormat_Stprintf)
2175 {
2176 TChar buf[1024];
2177
2178 Stprintf(
2179 buf,
2180 PAL_COUNT(buf),
2181 PAL_T("%T %S %s"),
2182 tcs(PAL_T("Red")),
2183 wcs(L"Green"),
2184 scs("Blue"));
2185 krisbash 1.1
2186 TEST_ASSERT(Tcscmp(buf, PAL_T("Red Green Blue")) == 0);
2187 }
2188 NitsEndTest
2189
2190 NitsTest(TestFormat_Stprintf_Strdup)
2191 {
2192 TChar* result = NULL;
2193
2194 result = Stprintf_StrDup(PAL_T("test = %d"), 12345);
2195 TEST_ASSERT(result != NULL);
2196 if (result != NULL)
2197 {
2198 TEST_ASSERT(Tcscmp(result, PAL_T("test = 12345")) == 0);
2199 }
2200
2201 PAL_Free(result);
2202 }
2203 NitsEndTest
2204
2205 #include <locale.h>
2206 krisbash 1.1 NitsTest(TestFormat_Stprintf_CultureInvariant)
2207 {
2208 TChar buf[1024] = {0};
2209
2210 char oldLocale[128];
2211 char testLocale[128];
2212 char *currentLocale = NULL;
2213 Strlcpy(oldLocale, setlocale(LC_ALL, NULL), PAL_COUNT(oldLocale));
2214 currentLocale = setlocale(LC_ALL, "polish");
2215 if(currentLocale)
2216 {
2217 Strlcpy(testLocale, currentLocale, PAL_COUNT(testLocale));
2218
2219 Stprintf(
2220 buf,
2221 PAL_COUNT(buf),
2222 PAL_T("%g"),
2223 1.23);
2224 NitsAssert(
2225 Tcscmp(buf, PAL_T("1,23")) == 0,
2226 PAL_T("Sanity check that polish locale uses a comma instead of a dot for decimal point"));
2227 krisbash 1.1 }
2228 else
2229 {
2230 /* ATTN: alternate implementation needed to test the functionality! */
2231 NitsAssert(true, PAL_T("test skipped"));
2232 }
2233
2234 Stprintf_CultureInvariant(
2235 buf,
2236 PAL_COUNT(buf),
2237 PAL_T("%g"),
2238 1.23);
2239 TEST_ASSERT(Tcscmp(buf, PAL_T("1.23")) == 0);
2240
2241 if(currentLocale)
2242 {
2243 NitsAssert(
2244 0 == Strcmp(testLocale, setlocale(LC_ALL, NULL)),
2245 PAL_T("Invocation of Stprintf_CultureInvariant shouldn't change current locale"));
2246 }
2247
2248 krisbash 1.1 setlocale(LC_ALL, oldLocale);
2249 }
2250 NitsEndTest
2251
2252
2253 NitsTest(TestFormat_Stscanf_CultureInvariant)
2254 {
2255 int result = 0;
2256 double number = 0.0;
2257
2258 char oldLocale[128];
2259 char testLocale[128];
2260 char *currentLocale = NULL;
2261 Strlcpy(oldLocale, setlocale(LC_ALL, NULL), PAL_COUNT(oldLocale));
2262 currentLocale = setlocale(LC_ALL, "polish");
2263 if(currentLocale)
2264 {
2265 Strlcpy(testLocale, currentLocale, PAL_COUNT(testLocale));
2266
2267 result = Stscanf_CultureInvariant(
2268 PAL_T("1.23"),
2269 krisbash 1.1 PAL_T("%lg"),
2270 &number);
2271 NitsAssert(
2272 (1.22 < number) && (number < 1.24),
2273 PAL_T("Sanity check that polish locale uses a comma instead of a dot for decimal point"));
2274 NitsAssert(
2275 result == 1,
2276 PAL_T("Scanf should return the number of elements it consumed"));
2277 NitsAssert(
2278 0 == Strcmp(testLocale, setlocale(LC_ALL, NULL)),
2279 PAL_T("Invocation of Stscanf_CultureInvariant shouldn't change current locale"));
2280 }
2281 else
2282 {
2283 /* ATTN: alternate implementation needed to test the functionality! */
2284 NitsAssert(true, PAL_T("test skipped"));
2285 }
2286
2287 setlocale(LC_ALL, oldLocale);
2288 }
2289 NitsEndTest
2290 krisbash 1.1
2291 //==============================================================================
2292 //
2293 // TestCondLock()
2294 //
2295 //==============================================================================
2296
2297 struct TestCondLockData
2298 {
2299 ptrdiff_t key;
2300 ptrdiff_t predicate;
2301 Lock lock;
2302 };
2303
2304 NITS_EXTERN_C PAL_Uint32 THREAD_API TestCondLockReader(void* arg)
2305 {
2306 TestCondLockData* data = (TestCondLockData*)arg;
2307
2308 // Wait on the condition variable:
2309
2310 for (;;)
2311 krisbash 1.1 {
2312 // Wait while predicate == 0:
2313
2314 CondLock_Wait(
2315 data->key, &data->predicate, 0, CONDLOCK_DEFAULT_SPINCOUNT);
2316
2317 Lock_Acquire(&data->lock);
2318
2319 // If predicate not satisfied, continue:
2320
2321 if (data->predicate == 0)
2322 {
2323 Lock_Release(&data->lock);
2324 continue;
2325 }
2326
2327 // Check the predicate:
2328
2329 TEST_ASSERT(data->predicate == 12345678);
2330 Lock_Release(&data->lock);
2331 break;
2332 krisbash 1.1 }
2333
2334 return 0;
2335 }
2336
2337 NITS_EXTERN_C PAL_Uint32 THREAD_API TestCondLockWriter(void* arg)
2338 {
2339 TestCondLockData* data = (TestCondLockData*)arg;
2340
2341 // Wait one second for reader to start:
2342
2343 Sleep_Milliseconds(1000);
2344
2345 // Update the predicate:
2346
2347 Lock_Acquire(&data->lock);
2348 data->predicate = 12345678;
2349 Lock_Release(&data->lock);
2350
2351 // Signal the reader:
2352
2353 krisbash 1.1 CondLock_Signal(data->key);
2354
2355 return 0;
2356 }
2357
2358 NitsTest(TestCondLock)
2359 {
2360 // Initialize the data:
2361
2362 TestCondLockData data;
2363 data.key = 1001;
2364 data.predicate = 0;
2365 Lock_Init(&data.lock);
2366
2367 // Create writer thread:
2368
2369 Thread writer;
2370 int writer_created = PAL_FALSE;
2371
2372 writer_created = (Thread_CreateJoinable(&writer, TestCondLockWriter, NULL, &data) == 0);
2373 TEST_ASSERT(writer_created);
2374 krisbash 1.1
2375 // Create reader threads:
2376
2377 Thread reader;
2378 int reader_created = PAL_FALSE;
2379
2380 reader_created = (Thread_CreateJoinable(&reader, TestCondLockReader, NULL, &data) == 0);
2381 TEST_ASSERT(reader_created);
2382
2383 if (writer_created)
2384 {
2385 PAL_Uint32 arg;
2386 Thread_Join(&writer, &arg);
2387 Thread_Destroy(&writer);
2388 }
2389 else
2390 {
2391 Lock_Acquire(&data.lock);
2392 data.predicate = 0xdeadbeef;
2393 Lock_Release(&data.lock);
2394
2395 krisbash 1.1 CondLock_Signal(data.key);
2396 }
2397
2398 if (reader_created)
2399 {
2400 PAL_Uint32 arg;
2401 Thread_Join(&reader, &arg);
2402 Thread_Destroy(&reader);
2403 }
2404 }
2405 NitsEndTest
2406
2407 //==============================================================================
2408 //
2409 // Tests for Intlstr
2410 //
2411 //==============================================================================
2412
2413 NitsTest(TestIntlstr_SimpleString)
2414 {
2415 Intlstr result = Intlstr_Null;
2416 krisbash 1.1 result = Intlstr_TestPal_SimpleString();
2417 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2418 if (result.str != NULL)
2419 {
2420 TEST_ASSERT(Tcscmp(result.str, PAL_T("My simple string")) == 0);
2421 }
2422 Intlstr_Free(result);
2423 }
2424 NitsEndTest
2425
2426 NitsTest(TestIntlstr_ReorderablePlaceholders)
2427 {
2428 Intlstr result = Intlstr_Null;
2429 result = Intlstr_TestPal_ReorderablePlaceholders(123, 456);
2430 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2431 if (result.str != NULL)
2432 {
2433 TEST_ASSERT(Tcscmp(result.str, PAL_T("Second integer = 456, First integer = 123")) == 0);
2434 }
2435 Intlstr_Free(result);
2436 }
2437 krisbash 1.1 NitsEndTest
2438
2439 NitsTest(TestIntlstr_OnePlaceholder)
2440 {
2441 Intlstr result = Intlstr_Null;
2442 result = Intlstr_TestPal_OnePlaceholder(1);
2443 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2444 if (result.str != NULL)
2445 {
2446 TEST_ASSERT(Tcscmp(result.str, PAL_T("p1=1")) == 0);
2447 }
2448 Intlstr_Free(result);
2449 }
2450 NitsEndTest
2451
2452 NitsTest(TestIntlstr_TwoPlaceholders)
2453 {
2454 Intlstr result = Intlstr_Null;
2455 result = Intlstr_TestPal_TwoPlaceholders(1,2);
2456 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2457 if (result.str != NULL)
2458 krisbash 1.1 {
2459 TEST_ASSERT(Tcscmp(result.str, PAL_T("p1=1, p2=2")) == 0);
2460 }
2461 Intlstr_Free(result);
2462 }
2463 NitsEndTest
2464
2465 NitsTest(TestIntlstr_ThreePlaceholders)
2466 {
2467 Intlstr result = Intlstr_Null;
2468 result = Intlstr_TestPal_ThreePlaceholders(1,2,3);
2469 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2470 if (result.str != NULL)
2471 {
2472 TEST_ASSERT(Tcscmp(result.str, PAL_T("p1=1, p2=2, p3=3")) == 0);
2473 }
2474 Intlstr_Free(result);
2475 }
2476 NitsEndTest
2477
2478 NitsTest(TestIntlstr_Specifier_d)
2479 krisbash 1.1 {
2480 Intlstr result = Intlstr_Null;
2481 result = Intlstr_TestPal_Specifier_d(123);
2482 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2483 if (result.str != NULL)
2484 {
2485 TEST_ASSERT(Tcscmp(result.str, PAL_T("p1=123")) == 0);
2486 }
2487 Intlstr_Free(result);
2488 }
2489 NitsEndTest
2490
2491 NitsTest(TestIntlstr_Specifier_tstr)
2492 {
2493 Intlstr result = Intlstr_Null;
2494 result = Intlstr_TestPal_Specifier_tstr(PAL_T("foo"));
2495 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2496 if (result.str != NULL)
2497 {
2498 TEST_ASSERT(Tcscmp(result.str, PAL_T("p1=foo")) == 0);
2499 }
2500 krisbash 1.1 Intlstr_Free(result);
2501 }
2502 NitsEndTest
2503
2504 NitsTest(TestIntlstr_Specifier_tchr)
2505 {
2506 Intlstr result = Intlstr_Null;
2507 result = Intlstr_TestPal_Specifier_tchr(PAL_T('f'));
2508 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2509 if (result.str != NULL)
2510 {
2511 TEST_ASSERT(Tcscmp(result.str, PAL_T("char=f")) == 0);
2512 }
2513 Intlstr_Free(result);
2514 }
2515 NitsEndTest
2516
2517 NitsTest(TestIntlstr_Specifier_x)
2518 {
2519 Intlstr result = Intlstr_Null;
2520 result = Intlstr_TestPal_Specifier_x(0x12345678);
2521 krisbash 1.1 NitsAssert(result.str != NULL, PAL_T("Could we get a localized string? (if not, double-check if mui file is deployed correctly)"));
2522 if (result.str != NULL)
2523 {
2524 TEST_ASSERT(Tcscmp(result.str, PAL_T("p1=0x12345678")) == 0);
2525 }
2526 Intlstr_Free(result);
2527 }
2528 NitsEndTest
2529
2530 #if defined(CONFIG_ENABLE_WCHAR)
2531
2532 bool TestWideCharConversion(const wchar_t *src, size_t srcSize, const char *expectedResult, int expectedDestSize)
2533 {
2534 size_t firstNonAscii = 0;
2535 int utf8Size = 0;
2536
2537 #if defined(_MSC_VER)
2538 int lastError = 0;
2539
2540 SetLastError(0);
2541 #endif
2542 krisbash 1.1
2543 utf8Size = ConvertWideCharToMultiByte(
2544 src,
2545 srcSize,
2546 &firstNonAscii,
2547 NULL,
2548 utf8Size);
2549
2550 #if defined(_MSC_VER)
2551 lastError = GetLastError();
2552 NitsAssert(lastError == 0, PAL_T("Last error not zero"));
2553 #endif
2554
2555 NitsAssert(utf8Size == (int)expectedDestSize, PAL_T("Space computed was 0"));
2556
2557
2558 char *dest = (char *)PAL_Calloc(1, utf8Size*sizeof(char));
2559
2560 if(!NitsAssert(dest, PAL_T("memory alloc failure")))
2561 return false;
2562
2563 krisbash 1.1 utf8Size = ConvertWideCharToMultiByte(
2564 src,
2565 srcSize,
2566 &firstNonAscii,
2567 dest,
2568 utf8Size * sizeof(char));
2569
2570
2571 NitsAssert(utf8Size == (int)expectedDestSize, PAL_T("Space computed was 0"));
2572 NitsAssert(Strncmp(dest, expectedResult, utf8Size) == 0, PAL_T("Result does not match expected"));
2573 #if defined(_MSC_VER)
2574 lastError = GetLastError();
2575 NitsAssert(lastError == 0, PAL_T("Last error not zero"));
2576 #endif
2577 PAL_Free(dest);
2578 return true;
2579 }
2580
2581 NitsTest(TestWideCharToMultiByteConversion1)
2582 const wchar_t *src = L"Mywidestring";
2583 size_t count = Wcslen(src);
2584 krisbash 1.1 const char *expectedResult = "Mywidestring";
2585
2586 NitsAssert(TestWideCharConversion(src, count, expectedResult, count), PAL_T("conversion failed"));
2587 NitsEndTest
2588
2589 NitsTest(TestWideCharToMultiByteConversion2)
2590 const wchar_t src[] = {0xE0, 0x248B, 0x61, 0x2173, 0x62, 0x1EA6, 0xFF21, 0xAA, 0x325, 0x2173, 0x249C, 0x63};
2591 size_t wideCharSize = sizeof(src)/sizeof(wchar_t);
2592 const char expectedResult[] = {0xC3, 0xA0, 0xE2, 0x92, 0x8B, 0x61, 0xE2, 0x85, 0xB3, 0x62, 0xE1, 0xBA, 0xA6, 0xEF, 0xBC, 0xA1, 0xC2, 0xAA, 0xCC, 0xA5, 0xE2, 0x85, 0xB3, 0xE2, 0x92, 0x9C, 0x63};
2593 int expectedSize = (int)(sizeof(expectedResult)/sizeof(char));
2594 NitsAssert(TestWideCharConversion(src, wideCharSize, expectedResult, expectedSize), PAL_T("conversion failed"));
2595 NitsEndTest
2596
2597
2598 #if !defined(_MSC_VER)
2599
2600 NitsTest(TestWideCharToMultiByteConversion3)
2601 const wchar_t src[] = {0x10FFFF, 0x110000};
2602 size_t wideCharSize = sizeof(src)/sizeof(wchar_t);
2603 const char expectedResult[] = {0xF4, 0x8F, 0xBF, 0xBF, '?'};
2604 int expectedSize = (int)(sizeof(expectedResult)/sizeof(char));
2605 krisbash 1.1 NitsAssert(TestWideCharConversion(src, wideCharSize, expectedResult, expectedSize), PAL_T("conversion failed"));
2606 NitsEndTest
2607
2608 #endif
2609
2610 #endif /* defined(CONFIG_ENABLE_WCHAR) */
2611
2612 #if defined(USE_ALLOCATOR)
2613 NitsTest(TestAlloc)
2614 {
2615 void* ptrs[1024];
2616 size_t n = sizeof(ptrs) / sizeof(ptrs[0]);
2617 size_t i;
2618 AllocStats stats = PAL_GetAllocStats();
2619 size_t numAllocs = stats.numAllocs;
2620 size_t numFrees = stats.numFrees;
2621 size_t usage = stats.usage;
2622 size_t extraUsage = 0;
2623
2624 for (i = 0; i < n; i++)
2625 {
2626 krisbash 1.1 ptrs[i] = PAL_Malloc(i+1);
2627 extraUsage += i + 1;
2628 }
2629
2630 stats = PAL_GetAllocStats();
2631 TEST_ASSERT(stats.numAllocs == numAllocs + n);
2632 TEST_ASSERT(stats.usage == usage + extraUsage);
2633
2634
2635 for (i = 0; i < n; i++)
2636 {
2637 PAL_Free(ptrs[i]);
2638 }
2639
2640 stats = PAL_GetAllocStats();
2641 TEST_ASSERT(stats.numFrees == numFrees + n);
2642 TEST_ASSERT(stats.usage == usage);
2643 }
2644 NitsEndTest
2645 #endif /* defined(USE_ALLOCATOR) */
|