원클릭으로
mutation-testing
Rust mutation testing with cargo-mutants, survived-mutant triage, and test adequacy fixes.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Rust mutation testing with cargo-mutants, survived-mutant triage, and test adequacy fixes.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use this skill to generate well-branded interfaces and assets for RIPDPI (an Android-native, Compose-first VPN and DPI-bypass app), either for production or throwaway prototypes/mocks/etc. Contains essential design guidelines, colors, type, fonts, brand-ship icons, and an interactive UI kit of every public composable from the live ui/components tree.
Use when managing the Rust workspace, adding/removing crates, editing workspace dependencies, running cargo nextest/audit/deny, configuring Cargo profiles for Android cross-compilation, debugging Cargo.lock churn, migrating crate edition, or wiring Gradle to cargo via the ripdpi.android.rust-native plugin.
Use when modifying the diagnostics scan pipeline, ScanRequest/ScanReport types, ProbeTask families, ripdpi-monitor-engine / ripdpi-diagnostics-* crates, strategy-probe candidates, the diagnostics catalog (packs/profiles), wire-schema contracts between Rust and Kotlin, DIAGNOSTICS_ENGINE_SCHEMA_VERSION, golden contract tests, or adding a new probe type / profile. Triggers on diagnostics scans, strategy probes, automatic audit, dpi-detector profiles, or anything in core/diagnostics or native/rust/crates/ripdpi-monitor-*.
Android-specific Rust build, verification, and packaging — per-target 16 KiB page alignment, size-optimized release profile, ELF symbol allowlist, .so size budgets, NDK 29 specifics. Use when modifying .cargo/config.toml for Android targets, the workspace [profile.release] / [profile.android-jni] block, or when verifying a built .so before release.
Telemetry and observability discipline for the RIPDPI Android Rust stack — control-plane vs data-plane logging, bounded flume event queues, atomic counters, snapshot polling, readiness callbacks, and deterministic JSON contracts. Use when authoring or modifying telemetry emission code, the bounded event ring, the Kotlin-side telemetry consumer, or any per-packet logging.
Custom detekt rules, DI/privacy/suppression guardrails, detekt.yml configuration, and false-positive triage.
| name | mutation-testing |
| description | Rust mutation testing with cargo-mutants, survived-mutant triage, and test adequacy fixes. |
Coverage tells you which lines execute during tests, not whether the tests verify the behavior. A function with 100% coverage can have zero assertions.
Mutation testing injects small semantic changes (mutants) -- flipping operators, replacing return values, deleting calls -- and re-runs the test suite for each. If tests still pass after a mutation, that mutant "survived," meaning tests execute the code but never check its correctness. Surviving mutants point directly at weak assertions, missing edge-case tests, or untested error paths.
All commands assume your working directory is the repository root.
cargo mutants \
--manifest-path native/rust/Cargo.toml \
--test-tool nextest \
--jobs auto \
--output target/mutants-output
Add --in-diff "git diff origin/main...HEAD" to the command above. This only
generates mutants for changed lines, so a focused PR might produce 10-50
mutants instead of thousands.
Add --package ripdpi-desync to target one crate. Combine with --in-diff
for the fastest feedback loop.
| Flag | Purpose |
|---|---|
--list | Dry-run: print mutants without executing tests |
--file <path> | Restrict to a specific source file |
--re <regex> | Only mutants matching a regex on the function name |
--timeout-multiplier <N> | Override the config timeout multiplier |
-j <N> / --jobs <N> | Parallel mutant jobs (default: auto) |
timeout_multiplier = 3.0
minimum_test_timeout = 30
baseline_duration * 3.0 before
being killed. The 3x accounts for build overhead and CI variability.All 23 workspace crates are mutation targets by default. Prefer narrow source-level excludes over disabling entire packages.
To exclude specific functions or modules, add to mutants.toml:
exclude_re = ["Display::fmt", "impl.*Debug"]
Schedule: Weekly on Monday 06:00 UTC (cron: "0 6 * * 1").
Manual dispatch inputs:
packages -- space-separated crate names; empty = all 23 cratesin_diff -- true to only mutate lines changed vs mainKey details:
rust-toolchain.toml)cargo-nextest and cargo-mutants via taiki-e/install-actionubuntu-latest with a 90-minute timeouttarget/mutants-output/ as artifact, retained 14 daysTo trigger manually from the CLI:
gh workflow run mutation-testing.yml \
-f packages="ripdpi-desync ripdpi-packets" \
-f in_diff=true
Results land in target/mutants-output/. Key files:
| File | Content |
|---|---|
caught.txt | Mutants killed by tests (good) |
missed.txt | Mutants that survived (test gaps) |
timeout.txt | Mutants that caused infinite loops / hangs |
unviable.txt | Mutants that failed to compile (not interesting) |
outcomes.json | Machine-readable full results |
missed.txtmutants.toml rather than writing a meaningless test// Weak: survives mutations that change the return value
assert!(compute_ttl(input).is_ok());
// Strong: catches any change to the computed value
assert_eq!(compute_ttl(input), Ok(Duration::from_secs(30)));
Mutants often flip < to <= or +1 to -1. Pin the boundaries:
#[test]
fn fragment_offset_boundary() {
// Exactly at limit -- should succeed
assert!(validate_offset(MAX_OFFSET).is_ok());
// One past limit -- should fail
assert!(validate_offset(MAX_OFFSET + 1).is_err());
}
Error branches often survive because no test triggers them. Write explicit tests for malformed input, invalid state, and rejection paths. Similarly, if a function has side effects (incrementing a counter, sending a metric), assert the effect occurred -- mutations that delete the call survive otherwise.
Suppress these in mutants.toml with exclude_re rather than writing
low-value tests:
tracing::debug! argument changes do not affect correctness.unreachable!() in type-guarded match arms.The script is the single entry point for both CI and local batch runs.
What it does: Locates native/rust/Cargo.toml, reads env vars
(MUTANTS_TEST_TOOL=nextest, MUTANTS_PACKAGES=all,
MUTANTS_JOBS unset = cargo-mutants default parallelism), filters packages via
cargo metadata --locked if a subset is requested, then calls cargo mutants with
assembled args. Extra CLI args (e.g., --in-diff) are passed through.
Local usage:
bash scripts/ci/run-rust-mutants.sh # all crates
MUTANTS_PACKAGES="ripdpi-desync" bash scripts/ci/run-rust-mutants.sh # one crate
bash scripts/ci/run-rust-mutants.sh --in-diff "git diff origin/main...HEAD" # incremental
MUTANTS_JOBS=4 bash scripts/ci/run-rust-mutants.sh # limit parallelism
The script uses run_workspace_mutants and currently targets only the main
workspace. Add another call at the bottom to extend to additional workspaces.