Skip to content

refactor(consensus): introduce a builder pattern for dependencies in consensus' unit tests - #11064

Open
pierugo-dfinity wants to merge 29 commits into
masterfrom
pierugo/subnet-splitting/deps-builder
Open

refactor(consensus): introduce a builder pattern for dependencies in consensus' unit tests#11064
pierugo-dfinity wants to merge 29 commits into
masterfrom
pierugo/subnet-splitting/deps-builder

Conversation

@pierugo-dfinity

@pierugo-dfinity pierugo-dfinity commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Consensus' (fake) dependencies in unit tests are built with functions like dependencies, dependencies_with_subnet_params, or dependencies_with_subnet_records_with_raw_state_manager that live in ic-consensus-mocks. Each time a developer wants to consistently modify a dependency, they should add such a function and then wire it through the others. This becomes hard to maintain and a Builder pattern is more than appropriate for this use-case. This PR removes these functions and replaces all call sites to build their dependencies through the builder. The relation is as follows:

  • Old dependencies_with_subnet_params(...) becomes DependenciesBuilder::single_subnet(...).build()
  • Old dependencies(...) becomes DependenciesBuilder::new(...).build(), which is a simple shortcut to single_subnet
  • Old dependencies_with_subnet_records_with_raw_state_manager(...) becomes DependenciesBuilder::single_subnet(...).without_mocked_state_manager().build()

The two above constructors then fall down to the multiple_subnets constructor, which is for now otherwise unused (as Consensus usually stays scoped only to a single subnet) but will soon be for incoming subnet-splitting unit tests.

One particularly frequent setup is

let committee: Vec<_> = (0..no_nodes).map(node_test_id).collect();
dependencies_with_subnet_params(
    pool_config,
    subnet_test_id(0),
    vec![(
        1,
        SubnetRecordBuilder::from(&committee)
            .with_dkg_interval_length(interval_length)
            .build(),
    )],
);

which uses ...with_subnet_params only just to modify the DKG interval length. DependenciesBuilder thus provides .with_dkg_interval_length such that such a setup boils down to a simple

DependenciesBuilder::new(pool_config, no_nodes)
    .with_dkg_interval_length(interval_length)
    .build()

I replaced such setups with this even when the subnet was not subnet_test_id(0) or the initial registry version was not 1 when it clearly did not matter. Otherwise, I kept them intact.

pierugo-dfinity and others added 16 commits August 7, 2026 08:59
Adds a builder for the consensus test Dependencies fixture with three
constructors: new(pool_config, nodes), single_subnet(pool_config,
subnet_id, records) and multiple_subnets(pool_config, records) — the
latter supporting multiple subnets in the registry, as needed by
subnet-splitting tests. The state manager is mocked by default and can
be opted out via without_mocked_state_manager(). The legacy
dependencies* functions are retargeted as thin wrappers and will be
removed once all call sites are migrated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sensus tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nsensus-mocks

All call sites have been migrated to DependenciesBuilder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…_dkg_interval_length to consensus test Dependencies

Dependencies now provides a bare RefMockPayloadBuilder and
RefMockMessageRouting (no pre-armed expectations), so tests no longer
need to construct these mocks themselves. DependenciesBuilder gains
with_dkg_interval_length(u64), which sets the DKG interval length on
every subnet record passed to the builder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ests

Dependencies now carries the mocked payload builder and message
routing, so the wrapper struct and its setup helpers are replaced by
direct DependenciesBuilder chains plus a make_validator helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h in ic-consensus tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h in ic-consensus-utils tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…h in ic-consensus-dkg tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… tests

Collapses the repeated build-deps / make_validator / destructure
boilerplate at the 21 test sites that use the default 4-node subnet
with DKG interval length 9. Non-default sites keep building their own
dependencies and calling make_validator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pierugo-dfinity and others added 13 commits August 7, 2026 12:22
…t subnet records in ic-consensus tests

Where tests pass custom SubnetRecords to DependenciesBuilder
(non-default subnet id, registry version, or membership), setting the
DKG interval length via the DependenciesBuilder would silently modify
the records built just above. Keep it on the SubnetRecordBuilder there;
only DependenciesBuilder::new sites use the builder-level setter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t subnet records in ic-consensus-dkg tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ngle_subnet sites in ic-consensus tests

share_aggregator and block_maker built default records for
subnet_test_id(0) at registry version 1 only to set the DKG interval
length, which DependenciesBuilder::new supports directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ngle_subnet sites in ic-consensus-dkg tests

These sites passed a custom subnet id (222, 1) or initial registry
version (10, 5) that the tests never rely on: the version is consumed
only through registry.get_latest_version(), and the subnet id never
reaches an assertion or registry key (no consensus code special-cases
the root subnet). Normalize them to the DependenciesBuilder::new
defaults. In test_validate_payload the ValidationContext registry
version is updated together with the record version (5 -> 1).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pierugo-dfinity

Copy link
Copy Markdown
Contributor Author

@frankdavid Maybe this PR could be of interest to you, following our discussion

@pierugo-dfinity
pierugo-dfinity marked this pull request as ready for review August 7, 2026 17:02
@pierugo-dfinity
pierugo-dfinity requested a review from a team as a code owner August 7, 2026 17:02
@zeropath-ai

