Skip to content

Commit

Permalink
Cli: tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TimeEngineer committed Dec 18, 2023
1 parent bd4f02e commit 8607e80
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 36 deletions.
4 changes: 4 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[profile.default]
# https://nexte.st/book/slow-tests.html
slow-timeout = { period = "10s", terminate-after = 3 } # Timeout a test after 30s (3 * 10s)
# Allow the server to shutdown after the tests
leak-timeout = "500ms"

[profile.ci]
slow-timeout = { period = "10s", terminate-after = 5 } # Timeout a test after 50s (5 * 10s)
Expand All @@ -12,3 +14,5 @@ status-level = "all"
failure-output = "immediate-final"
# Continue even if a test fail.
fail-fast = false
# Allow the server to shutdown after the tests
leak-timeout = "500ms"
35 changes: 35 additions & 0 deletions .github/workflows/ci-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ concurrency:
cancel-in-progress: true

env:
poetry-version: 1.5.1
CARGO_CI_FLAGS: --locked --profile ci-rust
CARGO_NEXTEST_CI_FLAGS: --profile=ci --locked --cargo-profile ci-rust
WINFSP_VERSION: 2.0.23075
Expand Down Expand Up @@ -89,6 +90,22 @@ jobs:
with:
tool: [email protected], [email protected], [email protected]

- uses: ./.github/actions/setup-python-poetry
id: setup-python
with:
poetry-version: ${{ env.poetry-version }}
project-path: ./server
timeout-minutes: 10

- name: Test cli
shell: bash
run: |
set -ex
python make.py python-dev-install
cargo build --profile ci-rust --package parsec_cli --features testenv
cargo nextest run ${{ env.CARGO_NEXTEST_CI_FLAGS }} --package parsec_cli --features testenv
timeout-minutes: 10

- name: Categorize workspace crates
id: crates
run: |
Expand Down Expand Up @@ -224,3 +241,21 @@ jobs:
env:
RUST_LOG: debug
TESTBED_SERVER: http://localhost:6777

- uses: ./.github/actions/setup-python-poetry
id: setup-python
with:
poetry-version: ${{ env.poetry-version }}
project-path: ./server
timeout-minutes: 10

