feat: release Dever 0.1.4 with enforceable project guidance
This commit is contained in:
1 parent
201bdee372
commit
89629c2197
86 files changed
+2798
-338
No files matched your search
@@ -151,6 +151,12 @@ fn application_check_rejects_redundancy_before_preparing_build_resources() {
|
||||
] {
|
||||
assert!(diagnostic.contains(expected), "{expected}: {diagnostic}");
|
||||
}
|
||||
assert_eq!(diagnostic.matches("error[C016]").count(), 3, "{diagnostic}");
|
||||
assert!(!diagnostic.contains("warning[W005]"), "{diagnostic}");
|
||||
assert!(
|
||||
diagnostic.contains("sample/profile/domain.dever:1:1: note:"),
|
||||
"{diagnostic}"
|
||||
);
|
||||
// The same source fails before native packs, output publication or execution.
|
||||
let executable = root.join("must-not-build");
|
||||
for (action, args) in [
|
||||
@@ -166,6 +172,120 @@ fn application_check_rejects_redundancy_before_preparing_build_resources() {
|
||||
assert!(!toolchain.path().join("cache").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn application_check_rejects_proven_duplicates_before_runtime_or_database_access() {
|
||||
let toolchain = TemporaryDirectory::new();
|
||||
let compiler = compiler(toolchain.path(), "dever");
|
||||
for (domain, app, diagnostic, location, warning) in [
|
||||
(
|
||||
"first(value: Int) (answer: Int) pure { answer = value + 1 }\nsecond(renamed: Int) (answer: Int) pure { answer = renamed + 1 }",
|
||||
"total(value: Int) (answer: Int) { first = domain.first(value)\nsecond = domain.second(value)\nanswer = first + second }",
|
||||
"same implementation and contract",
|
||||
"sample/count/domain.dever:2:1: error[C016]",
|
||||
"warning[W003]",
|
||||
),
|
||||
(
|
||||
"calculate(value: Int) (answer: Int) pure { answer = value + 1 }",
|
||||
"total(value: Int) (answer: Int) { first = domain.calculate(value)\nsecond = domain.calculate(value)\nanswer = first + second }",
|
||||
"earlier result is still available",
|
||||
"sample/count/app.dever:2:",
|
||||
"warning[W004]",
|
||||
),
|
||||
] {
|
||||
let project_dir = TemporaryDirectory::new();
|
||||
let root = project_dir.path();
|
||||
write(root, "config/setting.json", "{}");
|
||||
write(root, "module/sample/count/model.dever", "type Count { value: Int }");
|
||||
write(root, "module/sample/count/domain.dever", domain);
|
||||
write(root, "module/sample/count/app.dever", app);
|
||||
write(root, "module/sample/count/api.dever", "cmd total = app.total");
|
||||
let checked = cli(&compiler, root, "check", &[]);
|
||||
for expected in ["C016", diagnostic, location, "previous implementation or computation"] {
|
||||
failure(&checked, expected);
|
||||
}
|
||||
let stderr = String::from_utf8_lossy(&checked.stderr);
|
||||
assert_eq!(stderr.matches("error[C016]").count(), 1, "{stderr}");
|
||||
assert!(!stderr.contains(warning), "{stderr}");
|
||||
assert_eq!(
|
||||
stderr.matches("note: previous implementation or computation").count(),
|
||||
1,
|
||||
"{stderr}"
|
||||
);
|
||||
let executable = root.join("must-not-build");
|
||||
for (action, arguments) in [
|
||||
("run", vec!["--", "sample.count.total", "{\"value\":1}"]),
|
||||
("build", vec!["--output", executable.to_str().unwrap()]),
|
||||
] {
|
||||
let rejected = cli(&compiler, root, action, &arguments);
|
||||
assert!(!rejected.status.success());
|
||||
assert_eq!(rejected.stderr, checked.stderr);
|
||||
}
|
||||
let snapshot = cli(&compiler, root, "api", &[]);
|
||||
success(&snapshot);
|
||||
let stderr = String::from_utf8_lossy(&snapshot.stderr);
|
||||
assert!(stderr.contains(warning), "{stderr}");
|
||||
assert!(!stderr.contains("C016"), "{stderr}");
|
||||
write(
|
||||
root,
|
||||
"test/sample/count/value.dever",
|
||||
"value() () { assert_eq(app.total(1), 4) }",
|
||||
);
|
||||
let tests = cli(&compiler, root, "test", &[]);
|
||||
failure(&tests, "runtime pack");
|
||||
let stderr = String::from_utf8_lossy(&tests.stderr);
|
||||
assert!(stderr.contains(warning), "{stderr}");
|
||||
assert!(!stderr.contains("C016"), "{stderr}");
|
||||
write(root, "dever.api", "invalid baseline");
|
||||
let baseline = cli(&compiler, root, "check", &[]);
|
||||
failure(&baseline, "invalid API baseline");
|
||||
let stderr = String::from_utf8_lossy(&baseline.stderr);
|
||||
assert!(stderr.contains(warning), "{stderr}");
|
||||
assert!(!stderr.contains("C016"), "{stderr}");
|
||||
assert!(!executable.exists());
|
||||
assert!(!root.join("data").exists());
|
||||
}
|
||||
assert!(!toolchain.path().join("cache").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn application_check_keeps_warnings_with_distinct_evidence_and_other_codes() {
|
||||
let toolchain = TemporaryDirectory::new();
|
||||
let compiler = compiler(toolchain.path(), "dever");
|
||||
let project_dir = TemporaryDirectory::new();
|
||||
let root = project_dir.path();
|
||||
write(root, "config/setting.json", "{}");
|
||||
write(
|
||||
root,
|
||||
"module/sample/count/domain.dever",
|
||||
"orphan(value: Int) (answer: Int) pure { answer = value + 1 }\nfirst(value: Int) (answer: Int) pure { answer = value + 1 }\nsecond(value: Int) (answer: Int) pure { answer = value + 1 }",
|
||||
);
|
||||
write(
|
||||
root,
|
||||
"module/sample/count/app.dever",
|
||||
"total(value: Int) (answer: Int) { unused = 0\nfirst = domain.first(value)\nsecond = domain.second(value)\nanswer = first + second }",
|
||||
);
|
||||
write(root, "module/sample/count/api.dever", "cmd total = app.total");
|
||||
let checked = cli(&compiler, root, "check", &[]);
|
||||
failure(&checked, "C016");
|
||||
let stderr = String::from_utf8_lossy(&checked.stderr);
|
||||
assert_eq!(stderr.matches("error[C016]").count(), 2, "{stderr}");
|
||||
// Warning proof includes the orphan; production proof starts at the first reachable function.
|
||||
assert_eq!(stderr.matches("warning[W003]").count(), 2, "{stderr}");
|
||||
assert_eq!(stderr.matches("warning[W001]").count(), 1, "{stderr}");
|
||||
assert_eq!(
|
||||
stderr.matches("sample/count/domain.dever:1:1: note:").count(),
|
||||
2,
|
||||
"{stderr}"
|
||||
);
|
||||
assert_eq!(
|
||||
stderr.matches("sample/count/domain.dever:2:1: note:").count(),
|
||||
1,
|
||||
"{stderr}"
|
||||
);
|
||||
assert!(!root.join("data").exists());
|
||||
assert!(!toolchain.path().join("cache").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn application_check_rejects_plain_model_get_wrapper_without_opening_database() {
|
||||
let toolchain = TemporaryDirectory::new();
|
||||
@@ -303,6 +423,68 @@ fn application_check_does_not_apply_production_reachability_to_tests() {
|
||||
assert!(!toolchain.path().join("cache").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_still_checks_unselected_sources_and_reports_no_match_before_compilation() {
|
||||
let toolchain = TemporaryDirectory::new();
|
||||
let compiler = compiler(toolchain.path(), "dever");
|
||||
let project_dir = TemporaryDirectory::new();
|
||||
let root = project_dir.path();
|
||||
project(root);
|
||||
write(root, "test/sample/echo/first.dever", "first() () { assert_eq(1, 1) }");
|
||||
write(root, "test/sample/echo/second.dever", "second() () { assert_eq(1, 1) }");
|
||||
for filter in ["sam", "sample.ec", "sample.echo.fir", "sample.echo.missing"] {
|
||||
let result = cli(&compiler, root, "test", &["--filter", filter]);
|
||||
failure(&result, "no tests match filter");
|
||||
assert!(!String::from_utf8_lossy(&result.stdout).contains("runtime pack"));
|
||||
}
|
||||
let selected = cli(&compiler, root, "test", &["--filter", "sample.echo.second"]);
|
||||
failure(&selected, "runtime pack");
|
||||
let report = String::from_utf8_lossy(&selected.stdout);
|
||||
assert!(report.contains("0 passed; 1 failed; 1 not run"), "{report}");
|
||||
assert!(!report.contains("test sample/echo/first ..."), "{report}");
|
||||
write(root, "test/sample/echo/first.dever", "first() () { missing() }");
|
||||
failure(&cli(&compiler, root, "test", &["--filter", "sample.echo.second"]), "C004");
|
||||
assert!(!toolchain.path().join("cache").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires an explicitly prepared runtime pack adjacent to CARGO_BIN_EXE_dever; owned short-lived cases only"]
|
||||
fn llvm_test_controls_preserve_indices_prefix_boundaries_and_timeout_continuation() {
|
||||
let compiler = Path::new(env!("CARGO_BIN_EXE_dever"));
|
||||
let directory = TemporaryDirectory::new();
|
||||
let root = directory.path();
|
||||
project(root);
|
||||
for (relative, source) in [
|
||||
("test/sample/echo/alpha.dever", "alpha() () { assert_eq(1, 2) }"),
|
||||
("test/sample/echo/beta.dever", "beta() () { assert_eq(7, 7) }"),
|
||||
("test/sample/echo/slow.dever", "slow() () { dever.task.sleep(30000) }"),
|
||||
("test/sample/echo/zeta.dever", "zeta() () { assert_eq(9, 9) }"),
|
||||
("test/sample/echoes/first.dever", "first() () { assert_eq(1, 2) }"),
|
||||
("test/samples/echo/first.dever", "first() () { assert_eq(1, 2) }"),
|
||||
] {
|
||||
write(root, relative, source);
|
||||
}
|
||||
let selected = cli(compiler, root, "test", &["--filter", "sample.echo.beta"]);
|
||||
success(&selected);
|
||||
let report = String::from_utf8_lossy(&selected.stdout);
|
||||
assert!(report.contains("test sample/echo/beta ... ok"), "{report}");
|
||||
assert!(report.contains("1 passed; 0 failed; 5 not run"), "{report}");
|
||||
assert!(!report.contains("sample/echo/alpha"), "{report}");
|
||||
|
||||
for (filter, counts) in [
|
||||
("sample.echo", "2 passed; 2 failed; 2 not run"),
|
||||
("sample", "2 passed; 3 failed; 1 not run"),
|
||||
] {
|
||||
let selected = cli(compiler, root, "test", &["--filter", filter, "--timeout-ms", "250"]);
|
||||
failure(&selected, counts);
|
||||
let report = String::from_utf8_lossy(&selected.stdout);
|
||||
assert!(report.contains("test process timed out after 250 ms"), "{report}");
|
||||
assert!(report.contains("test sample/echo/zeta ... ok"), "{report}");
|
||||
assert!(!report.contains("test samples/echo/first"), "{report}");
|
||||
}
|
||||
failure(&cli(compiler, root, "test", &["--filter", "sample.echo.bet"]), "no tests match filter");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross_build_requires_the_selected_pack_even_when_host_pack_exists() {
|
||||
let root = TemporaryDirectory::new();
|
||||
|
||||
Reference in new issue
Block a user