@@ -273,6 +273,7 @@ const char * const TestInfoKindName[] =
273
273
" env" ,
274
274
" command" ,
275
275
" timeout" ,
276
+ " timeoutRetries" ,
276
277
" sourcepath" ,
277
278
" eol-normalization" ,
278
279
" custom-config-file" ,
@@ -315,34 +316,34 @@ char *CL, *_CL_;
315
316
const char *JCBinary = " jshost.exe" ;
316
317
317
318
BOOL FStatus = TRUE ;
318
- char *StatusPrefix;
319
- const char *StatusFormat;
319
+ char *StatusPrefix = nullptr ;
320
+ const char *StatusFormat = nullptr ;
320
321
321
- BOOL FVerbose;
322
- BOOL FQuiet;
323
- BOOL FNoWarn;
324
- BOOL FTest;
322
+ BOOL FVerbose = FALSE ;
323
+ BOOL FQuiet = FALSE ;
324
+ BOOL FNoWarn = FALSE ;
325
+ BOOL FTest = FALSE ;
325
326
BOOL FStopOnError = FALSE ;
326
327
BOOL GStopDueToError = FALSE ;
327
- BOOL FLow;
328
- BOOL FNoDelete;
329
- BOOL FCopyOnFail;
328
+ BOOL FLow = FALSE ;
329
+ BOOL FNoDelete = FALSE ;
330
+ BOOL FCopyOnFail = FALSE ;
330
331
BOOL FSummary = TRUE ;
331
- BOOL FMoveDiffs;
332
- BOOL FNoMoveDiffsSwitch;
333
- BOOL FRelativeLogPath;
332
+ BOOL FMoveDiffs = FALSE ;
333
+ BOOL FNoMoveDiffsSwitch = FALSE ;
334
+ BOOL FRelativeLogPath = FALSE ;
334
335
BOOL FNoDirName = TRUE ;
335
- BOOL FBaseline;
336
+ BOOL FBaseline = FALSE ;
336
337
BOOL FRebase = FALSE ;
337
- BOOL FDiff;
338
- BOOL FBaseDiff;
339
- BOOL FSyncEnumDirs;
338
+ BOOL FDiff = FALSE ;
339
+ BOOL FBaseDiff = FALSE ;
340
+ BOOL FSyncEnumDirs = FALSE ;
340
341
BOOL FNogpfnt = TRUE ;
341
- BOOL FAppend;
342
+ BOOL FAppend = FALSE ;
342
343
BOOL FAppendTestNameToExtraCCFlags = FALSE ;
343
344
344
345
#ifndef NODEBUG
345
- BOOL FDebug;
346
+ BOOL FDebug = FALSE ;
346
347
#endif
347
348
348
349
// Output synchronization options
@@ -364,7 +365,6 @@ RLMODE Mode = DEFAULT_RLMODE;
364
365
char *DCFGfile = NULL ;
365
366
char const *CFGfile = NULL ;
366
367
char const *CMDfile = NULL ;
367
- int CFGline;
368
368
369
369
#define MAX_ALLOWED_THREADS 10 // must be <= MAXIMUM_WAIT_OBJECTS (64)
370
370
unsigned NumberOfThreads = 0 ;
@@ -376,15 +376,17 @@ BOOL FNoProgramOutput = FALSE;
376
376
BOOL FOnlyAssertOutput = FALSE ;
377
377
BOOL FExcludeDirs = FALSE ;
378
378
BOOL FGenLst = FALSE ;
379
- char *ResumeDir, *MatchDir;
379
+ char *ResumeDir = nullptr ;
380
+ char *MatchDir = nullptr ;
380
381
381
382
TIME_OPTION Timing = TIME_DIR | TIME_TEST; // Default to report times at test and directory level
382
383
383
- static const char *ProgramName;
384
- static const char *LogName;
385
- static const char *FullLogName;
386
- static const char *ResultsLogName;
387
- static const char *TestTimeout; // Stores timeout in seconds for all tests
384
+ static const char *ProgramName = nullptr ;
385
+ static const char *LogName = nullptr ;
386
+ static const char *FullLogName = nullptr ;
387
+ static const char *ResultsLogName = nullptr ;
388
+ static const char *TestTimeout = nullptr ; // Stores timeout in seconds for all tests
389
+ static const char *TestTimeoutRetries = nullptr ; // Number of timeout retries for all tests
388
390
389
391
// NOTE: this might be unused now
390
392
static char TempPath[MAX_PATH] = " " ; // Path for temporary files
@@ -2474,6 +2476,7 @@ WriteEnvLst
2474
2476
NULL ,
2475
2477
NULL ,
2476
2478
NULL ,
2479
+ NULL ,
2477
2480
NULL
2478
2481
};
2479
2482
@@ -2994,6 +2997,11 @@ ParseArg(
2994
2997
break ;
2995
2998
}
2996
2999
3000
+ if (!_stricmp (&arg[1 ], " timeoutRetries" )) {
3001
+ TestTimeoutRetries = ComplainIfNoArg (arg, s);
3002
+ break ;
3003
+ }
3004
+
2997
3005
#ifndef NODEBUG
2998
3006
if (!_stricmp (&arg[1 ], " debug" )) {
2999
3007
FDebug = FVerbose = TRUE ;
@@ -3540,6 +3548,32 @@ IsTimeoutStringValid(const char *strTimeout)
3540
3548
return TRUE ;
3541
3549
}
3542
3550
3551
+ BOOL
3552
+ IsTimeoutRetriesStringValid (const char *strTimeoutRetries)
3553
+ {
3554
+ char *end;
3555
+ _set_errno (0 );
3556
+
3557
+ uint32 numRetries = strtoul (strTimeoutRetries, &end, 10 );
3558
+
3559
+ if (errno != 0 || *end != 0 )
3560
+ {
3561
+ return FALSE ;
3562
+ }
3563
+
3564
+ // We will not be doing any math with this value, so no need to check for overflow.
3565
+ // However, large values will possibly result in an unacceptably long retry loop,
3566
+ // (especially with the default timeout being multiple minutes long),
3567
+ // so limit the number of retries to some arbitrary max.
3568
+
3569
+ if (numRetries > 100 )
3570
+ {
3571
+ return FALSE ;
3572
+ }
3573
+
3574
+ return TRUE ;
3575
+ }
3576
+
3543
3577
uint32 GetTimeoutValue (const char *strTimeout)
3544
3578
{
3545
3579
if (strTimeout == nullptr )
@@ -3606,13 +3640,26 @@ GetTestInfoFromNode
3606
3640
if (i == TIK_TIMEOUT)
3607
3641
{
3608
3642
// Validate the timeout string now to fail early so we don't run any tests when there is an error.
3609
- if (!IsTimeoutStringValid (testInfo->data [i])) {
3643
+ if (!IsTimeoutStringValid (testInfo->data [i]))
3644
+ {
3610
3645
CFG_ERROR_EX (fileName, node->LineNumber ,
3611
3646
" Invalid timeout specified. Cannot parse or too large.\n " , nullptr );
3612
3647
childNode->Dump ();
3613
3648
return FALSE ;
3614
3649
}
3615
3650
}
3651
+
3652
+ if (i == TIK_TIMEOUT_RETRIES)
3653
+ {
3654
+ // Validate the timeoutRetries string now to fail early so we don't run any tests when there is an error.
3655
+ if (!IsTimeoutRetriesStringValid (testInfo->data [i]))
3656
+ {
3657
+ CFG_ERROR_EX (fileName, node->LineNumber ,
3658
+ " Invalid number of timeout retries specified. Value must be numeric and <= 100.\n " , nullptr );
3659
+ childNode->Dump ();
3660
+ return FALSE ;
3661
+ }
3662
+ }
3616
3663
}
3617
3664
}
3618
3665
@@ -3626,6 +3673,17 @@ GetTestInfoFromNode
3626
3673
testInfo->data [i] = TestTimeout;
3627
3674
}
3628
3675
}
3676
+
3677
+ if (i == TIK_TIMEOUT_RETRIES && TestTimeoutRetries != nullptr )
3678
+ {
3679
+ // Overriding the timeoutRetries value with the command line value (if the command line value is larger)
3680
+ uint32 xmlTimeoutRetriesValue = GetTimeoutValue (testInfo->data [i]);
3681
+ uint32 testTimeoutRetriesValue = GetTimeoutValue (TestTimeoutRetries);
3682
+ if (xmlTimeoutRetriesValue < testTimeoutRetriesValue)
3683
+ {
3684
+ testInfo->data [i] = TestTimeoutRetries;
3685
+ }
3686
+ }
3629
3687
}
3630
3688
3631
3689
return TRUE ;
0 commit comments