- name: Test cli
shell: bash
run: |
set -ex
python make.py python-dev-install
cargo build --profile ci-rust --package parsec_cli --features testenv
cargo nextest run ${{ env.CARGO_NEXTEST_CI_FLAGS }} --package parsec_cli --features testenv --nocapture
timeout-minutes: 20
env:
RUST_BACKTRACE=full
86 changes: 86 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ libparsec_tests_lite = { path = "libparsec/crates/tests_lite", default-features
android_logger = { version = "0.13", default-features = false }
anyhow = { version = "1.0.75", default-features = false }
argon2 = { version = "0.5.2", default-features = false }
assert_cmd = { version = "2.0.12", default-features = false }
async-lock = { version = "2.8.0", default-features = false }
async-broadcast = { version = "0.5.1", default-features = false }
async-trait = { version = "0.1.74", default-features = false }
Expand Down Expand Up @@ -148,6 +149,7 @@ openssl = { version = "0.10.61", default-features = false }
paste = { version = "1.0.14", default-features = false }
pin-project-lite = { version = "0.2.13", default-features = false }
percent-encoding = { version = "2.3.1", default-features = false }
predicates = { version = "3.0.4", default-features = false }
pretty_assertions = { version = "1.4.0", default-features = false }
proc-macro2 = { version = "1.0.70", default-features = false }
pyo3 = { version = "0.19.2", default-features = false }
Expand Down
7 changes: 7 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ serde_json = { workspace = true }
terminal-spinners = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
uuid = { workspace = true }

[dev-dependencies]
libparsec = { workspace = true, features = ["cli-tests"] }

assert_cmd = { workspace = true }
predicates = { workspace = true, features = ["regex"] }
rstest = { workspace = true }
3 changes: 3 additions & 0 deletions cli/src/bootstrap_organization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ pub async fn bootstrap_organization(
HumanHandle::new(&bootstrap_organization.email, &bootstrap_organization.label)
.map_err(|e| anyhow::anyhow!("Cannot create human handle: {e}"))?;

#[cfg(feature = "testenv")]
let password = "test".to_string().into();
#[cfg(not(feature = "testenv"))]
let password = rpassword::prompt_password("password:")?.into();

let handle = SpinnerBuilder::new()
Expand Down
4 changes: 1 addition & 3 deletions cli/src/create_organization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ pub async fn create_organization(create_organization: CreateOrganization) -> any
let organization_addr =
BackendOrganizationBootstrapAddr::new(addr, organization_id, Some(bootstrap_token));

let organization_addr_display = organization_addr.to_url();

println!("Organization bootstrap url: {YELLOW}{organization_addr_display}{RESET}");
println!("Organization bootstrap url: {YELLOW}{organization_addr}{RESET}");

Ok(())
}
5 changes: 3 additions & 2 deletions cli/src/list_devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ pub struct ListDevices {

pub async fn list_devices(list_devices: ListDevices) -> anyhow::Result<()> {
let config_dir = list_devices.config_dir.unwrap_or(get_default_config_dir());
let config_dir_str = config_dir.to_string_lossy();
let devices = list_available_devices(&config_dir).await;

if devices.is_empty() {
println!("No devices found in {YELLOW}{config_dir:?}{RESET}");
println!("No devices found in {YELLOW}{config_dir_str}{RESET}");
} else {
let n = devices.len();
println!("Found {GREEN}{n}{RESET} device(s) in {YELLOW}{config_dir:?}{RESET}:");
println!("Found {GREEN}{n}{RESET} device(s) in {YELLOW}{config_dir_str}{RESET}:");
format_devices(&devices);
}

Expand Down
2 changes: 2 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ mod create_organization;
mod list_devices;
#[cfg(feature = "testenv")]
mod run_testenv;
#[cfg(all(test, feature = "testenv"))]
mod tests;
mod utils;

use clap::{Parser, Subcommand};
Expand Down
54 changes: 23 additions & 31 deletions cli/src/run_testenv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ use crate::{
const DEFAULT_ADMINISTRATION_TOKEN: &str = "s3cr3t";
const DEFAULT_DEVICE_PASSWORD: &str = "test";
const RESERVED_PORT_OFFSET: u16 = 1024;
const AVAILABLE_PORT_COUNT: u16 = u16::MAX - RESERVED_PORT_OFFSET;
const LAST_SERVER_PID: &str = "LAST_SERVER_ID";
const TESTBED_SERVER_URL: &str = "TESTBED_SERVER_URL";
pub const TESTBED_SERVER_URL: &str = "TESTBED_SERVER_URL";

#[derive(Args)]
pub struct RunTestenv {
Expand All @@ -44,6 +45,11 @@ pub struct RunTestenv {
empty: bool,
}

pub fn process_id_to_port(pid: u32) -> u16 {
// The first ports are reserved, so let's take an available port
pid as u16 % AVAILABLE_PORT_COUNT + RESERVED_PORT_OFFSET
}

fn create_new_device(
new_device: Arc<LocalDevice>,
author: Arc<LocalDevice>,
Expand Down Expand Up @@ -196,7 +202,7 @@ async fn register_new_user(
Ok(new_device)
}

async fn initialize_test_organization(
pub async fn initialize_test_organization(
client_config: ClientConfig,
addr: BackendAddr,
) -> anyhow::Result<[Arc<LocalDevice>; 3]> {
Expand Down Expand Up @@ -270,13 +276,13 @@ async fn initialize_test_organization(

/// Setup the environment variables
/// Set stop_after_process to kill the server once the process will run down
async fn new_environment(
pub async fn new_environment(
tmp_dir: &Path,
source_file: Option<PathBuf>,
stop_after_process: u32,
empty: bool,
) -> anyhow::Result<()> {
let port = stop_after_process as u16 + RESERVED_PORT_OFFSET;
let port = process_id_to_port(stop_after_process);
let tmp_dir_str = tmp_dir.to_str().expect("Unreachable");
let _ = std::fs::create_dir_all(&tmp_dir);

Expand Down Expand Up @@ -390,37 +396,23 @@ async fn new_environment(
Ok(())
}

pub async fn run_local_organization(
tmp_dir: &Path,
source_file: Option<PathBuf>,
stop_after_process: u32,
) -> anyhow::Result<[Arc<LocalDevice>; 3]> {
let port = stop_after_process as u16 + RESERVED_PORT_OFFSET;
new_environment(tmp_dir, source_file, stop_after_process, false).await?;
pub async fn run_testenv(run_testenv: RunTestenv) -> anyhow::Result<()> {
let tmp_dir = std::env::temp_dir().join(format!("parsec-testenv-{}", &uuid::Uuid::new_v4()));

initialize_test_organization(
ClientConfig::default(),
BackendAddr::new("127.0.0.1".into(), Some(port), false),
new_environment(
&tmp_dir,
run_testenv.source_file,
run_testenv.main_process_id,
run_testenv.empty,
)
.await
}
.await?;

pub async fn run_testenv(run_testenv: RunTestenv) -> anyhow::Result<()> {
let tmp_dir = std::env::temp_dir().join(format!("parsec-testenv-{}", &uuid::Uuid::new_v4()));
if !run_testenv.empty {
let port = process_id_to_port(run_testenv.main_process_id);

if run_testenv.empty {
new_environment(
&tmp_dir,
run_testenv.source_file,
run_testenv.main_process_id,
true,
)
.await?;
} else {
let [alice_device, other_alice_device, bob_device] = run_local_organization(
&tmp_dir,
run_testenv.source_file,
run_testenv.main_process_id,
let [alice_device, other_alice_device, bob_device] = initialize_test_organization(
ClientConfig::default(),
BackendAddr::new("127.0.0.1".into(), Some(port), false),
)
.await?;

Expand Down
Loading

0 comments on commit 8607e80

Please sign in to comment.