diff --git a/Cargo.lock b/Cargo.lock index 1b321ba8f..3897d68e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3712,6 +3712,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "qcheck" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b439bd4242da51d62d18c95e6a6add749346756b0d1a587dfd0cc22fa6b5f3f0" +dependencies = [ + "rand 0.8.5", +] + [[package]] name = "qoi" version = "0.4.1" @@ -3762,6 +3771,7 @@ dependencies = [ "multibase", "nonempty", "once_cell", + "qcheck", "radicle-cob", "radicle-crypto", "radicle-git-ext", @@ -3801,7 +3811,9 @@ dependencies = [ "amplify", "cyphernet", "ec25519", + "fastrand", "multibase", + "qcheck", "radicle-git-ext", "radicle-ssh", "serde", @@ -3905,6 +3917,7 @@ dependencies = [ "radicle-surf", "serde", "serde_json", + "tempfile", "thiserror", "ts-rs", ] @@ -4265,9 +4278,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -5297,9 +5310,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -6063,7 +6076,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/crates/radicle-types/Cargo.toml b/crates/radicle-types/Cargo.toml index 10a5fb70e..8e458eaea 100644 --- a/crates/radicle-types/Cargo.toml +++ b/crates/radicle-types/Cargo.toml @@ -7,10 +7,11 @@ edition = "2021" anyhow = { version = "1.0.90" } axum = { version = "0.7.5", default-features = false, features = ["json"] } base64 = { version = "0.22.1" } -radicle = { git = "https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5.git" } +radicle = { git = "https://seed.radicle.xyz/z3gqcJUoA1n9HaHKufZs5FCSGazv5.git", features = ["test"] } radicle-surf = { version = "0.22.1", features = ["serde"] } serde = { version = "1.0.210", features = ["derive"] } serde_json = { version = "1.0.132" } thiserror = { version = "1.0.65" } ts-rs = { version = "10.0.0", features = [ "serde-json-impl", "no-serde-warnings" ] } localtime = { version = "1.3.1" } +tempfile = { version = "3.14.0" } diff --git a/crates/radicle-types/src/test.rs b/crates/radicle-types/src/test.rs new file mode 100644 index 000000000..c69bb7777 --- /dev/null +++ b/crates/radicle-types/src/test.rs @@ -0,0 +1,58 @@ +use std::path::Path; + +use radicle::cob::migrate; +use radicle::crypto::ssh::Keystore; +use radicle::crypto::{KeyPair, Seed}; +use radicle::node::{Features, Timestamp, UserAgent}; +use radicle::profile::Home; +use radicle::Storage; +use radicle::{node, profile}; + +pub const TIMESTAMP: u64 = 1671125284; + +/// Create a new profile. +pub fn profile(home: &Path, seed: [u8; 32]) -> radicle::Profile { + let home = Home::new(home).unwrap(); + let keystore = Keystore::new(&home.keys()); + + let keypair = KeyPair::from_seed(Seed::from(seed)); + let alias = node::Alias::new("seed"); + let storage = Storage::open( + home.storage(), + radicle::git::UserInfo { + alias: alias.clone(), + key: keypair.pk.into(), + }, + ) + .unwrap(); + + let mut db = home.policies_mut().unwrap(); + db.follow(&keypair.pk.into(), Some(&alias)).unwrap(); + + let node_db = home.database_mut().unwrap(); + node_db + .init( + &keypair.pk.into(), + Features::SEED, + &alias, + &UserAgent::default(), + Timestamp::try_from(TIMESTAMP).unwrap(), + [], + ) + .unwrap(); + + // Migrate COBs cache. + let mut cobs = home.cobs_db_mut().unwrap(); + cobs.migrate(migrate::ignore).unwrap(); + + radicle::storage::git::transport::local::register(storage.clone()); + keystore.store(keypair.clone(), "radicle", None).unwrap(); + + radicle::Profile { + home, + storage, + keystore, + public_key: keypair.pk.into(), + config: profile::Config::new(alias), + } +} diff --git a/crates/radicle-types/src/traits.rs b/crates/radicle-types/src/traits.rs index 8ead8766e..be9cf20aa 100644 --- a/crates/radicle-types/src/traits.rs +++ b/crates/radicle-types/src/traits.rs @@ -20,3 +20,33 @@ pub trait Profile { } } } + +#[cfg(test)] +#[allow(clippy::unwrap_used)] +mod test { + use std::str::FromStr; + + use radicle::crypto::test::signer::MockSigner; + use radicle::crypto::Signer; + use radicle::node::{config, Alias}; + + use crate::config::Config; + use crate::{test, AppState, Profile}; + + #[test] + fn config() { + let tmp = tempfile::tempdir().unwrap(); + let profile = test::profile(tmp.path(), [0xff; 32]); + let signer = MockSigner::from_seed([0xff; 32]); + let state = AppState { profile }; + + assert_eq!( + Profile::config(&state), + Config { + public_key: *signer.public_key(), + alias: Alias::from_str("seed").unwrap(), + seeding_policy: config::DefaultSeedingPolicy::Block, + } + ) + } +}