use std::{fs, path::Path, process::Command}; const LOWERING_FIXTURES: &[LoweringFixture] = &[ LoweringFixture { name: "add", source: "../examples/add.slo", surface_snapshot: "../tests/add.surface.lower", checked_snapshot: "../tests/add.checked.lower", }, LoweringFixture { name: "top-level-test", source: "../tests/top-level-test.slo", surface_snapshot: "../tests/top-level-test.surface.lower", checked_snapshot: "../tests/top-level-test.checked.lower", }, LoweringFixture { name: "comments", source: "../tests/comments.slo", surface_snapshot: "../tests/comments.surface.lower", checked_snapshot: "../tests/comments.checked.lower", }, LoweringFixture { name: "formatter-stability-v1", source: "../tests/formatter-stability-v1.fmt", surface_snapshot: "../tests/formatter-stability-v1.surface.lower", checked_snapshot: "../tests/formatter-stability-v1.checked.lower", }, LoweringFixture { name: "unsafe", source: "../tests/unsafe.slo", surface_snapshot: "../tests/unsafe.surface.lower", checked_snapshot: "../tests/unsafe.checked.lower", }, LoweringFixture { name: "local-variables", source: "../examples/local-variables.slo", surface_snapshot: "../tests/local-variables.surface.lower", checked_snapshot: "../tests/local-variables.checked.lower", }, LoweringFixture { name: "composite-locals", source: "../examples/composite-locals.slo", surface_snapshot: "../tests/composite-locals.surface.lower", checked_snapshot: "../tests/composite-locals.checked.lower", }, LoweringFixture { name: "composite-struct-fields", source: "../examples/composite-struct-fields.slo", surface_snapshot: "../tests/composite-struct-fields.surface.lower", checked_snapshot: "../tests/composite-struct-fields.checked.lower", }, LoweringFixture { name: "array-struct-fields", source: "../examples/array-struct-fields.slo", surface_snapshot: "../tests/array-struct-fields.surface.lower", checked_snapshot: "../tests/array-struct-fields.checked.lower", }, LoweringFixture { name: "array-struct-elements", source: "../examples/array-struct-elements.slo", surface_snapshot: "../tests/array-struct-elements.surface.lower", checked_snapshot: "../tests/array-struct-elements.checked.lower", }, LoweringFixture { name: "if", source: "../examples/if.slo", surface_snapshot: "../tests/if.surface.lower", checked_snapshot: "../tests/if.checked.lower", }, LoweringFixture { name: "while", source: "../examples/while.slo", surface_snapshot: "../tests/while.surface.lower", checked_snapshot: "../tests/while.checked.lower", }, LoweringFixture { name: "struct", source: "../examples/struct.slo", surface_snapshot: "../tests/struct.surface.lower", checked_snapshot: "../tests/struct.checked.lower", }, LoweringFixture { name: "struct-value-flow", source: "../examples/struct-value-flow.slo", surface_snapshot: "../tests/struct-value-flow.surface.lower", checked_snapshot: "../tests/struct-value-flow.checked.lower", }, LoweringFixture { name: "enum-struct-fields", source: "../examples/enum-struct-fields.slo", surface_snapshot: "../tests/enum-struct-fields.surface.lower", checked_snapshot: "../tests/enum-struct-fields.checked.lower", }, LoweringFixture { name: "enum-payload-direct-scalars", source: "../examples/enum-payload-direct-scalars.slo", surface_snapshot: "../tests/enum-payload-direct-scalars.surface.lower", checked_snapshot: "../tests/enum-payload-direct-scalars.checked.lower", }, LoweringFixture { name: "enum-payload-structs", source: "../examples/enum-payload-structs.slo", surface_snapshot: "../tests/enum-payload-structs.surface.lower", checked_snapshot: "../tests/enum-payload-structs.checked.lower", }, LoweringFixture { name: "primitive-struct-fields", source: "../examples/primitive-struct-fields.slo", surface_snapshot: "../tests/primitive-struct-fields.surface.lower", checked_snapshot: "../tests/primitive-struct-fields.checked.lower", }, LoweringFixture { name: "numeric-struct-fields", source: "../examples/numeric-struct-fields.slo", surface_snapshot: "../tests/numeric-struct-fields.surface.lower", checked_snapshot: "../tests/numeric-struct-fields.checked.lower", }, LoweringFixture { name: "array", source: "../examples/array.slo", surface_snapshot: "../tests/array.surface.lower", checked_snapshot: "../tests/array.checked.lower", }, LoweringFixture { name: "array-direct-scalars", source: "../examples/array-direct-scalars.slo", surface_snapshot: "../tests/array-direct-scalars.surface.lower", checked_snapshot: "../tests/array-direct-scalars.checked.lower", }, LoweringFixture { name: "array-direct-scalars-value-flow", source: "../examples/array-direct-scalars-value-flow.slo", surface_snapshot: "../tests/array-direct-scalars-value-flow.surface.lower", checked_snapshot: "../tests/array-direct-scalars-value-flow.checked.lower", }, LoweringFixture { name: "array-enum", source: "../examples/array-enum.slo", surface_snapshot: "../tests/array-enum.surface.lower", checked_snapshot: "../tests/array-enum.checked.lower", }, LoweringFixture { name: "array-string", source: "../examples/array-string.slo", surface_snapshot: "../tests/array-string.surface.lower", checked_snapshot: "../tests/array-string.checked.lower", }, LoweringFixture { name: "array-string-value-flow", source: "../examples/array-string-value-flow.slo", surface_snapshot: "../tests/array-string-value-flow.surface.lower", checked_snapshot: "../tests/array-string-value-flow.checked.lower", }, LoweringFixture { name: "array-value-flow", source: "../examples/array-value-flow.slo", surface_snapshot: "../tests/array-value-flow.surface.lower", checked_snapshot: "../tests/array-value-flow.checked.lower", }, LoweringFixture { name: "option-result", source: "../examples/option-result.slo", surface_snapshot: "../tests/option-result.surface.lower", checked_snapshot: "../tests/option-result.checked.lower", }, LoweringFixture { name: "option-result-flow", source: "../examples/option-result-flow.slo", surface_snapshot: "../tests/option-result-flow.surface.lower", checked_snapshot: "../tests/option-result-flow.checked.lower", }, LoweringFixture { name: "option-result-payload", source: "../examples/option-result-payload.slo", surface_snapshot: "../tests/option-result-payload.surface.lower", checked_snapshot: "../tests/option-result-payload.checked.lower", }, LoweringFixture { name: "option-result-match", source: "../examples/option-result-match.slo", surface_snapshot: "../tests/option-result-match.surface.lower", checked_snapshot: "../tests/option-result-match.checked.lower", }, LoweringFixture { name: "string-print", source: "../examples/string-print.slo", surface_snapshot: "../tests/string-print.surface.lower", checked_snapshot: "../tests/string-print.checked.lower", }, LoweringFixture { name: "string-value-flow", source: "../examples/string-value-flow.slo", surface_snapshot: "../tests/string-value-flow.surface.lower", checked_snapshot: "../tests/string-value-flow.checked.lower", }, LoweringFixture { name: "print-bool", source: "../examples/print-bool.slo", surface_snapshot: "../tests/print-bool.surface.lower", checked_snapshot: "../tests/print-bool.checked.lower", }, LoweringFixture { name: "random", source: "../examples/random.slo", surface_snapshot: "../tests/random.surface.lower", checked_snapshot: "../tests/random.checked.lower", }, LoweringFixture { name: "stdin-result", source: "../examples/stdin-result.slo", surface_snapshot: "../tests/stdin-result.surface.lower", checked_snapshot: "../tests/stdin-result.checked.lower", }, LoweringFixture { name: "string-parse-i32-result", source: "../examples/string-parse-i32-result.slo", surface_snapshot: "../tests/string-parse-i32-result.surface.lower", checked_snapshot: "../tests/string-parse-i32-result.checked.lower", }, LoweringFixture { name: "string-parse-i64-result", source: "../examples/string-parse-i64-result.slo", surface_snapshot: "../tests/string-parse-i64-result.surface.lower", checked_snapshot: "../tests/string-parse-i64-result.checked.lower", }, LoweringFixture { name: "string-parse-f64-result", source: "../examples/string-parse-f64-result.slo", surface_snapshot: "../tests/string-parse-f64-result.surface.lower", checked_snapshot: "../tests/string-parse-f64-result.checked.lower", }, LoweringFixture { name: "string-parse-bool-result", source: "../examples/string-parse-bool-result.slo", surface_snapshot: "../tests/string-parse-bool-result.surface.lower", checked_snapshot: "../tests/string-parse-bool-result.checked.lower", }, LoweringFixture { name: "result-helpers", source: "../examples/result-helpers.slo", surface_snapshot: "../tests/result-helpers.surface.lower", checked_snapshot: "../tests/result-helpers.checked.lower", }, LoweringFixture { name: "standard-runtime", source: "../examples/standard-runtime.slo", surface_snapshot: "../tests/standard-runtime.surface.lower", checked_snapshot: "../tests/standard-runtime.checked.lower", }, LoweringFixture { name: "owned-string-concat", source: "../examples/owned-string-concat.slo", surface_snapshot: "../tests/owned-string-concat.surface.lower", checked_snapshot: "../tests/owned-string-concat.checked.lower", }, LoweringFixture { name: "standard-io-host-env", source: "../tests/standard-io-host-env.slo", surface_snapshot: "../tests/standard-io-host-env.surface.lower", checked_snapshot: "../tests/standard-io-host-env.checked.lower", }, LoweringFixture { name: "host-io-result", source: "../tests/host-io-result.slo", surface_snapshot: "../tests/host-io-result.surface.lower", checked_snapshot: "../tests/host-io-result.checked.lower", }, LoweringFixture { name: "integer-to-string", source: "../examples/integer-to-string.slo", surface_snapshot: "../tests/integer-to-string.surface.lower", checked_snapshot: "../tests/integer-to-string.checked.lower", }, LoweringFixture { name: "f64-to-string", source: "../examples/f64-to-string.slo", surface_snapshot: "../tests/f64-to-string.surface.lower", checked_snapshot: "../tests/f64-to-string.checked.lower", }, LoweringFixture { name: "f64-to-i32-result", source: "../examples/f64-to-i32-result.slo", surface_snapshot: "../tests/f64-to-i32-result.surface.lower", checked_snapshot: "../tests/f64-to-i32-result.checked.lower", }, LoweringFixture { name: "f64-to-i64-result", source: "../examples/f64-to-i64-result.slo", surface_snapshot: "../tests/f64-to-i64-result.surface.lower", checked_snapshot: "../tests/f64-to-i64-result.checked.lower", }, LoweringFixture { name: "checked-i64-to-i32-conversion", source: "../examples/checked-i64-to-i32-conversion.slo", surface_snapshot: "../tests/checked-i64-to-i32-conversion.surface.lower", checked_snapshot: "../tests/checked-i64-to-i32-conversion.checked.lower", }, LoweringFixture { name: "vec-i32", source: "../examples/vec-i32.slo", surface_snapshot: "../tests/vec-i32.surface.lower", checked_snapshot: "../tests/vec-i32.checked.lower", }, ]; #[test] fn promoted_fixtures_print_expected_surface_ast() { for fixture in LOWERING_FIXTURES { assert_lowering_fixture(fixture, LoweringMode::Surface); } } #[test] fn promoted_fixtures_print_expected_checked_ast() { for fixture in LOWERING_FIXTURES { assert_lowering_fixture(fixture, LoweringMode::Checked); } } struct LoweringFixture { name: &'static str, source: &'static str, surface_snapshot: &'static str, checked_snapshot: &'static str, } #[derive(Clone, Copy)] enum LoweringMode { Surface, Checked, } impl LoweringMode { fn flag(self) -> &'static str { match self { LoweringMode::Surface => "--inspect-lowering=surface", LoweringMode::Checked => "--inspect-lowering=checked", } } fn snapshot(self, fixture: &LoweringFixture) -> &'static str { match self { LoweringMode::Surface => fixture.surface_snapshot, LoweringMode::Checked => fixture.checked_snapshot, } } } fn assert_lowering_fixture(fixture: &LoweringFixture, mode: LoweringMode) { let expected = fs::read_to_string(Path::new(env!("CARGO_MANIFEST_DIR")).join(mode.snapshot(fixture))) .expect("read lowering inspector fixture"); let output = run_lowering_inspector(mode.flag(), fixture.source); assert_success_output(output, expected, fixture.name, mode.flag()); } fn run_lowering_inspector(mode: &str, fixture: &str) -> std::process::Output { let compiler = env!("CARGO_BIN_EXE_glagol"); let fixture = Path::new(fixture); Command::new(compiler) .arg(mode) .arg(fixture) .current_dir(Path::new(env!("CARGO_MANIFEST_DIR"))) .output() .unwrap_or_else(|err| panic!("run glagol {} on fixture: {}", mode, err)) } fn assert_success_output(output: std::process::Output, expected: String, name: &str, mode: &str) { assert!( output.status.success(), "lowering inspector failed for `{}` `{}`\nstdout:\n{}\nstderr:\n{}", name, mode, String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr), ); let actual = String::from_utf8(output.stdout).expect("lowering inspector output is UTF-8"); assert_eq!( actual, expected, "lowering inspector fixture drifted for `{}` `{}`", name, mode ); assert!( output.stderr.is_empty(), "lowering inspector wrote stderr for `{}` `{}`:\n{}", name, mode, String::from_utf8_lossy(&output.stderr), ); }