diff --git a/test/parachain/src/cli.rs b/test/parachain/src/cli.rs index d0b53837841..95e49eadd1b 100644 --- a/test/parachain/src/cli.rs +++ b/test/parachain/src/cli.rs @@ -39,6 +39,11 @@ pub struct ExportGenesisStateCommand { } #[derive(Debug, StructOpt, Clone)] +#[structopt(settings = &[ + structopt::clap::AppSettings::GlobalVersion, + structopt::clap::AppSettings::ArgsNegateSubcommands, + structopt::clap::AppSettings::SubcommandsNegateReqs, +])] pub struct Cli { #[structopt(subcommand)] pub subcommand: Option, diff --git a/test/parachain/src/command.rs b/test/parachain/src/command.rs index 584e7424932..c769b8ae10c 100644 --- a/test/parachain/src/command.rs +++ b/test/parachain/src/command.rs @@ -29,6 +29,7 @@ use sp_runtime::{ traits::{Block as BlockT, Hash as HashT, Header as HeaderT}, BuildStorage, }; +use sc_network::config::TransportConfig; use polkadot_service::ChainSpec as ChainSpecPolkadot; use codec::Encode; @@ -98,6 +99,7 @@ pub fn run(version: VersionInfo) -> error::Result<()> { polkadot_config.config_dir = config.in_chain_config_dir("polkadot"); let polkadot_opt: PolkadotCli = sc_cli::from_iter(opt.relaychain_args, &version); + let allow_private_ipv4 = !polkadot_opt.run.network_config.no_private_ipv4; polkadot_config.rpc_http = Some(DEFAULT_POLKADOT_RPC_HTTP.parse().unwrap()); polkadot_config.rpc_ws = Some(DEFAULT_POLKADOT_RPC_WS.parse().unwrap()); @@ -111,6 +113,14 @@ pub fn run(version: VersionInfo) -> error::Result<()> { )?; sc_cli::update_config_for_running_node(&mut polkadot_config, polkadot_opt.run)?; + // TODO: we disable mdns for the polkadot node because it prevents the process to exit + // properly. See https://github.com/paritytech/cumulus/issues/57 + polkadot_config.network.transport = TransportConfig::Normal { + enable_mdns: false, + allow_private_ipv4, + wasm_external_transport: None, + }; + match config.roles { ServiceRoles::LIGHT => unimplemented!("Light client not supported!"), _ => crate::service::run_collator(config, key, polkadot_config), diff --git a/test/parachain/tests/common.rs b/test/parachain/tests/common.rs new file mode 100644 index 00000000000..96060bf85d9 --- /dev/null +++ b/test/parachain/tests/common.rs @@ -0,0 +1,34 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{process::{Child, ExitStatus}, thread, time::Duration}; + +/// Wait for the given `child` the given ammount of `secs`. +/// +/// Returns the `Some(exit status)` or `None` if the process did not finish in the given time. +pub fn wait_for(child: &mut Child, secs: usize) -> Option { + for _ in 0..secs { + match child.try_wait().unwrap() { + Some(status) => return Some(status), + None => thread::sleep(Duration::from_secs(1)), + } + } + eprintln!("Took to long to exit. Killing..."); + let _ = child.kill(); + child.wait().unwrap(); + + None +} diff --git a/test/parachain/tests/polkadot_mdns_issue.rs b/test/parachain/tests/polkadot_mdns_issue.rs new file mode 100644 index 00000000000..aafac0c1e29 --- /dev/null +++ b/test/parachain/tests/polkadot_mdns_issue.rs @@ -0,0 +1,48 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use assert_cmd::cargo::cargo_bin; +use std::{convert::TryInto, process::Command, thread, time::Duration, fs}; + +mod common; + +#[test] +#[cfg(unix)] +fn interrupt_polkadot_mdns_issue_test() { + use nix::sys::signal::{kill, Signal::{self, SIGINT, SIGTERM}}; + use nix::unistd::Pid; + + fn run_command_and_kill(signal: Signal) { + let _ = fs::remove_dir_all("interrupt_polkadot_mdns_issue_test"); + let mut cmd = Command::new(cargo_bin("cumulus-test-parachain-collator")) + .args(&["-d", "interrupt_polkadot_mdns_issue_test"]) + .spawn() + .unwrap(); + + thread::sleep(Duration::from_secs(20)); + assert!(cmd.try_wait().unwrap().is_none(), "the process should still be running"); + kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap(); + assert_eq!( + common::wait_for(&mut cmd, 30).map(|x| x.success()), + Some(true), + "the process must exit gracefully after signal {}", + signal, + ); + } + + run_command_and_kill(SIGINT); + run_command_and_kill(SIGTERM); +} diff --git a/test/parachain/tests/purge_chain_works.rs b/test/parachain/tests/purge_chain_works.rs new file mode 100644 index 00000000000..6746ebe5282 --- /dev/null +++ b/test/parachain/tests/purge_chain_works.rs @@ -0,0 +1,53 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use assert_cmd::cargo::cargo_bin; +use std::{convert::TryInto, process::Command, thread, time::Duration, fs, path::PathBuf}; + +mod common; + +#[test] +#[cfg(unix)] +fn purge_chain_works() { + use nix::sys::signal::{kill, Signal::SIGINT}; + use nix::unistd::Pid; + + let base_path = "purge_chain_test"; + + let _ = fs::remove_dir_all(base_path); + let mut cmd = Command::new(cargo_bin("cumulus-test-parachain-collator")) + .args(&["-d", base_path]) + .spawn() + .unwrap(); + + // Let it produce some blocks. + thread::sleep(Duration::from_secs(30)); + assert!(cmd.try_wait().unwrap().is_none(), "the process should still be running"); + + // Stop the process + kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap(); + assert!(common::wait_for(&mut cmd, 30).map(|x| x.success()).unwrap_or_default()); + + let status = Command::new(cargo_bin("cumulus-test-parachain-collator")) + .args(&["purge-chain", "-d", base_path, "-y"]) + .status() + .unwrap(); + assert!(status.success()); + + // Make sure that the `parachain_local_testnet` chain folder exists, but the `db` is deleted. + assert!(PathBuf::from(base_path).join("chains/parachain_local_testnet/").exists()); + assert!(!PathBuf::from(base_path).join("chains/parachain_local_testnet/db").exists()); +} diff --git a/test/parachain/tests/running_the_node_and_interrupt.rs b/test/parachain/tests/running_the_node_and_interrupt.rs index 6f175531794..dc4e0e11ae1 100644 --- a/test/parachain/tests/running_the_node_and_interrupt.rs +++ b/test/parachain/tests/running_the_node_and_interrupt.rs @@ -15,10 +15,9 @@ // along with Substrate. If not, see . use assert_cmd::cargo::cargo_bin; -use std::convert::TryInto; -use std::process::{Child, Command, ExitStatus}; -use std::thread::sleep; -use std::time::Duration; +use std::{convert::TryInto, process::Command, thread, time::Duration, fs}; + +mod common; #[test] #[cfg(unix)] @@ -26,29 +25,20 @@ fn running_the_node_works_and_can_be_interrupted() { use nix::sys::signal::{kill, Signal::{self, SIGINT, SIGTERM}}; use nix::unistd::Pid; - fn wait_for(child: &mut Child, secs: usize) -> Option { - for _ in 0..secs { - match child.try_wait().unwrap() { - Some(status) => return Some(status), - None => sleep(Duration::from_secs(1)), - } - } - eprintln!("Took to long to exit. Killing..."); - let _ = child.kill(); - child.wait().unwrap(); - - None - } - fn run_command_and_kill(signal: Signal) { - let mut cmd = Command::new(cargo_bin("cumulus-test-parachain-collator")).args(&["--dev", "-d", "interrupt_test"]).spawn().unwrap(); - sleep(Duration::from_secs(30)); + let _ = fs::remove_dir_all("interrupt_test"); + let mut cmd = Command::new(cargo_bin("cumulus-test-parachain-collator")) + .args(&["--dev", "-d", "interrupt_test"]) + .spawn() + .unwrap(); + + thread::sleep(Duration::from_secs(30)); assert!(cmd.try_wait().unwrap().is_none(), "the process should still be running"); kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap(); assert_eq!( - wait_for(&mut cmd, 30).map(|x| x.success()), + common::wait_for(&mut cmd, 30).map(|x| x.success()), Some(true), - "the pocess must exit gracefully after signal {}", + "the process must exit gracefully after signal {}", signal, ); }