11use std:: { env, fs, io:: BufReader , path:: Path , thread} ;
22
33use assert_matches:: assert_matches;
4- use bundle:: { BundleMeta , FileSetType } ;
4+ use axum:: { extract:: State , Json } ;
5+ use bundle:: { BundleMeta , FileSetType , Test } ;
56use constants:: {
67 TRUNK_ALLOW_EMPTY_TEST_RESULTS_ENV , TRUNK_API_TOKEN_ENV , TRUNK_CODEOWNERS_PATH_ENV ,
78 TRUNK_DISABLE_QUARANTINING_ENV , TRUNK_DRY_RUN_ENV , TRUNK_ORG_URL_SLUG_ENV ,
@@ -18,7 +19,7 @@ use serial_test::serial;
1819use tempfile:: tempdir;
1920use test_report:: report:: { MutTestReport , Status } ;
2021use test_utils:: mock_git_repo:: setup_repo_with_commit;
21- use test_utils:: mock_server:: { MockServerBuilder , RequestPayload } ;
22+ use test_utils:: mock_server:: { MockServerBuilder , RequestPayload , SharedMockServerState } ;
2223
2324pub fn generate_mock_codeowners < T : AsRef < Path > > ( directory : T ) {
2425 const CODEOWNERS : & str = r#"
@@ -472,3 +473,166 @@ async fn test_variant_priority_constructor_over_env() {
472473 // Restore original directory
473474 let _ = env:: set_current_dir ( original_dir) ;
474475}
476+
477+ #[ tokio:: test( flavor = "multi_thread" ) ]
478+ #[ serial]
479+ async fn test_variant_impacts_quarantining ( ) {
480+ cleanup_env_vars ( ) ;
481+ let temp_dir = tempdir ( ) . unwrap ( ) ;
482+ let repo_setup_res = setup_repo_with_commit ( & temp_dir) ;
483+ assert ! ( repo_setup_res. is_ok( ) ) ;
484+ let _ = env:: set_current_dir ( & temp_dir) ;
485+
486+ // Test parameters that will be used for quarantine checking
487+ let test_name = Some ( "test_name" . to_string ( ) ) ;
488+ let test_parent_name = Some ( "test_parent" . to_string ( ) ) ;
489+ let test_classname = Some ( "TestClass" . to_string ( ) ) ;
490+ let test_file = Some ( "test_file.rs" . to_string ( ) ) ;
491+
492+ let repo = RepoUrlParts {
493+ host : "github.com" . into ( ) ,
494+ owner : "trunk-io" . into ( ) ,
495+ name : "analytics-cli" . into ( ) ,
496+ } ;
497+
498+ // Generate the expected test ID with variant1
499+ let expected_test_id_variant1 = Test :: new (
500+ None ,
501+ test_name. clone ( ) . unwrap_or_default ( ) ,
502+ test_parent_name. clone ( ) . unwrap_or_default ( ) ,
503+ test_classname. clone ( ) ,
504+ test_file. clone ( ) ,
505+ "test-org" . to_string ( ) ,
506+ & repo,
507+ None ,
508+ "variant1" . to_string ( ) ,
509+ )
510+ . id ;
511+
512+ // Generate the expected test ID with variant2
513+ let expected_test_id_variant2 = Test :: new (
514+ None ,
515+ test_name. clone ( ) . unwrap_or_default ( ) ,
516+ test_parent_name. clone ( ) . unwrap_or_default ( ) ,
517+ test_classname. clone ( ) ,
518+ test_file. clone ( ) ,
519+ "test-org" . to_string ( ) ,
520+ & repo,
521+ None ,
522+ "variant2" . to_string ( ) ,
523+ )
524+ . id ;
525+
526+ // Verify they're different
527+ assert_ne ! ( expected_test_id_variant1, expected_test_id_variant2) ;
528+
529+ // Create a custom mock server handler that returns a quarantined test with the variant1 ID
530+ use api:: message:: { ListQuarantinedTestsResponse , Page , QuarantineSetting , QuarantinedTest } ;
531+ let state = {
532+ let mut builder = MockServerBuilder :: new ( ) ;
533+ let expected_id_v1 = expected_test_id_variant1. clone ( ) ;
534+ let test_name_clone = test_name. clone ( ) ;
535+ let test_parent_name_clone = test_parent_name. clone ( ) ;
536+ let test_classname_clone = test_classname. clone ( ) ;
537+ let test_file_clone = test_file. clone ( ) ;
538+ builder. list_quarantined_tests_handler (
539+ move |_state : State < SharedMockServerState > ,
540+ _req : Json < api:: message:: ListQuarantinedTestsRequest > | async move {
541+ Json ( ListQuarantinedTestsResponse {
542+ quarantined_tests : vec ! [ QuarantinedTest {
543+ test_case_id: expected_id_v1. clone( ) ,
544+ name: test_name_clone. clone( ) . unwrap_or_default( ) ,
545+ parent: Some ( test_parent_name_clone. clone( ) . unwrap_or_default( ) ) ,
546+ classname: test_classname_clone. clone( ) ,
547+ file: test_file_clone. clone( ) ,
548+ status: "failure" . to_string( ) ,
549+ quarantine_setting: QuarantineSetting :: AlwaysQuarantine ,
550+ } ] ,
551+ page : Page {
552+ total_rows : 1 ,
553+ total_pages : 1 ,
554+ next_page_token : "" . to_string ( ) ,
555+ prev_page_token : "" . to_string ( ) ,
556+ last_page_token : "" . to_string ( ) ,
557+ page_index : 0 ,
558+ } ,
559+ } )
560+ } ,
561+ ) ;
562+ builder. spawn_mock_server ( ) . await
563+ } ;
564+
565+ env:: set_var ( TRUNK_PUBLIC_API_ADDRESS_ENV , & state. host ) ;
566+ env:: set_var ( TRUNK_API_TOKEN_ENV , "test-token" ) ;
567+ env:: set_var ( TRUNK_ORG_URL_SLUG_ENV , "test-org" ) ;
568+ env:: set_var ( TRUNK_USE_UNCLONED_REPO_ENV , "false" ) ;
569+
570+ // Test with variant1 - should find the quarantined test
571+ env:: set_var ( TRUNK_VARIANT_ENV , "variant1" ) ;
572+ let test_name_v1 = test_name. clone ( ) ;
573+ let test_parent_name_v1 = test_parent_name. clone ( ) ;
574+ let test_classname_v1 = test_classname. clone ( ) ;
575+ let test_file_v1 = test_file. clone ( ) ;
576+ let is_quarantined_v1 = thread:: spawn ( move || {
577+ let test_report_v1 = MutTestReport :: new ( "test" . into ( ) , "test-command" . into ( ) , None ) ;
578+ test_report_v1. is_quarantined (
579+ None ,
580+ test_name_v1,
581+ test_parent_name_v1,
582+ test_classname_v1,
583+ test_file_v1,
584+ )
585+ } )
586+ . join ( )
587+ . unwrap ( ) ;
588+ assert ! (
589+ is_quarantined_v1,
590+ "Test should be quarantined when variant matches"
591+ ) ;
592+
593+ // Test with variant2 - should NOT find the quarantined test (different variant)
594+ env:: set_var ( TRUNK_VARIANT_ENV , "variant2" ) ;
595+ let test_name_v2 = test_name. clone ( ) ;
596+ let test_parent_name_v2 = test_parent_name. clone ( ) ;
597+ let test_classname_v2 = test_classname. clone ( ) ;
598+ let test_file_v2 = test_file. clone ( ) ;
599+ let is_quarantined_v2 = thread:: spawn ( move || {
600+ let test_report_v2 = MutTestReport :: new ( "test" . into ( ) , "test-command" . into ( ) , None ) ;
601+ test_report_v2. is_quarantined (
602+ None ,
603+ test_name_v2,
604+ test_parent_name_v2,
605+ test_classname_v2,
606+ test_file_v2,
607+ )
608+ } )
609+ . join ( )
610+ . unwrap ( ) ;
611+ assert ! (
612+ !is_quarantined_v2,
613+ "Test should NOT be quarantined when variant doesn't match"
614+ ) ;
615+
616+ // Test with no variant - should NOT find the quarantined test
617+ env:: remove_var ( TRUNK_VARIANT_ENV ) ;
618+ let test_name_v3 = test_name. clone ( ) ;
619+ let test_parent_name_v3 = test_parent_name. clone ( ) ;
620+ let test_classname_v3 = test_classname. clone ( ) ;
621+ let test_file_v3 = test_file. clone ( ) ;
622+ let is_quarantined_v3 = thread:: spawn ( move || {
623+ let test_report_v3 = MutTestReport :: new ( "test" . into ( ) , "test-command" . into ( ) , None ) ;
624+ test_report_v3. is_quarantined (
625+ None ,
626+ test_name_v3,
627+ test_parent_name_v3,
628+ test_classname_v3,
629+ test_file_v3,
630+ )
631+ } )
632+ . join ( )
633+ . unwrap ( ) ;
634+ assert ! (
635+ !is_quarantined_v3,
636+ "Test should NOT be quarantined when variant is empty"
637+ ) ;
638+ }
0 commit comments