test(derive): close seventh mutation shard
Prove all state, async, and Result registration combinations and the exact no-generated-component repair diagnostic. 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 `6/8` are clean. Shard `6/8` passed with 60 mutants (50 caught, 10 unviable) after malformed parameter-manifest, handler-pattern, app diagnostic, and component registration guard coverage; an unreachable empty-handler branch was deleted, and static quote-owned syntax parsing is narrowly classified as invariant-equivalent. Shards `7/8` and `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 `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.
|
||||||
- **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
|
||||||
|
|||||||
+63
-6
@@ -1016,13 +1016,14 @@ fn compile_error(message: &str) -> TokenStream {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
add_app_registry_helper, add_component_register_helper, client_handler_has_inputs,
|
add_app_registry_helper, add_component_register_helper, client_handler_has_inputs,
|
||||||
component_handler_names, expand_handler_function, form_contract_errors, form_decode_fields,
|
component_contract_errors, component_handler_names, component_registration_call,
|
||||||
form_fields, form_impl_generics, form_model_type, form_resource_id, generic_inner_type,
|
expand_handler_function, form_contract_errors, form_decode_fields, form_fields,
|
||||||
handle_params, handle_requires_form, handler_arg_names, handler_form_model_type,
|
form_impl_generics, form_model_type, form_resource_id, generic_inner_type, handle_params,
|
||||||
handler_placement, handler_syms_path, has_form_param, has_non_unit_return, is_type_named,
|
handle_requires_form, handler_arg_names, handler_form_model_type, handler_placement,
|
||||||
|
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, HandlerPlacement,
|
returns_result, rust_ident, syms_contains_handle, ComponentHandler, HandlerPlacement,
|
||||||
};
|
};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{parse_quote, ItemFn, Type};
|
use syn::{parse_quote, ItemFn, Type};
|
||||||
@@ -1469,6 +1470,55 @@ mod tests {
|
|||||||
let _ = std::fs::remove_file(path);
|
let _ = std::fs::remove_file(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn component_registration_selects_each_state_async_result_shape() {
|
||||||
|
let component_ident: syn::Ident = parse_quote!(todos);
|
||||||
|
let expected = [
|
||||||
|
(0, false, false, quote!(.on(super::todos::save, save))),
|
||||||
|
(0, false, true, quote!(.on_result(super::todos::save, save))),
|
||||||
|
(0, true, false, quote!(.on_async(super::todos::save, save))),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
quote!(.on_async_result(super::todos::save, save)),
|
||||||
|
),
|
||||||
|
(1, false, false, quote!(.on_state(super::todos::save, save))),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
quote!(.on_state_result(super::todos::save, save)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
quote!(.on_state_async(super::todos::save, save)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
quote!(.on_state_async_result(super::todos::save, save)),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
for (typed_arg_count, is_async, returns_result, expected) in expected {
|
||||||
|
let handler = ComponentHandler {
|
||||||
|
ident: parse_quote!(save),
|
||||||
|
is_async,
|
||||||
|
returns_result,
|
||||||
|
typed_arg_count,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
component_registration_call(&handler, &component_ident).to_string(),
|
||||||
|
expected.to_string(),
|
||||||
|
"args={typed_arg_count} async={is_async} result={returns_result}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// test req: component/003 req: derive_handler/003
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn component_handlers_match_generated_handles() {
|
fn component_handlers_match_generated_handles() {
|
||||||
let path = std::env::temp_dir().join("hemx-derive-component-test.syms");
|
let path = std::env::temp_dir().join("hemx-derive-component-test.syms");
|
||||||
@@ -1495,7 +1545,14 @@ mod tests {
|
|||||||
vec!["delete"]
|
vec!["delete"]
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = std::fs::remove_file(path);
|
let _ = std::fs::remove_file(&path);
|
||||||
|
assert_eq!(
|
||||||
|
component_contract_errors(&path, Some("missing"), &items),
|
||||||
|
vec![
|
||||||
|
"#[hemx::component(\"missing\")] does not match any generated handles; no generated components with handles are available; add a data-hemx-handle to the component template or check build.rs generation",
|
||||||
|
"#[hemx::component] handler(s) not declared by this component's generated handles: create; move them to the matching component module or add data-hemx-handle in .heml",
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user