feat: release Dever 0.1.4 with enforceable project guidance

This commit is contained in:
Antigravity committed 2026-10-09 05:33:57 +00:00
1 parent 201bdee372
commit 89629c2197
86 files changed
+2798 -338

No files matched your search

+182
View File
@@ -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();