rl.h 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. // rl.h
  6. // Header file for rl
  7. #undef UNICODE
  8. #undef _UNICODE
  9. #include <windows.h>
  10. #include <process.h>
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include <direct.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <time.h>
  18. #include <sys/stat.h>
  19. #include "xmlreader.h"
  20. #include "rlfeint.h"
  21. #pragma warning(disable:4127) // expression is constant, e.g., while(TRUE)
  22. #define LOCAL static
  23. typedef __int32 int32;
  24. typedef unsigned __int32 uint32;
  25. #define BUFFER_SIZE 1024
  26. #define MAXQUEUE 10000
  27. extern void assert(const char *file, int line);
  28. #define ASSERT(ex) ((ex) ? (void)0 : assert(__FILE__, __LINE__))
  29. #define ASSERTNR ASSERT
  30. #define UNREACHED FALSE
  31. #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
  32. #define REMAININGARRAYLEN(a, p) (ASSERT(a <= p && p <= a + ARRAYLEN(a)), ((sizeof(a) - (p - a)) / sizeof((a)[0])))
  33. // Target machines
  34. typedef struct tagTARGETINFO {
  35. const char * name;
  36. BOOL fRL_MACHINEonly;
  37. BOOL fAutoCrossCompilation;
  38. BOOL fUseNoGPF;
  39. const char * TARGET_VM;
  40. const char * LINKFLAGS;
  41. const char * NotTags;
  42. } TARGETINFO;
  43. extern TARGETINFO TargetInfo[];
  44. // Any changes made here should have corresponding name added
  45. // to TargetInfo in rl.cpp. NOTE: The TARGET_MACHINES enum is in exactly
  46. // the same order as the TargetInfo array is initialized
  47. typedef enum {
  48. TM_UNKNOWN,
  49. TM_X86,
  50. TM_PPCWCE,
  51. TM_WVM,
  52. TM_WVMCEE,
  53. TM_WVMX86,
  54. TM_MIPS,
  55. TM_ARM,
  56. TM_THUMB,
  57. TM_ARM64,
  58. TM_SH3,
  59. TM_SH4,
  60. TM_SH5C,
  61. TM_SH5M,
  62. TM_IA64,
  63. TM_AMD64,
  64. TM_AMD64SYS,
  65. TM_WVM64,
  66. TM_AM33,
  67. TM_M32R,
  68. TM_MSIL,
  69. TM_ALL
  70. } TARGET_MACHINES;
  71. extern TARGET_MACHINES TargetMachine;
  72. extern TARGET_MACHINES RLMachine;
  73. // Any changes made here should have corresponding name added
  74. // to TargetOSNames in rl.cpp. NOTE: The TARGET_OS enum is in exactly
  75. // the same order as the TargetOSNames array is initialized
  76. typedef enum {
  77. TO_UNKNOWN,
  78. TO_WIN7,
  79. TO_WIN8,
  80. TO_WINBLUE,
  81. TO_WIN10,
  82. TO_WP8,
  83. TO_ALL
  84. } TARGET_OS;
  85. extern TARGET_OS TargetOS;
  86. #define DEFAULT_OS TO_WIN7
  87. #define CFG_ERROR_EX(file,line,fmt,args) fprintf(stderr, "Error: %s(%d) - " ##fmt "\n", file, line, args)
  88. #define CFG_WARNING_EX(file,line,fmt,args) do { if (!FQuiet) printf("Warning: %s(%d) - " ##fmt "\n", file, line, (args)); } while (0)
  89. // Parsing delimiters
  90. #define OPT_DELIM " \t"
  91. #define XML_DELIM ","
  92. #define POGO_TEST_PREFIX "Pogo:"
  93. // Set default target machine based on the host machine
  94. // NOTE: this should be done dynamically, using getenv("PROCESSOR_ARCHITECTURE")
  95. #if defined(_M_IX86)
  96. #define DEFAULT_TM TM_X86
  97. #elif defined(_M_PPC)
  98. #define DEFAULT_TM TM_PPCWCE
  99. #elif defined(_M_MIPS)
  100. #define DEFAULT_TM TM_MIPS
  101. #elif defined(_M_ARM)
  102. #define DEFAULT_TM TM_ARM
  103. #elif defined(_M_ARM64)
  104. #define DEFAULT_TM TM_ARM64
  105. #elif defined(_M_THUMB)
  106. #define DEFAULT_TM TM_THUMB
  107. #elif defined(_M_SH)
  108. #define DEFAULT_TM TM_SH
  109. #elif defined(_M_IA64)
  110. #define DEFAULT_TM TM_IA64
  111. #else
  112. #define DEFAULT_TM TM_X86
  113. #endif
  114. #define RL_PRE_ENV_VAR "RL"
  115. #define RL_POST_ENV_VAR "_RL_"
  116. enum RLMODE
  117. {
  118. RM_ASM, RM_EXE, RM_DIR
  119. };
  120. extern RLMODE Mode;
  121. #define DEFAULT_RLMODE RM_EXE
  122. #define DEFAULT_ASM_DCFG "rlexedirs.xml"
  123. #define DEFAULT_ASM_CFG "rlexe.xml"
  124. #define DEFAULT_ASM_CMD "rl"
  125. #define DEFAULT_EXE_DCFG "rlexedirs.xml"
  126. #define DEFAULT_EXE_CFG "rlexe.xml"
  127. #define DEFAULT_EXE_CMD "rl"
  128. #define DEFAULT_TESTLST_DCFG "test.lst"
  129. #define DEFAULT_ENVLST_CFG "env.lst"
  130. #define DEFAULT_REGR_CL "cl"
  131. #define DEFAULT_REGR_DIFF "diff"
  132. #define DEFAULT_LOG_FILE "rl.log"
  133. #define DEFAULT_FULL_LOG_FILE "rl.full.log"
  134. #define DEFAULT_RESULTS_LOG_FILE "rl.results.log"
  135. #define DEFAULT_CROSS_TARGET_VM "issuerun -id:%d"
  136. #define DEFAULT_LINKER "link"
  137. #define DEFAULT_EXEC_TESTS_FLAGS ";"
  138. #define DEFAULT_TEST_TIMEOUT 60000
  139. #define DIR_LOCKFILE "regrlock.txt"
  140. // Statistics index.
  141. #ifndef _RL_STATS_DEFINED
  142. #define _RL_STATS_DEFINED
  143. typedef enum RL_STATS {
  144. RLS_TOTAL = 0, // overall stats
  145. RLS_EXE, // should == RLS_TOTAL at this time
  146. RLS_BASELINES, // baseline stats (== total if FBaseline && !FDiff)
  147. RLS_DIFFS, // diff stats (== total if FDiff && !FBaseline)
  148. RLS_COUNT
  149. };
  150. #endif
  151. enum ExternalTestKind
  152. {
  153. TK_MAKEFILE,
  154. TK_CMDSCRIPT,
  155. TK_JSCRIPT,
  156. TK_HTML,
  157. TK_COMMAND,
  158. };
  159. enum TestInfoKind
  160. {
  161. TIK_FILES = 0,
  162. TIK_BASELINE,
  163. TIK_COMPILE_FLAGS,
  164. TIK_LINK_FLAGS,
  165. TIK_TAGS,
  166. TIK_RL_DIRECTIVES,
  167. TIK_ENV,
  168. TIK_COMMAND,
  169. TIK_TIMEOUT,
  170. TIK_SOURCE_PATH,
  171. TIK_EOL_NORMALIZATION,
  172. _TIK_COUNT
  173. };
  174. extern const char * const TestInfoKindName[];
  175. struct TestInfo
  176. {
  177. BOOL hasData[_TIK_COUNT];
  178. const char * data[_TIK_COUNT];
  179. };
  180. struct Tags
  181. {
  182. Tags * next;
  183. const char * str;
  184. BOOL fInclude;
  185. };
  186. struct ConditionNodeList
  187. {
  188. ConditionNodeList * next;
  189. Xml::Node * node;
  190. };
  191. enum FILE_STATUS
  192. {
  193. FS_NONE, FS_EXCLUDED, FS_INCLUDED
  194. };
  195. enum PROCESS_CONFIG_STATUS
  196. {
  197. PCS_OK, PCS_ERROR, PCS_FILE_NOT_FOUND
  198. };
  199. enum FILE_CONFIG_STATUS
  200. {
  201. FCS_USER_SPECIFIED, FCS_US_FLAGS, FCS_READ
  202. };
  203. template<typename T>
  204. struct ListNode
  205. {
  206. ListNode *next;
  207. T string;
  208. };
  209. typedef ListNode<char*> StringList;
  210. typedef ListNode<const char*> ConstStringList;
  211. struct TestVariant
  212. {
  213. TestVariant() : next(NULL), optFlags(NULL) {}
  214. TestVariant * next;
  215. // Exe optimization flags.
  216. const char * optFlags;
  217. // Test-specific info.
  218. TestInfo testInfo;
  219. };
  220. struct Test
  221. {
  222. Test * next;
  223. // For tests
  224. StringList * files;
  225. // For directories
  226. const char * name;
  227. char * fullPath;
  228. int num;
  229. // Common.
  230. ConditionNodeList * conditionNodeList;
  231. TestInfo defaultTestInfo;
  232. TestVariant * variants;
  233. };
  234. struct TestList
  235. {
  236. Test * first;
  237. Test * last;
  238. };
  239. // Time options. Can do multiple types of timings, so do it bitwise
  240. #define TIME_NOTHING 0x0
  241. #define TIME_DIR 0x1
  242. #define TIME_TEST 0x2
  243. #define TIME_VARIATION 0x4
  244. #define TIME_ALL 0x7 // bitmask of all timing options
  245. typedef int TIME_OPTION; // could be enum, but C++ doesn't like |= on enum
  246. extern TIME_OPTION Timing;
  247. /////////////////////////////////////////////////////////////////////////
  248. //
  249. // Class declarations. Non-inline member functions are defined in rlmp.cpp.
  250. //
  251. /////////////////////////////////////////////////////////////////////////
  252. class CProtectedLong;
  253. class CHandle;
  254. class CDirectory;
  255. class CDirectoryQueue;
  256. class CThreadInfo;
  257. class COutputBuffer;
  258. /////////////////////////////////////////////////////////////////////////
  259. // CProtectedLong: a single value protected by a critical section. This is
  260. // used for things like test counts which are accessed by both worker threads
  261. // and the display thread.
  262. class CProtectedLong {
  263. CRITICAL_SECTION _cs;
  264. int32 _value;
  265. public:
  266. CProtectedLong() : _value(0)
  267. {
  268. InitializeCriticalSection(&_cs);
  269. }
  270. ~CProtectedLong()
  271. {
  272. DeleteCriticalSection(&_cs);
  273. }
  274. int32 operator++(int)
  275. {
  276. EnterCriticalSection(&_cs);
  277. int32 tmp = _value++;
  278. LeaveCriticalSection(&_cs);
  279. return tmp;
  280. }
  281. int32 operator--(int)
  282. {
  283. EnterCriticalSection(&_cs);
  284. int32 tmp = _value--;
  285. LeaveCriticalSection(&_cs);
  286. return tmp;
  287. }
  288. int32 operator+=(int32 incr)
  289. {
  290. EnterCriticalSection(&_cs);
  291. int32 tmp = (_value += incr);
  292. LeaveCriticalSection(&_cs);
  293. return tmp;
  294. }
  295. int32 operator=(int32 val)
  296. {
  297. EnterCriticalSection(&_cs);
  298. _value = val;
  299. LeaveCriticalSection(&_cs);
  300. return val;
  301. }
  302. bool operator==(CProtectedLong& rhs)
  303. {
  304. return _value == rhs._value;
  305. }
  306. operator int() { return _value; }
  307. };
  308. /////////////////////////////////////////////////////////////////////////
  309. // CHandle: a convenience class for storing HANDLE objects. When destructed
  310. // or set to another value, the current handle is closed. Helps prevent
  311. // handle leaks.
  312. class CHandle {
  313. HANDLE _h;
  314. public:
  315. CHandle() : _h(INVALID_HANDLE_VALUE) {}
  316. ~CHandle()
  317. {
  318. if (_h != INVALID_HANDLE_VALUE && _h != NULL)
  319. CloseHandle(_h);
  320. }
  321. HANDLE operator=(HANDLE h)
  322. {
  323. if (_h != INVALID_HANDLE_VALUE && _h != NULL)
  324. CloseHandle(_h);
  325. _h = h;
  326. return _h;
  327. }
  328. BOOL operator==(HANDLE h) { return h == _h ? TRUE : FALSE; }
  329. BOOL operator!=(HANDLE h) { return h != _h ? TRUE : FALSE; }
  330. operator HANDLE() { return _h; };
  331. };
  332. /////////////////////////////////////////////////////////////////////////
  333. // WorkObject: a wrapper class for elements used by WorkQueue. Requires
  334. // children classes to implement Dump if debug and keeps track of a _next
  335. // for use by WorkQueue.
  336. template <typename TWorkObject>
  337. class WorkObject {
  338. public:
  339. TWorkObject* _next;
  340. public:
  341. #ifndef NODEBUG
  342. virtual void Dump() = 0;
  343. #endif
  344. };
  345. /////////////////////////////////////////////////////////////////////////
  346. // WorkQueue: a generic class for keeping track of WorkObjects which need
  347. // to be queued and worked on.
  348. template <typename TWorkObject>
  349. class WorkQueue {
  350. protected:
  351. int _length;
  352. TWorkObject* _head;
  353. TWorkObject* _tail;
  354. CRITICAL_SECTION _cs; // ensure proper synchronized access
  355. CHandle _hWorkAvailSem; // signalled whenever there's work on the list
  356. CHandle _hMaxWorkQueueSem; // used to control length of work queue
  357. public:
  358. WorkQueue()
  359. : _head(NULL), _tail(NULL), _length(0)
  360. {
  361. SECURITY_ATTRIBUTES sa;
  362. InitializeCriticalSection(&_cs);
  363. /*
  364. * Create the semaphores for the work lists
  365. */
  366. memset(&sa, 0, sizeof(sa));
  367. sa.nLength = sizeof(sa);
  368. sa.lpSecurityDescriptor = NULL;
  369. sa.bInheritHandle = TRUE;
  370. _hWorkAvailSem = CreateSemaphoreW(&sa, 0, 100000, NULL);
  371. if (_hWorkAvailSem == NULL)
  372. Fatal("Unable to create semaphore (err %u)!\n", GetLastError());
  373. _hMaxWorkQueueSem = CreateSemaphoreW(&sa, MAXQUEUE, MAXQUEUE, NULL);
  374. if (_hMaxWorkQueueSem == NULL)
  375. Fatal("Unable to create queue length semaphore (err %u)!\n", GetLastError());
  376. }
  377. ~WorkQueue()
  378. {
  379. // The CHandle objects clean up after themselves.
  380. DeleteCriticalSection(&_cs);
  381. }
  382. virtual TWorkObject* Pop() = 0;
  383. TWorkObject* Append(TWorkObject* pNew)
  384. {
  385. if (WaitForSingleObject(_hMaxWorkQueueSem, INFINITE) != WAIT_OBJECT_0) {
  386. Fatal("Semaphore wait failed, can't add to work list");
  387. }
  388. EnterCriticalSection(&_cs);
  389. if (_tail == NULL) {
  390. _head = _tail = pNew;
  391. } else {
  392. _tail->_next = pNew;
  393. _tail = pNew;
  394. }
  395. pNew->_next = NULL;
  396. ++_length;
  397. LeaveCriticalSection(&_cs);
  398. ReleaseSemaphore(_hWorkAvailSem, 1, NULL);
  399. return pNew;
  400. }
  401. int Length()
  402. {
  403. int tmp;
  404. EnterCriticalSection(&_cs);
  405. tmp = _length;
  406. LeaveCriticalSection(&_cs);
  407. return tmp;
  408. }
  409. DWORD WaitForWork(DWORD dwMilliseconds)
  410. {
  411. return WaitForSingleObject(_hWorkAvailSem, dwMilliseconds);
  412. }
  413. // The queue work available semaphore has a count for every
  414. // directory. When the queue is exhausted, each thread waits on
  415. // this semaphore again. So at the end, everyone will still be waiting!
  416. // So, add the number of threads to the count, so each thread
  417. // notices, one by one, that everything's done.
  418. void AdjustWaitForThreadCount()
  419. {
  420. ReleaseSemaphore(_hWorkAvailSem, (int)NumberOfThreads, NULL);
  421. }
  422. TWorkObject* GetNextItem()
  423. {
  424. DWORD dwWait = 0;
  425. TWorkObject* toReturn = NULL;
  426. while (TRUE)
  427. {
  428. dwWait = this->WaitForWork(1000);
  429. if (dwWait == WAIT_OBJECT_0) {
  430. // pick an item off the head of the work list
  431. toReturn = this->Pop();
  432. break;
  433. } else if (dwWait == WAIT_TIMEOUT) {
  434. if (bThreadStop)
  435. break;
  436. } else {
  437. LogError("Thread %d: Semaphore wait failed\n", ThreadId);
  438. break;
  439. }
  440. }
  441. if (dwWait != WAIT_OBJECT_0)
  442. return NULL;
  443. if (bThreadStop)
  444. return NULL;
  445. return toReturn;
  446. }
  447. TWorkObject* GetNextItem_NoBlock(DWORD waitTime)
  448. {
  449. DWORD dwWait = 0;
  450. TWorkObject* toReturn = NULL;
  451. dwWait = this->WaitForWork(waitTime);
  452. if(dwWait == WAIT_OBJECT_0) {
  453. // pick an item off the head of the work list
  454. toReturn = this->Pop();
  455. }
  456. return toReturn;
  457. }
  458. #ifndef NODEBUG
  459. void Dump()
  460. {
  461. TWorkObject* tmp;
  462. EnterCriticalSection(&_cs);
  463. printf("WorkQueue, length %d\n", _length);
  464. for (tmp = _head; tmp != NULL; tmp = tmp->_next) {
  465. tmp->Dump();
  466. }
  467. LeaveCriticalSection(&_cs);
  468. }
  469. #endif
  470. };
  471. /////////////////////////////////////////////////////////////////////////
  472. // CDirectory: represents a single directory and the tests that need to
  473. // be run within it.
  474. class CDirectory : public WorkObject<CDirectory> {
  475. friend class CDirectoryQueue;
  476. TestList _testList; // list of files in directory
  477. Test * _pDir; // directory info
  478. CHandle _dirLock; // the directory lock file
  479. bool _isDiffDirectory; // directory is for doing diffs, not masters
  480. bool _isDirStarted; // indicates if the directory has begun executing
  481. time_t start_dir; // time when dir began executing
  482. time_t elapsed_dir; // time taken for dir to execute.
  483. // initialized to 0 but set to a value upon directory finish.
  484. CRITICAL_SECTION _cs; // ensure proper synchronized access
  485. // Try to lock the directory. If we successfully got the lock without
  486. // waiting, return true.
  487. // Note that since we use FILE_FLAG_DELETE_ON_CLOSE, the lock file should
  488. // go away if the process dies because of ctrl-c.
  489. bool TryLock();
  490. // Lock the directory; wait on the lock until it's available
  491. void WaitLock();
  492. // Output begin/finish summaries if all tests in the directory are executed.
  493. void WriteDirectoryBeginSummary();
  494. void WriteDirectoryFinishSummary();
  495. public:
  496. // Multiple threads can be working in a single directory,
  497. // we'll need to make these CProtectedLong.
  498. CProtectedLong NumVariations, NumVariationsRun, NumFailures, NumDiffs;
  499. RL_STATS stat; // which mode stat to update
  500. CDirectory(Test * pDir, TestList testList)
  501. : _pDir(pDir), _testList(testList), _isDiffDirectory(false), _isDirStarted(false), elapsed_dir(0)
  502. {
  503. InitializeCriticalSection(&_cs);
  504. }
  505. ~CDirectory();
  506. TestList * GetTestList() { return &_testList; }
  507. const char* GetDirectoryName() { return _pDir->name; }
  508. char* GetDirectoryPath() { return _pDir->fullPath; }
  509. int GetDirectoryNumber() { return _pDir->num; }
  510. BOOL HasTestInfoData(TestInfoKind testInfoKind) { return _pDir->defaultTestInfo.hasData[testInfoKind]; }
  511. const char* GetTestInfoData(TestInfoKind testInfoKind) { return _pDir->defaultTestInfo.data[testInfoKind]; }
  512. const char* GetFullPathFromSourceOrDirectory() { return HasTestInfoData(TIK_SOURCE_PATH) ? GetTestInfoData(TIK_SOURCE_PATH) : GetDirectoryPath(); }
  513. bool IsBaseline() { return !_isDiffDirectory; }
  514. void SetDiffFlag() { _isDiffDirectory = true; }
  515. void InitStats(int run);
  516. int32 IncRun(int inc = 1);
  517. int32 IncFailures(int inc = 1);
  518. int32 IncDiffs();
  519. // Trigger update of directory state.
  520. void UpdateState();
  521. void TryBeginDirectory();
  522. void TryEndDirectory();
  523. int Count(); // return count of tests in the directory
  524. #ifndef NODEBUG
  525. void Dump();
  526. #endif
  527. };
  528. /////////////////////////////////////////////////////////////////////////
  529. // CDirectoryQueue: a queue of directories that need to have work done.
  530. class CDirectoryQueue : public WorkQueue<CDirectory> {
  531. public:
  532. ~CDirectoryQueue();
  533. // Return a directory to use. Normally, just peel the first one off the
  534. // work queue. However, if that directory is locked by another copy of
  535. // rl.exe, then skip it and try the next directory, until there are no
  536. // directories left. If that happens, just wait on the first locked
  537. // directory.
  538. CDirectory* Pop();
  539. };
  540. /////////////////////////////////////////////////////////////////////////
  541. // CDirectoryAndTestCase: Keep track of directory and test case in a class for
  542. // use in CDirectoryAndTestCaseQueue.
  543. // Reuse CDirectory because it has all the nice profiling data already.
  544. class CDirectoryAndTestCase : public WorkObject<CDirectoryAndTestCase> {
  545. public:
  546. CDirectory* _pDir;
  547. Test* _pTest;
  548. public:
  549. CDirectoryAndTestCase(CDirectory* pDir, Test* pTest)
  550. : _pDir(pDir), _pTest(pTest)
  551. {
  552. _next = NULL;
  553. }
  554. ~CDirectoryAndTestCase()
  555. {
  556. // This class is just a container for CDirectory and Test.
  557. // We don't want to clean up the objects here,
  558. // CDirectory will be cleaned up via ~CDirectoryQueue.
  559. }
  560. #ifndef NODEBUG
  561. void Dump()
  562. {
  563. _pDir->Dump();
  564. }
  565. #endif
  566. };
  567. /////////////////////////////////////////////////////////////////////////
  568. // CDirectoryAndTestCaseQueue: a simple queue to hold CDirectoryAndTestCase objects.
  569. class CDirectoryAndTestCaseQueue : public WorkQueue<CDirectoryAndTestCase> {
  570. public:
  571. CDirectoryAndTestCase* Pop();
  572. };
  573. /////////////////////////////////////////////////////////////////////////
  574. // CThreadInfo: a class with various bits of information about the current
  575. // state of a thread. An array of these objects is created before the worker
  576. // threads are started. This array is accessed like this: ThreadInfo[ThreadId],
  577. // where ThreadId is a __declspec(thread) TLS variable. The status update
  578. // thread uses the info here to construct the title bar.
  579. class CThreadInfo
  580. {
  581. CRITICAL_SECTION _cs;
  582. char _currentTest[BUFFER_SIZE];
  583. bool _isDone;
  584. struct TmpFileList
  585. {
  586. TmpFileList* _next;
  587. char* const _fullPath;
  588. TmpFileList(TmpFileList* next, char* fullPath)
  589. : _next(next), _fullPath(_strdup(fullPath))
  590. {
  591. }
  592. ~TmpFileList()
  593. {
  594. free(_fullPath);
  595. }
  596. TmpFileList(const TmpFileList&) = delete;
  597. void operator=(const TmpFileList&) = delete;
  598. };
  599. TmpFileList* _head;
  600. public:
  601. CThreadInfo()
  602. : _head(NULL), _isDone(false)
  603. {
  604. InitializeCriticalSection(&_cs);
  605. _currentTest[0] = '\0';
  606. }
  607. ~CThreadInfo()
  608. {
  609. ClearTmpFileList();
  610. DeleteCriticalSection(&_cs);
  611. }
  612. bool IsDone() { return _isDone; }
  613. void Done();
  614. // Track current test, for use in creating the title bar
  615. void SetCurrentTest(const char* dir, const char* test, bool isBaseline);
  616. template <size_t bufSize>
  617. void GetCurrentTest(char (&currentTest)[bufSize])
  618. {
  619. EnterCriticalSection(&_cs);
  620. strcpy_s(currentTest, _currentTest);
  621. LeaveCriticalSection(&_cs);
  622. }
  623. // Track currently in-use temp files, so we can clean them up if we exit
  624. // by ctrl-c.
  625. void AddToTmpFileList(char* fullPath);
  626. void ClearTmpFileList();
  627. void DeleteTmpFileList();
  628. };
  629. /////////////////////////////////////////////////////////////////////////
  630. // COutputBuffer: a buffered output class. Store up output so it can
  631. // all be flushed at once. Used to keep per-thread output from
  632. // interleaving too much and becoming unreadable. This class is
  633. // not synchronized. It is expected that there is one of these objects per
  634. // output location (stdout, file, etc) per thread. Flushing the output *is*
  635. // synchronized on a critical section that should be used around *all*
  636. // worker thread stdio. (Actually, all normal output should go through this
  637. // class.) A NULL file or filename is allowed, in which case everything
  638. // happens as normal, but the Flush() operation doesn't display anything or
  639. // send anything to disk.
  640. class COutputBuffer
  641. {
  642. char* _start;
  643. char* _end;
  644. bool _buffered; // true == buffer output; false == flush immediately (e.g., primary thread)
  645. bool _textGrabbed; // true == someone grabbed the text, used for asserting
  646. size_t _bufSize;
  647. enum { OUT_ILLEGAL=0, OUT_FILE, OUT_FILENAME } _type;
  648. union { // output type info
  649. FILE* _pfile; // OUT_FILE
  650. char* _filename; // OUT_FILENAME
  651. };
  652. // Set the pointers to indicate the buffer is empty. Don't reallocate
  653. // or free the buffer, though---it will get reused.
  654. void Reset();
  655. // Flush the output; synchronizes printf output using csStdio
  656. void Flush(FILE* pfile);
  657. public:
  658. COutputBuffer(const char* logfile, bool buffered = true);
  659. COutputBuffer(FILE* pfile, bool buffered = true);
  660. ~COutputBuffer();
  661. const char *GetText() { ASSERTNR(_type == OUT_FILE); _textGrabbed = true; return _start; }
  662. // Add without doing varargs formatting (avoids local buffer size problems)
  663. void AddDirect(char* string);
  664. // Add text to the output buffer. Just like printf.
  665. void Add(const char* fmt, ...);
  666. // Flush the output to wherever it's going
  667. void Flush();
  668. };
  669. /////////////////////////////////////////////////////////////////////////
  670. extern const char *DIFF_DIR;
  671. extern char *REGRESS, *MASTER_DIR;
  672. extern const char *REGR_CL, *REGR_DIFF;
  673. extern char *REGR_ASM, *REGR_SHOWD;
  674. extern const char *TARGET_VM;
  675. extern char *EXTRA_CC_FLAGS, *EXEC_TESTS_FLAGS;
  676. extern const char *LINKER, *LINKFLAGS;
  677. extern const char *JCBinary;
  678. extern BOOL FBaseline;
  679. extern BOOL FRebase; // Whether creates .rebase file if testout mismatches baseline
  680. extern BOOL FDiff;
  681. extern BOOL FBaseDiff;
  682. extern BOOL FVerbose;
  683. extern BOOL FSummary;
  684. extern BOOL FNoDelete;
  685. extern BOOL FCopyOnFail;
  686. extern BOOL FParallel;
  687. extern BOOL FSyncEnumDirs;
  688. extern BOOL FNogpfnt;
  689. extern BOOL FTest;
  690. extern BOOL FAppendTestNameToExtraCCFlags;
  691. #define MAXOPTIONS 60
  692. extern const char *OptFlags[MAXOPTIONS + 1], *PogoOptFlags[MAXOPTIONS + 1];
  693. #ifndef NODEBUG
  694. extern BOOL FDebug;
  695. #endif
  696. extern BOOL bThreadStop;
  697. extern BOOL FSyncImmediate;
  698. extern BOOL FSyncVariation;
  699. extern BOOL FSyncTest;
  700. extern BOOL FSyncDir;
  701. extern BOOL FNoThreadId;
  702. extern char* BaseCompiler;
  703. extern char* DiffCompiler;
  704. extern CDirectoryQueue DiffDirectoryQueue;
  705. extern unsigned NumberOfThreads;
  706. extern CRITICAL_SECTION csCurrentDirectory; // used when changing current directory
  707. extern CRITICAL_SECTION csStdio; // for printf / fprintf synchronization
  708. extern __declspec(thread) int ThreadId;
  709. extern __declspec(thread) char *TargetVM;
  710. extern __declspec(thread) COutputBuffer* ThreadOut; // stdout
  711. extern __declspec(thread) COutputBuffer* ThreadLog; // log file
  712. extern __declspec(thread) COutputBuffer* ThreadFull; // full log file
  713. extern CThreadInfo* ThreadInfo;
  714. extern CProtectedLong NumVariationsRun[RLS_COUNT];
  715. extern CProtectedLong NumVariationsTotal[RLS_COUNT];
  716. extern CProtectedLong NumFailuresTotal[RLS_COUNT];
  717. extern CProtectedLong NumDiffsTotal[RLS_COUNT];
  718. extern BOOL FRLFE;
  719. extern char *RLFEOpts;
  720. extern const char * const ModeNames[];
  721. // rl.cpp
  722. extern void __cdecl Fatal(const char *fmt, ...);
  723. extern void __cdecl Warning(const char *fmt, ...);
  724. extern void __cdecl Message(const char *fmt, ...);
  725. extern void __cdecl WriteLog(const char *fmt, ...);
  726. extern void __cdecl LogOut(const char *fmt, ...);
  727. extern void __cdecl LogError(const char *fmt, ...);
  728. extern void FlushOutput(void);
  729. extern char *mytmpnam(const char* directory, const char *prefix, char *filename);
  730. extern int DoCompare(char *file1, char *file2, BOOL normalizeLineEndings = false);
  731. extern void UpdateTitleStatus();
  732. extern int mystrcmp(const char *a, const char *b);
  733. extern char * mystrtok(char *s, const char *delim, const char *term);
  734. extern void FreeTestList(TestList * pTestList);
  735. #ifndef NODEBUG
  736. extern void DumpTestList(TestList * pTestList);
  737. #endif
  738. extern void DeleteMultipleFiles(CDirectory* pDir, const char *pattern);
  739. extern char *GetFilenamePtr(char *path);
  740. extern const char* GetFilenameExt(const char *path);
  741. extern void DeleteFileMsg(char *filename);
  742. extern BOOL DeleteFileIfFound(const char *filename);
  743. extern void DeleteFileRetryMsg(char *filename);
  744. extern StringList * ParseStringList(const char* p, const char* delim);
  745. extern StringList * AppendStringList(StringList * stringList, StringList * appendList);
  746. extern StringList * AppendStringListCopy(StringList * stringList, StringList * appendList);
  747. extern void PrintTagsList(Tags* pTagsList);
  748. extern void AddTagToTagsList(Tags** pTagsList, Tags** pTagsLast, const char* str, BOOL fInclude);
  749. extern BOOL
  750. SuppressNoGPF(
  751. Test * pTest
  752. );
  753. extern BOOL
  754. HasInfo
  755. (
  756. const char * szInfoList,
  757. const char * delim,
  758. const char * szInfo
  759. );
  760. extern BOOL
  761. HasInfoList
  762. (
  763. const char * szInfoList1,
  764. const char * delim1,
  765. const char * szInfoList2,
  766. const char * delim2,
  767. bool allMustMatch
  768. );
  769. extern BOOL
  770. GetTestInfoFromNode
  771. (
  772. const char * fileName,
  773. Xml::Node * node,
  774. TestInfo * testInfo
  775. );
  776. extern char * getenv_unsafe(const char *);
  777. extern FILE * fopen_unsafe(const char *, const char *);
  778. extern char* strerror_unsafe(int errnum);
  779. // rlregr.cpp
  780. extern void RegrInit(void);
  781. extern BOOL RegrStartDir(char* path);
  782. extern BOOL RegrEndDir(char* path);
  783. extern int RegrFile(CDirectory* pDir, Test * pTest, TestVariant * pTestVariant);
  784. // rlrun.cpp
  785. extern void RunInit(void);
  786. extern BOOL IsPogoTest(Test * pFilename);
  787. extern BOOL RunStartDir(char *dir);
  788. extern int ExecTest(CDirectory* pDir, Test * pTest, TestVariant * pTestVariant);
  789. // rlmp.cpp
  790. extern int ExecuteCommand(const char* path, const char* CommandLine, DWORD millisecTimeout = INFINITE, void* localEnvVars = NULL);
  791. extern int DoOneExternalTest(
  792. CDirectory* pDir,
  793. TestVariant* pTestVariant,
  794. char *optFlags,
  795. char *inCCFlags,
  796. char *inLinkFlags,
  797. char *testCmd,
  798. ExternalTestKind kind,
  799. BOOL fSyncVariationWhenFinished,
  800. BOOL fCleanBefore,
  801. BOOL fCleanAfter,
  802. BOOL fSuppressNoGPF,
  803. void *localEnvVars = NULL
  804. );
  805. extern void
  806. WriteSummary(
  807. const char *name,
  808. BOOL fBaseline,
  809. int tests,
  810. int diffs,
  811. int failures
  812. );
  813. // rlfeint.cpp
  814. extern void RLFEInit(BYTE numThreads, int numDirs);
  815. extern void RLFEAddRoot(RL_STATS stat, DWORD total);
  816. extern void RLFEAddTest(RL_STATS stat, CDirectory *pDir);
  817. extern void RLFEAddLog(CDirectory *pDir, RLFE_STATUS rlfeStatus, const char *testName, const char *subTestName, const char *logText);
  818. extern void RLFETestStatus(CDirectory *pDir);
  819. extern void RLFEThreadDir(CDirectory *pDir, BYTE num);
  820. extern void RLFEThreadStatus(BYTE num, const char *text);
  821. extern BOOL RLFEConnect(const char *prefix);
  822. extern void RLFEDisconnect(BOOL fKilled);