Skip to content

Add focused coverage for production readiness test gaps#688

Open
ChristianPavilonis wants to merge 2 commits into
mainfrom
test-coverage-cleanup-396
Open

Add focused coverage for production readiness test gaps#688
ChristianPavilonis wants to merge 2 commits into
mainfrom
test-coverage-cleanup-396

Conversation

@ChristianPavilonis
Copy link
Copy Markdown
Collaborator

@ChristianPavilonis ChristianPavilonis commented May 13, 2026

Summary

Changes

File Change
crates/trusted-server-core/src/error.rs Added direct status-code mapping coverage for every current TrustedServerError variant, including a compile-time exhaustive match guard for new variants.
crates/trusted-server-core/src/host_rewrite.rs Added direct boundary tests for exact hosts, paths, punctuation, multiple occurrences, subdomains, suffixes, empty inputs, and ports.
crates/trusted-server-core/src/tsjs.rs Added tests for unified/deferred script source formatting, hash shape, script tag attributes, empty deferred output, and deferred order preservation.
crates/trusted-server-core/src/auction/formats.rs Added request/response conversion tests for banner formats, bidder params, context allowlisting, malformed sizes, unsupported media skip behavior, OpenRTB response fields, mediation strategy, missing prices, and out-of-range dimensions.

Closes

Closes #448
Closes #449
Closes #450
Closes #453

Note: #455 references the old synthetic-template path, which no longer exists on current main after the EC ID migration. It should be triaged separately rather than auto-closed by this PR.

Test plan

  • cargo test --workspace
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • JS tests: cd crates/js/lib && npx vitest run
  • JS format: cd crates/js/lib && npm run format
  • Docs format: cd docs && npm run format
  • WASM build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1
  • Manual testing via fastly compute serve
  • Other: cargo test -p trusted-server-core status_code_maps_each_error_variant_to_expected_http_response -- --nocapture; cargo test -p trusted-server-core tsjs_ -- --nocapture; cargo test -p trusted-server-core rewrite -- --nocapture; cargo test -p trusted-server-core convert_tsjs_to_auction_request -- --nocapture; cargo test -p trusted-server-core convert_to_openrtb_response -- --nocapture

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() in production code — use expect("should ...")
  • Uses log macros (not println!)
  • New code has tests
  • No secrets or credentials committed

Copy link
Copy Markdown
Collaborator

@prk-Jr prk-Jr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Pure test additions across four files — error.rs, host_rewrite.rs, tsjs.rs, and auction/formats.rs. No production code changed. All CI checks pass. Test quality is high overall; a few missing edge cases and one misleading helper message noted inline.

Non-blocking

🏕 camp site

  • Forbidden and AllowlistViolation user_message untested — Both variants fall into the _ catch-all in user_message and return "An internal error occurred" despite being 4xx responses. The existing server_errors_return_generic_message test does not include them. Worth adding both to explicitly document (and lock in) the intended behavior — or, if a more descriptive message is preferred for 403s, this is the place to catch it.

🌱 seedling

  • Host-in-path-segment behavior unspecified (host_rewrite.rs) — Input https://cdn.example.com/assets/origin.example.com/image.png will be rewritten because / is not a is_host_char. This may be intentional for Next.js __next_f payloads but is undocumented and untested. A test explicitly asserting current behavior would prevent silent regressions.

  • Empty module list edge case (tsjs.rs) — tsjs_script_src(&[]) behavior is unspecified. What does concatenated_hash(&[]) return? Low risk but a documentation test would lock in the contract.

CI Status

  • cargo fmt: PASS
  • cargo clippy: PASS
  • cargo test: PASS
  • vitest: PASS
  • integration tests: PASS
  • browser integration tests: PASS

fn status_code_maps_each_error_variant_to_expected_http_response() {
// Compile-time guard: adding a TrustedServerError variant without
// updating this test will fail to compile.
let _exhaustive = |error: &TrustedServerError| match error {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 thinking_exhaustive is never called; it works because Rust type-checks closure bodies at compile time even for dead closures, but the intent is non-obvious to a reader. A comment above it explaining the compile-time guard purpose would help, or use the more explicit form:

let _guard: fn(&TrustedServerError) = |e| match e {
    TrustedServerError::BadRequest { .. }
    | ...
    | TrustedServerError::Ec { .. } => (),
};

| TrustedServerError::Ec { .. } => (),
};

let cases = vec![
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicklet cases = vec![...] here; existing tests in this module use array literals (let cases = [...]). Minor inconsistency.

);
}

fn assert_no_rewrite(input: &str) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick — The assertion message "should not rewrite host embedded in a larger host token" is inaccurate when called from returns_none_when_origin_host_is_absent (line 89) — there the host is simply absent, not embedded. Consider accepting a message parameter or a separate assert_absent helper.

}

#[test]
fn rewrites_origin_host_with_port_when_origin_includes_port() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 praise — The port inclusion/exclusion distinction (origin.example.com:8443 as origin vs. origin.example.com alone) is a subtle and important boundary. Good coverage.

}

#[test]
fn tsjs_deferred_script_src_uses_empty_hash_for_unknown_module() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 praise — Documenting the ?v= empty-hash fallback as spec (rather than asserting a computed value) is a clean use of tests as specification.

}
}

fn make_bid(slot_id: &str, bidder: &str, price: Option<f64>) -> Bid {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏕 camp sitemake_bid always sets creative: Some(...) and adomain: Some(...), leaving two paths uncovered:

  1. creative: None — the else branch in convert_to_openrtb_response emits log::warn! and sets adm: "". No test verifies the response still succeeds.
  2. adomain: None — exercises unwrap_or_default(), which should serialize as "adomain": [].

}
}

fn make_result(bid: Bid) -> OrchestrationResult {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏕 camp sitemake_result always produces a single winning bid. No test exercises convert_to_openrtb_response with multiple slots. Adding a two-slot result would verify seatbid ordering and per-slot impid values are preserved.

}

#[test]
fn convert_tsjs_to_auction_request_maps_banner_units_bidders_context_and_request_metadata() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ refactor — This 130-line test exercises ~9 behaviors in one function: slot mapping, format sizes, bidder params, publisher domain, site metadata, EC ID, fresh ID, device user-agent, and context filtering. When it fails the full setup must be re-read to isolate which invariant broke. Consider splitting into focused tests — e.g. maps_banner_sizes_to_formats, copies_user_agent_to_device_info, filters_disallowed_context_keys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants