From f2d7b6f5ac7d611f7c807fca72f287321311c058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <bkchr@users.noreply.github.com> Date: Thu, 8 Oct 2020 11:27:19 +0200 Subject: [PATCH] Make `AllSubsystems` usage easier in tests (#1794) * Make `AllSubsystems` usage easier in tests This makes the usage of `AllSubsystems` easier in tests by introducing new methods. - `dummy` initializes `AllSubsystems` with all systems set to dummy - `replace_*` to replace any subsystem Besides that this pr adds a `ForwardSubsystem` that is also useful for tests. This subsystem will forward all incoming messages to the given channel. * Update node/overseer/src/lib.rs Co-authored-by: Andronik Ordian <write@reusable.software> * Update node/subsystem/src/lib.rs Co-authored-by: Andronik Ordian <write@reusable.software> * Update node/subsystem/src/lib.rs Co-authored-by: Andronik Ordian <write@reusable.software> * Move ForwardSubsystem and add a test * Break some lines Co-authored-by: Andronik Ordian <write@reusable.software> --- polkadot/Cargo.lock | 1 + .../node/overseer/examples/minimal-example.rs | 25 +- polkadot/node/overseer/src/lib.rs | 548 ++++++++++++++---- .../node/subsystem-test-helpers/Cargo.toml | 3 + .../node/subsystem-test-helpers/src/lib.rs | 61 +- polkadot/node/subsystem/src/lib.rs | 2 +- 6 files changed, 505 insertions(+), 135 deletions(-) diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index 976d77b7315..f4de76c2e2c 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -5060,6 +5060,7 @@ dependencies = [ "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", + "polkadot-overseer", "polkadot-primitives", "polkadot-statement-table", "sc-network", diff --git a/polkadot/node/overseer/examples/minimal-example.rs b/polkadot/node/overseer/examples/minimal-example.rs index 2b55fa2634c..9c0864a9b79 100644 --- a/polkadot/node/overseer/examples/minimal-example.rs +++ b/polkadot/node/overseer/examples/minimal-example.rs @@ -30,10 +30,7 @@ use kv_log_macro as log; use polkadot_primitives::v1::{BlockData, PoV}; use polkadot_overseer::{Overseer, AllSubsystems}; -use polkadot_subsystem::{ - Subsystem, SubsystemContext, DummySubsystem, - SpawnedSubsystem, FromOverseer, -}; +use polkadot_subsystem::{Subsystem, SubsystemContext, SpawnedSubsystem, FromOverseer}; use polkadot_subsystem::messages::{ CandidateValidationMessage, CandidateBackingMessage, AllMessages, }; @@ -141,23 +138,9 @@ fn main() { Delay::new(Duration::from_secs(1)).await; }); - let all_subsystems = AllSubsystems { - candidate_validation: Subsystem2, - candidate_backing: Subsystem1, - candidate_selection: DummySubsystem, - statement_distribution: DummySubsystem, - availability_distribution: DummySubsystem, - bitfield_signing: DummySubsystem, - bitfield_distribution: DummySubsystem, - provisioner: DummySubsystem, - pov_distribution: DummySubsystem, - runtime_api: DummySubsystem, - availability_store: DummySubsystem, - network_bridge: DummySubsystem, - chain_api: DummySubsystem, - collation_generation: DummySubsystem, - collator_protocol: DummySubsystem, - }; + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(Subsystem2) + .replace_candidate_backing(Subsystem1); let (overseer, _handler) = Overseer::new( vec![], all_subsystems, diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs index 0318cad34b4..e33a5756c80 100644 --- a/polkadot/node/overseer/src/lib.rs +++ b/polkadot/node/overseer/src/lib.rs @@ -83,7 +83,7 @@ use polkadot_subsystem::messages::{ }; pub use polkadot_subsystem::{ Subsystem, SubsystemContext, OverseerSignal, FromOverseer, SubsystemError, SubsystemResult, - SpawnedSubsystem, ActiveLeavesUpdate, + SpawnedSubsystem, ActiveLeavesUpdate, DummySubsystem, }; use polkadot_node_subsystem_util::metrics::{self, prometheus}; use polkadot_node_primitives::SpawnNamed; @@ -348,7 +348,7 @@ struct OverseenSubsystem<M> { } /// The `Overseer` itself. -pub struct Overseer<S: SpawnNamed> { +pub struct Overseer<S> { /// A candidate validation subsystem. candidate_validation_subsystem: OverseenSubsystem<CandidateValidationMessage>, @@ -429,10 +429,10 @@ pub struct Overseer<S: SpawnNamed> { /// Each [`Subsystem`] is supposed to implement some interface that is generic over /// message type that is specific to this [`Subsystem`]. At the moment not all /// subsystems are implemented and the rest can be mocked with the [`DummySubsystem`]. -/// -/// [`Subsystem`]: trait.Subsystem.html -/// [`DummySubsystem`]: struct.DummySubsystem.html -pub struct AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { +pub struct AllSubsystems< + CV = (), CB = (), CS = (), SD = (), AD = (), BS = (), BD = (), P = (), + PoVD = (), RA = (), AS = (), NB = (), CA = (), CG = (), CP = () +> { /// A candidate validation subsystem. pub candidate_validation: CV, /// A candidate backing subsystem. @@ -465,6 +465,418 @@ pub struct AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG pub collator_protocol: CP, } +impl<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> + AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> +{ + /// Create a new instance of [`AllSubsystems`]. + /// + /// Each subsystem is set to [`DummySystem`]. + /// + ///# Note + /// + /// Because of a bug in rustc it is required that when calling this function, + /// you provide a "random" type for the first generic parameter: + /// + /// ``` + /// polkadot_overseer::AllSubsystems::<()>::dummy(); + /// ``` + pub fn dummy() -> AllSubsystems< + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem, + DummySubsystem + > { + AllSubsystems { + candidate_validation: DummySubsystem, + candidate_backing: DummySubsystem, + candidate_selection: DummySubsystem, + statement_distribution: DummySubsystem, + availability_distribution: DummySubsystem, + bitfield_signing: DummySubsystem, + bitfield_distribution: DummySubsystem, + provisioner: DummySubsystem, + pov_distribution: DummySubsystem, + runtime_api: DummySubsystem, + availability_store: DummySubsystem, + network_bridge: DummySubsystem, + chain_api: DummySubsystem, + collation_generation: DummySubsystem, + collator_protocol: DummySubsystem, + } + } + + /// Replace the `candidate_validation` instance in `self`. + pub fn replace_candidate_validation<NEW>( + self, + candidate_validation: NEW, + ) -> AllSubsystems<NEW, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `candidate_backing` instance in `self`. + pub fn replace_candidate_backing<NEW>( + self, + candidate_backing: NEW, + ) -> AllSubsystems<CV, NEW, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `candidate_selection` instance in `self`. + pub fn replace_candidate_selection<NEW>( + self, + candidate_selection: NEW, + ) -> AllSubsystems<CV, CB, NEW, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `statement_distribution` instance in `self`. + pub fn replace_statement_distribution<NEW>( + self, + statement_distribution: NEW, + ) -> AllSubsystems<CV, CB, CS, NEW, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `availability_distribution` instance in `self`. + pub fn replace_availability_distribution<NEW>( + self, + availability_distribution: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, NEW, BS, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `bitfield_signing` instance in `self`. + pub fn replace_bitfield_signing<NEW>( + self, + bitfield_signing: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, NEW, BD, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `bitfield_distribution` instance in `self`. + pub fn replace_bitfield_distribution<NEW>( + self, + bitfield_distribution: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, NEW, P, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `provisioner` instance in `self`. + pub fn replace_provisioner<NEW>( + self, + provisioner: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, NEW, PoVD, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `pov_distribution` instance in `self`. + pub fn replace_pov_distribution<NEW>( + self, + pov_distribution: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, NEW, RA, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `runtime_api` instance in `self`. + pub fn replace_runtime_api<NEW>( + self, + runtime_api: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, NEW, AS, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `availability_store` instance in `self`. + pub fn replace_availability_store<NEW>( + self, + availability_store: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, NEW, NB, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `network_bridge` instance in `self`. + pub fn replace_network_bridge<NEW>( + self, + network_bridge: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NEW, CA, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `chain_api` instance in `self`. + pub fn replace_chain_api<NEW>( + self, + chain_api: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, NEW, CG, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api, + collation_generation: self.collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `collation_generation` instance in `self`. + pub fn replace_collation_generation<NEW>( + self, + collation_generation: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, NEW, CP> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation, + collator_protocol: self.collator_protocol, + } + } + + /// Replace the `collator_protocol` instance in `self`. + pub fn replace_collator_protocol<NEW>( + self, + collator_protocol: NEW, + ) -> AllSubsystems<CV, CB, CS, SD, AD, BS, BD, P, PoVD, RA, AS, NB, CA, CG, NEW> { + AllSubsystems { + candidate_validation: self.candidate_validation, + candidate_backing: self.candidate_backing, + candidate_selection: self.candidate_selection, + statement_distribution: self.statement_distribution, + availability_distribution: self.availability_distribution, + bitfield_signing: self.bitfield_signing, + bitfield_distribution: self.bitfield_distribution, + provisioner: self.provisioner, + pov_distribution: self.pov_distribution, + runtime_api: self.runtime_api, + availability_store: self.availability_store, + network_bridge: self.network_bridge, + chain_api: self.chain_api, + collation_generation: self.collation_generation, + collator_protocol, + } + } +} + /// Overseer Prometheus metrics. #[derive(Clone)] struct MetricsInner { @@ -591,23 +1003,7 @@ where /// /// # fn main() { executor::block_on(async move { /// let spawner = sp_core::testing::TaskExecutor::new(); - /// let all_subsystems = AllSubsystems { - /// candidate_validation: ValidationSubsystem, - /// candidate_backing: DummySubsystem, - /// candidate_selection: DummySubsystem, - /// statement_distribution: DummySubsystem, - /// availability_distribution: DummySubsystem, - /// bitfield_signing: DummySubsystem, - /// bitfield_distribution: DummySubsystem, - /// provisioner: DummySubsystem, - /// pov_distribution: DummySubsystem, - /// runtime_api: DummySubsystem, - /// availability_store: DummySubsystem, - /// network_bridge: DummySubsystem, - /// chain_api: DummySubsystem, - /// collation_generation: DummySubsystem, - /// collator_protocol: DummySubsystem, - /// }; + /// let all_subsystems = AllSubsystems::<()>::dummy().replace_candidate_validation(ValidationSubsystem); /// let (overseer, _handler) = Overseer::new( /// vec![], /// all_subsystems, @@ -1228,7 +1624,6 @@ mod tests { use futures::{executor, pin_mut, select, channel::mpsc, FutureExt}; use polkadot_primitives::v1::{BlockData, CollatorPair, PoV}; - use polkadot_subsystem::DummySubsystem; use polkadot_subsystem::messages::RuntimeApiRequest; use polkadot_node_primitives::{Collation, CollationGenerationConfig}; use polkadot_node_network_protocol::{PeerId, ReputationChange, NetworkBridgeEvent}; @@ -1237,7 +1632,6 @@ mod tests { use super::*; - struct TestSubsystem1(mpsc::Sender<usize>); impl<C> Subsystem<C> for TestSubsystem1 @@ -1334,26 +1728,13 @@ mod tests { let spawner = sp_core::testing::TaskExecutor::new(); executor::block_on(async move { - let (s1_tx, mut s1_rx) = mpsc::channel(64); - let (s2_tx, mut s2_rx) = mpsc::channel(64); + let (s1_tx, mut s1_rx) = mpsc::channel::<usize>(64); + let (s2_tx, mut s2_rx) = mpsc::channel::<usize>(64); + + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem1(s1_tx)) + .replace_candidate_backing(TestSubsystem2(s2_tx)); - let all_subsystems = AllSubsystems { - candidate_validation: TestSubsystem1(s1_tx), - candidate_backing: TestSubsystem2(s2_tx), - candidate_selection: DummySubsystem, - statement_distribution: DummySubsystem, - availability_distribution: DummySubsystem, - bitfield_signing: DummySubsystem, - bitfield_distribution: DummySubsystem, - provisioner: DummySubsystem, - pov_distribution: DummySubsystem, - runtime_api: DummySubsystem, - availability_store: DummySubsystem, - network_bridge: DummySubsystem, - chain_api: DummySubsystem, - collation_generation: DummySubsystem, - collator_protocol: DummySubsystem, - }; let (overseer, mut handler) = Overseer::new( vec![], all_subsystems, @@ -1421,23 +1802,7 @@ mod tests { number: 3, }; - let all_subsystems = AllSubsystems { - collation_generation: DummySubsystem, - candidate_validation: DummySubsystem, - candidate_backing: DummySubsystem, - candidate_selection: DummySubsystem, - collator_protocol: DummySubsystem, - statement_distribution: DummySubsystem, - availability_distribution: DummySubsystem, - bitfield_signing: DummySubsystem, - bitfield_distribution: DummySubsystem, - provisioner: DummySubsystem, - pov_distribution: DummySubsystem, - runtime_api: DummySubsystem, - availability_store: DummySubsystem, - network_bridge: DummySubsystem, - chain_api: DummySubsystem, - }; + let all_subsystems = AllSubsystems::<()>::dummy(); let registry = prometheus::Registry::new(); let (overseer, mut handler) = Overseer::new( vec![first_block], @@ -1491,23 +1856,9 @@ mod tests { executor::block_on(async move { let (s1_tx, _) = mpsc::channel(64); - let all_subsystems = AllSubsystems { - candidate_validation: TestSubsystem1(s1_tx), - candidate_backing: TestSubsystem4, - candidate_selection: DummySubsystem, - statement_distribution: DummySubsystem, - availability_distribution: DummySubsystem, - bitfield_signing: DummySubsystem, - bitfield_distribution: DummySubsystem, - provisioner: DummySubsystem, - pov_distribution: DummySubsystem, - runtime_api: DummySubsystem, - availability_store: DummySubsystem, - network_bridge: DummySubsystem, - chain_api: DummySubsystem, - collation_generation: DummySubsystem, - collator_protocol: DummySubsystem, - }; + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem1(s1_tx)) + .replace_candidate_backing(TestSubsystem4); let (overseer, _handle) = Overseer::new( vec![], all_subsystems, @@ -1611,23 +1962,9 @@ mod tests { let (tx_5, mut rx_5) = mpsc::channel(64); let (tx_6, mut rx_6) = mpsc::channel(64); - let all_subsystems = AllSubsystems { - candidate_validation: TestSubsystem5(tx_5), - candidate_backing: TestSubsystem6(tx_6), - candidate_selection: DummySubsystem, - statement_distribution: DummySubsystem, - availability_distribution: DummySubsystem, - bitfield_signing: DummySubsystem, - bitfield_distribution: DummySubsystem, - provisioner: DummySubsystem, - pov_distribution: DummySubsystem, - runtime_api: DummySubsystem, - availability_store: DummySubsystem, - network_bridge: DummySubsystem, - chain_api: DummySubsystem, - collation_generation: DummySubsystem, - collator_protocol: DummySubsystem, - }; + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem5(tx_5)) + .replace_candidate_backing(TestSubsystem6(tx_6)); let (overseer, mut handler) = Overseer::new( vec![first_block], all_subsystems, @@ -1716,23 +2053,10 @@ mod tests { let (tx_5, mut rx_5) = mpsc::channel(64); let (tx_6, mut rx_6) = mpsc::channel(64); - let all_subsystems = AllSubsystems { - candidate_validation: TestSubsystem5(tx_5), - candidate_backing: TestSubsystem6(tx_6), - candidate_selection: DummySubsystem, - statement_distribution: DummySubsystem, - availability_distribution: DummySubsystem, - bitfield_signing: DummySubsystem, - bitfield_distribution: DummySubsystem, - provisioner: DummySubsystem, - pov_distribution: DummySubsystem, - runtime_api: DummySubsystem, - availability_store: DummySubsystem, - network_bridge: DummySubsystem, - chain_api: DummySubsystem, - collation_generation: DummySubsystem, - collator_protocol: DummySubsystem, - }; + let all_subsystems = AllSubsystems::<()>::dummy() + .replace_candidate_validation(TestSubsystem5(tx_5)) + .replace_candidate_backing(TestSubsystem6(tx_6)); + // start with two forks of different height. let (overseer, mut handler) = Overseer::new( vec![first_block, second_block], diff --git a/polkadot/node/subsystem-test-helpers/Cargo.toml b/polkadot/node/subsystem-test-helpers/Cargo.toml index 220af40deb9..5f1388136a3 100644 --- a/polkadot/node/subsystem-test-helpers/Cargo.toml +++ b/polkadot/node/subsystem-test-helpers/Cargo.toml @@ -22,3 +22,6 @@ polkadot-statement-table = { path = "../../statement-table" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } smallvec = "1.4.1" sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[dev-dependencies] +polkadot-overseer = { path = "../overseer" } diff --git a/polkadot/node/subsystem-test-helpers/src/lib.rs b/polkadot/node/subsystem-test-helpers/src/lib.rs index 817cad37f0d..ae1dd91ad1c 100644 --- a/polkadot/node/subsystem-test-helpers/src/lib.rs +++ b/polkadot/node/subsystem-test-helpers/src/lib.rs @@ -17,7 +17,10 @@ //! Utilities for testing subsystems. use polkadot_node_subsystem::messages::AllMessages; -use polkadot_node_subsystem::{FromOverseer, SubsystemContext, SubsystemError, SubsystemResult}; +use polkadot_node_subsystem::{ + FromOverseer, SubsystemContext, SubsystemError, SubsystemResult, Subsystem, + SpawnedSubsystem, OverseerSignal, +}; use polkadot_node_subsystem_util::TimeoutExt; use futures::channel::mpsc; @@ -283,3 +286,59 @@ pub fn subsystem_test_harness<M, OverseerFactory, Overseer, TestFactory, Test>( .expect("test timed out instead of completing") }); } + +/// A forward subsystem that implements [`Subsystem`]. +/// +/// It forwards all communication from the overseer to the internal message +/// channel. +/// +/// This subsystem is useful for testing functionality that interacts with the overseer. +pub struct ForwardSubsystem<Msg>(pub mpsc::Sender<Msg>); + +impl<C: SubsystemContext<Message = Msg>, Msg: Send + 'static> Subsystem<C> for ForwardSubsystem<Msg> { + fn start(mut self, mut ctx: C) -> SpawnedSubsystem { + let future = Box::pin(async move { + loop { + match ctx.recv().await { + Ok(FromOverseer::Signal(OverseerSignal::Conclude)) => return, + Ok(FromOverseer::Communication { msg }) => { + let _ = self.0.send(msg).await; + }, + Err(_) => return, + _ => (), + } + } + }); + + SpawnedSubsystem { + name: "forward-subsystem", + future, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use polkadot_overseer::{Overseer, AllSubsystems}; + use futures::executor::block_on; + use polkadot_node_subsystem::messages::CandidateSelectionMessage; + + #[test] + fn forward_subsystem_works() { + let spawner = sp_core::testing::TaskExecutor::new(); + let (tx, rx) = mpsc::channel(2); + let all_subsystems = AllSubsystems::<()>::dummy().replace_candidate_selection(ForwardSubsystem(tx)); + let (overseer, mut handler) = Overseer::new( + Vec::new(), + all_subsystems, + None, + spawner.clone(), + ).unwrap(); + + spawner.spawn("overseer", overseer.run().then(|_| async { () }).boxed()); + + block_on(handler.send_msg(CandidateSelectionMessage::Invalid(Default::default(), Default::default()))).unwrap(); + assert!(matches!(block_on(rx.into_future()).0.unwrap(), CandidateSelectionMessage::Invalid(_, _))); + } +} diff --git a/polkadot/node/subsystem/src/lib.rs b/polkadot/node/subsystem/src/lib.rs index 843791b7206..dea391c5b2c 100644 --- a/polkadot/node/subsystem/src/lib.rs +++ b/polkadot/node/subsystem/src/lib.rs @@ -223,7 +223,7 @@ impl<C: SubsystemContext> Subsystem<C> for DummySubsystem { }); SpawnedSubsystem { - name: "DummySubsystem", + name: "dummy-subsystem", future, } } -- GitLab