From 13b48d9cf5e6d3f76608052da9e38f25141ca95e Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Mon, 27 Jul 2020 22:39:02 +0200 Subject: [PATCH 1/7] build: parallelize the e2e bats tests Running the e2e bats test sequentially took 15m on my laptop. We should run them all in parallel such that we don't have to wait so long on CI. --- e2e/bats/default.nix | 89 +++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/e2e/bats/default.nix b/e2e/bats/default.nix index f4f0e92b73..15fa30f35a 100644 --- a/e2e/bats/default.nix +++ b/e2e/bats/default.nix @@ -4,47 +4,58 @@ , use_ic_ref ? false }: let - e2e = lib.noNixFiles (lib.gitOnlySource ./.); - lib = pkgs.lib; - sources = pkgs.sources; + inherit (pkgs) lib; - inputs = with pkgs; [ - bats - bash - coreutils - diffutils - curl - findutils - gnugrep - gnutar - gzip - jq - netcat - ps - python3 - procps - which - dfx.standalone - ] ++ lib.optional use_ic_ref ic-ref; -in + isBatsTest = fileName: type: lib.hasSuffix ".bash" fileName && type == "regular"; -builtins.derivation { - name = "e2e-tests"; - system = pkgs.stdenv.system; - PATH = pkgs.lib.makeSearchPath "bin" inputs; - BATSLIB = sources.bats-support; - builder = - pkgs.writeScript "builder.sh" '' - #!${pkgs.stdenv.shell} - set -eo pipefail + here = ./.; - # We want $HOME/.cache to be in a new temporary directory. - export HOME=$(mktemp -d -t dfx-e2e-home-XXXX) + mkBatsTest = fileName: + let + name = lib.removeSuffix ".bash" fileName; + in + lib.nameValuePair name ( + pkgs.runCommandNoCC name { + nativeBuildInputs = with pkgs; [ + bats + diffutils + curl + findutils + gnugrep + gnutar + gzip + jq + netcat + ps + python3 + procps + which + dfx.standalone + ] ++ lib.optional use_ic_ref ic-ref; + BATSLIB = pkgs.sources.bats-support; + USE_IC_REF = use_ic_ref; + } '' + # We want $HOME/.cache to be in a new temporary directory. + export HOME=$(mktemp -d -t dfx-e2e-home-XXXX) - export USE_IC_REF=${if use_ic_ref then "1" else ""} + ln -s ${./utils} utils + ln -s ${./assets} assets + ln -s ${here + "/${fileName}"} ${fileName} - # Timeout of 10 minutes is enough for now. Reminder; CI might be running with - # less resources than a dev's computer, so e2e might take longer. - timeout --preserve-status 3600 bats --recursive ${e2e}/* | tee $out - ''; -} // { meta = {}; } + # Timeout of 10 minutes is enough for now. Reminder; CI might be running with + # less resources than a dev's computer, so e2e might take longer. + timeout --preserve-status 3600 bats ${fileName} | tee $out + '' + ); +in +builtins.listToAttrs + ( + builtins.map mkBatsTest + ( + lib.attrNames + ( + lib.filterAttrs isBatsTest + (builtins.readDir here) + ) + ) + ) From db5b7e264ecb9e6a4b5e0445dc11422bc28e0ebc Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Tue, 28 Jul 2020 09:31:18 +0200 Subject: [PATCH 2/7] e2e/bats: better name of the derivations --- e2e/bats/default.nix | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/e2e/bats/default.nix b/e2e/bats/default.nix index 15fa30f35a..b468eebae4 100644 --- a/e2e/bats/default.nix +++ b/e2e/bats/default.nix @@ -15,7 +15,7 @@ let name = lib.removeSuffix ".bash" fileName; in lib.nameValuePair name ( - pkgs.runCommandNoCC name { + pkgs.runCommandNoCC "e2e-test-${name}${lib.optionalString use_ic_ref "-use_ic_ref"}" { nativeBuildInputs = with pkgs; [ bats diffutils @@ -34,17 +34,19 @@ let ] ++ lib.optional use_ic_ref ic-ref; BATSLIB = pkgs.sources.bats-support; USE_IC_REF = use_ic_ref; + utils = lib.gitOnlySource ../../. ./utils; + assets = lib.gitOnlySource ../../. ./assets; + test = here + "/${fileName}"; } '' - # We want $HOME/.cache to be in a new temporary directory. - export HOME=$(mktemp -d -t dfx-e2e-home-XXXX) + export HOME=$(pwd) - ln -s ${./utils} utils - ln -s ${./assets} assets - ln -s ${here + "/${fileName}"} ${fileName} + ln -s $utils utils + ln -s $assets assets + ln -s $test test # Timeout of 10 minutes is enough for now. Reminder; CI might be running with # less resources than a dev's computer, so e2e might take longer. - timeout --preserve-status 3600 bats ${fileName} | tee $out + timeout --preserve-status 3600 bats test | tee $out '' ); in From 181da96b798046c9d4294f55e10d4007a180dafc Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Tue, 11 Aug 2020 18:30:15 -0700 Subject: [PATCH 3/7] add stuff --- Cargo.lock | 56 +++++++++++++++++++++++------------ src/dfx/Cargo.toml | 1 + src/dfx/src/commands/start.rs | 31 +++++++++++++++---- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd3ec73bcc..f8d4fd3730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -762,6 +762,23 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "console" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b1aacfaffdbff75be81c15a399b4bedf78aaefe840e8af1d299ac2ade885d2" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "termios", + "unicode-width", + "winapi 0.3.9", + "winapi-util", +] + [[package]] name = "const-random" version = "0.1.8" @@ -985,6 +1002,7 @@ dependencies = [ "libflate", "mockall", "mockito", + "net2", "petgraph", "proptest", "rand 0.7.3", @@ -1107,9 +1125,9 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" [[package]] name = "either" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" [[package]] name = "ena" @@ -1475,9 +1493,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f595585f103464d8d2f6e9864682d74c1601fed5e07d62b1c9058dba8246fb" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" dependencies = [ "autocfg 1.0.0", ] @@ -1691,7 +1709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg 1.0.0", - "hashbrown 0.8.1", + "hashbrown 0.8.2", ] [[package]] @@ -1700,7 +1718,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8572bccfb0665e70b7faf44ee28841b8e0823450cd4ad562a76b5a3c4bf48487" dependencies = [ - "console 0.11.3", + "console 0.12.0", "lazy_static", "number_prefix", "regex", @@ -1844,9 +1862,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "leb128" @@ -2353,7 +2371,7 @@ dependencies = [ "instant", "libc", "redox_syscall", - "smallvec 1.4.1", + "smallvec 1.4.2", "winapi 0.3.9", ] @@ -3043,9 +3061,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] @@ -3082,9 +3100,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2 1.0.19", "quote 1.0.7", @@ -3223,9 +3241,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f" +checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" [[package]] name = "socket2" @@ -3661,9 +3679,9 @@ checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" [[package]] name = "tracing" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178" +checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" dependencies = [ "cfg-if", "log", @@ -3672,9 +3690,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9" +checksum = "db63662723c316b43ca36d833707cc93dff82a02ba3d7e354f342682cc8b3545" dependencies = [ "lazy_static", ] diff --git a/src/dfx/Cargo.toml b/src/dfx/Cargo.toml index b177d145ac..6461fb7b7e 100644 --- a/src/dfx/Cargo.toml +++ b/src/dfx/Cargo.toml @@ -39,6 +39,7 @@ lazy_static = "1.4.0" libflate = "0.1.27" hotwatch = "0.4.3" mockall = "0.6.0" +net2 = "0.2.34" petgraph = "0.5.0" rand = "0.7.2" regex = "1.3.1" diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 628df41770..5065d2ec8f 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -14,15 +14,16 @@ use crossbeam::unbounded; use futures::future::Future; use ic_agent::{Agent, AgentConfig}; use indicatif::{ProgressBar, ProgressDrawTarget}; +use net2::{unix::UnixTcpBuilderExt, TcpBuilder}; use std::fs; use std::io::{Error, ErrorKind}; use std::net::SocketAddr; use std::path::PathBuf; use std::process::Command; use std::time::Duration; + use sysinfo::{Pid, Process, ProcessExt, Signal, System, SystemExt}; use tokio::runtime::Runtime; - /// Provide necessary arguments to start the Internet Computer /// locally. See `exec` for further information. pub fn construct() -> App<'static, 'static> { @@ -290,12 +291,30 @@ fn frontend_address(args: &ArgMatches<'_>, config: &Config) -> DfxResult<(String .expect("could not get socket_addr")) }) .map_err(|e| DfxError::InvalidArgument(format!("Invalid host: {}", e)))?; - let frontend_url = format!( - "http://{}:{}", - address_and_port.ip(), - address_and_port.port() - ); + // The user can pass in port "0" i.e. "127.0.0.1:0" or "[::1]:0", thus, + // we need to recreate SocketAddr with the kernel provided dynmically allocated port here. + // TcpBuilder is used with reuse_address and reuse_port set to "true" because + // the Actix HttpServer in webserver.rs will bind to this SocketAddr. + let address_and_port = match address_and_port.is_ipv4() { + true => TcpBuilder::new_v4()? + .bind(address_and_port)? + .reuse_address(true)? + .reuse_port(true)? + .to_tcp_listener()? + .local_addr()?, + false => TcpBuilder::new_v6()? + .bind(address_and_port)? + .reuse_address(true)? + .reuse_port(true)? + .to_tcp_listener()? + .local_addr()?, + }; + let ip = match address_and_port.is_ipv6() { + true => format!("[{}]", address_and_port.ip()), + false => address_and_port.ip().to_string(), + }; + let frontend_url = format!("http://{}:{}", ip, address_and_port.port()); Ok((frontend_url, address_and_port)) } From 3076e320969e886ae6bf0f1bfb6d3bc7ed5194ee Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Tue, 11 Aug 2020 19:25:25 -0700 Subject: [PATCH 4/7] fix not exiting process if port 0 provided and --background --- src/dfx/src/commands/start.rs | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 5065d2ec8f..9cb96b84b7 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -114,7 +114,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { if args.is_present("background") { send_background()?; - return ping_and_wait(&frontend_url); + return Ok(()); } // Start the client. @@ -281,7 +281,7 @@ fn send_background() -> DfxResult<()> { } fn frontend_address(args: &ArgMatches<'_>, config: &Config) -> DfxResult<(String, SocketAddr)> { - let address_and_port = args + let mut address_and_port = args .value_of("host") .and_then(|host| Option::from(host.parse())) .unwrap_or_else(|| { @@ -296,25 +296,28 @@ fn frontend_address(args: &ArgMatches<'_>, config: &Config) -> DfxResult<(String // we need to recreate SocketAddr with the kernel provided dynmically allocated port here. // TcpBuilder is used with reuse_address and reuse_port set to "true" because // the Actix HttpServer in webserver.rs will bind to this SocketAddr. - let address_and_port = match address_and_port.is_ipv4() { - true => TcpBuilder::new_v4()? - .bind(address_and_port)? - .reuse_address(true)? - .reuse_port(true)? - .to_tcp_listener()? - .local_addr()?, - false => TcpBuilder::new_v6()? - .bind(address_and_port)? - .reuse_address(true)? - .reuse_port(true)? - .to_tcp_listener()? - .local_addr()?, - }; + if !args.is_present("background") { + address_and_port = match address_and_port.is_ipv4() { + true => TcpBuilder::new_v4()? + .bind(address_and_port)? + .reuse_address(true)? + .reuse_port(true)? + .to_tcp_listener()? + .local_addr()?, + false => TcpBuilder::new_v6()? + .bind(address_and_port)? + .reuse_address(true)? + .reuse_port(true)? + .to_tcp_listener()? + .local_addr()?, + }; + } let ip = match address_and_port.is_ipv6() { true => format!("[{}]", address_and_port.ip()), false => address_and_port.ip().to_string(), }; let frontend_url = format!("http://{}:{}", ip, address_and_port.port()); + println!("frontend_url {:?}", frontend_url); Ok((frontend_url, address_and_port)) } From c84a4f25bb47b1eb06898afa566430a4f01edd9d Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Tue, 11 Aug 2020 22:43:14 -0700 Subject: [PATCH 5/7] move to utils --- src/dfx/src/commands/bootstrap.rs | 15 +++++++++++++-- src/dfx/src/commands/start.rs | 31 +++++++++++-------------------- src/dfx/src/util/mod.rs | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/dfx/src/commands/bootstrap.rs b/src/dfx/src/commands/bootstrap.rs index e5edff1c23..3c969a4735 100644 --- a/src/dfx/src/commands/bootstrap.rs +++ b/src/dfx/src/commands/bootstrap.rs @@ -5,12 +5,13 @@ use crate::lib::message::UserMessage; use crate::lib::network::network_descriptor::NetworkDescriptor; use crate::lib::provider::get_network_descriptor; use crate::lib::webserver::webserver; +use crate::util::get_reusable_socket_addr; use clap::{App, Arg, ArgMatches, SubCommand}; use slog::info; use std::default::Default; use std::fs; use std::io::{Error, ErrorKind}; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::net::{IpAddr, Ipv4Addr}; use std::path::PathBuf; use std::str::FromStr; use std::time::Duration; @@ -70,11 +71,21 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { let (sender, receiver) = crossbeam::unbounded(); + // Since the user may have provided port "0", we need to grab a dynamically + // allocated port and construct a resuable SocketAddr which the actix + // HttpServer will bind to + let socket_addr = + get_reusable_socket_addr(config_bootstrap.ip.unwrap(), config_bootstrap.port.unwrap())?; + + let webserver_port_path = env.get_temp_dir().join("webserver-port"); + std::fs::write(&webserver_port_path, "")?; + std::fs::write(&webserver_port_path, socket_addr.port().to_string())?; + webserver( logger.clone(), build_output_root, network_descriptor, - SocketAddr::new(config_bootstrap.ip.unwrap(), config_bootstrap.port.unwrap()), + socket_addr, providers .iter() .map(|uri| Url::from_str(uri).unwrap()) diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 9cb96b84b7..718a9640aa 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -7,6 +7,7 @@ use crate::lib::proxy::{CoordinateProxy, ProxyConfig}; use crate::lib::proxy_process::spawn_and_update_proxy; use crate::lib::replica_config::ReplicaConfig; use crate::lib::waiter::create_waiter; +use crate::util::get_reusable_socket_addr; use clap::{App, Arg, ArgMatches, SubCommand}; use crossbeam::channel::{Receiver, Sender}; @@ -14,7 +15,6 @@ use crossbeam::unbounded; use futures::future::Future; use ic_agent::{Agent, AgentConfig}; use indicatif::{ProgressBar, ProgressDrawTarget}; -use net2::{unix::UnixTcpBuilderExt, TcpBuilder}; use std::fs; use std::io::{Error, ErrorKind}; use std::net::SocketAddr; @@ -72,12 +72,16 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; + let temp_dir = env.get_temp_dir(); + let (frontend_url, address_and_port) = frontend_address(args, &config)?; + let webserver_port_path = temp_dir.join("webserver-port"); + std::fs::write(&webserver_port_path, "")?; + std::fs::write(&webserver_port_path, address_and_port.port().to_string())?; let client_pathbuf = env.get_cache().get_binary_command_path("replica")?; let ic_starter_pathbuf = env.get_cache().get_binary_command_path("ic-starter")?; - let temp_dir = env.get_temp_dir(); let state_root = env.get_state_dir(); let pid_file_path = temp_dir.join("pid"); @@ -292,25 +296,12 @@ fn frontend_address(args: &ArgMatches<'_>, config: &Config) -> DfxResult<(String }) .map_err(|e| DfxError::InvalidArgument(format!("Invalid host: {}", e)))?; - // The user can pass in port "0" i.e. "127.0.0.1:0" or "[::1]:0", thus, - // we need to recreate SocketAddr with the kernel provided dynmically allocated port here. - // TcpBuilder is used with reuse_address and reuse_port set to "true" because - // the Actix HttpServer in webserver.rs will bind to this SocketAddr. if !args.is_present("background") { - address_and_port = match address_and_port.is_ipv4() { - true => TcpBuilder::new_v4()? - .bind(address_and_port)? - .reuse_address(true)? - .reuse_port(true)? - .to_tcp_listener()? - .local_addr()?, - false => TcpBuilder::new_v6()? - .bind(address_and_port)? - .reuse_address(true)? - .reuse_port(true)? - .to_tcp_listener()? - .local_addr()?, - }; + // Since the user may have provided port "0", we need to grab a dynamically + // allocated port and construct a resuable SocketAddr which the actix + // HttpServer will bind to + address_and_port = + get_reusable_socket_addr(address_and_port.ip(), address_and_port.port())?; } let ip = match address_and_port.is_ipv6() { true => format!("[{}]", address_and_port.ip()), diff --git a/src/dfx/src/util/mod.rs b/src/dfx/src/util/mod.rs index c55918f2e2..38ecf3c11c 100644 --- a/src/dfx/src/util/mod.rs +++ b/src/dfx/src/util/mod.rs @@ -3,10 +3,29 @@ use candid::parser::typing::{check_prog, TypeEnv}; use candid::types::{Function, Type}; use candid::{parser::value::IDLValue, IDLArgs, IDLProg}; use ic_agent::Blob; +use net2::{unix::UnixTcpBuilderExt, TcpBuilder}; +use std::net::{IpAddr, SocketAddr}; pub mod assets; pub mod clap; +// The user can pass in port "0" to dfx start or dfx bootstrap i.e. "127.0.0.1:0" or "[::1]:0", +// thus, we need to recreate SocketAddr with the kernel provided dynmically allocated port here. +// TcpBuilder is used with reuse_address and reuse_port set to "true" because +// the Actix HttpServer in webserver.rs will bind to this SocketAddr. +pub fn get_reusable_socket_addr(ip: IpAddr, port: u16) -> DfxResult { + let tcp_builder = match ip.is_ipv4() { + true => TcpBuilder::new_v4()?, + false => TcpBuilder::new_v6()?, + }; + Ok(tcp_builder + .bind(SocketAddr::new(ip, port))? + .reuse_address(true)? + .reuse_port(true)? + .to_tcp_listener()? + .local_addr()?) +} + /// Deserialize and print return values from canister method. pub fn print_idl_blob( blob: &Blob, From 7c81e5a70fbc73aa17ad1c48115c3b956137644c Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Wed, 12 Aug 2020 13:12:36 -0700 Subject: [PATCH 6/7] modify tests --- e2e/bats/bootstrap.bash | 6 +++--- e2e/bats/build.bash | 6 ++++-- e2e/bats/create.bash | 3 ++- e2e/bats/frontend.bash | 5 +++-- e2e/bats/network.bash | 9 ++++++--- e2e/bats/ping.bash | 9 ++++----- e2e/bats/utils/_.bash | 14 ++++++++++++-- 7 files changed, 34 insertions(+), 18 deletions(-) diff --git a/e2e/bats/bootstrap.bash b/e2e/bats/bootstrap.bash index 8a08648aac..0d1df0343c 100644 --- a/e2e/bats/bootstrap.bash +++ b/e2e/bats/bootstrap.bash @@ -18,10 +18,10 @@ teardown() { dfx build dfx canister install hello ID=$(dfx canister id hello) - - assert_command curl http://localhost:8000/_/candid?canisterId="$ID" -o ./web.txt + PORT=$(cat .dfx/webserver-port) + assert_command curl http://localhost:"$PORT"/_/candid?canisterId="$ID" -o ./web.txt assert_command diff .dfx/local/canisters/hello/hello.did ./web.txt - assert_command curl http://localhost:8000/_/candid?canisterId="$ID"\&format=js -o ./web.txt + assert_command curl http://localhost:"$PORT"/_/candid?canisterId="$ID"\&format=js -o ./web.txt # Relax diff as it's produced by two different compilers. assert_command diff --ignore-all-space --ignore-blank-lines .dfx/local/canisters/hello/hello.did.js ./web.txt } diff --git a/e2e/bats/build.bash b/e2e/bats/build.bash index c6a8676897..15b4025887 100644 --- a/e2e/bats/build.bash +++ b/e2e/bats/build.bash @@ -93,7 +93,8 @@ teardown() { @test "build succeeds when requested network is configured" { dfx_start - assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:8000" ]' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:'$webserver_port'" ]' assert_command dfx canister --network tungsten create --all assert_command dfx build --network tungsten } @@ -108,7 +109,8 @@ teardown() { @test "build output for non-local network is in expected directory" { dfx_start - assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:8000" ]' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:'$webserver_port'" ]' dfx canister --network tungsten create --all assert_command dfx build --network tungsten assert_command ls .dfx/tungsten/canisters/e2e_project/ diff --git a/e2e/bats/create.bash b/e2e/bats/create.bash index 00c289ec78..b7004bce75 100644 --- a/e2e/bats/create.bash +++ b/e2e/bats/create.bash @@ -52,7 +52,8 @@ teardown() { @test "create succeeds when requested network is configured" { dfx_start - assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:8000" ]' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:'$webserver_port'" ]' assert_command dfx canister --network tungsten create --all } diff --git a/e2e/bats/frontend.bash b/e2e/bats/frontend.bash index c242347596..31cda2626a 100644 --- a/e2e/bats/frontend.bash +++ b/e2e/bats/frontend.bash @@ -19,7 +19,8 @@ teardown() { dfx build --skip-frontend sleep 1 - assert_command curl http://localhost:8000 # 8000 = default port. + PORT=$(cat .dfx/webserver-port) + assert_command curl http://localhost:"$PORT" assert_match "" } @@ -33,7 +34,7 @@ teardown() { dfx canister create --all dfx build --skip-frontend - assert_command curl http://localhost:12345 # 8000 = default port. + assert_command curl http://localhost:12345 assert_match "" assert_command_fail curl http://localhost:8000 diff --git a/e2e/bats/network.bash b/e2e/bats/network.bash index 9a3abe0f6e..eec57d13cc 100644 --- a/e2e/bats/network.bash +++ b/e2e/bats/network.bash @@ -17,7 +17,8 @@ teardown() { @test "create stores canister ids for default-persistent networks in canister_ids.json" { dfx_start - assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:8000" ]' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:'$webserver_port'" ]' assert_command dfx canister --network tungsten create --all @@ -29,7 +30,8 @@ teardown() { @test "create stores canister ids for configured-ephemeral networks in canister_ids.json" { dfx_start - assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:8000" ]' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:'$webserver_port'" ]' cat <<<$(jq .networks.tungsten.type=\"ephemeral\" dfx.json) >dfx.json assert_command dfx canister --network tungsten create --all @@ -71,7 +73,8 @@ teardown() { @test "failure message does include network if for non-local network" { dfx_start - assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:8000" ]' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.tungsten.providers '[ "http://127.0.0.1:'$webserver_port'" ]' assert_command_fail dfx build --network tungsten assert_match "Cannot find canister id. Please issue 'dfx canister --network tungsten create e2e_project" diff --git a/e2e/bats/ping.bash b/e2e/bats/ping.bash index 62af13b3f5..44d6cb0530 100644 --- a/e2e/bats/ping.bash +++ b/e2e/bats/ping.bash @@ -17,9 +17,6 @@ teardown() { assert_command_fail dfx ping } -@test "dfx start succeeds" { - dfx_start -} @test "dfx ping succeeds if replica is running" { dfx_start @@ -30,7 +27,8 @@ teardown() { @test "dfx ping succeeds by specific host:post" { dfx_start - assert_command dfx ping http://127.0.0.1:8000 + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx ping http://127.0.0.1:"$webserver_port" assert_match "\"ic_api_version\"" } @@ -44,7 +42,8 @@ teardown() { @test "dfx ping succeeds by network name if network bind address is host:port format" { dfx_start - assert_command dfx config networks.local.bind '"127.0.0.1:8000"' + webserver_port=$(cat .dfx/webserver-port) + assert_command dfx config networks.local.bind '"127.0.0.1:'$webserver_port'"' assert_command dfx ping local assert_match "\"ic_api_version\"" diff --git a/e2e/bats/utils/_.bash b/e2e/bats/utils/_.bash index 003e9c3cd1..833b3a5fe3 100644 --- a/e2e/bats/utils/_.bash +++ b/e2e/bats/utils/_.bash @@ -43,21 +43,31 @@ dfx_start() { cat <<<$(jq .networks.local.bind=\"127.0.0.1:${port}\" dfx.json) >dfx.json cat dfx.json - dfx bootstrap --port 8000 & + dfx bootstrap --port 0 & # Start on random port for parallel test execution + local webserver_port=$(cat .dfx/webserver-port) echo $! > dfx-bootstrap.pid else # Bats creates a FD 3 for test output, but child processes inherit it and Bats will # wait for it to close. Because `dfx start` leaves child processes running, we need # to close this pipe, otherwise Bats will wait indefinitely. - dfx start --background "$@" 3>&- + if [[ "$@" == "" ]]; then + dfx start --background --host "127.0.0.1:0" 3>&- # Start on random port for parallel test execution + else + dfx start --background "$@" 3>&- # Start on random port for parallel test execution + fi local project_dir=${pwd} local dfx_config_root=.dfx/client-configuration printf "Configuration Root for DFX: %s\n" "${dfx_config_root}" test -f ${dfx_config_root}/client-1.port local port=$(cat ${dfx_config_root}/client-1.port) + + # Overwrite the default networks.local.bind 127.0.0.1:8000 with allocated port + local webserver_port=$(cat .dfx/webserver-port) + cat <<<$(jq .networks.local.bind=\"127.0.0.1:${webserver_port}\" dfx.json) >dfx.json fi printf "Replica Configured Port: %s\n" "${port}" + printf "Webserver Configured Port: %s\n" "${webserver_port}" timeout 5 sh -c \ "until nc -z localhost ${port}; do echo waiting for replica; sleep 1; done" \ From 6efa2bf1dca1f5d9995f195b392141bc45818b54 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Wed, 12 Aug 2020 13:26:13 -0700 Subject: [PATCH 7/7] fix fmt and clippy --- src/dfx/src/commands/start.rs | 7 ++++--- src/dfx/src/util/mod.rs | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 718a9640aa..a38353ac50 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -303,9 +303,10 @@ fn frontend_address(args: &ArgMatches<'_>, config: &Config) -> DfxResult<(String address_and_port = get_reusable_socket_addr(address_and_port.ip(), address_and_port.port())?; } - let ip = match address_and_port.is_ipv6() { - true => format!("[{}]", address_and_port.ip()), - false => address_and_port.ip().to_string(), + let ip = if address_and_port.is_ipv6() { + format!("[{}]", address_and_port.ip()) + } else { + address_and_port.ip().to_string() }; let frontend_url = format!("http://{}:{}", ip, address_and_port.port()); println!("frontend_url {:?}", frontend_url); diff --git a/src/dfx/src/util/mod.rs b/src/dfx/src/util/mod.rs index 38ecf3c11c..ea891022ef 100644 --- a/src/dfx/src/util/mod.rs +++ b/src/dfx/src/util/mod.rs @@ -14,9 +14,10 @@ pub mod clap; // TcpBuilder is used with reuse_address and reuse_port set to "true" because // the Actix HttpServer in webserver.rs will bind to this SocketAddr. pub fn get_reusable_socket_addr(ip: IpAddr, port: u16) -> DfxResult { - let tcp_builder = match ip.is_ipv4() { - true => TcpBuilder::new_v4()?, - false => TcpBuilder::new_v6()?, + let tcp_builder = if ip.is_ipv4() { + TcpBuilder::new_v4()? + } else { + TcpBuilder::new_v6()? }; Ok(tcp_builder .bind(SocketAddr::new(ip, port))?