Skip to content

layout: compile library tests against the normal rlib - #1097

Merged
reardencode merged 14 commits into
masterfrom
compile/crate-layout
Oct 20, 2026
Merged

reardencode merged 14 commits into
masterfrom
compile/crate-layout

Conversation

@rearden-grok

@rearden-grok rearden-grok Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Each library package has one tests/suite target and [lib] test = false, so cargo test links the dev rlib instead of rebuilding the crate under --cfg test.
  • test-hooks is gone. The same hooks are cfg(debug_assertions), which dev and test builds already share.
  • Initial block download is rbitcoin-ibd. RPC, Electrum, Esplora, and SV2 depend on rbitcoin-net only. The node depends on IBD.
  • rbitcoin-test default scenarios are one suite binary. Overlay stays feature-gated. NODE_COMPACT_FILTERS is advertised per peer hub so one process can run more than one node.

Test plan

  • cargo test --workspace --exclude rbitcoin-bench locally
  • qc, test, windows, macos, and coverage on this PR

Made with Cursor

@rearden-grok
rearden-grok Bot force-pushed the compile/crate-layout branch 3 times, most recently from 44878ba to 04f9de8 Compare October 20, 2026 15:30

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@rearden-grok rearden-grok Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Summary

The compile goal holds. Each library has one tests/suite target and [lib] test = false, so cargo test links the normal rlib. IBD is rbitcoin-ibd; RPC, Electrum, Esplora, and SV2 depend on rbitcoin-net only, and the node still calls the same sync_cancellable arguments. Smoke filters, the journey manifest, and per-hub NODE_COMPACT_FILTERS match that layout. The 89% line-coverage floor matches this run (89.71%, 91583/102091). A 90% floor would still fail.

It is not behavior-equivalent. Twelve tests that exist on e16642338 are absent from the suites (they lived in mod tests blocks the move deleted). Two cfg(test) arms were rewritten as debug_assertions, so a debug node no longer aborts on an undrained io_uring and uses a 2s outbound connect timeout instead of 8s. Eight rbitcoin-test unit tests stay behind #[cfg(test)] and never compile.

Disposition: do not merge until those tests run again and the two debug-node arms match release. The IBD cut, the suite link model, and the 89% floor can stay.

Issue counts by severity

  • bugs: 8
  • suggestions: 2
  • nits: 1

Issues outside the diff

  • [nit] .github/workflows/ci.yml:188 -- The coverage job comment still says "Line-coverage 93% floor". The job runs ./scripts/coverage.sh, whose gate is LH*100 >= LF*89. That comment line is not in this diff. CHANGELOG.md history of the old floor is fine.
    • Suggestion: Say 89% in the workflow comment.

/// `--proxy` turns the DNS seeds into addr-fetch dials by name. The
/// proxy resolves the name, so the node holds no address for it.
#[tokio::test]
async fn proxied_dns_seed_dials_by_name_through_socks() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] accept_retries_a_full_fd_table_and_stops_on_a_dead_listener and shutdown_finishes_without_the_dial_grace are on master in rbitcoin-net/src/service.rs and are not in this suite. The rebase deleted master's mod tests and ported only proxied_dns_seed_dials_by_name_through_socks.

Suggestion: Move both tests into tests/service.rs with the same assertions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Both tests are back in tests/service.rs. accept_error_ends_listen is public so the suite can call it. The fd-table cases and the shutdown deadline match master.

/// back to the tip's own time, and a coin median is not
/// `bad-txns-nonfinal`.
#[test]
fn check_block_proposal_reads_medians_from_confirmed_headers() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] reconsider_skips_a_branch_that_fails (master chain.rs, from net: reconsiderblock activates the most-work chain) is not in tests/chain.rs. The median proposal test was ported; this one was not.

Suggestion: Move the test into tests/chain.rs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

reconsider_skips_a_branch_that_fails is in tests/chain.rs again, including the invalid branch and the store-fault arm.

}

#[test]
fn pending_sendcmpct_from_u8_maps_wire_payload() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] external_ip_uses_the_clearnet_bogon_filter (master peers.rs, from the CJDNS/bogon self-announce change) is not in tests/peers.rs.

Suggestion: Move the test into tests/peers.rs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

