#![allow(clippy::expect_used, clippy::unwrap_used, clippy::panic, missing_docs)]
use std::fs;
use zerodds_build::{Config, DefaultExt};
#[test]
fn a_struct_becomes_a_type_with_a_codec() {
let dir = tempfile::tempdir().expect("tempdir");
let idl = dir.path().join("Sample.idl");
fs::write(&idl, "struct Sample { long id; string name; };").expect("write idl");
let out_dir = dir.path().join("out");
fs::create_dir_all(&out_dir).expect("out dir");
Config::new()
.out_dir(&out_dir)
.emit_cargo_directives(false)
.compile(&[&idl])
.expect("compile");
let generated = fs::read_to_string(out_dir.join("Sample.rs")).expect("read generated");
assert!(generated.contains("struct Sample"), "{generated}");
assert!(
generated.contains("fn encode") && generated.contains("fn decode"),
"a type without a codec cannot go on a wire: {generated}"
);
}
#[test]
fn a_vendor_keylist_pragma_reaches_the_generated_type() {
let dir = tempfile::tempdir().expect("tempdir");
let idl = dir.path().join("Sample.idl");
fs::write(
&idl,
"struct Sample { long id; long payload; };\n#pragma keylist Sample id\n",
)
.expect("write idl");
let out_dir = dir.path().join("out");
fs::create_dir_all(&out_dir).expect("out dir");
Config::new()
.out_dir(&out_dir)
.emit_cargo_directives(false)
.compile(&[&idl])
.expect("compile");
let generated = fs::read_to_string(out_dir.join("Sample.rs")).expect("read generated");
assert!(
generated.contains("key"),
"the pragma must reach the model: {generated}"
);
}
#[test]
fn the_type_object_module_is_there_by_default_and_absent_when_turned_off() {
let dir = tempfile::tempdir().expect("tempdir");
let idl = dir.path().join("Sample.idl");
fs::write(&idl, "struct Sample { long id; };").expect("write idl");
let with = dir.path().join("with");
fs::create_dir_all(&with).expect("with");
Config::new()
.out_dir(&with)
.emit_cargo_directives(false)
.compile(&[&idl])
.expect("compile");
let with_code = fs::read_to_string(with.join("Sample.rs")).expect("read");
assert!(with_code.contains("pub mod type_objects"), "{with_code}");
assert!(
with_code.contains("pub const Sample"),
"the type is named: {with_code}"
);
let without = dir.path().join("without");
fs::create_dir_all(&without).expect("without");
Config::new()
.out_dir(&without)
.emit_cargo_directives(false)
.typeobject(false)
.compile(&[&idl])
.expect("compile");
let without_code = fs::read_to_string(without.join("Sample.rs")).expect("read");
assert!(
!without_code.contains("pub mod type_objects"),
"{without_code}"
);
}
#[test]
fn the_default_extensibility_reaches_only_the_silent_type() {
let dir = tempfile::tempdir().expect("tempdir");
let idl = dir.path().join("Ext.idl");
fs::write(
&idl,
"struct Silent { long a; };\n@final struct Said { long a; };",
)
.expect("write idl");
let chosen = dir.path().join("chosen");
fs::create_dir_all(&chosen).expect("chosen");
Config::new()
.out_dir(&chosen)
.emit_cargo_directives(false)
.default_extensibility(DefaultExt::Mutable)
.compile(&[&idl])
.expect("compile");
let chosen_code = fs::read_to_string(chosen.join("Ext.rs")).expect("read");
let plain = dir.path().join("plain");
fs::create_dir_all(&plain).expect("plain");
Config::new()
.out_dir(&plain)
.emit_cargo_directives(false)
.compile(&[&idl])
.expect("compile");
let plain_code = fs::read_to_string(plain.join("Ext.rs")).expect("read");
assert_ne!(
chosen_code, plain_code,
"@mutable and the specification's @appendable are different plans"
);
assert!(
chosen_code.contains("write_emheader"),
"the silent type took the chosen default: {chosen_code}"
);
}
#[test]
fn an_include_is_resolved_and_both_files_are_reported() {
let dir = tempfile::tempdir().expect("tempdir");
let headers = dir.path().join("headers");
fs::create_dir_all(&headers).expect("headers");
fs::write(headers.join("Common.idl"), "struct Common { long a; };").expect("common");
let idl = dir.path().join("Robot.idl");
fs::write(
&idl,
"#include \"Common.idl\"\nstruct Robot { Common base; long id; };",
)
.expect("write idl");
let out_dir = dir.path().join("out");
fs::create_dir_all(&out_dir).expect("out dir");
Config::new()
.out_dir(&out_dir)
.include_dir(&headers)
.emit_cargo_directives(false)
.compile(&[&idl])
.expect("compile");
let generated = fs::read_to_string(out_dir.join("Robot.rs")).expect("read generated");
assert!(generated.contains("struct Robot"), "{generated}");
assert!(
generated.contains("struct Common"),
"the included type came with it: {generated}"
);
}
#[test]
fn a_define_selects_a_guarded_declaration() {
let dir = tempfile::tempdir().expect("tempdir");
let idl = dir.path().join("Guarded.idl");
fs::write(
&idl,
"#ifdef WITH_EXTRA\nstruct Extra { long a; };\n#endif\nstruct Always { long b; };",
)
.expect("write idl");
let with = dir.path().join("with");
fs::create_dir_all(&with).expect("with");
Config::new()
.out_dir(&with)
.emit_cargo_directives(false)
.define("WITH_EXTRA", None)
.compile(&[&idl])
.expect("compile");
assert!(
fs::read_to_string(with.join("Guarded.rs"))
.expect("read")
.contains("struct Extra"),
"the define selected it"
);
let without = dir.path().join("without");
fs::create_dir_all(&without).expect("without");
Config::new()
.out_dir(&without)
.emit_cargo_directives(false)
.compile(&[&idl])
.expect("compile");
assert!(
!fs::read_to_string(without.join("Guarded.rs"))
.expect("read")
.contains("struct Extra"),
"and without it, it is out"
);
}
#[test]
fn a_broken_unit_writes_nothing() {
let dir = tempfile::tempdir().expect("tempdir");
let idl = dir.path().join("Bad.idl");
fs::write(&idl, "struct Bad { long ; };").expect("write idl");
let out_dir = dir.path().join("out");
fs::create_dir_all(&out_dir).expect("out dir");
let result = Config::new()
.out_dir(&out_dir)
.emit_cargo_directives(false)
.compile(&[&idl]);
assert!(result.is_err(), "a syntax error must fail the build");
assert!(!out_dir.join("Bad.rs").exists(), "and write nothing");
}