zeropath-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to ff2d309.

Security Overview
Detected Code Changes

The diff is too large to display a summary of code changes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors consensus-related unit tests and benchmarks to replace a set of ad-hoc dependency-construction helpers from ic-consensus-mocks with a DependenciesBuilder (including support for common tweaks like DKG interval length and opting out of mocked state manager behavior). It also extends the shared Dependencies test fixture to bundle additional commonly-used mocks.

Changes:

  • Introduces DependenciesBuilder in ic-consensus-mocks and removes the old dependencies* helper functions in favor of builder-based construction.
  • Updates consensus / idkg / dkg / https-outcalls tests and benches to build dependencies via DependenciesBuilder APIs.
  • Expands the shared Dependencies fixture to include reusable payload_builder and message_routing mocks.

Reviewed changes

Copilot reviewed 35 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rs/https_outcalls/consensus/src/pool_manager.rs Updates unit tests to construct consensus mocks via DependenciesBuilder.
rs/https_outcalls/consensus/src/payload_builder/tests.rs Replaces old dependency helpers with DependenciesBuilder::single_subnet(...).build().
rs/https_outcalls/consensus/benches/payload_validation.rs Migrates benchmark setup to use DependenciesBuilder.
rs/consensus/utils/src/pool_reader.rs Refactors tests to use DependenciesBuilder and builder helpers (e.g. DKG interval).
rs/consensus/utils/src/lib.rs Updates tests to use DependenciesBuilder instead of dependencies(...).
rs/consensus/src/consensus/validator.rs Refactors extensive test harness to a local builder wrapping DependenciesBuilder and centralizes DKG interval constant.
rs/consensus/src/consensus/status.rs Updates tests to use DependenciesBuilder::single_subnet(...).build().
rs/consensus/src/consensus/share_aggregator.rs Replaces old dependency helpers with DependenciesBuilder.
rs/consensus/src/consensus/random_tape_maker.rs Updates tests to use DependenciesBuilder.
rs/consensus/src/consensus/random_beacon_maker.rs Updates tests to use DependenciesBuilder.
rs/consensus/src/consensus/purger.rs Updates tests to use DependenciesBuilder and shared message_routing mock from Dependencies.
rs/consensus/src/consensus/proptests.rs Migrates proptests to builder-based dependency setup.
rs/consensus/src/consensus/priority.rs Refactors tests to use DependenciesBuilder (including DKG interval customization).
rs/consensus/src/consensus/payload_builder.rs Updates payload builder tests to use DependenciesBuilder.
rs/consensus/src/consensus/notary.rs Migrates tests to DependenciesBuilder (including DKG interval customization).
rs/consensus/src/consensus/finalizer.rs Updates tests to use DependenciesBuilder::new/single_subnet.
rs/consensus/src/consensus/catchup_package_maker.rs Updates tests to use DependenciesBuilder, including .without_mocked_state_manager().
rs/consensus/src/consensus/bounds.rs Refactors pool-bounds test setup to use DependenciesBuilder.
rs/consensus/src/consensus/block_maker.rs Updates tests to use DependenciesBuilder and the shared payload_builder from Dependencies.
rs/consensus/src/consensus.rs Updates consensus tests to build dependencies via DependenciesBuilder::single_subnet(...).build().
rs/consensus/mocks/src/lib.rs Introduces DependenciesBuilder, removes old helper constructors, and extends Dependencies with shared mocks.
rs/consensus/mocks/Cargo.toml Adds ic-interfaces-mocks dependency for shared message_routing mock wrapper.
rs/consensus/mocks/BUILD.bazel Adds Bazel dep on //rs/interfaces/mocks for new mocks usage.
rs/consensus/idkg/src/utils.rs Updates tests to use DependenciesBuilder.
rs/consensus/idkg/src/test_utils.rs Updates test utility builders to use DependenciesBuilder.
rs/consensus/idkg/src/payload_builder/pre_signatures.rs Migrates tests from dependencies(...) to DependenciesBuilder.
rs/consensus/idkg/src/payload_builder.rs Updates tests to use DependenciesBuilder.
rs/consensus/idkg/src/lib.rs Updates tests to use DependenciesBuilder.
rs/consensus/dkg/src/utils.rs Refactors tests to use DependenciesBuilder and uses replica_config.subnet_id from built deps.
rs/consensus/dkg/src/payload_validator.rs Updates tests to use DependenciesBuilder and align registry/subnet inputs accordingly.
rs/consensus/dkg/src/payload_builder.rs Migrates tests to builder pattern, including raw state manager scenarios via .without_mocked_state_manager().
rs/consensus/dkg/src/lib.rs Updates tests to use DependenciesBuilder and removes old dependency helper usage.
rs/consensus/dkg/src/dkg_key_manager.rs Migrates test dependency setup to DependenciesBuilder.
rs/consensus/chain_key/src/lib.rs Updates tests to use DependenciesBuilder, including opting out of mocked state manager.
rs/consensus/certification/src/certifier.rs Refactors certifier tests to use DependenciesBuilder.
Cargo.lock Records new workspace dependency (ic-interfaces-mocks) for ic-consensus-mocks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants