(file) Return to test_pal.cpp CVS log (file) (dir) Up to [OMI] / omi / tests / pal

   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) */

ViewCVS 0.9.2