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:
parent
3aff91f9b7
commit
b78790622f
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue