Description
crates/rmcp/tests/ has 81 *.rs files but only 39 are declared as [[test]] targets with required-features in crates/rmcp/Cargo.toml. The other 42 are auto-discovered by Cargo and always get compiled by cargo test -p rmcp regardless of which --features are passed, unless the file itself carries a complete internal #![cfg(feature = "...")] gate. This breaks the exact "filter by test name" workflow this repo's own .claude/CLAUDE.md documents as the way to run a feature-scoped test subset:
cargo test -p rmcp --features "<feat1>,<feat2>" test_name_substring
Two files are confirmed broken by live reproduction:
test_cancelled_response.rs — no internal cfg gate at all; references RoleServer, ServiceExt, service::RequestContext (server-feature-gated).
test_stdio_response_concurrency.rs — has #![cfg(not(feature = "local"))], but that gate is incomplete: it calls rmcp::transport::stdio(), gated behind transport-io, which the existing cfg doesn't cover.
A broader audit found 21 of the 42 undeclared files have no internal cfg gate at all, and the remaining 21 have a gate whose completeness hasn't been individually verified (only test_stdio_response_concurrency.rs's incompleteness is confirmed). Full inventory in the linked spec.
Reproduction Steps
- On
main @ 02c62ae (v3.1.2, no drift as of this cycle):
cargo test -p rmcp --features "server,client" test_mrtr_behavior
- Observe a compile error instead of the expected test run:
error[E0425]: cannot find function `stdio` in module `rmcp::transport`
--> crates/rmcp/tests/test_stdio_response_concurrency.rs:106:61
|
106 | let server = LargeResponseServer.serve(rmcp::transport::stdio()).await?;
| ^^^^^ not found in `rmcp::transport`
note: found an item that was configured out
--> crates/rmcp/src/transport.rs:94:13
93 | #[cfg(feature = "transport-io")]
94 | pub use io::stdio;
error: could not compile `rmcp` (test "test_stdio_response_concurrency") due to 1 previous error
- A second run with
--features request-state independently fails on both test_stdio_response_concurrency (same error) and test_cancelled_response (unresolved server-feature-gated symbols) — confirms the pattern, not a one-off.
Expected Behavior
cargo test -p rmcp --features "<any valid combo>" <test_name_substring> should either run the matching tests or report 0 matched — never fail to compile because of an unrelated test file outside the requested scope. Every file under crates/rmcp/tests/ should have either a [[test]]/required-features declaration in Cargo.toml (like the other 39 files) or a complete internal cfg gate covering every feature-gated API it references.
Actual Behavior
The documented "filter by test name" workflow fails to compile on an unrelated file whenever the passed --features set doesn't happen to satisfy every undeclared/under-gated test file's real requirements.
Environment
- Version: v3.1.2, commit
02c62ae
- Features: reproduced with
server,client and separately with request-state
Upstream
No exact duplicate found. modelcontextprotocol/rust-sdk#1067 ("Rationalize feature flags for v3.0", open) covers feature-flag naming/design problems (a reqwest TLS trap, local's additivity violation, internal flags leaking to docs.rs) but does not mention the tests/ directory's undeclared-file/under-gated-cfg compile-break described here — different root cause, filed locally as a distinct issue.
Spec
.local/specs/003-test-feature-gate-compile-break/spec.md
Description
crates/rmcp/tests/has 81*.rsfiles but only 39 are declared as[[test]]targets withrequired-featuresincrates/rmcp/Cargo.toml. The other 42 are auto-discovered by Cargo and always get compiled bycargo test -p rmcpregardless of which--featuresare passed, unless the file itself carries a complete internal#![cfg(feature = "...")]gate. This breaks the exact "filter by test name" workflow this repo's own.claude/CLAUDE.mddocuments as the way to run a feature-scoped test subset:Two files are confirmed broken by live reproduction:
test_cancelled_response.rs— no internal cfg gate at all; referencesRoleServer,ServiceExt,service::RequestContext(server-feature-gated).test_stdio_response_concurrency.rs— has#![cfg(not(feature = "local"))], but that gate is incomplete: it callsrmcp::transport::stdio(), gated behindtransport-io, which the existing cfg doesn't cover.A broader audit found 21 of the 42 undeclared files have no internal cfg gate at all, and the remaining 21 have a gate whose completeness hasn't been individually verified (only
test_stdio_response_concurrency.rs's incompleteness is confirmed). Full inventory in the linked spec.Reproduction Steps
main@02c62ae(v3.1.2, no drift as of this cycle):--features request-stateindependently fails on bothtest_stdio_response_concurrency(same error) andtest_cancelled_response(unresolved server-feature-gated symbols) — confirms the pattern, not a one-off.Expected Behavior
cargo test -p rmcp --features "<any valid combo>" <test_name_substring>should either run the matching tests or report 0 matched — never fail to compile because of an unrelated test file outside the requested scope. Every file undercrates/rmcp/tests/should have either a[[test]]/required-featuresdeclaration inCargo.toml(like the other 39 files) or a complete internal cfg gate covering every feature-gated API it references.Actual Behavior
The documented "filter by test name" workflow fails to compile on an unrelated file whenever the passed
--featuresset doesn't happen to satisfy every undeclared/under-gated test file's real requirements.Environment
02c62aeserver,clientand separately withrequest-stateUpstream
No exact duplicate found.
modelcontextprotocol/rust-sdk#1067("Rationalize feature flags for v3.0", open) covers feature-flag naming/design problems (areqwestTLS trap,local's additivity violation, internal flags leaking to docs.rs) but does not mention thetests/directory's undeclared-file/under-gated-cfg compile-break described here — different root cause, filed locally as a distinct issue.Spec
.local/specs/003-test-feature-gate-compile-break/spec.md