@@ -33,7 +33,11 @@ const {
33
33
TEST_SOURCE_START ,
34
34
TEST_CODE_OWNERS ,
35
35
TEST_SESSION_NAME ,
36
- TEST_LEVEL_EVENT_TYPES
36
+ TEST_LEVEL_EVENT_TYPES ,
37
+ DI_ERROR_DEBUG_INFO_CAPTURED ,
38
+ DI_DEBUG_ERROR_FILE ,
39
+ DI_DEBUG_ERROR_SNAPSHOT_ID ,
40
+ DI_DEBUG_ERROR_LINE
37
41
} = require ( '../../packages/dd-trace/src/plugins/util/test' )
38
42
const { DD_HOST_CPU_COUNT } = require ( '../../packages/dd-trace/src/plugins/util/env' )
39
43
const { ERROR_MESSAGE } = require ( '../../packages/dd-trace/src/constants' )
@@ -2399,4 +2403,205 @@ describe('jest CommonJS', () => {
2399
2403
} )
2400
2404
} )
2401
2405
} )
2406
+
2407
+ context ( 'dynamic instrumentation' , ( ) => {
2408
+ it ( 'does not activate dynamic instrumentation if DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED is not set' , ( done ) => {
2409
+ receiver . setSettings ( {
2410
+ itr_enabled : false ,
2411
+ code_coverage : false ,
2412
+ tests_skipping : false ,
2413
+ flaky_test_retries_enabled : true ,
2414
+ early_flake_detection : {
2415
+ enabled : false
2416
+ }
2417
+ // di_enabled: true // TODO
2418
+ } )
2419
+ const eventsPromise = receiver
2420
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
2421
+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
2422
+
2423
+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
2424
+ const retriedTests = tests . filter ( test => test . meta [ TEST_IS_RETRY ] === 'true' )
2425
+
2426
+ assert . equal ( retriedTests . length , 1 )
2427
+ const [ retriedTest ] = retriedTests
2428
+
2429
+ assert . notProperty ( retriedTest . meta , DI_ERROR_DEBUG_INFO_CAPTURED )
2430
+ assert . notProperty ( retriedTest . meta , DI_DEBUG_ERROR_FILE )
2431
+ assert . notProperty ( retriedTest . metrics , DI_DEBUG_ERROR_LINE )
2432
+ assert . notProperty ( retriedTest . meta , DI_DEBUG_ERROR_SNAPSHOT_ID )
2433
+ } )
2434
+ const logsPromise = receiver
2435
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/logs' ) , ( payloads ) => {
2436
+ if ( payloads . length > 0 ) {
2437
+ throw new Error ( 'Unexpected logs' )
2438
+ }
2439
+ } , 5000 )
2440
+
2441
+ childProcess = exec ( runTestsWithCoverageCommand ,
2442
+ {
2443
+ cwd,
2444
+ env : {
2445
+ ...getCiVisAgentlessConfig ( receiver . port ) ,
2446
+ TESTS_TO_RUN : 'dynamic-instrumentation/test-hit-breakpoint'
2447
+ } ,
2448
+ stdio : 'inherit'
2449
+ }
2450
+ )
2451
+
2452
+ childProcess . on ( 'exit' , ( code ) => {
2453
+ Promise . all ( [ eventsPromise , logsPromise ] ) . then ( ( ) => {
2454
+ assert . equal ( code , 0 )
2455
+ done ( )
2456
+ } ) . catch ( done )
2457
+ } )
2458
+ } )
2459
+
2460
+ it ( 'runs retries with dynamic instrumentation' , ( done ) => {
2461
+ receiver . setSettings ( {
2462
+ itr_enabled : false ,
2463
+ code_coverage : false ,
2464
+ tests_skipping : false ,
2465
+ flaky_test_retries_enabled : true ,
2466
+ early_flake_detection : {
2467
+ enabled : false
2468
+ }
2469
+ // di_enabled: true // TODO
2470
+ } )
2471
+ let snapshotIdByTest , snapshotIdByLog
2472
+ let spanIdByTest , spanIdByLog , traceIdByTest , traceIdByLog
2473
+ const eventsPromise = receiver
2474
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
2475
+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
2476
+
2477
+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
2478
+ const retriedTests = tests . filter ( test => test . meta [ TEST_IS_RETRY ] === 'true' )
2479
+
2480
+ assert . equal ( retriedTests . length , 1 )
2481
+ const [ retriedTest ] = retriedTests
2482
+
2483
+ assert . propertyVal ( retriedTest . meta , DI_ERROR_DEBUG_INFO_CAPTURED , 'true' )
2484
+ assert . propertyVal (
2485
+ retriedTest . meta ,
2486
+ DI_DEBUG_ERROR_FILE ,
2487
+ 'ci-visibility/dynamic-instrumentation/dependency.js'
2488
+ )
2489
+ assert . equal ( retriedTest . metrics [ DI_DEBUG_ERROR_LINE ] , 4 )
2490
+ assert . exists ( retriedTest . meta [ DI_DEBUG_ERROR_SNAPSHOT_ID ] )
2491
+
2492
+ snapshotIdByTest = retriedTest . meta [ DI_DEBUG_ERROR_SNAPSHOT_ID ]
2493
+ spanIdByTest = retriedTest . span_id . toString ( )
2494
+ traceIdByTest = retriedTest . trace_id . toString ( )
2495
+
2496
+ const notRetriedTest = tests . find ( test => test . meta [ TEST_NAME ] . includes ( 'is not retried' ) )
2497
+
2498
+ assert . notProperty ( notRetriedTest . meta , DI_ERROR_DEBUG_INFO_CAPTURED )
2499
+ } )
2500
+
2501
+ const logsPromise = receiver
2502
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/logs' ) , ( payloads ) => {
2503
+ const [ { logMessage : [ diLog ] } ] = payloads
2504
+ assert . deepInclude ( diLog , {
2505
+ ddsource : 'dd_debugger' ,
2506
+ level : 'error'
2507
+ } )
2508
+ assert . equal ( diLog . debugger . snapshot . language , 'javascript' )
2509
+ assert . deepInclude ( diLog . debugger . snapshot . captures . lines [ '4' ] . locals , {
2510
+ a : {
2511
+ type : 'number' ,
2512
+ value : '11'
2513
+ } ,
2514
+ b : {
2515
+ type : 'number' ,
2516
+ value : '3'
2517
+ } ,
2518
+ localVariable : {
2519
+ type : 'number' ,
2520
+ value : '2'
2521
+ }
2522
+ } )
2523
+ spanIdByLog = diLog . dd . span_id
2524
+ traceIdByLog = diLog . dd . trace_id
2525
+ snapshotIdByLog = diLog . debugger . snapshot . id
2526
+ } )
2527
+
2528
+ childProcess = exec ( runTestsWithCoverageCommand ,
2529
+ {
2530
+ cwd,
2531
+ env : {
2532
+ ...getCiVisAgentlessConfig ( receiver . port ) ,
2533
+ TESTS_TO_RUN : 'dynamic-instrumentation/test-hit-breakpoint' ,
2534
+ DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED : 'true'
2535
+ } ,
2536
+ stdio : 'inherit'
2537
+ }
2538
+ )
2539
+
2540
+ childProcess . on ( 'exit' , ( ) => {
2541
+ Promise . all ( [ eventsPromise , logsPromise ] ) . then ( ( ) => {
2542
+ assert . equal ( snapshotIdByTest , snapshotIdByLog )
2543
+ assert . equal ( spanIdByTest , spanIdByLog )
2544
+ assert . equal ( traceIdByTest , traceIdByLog )
2545
+ done ( )
2546
+ } ) . catch ( done )
2547
+ } )
2548
+ } )
2549
+
2550
+ it ( 'does not crash if the retry does not hit the breakpoint' , ( done ) => {
2551
+ receiver . setSettings ( {
2552
+ itr_enabled : false ,
2553
+ code_coverage : false ,
2554
+ tests_skipping : false ,
2555
+ flaky_test_retries_enabled : true ,
2556
+ early_flake_detection : {
2557
+ enabled : false
2558
+ }
2559
+ // di_enabled: true // TODO
2560
+ } )
2561
+ const eventsPromise = receiver
2562
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/citestcycle' ) , ( payloads ) => {
2563
+ const events = payloads . flatMap ( ( { payload } ) => payload . events )
2564
+
2565
+ const tests = events . filter ( event => event . type === 'test' ) . map ( event => event . content )
2566
+ const retriedTests = tests . filter ( test => test . meta [ TEST_IS_RETRY ] === 'true' )
2567
+
2568
+ assert . equal ( retriedTests . length , 1 )
2569
+ const [ retriedTest ] = retriedTests
2570
+
2571
+ assert . propertyVal ( retriedTest . meta , DI_ERROR_DEBUG_INFO_CAPTURED , 'true' )
2572
+ assert . propertyVal (
2573
+ retriedTest . meta ,
2574
+ DI_DEBUG_ERROR_FILE ,
2575
+ 'ci-visibility/dynamic-instrumentation/dependency.js'
2576
+ )
2577
+ assert . equal ( retriedTest . metrics [ DI_DEBUG_ERROR_LINE ] , 4 )
2578
+ assert . exists ( retriedTest . meta [ DI_DEBUG_ERROR_SNAPSHOT_ID ] )
2579
+ } )
2580
+ const logsPromise = receiver
2581
+ . gatherPayloadsMaxTimeout ( ( { url } ) => url . endsWith ( '/api/v2/logs' ) , ( payloads ) => {
2582
+ if ( payloads . length > 0 ) {
2583
+ throw new Error ( 'Unexpected logs' )
2584
+ }
2585
+ } , 5000 )
2586
+
2587
+ childProcess = exec ( runTestsWithCoverageCommand ,
2588
+ {
2589
+ cwd,
2590
+ env : {
2591
+ ...getCiVisAgentlessConfig ( receiver . port ) ,
2592
+ TESTS_TO_RUN : 'dynamic-instrumentation/test-not-hit-breakpoint' ,
2593
+ DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED : 'true'
2594
+ } ,
2595
+ stdio : 'inherit'
2596
+ }
2597
+ )
2598
+
2599
+ childProcess . on ( 'exit' , ( code ) => {
2600
+ Promise . all ( [ eventsPromise , logsPromise ] ) . then ( ( ) => {
2601
+ assert . equal ( code , 0 )
2602
+ done ( )
2603
+ } ) . catch ( done )
2604
+ } )
2605
+ } )
2606
+ } )
2402
2607
} )
0 commit comments