9
9
"fmt"
10
10
"reflect"
11
11
"runtime"
12
- "slices"
13
12
"sync"
14
13
"sync/atomic"
15
14
"testing"
36
35
panicData any // panic data recovered from an internal test execution when using an additional feature wrapper
37
36
panicStacktrace string // stacktrace from the panic recovered from an internal test
38
37
isARetry bool // flag to tag if a current test execution is a retry
39
- isANewTest bool // flag to tag if a current test execution is part of a new test (EFD not known test)
38
+ isANewTest bool // flag to tag if a current test execution is part of a new test
39
+ isEFDExecution bool // flag to tag if a current test execution is part of an EFD execution
40
+ isATRExecution bool // flag to tag if a current test execution is part of an ATR execution
40
41
hasAdditionalFeatureWrapper bool // flag to check if the current execution is part of an additional feature wrapper
41
42
}
42
43
@@ -234,7 +235,10 @@ func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) (func(*
234
235
}
235
236
}
236
237
},
237
- execMetaAdjust : nil , // No execMetaAdjust needed
238
+ execMetaAdjust : func (execMeta * testExecutionMetadata , executionIndex int ) {
239
+ // Set the flag ATR execution to true
240
+ execMeta .isATRExecution = true
241
+ },
238
242
})
239
243
}, true
240
244
}
@@ -243,95 +247,82 @@ func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) (func(*
243
247
244
248
// applyEarlyFlakeDetectionAdditionalFeature applies the early flake detection feature as a wrapper of a func(*testing.T)
245
249
func applyEarlyFlakeDetectionAdditionalFeature (testInfo * commonInfo , targetFunc func (* testing.T ), settings * net.SettingsResponseData ) (func (* testing.T ), bool ) {
246
- earlyFlakeDetectionData := integrations .GetEarlyFlakeDetectionSettings ()
247
- if earlyFlakeDetectionData != nil &&
248
- len (earlyFlakeDetectionData .Tests ) > 0 {
249
-
250
- // Define is a known test flag
251
- isAKnownTest := false
252
-
253
- // Check if the test is a known test or a new one
254
- if knownSuites , ok := earlyFlakeDetectionData .Tests [testInfo .moduleName ]; ok {
255
- if knownTests , ok := knownSuites [testInfo .suiteName ]; ok {
256
- if slices .Contains (knownTests , testInfo .testName ) {
257
- isAKnownTest = true
258
- }
259
- }
260
- }
250
+ isKnown , hasKnownData := isKnownTest (testInfo )
251
+ if ! hasKnownData || isKnown {
252
+ return targetFunc , false
253
+ }
261
254
262
- // If it's a new test, then we apply the EFD wrapper
263
- if ! isAKnownTest {
264
- return func (t * testing.T ) {
265
- var testPassCount , testSkipCount , testFailCount int
266
-
267
- runTestWithRetry (& runTestWithRetryOptions {
268
- targetFunc : targetFunc ,
269
- t : t ,
270
- initialRetryCount : 0 ,
271
- adjustRetryCount : func (duration time.Duration ) int64 {
272
- slowTestRetriesSettings := settings .EarlyFlakeDetection .SlowTestRetries
273
- durationSecs := duration .Seconds ()
274
- if durationSecs < 5 {
275
- return int64 (slowTestRetriesSettings .FiveS )
276
- } else if durationSecs < 10 {
277
- return int64 (slowTestRetriesSettings .TenS )
278
- } else if durationSecs < 30 {
279
- return int64 (slowTestRetriesSettings .ThirtyS )
280
- } else if duration .Minutes () < 5 {
281
- return int64 (slowTestRetriesSettings .FiveM )
282
- }
283
- return 0
284
- },
285
- shouldRetry : func (ptrToLocalT * testing.T , executionIndex int , remainingRetries int64 ) bool {
286
- return remainingRetries >= 0
287
- },
288
- perExecution : func (ptrToLocalT * testing.T , executionIndex int , duration time.Duration ) {
289
- // Collect test results
290
- if ptrToLocalT .Failed () {
291
- testFailCount ++
292
- } else if ptrToLocalT .Skipped () {
293
- testSkipCount ++
294
- } else {
295
- testPassCount ++
296
- }
297
- },
298
- onRetryEnd : func (t * testing.T , executionIndex int , lastPtrToLocalT * testing.T ) {
299
- // Update test status based on collected counts
300
- tCommonPrivates := getTestPrivateFields (t )
301
- if tCommonPrivates == nil {
302
- panic ("getting test private fields failed" )
303
- }
304
- status := "passed"
305
- if testPassCount == 0 {
306
- if testSkipCount > 0 {
307
- status = "skipped"
308
- tCommonPrivates .SetSkipped (true )
309
- }
310
- if testFailCount > 0 {
311
- status = "failed"
312
- tCommonPrivates .SetFailed (true )
313
- tParentCommonPrivates := getTestParentPrivateFields (t )
314
- if tParentCommonPrivates == nil {
315
- panic ("getting test parent private fields failed" )
316
- }
317
- tParentCommonPrivates .SetFailed (true )
318
- }
255
+ // If it's a new test, then we apply the EFD wrapper
256
+ return func (t * testing.T ) {
257
+ var testPassCount , testSkipCount , testFailCount int
258
+
259
+ runTestWithRetry (& runTestWithRetryOptions {
260
+ targetFunc : targetFunc ,
261
+ t : t ,
262
+ initialRetryCount : 0 ,
263
+ adjustRetryCount : func (duration time.Duration ) int64 {
264
+ slowTestRetriesSettings := settings .EarlyFlakeDetection .SlowTestRetries
265
+ durationSecs := duration .Seconds ()
266
+ if durationSecs < 5 {
267
+ return int64 (slowTestRetriesSettings .FiveS )
268
+ } else if durationSecs < 10 {
269
+ return int64 (slowTestRetriesSettings .TenS )
270
+ } else if durationSecs < 30 {
271
+ return int64 (slowTestRetriesSettings .ThirtyS )
272
+ } else if duration .Minutes () < 5 {
273
+ return int64 (slowTestRetriesSettings .FiveM )
274
+ }
275
+ return 0
276
+ },
277
+ shouldRetry : func (ptrToLocalT * testing.T , executionIndex int , remainingRetries int64 ) bool {
278
+ return remainingRetries >= 0
279
+ },
280
+ perExecution : func (ptrToLocalT * testing.T , executionIndex int , duration time.Duration ) {
281
+ // Collect test results
282
+ if ptrToLocalT .Failed () {
283
+ testFailCount ++
284
+ } else if ptrToLocalT .Skipped () {
285
+ testSkipCount ++
286
+ } else {
287
+ testPassCount ++
288
+ }
289
+ },
290
+ onRetryEnd : func (t * testing.T , executionIndex int , lastPtrToLocalT * testing.T ) {
291
+ // Update test status based on collected counts
292
+ tCommonPrivates := getTestPrivateFields (t )
293
+ if tCommonPrivates == nil {
294
+ panic ("getting test private fields failed" )
295
+ }
296
+ status := "passed"
297
+ if testPassCount == 0 {
298
+ if testSkipCount > 0 {
299
+ status = "skipped"
300
+ tCommonPrivates .SetSkipped (true )
301
+ }
302
+ if testFailCount > 0 {
303
+ status = "failed"
304
+ tCommonPrivates .SetFailed (true )
305
+ tParentCommonPrivates := getTestParentPrivateFields (t )
306
+ if tParentCommonPrivates == nil {
307
+ panic ("getting test parent private fields failed" )
319
308
}
309
+ tParentCommonPrivates .SetFailed (true )
310
+ }
311
+ }
320
312
321
- // Print summary after retries
322
- if executionIndex > 0 {
323
- fmt .Printf (" [ %v after %v retries by Datadog's early flake detection ]\n " , status , executionIndex )
324
- }
325
- },
326
- execMetaAdjust : func (execMeta * testExecutionMetadata , executionIndex int ) {
327
- // Set the flag new test to true
328
- execMeta .isANewTest = true
329
- },
330
- })
331
- }, true
332
- }
333
- }
334
- return targetFunc , false
313
+ // Print summary after retries
314
+ if executionIndex > 0 {
315
+ fmt .Printf (" [ %v after %v retries by Datadog's early flake detection ]\n " , status , executionIndex )
316
+ }
317
+ },
318
+ execMetaAdjust : func (execMeta * testExecutionMetadata , executionIndex int ) {
319
+ // Set the flag new test to true
320
+ execMeta .isANewTest = true
321
+ // Set the flag EFD execution to true
322
+ execMeta .isEFDExecution = true
323
+ },
324
+ })
325
+ }, true
335
326
}
336
327
337
328
// runTestWithRetry encapsulates the common retry logic for test functions.
@@ -386,6 +377,12 @@ func runTestWithRetry(options *runTestWithRetryOptions) {
386
377
if originalExecMeta .isARetry {
387
378
execMeta .isARetry = true
388
379
}
380
+ if originalExecMeta .isEFDExecution {
381
+ execMeta .isEFDExecution = true
382
+ }
383
+ if originalExecMeta .isATRExecution {
384
+ execMeta .isATRExecution = true
385
+ }
389
386
}
390
387
391
388
// If we are in a retry execution, set the `isARetry` flag
0 commit comments