external_ip_uses_the_clearnet_bogon_filter is in tests/peers.rs. It still rejects CGNAT, documentation, and benchmark ranges, and it still allows 1.2.3.4.

@@ -0,0 +1,10 @@
#![allow(unused_imports, dead_code, unused_variables)]
mod accept;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] Seven master tests in rbitcoin-mempool/src/accept.rs are absent: promote_keeps_the_announcer_of_a_multi_parent_orphan, disconnect_while_the_orphan_is_out_is_not_reparked, older_promote_forget_does_not_clear_a_newer_take, package_lift_disconnect_is_not_reparked, package_admit_drops_the_inflight_row, package_rollback_admit_drops_the_inflight_row, and package_rollback_reject_drops_the_inflight_row. Name diff of every #[test] on e16642338 vs this head is 3003 vs 2991 (twelve missing, zero new).

Suggestion: Move the seven into tests/accept.rs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

All seven accept tests are in tests/accept.rs with the same assertions, including the in-flight announcer checks.

mod inhibit;
mod lock;
mod regtest_rpc;
mod run;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] max_run_deadline_wakes_without_the_perf_tick (master rbitcoin-node/src/run.rs) is not in tests/run.rs.

Suggestion: Move the tokio test into tests/run.rs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

max_run_deadline_wakes_without_the_perf_tick is in tests/run.rs. A 40ms deadline still returns Stop in under 200ms.

let thread = std::thread::current();
let thread = thread.name().unwrap_or("unnamed");
let reason = format!("drain hard cap pending={pending} thread={thread}");
#[cfg(test)]
#[cfg(debug_assertions)]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] finish_drain_hard_cap used to abort outside cfg(test) and return StoreError::Corrupt("invariant: io_uring undrained") only under cfg(test). It now returns that error for every debug_assertions build and aborts only in release. drop_drain and inflight_enter_failure call it. A debug node no longer aborts when SQEs still own caller buffers. The comment above still says abort outside tests.

Suggestion: Abort on every build except an explicit test override. Do not treat debug_assertions as cfg(test) here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

finish_drain_hard_cap aborts again on a debug node. The suite still sees the Corrupt error, but only inside with_drain_hard_cap. A normal debug build never sets that hook.

Comment thread crates/rbitcoin-net/src/service.rs Outdated
pub const OUTBOUND_CONNECT_TIMEOUT: Duration = Duration::from_secs(8);
#[cfg(debug_assertions)]
#[doc(hidden)]
pub const OUTBOUND_CONNECT_TIMEOUT: Duration = Duration::from_secs(2);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] OUTBOUND_CONNECT_TIMEOUT was 8s under cfg(not(test)) and 2s only under cfg(test). The rlib, including a debug node and integration tests, used 8s. It is now 2s whenever debug_assertions is on, and prepare_outbound_session passes it to every outbound dial. The comment still says the bound is 8s. Release stays 8s.

Suggestion: Keep 8s in the rlib. If the suite needs 2s, arm that from a hook the test sets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OUTBOUND_CONNECT_TIMEOUT is 8 seconds in every build, including debug. The short redial interval is unchanged. outbound_connect_timeout_is_eight_seconds pins the constant.

@@ -11,17 +11,19 @@ autotests = false

[lib]
doctest = false
test = false

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] [lib] test = false means cargo test --test suite never compiles #[cfg(test)] inside this library. These tests were not moved: jsonrpc.rs (try_jsonrpc_returns_the_connect_error, try_jsonrpc_panics_when_the_body_is_not_json), mine.rs (bip34_and_coinbase_height_zero_and_pow, mine_regtest_block_keeps_fixed_coinbase_and_skips_witness_commitment), overlay.rs (jsonrpc_try_panics_when_the_body_is_not_json, i2p_b32_rejects_unknown_base64, i2p_b32_rejects_a_short_destination, i2p_b32_matches_the_address_host). They still exist only under #[cfg(test)].

