use super::*;
#[test]
fn empty_file_generates_project() {
let project = codegen_ok("");
assert!(!project.cargo_toml.is_empty());
assert_eq!(project.files.len(), 1);
assert_eq!(project.files[0].0, "src/lib.rs");
assert!(
project.files[0]
.1
.contains("Generated by the Assura compiler")
);
}
#[test]
fn struct_codegen() {
let project = codegen_ok(
r#"
type Point {
x: Int
y: Int
}
"#,
);
let lib = &project.files[0].1;
assert!(lib.contains("struct Point"), "should contain struct Point");
assert!(lib.contains("i64"), "should map Int to i64");
}
#[test]
fn enum_codegen() {
let project = codegen_ok(
r#"
enum Color {
Red,
Green,
Blue
}
"#,
);
let lib = &project.files[0].1;
assert!(lib.contains("enum Color"), "should contain enum Color");
assert!(lib.contains("Red"), "should contain Red variant");
assert!(lib.contains("Green"), "should contain Green variant");
assert!(lib.contains("Blue"), "should contain Blue variant");
}
#[test]
fn enum_generates_display_impl() {
let project = codegen_ok(
r#"
enum Status {
Active,
Inactive,
Pending
}
"#,
);
let lib = &project.files[0].1;
assert!(
lib.contains("impl std::fmt::Display for Status"),
"should generate Display impl: {lib}"
);
assert!(
lib.contains("Status::Active => write!(f, \"Active\")"),
"should have Active display arm: {lib}"
);
}
#[test]
fn contract_generates_module() {
let project = codegen_ok(
r#"
contract SafeDivision {
requires { true }
ensures { true }
}
"#,
);
let lib = &project.files[0].1;
assert!(
lib.contains("contract_safedivision"),
"should contain contract module"
);
}
#[test]
fn fn_def_codegen() {
let project = codegen_ok(
r#"
fn helper(n: Int) -> Int {
requires { n >= 0 }
ensures { result >= 0 }
}
"#,
);
let lib = &project.files[0].1;
assert!(lib.contains("fn helper"), "should contain fn helper");
}
#[test]
fn contract_generates_debug_assert() {
let project = codegen_ok(
r#"
contract Positive {
requires { true }
}
"#,
);
let lib = &project.files[0].1;
assert!(
lib.contains("debug_assert!"),
"contract requires should generate debug_assert"
);
}
#[test]
fn project_name_used_in_cargo_toml() {
let project = codegen_ok(
r#"
project my_cool_project {
profile: [core]
}
contract Foo {
requires { true }
}
"#,
);
assert!(
project.cargo_toml.contains("my_cool_project"),
"Cargo.toml should use the project name"
);
}
#[test]
fn service_generates_module() {
let project = codegen_ok(
r#"
service MyService {
states: Init -> Running -> Stopped
operation Start {
requires: true
}
}
"#,
);
let lib = &project.files[0].1;
assert!(
lib.contains("mod myservice"),
"should contain service module"
);
assert!(
lib.contains("pub struct Init"),
"should contain state marker struct Init: {lib}"
);
assert!(
lib.contains("PhantomData"),
"should contain PhantomData for typestate: {lib}"
);
}
#[test]
fn service_state_transition_codegen() {
let project = codegen_ok(
r#"
service Connection {
states: Disconnected -> Connected -> Closed
operation Connect {
requires { self.state == Disconnected }
ensures { self.state == Connected }
}
}
"#,
);
let lib = &project.files[0].1;
assert!(
lib.contains("impl Connection<Disconnected>"),
"should contain state-specific impl block: {lib}"
);
assert!(
lib.contains("Connection<Connected>"),
"should contain transition return type: {lib}"
);
assert!(
lib.contains("fn Connect(self)"),
"state-transitioning method should consume self: {lib}"
);
}
#[test]
fn cargo_toml_well_formed() {
let project = codegen_ok("");
assert!(project.cargo_toml.contains("[package]"));
assert!(project.cargo_toml.contains("edition = \"2024\""));
assert!(project.cargo_toml.contains("[dependencies]"));
}