From c673f5db6818bc93d33674ebe833645f944133bd Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sun, 12 Feb 2023 21:03:28 +0100 Subject: [PATCH] node: Add some useful test utility functions --- Cargo.lock | 1 + radicle-node/Cargo.toml | 4 ++- radicle-node/src/test/environment.rs | 54 +++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 010282b7..3f16c39a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2007,6 +2007,7 @@ dependencies = [ "scrypt", "serde", "serde_json", + "snapbox", "sqlite", "sqlite3-src", "tempfile", diff --git a/radicle-node/Cargo.toml b/radicle-node/Cargo.toml index 07f4ec9f..c039a85d 100644 --- a/radicle-node/Cargo.toml +++ b/radicle-node/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Alexis Sellier "] edition = "2021" [features] -test = ["radicle/test", "radicle-crypto/test", "radicle-crypto/cyphernet", "qcheck"] +test = ["radicle/test", "radicle-crypto/test", "radicle-crypto/cyphernet", "qcheck", "snapbox"] [dependencies] amplify = { version = "4.0.0-beta.7" } @@ -32,6 +32,7 @@ sqlite3-src = { version = "0.4.0", features = ["bundled"] } # Ensures static lin scrypt = { version = "0.10.0", default-features = false } serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } +snapbox = { version = "0.4.3", optional = true } tempfile = { version = "3.3.0" } thiserror = { version = "1" } @@ -45,3 +46,4 @@ radicle = { path = "../radicle", version = "*", features = ["test"] } radicle-crypto = { path = "../radicle-crypto", version = "*", features = ["test", "cyphernet"] } qcheck = { version = "1", default-features = false } qcheck-macros = { version = "1", default-features = false } +snapbox = { version = "0.4.3" } diff --git a/radicle-node/src/test/environment.rs b/radicle-node/src/test/environment.rs index 21d5ffab..46652c00 100644 --- a/radicle-node/src/test/environment.rs +++ b/radicle-node/src/test/environment.rs @@ -2,13 +2,14 @@ use std::mem::ManuallyDrop; use std::path::{Path, PathBuf}; use std::{ collections::{BTreeMap, BTreeSet}, - iter, net, thread, + env, fs, io, iter, net, process, thread, time::Duration, }; use radicle::crypto::ssh::{keystore::MemorySigner, Keystore}; use radicle::crypto::test::signer::MockSigner; use radicle::crypto::{KeyPair, Seed, Signature, Signer}; +use radicle::git; use radicle::git::refname; use radicle::identity::Id; use radicle::node::Handle as _; @@ -159,6 +160,57 @@ impl NodeHandle { ) -> BTreeSet<(Id, NodeId)> { converge(iter::once(self).chain(remotes.into_iter())) } + + /// Wait until this node's routing table contains the given routes. + pub fn routes_to(&self, routes: &[(Id, NodeId)]) { + let mut remaining: BTreeSet<_> = routes.iter().collect(); + + while !remaining.is_empty() { + for (rid, nid) in self.handle.routing().unwrap() { + remaining.remove(&(rid, nid)); + } + thread::sleep(Duration::from_millis(100)); + } + log::debug!(target: "test", "Node {} routes to {:?}", self.id, routes); + } + + /// Run a `rad` CLI command. + pub fn rad>(&self, cmd: &str, args: &[&str], cwd: P) -> io::Result<()> { + let cwd = cwd.as_ref(); + log::debug!(target: "test", "Running `rad {cmd} {args:?}` in {}..", cwd.display()); + + fs::create_dir_all(cwd)?; + + let result = process::Command::new(snapbox::cmd::cargo_bin("rad")) + .env_clear() + .envs(env::vars().filter(|(k, _)| k == "PATH")) + .env("GIT_AUTHOR_DATE", "1671125284") + .env("GIT_AUTHOR_EMAIL", "radicle@localhost") + .env("GIT_AUTHOR_NAME", "radicle") + .env("GIT_COMMITTER_DATE", "1671125284") + .env("GIT_COMMITTER_EMAIL", "radicle@localhost") + .env("GIT_COMMITTER_NAME", "radicle") + .env("RAD_HOME", self.home.path().to_string_lossy().to_string()) + .env("RAD_PASSPHRASE", "radicle") + .env("TZ", "UTC") + .env("LANG", "C") + .envs(git::env::GIT_DEFAULT_CONFIG) + .current_dir(cwd) + .arg(cmd) + .args(args) + .output()?; + + log::debug!( + target: "test", + "Ran command `rad {cmd}` (status={})", result.status.code().unwrap() + ); + + if !result.status.success() { + log::debug!(target: "test", "Command: {result:#?}"); + } + + Ok(()) + } } impl Node {