Speed up node E2E tests
By allowing the node to run using a `MockSigner`, we speed up tests significantly, since PBKDF2 doesn't need to run. Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
parent
72cb2fd713
commit
d31968509d
|
|
@ -80,7 +80,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
|
||||
pub fn clone(id: Id, _interactive: Interactive, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||
let profile = ctx.profile()?;
|
||||
let mut node = radicle::node::connect(profile.node())?;
|
||||
let mut node = radicle::node::connect(profile.socket())?;
|
||||
let signer = term::signer(&profile)?;
|
||||
|
||||
// Track & fetch project.
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
let storage = &profile.storage;
|
||||
let (_, rid) = radicle::rad::cwd().context("this command must be run within a project")?;
|
||||
let project = storage.repository(rid)?.project_of(profile.id())?;
|
||||
let mut node = radicle::node::connect(profile.node())?;
|
||||
let mut node = radicle::node::connect(profile.socket())?;
|
||||
|
||||
term::info!(
|
||||
"Establishing 🌱 tracking relationship for {}",
|
||||
|
|
|
|||
|
|
@ -88,6 +88,6 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
pub fn untrack(id: Id, profile: &Profile) -> anyhow::Result<bool> {
|
||||
let mut node = radicle::node::connect(profile.node())?;
|
||||
let mut node = radicle::node::connect(profile.socket())?;
|
||||
node.untrack_repo(id).map_err(|e| anyhow!(e))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ fn test(
|
|||
let base = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let home = if let Some(profile) = profile {
|
||||
profile.home.as_path().to_path_buf()
|
||||
profile.home().to_path_buf()
|
||||
} else {
|
||||
tmp.path().to_path_buf()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,3 +71,28 @@ impl Signer for MockSigner {
|
|||
Ok(self.sign(msg))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "cyphernet")]
|
||||
impl cyphernet::EcSk for MockSigner {
|
||||
type Pk = PublicKey;
|
||||
|
||||
fn generate_keypair() -> (Self, Self::Pk)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
unimplemented! {}
|
||||
}
|
||||
|
||||
fn to_pk(&self) -> Result<Self::Pk, cyphernet::EcSkInvalid> {
|
||||
Ok(*self.public_key())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "cyphernet")]
|
||||
impl cyphernet::EcSign for MockSigner {
|
||||
type Sig = Signature;
|
||||
|
||||
fn sign(&self, msg: impl AsRef<[u8]>) -> Self::Sig {
|
||||
Signer::sign(self, msg.as_ref())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ pub async fn run(options: Options) -> anyhow::Result<()> {
|
|||
tracing::info!("{}", str::from_utf8(&git_version)?.trim());
|
||||
|
||||
let profile = Arc::new(radicle::Profile::load()?);
|
||||
tracing::info!("using radicle home at {}", profile.home.display());
|
||||
tracing::info!("using radicle home at {}", profile.home().display());
|
||||
|
||||
let git_router = Router::new()
|
||||
.route("/:project/*request", any(git_handler))
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::io;
|
||||
use std::{net, thread, time};
|
||||
use std::{io, net, thread, time};
|
||||
|
||||
use cyphernet::{Cert, EcSign};
|
||||
use netservices::resource::NetAccept;
|
||||
use radicle::profile::Paths;
|
||||
use radicle::Storage;
|
||||
use reactor::poller::popol;
|
||||
use reactor::Reactor;
|
||||
use thiserror::Error;
|
||||
|
|
@ -14,7 +15,7 @@ use crate::node::NodeId;
|
|||
use crate::service::{routing, tracking};
|
||||
use crate::wire::Wire;
|
||||
use crate::worker::{WorkerPool, WorkerReq};
|
||||
use crate::{crypto, profile, service, LocalTime};
|
||||
use crate::{crypto, service, LocalTime};
|
||||
|
||||
pub mod handle;
|
||||
use handle::Handle;
|
||||
|
|
@ -66,19 +67,19 @@ impl<G: crypto::Signer + EcSign<Pk = NodeId, Sig = Signature> + Clone + 'static>
|
|||
///
|
||||
/// This function spawns threads.
|
||||
pub fn with(
|
||||
profile: profile::Profile,
|
||||
paths: Paths,
|
||||
config: service::Config,
|
||||
listen: Vec<net::SocketAddr>,
|
||||
proxy: net::SocketAddr,
|
||||
signer: G,
|
||||
) -> Result<Runtime<G>, Error> {
|
||||
let id = *profile.id();
|
||||
let node = profile.node();
|
||||
let id = *signer.public_key();
|
||||
let node_sock = paths.socket();
|
||||
let node_dir = paths.node();
|
||||
let network = config.network;
|
||||
let rng = fastrand::Rng::new();
|
||||
let clock = LocalTime::now();
|
||||
let storage = profile.storage;
|
||||
let node_dir = profile.home.join(NODE_DIR);
|
||||
let storage = Storage::open(paths.storage())?;
|
||||
let address_db = node_dir.join(ADDRESS_DB_FILE);
|
||||
let routing_db = node_dir.join(ROUTING_DB_FILE);
|
||||
let tracking_db = node_dir.join(TRACKING_DB_FILE);
|
||||
|
|
@ -122,7 +123,7 @@ impl<G: crypto::Signer + EcSign<Pk = NodeId, Sig = Signature> + Clone + 'static>
|
|||
let handle = Handle::from(reactor.controller());
|
||||
let control = thread::spawn({
|
||||
let handle = handle.clone();
|
||||
move || control::listen(node, handle)
|
||||
move || control::listen(node_sock, handle)
|
||||
});
|
||||
let controller = reactor.controller();
|
||||
let mut local_addrs = Vec::new();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use nakamoto_net::LocalDuration;
|
|||
|
||||
use radicle::profile;
|
||||
use radicle_node::client::Runtime;
|
||||
use radicle_node::crypto::ssh::keystore::MemorySigner;
|
||||
use radicle_node::crypto::ssh::keystore::{Keystore, MemorySigner};
|
||||
use radicle_node::prelude::{Address, NodeId};
|
||||
use radicle_node::profile::Paths;
|
||||
use radicle_node::{logger, service};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -77,11 +78,13 @@ fn main() -> anyhow::Result<()> {
|
|||
logger::init(log::Level::Debug)?;
|
||||
|
||||
let options = Options::from_env()?;
|
||||
let profile = radicle::Profile::load().context("Failed to load node profile")?;
|
||||
let home = profile::home()?;
|
||||
let paths = Paths::new(home);
|
||||
let passphrase = env::var(profile::env::RAD_PASSPHRASE)
|
||||
.context("`RAD_PASSPHRASE` is required to be set for the node to establish connections")?
|
||||
.into();
|
||||
let signer = MemorySigner::load(&profile.keystore, passphrase)?;
|
||||
let keystore = Keystore::new(&paths.keys());
|
||||
let signer = MemorySigner::load(&keystore, passphrase)?;
|
||||
let config = service::Config {
|
||||
connect: options.connect.into_iter().collect(),
|
||||
external_addresses: options.external_addresses,
|
||||
|
|
@ -89,7 +92,7 @@ fn main() -> anyhow::Result<()> {
|
|||
..service::Config::default()
|
||||
};
|
||||
let proxy = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 9050);
|
||||
let runtime = Runtime::with(profile, config, options.listen, proxy, signer)?;
|
||||
let runtime = Runtime::with(paths, config, options.listen, proxy, signer)?;
|
||||
|
||||
runtime.run()?;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
use radicle::crypto::ssh::keystore::MemorySigner;
|
||||
use radicle::crypto::test::signer::MockSigner;
|
||||
use radicle::git::refname;
|
||||
use radicle::identity::Id;
|
||||
use radicle::node::Handle;
|
||||
use radicle::profile::Paths;
|
||||
use radicle::storage::WriteStorage;
|
||||
use radicle::test::fixtures;
|
||||
use radicle::Profile;
|
||||
use radicle::Storage;
|
||||
use radicle::{assert_matches, rad};
|
||||
|
||||
|
|
@ -27,8 +27,8 @@ use crate::{client, client::Runtime, service};
|
|||
struct Node {
|
||||
id: NodeId,
|
||||
addr: net::SocketAddr,
|
||||
handle: client::handle::Handle<Wire<routing::Table, address::Book, Storage, MemorySigner>>,
|
||||
signer: MemorySigner,
|
||||
handle: client::handle::Handle<Wire<routing::Table, address::Book, Storage, MockSigner>>,
|
||||
signer: MockSigner,
|
||||
storage: Storage,
|
||||
#[allow(dead_code)]
|
||||
thread: thread::JoinHandle<Result<(), client::Error>>,
|
||||
|
|
@ -42,15 +42,12 @@ impl Node {
|
|||
.take(8)
|
||||
.collect::<String>(),
|
||||
);
|
||||
|
||||
let profile = Profile::init(home.as_path(), "pasphrase".to_owned()).unwrap();
|
||||
let signer = MemorySigner::load(&profile.keystore, "pasphrase".to_owned().into()).unwrap();
|
||||
let paths = Paths::init(home).unwrap();
|
||||
let signer = MockSigner::default();
|
||||
let listen = vec![([0, 0, 0, 0], 0).into()];
|
||||
let proxy = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 9050);
|
||||
let storage = profile.storage.clone();
|
||||
|
||||
let rt = Runtime::with(profile, config, listen, proxy, signer.clone()).unwrap();
|
||||
|
||||
let storage = Storage::open(paths.storage()).unwrap();
|
||||
let rt = Runtime::with(paths, config, listen, proxy, signer.clone()).unwrap();
|
||||
let addr = *rt.local_addrs.first().unwrap();
|
||||
let id = rt.id;
|
||||
let handle = rt.handle.clone();
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Box<dyn std::error::Error +
|
|||
// Connect to local node and announce refs to the network.
|
||||
// If our node is not running, we simply skip this step, as the
|
||||
// refs will be announced eventually, when the node restarts.
|
||||
if let Ok(mut conn) = radicle::node::connect(profile.node()) {
|
||||
if let Ok(mut conn) = radicle::node::connect(profile.socket()) {
|
||||
conn.announce_refs(url.repo)?;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ fn main() -> anyhow::Result<()> {
|
|||
};
|
||||
|
||||
println!("id: {}", profile.id());
|
||||
println!("home: {}", profile.home.display());
|
||||
println!("home: {}", profile.home().display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ fn main() -> anyhow::Result<()> {
|
|||
|
||||
if let Some(id) = env::args().nth(1) {
|
||||
let id = Id::from_str(&id)?;
|
||||
let mut node = radicle::node::connect(profile.node())?;
|
||||
let mut node = radicle::node::connect(profile.socket())?;
|
||||
let repo = radicle::rad::clone(id, &cwd, &signer, &profile.storage, &mut node)?;
|
||||
|
||||
println!(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ fn main() -> anyhow::Result<()> {
|
|||
let sigrefs = project.sign_refs(&signer)?;
|
||||
let head = project.set_head()?;
|
||||
|
||||
radicle::node::connect(profile.node())?.announce_refs(id)?;
|
||||
radicle::node::connect(profile.socket())?.announce_refs(id)?;
|
||||
|
||||
println!("head: {}", head);
|
||||
println!("ok: {}", sigrefs.signature);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ fn main() -> anyhow::Result<()> {
|
|||
"fingerprint: {}",
|
||||
radicle::crypto::ssh::fmt::fingerprint(profile.id())
|
||||
);
|
||||
println!("home: {}", profile.home.display());
|
||||
println!("home: {}", profile.home().display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ pub enum Error {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Profile {
|
||||
pub home: PathBuf,
|
||||
pub paths: Paths,
|
||||
pub storage: Storage,
|
||||
pub keystore: Keystore,
|
||||
pub public_key: PublicKey,
|
||||
|
|
@ -68,19 +68,15 @@ pub struct Profile {
|
|||
impl Profile {
|
||||
pub fn init(home: impl AsRef<Path>, passphrase: impl Into<Passphrase>) -> Result<Self, Error> {
|
||||
let home = home.as_ref().to_path_buf();
|
||||
let paths = Paths {
|
||||
home: home.as_path(),
|
||||
};
|
||||
let paths = Paths::init(home.as_path())?;
|
||||
let storage = Storage::open(paths.storage())?;
|
||||
let keystore = Keystore::new(&paths.keys());
|
||||
let public_key = keystore.init("radicle", passphrase)?;
|
||||
|
||||
fs::create_dir_all(paths.node()).ok();
|
||||
|
||||
transport::local::register(storage.clone());
|
||||
|
||||
Ok(Profile {
|
||||
home,
|
||||
paths,
|
||||
storage,
|
||||
keystore,
|
||||
public_key,
|
||||
|
|
@ -89,16 +85,17 @@ impl Profile {
|
|||
|
||||
pub fn load() -> Result<Self, Error> {
|
||||
let home = self::home()?;
|
||||
let storage = Storage::open(home.join("storage"))?;
|
||||
let keystore = Keystore::new(&home.join("keys"));
|
||||
let paths = Paths::new(home);
|
||||
let storage = Storage::open(paths.storage())?;
|
||||
let keystore = Keystore::new(&paths.keys());
|
||||
let public_key = keystore
|
||||
.public_key()?
|
||||
.ok_or_else(|| Error::NotFound(home.clone()))?;
|
||||
.ok_or_else(|| Error::NotFound(paths.home.clone()))?;
|
||||
|
||||
transport::local::register(storage.clone());
|
||||
|
||||
Ok(Profile {
|
||||
home,
|
||||
paths,
|
||||
storage,
|
||||
keystore,
|
||||
public_key,
|
||||
|
|
@ -130,19 +127,22 @@ impl Profile {
|
|||
|
||||
/// Return the path to the keys folder.
|
||||
pub fn keys(&self) -> PathBuf {
|
||||
self.home.join("keys")
|
||||
self.paths.keys()
|
||||
}
|
||||
|
||||
/// Get the profile home directory.
|
||||
pub fn home(&self) -> &Path {
|
||||
self.paths.home()
|
||||
}
|
||||
|
||||
/// Get the path to the radicle node socket.
|
||||
pub fn node(&self) -> PathBuf {
|
||||
env::var_os(env::RAD_SOCKET)
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| self.home.join("node").join(node::DEFAULT_SOCKET_NAME))
|
||||
pub fn socket(&self) -> PathBuf {
|
||||
self.paths.socket()
|
||||
}
|
||||
|
||||
/// Get `Paths` of profile
|
||||
pub fn paths(&self) -> Paths {
|
||||
Paths { home: &self.home }
|
||||
pub fn paths(&self) -> &Paths {
|
||||
&self.paths
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,13 +161,24 @@ pub fn home() -> Result<PathBuf, io::Error> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Paths<'a> {
|
||||
home: &'a Path,
|
||||
pub struct Paths {
|
||||
home: PathBuf,
|
||||
}
|
||||
|
||||
impl<'a> Paths<'a> {
|
||||
pub fn new(home: &'a Path) -> Self {
|
||||
Self { home }
|
||||
impl Paths {
|
||||
pub fn init(home: impl Into<PathBuf>) -> Result<Self, io::Error> {
|
||||
let paths = Self::new(home);
|
||||
fs::create_dir_all(paths.node()).ok();
|
||||
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
pub fn new(home: impl Into<PathBuf>) -> Self {
|
||||
Self { home: home.into() }
|
||||
}
|
||||
|
||||
pub fn home(&self) -> &Path {
|
||||
self.home.as_path()
|
||||
}
|
||||
|
||||
pub fn storage(&self) -> PathBuf {
|
||||
|
|
@ -181,4 +192,10 @@ impl<'a> Paths<'a> {
|
|||
pub fn node(&self) -> PathBuf {
|
||||
self.home.join("node")
|
||||
}
|
||||
|
||||
pub fn socket(&self) -> PathBuf {
|
||||
env::var_os(env::RAD_SOCKET)
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| self.node().join(node::DEFAULT_SOCKET_NAME))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue