test(derive): close final mutation shard
Fail closed on malformed symbol lines, prove sorted deduplicated component discovery and component filtering, exclude ordinary functions from handler registration, and emit diagnostics through quoted tokens without string reparsing. req: diagnostics/003 req: component/003 req: derive_handler/003 req: test/020 req: test/021 req: test/022 req: test/023
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
- [ ] **State:** In progress — the package-native capped xtask entry point is reachable, rejects unknown packages and invalid shards, propagates mutest failure, and mutation-tests `hemx-axum`, `hemx-build`, `hemx-core`, `hemx-js`, and the full `hemx-test` package cleanly; full package closure remains.
|
- [ ] **State:** In progress — the package-native capped xtask entry point is reachable, rejects unknown packages and invalid shards, propagates mutest failure, and mutation-tests `hemx-axum`, `hemx-build`, `hemx-core`, `hemx-js`, and the full `hemx-test` package cleanly; full package closure remains.
|
||||||
- **User value:** maintainers can run one bounded repository command and trust that meaningful Rust logic across every mutation-applicable library is either killed or explicitly justified.
|
- **User value:** maintainers can run one bounded repository command and trust that meaningful Rust logic across every mutation-applicable library is either killed or explicitly justified.
|
||||||
- **Build:** add a capped `hemx-xtask` mutation command that invokes `/opt/repositories/mutest`/`mutest` through package-native test targets rather than the broken workspace-wide example path; enumerate only current mutation-applicable library/proc-macro packages; finish adversarial tests or simplify code until every survivor is classified; keep equivalent, invariant-only, and infrastructure-inapplicable classifications inspectable and minimal; document the exact local release command in the existing readiness surface.
|
- **Build:** add a capped `hemx-xtask` mutation command that invokes `/opt/repositories/mutest`/`mutest` through package-native test targets rather than the broken workspace-wide example path; enumerate only current mutation-applicable library/proc-macro packages; finish adversarial tests or simplify code until every survivor is classified; keep equivalent, invariant-only, and infrastructure-inapplicable classifications inspectable and minimal; document the exact local release command in the existing readiness surface.
|
||||||
- **Blocked by:** none; broad survivors currently remain in `hemx-derive` and `hemx-lsp` outside already-clean focused contracts. The xtask mutation runner now creates shard output parents before invoking mutest, fixing first-use failure for newly sharded packages. `hemx-derive` public shards `1/8` through `7/8` are clean. Shard `7/8` passed with 60 mutants (45 caught, 15 unviable) after exact coverage of all state/async/result registration shapes and the no-generated-component repair diagnostic. Shard `8/8` remains. The mutation entry point accepts validated one-based `SHARD/TOTAL` operands, maps them to native zero-based shards, uses shard-specific output directories, grants repo-owned compiler probes a 120-second floor, and preserves the unsharded gate. All eight deterministic `hemx-build` shards now pass: 1,304 mutants total, 1,070 caught and 234 unviable, including final shard `8/8` with 159 mutants (139 caught, 20 unviable). The complete 470-mutant `hemx-axum` package gate passes with 262 caught and 208 unviable after public page/form/multipart/registry/response/runtime proofs and narrow classification of infallible header parsing and streamed multipart unwrap-equivalent mutants.
|
- **Blocked by:** none; broad survivors currently remain in `hemx-lsp` outside already-clean focused contracts. The xtask mutation runner now creates shard output parents before invoking mutest, fixing first-use failure for newly sharded packages. All eight deterministic `hemx-derive` shards pass: 480 mutants total, 393 caught and 87 unviable, including final shard `8/8` with 54 mutants (42 caught, 12 unviable) after fail-closed malformed symbol-line handling, exact sorted/deduplicated component discovery, component filtering, non-handler exclusion, and direct quoted compile diagnostics. The mutation entry point accepts validated one-based `SHARD/TOTAL` operands, maps them to native zero-based shards, uses shard-specific output directories, grants repo-owned compiler probes a 120-second floor, and preserves the unsharded gate. All eight deterministic `hemx-build` shards now pass: 1,304 mutants total, 1,070 caught and 234 unviable, including final shard `8/8` with 159 mutants (139 caught, 20 unviable). The complete 470-mutant `hemx-axum` package gate passes with 262 caught and 208 unviable after public page/form/multipart/registry/response/runtime proofs and narrow classification of infallible header parsing and streamed multipart unwrap-equivalent mutants.
|
||||||
- **Proof:** the new xtask mutation command exits zero within its documented bound, covers each applicable package, emits no unexplained missed mutant, and a deliberate adjacent mutation makes it fail. `cargo run -p hemx-xtask -- test` remains green. req: test/020 req: test/021
|
- **Proof:** the new xtask mutation command exits zero within its documented bound, covers each applicable package, emits no unexplained missed mutant, and a deliberate adjacent mutation makes it fail. `cargo run -p hemx-xtask -- test` remains green. req: test/020 req: test/021
|
||||||
|
|
||||||
## 3. Elect and enforce the release license policy
|
## 3. Elect and enforce the release license policy
|
||||||
|
|||||||
+19
-5
@@ -1007,9 +1007,7 @@ fn symbol_component(symbol: &str) -> Option<&str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn compile_error(message: &str) -> TokenStream {
|
fn compile_error(message: &str) -> TokenStream {
|
||||||
format!("compile_error!({message:?});")
|
quote!(compile_error!(#message);).into()
|
||||||
.parse()
|
|
||||||
.expect("compile_error expansion is valid")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -1023,7 +1021,8 @@ mod tests {
|
|||||||
handler_syms_path, has_form_param, has_non_unit_return, is_type_named,
|
handler_syms_path, has_form_param, has_non_unit_return, is_type_named,
|
||||||
join_contract_errors, missing_component_handlers, missing_form_generated_files_message,
|
join_contract_errors, missing_component_handlers, missing_form_generated_files_message,
|
||||||
missing_handle_params, missing_handler_generated_files_message, parser_type,
|
missing_handle_params, missing_handler_generated_files_message, parser_type,
|
||||||
returns_result, rust_ident, syms_contains_handle, ComponentHandler, HandlerPlacement,
|
returns_result, rust_ident, symbol_component, syms_components, syms_contains_handle,
|
||||||
|
syms_handles, ComponentHandler, HandlerPlacement,
|
||||||
};
|
};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{parse_quote, ItemFn, Type};
|
use syn::{parse_quote, ItemFn, Type};
|
||||||
@@ -1345,7 +1344,7 @@ mod tests {
|
|||||||
let path = std::env::temp_dir().join("hemx-derive-syms-test.syms");
|
let path = std::env::temp_dir().join("hemx-derive-syms-test.syms");
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
&path,
|
&path,
|
||||||
"hemx-syms-v1\nslot\ttemplates/a.heml::count\tcount\t1\nhandle\ttemplates/a.heml::create\tcreate\t2\nhandle_form\tcreate\tnew_todo\nhandle_param\tcreate\ttodo_id\n",
|
"hemx-syms-v1\nslot\ttemplates/a.heml::count\tcount\t1\nhandle\ttemplates/z.heml::archive\tarchive\t3\nhandle\ttemplates/a.heml::create\tcreate\t2\nhandle\ttemplates/a.heml::delete\tdelete\t4\nhandle\ttemplates/a.heml::create\tcreate-again\t5\nhandle\thas-no-component\tignored\t6\nhandle\nhandle_form\tcreate\tnew_todo\nhandle_param\tcreate\ttodo_id\n",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -1355,6 +1354,19 @@ mod tests {
|
|||||||
assert!(!handle_requires_form(&path, "missing"));
|
assert!(!handle_requires_form(&path, "missing"));
|
||||||
assert_eq!(handle_params(&path, "create"), vec!["todo_id"]);
|
assert_eq!(handle_params(&path, "create"), vec!["todo_id"]);
|
||||||
assert!(handle_params(&path, "missing").is_empty());
|
assert!(handle_params(&path, "missing").is_empty());
|
||||||
|
assert_eq!(
|
||||||
|
syms_handles(&path, Some("a")),
|
||||||
|
vec!["create", "delete", "create-again"]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
syms_handles(&path, None),
|
||||||
|
vec!["archive", "create", "delete", "create-again", "ignored"]
|
||||||
|
);
|
||||||
|
assert_eq!(syms_components(&path), vec!["a", "z"]);
|
||||||
|
assert_eq!(symbol_component("templates/a.heml::create"), Some("a"));
|
||||||
|
assert_eq!(symbol_component("a.heml::create"), Some("a"));
|
||||||
|
assert_eq!(symbol_component("a.html::create"), None);
|
||||||
|
assert_eq!(symbol_component("a.heml"), None);
|
||||||
|
|
||||||
let _ = std::fs::remove_file(&path);
|
let _ = std::fs::remove_file(&path);
|
||||||
assert!(
|
assert!(
|
||||||
@@ -1531,6 +1543,8 @@ mod tests {
|
|||||||
mod component {
|
mod component {
|
||||||
#[hemx::handler]
|
#[hemx::handler]
|
||||||
fn create() -> impl hemx::IntoEffect { hemx::advanced::EffectBatch::default() }
|
fn create() -> impl hemx::IntoEffect { hemx::advanced::EffectBatch::default() }
|
||||||
|
|
||||||
|
fn helper() {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (_, items) = module.content.expect("inline module");
|
let (_, items) = module.content.expect("inline module");
|
||||||
|
|||||||
Reference in New Issue
Block a user