rl.h 28 KB

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