Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Improve test utilities
Alexis Sellier committed 3 years ago
commit b78790622fb2b1cb4e7243da191cb8a856472031
parent 3aff91f9b7815ce698195f10fcb5cb6d7cdb0d94
3 files changed +93 -32
modified radicle-cli/tests/commands.rs
@@ -1,22 +1,67 @@
use std::env;
use std::path::Path;

+
use radicle::crypto::ssh::Keystore;
+
use radicle::crypto::KeyPair;
use radicle::profile::{Home, Profile};
+
use radicle::storage::git::transport;
+
use radicle::storage::git::Storage;
use radicle::test::fixtures;

mod framework;
use framework::TestFormula;
+
use radicle_crypto::Seed;
+

+
/// Test environment.
+
pub struct Environment {
+
    tempdir: tempfile::TempDir,
+
    users: usize,
+
}
+

+
impl Environment {
+
    /// Create a new test environment.
+
    fn new() -> Self {
+
        Self {
+
            tempdir: tempfile::tempdir().unwrap(),
+
            users: 0,
+
        }
+
    }
+

+
    /// Create a new profile in this environment.
+
    fn profile(&mut self, name: &str) -> Profile {
+
        let home = Home::new(self.tempdir.path().join(name)).init().unwrap();
+
        let storage = Storage::open(home.storage()).unwrap();
+
        let keystore = Keystore::new(&home.keys());
+
        let keypair = KeyPair::from_seed(Seed::from([!(self.users as u8); 32]));
+

+
        transport::local::register(storage.clone());
+
        keystore
+
            .store(keypair.clone(), "radicle", "radicle".to_owned())
+
            .unwrap();
+

+
        // Ensures that each user has a unique but deterministic public key.
+
        self.users += 1;
+

+
        Profile {
+
            home,
+
            storage,
+
            keystore,
+
            public_key: keypair.pk.into(),
+
        }
+
    }
+
}

