Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli-test: Build radicle binaries automatically
Alexis Sellier committed 2 years ago
commit 97f122c4512fbc5ea0b04a11db01d0d2d0977527
parent 21533f37ebde5fda1dc56594ff0e6f546736cc3a
4 files changed +90 -16
modified Cargo.lock
@@ -834,6 +834,18 @@ dependencies = [
]

[[package]]
+
name = "escargot"
+
version = "0.5.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f5584ba17d7ab26a8a7284f13e5bd196294dd2f2d79773cff29b9e9edef601a6"
+
dependencies = [
+
 "log",
+
 "once_cell",
+
 "serde",
+
 "serde_json",
+
]
+

+
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1947,6 +1959,7 @@ dependencies = [
name = "radicle-cli-test"
version = "0.1.1"
dependencies = [
+
 "escargot",
 "log",
 "pretty_assertions",
 "shlex",
modified radicle-cli-test/Cargo.toml
@@ -15,6 +15,7 @@ keywords = ["cli", "test", "command"]
readme = "README.md"

[dependencies]
+
escargot = { version = "0.5.7" }
log = { version = "0.4", features = ["std"] }
pretty_assertions = { version = "1.3.0" }
shlex = { version = "1.1.0" }
modified radicle-cli-test/src/lib.rs
@@ -2,12 +2,16 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
-
use std::{env, fs, io, mem};
+
use std::sync;
+
use std::{env, ffi, fs, io, mem};

use snapbox::cmd::{Command, OutputAssert};
use snapbox::{Assert, Substitutions};
use thiserror::Error;

+
/// Used to ensure the build task is only run once.
+
static BUILD: sync::Once = sync::Once::new();
+

#[derive(Error, Debug)]
pub enum Error {
    #[error("parsing failed")]
@@ -66,6 +70,8 @@ pub struct TestFormula {
    tests: Vec<Test>,
    /// Output substitutions.
    subs: Substitutions,
+
    /// Binaries path.
+
    bins: Vec<PathBuf>,
}

impl TestFormula {
@@ -75,9 +81,62 @@ impl TestFormula {
            env: HashMap::new(),
            tests: Vec::new(),
            subs: Substitutions::new(),
+
            bins: env::var("PATH")
+
                .map(|p| p.split(':').map(PathBuf::from).collect())
+
                .unwrap_or_default(),
        }
    }

+
    pub fn build(&mut self, binaries: &[(&str, &str)]) -> &mut Self {
+
        let manifest = env::var("CARGO_MANIFEST_DIR").expect(
+
            "TestFormula::build: cannot build binaries: variable `CARGO_MANIFEST_DIR` is not set",
+
        );
+
        let profile = if cfg!(debug_assertions) {
+
            "debug"
+
        } else {
+
            "release"
+
        };
+
        let target_dir = env::var("CARGO_TARGET_DIR").unwrap_or("target".to_string());
+
        let manifest = Path::new(manifest.as_str());
+
        let bins = manifest.join(&target_dir).join(profile);
+

+
        // Add the target dir to the beginning of the list we will use as `PATH`.
+
        self.bins.insert(0, bins);
+

+
        // We don't need to re-build everytime the `build` function is called. Once is enough.
+
        BUILD.call_once(|| {
+
            use escargot::format::Message;
+

+
            for (package, binary) in binaries {
+
                log::debug!(target: "test", "Building binaries for package `{package}`..");
+

+
                let results = escargot::CargoBuild::new()
+
                    .package(package)
+
                    .bin(binary)
+
                    .manifest_path(&manifest.join("Cargo.toml"))
+
                    .target_dir(&target_dir)
+
                    .exec()
+
                    .unwrap();
+

+
                for result in results {
+
                    match result {
+
                        Ok(msg) => {
+
                            if let Ok(Message::CompilerArtifact(a)) = msg.decode() {
+
                                if let Some(e) = a.executable {
+
                                    log::debug!(target: "test", "Built {}", e.display());
+
                                }
+
                            }
+
                        }
+
                        Err(e) => {
+
                            log::error!(target: "test", "Error building package `{package}`: {e}");
+
                        }
+
                    }
+
                }
+
            }
+
        });
+
        self
+
    }
+

    pub fn cwd(&mut self, path: impl AsRef<Path>) -> &mut Self {
        self.cwd = path.as_ref().into();
        self
@@ -208,21 +267,7 @@ impl TestFormula {
        let assert = Assert::new().substitutions(self.subs.clone());

        fs::create_dir_all(&self.cwd)?;
-

-
        let mut bins = env::var("PATH").unwrap_or_default();
-
        if let Ok(manifest) = env::var("CARGO_MANIFEST_DIR") {
-
            let profile = if cfg!(debug_assertions) {
-
                "debug"
-
            } else {
-
                "release"
-
            };
-
            let cargo_target_dir = env::var("CARGO_TARGET_DIR").unwrap_or("target".to_string());
-
            let path = Path::new(manifest.as_str());
-
            let path = path.parent().unwrap().join(cargo_target_dir).join(profile);
-

-
            bins = format!("{}:{bins}", path.display());
-
        }
-
        log::debug!(target: "test", "Using PATH={bins}");
+
        log::debug!(target: "test", "Using PATH {:?}", self.bins);

        for test in &self.tests {
            for assertion in &test.assertions {
@@ -258,6 +303,12 @@ impl TestFormula {
                    log::error!(target: "test", "{path}: Directory {} does not exist..", self.cwd.display());
                }

+
                let bins = self
+
                    .bins
+
                    .iter()
+
                    .map(|p| p.as_os_str())
+
                    .collect::<Vec<_>>()
+
                    .join(ffi::OsStr::new(":"));
                let result = Command::new(cmd.clone())
                    .env_clear()
                    .env("PATH", &bins)
@@ -342,6 +393,11 @@ $ rad sync
            cwd: PathBuf::new(),
            env: HashMap::new(),
            subs: Substitutions::new(),
+
            bins: env::var("PATH")
+
                .unwrap()
+
                .split(':')
+
                .map(PathBuf::from)
+
                .collect(),
            tests: vec![
                Test {
                    context: vec![String::from("Let's try to track @dave and @sean:")],
modified radicle-cli/tests/commands.rs
@@ -53,6 +53,10 @@ fn test<'a>(
        .envs(git::env::GIT_DEFAULT_CONFIG)
        .envs(envs)
        .cwd(cwd)
+
        .build(&[
+
            ("radicle-remote-helper", "git-remote-rad"),
+
            ("radicle-cli", "rad"),
+
        ])
        .file(base.join(test))?
        .run()?;