Rust · 3212 bytes Raw Blame History
1 use std::collections::BTreeSet;
2 use std::path::PathBuf;
3
4 use armfortas::driver::OptLevel;
5 use armfortas::testing::{capture_from_path, CaptureRequest, CapturedStage, RunCapture, Stage};
6
7 fn fixture(name: &str) -> PathBuf {
8 let path = PathBuf::from("test_programs").join(name);
9 assert!(path.exists(), "missing test fixture {}", path.display());
10 path
11 }
12
13 fn capture_text(request: CaptureRequest, stage: Stage) -> String {
14 let result = capture_from_path(&request).expect("capture should succeed");
15 match result.get(stage) {
16 Some(CapturedStage::Text(text)) => text.clone(),
17 Some(CapturedStage::Run(_)) => panic!("expected text stage for {}", stage.as_str()),
18 None => panic!("missing requested stage {}", stage.as_str()),
19 }
20 }
21
22 fn capture_run(request: CaptureRequest) -> RunCapture {
23 let result = capture_from_path(&request).expect("capture should succeed");
24 match result.get(Stage::Run) {
25 Some(CapturedStage::Run(run)) => run.clone(),
26 Some(CapturedStage::Text(_)) => panic!("expected run stage"),
27 None => panic!("missing requested stage {}", Stage::Run.as_str()),
28 }
29 }
30
31 fn main_section<'a>(asm: &'a str) -> &'a str {
32 let start = asm
33 .find("\n_main:\n")
34 .unwrap_or_else(|| panic!("missing _main section:\n{}", asm));
35 &asm[start..]
36 }
37
38 #[test]
39 fn capture_main_wrapper_calls_program_body_not_first_helper() {
40 let asm = capture_text(
41 CaptureRequest {
42 input: fixture("program_entry_helper.f90"),
43 requested: BTreeSet::from([Stage::Asm]),
44 opt_level: OptLevel::O0,
45 },
46 Stage::Asm,
47 );
48
49 let main = main_section(&asm);
50 assert!(
51 main.contains("bl ___prog_program_entry_helper"),
52 "_main should call the lowered program body:\n{}",
53 main
54 );
55 assert!(
56 !main.contains("bl _set_value"),
57 "_main should not jump directly to the first helper procedure:\n{}",
58 main
59 );
60 }
61
62 #[test]
63 fn capture_program_entry_fixture_runs_at_o2() {
64 let run = capture_run(CaptureRequest {
65 input: fixture("program_entry_helper.f90"),
66 requested: BTreeSet::from([Stage::Run]),
67 opt_level: OptLevel::O2,
68 });
69
70 assert_eq!(
71 run.exit_code, 0,
72 "program should run successfully:\n{run:#?}"
73 );
74 assert!(
75 run.stdout.split_whitespace().any(|field| field == "99"),
76 "program body should execute and print the helper-written value:\n{}",
77 run.stdout
78 );
79 }
80
81 #[test]
82 fn capture_program_entry_object_snapshot_is_deterministic_at_o2() {
83 let source = fixture("program_entry_helper.f90");
84 let first = capture_text(
85 CaptureRequest {
86 input: source.clone(),
87 requested: BTreeSet::from([Stage::Obj]),
88 opt_level: OptLevel::O2,
89 },
90 Stage::Obj,
91 );
92 let second = capture_text(
93 CaptureRequest {
94 input: source,
95 requested: BTreeSet::from([Stage::Obj]),
96 opt_level: OptLevel::O2,
97 },
98 Stage::Obj,
99 );
100
101 assert_eq!(
102 first, second,
103 "object snapshot should stay deterministic for helper-before-program entry wiring"
104 );
105 }
106