test(axum): close page edge-case mutants
Prove partial constructor defaults, missing multipart-boundary rejection, first-root fingerprint replacement, and unchanged non-root HTML through public and nearest-boundary paths. req: page_swap/001 req: multipart/003 req: abi/005
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
- [ ] **State:** In progress — the package-native capped xtask entry point is reachable, rejects unknown packages, propagates mutest failure, and mutation-tests `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, propagates mutest failure, and mutation-tests `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-axum`, `hemx-build`, `hemx-derive`, and `hemx-lsp` outside already-clean focused contracts; the current `hemx-axum` frontier now proves page-mode, response constructors, form accessors/rejections, media-type limits, multipart success/error semantics, sync/async registry dispatch, effect/rejection responses, and embedded runtime delivery mutation-clean; page extraction/response and media-type integration paths are now mutation-clean; remaining app/transport integration paths remain.
|
- **Blocked by:** none; broad survivors currently remain in `hemx-axum`, `hemx-build`, `hemx-derive`, and `hemx-lsp` outside already-clean focused contracts; the current `hemx-axum` frontier now proves page-mode, response constructors, form accessors/rejections, media-type limits, multipart success/error semantics, sync/async registry dispatch, effect/rejection responses, and embedded runtime delivery mutation-clean; page extraction/response, media-type integration, partial-constructor defaults, missing multipart-boundary rejection, and root-fingerprint injection are now mutation-clean; handler-registration and infallible runtime-header construction remain before the full package gate can pass.
|
||||||
- **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
|
||||||
|
|||||||
@@ -1609,6 +1609,18 @@ mod tests {
|
|||||||
.expect("root element is rendered");
|
.expect("root element is rendered");
|
||||||
assert_eq!(root.value().attr("data-hemx-fp"), Some("1"));
|
assert_eq!(root.value().attr("data-hemx-fp"), Some("1"));
|
||||||
assert_eq!(root.text().collect::<String>(), "Docs");
|
assert_eq!(root.text().collect::<String>(), "Docs");
|
||||||
|
assert_eq!(html.matches("data-hemx-fp=").count(), 1);
|
||||||
|
assert!(!html.contains("data-hemx-fp=\"99\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fingerprint_injection_leaves_html_without_a_hemx_root_unchanged() {
|
||||||
|
let html = "<main>Docs</main>".to_owned();
|
||||||
|
assert_eq!(
|
||||||
|
html_with_root_fingerprint(html.clone(), BuildFingerprint(99)),
|
||||||
|
html
|
||||||
|
);
|
||||||
|
// test req: abi/005
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -144,6 +144,19 @@ async fn interaction_boundary_skips_unnamed_parts_and_rejects_invalid_multipart(
|
|||||||
let _guard = BOUNDARY_TEST_LOCK
|
let _guard = BOUNDARY_TEST_LOCK
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap_or_else(|error| error.into_inner());
|
.unwrap_or_else(|error| error.into_inner());
|
||||||
|
let app = Router::new().route("/mutate", post(bounded_mutation));
|
||||||
|
let missing_boundary = app
|
||||||
|
.clone()
|
||||||
|
.oneshot(
|
||||||
|
Request::post("/mutate")
|
||||||
|
.header(header::CONTENT_TYPE, "multipart/form-data")
|
||||||
|
.body(Body::from("invalid"))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(missing_boundary.status(), StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
let accepted = concat!(
|
let accepted = concat!(
|
||||||
"--b\r\n",
|
"--b\r\n",
|
||||||
"Content-Disposition: form-data; filename=\"ignored.txt\"\r\n\r\n",
|
"Content-Disposition: form-data; filename=\"ignored.txt\"\r\n\r\n",
|
||||||
@@ -153,7 +166,6 @@ async fn interaction_boundary_skips_unnamed_parts_and_rejects_invalid_multipart(
|
|||||||
"1\r\n",
|
"1\r\n",
|
||||||
"--b--\r\n"
|
"--b--\r\n"
|
||||||
);
|
);
|
||||||
let app = Router::new().route("/mutate", post(bounded_mutation));
|
|
||||||
let response = app
|
let response = app
|
||||||
.clone()
|
.clone()
|
||||||
.oneshot(
|
.oneshot(
|
||||||
@@ -369,6 +381,7 @@ fn page_response_constructors_preserve_mode_and_optional_fingerprint() {
|
|||||||
let partial = PageResponse::partial("<main>Partial</main>");
|
let partial = PageResponse::partial("<main>Partial</main>");
|
||||||
assert_eq!(partial.mode, PageMode::Partial);
|
assert_eq!(partial.mode, PageMode::Partial);
|
||||||
assert_eq!(partial.html, "<main>Partial</main>");
|
assert_eq!(partial.html, "<main>Partial</main>");
|
||||||
|
assert_eq!(partial.title, None);
|
||||||
assert_eq!(partial.fingerprint, None);
|
assert_eq!(partial.fingerprint, None);
|
||||||
|
|
||||||
let fingerprint = BuildFingerprint(42);
|
let fingerprint = BuildFingerprint(42);
|
||||||
|
|||||||
Reference in New Issue
Block a user