259 lines
8.9 KiB
Rust
259 lines
8.9 KiB
Rust
use std::{fs, path::Path, process::Command};
|
|
|
|
#[test]
|
|
fn struct_fixture_emits_llvm_field_read_shape() {
|
|
let output = run_glagol(["../examples/struct.slo"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"compiler rejected struct fixture\nstdout:\n{}\nstderr:\n{}",
|
|
stdout,
|
|
stderr
|
|
);
|
|
assert!(
|
|
stdout.contains("define i32 @point_sum()")
|
|
&& stdout.contains("insertvalue { i32, i32 }")
|
|
&& stdout.contains("extractvalue { i32, i32 }")
|
|
&& stdout.contains("define i32 @main()"),
|
|
"LLVM output did not contain expected struct field-read shape\nstdout:\n{}",
|
|
stdout
|
|
);
|
|
assert!(
|
|
!stdout.contains("struct field access"),
|
|
"compiler emitted test metadata into LLVM output\nstdout:\n{}",
|
|
stdout
|
|
);
|
|
assert!(
|
|
!stdout.contains("type {"),
|
|
"first-pass struct fixture should not emit aggregate layout promises\nstdout:\n{}",
|
|
stdout
|
|
);
|
|
assert!(stderr.is_empty(), "compiler wrote stderr:\n{}", stderr);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_value_flow_fixture_emits_llvm_aggregate_shape() {
|
|
let output = run_glagol(["../examples/struct-value-flow.slo"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"compiler rejected struct value-flow fixture\nstdout:\n{}\nstderr:\n{}",
|
|
stdout,
|
|
stderr
|
|
);
|
|
assert!(
|
|
stdout.contains("define { i32, i32 } @make_point(i32 %x, i32 %y)")
|
|
&& stdout.contains("define i32 @point_x({ i32, i32 } %p)")
|
|
&& stdout.contains("define i32 @point_sum({ i32, i32 } %p)")
|
|
&& stdout.contains("alloca { i32, i32 }")
|
|
&& stdout.contains("call i32 @point_sum({ i32, i32 }"),
|
|
"LLVM output did not contain expected struct value-flow shape\nstdout:\n{}",
|
|
stdout
|
|
);
|
|
assert!(
|
|
!stdout.contains("type {"),
|
|
"struct value-flow fixture should not emit named layout promises\nstdout:\n{}",
|
|
stdout
|
|
);
|
|
assert!(stderr.is_empty(), "compiler wrote stderr:\n{}", stderr);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_fixture_runs_top_level_tests() {
|
|
let output = run_glagol(["--run-tests", "../examples/struct.slo"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"test runner rejected struct fixture\nstdout:\n{}\nstderr:\n{}",
|
|
stdout,
|
|
stderr
|
|
);
|
|
assert_eq!(
|
|
stdout,
|
|
concat!(
|
|
"test \"struct field access\" ... ok\n",
|
|
"test \"struct field compares\" ... ok\n",
|
|
"2 test(s) passed\n",
|
|
),
|
|
"test runner output drifted"
|
|
);
|
|
assert!(stderr.is_empty(), "test runner wrote stderr:\n{}", stderr);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_value_flow_fixture_runs_top_level_tests() {
|
|
let output = run_glagol(["--run-tests", "../examples/struct-value-flow.slo"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"test runner rejected struct value-flow fixture\nstdout:\n{}\nstderr:\n{}",
|
|
stdout,
|
|
stderr
|
|
);
|
|
assert_eq!(
|
|
stdout,
|
|
concat!(
|
|
"test \"struct local value flow\" ... ok\n",
|
|
"test \"struct parameter value flow\" ... ok\n",
|
|
"test \"stored struct field access\" ... ok\n",
|
|
"3 test(s) passed\n",
|
|
),
|
|
"test runner output drifted"
|
|
);
|
|
assert!(stderr.is_empty(), "test runner wrote stderr:\n{}", stderr);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_fixture_is_formatter_stable() {
|
|
let expected = fs::read_to_string("../tests/struct.slo").expect("read fixture");
|
|
let output = run_glagol(["--format", "../tests/struct.slo"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"formatter rejected struct fixture\nstdout:\n{}\nstderr:\n{}",
|
|
stdout,
|
|
stderr
|
|
);
|
|
assert_eq!(stdout, expected, "formatter output drifted");
|
|
assert!(stderr.is_empty(), "formatter wrote stderr:\n{}", stderr);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_value_flow_fixture_is_formatter_stable() {
|
|
let expected = fs::read_to_string("../tests/struct-value-flow.slo").expect("read fixture");
|
|
let output = run_glagol(["--format", "../tests/struct-value-flow.slo"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
assert!(
|
|
output.status.success(),
|
|
"formatter rejected struct value-flow fixture\nstdout:\n{}\nstderr:\n{}",
|
|
stdout,
|
|
stderr
|
|
);
|
|
assert_eq!(stdout, expected, "formatter output drifted");
|
|
assert!(stderr.is_empty(), "formatter wrote stderr:\n{}", stderr);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_fixture_prints_lowered_shape() {
|
|
let surface = run_glagol(["--inspect-lowering=surface", "../examples/struct.slo"]);
|
|
let surface_stdout = String::from_utf8_lossy(&surface.stdout);
|
|
let surface_stderr = String::from_utf8_lossy(&surface.stderr);
|
|
assert!(
|
|
surface.status.success(),
|
|
"surface lowering rejected struct fixture\nstdout:\n{}\nstderr:\n{}",
|
|
surface_stdout,
|
|
surface_stderr
|
|
);
|
|
assert!(
|
|
surface_stdout.contains("struct Point")
|
|
&& surface_stdout.contains("construct Point")
|
|
&& surface_stdout.contains("field-access x")
|
|
&& surface_stdout.contains("field-access y"),
|
|
"surface lowering output lost struct shape\nstdout:\n{}",
|
|
surface_stdout
|
|
);
|
|
assert!(
|
|
surface_stderr.is_empty(),
|
|
"surface lowering wrote stderr:\n{}",
|
|
surface_stderr
|
|
);
|
|
|
|
let checked = run_glagol(["--inspect-lowering=checked", "../examples/struct.slo"]);
|
|
let checked_stdout = String::from_utf8_lossy(&checked.stdout);
|
|
let checked_stderr = String::from_utf8_lossy(&checked.stderr);
|
|
assert!(
|
|
checked.status.success(),
|
|
"checked lowering rejected struct fixture\nstdout:\n{}\nstderr:\n{}",
|
|
checked_stdout,
|
|
checked_stderr
|
|
);
|
|
assert!(
|
|
checked_stdout.contains("struct Point")
|
|
&& checked_stdout.contains("construct Point : Point")
|
|
&& checked_stdout.contains("field-access x : i32")
|
|
&& checked_stdout.contains("field-access y : i32"),
|
|
"checked lowering output lost typed struct shape\nstdout:\n{}",
|
|
checked_stdout
|
|
);
|
|
assert!(
|
|
checked_stderr.is_empty(),
|
|
"checked lowering wrote stderr:\n{}",
|
|
checked_stderr
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn struct_value_flow_fixture_prints_lowered_shape() {
|
|
let surface = run_glagol([
|
|
"--inspect-lowering=surface",
|
|
"../examples/struct-value-flow.slo",
|
|
]);
|
|
let surface_stdout = String::from_utf8_lossy(&surface.stdout);
|
|
let surface_stderr = String::from_utf8_lossy(&surface.stderr);
|
|
assert!(
|
|
surface.status.success(),
|
|
"surface lowering rejected struct value-flow fixture\nstdout:\n{}\nstderr:\n{}",
|
|
surface_stdout,
|
|
surface_stderr
|
|
);
|
|
assert!(
|
|
surface_stdout.contains("fn make_point(x: i32, y: i32) -> Point")
|
|
&& surface_stdout.contains("fn point_x(p: Point) -> i32")
|
|
&& surface_stdout.contains("local let p: Point")
|
|
&& surface_stdout.contains("field-access y"),
|
|
"surface lowering output lost struct value-flow shape\nstdout:\n{}",
|
|
surface_stdout
|
|
);
|
|
assert!(
|
|
surface_stderr.is_empty(),
|
|
"surface lowering wrote stderr:\n{}",
|
|
surface_stderr
|
|
);
|
|
|
|
let checked = run_glagol([
|
|
"--inspect-lowering=checked",
|
|
"../examples/struct-value-flow.slo",
|
|
]);
|
|
let checked_stdout = String::from_utf8_lossy(&checked.stdout);
|
|
let checked_stderr = String::from_utf8_lossy(&checked.stderr);
|
|
assert!(
|
|
checked.status.success(),
|
|
"checked lowering rejected struct value-flow fixture\nstdout:\n{}\nstderr:\n{}",
|
|
checked_stdout,
|
|
checked_stderr
|
|
);
|
|
assert!(
|
|
checked_stdout.contains("fn make_point(x: i32, y: i32) -> Point")
|
|
&& checked_stdout.contains("fn point_x(p: Point) -> i32")
|
|
&& checked_stdout.contains("call make_point : Point")
|
|
&& checked_stdout.contains("var p : Point"),
|
|
"checked lowering output lost typed struct value-flow shape\nstdout:\n{}",
|
|
checked_stdout
|
|
);
|
|
assert!(
|
|
checked_stderr.is_empty(),
|
|
"checked lowering wrote stderr:\n{}",
|
|
checked_stderr
|
|
);
|
|
}
|
|
|
|
fn run_glagol<const N: usize>(args: [&str; N]) -> std::process::Output {
|
|
Command::new(env!("CARGO_BIN_EXE_glagol"))
|
|
.args(args)
|
|
.current_dir(Path::new(env!("CARGO_MANIFEST_DIR")))
|
|
.output()
|
|
.expect("run glagol")
|
|
}
|