Suggestion: Move them into the suite (overlay's own [[test]] for the overlay ones) and delete the #[cfg(test)] blocks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The jsonrpc and mine tests now run in the default suite. The four overlay helper tests run in the overlay test binary, which is what compiles that module. i2p_b32_matches_the_address_host builds the same 387-byte destination as the net test and encodes it with the I2P alphabet. The old standard-base64 literal no longer parses.

@@ -65,7 +73,7 @@ pub fn inclusive_u8x8_times_8(st: &[u8; 8], no: &[u8; 8]) -> ([u32; 8], [u32; 8]
/// # Safety
/// `p` must be readable for 16 bytes.
#[cfg(target_arch = "x86_64")]
unsafe fn sse2_deinterleave_pairs_u8x8(p: *const u8) -> ([u8; 8], [u8; 8], bool) {
pub unsafe fn sse2_deinterleave_pairs_u8x8(p: *const u8) -> ([u8; 8], [u8; 8], bool) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[suggestion] sse2_deinterleave_pairs_u8x8 and the sibling SIMD helpers were private and are now pub unsafe with no #[doc(hidden)]. Call sites are unchanged, so node behavior is the same, but the crate surface now exports the raw pointers. The scalar twins stay #[doc(hidden)].

Suggestion: Keep them private, or #[doc(hidden)] pub if the suite must call them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The four SIMD helpers are private again. Only loc_simd.rs calls them.

@@ -12,14 +12,14 @@ if ! command -v cargo >/dev/null 2>&1; then
fi

echo "== structure, header, finality, sigops =="
cargo test -p rbitcoin-consensus --lib -- \
cargo test -p rbitcoin-consensus --test suite -- \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[suggestion] The consensus command filters structure_rule_tests and assemble_second_block_rejects_stale_nversion, which are not in rbitcoin-consensus. They live in the query suite. Libtest ORs filters, and the other three names match, so the script prints hornet-mapped pins OK without running those two. The same miss existed at the base under --lib. This edit only swapped --lib for --test suite.

Suggestion: Run those two filters as cargo test -p rbitcoin-query --test suite.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The script now runs structure_rule_tests and assemble_second_block_rejects_stale_nversion in the query suite. The other three filters stay on consensus.

@rearden-grok rearden-grok Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Summary

Follow-up from the test-move equivalence pass, after the first comment review. Three moved tests are still present but weaker than master. The twelve deleted tests and the two debug_assertions behavior bugs in that review stand.

Short debug redial (250 ms), I2P SAM retry (50 ms), and SV2 constraints cooldown (100 ms) are the intended debug_assertions intervals. run_p2p already warns about those three. They are not additional bugs. The io_uring abort and the 8 s outbound connect timeout are.

Disposition is unchanged: do not merge until the deleted tests run again, these three assertions are restored, and the two debug-node arms match release.

Issue counts by severity

  • bugs: 3
  • suggestions: 0
  • nits: 0

}
let accepted = hub
.accept_package(&[parent.clone(), child.clone()])
.expect("hub package contains the parked child");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] hub_package_admits_its_parked_child no longer calls add_orphan_announcer before accept_package, and it no longer asserts orphanage.has_announcer(4) is false after admit. Master locked both: "the parked child takes the peer" and "admitting the lifted child must drop its in-flight peer". No other test in this file keeps those two strings. This is the hub-level twin of the deleted package_admit_drops_the_inflight_row case.

Suggestion: Restore both announcer assertions around this accept_package call.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

hub_package_admits_its_parked_child again checks that the parked child takes peer 4 and that admit drops that announcer.

assert_eq!(
side_status(&hub).as_deref(),
Some("valid-headers"),
"a held side block outranks a header-only label"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] After this valid-headers check, master called hub.reconsider_block(side.block_hash()) and asserted the status stayed "valid-headers" ("a block that never connected is not a valid fork after reconsider"). That call and assert are gone. Other reconsider_block calls remain in this file. reconsider_skips_a_branch_that_fails is still missing entirely, as the first review said.

Suggestion: Put the reconsider status assert back here, and restore reconsider_skips_a_branch_that_fails.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The reconsider of the never-connected side block is back, and the status stays valid-headers. reconsider_skips_a_branch_that_fails is restored in the same file.

.as_nanos();
let dir = std::env::temp_dir().join(format!("rbitcoin-node-signet-gen-{n}"));
std::fs::create_dir_all(&dir).unwrap();
let params = ChainParams::custom_signet(ScriptBuf::from_bytes(vec![0x51]), 10 * 60).unwrap();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] hub_op_true_signet_generate_one used to start from ChainParams::regtest() with signet_challenge = Some(OP_TRUE) and assert the mined tip bits equal REGTEST_POW_BITS ("the signet miner must grind the parent target, which is regtest here"). It now uses ChainParams::custom_signet, which is signet network parameters and a signet PoW limit, and only checks that the tip height becomes 1. signet_challenge is still a public field and REGTEST_POW_BITS still exists, so the rewrite was not forced by an API removal.

