cli: Improve test utilities

This will allow easy creation of multiple users with deterministic keys.

Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
Alexis Sellier 2023-01-24 10:46:57 +01:00
parent 3aff91f9b7
commit b78790622f
No known key found for this signature in database
3 changed files with 93 additions and 32 deletions

View File

@ -1,22 +1,67 @@
use std::env; use std::env;
use std::path::Path; use std::path::Path;
use radicle::crypto::ssh::Keystore;
use radicle::crypto::KeyPair;
use radicle::profile::{Home, Profile}; use radicle::profile::{Home, Profile};
use radicle::storage::git::transport;
use radicle::storage::git::Storage;
use radicle::test::fixtures; use radicle::test::fixtures;
mod framework; mod framework;
use framework::TestFormula; 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. /// Run a CLI test file.
fn test( fn test<'a>(
test: impl AsRef<Path>, test: impl AsRef<Path>,
cwd: 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>> { ) -> Result<(), Box<dyn std::error::Error>> {
let base = Path::new(env!("CARGO_MANIFEST_DIR")); let base = Path::new(env!("CARGO_MANIFEST_DIR"));
let tmp = tempfile::tempdir().unwrap(); let tmp = tempfile::tempdir().unwrap();
let home = if let Some(profile) = profile { let home = if let Some(home) = home {
profile.home().to_path_buf() home.path().to_path_buf()
} else { } else {
tmp.path().to_path_buf() tmp.path().to_path_buf()
}; };
@ -28,11 +73,11 @@ fn test(
.env("GIT_COMMITTER_DATE", "1671125284") .env("GIT_COMMITTER_DATE", "1671125284")
.env("GIT_COMMITTER_EMAIL", "radicle@localhost") .env("GIT_COMMITTER_EMAIL", "radicle@localhost")
.env("GIT_COMMITTER_NAME", "radicle") .env("GIT_COMMITTER_NAME", "radicle")
.env("RAD_DEBUG", "1")
.env("RAD_HOME", home.to_string_lossy()) .env("RAD_HOME", home.to_string_lossy())
.env("RAD_PASSPHRASE", "radicle") .env("RAD_PASSPHRASE", "radicle")
.env("TZ", "Etc/GMT") .env("TZ", "Etc/GMT")
.env(radicle_cob::git::RAD_COMMIT_TIME, "1671125284") .env(radicle_cob::git::RAD_COMMIT_TIME, "1671125284")
.envs(envs)
.cwd(cwd) .cwd(cwd)
.file(base.join(test))? .file(base.join(test))?
.run()?; .run()?;
@ -40,70 +85,77 @@ fn test(
Ok(()) 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] #[test]
fn rad_auth() { 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] #[test]
fn rad_issue() { 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 working = tempfile::tempdir().unwrap();
let profile = profile(home.path());
// Setup a test repository. // Setup a test repository.
fixtures::repository(working.path()); fixtures::repository(working.path());
// Set a fixed commit time. // Set a fixed commit time.
env::set_var(radicle_cob::git::RAD_COMMIT_TIME, "1671125284"); env::set_var(radicle_cob::git::RAD_COMMIT_TIME, "1671125284");
test("examples/rad-init.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
test("examples/rad-issue.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-issue.md", working.path(), Some(home), []).unwrap();
} }
#[test] #[test]
fn rad_init() { fn rad_init() {
let home = tempfile::tempdir().unwrap(); let mut environment = Environment::new();
let profile = environment.profile("alice");
let working = tempfile::tempdir().unwrap(); let working = tempfile::tempdir().unwrap();
let profile = profile(home.path());
// Setup a test repository. // Setup a test repository.
fixtures::repository(working.path()); 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] #[test]
fn rad_delegate() { fn rad_delegate() {
let home = tempfile::tempdir().unwrap(); let mut environment = Environment::new();
let profile = environment.profile("alice");
let working = tempfile::tempdir().unwrap(); let working = tempfile::tempdir().unwrap();
let profile = profile(home.path()); let home = &profile.home;
// Setup a test repository. // Setup a test repository.
fixtures::repository(working.path()); fixtures::repository(working.path());
test("examples/rad-init.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
test("examples/rad-delegate.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-delegate.md", working.path(), Some(home), []).unwrap();
} }
#[test] #[test]
#[ignore] #[ignore]
fn rad_patch() { fn rad_patch() {
let home = tempfile::tempdir().unwrap(); let mut environment = Environment::new();
let profile = environment.profile("alice");
let working = tempfile::tempdir().unwrap(); let working = tempfile::tempdir().unwrap();
let profile = profile(home.path()); let home = &profile.home;
// Setup a test repository. // Setup a test repository.
fixtures::repository(working.path()); fixtures::repository(working.path());
test("examples/rad-init.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
test("examples/rad-issue.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-issue.md", working.path(), Some(home), []).unwrap();
test("examples/rad-patch.md", working.path(), Some(&profile)).unwrap(); test("examples/rad-patch.md", working.path(), Some(home), []).unwrap();
} }

View File

@ -70,6 +70,16 @@ impl TestFormula {
self 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> { pub fn file(&mut self, path: impl AsRef<Path>) -> Result<&mut Self, Error> {
let contents = fs::read(path)?; let contents = fs::read(path)?;
self.read(io::Cursor::new(contents)) self.read(io::Cursor::new(contents))

View File

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