Skip to content

Commit

Permalink
migrate to local integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
itegulov committed Oct 18, 2023
1 parent 3b54535 commit 95e45d5
Show file tree
Hide file tree
Showing 14 changed files with 525 additions and 322 deletions.
20 changes: 9 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ publish = false
aes-gcm = "0.10"
anyhow = { version = "1.0", features = ["backtrace"] }
async-process = "1"
bollard = "0.11"
bollard = "0.13"
clap = { version = "4.2", features = ["derive", "env"] }
curv = { package = "curv-kzen", version = "0.9", default-features = false }
ed25519-dalek = { version = "1.0.1", features = ["serde"] }
futures = "0.3"
hex = "0.4.3"
hyper = { version = "0.14", features = ["full"] }
mpc-contract = { path = "../contract" }
mpc-recovery = { path = "../mpc-recovery" }
mpc-recovery-node = { path = "../node" }
multi-party-eddsa = { git = "https://github.com/DavidM-D/multi-party-eddsa.git", rev = "25ae4fdc5ff7819ae70e73ab4afacf1c24fc4da1" }
tracing = "0.1"
near-crypto = "0.17"
Expand All @@ -26,7 +28,7 @@ near-units = "0.2.0"
once_cell = "1"
serde = "1"
serde_json = "1"
testcontainers = { version = "0.14", features = ["experimental"] }
testcontainers = { version = "0.15", features = ["experimental"] }
tokio = { version = "1.28", features = ["full"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
near-workspaces = "0.8.0"
Expand Down
78 changes: 1 addition & 77 deletions integration-tests/src/env/containers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ use once_cell::sync::Lazy;
use testcontainers::{
clients::Cli,
core::{ExecCommand, WaitFor},
images::generic::GenericImage,
Container, Image, RunnableImage,
Container, GenericImage, Image, RunnableImage,
};
use tokio::io::AsyncWriteExt;
use tracing;
Expand Down Expand Up @@ -972,78 +971,3 @@ impl LeaderNodeApi {
.await
}
}

pub struct Node<'a> {
pub container: Container<'a, GenericImage>,
pub address: String,
pub local_address: String,
}

pub struct NodeApi {
pub address: String,
pub node_id: usize,
pub sk_share: ExpandedKeyPair,
pub cipher_key: GenericArray<u8, U32>,
pub gcp_project_id: String,
pub gcp_datastore_local_url: String,
}

impl<'a> Node<'a> {
// Container port used for the docker network, does not have to be unique
const CONTAINER_PORT: u16 = 3000;

pub async fn run(
docker_client: &'a DockerClient,
network: &str,
node_id: u64,
near_rpc: &str,
signer_account: &AccountId,
account: &AccountId,
account_sk: &near_workspaces::types::SecretKey,
) -> anyhow::Result<Node<'a>> {
tracing::info!(node_id, "running node container");
let image: GenericImage = GenericImage::new("near/mpc-recovery-node", "latest")
.with_wait_for(WaitFor::Nothing)
.with_exposed_port(Self::CONTAINER_PORT)
.with_env_var("RUST_LOG", "mpc_recovery_node=DEBUG")
.with_env_var("RUST_BACKTRACE", "1");
let image: RunnableImage<GenericImage> = (
image,
vec![
"start".to_string(),
"--node-id".to_string(),
node_id.to_string(),
"--near-rpc".to_string(),
near_rpc.to_string(),
"--mpc-contract-id".to_string(),
signer_account.to_string(),
"--account".to_string(),
account.to_string(),
"--account-sk".to_string(),
account_sk.to_string(),
"--web-port".to_string(),
Self::CONTAINER_PORT.to_string(),
],
)
.into();
let image = image.with_network(network);
let container = docker_client.cli.run(image);
let ip_address = docker_client
.get_network_ip_address(&container, network)
.await?;
let host_port = container.get_host_port_ipv4(Self::CONTAINER_PORT);

container.exec(ExecCommand {
cmd: format!("bash -c 'while [[ \"$(curl -s -o /dev/null -w ''%{{http_code}}'' localhost:{})\" != \"200\" ]]; do sleep 1; done'", Self::CONTAINER_PORT),
ready_conditions: vec![WaitFor::message_on_stdout("node is ready to accept connections")]
});

let full_address = format!("http://{ip_address}:{}", Self::CONTAINER_PORT);
tracing::info!(node_id, full_address, "node container is running");
Ok(Node {
container,
address: full_address,
local_address: format!("http://localhost:{host_port}"),
})
}
}
1 change: 1 addition & 0 deletions integration-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use near_workspaces::{
use crate::env::containers;

pub mod env;
pub mod multichain;
pub mod sandbox;
pub mod util;

Expand Down
72 changes: 72 additions & 0 deletions integration-tests/src/multichain/containers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use ed25519_dalek::ed25519::signature::digest::{consts::U32, generic_array::GenericArray};
use multi_party_eddsa::protocols::ExpandedKeyPair;
use near_workspaces::AccountId;
use testcontainers::{
core::{ExecCommand, WaitFor},
Container, GenericImage, RunnableImage,
};
use tracing;

pub struct Node<'a> {
pub container: Container<'a, GenericImage>,
pub address: String,
pub local_address: String,
}

pub struct NodeApi {
pub address: String,
pub node_id: usize,
pub sk_share: ExpandedKeyPair,
pub cipher_key: GenericArray<u8, U32>,
pub gcp_project_id: String,
pub gcp_datastore_local_url: String,
}

impl<'a> Node<'a> {
// Container port used for the docker network, does not have to be unique
const CONTAINER_PORT: u16 = 3000;

pub async fn run(
ctx: &super::Context<'a>,
node_id: u32,
account: &AccountId,
account_sk: &near_workspaces::types::SecretKey,
) -> anyhow::Result<Node<'a>> {
tracing::info!(node_id, "running node container");
let args = mpc_recovery_node::cli::Cli::Start {
node_id: node_id.into(),
near_rpc: ctx.sandbox.local_address.clone(),
mpc_contract_id: ctx.mpc_contract.id().clone(),
account: account.clone(),
account_sk: account_sk.to_string().parse()?,
web_port: Self::CONTAINER_PORT,
}
.into_str_args();
let image: GenericImage = GenericImage::new("near/mpc-recovery-node", "latest")
.with_wait_for(WaitFor::Nothing)
.with_exposed_port(Self::CONTAINER_PORT)
.with_env_var("RUST_LOG", "mpc_recovery_node=DEBUG")
.with_env_var("RUST_BACKTRACE", "1");
let image: RunnableImage<GenericImage> = (image, args).into();
let image = image.with_network(&ctx.docker_network);
let container = ctx.docker_client.cli.run(image);
let ip_address = ctx
.docker_client
.get_network_ip_address(&container, &ctx.docker_network)
.await?;
let host_port = container.get_host_port_ipv4(Self::CONTAINER_PORT);

container.exec(ExecCommand {
cmd: format!("bash -c 'while [[ \"$(curl -s -o /dev/null -w ''%{{http_code}}'' localhost:{})\" != \"200\" ]]; do sleep 1; done'", Self::CONTAINER_PORT),
ready_conditions: vec![WaitFor::message_on_stdout("node is ready to accept connections")]
});

let full_address = format!("http://{ip_address}:{}", Self::CONTAINER_PORT);
tracing::info!(node_id, full_address, "node container is running");
Ok(Node {
container,
address: full_address,
local_address: format!("http://localhost:{host_port}"),
})
}
}
49 changes: 49 additions & 0 deletions integration-tests/src/multichain/local.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::util;
use async_process::Child;
use near_workspaces::AccountId;

pub struct Node {
pub address: String,
node_id: usize,
account: AccountId,
account_sk: near_workspaces::types::SecretKey,

// process held so it's not dropped. Once dropped, process will be killed.
#[allow(unused)]
process: Child,
}

impl Node {
pub async fn run(
ctx: &super::Context<'_>,
node_id: u32,
account: &AccountId,
account_sk: &near_workspaces::types::SecretKey,
) -> anyhow::Result<Self> {
let web_port = util::pick_unused_port().await?;
let args = mpc_recovery_node::cli::Cli::Start {
node_id: node_id.into(),
near_rpc: ctx.sandbox.local_address.clone(),
mpc_contract_id: ctx.mpc_contract.id().clone(),
account: account.clone(),
account_sk: account_sk.to_string().parse()?,
web_port,
}
.into_str_args();

let mpc_node_id = format!("multichain/{node_id}");
let process = util::spawn_mpc_multichain(ctx.release, &mpc_node_id, &args)?;
let address = format!("http://127.0.0.1:{web_port}");
tracing::info!("node is starting at {}", address);
util::ping_until_ok(&address, 60).await?;
tracing::info!("node started [node_id={node_id}, {address}]");

Ok(Self {
address,
node_id: node_id as usize,
account: account.clone(),
account_sk: account_sk.clone(),
process,
})
}
}
Loading

0 comments on commit 95e45d5

Please sign in to comment.