/// Run a CLI test file.
-
fn test(
+
fn test<'a>(
    test: impl AsRef<Path>,
    cwd: impl AsRef<Path>,
-
    profile: Option<&Profile>,
+
    home: Option<&Home>,
+
    envs: impl IntoIterator<Item = (&'a str, &'a str)>,
) -> Result<(), Box<dyn std::error::Error>> {
    let base = Path::new(env!("CARGO_MANIFEST_DIR"));
    let tmp = tempfile::tempdir().unwrap();
-
    let home = if let Some(profile) = profile {
-
        profile.home().to_path_buf()
+
    let home = if let Some(home) = home {
+
        home.path().to_path_buf()
    } else {
        tmp.path().to_path_buf()
    };
@@ -28,11 +73,11 @@ fn test(
        .env("GIT_COMMITTER_DATE", "1671125284")
        .env("GIT_COMMITTER_EMAIL", "radicle@localhost")
        .env("GIT_COMMITTER_NAME", "radicle")
-
        .env("RAD_DEBUG", "1")
        .env("RAD_HOME", home.to_string_lossy())
        .env("RAD_PASSPHRASE", "radicle")
        .env("TZ", "Etc/GMT")
        .env(radicle_cob::git::RAD_COMMIT_TIME, "1671125284")
+
        .envs(envs)
        .cwd(cwd)
        .file(base.join(test))?
        .run()?;
@@ -40,70 +85,77 @@ fn test(
    Ok(())
}

-
/// Create a new user profile.
-
fn profile(home: &Path) -> Profile {
-
    // Set debug mode, to make test output more predictable.
-
    env::set_var("RAD_DEBUG", "1");
-
    // Setup a new user.
-
    Profile::init(Home::new(home.to_path_buf()), "radicle".to_owned()).unwrap()
-
}
-

#[test]
fn rad_auth() {
-
    test("examples/rad-auth.md", Path::new("."), None).unwrap();
+
    test(
+
        "examples/rad-auth.md",
+
        Path::new("."),
+
        None,
+
        [("RAD_DEBUG", "1")],
+
    )
+
    .unwrap();
}

#[test]
fn rad_issue() {
-
    let home = tempfile::tempdir().unwrap();
+
    let mut environment = Environment::new();
+
    let profile = environment.profile("alice");
+
    let home = &profile.home;
    let working = tempfile::tempdir().unwrap();
-
    let profile = profile(home.path());

    // Setup a test repository.
    fixtures::repository(working.path());
    // Set a fixed commit time.
    env::set_var(radicle_cob::git::RAD_COMMIT_TIME, "1671125284");

-
    test("examples/rad-init.md", working.path(), Some(&profile)).unwrap();
-
    test("examples/rad-issue.md", working.path(), Some(&profile)).unwrap();
+
    test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
+
    test("examples/rad-issue.md", working.path(), Some(home), []).unwrap();
}

#[test]
fn rad_init() {
-
    let home = tempfile::tempdir().unwrap();
+
    let mut environment = Environment::new();
+
    let profile = environment.profile("alice");
    let working = tempfile::tempdir().unwrap();
-
    let profile = profile(home.path());

    // Setup a test repository.
    fixtures::repository(working.path());

-
    test("examples/rad-init.md", working.path(), Some(&profile)).unwrap();
+
    test(
+
        "examples/rad-init.md",
+
        working.path(),
+
        Some(&profile.home),
+
        [],
+
    )
+
    .unwrap();
}

#[test]
fn rad_delegate() {
-
    let home = tempfile::tempdir().unwrap();
+
    let mut environment = Environment::new();
+
    let profile = environment.profile("alice");
    let working = tempfile::tempdir().unwrap();
-
    let profile = profile(home.path());
+
    let home = &profile.home;

    // Setup a test repository.
    fixtures::repository(working.path());

-
    test("examples/rad-init.md", working.path(), Some(&profile)).unwrap();
-
    test("examples/rad-delegate.md", working.path(), Some(&profile)).unwrap();
+
    test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
+
    test("examples/rad-delegate.md", working.path(), Some(home), []).unwrap();
}

#[test]
#[ignore]
fn rad_patch() {
-
    let home = tempfile::tempdir().unwrap();
+
    let mut environment = Environment::new();
+
    let profile = environment.profile("alice");
    let working = tempfile::tempdir().unwrap();
-
    let profile = profile(home.path());
+
    let home = &profile.home;

    // Setup a test repository.
    fixtures::repository(working.path());

-
    test("examples/rad-init.md", working.path(), Some(&profile)).unwrap();
-
    test("examples/rad-issue.md", working.path(), Some(&profile)).unwrap();
-
    test("examples/rad-patch.md", working.path(), Some(&profile)).unwrap();
+
    test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
+
    test("examples/rad-issue.md", working.path(), Some(home), []).unwrap();
+
    test("examples/rad-patch.md", working.path(), Some(home), []).unwrap();
}
modified radicle-cli/tests/framework/mod.rs
@@ -70,6 +70,16 @@ impl TestFormula {
        self
    }

+
    pub fn envs<K: ToString, V: ToString>(
+
        &mut self,
+
        envs: impl IntoIterator<Item = (K, V)>,
+
    ) -> &mut Self {
+
        for (k, v) in envs {
+
            self.env.insert(k.to_string(), v.to_string());
+
        }
+
        self
+
    }
+

    pub fn file(&mut self, path: impl AsRef<Path>) -> Result<&mut Self, Error> {
        let contents = fs::read(path)?;
        self.read(io::Cursor::new(contents))
modified radicle-crypto/src/ssh/keystore.rs
@@ -201,8 +201,7 @@ impl MemorySigner {

    /// Generate a new memory signer.
    pub fn gen() -> Self {
-
        let seed = crate::Seed::generate();
-
        let keypair = KeyPair::from_seed(seed);
+
        let keypair = KeyPair::generate();
        let sk = keypair.sk;

        Self {