From 0fe23768742c6e2fa64cf40d7d4e0d2534e726cc Mon Sep 17 00:00:00 2001 From: slhx agent Date: Fri, 17 Jul 2026 00:21:42 +0200 Subject: [PATCH] test(axum): prove response delivery boundary Decode emitted effect bytes, assert dispatch rejection status and diagnostics, and verify the shared embedded runtime body through public IntoResponse paths. req: axum_integration/003 req: axum_integration/005 req: failure/005 req: wire/007 --- PLAN.md | 2 +- hemx-axum/tests/response.rs | 62 +++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/PLAN.md b/PLAN.md index 02d85bb..111cb95 100644 --- a/PLAN.md +++ b/PLAN.md @@ -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. - **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-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, and sync/async registry dispatch mutation-clean; remaining response and 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; remaining integration paths remain. - **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 diff --git a/hemx-axum/tests/response.rs b/hemx-axum/tests/response.rs index d1ac677..d0276ad 100644 --- a/hemx-axum/tests/response.rs +++ b/hemx-axum/tests/response.rs @@ -829,8 +829,59 @@ fn interactions_reject_unknown_handle_ids() { ); } -#[test] -fn runtime_js_response_serves_embedded_runtime() { +#[tokio::test] +async fn effect_and_dispatch_responses_preserve_status_wire_and_diagnostics() { + let batch = Slot::::new(3) + .text("saved") + .into_batch(BuildFingerprint(77)); + let response = EffectResponse { + batch: batch.clone(), + } + .into_response(); + assert_eq!(response.status(), StatusCode::OK); + assert_eq!(response.headers()[header::CONTENT_TYPE], HEMX_CONTENT_TYPE); + assert_eq!(response.headers()[HEMX_FINGERPRINT_HEADER], "77"); + let body = to_bytes(response.into_body(), 4096).await.unwrap(); + assert_eq!(hemx_core::EffectBatch::from_wire(&body), Ok(batch.clone())); + + for (rejection, status, message) in [ + ( + DispatchRejection::UnknownHandle(9), + StatusCode::NOT_FOUND, + "unknown hemx handle id 9", + ), + ( + DispatchRejection::InvalidForm { + handle_id: 9, + message: "missing title".into(), + }, + StatusCode::BAD_REQUEST, + "invalid hemx form for handle id 9: missing title", + ), + ( + DispatchRejection::HandlerError(HandlerFailure::Response { + status: StatusCode::CONFLICT, + message: "stale".into(), + }), + StatusCode::CONFLICT, + "stale", + ), + ] { + let response = rejection.into_response(); + assert_eq!(response.status(), status); + assert_eq!( + to_bytes(response.into_body(), 4096).await.unwrap().as_ref(), + message.as_bytes() + ); + } + + let response = DispatchRejection::HandlerError(HandlerFailure::Effects(batch)).into_response(); + assert_eq!(response.headers()[header::CONTENT_TYPE], HEMX_CONTENT_TYPE); + // test req: axum_integration/003 req: failure/005 req: wire/007 +} + +#[tokio::test] +async fn runtime_js_response_serves_embedded_runtime() { let response = runtime_js().into_response(); assert_eq!( @@ -849,6 +900,13 @@ fn runtime_js_response_serves_embedded_runtime() { response.headers()[header::CONTENT_LENGTH], runtime_js_source().len().to_string() ); + assert_eq!( + to_bytes(response.into_body(), runtime_js_source().len() + 1) + .await + .unwrap() + .as_ref(), + runtime_js_source().as_bytes() + ); } // req: axum_integration/005