Suggestion: Keep the regtest-plus-challenge setup and the bits assertion from master.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The test is back on regtest params with an OP_TRUE signet challenge, and it again checks that the mined bits equal REGTEST_POW_BITS.

@rearden-grok

rearden-grok Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

The coverage job comment in .github/workflows/ci.yml now says 89%. That line was not in the diff, so this is the reply for that note.

@rearden-grok rearden-grok Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Summary

Re-review of ac0d77c0d against e16642338 in four passes: equivalence, goal completeness, safety, and production performance.

Release behavior matches master. Outbound connect stays 8s in every build. An undrained io_uring drain still aborts unless the thread is inside with_drain_hard_cap. Debug builds only shorten the three known intervals (redial 250 ms, SAM retry 50 ms, SV2 cooldown 100 ms). cargo tree -p rbitcoin-node shows rbitcoin-consensus with no features, so the corpus assembler stays out of the node. The consensus suite runs under cargo test --workspace, and after this commit its CRAP set is clean. IBD moved as one crate, so per-header #[inline] helpers did not become cross-crate calls. Release confirm, script, store, mempool accept, and dial match master. No production runtime regression.

The suite-on-rlib layout, the IBD split, the 89% floor, and the overlay feature gate match the goals. On this commit the line gate passed at 91.26% (93410/102361). Coverage is still red: Dialer::connect_isolated_net is the only function over the CRAP 30 gate (43.2).

Two tests that ran in the default suite on master are no longer selected. One Electrum file was already outside the module tree and is still unwired. Two #[cfg(test)] copies can no longer compile. One doc command names a test target that is now only a suite filter.

Issue counts by severity

  • bugs: 4
  • suggestions: 2
  • nits: 1

&self,
addr: crate::NetAddr,
) -> Result<TcpStream, NetError> {
pub async fn connect_isolated_net(&self, addr: crate::NetAddr) -> Result<TcpStream, NetError> {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] Coverage on ac0d77c0d passes the 89% line gate at 91.26% (93410/102361) and then fails CRAP. The only function over 30 is Dialer::connect_isolated_net (CRAP 43.2, complexity 9). The body matches master aside from pub(crate) becoming pub. The only production caller is still ephemeral.rs. Nothing in the suite calls this method; the socks tests call dial_isolated. The onion, i2p, and cjdns arms stay dark, which is enough to push CRAP from under 30 on master to 43.2 once the suite links the normal rlib.

Suggestion: Exercise the NetAddr arms through the ephemeral caller (IP, onion with and without SOCKS, i2p, cjdns) from the net suite. Do not add the function to .cargo-crap.toml. A test whose only job is to move the CRAP input is not the fix.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Isolated broadcast now drives the onion and i2p refusals through send_tx_isolated. The same test also dials a clearnet address, an onion host through SOCKS, and a cjdns address to a local listener. Those are the arms connect_isolated_net has. It is not on the CRAP allowlist.

use std::path::{Path, PathBuf};

#[test]
fn legacy_names_rename_and_both_exist_errors() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] legacy_names_rename_and_both_exist_errors ran on master inside the library #[cfg(test)] module. It is now the only test in this file, and tests/store/mod.rs never declares mod legacy_rename_tests. With autotests = false and [lib] test = false, cargo test --workspace does not compile this file. The open-path renames still run. The "both exist" StoreError::Layout assert does not.

Suggestion: Add mod legacy_rename_tests; to tests/store/mod.rs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

legacy_names_rename_and_both_exist_errors is a module of the store suite again. It still renames the legacy stems and still returns StoreError::Layout when both the old and new files exist.

Comment thread crates/rbitcoin-test/tests/overlay.rs Outdated

