TestThread.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include "TestThread.h"
  5. #include <eathread/eathread.h>
  6. #include <eathread/eathread_callstack.h>
  7. #include <EATest/EATest.h>
  8. #include <EAStdC/EAString.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. //Prevents false positive memory leaks on GCC/Clang platforms
  13. #if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)
  14. #define EA_MEMORY_GCC_USE_FINALIZE
  15. #endif
  16. #ifndef EA_OPENSOURCE
  17. #include <MemoryMan/MemoryMan.inl>
  18. #include <MemoryMan/CoreAllocator.inl>
  19. #include <coreallocator/icoreallocator_interface.h>
  20. #endif
  21. #ifdef EA_OPENSOURCE
  22. void* operator new[](size_t size, const char* /*pName*/, int /*flags*/,
  23. unsigned /*debugFlags*/, const char* /*file*/, int /*line*/)
  24. {
  25. return operator new[](size);
  26. }
  27. void* operator new[](size_t size, size_t /*alignment*/, size_t /*alignmentOffset*/, const char* /*pName*/,
  28. int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/, int /*line*/)
  29. {
  30. return operator new[](size);
  31. }
  32. #endif
  33. #ifdef EA_DLL
  34. #include <MemoryMan/MemoryManDLL.h>
  35. #endif
  36. #if defined(EA_PLATFORM_MICROSOFT)
  37. EA_DISABLE_ALL_VC_WARNINGS()
  38. #include <Windows.h>
  39. EA_RESTORE_ALL_VC_WARNINGS()
  40. #endif
  41. #if defined(EA_COMPILER_MSVC) && defined(EA_PLATFORM_MICROSOFT)
  42. EA_DISABLE_ALL_VC_WARNINGS()
  43. #include <crtdbg.h>
  44. EA_RESTORE_ALL_VC_WARNINGS()
  45. #endif
  46. #include <EAMain/EAEntryPointMain.inl>
  47. #include <EATest/EASTLVsnprintf.inl>
  48. #include <EAMain/EAEntryPointMain.inl>
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // gTestLengthSeconds
  51. //
  52. unsigned int gTestLengthSeconds = 2;
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // EAThreadFailure
  55. //
  56. // This is called by EAThread's assert failure function.
  57. //
  58. static void EAThreadFailure(const char* pMessage, void* /*pContext*/)
  59. {
  60. EA::UnitTest::IncrementGlobalErrorCount(1);
  61. EA::UnitTest::Report("Thread test failure (EAThread assert): %s\n", pMessage);
  62. }
  63. ///////////////////////////////////////////////////////////////////////////////
  64. // TestThreadMisc
  65. //
  66. // To do: Move this to its own file.
  67. //
  68. #if defined(EA_PLATFORM_APPLE)
  69. #include <eathread/apple/eathread_callstack_apple.h>
  70. #endif
  71. #if defined(EA_PLATFORM_POSIX)
  72. #include <unistd.h>
  73. #endif
  74. bool IsSuperUser()
  75. {
  76. #if defined(EA_PLATFORM_POSIX) && !defined(EA_PLATFORM_SONY) && !defined(CS_UNDEFINED_STRING) // PS4 is a POSIX machine but doesn't implement 'getuid'.
  77. // http://pubs.opengroup.org/onlinepubs/009695399/functions/geteuid.html
  78. // http://pubs.opengroup.org/onlinepubs/009695399/functions/getuid.html
  79. uid_t uid = getuid(), euid = geteuid();
  80. return (uid == 0 || euid == 0);
  81. #else
  82. return true;
  83. #endif
  84. }
  85. int TestThreadGetThreadTimeMin()
  86. {
  87. int nErrorCount(0);
  88. #if defined(EA_PLATFORM_MICROSOFT) || defined(EA_PLATFORM_PS4)
  89. EATEST_VERIFY_MSG(EA::Thread::GetThreadTime() >= EATHREAD_MIN_ABSOLUTE_TIME, "Reported GetThreadTime absolute time is less than EATHREAD_MIN_ABSOLUTE_TIME. You are going to have a bad time.");
  90. #endif
  91. return nErrorCount;
  92. }
  93. int TestThreadMisc()
  94. {
  95. int nErrorCount = 0;
  96. // this is here because its intended to be the first test run. Since it depends on tick count since title start.
  97. nErrorCount += TestThreadGetThreadTimeMin();
  98. #if defined(EA_PLATFORM_APPLE) && EATHREAD_APPLE_GETMODULEINFO_ENABLED
  99. if(!IsSuperUser())
  100. {
  101. EA::EAMain::Report("Skipping GetModuleInfoApple test because we don't have sufficient system privileges.\n");
  102. return nErrorCount;
  103. }
  104. EA::Thread::ModuleInfoApple moduleInfoApple[15];
  105. size_t n = EA::Thread::GetModuleInfoApple(moduleInfoApple, EAArrayCount(moduleInfoApple), NULL, true);
  106. #if defined(EA_PLATFORM_OSX)
  107. EATEST_VERIFY(n > 0);
  108. for(size_t i = 0; i < eastl::min(n, EAArrayCount(moduleInfoApple)); i++)
  109. EA::UnitTest::Report("%s\n", moduleInfoApple[i].mPath);
  110. #else
  111. EA_UNUSED(n);
  112. #endif
  113. #endif
  114. return nErrorCount;
  115. }
  116. ///////////////////////////////////////////////////////////////////////////////
  117. // EAMain
  118. //
  119. int EAMain(int argc, char** argv)
  120. {
  121. using namespace EA::Thread;
  122. using namespace EA::UnitTest;
  123. int nErrorCount(0);
  124. EA::EAMain::PlatformStartup();
  125. gTestLengthSeconds = (unsigned int)(3 * EA::UnitTest::GetSystemSpeed());
  126. if(gTestLengthSeconds == 0)
  127. gTestLengthSeconds = 1;
  128. // Set EAThread to route its errors to our own error reporting function.
  129. EA::Thread::SetAssertionFailureFunction(EAThreadFailure, NULL);
  130. #if defined(EA_DLL) && defined(EA_MEMORY_ENABLED) && EA_MEMORY_ENABLED
  131. EA::Allocator::InitSharedDllAllocator();
  132. #endif
  133. //Set EAThread to use the Default Allocator to keep track of our memory usage
  134. #ifndef EA_OPENSOURCE
  135. EA::Thread::SetAllocator(EA::Allocator::ICoreAllocator::GetDefaultAllocator());
  136. #endif
  137. EA::Thread::InitCallstack();
  138. // Print ThreadId for this primary thread.
  139. const ThreadId threadId = GetThreadId();
  140. ReportVerbosity(1, "Primary thread ThreadId: %s\n", EAThreadThreadIdToString(threadId));
  141. // Print SysThreadId for this primary thread.
  142. const SysThreadId sysThreadId = GetSysThreadId(threadId);
  143. ReportVerbosity(1, "Primary thread SysThreadId: %s\n", EAThreadSysThreadIdToString(sysThreadId));
  144. // Print thread priority for this primary thread.
  145. const int nPriority = EA::Thread::GetThreadPriority();
  146. ReportVerbosity(1, "Primary thread priority: %d\n", nPriority);
  147. const int nProcessorCount = EA::Thread::GetProcessorCount();
  148. ReportVerbosity(1, "Currently active virtual processor count: %d\n", nProcessorCount);
  149. #if defined(EA_PLATFORM_MICROSOFT) && !EA_POSIX_THREADS_AVAILABLE && !EA_USE_CPP11_CONCURRENCY
  150. const DWORD dwCurrentThreadId = GetCurrentThreadId(); // This is a system OS call.
  151. EATEST_VERIFY_F(sysThreadId == dwCurrentThreadId, "GetSysThreadId failed. SysThreadId = %u, sys thread id = %u.\n", (unsigned)sysThreadId, (unsigned)dwCurrentThreadId);
  152. #endif
  153. // Add the tests
  154. TestApplication testSuite("EAThread Unit Tests", argc, argv);
  155. testSuite.AddTest("Atomic", TestThreadAtomic);
  156. testSuite.AddTest("Barrier", TestThreadBarrier);
  157. testSuite.AddTest("Callstack", TestThreadCallstack);
  158. testSuite.AddTest("Condition", TestThreadCondition);
  159. testSuite.AddTest("EnumerateThreads", TestEnumerateThreads);
  160. testSuite.AddTest("Futex", TestThreadFutex);
  161. testSuite.AddTest("Misc", TestThreadMisc);
  162. testSuite.AddTest("Mutex", TestThreadMutex);
  163. testSuite.AddTest("RWMutex", TestThreadRWMutex);
  164. testSuite.AddTest("RWSemaphore", TestThreadRWSemaLock);
  165. testSuite.AddTest("RWSpinLock", TestThreadRWSpinLock);
  166. testSuite.AddTest("Semaphore", TestThreadSemaphore);
  167. testSuite.AddTest("SmartPtr", TestThreadSmartPtr);
  168. testSuite.AddTest("SpinLock", TestThreadSpinLock);
  169. testSuite.AddTest("Storage", TestThreadStorage);
  170. testSuite.AddTest("Sync", TestThreadSync);
  171. testSuite.AddTest("Thread", TestThreadThread);
  172. testSuite.AddTest("ThreadPool", TestThreadThreadPool);
  173. nErrorCount += testSuite.Run();
  174. #ifndef EA_USE_CPP11_CONCURRENCY
  175. // Verify the converted a EA::Thread::ThreadId to a EA::Thread::SysThreadId id matches this thread context id.
  176. const ThreadId convertedThreadId = GetThreadId(sysThreadId);
  177. EATEST_VERIFY_F(threadId == convertedThreadId , "GetThreadId failed to convert SysThreadId. ThreadId = %s, converted thread id = %s.\n", EAThreadThreadIdToString(threadId), EAThreadThreadIdToString(convertedThreadId));
  178. #endif
  179. EA::Thread::ShutdownCallstack();
  180. EA::EAMain::PlatformShutdown(nErrorCount);
  181. return nErrorCount;
  182. }