tenseleyflow/bencch / 9367222

Browse files

Tighten failure-path reporting

Authored by espadonne
SHA
9367222320a41059181e6e1661462f31df41bd58
Parents
4d8d871
Tree
81fce23

1 changed file

StatusFile+-
M bench/src/lib.rs 146 9
bench/src/lib.rsmodified
@@ -1403,15 +1403,7 @@ fn execute_case_cell(
14031403
             }
14041404
         }
14051405
         (None, Some(failure)) => {
1406
-            let partial = failure.partial_result();
1407
-            let mut execution = evaluate_positive_expectations(case, &partial);
1408
-            if execution.is_ok() {
1409
-                if has_failure_expectation(case) {
1410
-                    execution = evaluate_failure_expectations(case, failure);
1411
-                } else {
1412
-                    execution = Err(compose_armfortas_failure_detail(&artifacts));
1413
-                }
1414
-            }
1406
+            let mut execution = evaluate_failed_armfortas(case, &artifacts, failure);
14151407
             if execution.is_ok() && !artifacts.references.is_empty() {
14161408
                 execution =
14171409
                     Err("differential comparison requires a successful armfortas run".to_string());
@@ -1748,6 +1740,25 @@ fn evaluate_failure_expectations(case: &CaseSpec, failure: &CaptureFailure) -> R
17481740
     Ok(())
17491741
 }
17501742
 
1743
+fn evaluate_failed_armfortas(
1744
+    case: &CaseSpec,
1745
+    artifacts: &ExecutionArtifacts,
1746
+    failure: &CaptureFailure,
1747
+) -> Result<(), String> {
1748
+    if has_failure_expectation(case) {
1749
+        evaluate_failure_expectations(case, failure)
1750
+    } else {
1751
+        let partial = failure.partial_result();
1752
+        match evaluate_positive_expectations(case, &partial) {
1753
+            Ok(()) => Err(compose_armfortas_failure_detail(artifacts)),
1754
+            Err(detail) if is_missing_stage_detail(&detail) => {
1755
+                Err(compose_armfortas_failure_detail(artifacts))
1756
+            }
1757
+            Err(detail) => Err(detail),
1758
+        }
1759
+    }
1760
+}
1761
+
17511762
 fn has_failure_expectation(case: &CaseSpec) -> bool {
17521763
     case.expectations.iter().any(|expectation| {
17531764
         matches!(
@@ -1777,6 +1788,10 @@ fn expected_failure_description(case: &CaseSpec) -> String {
17771788
     }
17781789
 }
17791790
 
1791
+fn is_missing_stage_detail(detail: &str) -> bool {
1792
+    detail.starts_with("missing captured stage '") || detail == "missing captured run stage"
1793
+}
1794
+
17801795
 fn target_text<'a>(result: &'a CaptureResult, target: &Target) -> Result<&'a str, String> {
17811796
     match target {
17821797
         Target::Stage(stage) => match result.get(*stage) {
@@ -5721,4 +5736,126 @@ end
57215736
             errors
57225737
         );
57235738
     }
5739
+
5740
+    #[test]
5741
+    fn failure_expectation_precedes_partial_stage_checks() {
5742
+        let case = CaseSpec {
5743
+            name: "missing_then".into(),
5744
+            source: PathBuf::from("demo.f90"),
5745
+            graph_files: Vec::new(),
5746
+            requested: BTreeSet::from([Stage::Tokens, Stage::Run]),
5747
+            opt_levels: vec![OptLevel::O0],
5748
+            repeat_count: 3,
5749
+            reference_compilers: Vec::new(),
5750
+            consistency_checks: Vec::new(),
5751
+            expectations: vec![
5752
+                Expectation::Contains {
5753
+                    target: Target::RunStdout,
5754
+                    needle: "42".into(),
5755
+                },
5756
+                Expectation::FailContains {
5757
+                    stage: FailureStage::Parser,
5758
+                    needle: "expected 'then'".into(),
5759
+                },
5760
+            ],
5761
+            status_rules: Vec::new(),
5762
+        };
5763
+        let artifacts = ExecutionArtifacts {
5764
+            requested: BTreeSet::from([Stage::Tokens, Stage::Run]),
5765
+            armfortas: None,
5766
+            armfortas_failure: None,
5767
+            references: Vec::new(),
5768
+            consistency_issues: Vec::new(),
5769
+        };
5770
+        let failure = CaptureFailure {
5771
+            input: PathBuf::from("demo.f90"),
5772
+            opt_level: OptLevel::O0,
5773
+            stage: FailureStage::Parser,
5774
+            detail: "expected 'then'".into(),
5775
+            stages: BTreeMap::from([(
5776
+                Stage::Tokens,
5777
+                CapturedStage::Text("if\n".into()),
5778
+            )]),
5779
+        };
5780
+
5781
+        assert!(evaluate_failed_armfortas(&case, &artifacts, &failure).is_ok());
5782
+    }
5783
+
5784
+    #[test]
5785
+    fn unexpected_capture_failure_reports_compiler_failure_detail() {
5786
+        let case = CaseSpec {
5787
+            name: "module_procedure_runtime".into(),
5788
+            source: PathBuf::from("graph.f90"),
5789
+            graph_files: Vec::new(),
5790
+            requested: BTreeSet::from([Stage::Run]),
5791
+            opt_levels: vec![OptLevel::O0],
5792
+            repeat_count: 3,
5793
+            reference_compilers: Vec::new(),
5794
+            consistency_checks: Vec::new(),
5795
+            expectations: vec![Expectation::Contains {
5796
+                target: Target::RunStdout,
5797
+                needle: "42".into(),
5798
+            }],
5799
+            status_rules: Vec::new(),
5800
+        };
5801
+        let failure = CaptureFailure {
5802
+            input: PathBuf::from("graph.f90"),
5803
+            opt_level: OptLevel::O0,
5804
+            stage: FailureStage::Run,
5805
+            detail: "Undefined symbols for architecture arm64:\n  \"_add_one\"".into(),
5806
+            stages: BTreeMap::new(),
5807
+        };
5808
+        let artifacts = ExecutionArtifacts {
5809
+            requested: BTreeSet::from([Stage::Run]),
5810
+            armfortas: None,
5811
+            armfortas_failure: Some(failure.clone()),
5812
+            references: Vec::new(),
5813
+            consistency_issues: Vec::new(),
5814
+        };
5815
+
5816
+        let err = evaluate_failed_armfortas(&case, &artifacts, &failure).unwrap_err();
5817
+        assert!(err.contains("armfortas failed in run"));
5818
+        assert!(err.contains("_add_one"));
5819
+        assert!(!err.contains("missing captured run stage"));
5820
+    }
5821
+
5822
+    #[test]
5823
+    fn partial_stage_expectation_failure_is_preserved_on_capture_failure() {
5824
+        let case = CaseSpec {
5825
+            name: "module_procedure_backend".into(),
5826
+            source: PathBuf::from("graph.f90"),
5827
+            graph_files: Vec::new(),
5828
+            requested: BTreeSet::from([Stage::Asm, Stage::Obj, Stage::Run]),
5829
+            opt_levels: vec![OptLevel::O0],
5830
+            repeat_count: 3,
5831
+            reference_compilers: Vec::new(),
5832
+            consistency_checks: Vec::new(),
5833
+            expectations: vec![Expectation::Contains {
5834
+                target: Target::Stage(Stage::Asm),
5835
+                needle: ".globl _add_one".into(),
5836
+            }],
5837
+            status_rules: Vec::new(),
5838
+        };
5839
+        let failure = CaptureFailure {
5840
+            input: PathBuf::from("graph.f90"),
5841
+            opt_level: OptLevel::O0,
5842
+            stage: FailureStage::Run,
5843
+            detail: "Undefined symbols for architecture arm64:\n  \"_add_one\"".into(),
5844
+            stages: BTreeMap::from([(
5845
+                Stage::Asm,
5846
+                CapturedStage::Text(".globl _main\n".into()),
5847
+            )]),
5848
+        };
5849
+        let artifacts = ExecutionArtifacts {
5850
+            requested: BTreeSet::from([Stage::Asm, Stage::Obj, Stage::Run]),
5851
+            armfortas: None,
5852
+            armfortas_failure: Some(failure.clone()),
5853
+            references: Vec::new(),
5854
+            consistency_issues: Vec::new(),
5855
+        };
5856
+
5857
+        let err = evaluate_failed_armfortas(&case, &artifacts, &failure).unwrap_err();
5858
+        assert!(err.contains("expected asm to contain"));
5859
+        assert!(!err.contains("armfortas failed in run"));
5860
+    }
57245861
 }