test(derive): close fifth mutation shard

Fail closed when generated form field names cannot map to Rust identifiers and delete the redundant empty generated-parameter branch.

req: form/004

req: diagnostics/003

req: test/022

req: test/023
This commit is contained in:
slhx agent
2026-07-17 14:32:48 +02:00
parent 78a0d91223
commit 31c52698e3
2 changed files with 14 additions and 7 deletions
+1 -1
View File
@@ -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.
- **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.
- **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 `4/8` are clean. Shard `4/8` passed with 61 mutants (49 caught, 12 unviable) after exact required/optional/multiple form-decoding code generation plus bare/qualified/mismatched/empty generic container boundaries. Shards `5/8` through `8/8` remain. 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-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 `5/8` are clean. Shard `5/8` passed with 61 mutants (57 caught, 4 unviable) after fail-closed generated field-name validation and deletion of a redundant empty-parameter branch. Shards `6/8` through `8/8` remain. 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
## 3. Elect and enforce the release license policy
+13 -6
View File
@@ -670,12 +670,8 @@ fn rust_ident(name: &str) -> Option<String> {
}
fn missing_handle_params(path: &PathBuf, ident: &str, function: &ItemFn) -> Vec<String> {
let required = handle_params(path, ident);
if required.is_empty() {
return Vec::new();
}
let args = handler_arg_names(function);
required
handle_params(path, ident)
.into_iter()
.filter(|param| !args.contains(param))
.collect()
@@ -1029,7 +1025,7 @@ mod tests {
handler_syms_path, has_form_param, has_non_unit_return, is_type_named,
join_contract_errors, missing_component_handlers, missing_form_generated_files_message,
missing_handle_params, missing_handler_generated_files_message, parser_type,
returns_result, syms_contains_handle, HandlerPlacement,
returns_result, rust_ident, syms_contains_handle, HandlerPlacement,
};
use quote::{quote, ToTokens};
use syn::{parse_quote, ItemFn, Type};
@@ -1432,6 +1428,16 @@ mod tests {
assert!(form_model_type(&foreign_form).is_none());
}
#[test]
fn generated_form_field_names_map_only_to_valid_rust_identifiers() {
assert_eq!(rust_ident("first-name").as_deref(), Some("first_name"));
assert_eq!(rust_ident("_private2").as_deref(), Some("_private2"));
for invalid in ["", "2fast", "with space", "naïve"] {
assert_eq!(rust_ident(invalid), None, "{invalid:?} must fail closed");
}
// test req: form/004 req: diagnostics/003
}
#[test]
fn handler_params_match_generated_param_names() {
let path = std::env::temp_dir().join("hemx-derive-param-test.syms");
@@ -1453,6 +1459,7 @@ mod tests {
assert!(missing_handle_params(&path, "show", &complete).is_empty());
assert_eq!(missing_handle_params(&path, "show", &missing), vec!["mode"]);
assert!(missing_handle_params(&path, "unknown", &missing).is_empty());
let _ = std::fs::remove_file(path);
}