Skip to content

Commit

Permalink
ci: setup e2e-tests in github workflow (#976)
Browse files Browse the repository at this point in the history
  • Loading branch information
fbozic authored Nov 26, 2024
1 parent 8b26910 commit eade923
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 25 deletions.
79 changes: 79 additions & 0 deletions .github/workflows/e2e_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: End-to-end tests

on:
push:
branches:
- '**'
paths:
- Cargo.toml
- Cargo.lock
- 'contracts/**'
- 'crates/**'
- 'e2e-tests/**'
- '.github/workflows/e2e_tests.yml'

jobs:
test:
name: Test
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup rust toolchain
run: rustup toolchain install stable --profile minimal

- name: Setup rust cache
uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true

- name: Build apps
run: |
./apps/kv-store/build.sh
- name: Build contracts
run: |
./contracts/context-config/build.sh
./contracts/proxy-lib/build.sh
- name: Build binaries
run: |
cargo build -p meroctl -p merod -p e2e-tests
- name: Run e2e tests
run: |
export NO_COLOR=1
echo "Running e2e tests, check job summary for details"
echo "# E2E tests 🏗️" >> $GITHUB_STEP_SUMMARY
./target/debug/e2e-tests \
--input-dir ./e2e-tests/config \
--output-dir ./e2e-tests/corpus \
--merod-binary ./target/debug/merod \
--meroctl-binary ./target/debug/meroctl \
--output-format markdown >> $GITHUB_STEP_SUMMARY
- name: Run e2e tests
if: success() || failure()
run: |
LOGS_DIR=./e2e-tests/corpus/logs
if [ ! -d "$LOGS_DIR" ]; then
echo "Directory $LOGS_DIR does not exist."
exit 1
fi
echo "# Node logs 📋" >> $GITHUB_STEP_SUMMARY
for FOLDER in "$LOGS_DIR"/*; do
if [ -d "$FOLDER" ]; then
RUN_LOG="$FOLDER/run.log"
if [ -f "$RUN_LOG" ]; then
echo "## Node logs: $(basename $FOLDER) 📋" >> $GITHUB_STEP_SUMMARY
cat "$RUN_LOG" >> $GITHUB_STEP_SUMMARY
else
echo "## No run.log found in $FOLDER ⚠️" >> $GITHUB_STEP_SUMMARY
fi
fi
done
18 changes: 16 additions & 2 deletions e2e-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,26 @@ Binary crate which runs e2e tests for the merod node.

## Usage

Build the merod and meroctl binaries and run the e2e tests with the following
commands:
First build apps, contracts, and mero binaries. After that run the e2e tests.

Example of running the e2e tests:

```bash
./apps/kv-store/build.sh

./contracts/context-config/build.sh
./contracts/proxy-lib/build.sh

cargo build -p merod
cargo build -p meroctl

export NO_COLOR=1 # Disable color output for merod logs
cargo run -p e2e-tests -- --input-dir ./e2e-tests/config --output-dir ./e2e-tests/corpus --merod-binary ./target/debug/merod --meroctl-binary ./target/debug/meroctl
```

Useful env vars for debugging:

- `RUST_LOG=debug` - enable debug logs
- `RUST_LOG=near_jsonrpc_client=debug` - or more specific logs
- `NEAR_ENABLE_SANDBOX_LOG=1` - enable near sandbox logs
- `NO_COLOR=1` - disable color output
66 changes: 48 additions & 18 deletions e2e-tests/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use tokio::time::sleep;
use crate::config::Config;
use crate::meroctl::Meroctl;
use crate::merod::Merod;
use crate::output::OutputWriter;
use crate::steps::{TestScenario, TestStep};
use crate::TestEnvironment;

Expand All @@ -24,21 +25,28 @@ pub struct TestContext<'a> {
pub context_id: Option<String>,
pub inviter_public_key: Option<String>,
pub invitees_public_keys: HashMap<String, String>,
pub output_writer: OutputWriter,
}

pub trait Test {
async fn run_assert(&self, ctx: &mut TestContext<'_>) -> EyreResult<()>;
}

impl<'a> TestContext<'a> {
pub fn new(inviter: String, invitees: Vec<String>, meroctl: &'a Meroctl) -> Self {
pub fn new(
inviter: String,
invitees: Vec<String>,
meroctl: &'a Meroctl,
output_writer: OutputWriter,
) -> Self {
Self {
inviter,
invitees,
meroctl,
context_id: None,
inviter_public_key: None,
invitees_public_keys: HashMap::new(),
output_writer,
}
}
}
Expand Down Expand Up @@ -81,6 +89,13 @@ impl Driver {

self.stop_merods().await;

if let Err(e) = &result {
self.environment
.output_writer
.write_str("Error occurred during test run:");
self.environment.output_writer.write_string(e.to_string());
}

result
}

Expand Down Expand Up @@ -113,7 +128,9 @@ impl Driver {
}

async fn boot_merods(&mut self) -> EyreResult<()> {
println!("========================= Starting nodes ===========================");
self.environment
.output_writer
.write_header("Starting merod nodes", 2);

for i in 0..self.config.network.node_count {
let node_name = format!("node{}", i + 1);
Expand Down Expand Up @@ -178,9 +195,7 @@ impl Driver {
}

// TODO: Implement health check?
sleep(Duration::from_secs(20)).await;

println!("====================================================================");
sleep(Duration::from_secs(10)).await;

Ok(())
}
Expand Down Expand Up @@ -213,35 +228,50 @@ impl Driver {
}

async fn run_scenario(&self, file_path: PathBuf) -> EyreResult<()> {
println!("================= Setting up scenario and context ==================");
self.environment
.output_writer
.write_header("Running scenario", 2);

let scenario: TestScenario = from_slice(&read(&file_path).await?)?;

println!(
"Loaded test scenario from file: {:?}\n{:?}",
file_path, scenario
);
self.environment
.output_writer
.write_string(format!("Source file: {:?}", file_path));
self.environment
.output_writer
.write_string(format!("Steps count: {}", scenario.steps.len()));

let (inviter, invitees) = match self.pick_inviter_node() {
Some((inviter, invitees)) => (inviter, invitees),
None => bail!("Not enough nodes to run the test"),
};

println!("Picked inviter: {}", inviter);
println!("Picked invitees: {:?}", invitees);
self.environment
.output_writer
.write_string(format!("Picked inviter: {}", inviter));
self.environment
.output_writer
.write_string(format!("Picked invitees: {:?}", invitees));

let mut ctx = TestContext::new(inviter, invitees, &self.meroctl);

println!("====================================================================");
let mut ctx = TestContext::new(
inviter,
invitees,
&self.meroctl,
self.environment.output_writer,
);

for step in scenario.steps.iter() {
println!("======================== Starting step =============================");
println!("Step: {:?}", step);
self.environment
.output_writer
.write_header("Running test step", 3);
self.environment.output_writer.write_str("Step spec:");
self.environment.output_writer.write_json(&step)?;

match step {
TestStep::ContextCreate(step) => step.run_assert(&mut ctx).await?,
TestStep::ContextInviteJoin(step) => step.run_assert(&mut ctx).await?,
TestStep::JsonRpcCall(step) => step.run_assert(&mut ctx).await?,
};
println!("====================================================================");
}

Ok(())
Expand Down
9 changes: 9 additions & 0 deletions e2e-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use config::Config;
use const_format::concatcp;
use driver::Driver;
use eyre::Result as EyreResult;
use output::{OutputFormat, OutputWriter};
use rand::Rng;
use tokio::fs::{create_dir_all, read_to_string, remove_dir_all};

mod config;
mod driver;
mod meroctl;
mod merod;
mod output;
mod steps;

pub const EXAMPLES: &str = r"
Expand Down Expand Up @@ -51,6 +53,11 @@ pub struct Args {
#[arg(long, value_name = "PATH")]
#[arg(env = "MEROCTL_BINARY", hide_env_values = true)]
pub meroctl_binary: Utf8PathBuf,

/// Format of the E2E test output.
#[arg(long, value_name = "OUTPUT_FORMAT", default_value_t, value_enum)]
#[arg(env = "E2E_OUTPUT_FORMAT", hide_env_values = true)]
pub output_format: OutputFormat,
}

#[derive(Debug)]
Expand All @@ -62,6 +69,7 @@ pub struct TestEnvironment {
pub output_dir: Utf8PathBuf,
pub nodes_dir: Utf8PathBuf,
pub logs_dir: Utf8PathBuf,
pub output_writer: OutputWriter,
}

impl Into<TestEnvironment> for Args {
Expand All @@ -76,6 +84,7 @@ impl Into<TestEnvironment> for Args {
output_dir: self.output_dir.clone(),
nodes_dir: self.output_dir.join("nodes"),
logs_dir: self.output_dir.join("logs"),
output_writer: OutputWriter::new(self.output_format),
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion e2e-tests/src/meroctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ use camino::Utf8PathBuf;
use eyre::{bail, eyre, OptionExt, Result as EyreResult};
use tokio::process::Command;

use crate::output::OutputWriter;
use crate::TestEnvironment;

pub struct Meroctl {
nodes_dir: Utf8PathBuf,
binary: Utf8PathBuf,
output_writer: OutputWriter,
}

impl Meroctl {
pub fn new(environment: &TestEnvironment) -> Self {
Self {
nodes_dir: environment.nodes_dir.clone(),
binary: environment.meroctl_binary.clone(),
output_writer: environment.output_writer,
}
}

Expand Down Expand Up @@ -148,7 +151,8 @@ impl Meroctl {

root_args.extend(args);

println!("Command: '{:}' {:?}", &self.binary, root_args);
self.output_writer
.write_string(format!("Command: '{:}' {:?}", &self.binary, root_args));

let output = Command::new(&self.binary)
.args(root_args)
Expand Down
6 changes: 5 additions & 1 deletion e2e-tests/src/merod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use tokio::fs::{create_dir_all, File};
use tokio::io::copy;
use tokio::process::{Child, Command};

use crate::output::OutputWriter;
use crate::TestEnvironment;

pub struct Merod {
Expand All @@ -15,6 +16,7 @@ pub struct Merod {
nodes_dir: Utf8PathBuf,
log_dir: Utf8PathBuf,
binary: Utf8PathBuf,
output_writer: OutputWriter,
}

impl Merod {
Expand All @@ -25,6 +27,7 @@ impl Merod {
log_dir: environment.logs_dir.join(&name),
binary: environment.merod_binary.clone(),
name,
output_writer: environment.output_writer,
}
}

Expand Down Expand Up @@ -92,7 +95,8 @@ impl Merod {
let log_file = self.log_dir.join(format!("{}.log", log_suffix));
let mut log_file = File::create(&log_file).await?;

println!("Command: '{:}' {:?}", &self.binary, root_args);
self.output_writer
.write_string(format!("Command: '{:}' {:?}", &self.binary, root_args));

let mut child = Command::new(&self.binary)
.args(root_args)
Expand Down
Loading

0 comments on commit eade923

Please sign in to comment.