99 "fmt"
1010 "reflect"
1111 "runtime"
12- "slices"
1312 "sync"
1413 "sync/atomic"
1514 "testing"
3635 panicData any // panic data recovered from an internal test execution when using an additional feature wrapper
3736 panicStacktrace string // stacktrace from the panic recovered from an internal test
3837 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
4041 hasAdditionalFeatureWrapper bool // flag to check if the current execution is part of an additional feature wrapper
4142 }
4243
@@ -234,7 +235,10 @@ func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) (func(*
234235 }
235236 }
236237 },
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+ },
238242 })
239243 }, true
240244 }
@@ -243,95 +247,82 @@ func applyFlakyTestRetriesAdditionalFeature(targetFunc func(*testing.T)) (func(*
243247
244248// applyEarlyFlakeDetectionAdditionalFeature applies the early flake detection feature as a wrapper of a func(*testing.T)
245249func 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+ }
261254
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" )
319308 }
309+ tParentCommonPrivates .SetFailed (true )
310+ }
311+ }
320312
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
335326}
336327
337328// runTestWithRetry encapsulates the common retry logic for test functions.
@@ -386,6 +377,12 @@ func runTestWithRetry(options *runTestWithRetryOptions) {
386377 if originalExecMeta .isARetry {
387378 execMeta .isARetry = true
388379 }
380+ if originalExecMeta .isEFDExecution {
381+ execMeta .isEFDExecution = true
382+ }
383+ if originalExecMeta .isATRExecution {
384+ execMeta .isATRExecution = true
385+ }
389386 }
390387
391388 // If we are in a retry execution, set the `isARetry` flag
0 commit comments