#[test]
#[should_panic(expected = "i2p destination base64 contains")]
fn i2p_b32_rejects_unknown_base64() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] i2p_b32_rejects_unknown_base64, i2p_b32_rejects_a_short_destination, and i2p_b32_matches_the_address_host were #[cfg(test)] tests on the rbitcoin-test library, so cargo test --workspace ran them. They now live only in tests/overlay.rs, whose [[test]] has required-features = ["overlay"]. That feature is not default, and i2p_b32_from_dest itself sits behind #[cfg(feature = "overlay")]. Default CI therefore skips the unknown-base64 panic, the short-destination panic, and the 387-byte identity host assert.

Suggestion: Move i2p_b32_from_dest and these three tests onto the default suite. Leave the live Tor, i2p, and cjdns journeys on the overlay target. Linking the tests from suite.rs without moving the helper will not compile.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The three i2p b32 checks run in the default suite. i2p_b32_from_dest moved out of the overlay feature so they compile without it. The live Tor, i2p, and cjdns journeys stay on the overlay target. The host assert is unchanged.

@@ -328,7 +337,8 @@ fn connect_script_block(
/// `from_height` above 0 is that window and is served above the create cap.
/// Open history, and a window that still starts at height 0, stay capped.
#[test]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[bug] from_height_window_is_served_above_the_create_cap, from_height_ignores_a_spend_of_another_output, and electrum_sh_join live in this file. src/lib.rs does not declare the module, and no tests file includes it, so they never compile. This was already true on the base. This PR made the items pub and #[doc(hidden)] and still did not attach the file. The coverage job lists this file as analyzed source with no LCOV entry. tests/server covers a smaller from_height parser, not these three journeys.

Suggestion: include! the file from the electrum suite, or delete it if those pins are intentionally dropped.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

electrum_sh_journey.rs is part of the electrum suite now. The from_height window, the spend of another output, and the join journey all run. The file is no longer a source module the suite never included.

Comment thread crates/rbitcoin-store/src/store.rs Outdated
@@ -2130,7 +2140,7 @@ fn check_meta(dir: &Path) -> Result<u16, StoreError> {
}

/// One wipe-and-IBD line for every store `meta` older than schema 22.
const PRE22_WIPE: &str = "schema before 22 refuses this datadir; wipe datadir and redo IBD";
pub const PRE22_WIPE: &str = "schema before 22 refuses this datadir; wipe datadir and redo IBD";

#[cfg(test)]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[suggestion] [lib] test = false strips #[cfg(test)] mod tests here and the same module in crates/rbitcoin-node/src/config.rs (line 1663). The function names match the suite copies, so the live tests still run. Rustc and clippy do not typecheck these copies, so they can rot beside the suite.

Suggestion: Delete both #[cfg(test)] modules. Keep the tests/ copies.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The cfg(test) copies in store.rs and config.rs are gone. The suite already had the same cases, and those are the ones that compile. Nothing those modules tested was dropped.

Comment thread docs/consensus-tests.md Outdated
cargo test --manifest-path script-oracle/Cargo.toml --quiet
cargo test -p rbitcoin-consensus --lib block_866342 -- --nocapture
cargo test -p rbitcoin-consensus --test suite block_866342 -- --nocapture
cargo test -p rbitcoin-consensus --test script_edge_fixtures

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[suggestion] cargo test -p rbitcoin-consensus --test script_edge_fixtures is not a target. The only consensus [[test]] is suite. script_edge_fixtures is a module of that suite. The other commands in this block already use --test suite. An operator following this line gets "no test target" and does not run that subset.

Suggestion: Change the line to cargo test -p rbitcoin-consensus --test suite script_edge.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That line is now cargo test -p rbitcoin-consensus --test suite script_edge. script_edge_fixtures is a filter of the suite, not its own target.

Comment thread changelog.d/crate-layout-compile.md Outdated
@@ -0,0 +1,4 @@
Changed

- **Library tests compile against the normal rlib.** Each library package has one `tests/suite` target (`[lib] test = false`), so `cargo test` no longer rebuilds the crate under `--cfg test`. `test-hooks` is gone. Hooks a test arms stay `cfg(debug_assertions)`. A debug node still uses the 8 s outbound connect timeout and still aborts when an io_uring drain leaves SQEs. Initial block download is `rbitcoin-ibd`, and RPC, Electrum, Esplora, and SV2 do not depend on it. The consensus suite is the package's default `corpus` feature (the Core script assembler). Product crates depend on consensus with `default-features = false`, so a node build leaves that assembler out. `rbitcoin-test`'s default scenarios are one `suite` binary; `overlay` stays feature-gated. `NODE_COMPACT_FILTERS` is advertised per peer hub, so one process can run more than one node.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[nit] The fragment says each library package has one tests/suite and [lib] test = false. rbitcoin-bench still has #[cfg(test)] modules under src/ and no suite target. CI still runs cargo test -p rbitcoin-bench --lib, which is intentional. rbitcoin-ibd sets test = false but not doctest = false. It has no doc-test fences, so the extra harness is empty.

Suggestion: Name bench as the remaining --lib crate, and set doctest = false on rbitcoin-ibd or narrow the sentence.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The note now says bench is the library that still tests with --lib, and rbitcoin-ibd sets doctest = false like the other libraries. The floor in that note is 91%. The last full run measured 91.26% (93410/102361), and the unrounded gate still leaves room for the usual line jitter.

Comment thread crates/rbitcoin-esplora/tests/handlers/pure_helper_tests.rs Dismissed
Comment thread crates/rbitcoin-esplora/tests/tx_json.rs Dismissed
Comment thread crates/rbitcoin-esplora/tests/tx_json.rs Dismissed
Comment thread crates/rbitcoin-esplora/tests/tx_json.rs Dismissed
Comment thread crates/rbitcoin-esplora/tests/tx_json.rs Dismissed
Comment thread crates/rbitcoin-esplora/tests/tx_json.rs Dismissed
Comment thread crates/rbitcoin-esplora/tests/tx_json.rs Dismissed
Comment thread crates/rbitcoin-ibd/tests/ibd/archive/class_a_rehydrate_tests.rs Dismissed
Comment thread crates/rbitcoin-net/tests/peer/mod.rs Dismissed
Comment thread crates/rbitcoin-net/tests/peers.rs Dismissed
reardencode and others added 14 commits October 20, 2026 10:02
Move each library's tests into one suite target so cargo test links the
dev rlib, and split initial block download into rbitcoin-ibd so RPC and
Electrum do not build it.

Co-authored-by: Cursor <cursoragent@cursor.com>
The suite target dropped the inner tests module, and rbitcoin-test
compiles its journeys from suite.rs. The old paths failed qc and the
Windows smoke.
Suite targets compile the normal rlib, so doc(hidden) items are public
to clippy. Add is_empty and Default, allow the () sentinels callers
already map to a miss, and drop the test-hooks dev-deps. Those hooks
are debug_assertions items on the rlib, and the features are gone.
Suite tests link the normal rlib, so cfg(test) lines leave the production
LCOV. This run is 89.71% (91583/102091), short of 90%. 89% still clears
with about 720 lines of jitter room.
Twelve master tests never landed in the suite, and three moved tests lost assertions. The rbitcoin-test helper tests now compile in the suite and the overlay binary.
Mapping cfg(test) onto debug_assertions made a debug node dial with a 2s connect timeout and return from an undrained io_uring instead of aborting. The suite still observes that error inside with_drain_hard_cap.
structure_rule_tests and the stale-nversion pin live in the query suite. The coverage job comment matches the 89% floor.
The suite needs the corpus feature, so workspace test skipped it.
Script lines then scored as uncovered and the CRAP gate failed.
corpus is the consensus package default. Product crates keep
default-features off, so a node build still omits the assembler.
send_tx_isolated refuses onion without SOCKS and i2p without SAM.
connect_isolated_net also dials a clearnet address, an onion host
through SOCKS, and a cjdns address.
The both-exist layout error is part of the store suite again.
The cfg(test) modules in store and node config no longer compile, and
the suite already has those cases.
i2p_b32_from_dest is no longer behind the overlay feature. The three
host checks run with cargo test. Live mesh journeys stay on overlay.
The from_height window, the other-output spend, and the join scenario
compile in the electrum suite. They were a source file the suite never
included.
script_edge_fixtures is a module of the suite target, not its own
cargo test binary.
The suite-on-rlib run measured 91.26% (93410/102361). The gate stays
unrounded LH*100 >= LF*91, which still leaves room for llvm-cov jitter.
rbitcoin-ibd turns doctests off. Bench remains the --lib exception.
@rearden-grok
rearden-grok Bot force-pushed the compile/crate-layout branch from 042c6b1 to 351591d Compare October 20, 2026 17:03

@rearden-grok rearden-grok Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Summary

Ready to merge. Head 351591d75 is mergeable onto d850f041d. Required checks on that commit are green: qc, test, windows, macos, and coverage.

This pass checked that every issue from the earlier reviews is still fixed after the rebase onto the empty catch-up pool RPC change. No new issue.

Disposition

Closed:

  • Isolated dial coverage. connect_isolated_net_dials_ip_and_onion_and_rejects_the_rest drives onion and i2p refusals through send_tx_isolated, and dials clearnet, onion-via-SOCKS, and cjdns. The function is not on the CRAP allowlist. Coverage on this commit passed, so that gate is clear.
  • Legacy rename. legacy_names_rename_and_both_exist_errors is mod legacy_rename_tests in the store suite.
  • I2P b32 checks. They live in rbitcoin-test's default suite. i2p_b32_from_dest is no longer behind the overlay feature. Live mesh journeys stay on overlay.
  • Electrum scripthash journey. electrum_sh_journey is a module of the electrum suite.
  • Dead #[cfg(test)] copies in store.rs and config.rs are gone.
  • docs/consensus-tests.md runs script_edge as a suite filter.
  • Line-coverage floor is 91% (FLOOR_PCT = 91). The changelog names bench as the remaining --lib crate, and rbitcoin-ibd sets doctest = false.
  • Earlier fixes still hold: outbound connect is 8s in every build, an undrained io_uring drain aborts unless the thread is inside with_drain_hard_cap, and the short redial, SAM retry, and SV2 cooldown stay debug-only (compiled_with_test_hooks is cfg!(debug_assertions)).
  • The rebase kept the master behavior that an empty catch-up pool is served. relay_off_empty_mempool_is_listed, relay_off_empty_pool_serves_template, and blocksonly_lists_mempool_mines_and_refuses_template are in the RPC suite.

Not a merge blocker:

  • The three high CodeQL uncontrolled-allocation-size alerts on reconstruct.rs (329, 330, 331) are false positives. Each with_capacity uses the length of records already loaded from this node's store. Dismiss them. The cleartext-logging hits in test files are the same codec-name false positive already dismissed elsewhere.

Issue counts by severity

  • bugs: 0
  • suggestions: 0
  • nits: 0

@reardencode
reardencode merged commit a953d8c into master Oct 20, 2026
18 checks passed
@rearden-grok
rearden-grok Bot deleted the compile/crate-layout branch October 20, 2026 17:52
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
#1097 mapped cfg(test) onto cfg(debug_assertions). Two of those gates
landed on items production code also uses, so `cargo check --release`
failed in rbitcoin-store (lib) and, once that was patched, rbitcoin-query:

- scripthash_head.rs gated `use crate::open_address::{self, MAX_LOAD_DEN,
  MAX_LOAD_NUM}` while `hash_slot` and the bulk-fill load cap use it.
- confirm_run/mod.rs re-exported `expected_bits_extending` and
  `ensure_spend_abs_layouts`, both debug-only, from ungated `pub use`.

No PR job compiles the release profile; release.yml and nix do. `qc` now
runs `cargo check --release --workspace --exclude rbitcoin-bench` after
clippy, and coverage.test.sh pins that step the way it pins the test
job's commands.
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
Every tests/suite.rs opened with
`#![allow(unused_imports, dead_code, unused_variables)]`, which switched
the compiler's warnings off for all test code. With the allow gone the
workspace reported ~2000 unused imports (all from the src/ -> tests/ move;
`cargo fix` removed them), ~20 unused trait imports (by hand), and one
dead helper: the `RBITCOIN_BLOCK_QUEUE_*` env lock in ibd/assign.rs,
which #1097 replaced with a config field. No unused variables.

Imports used only inside a Windows or Darwin cfg block were checked by
hand; none were removed.

Co-authored-by: Cursor <cursoragent@cursor.com>
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
…out move

#1097 set the floor to 89 and then 91; the badge kept `--gate 89` in
coverage.sh and as the coverage-badge.py default, so a run between 89
and 91 would draw a passing badge on a failing gate. coverage.test.sh
now reads FLOOR_PCT from coverage-gate.py and pins both to it.

The IGNORE regex fixtures in coverage.test.sh name current files
(tests/ and rbitcoin-ibd) instead of the src/*_tests.rs they described
before the move. docs/concurrency.md links perf_log.rs where it lives
now. Five rustdoc links to ChainHub and IndexMode, which rpc and node
cannot resolve since IBD moved to rbitcoin-ibd, are plain code spans.

Co-authored-by: Cursor <cursoragent@cursor.com>
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
…in hooks

After #1097 the suite reaches internals through `#[doc(hidden)] pub` and
test hooks are `cfg(debug_assertions)`, but CONTRIBUTING principle 11
still said to drop to `pub(crate)`, that `-D warnings` would report dead
`pub`, and that a `cfg(test)` hook is a smell. The rule now states the
convention and its two limits: a hook is off until a test arms it, and a
debug gate never covers an import production code uses (the release
check in `qc` pins that). code-shape points at it from the lint section
and notes suite roots carry no blanket allow. TESTING.md records that
the suites build in dev/test only. rbitcoin-ibd gets the AGENTS.md the
other crates have.

Co-authored-by: Cursor <cursoragent@cursor.com>
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
#1097 mapped cfg(test) onto cfg(debug_assertions). Two of those gates
landed on items production code also uses, so `cargo check --release`
failed in rbitcoin-store (lib) and, once that was patched, rbitcoin-query:

- scripthash_head.rs gated `use crate::open_address::{self, MAX_LOAD_DEN,
  MAX_LOAD_NUM}` while `hash_slot` and the bulk-fill load cap use it.
- confirm_run/mod.rs re-exported `expected_bits_extending` and
  `ensure_spend_abs_layouts`, both debug-only, from ungated `pub use`.

No PR job compiles the release profile; release.yml and nix do. `qc` now
runs `cargo check --release --workspace --exclude rbitcoin-bench` after
clippy, and coverage.test.sh pins that step the way it pins the test
job's commands.
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
Every tests/suite.rs opened with
`#![allow(unused_imports, dead_code, unused_variables)]`, which switched
the compiler's warnings off for all test code. With the allow gone the
workspace reported ~2000 unused imports (all from the src/ -> tests/ move;
`cargo fix` removed them), ~20 unused trait imports (by hand), and one
dead helper: the `RBITCOIN_BLOCK_QUEUE_*` env lock in ibd/assign.rs,
which #1097 replaced with a config field. No unused variables.

Imports used only inside a Windows or Darwin cfg block were checked by
hand; none were removed.

Co-authored-by: Cursor <cursoragent@cursor.com>
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
…out move

#1097 set the floor to 89 and then 91; the badge kept `--gate 89` in
coverage.sh and as the coverage-badge.py default, so a run between 89
and 91 would draw a passing badge on a failing gate. coverage.test.sh
now reads FLOOR_PCT from coverage-gate.py and pins both to it.

The IGNORE regex fixtures in coverage.test.sh name current files
(tests/ and rbitcoin-ibd) instead of the src/*_tests.rs they described
before the move. docs/concurrency.md links perf_log.rs where it lives
now. Five rustdoc links to ChainHub and IndexMode, which rpc and node
cannot resolve since IBD moved to rbitcoin-ibd, are plain code spans.

Co-authored-by: Cursor <cursoragent@cursor.com>
rearden-grok Bot added a commit that referenced this pull request Oct 20, 2026
…in hooks

After #1097 the suite reaches internals through `#[doc(hidden)] pub` and
test hooks are `cfg(debug_assertions)`, but CONTRIBUTING principle 11
still said to drop to `pub(crate)`, that `-D warnings` would report dead
`pub`, and that a `cfg(test)` hook is a smell. The rule now states the
convention and its two limits: a hook is off until a test arms it, and a
debug gate never covers an import production code uses (the release
check in `qc` pins that). code-shape points at it from the lint section
and notes suite roots carry no blanket allow. TESTING.md records that
the suites build in dev/test only. rbitcoin-ibd gets the AGENTS.md the
other crates have.

Co-authored-by: Cursor <cursoragent@cursor.com>
reardencode added a commit that referenced this pull request Oct 20, 2026
fix: release build, opt-in spindle trace, suite lint after the #1097 layout move
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants