diff --git a/.github/workflows/e2e_tests.yml b/.github/workflows/e2e_tests.yml new file mode 100644 index 000000000..0592e5ccb --- /dev/null +++ b/.github/workflows/e2e_tests.yml @@ -0,0 +1,74 @@ +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 + + - 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 "### E2E tests 🏗️" >> $GITHUB_STEP_SUMMARY + TEST_REPORT = $(./target/debug/e2e-tests \ + --input-dir ./e2e-tests/config \ + --output-dir ./e2e-tests/corpus \ + --merod-binary ./target/debug/merod \ + --meroctl-binary ./target/debug/meroctl) + cat $TEST_REPORT >> $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 + + 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 diff --git a/e2e-tests/README.md b/e2e-tests/README.md index 299b0387d..dcc926fed 100644 --- a/e2e-tests/README.md +++ b/e2e-tests/README.md @@ -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 diff --git a/e2e-tests/src/driver.rs b/e2e-tests/src/driver.rs index 728acc814..39789e5b0 100644 --- a/e2e-tests/src/driver.rs +++ b/e2e-tests/src/driver.rs @@ -113,7 +113,7 @@ impl Driver { } async fn boot_merods(&mut self) -> EyreResult<()> { - println!("========================= Starting nodes ==========================="); + println!("------------------------- Starting nodes ---------------------------"); for i in 0..self.config.network.node_count { let node_name = format!("node{}", i + 1); @@ -180,7 +180,7 @@ impl Driver { // TODO: Implement health check? sleep(Duration::from_secs(20)).await; - println!("===================================================================="); + println!("--------------------------------------------------------------------"); Ok(()) } @@ -213,7 +213,7 @@ impl Driver { } async fn run_scenario(&self, file_path: PathBuf) -> EyreResult<()> { - println!("================= Setting up scenario and context =================="); + println!("----------------- Setting up scenario and context ------------------"); let scenario: TestScenario = from_slice(&read(&file_path).await?)?; println!( @@ -231,17 +231,17 @@ impl Driver { let mut ctx = TestContext::new(inviter, invitees, &self.meroctl); - println!("===================================================================="); + println!("--------------------------------------------------------------------"); for step in scenario.steps.iter() { - println!("======================== Starting step ============================="); + println!("------------------------ Starting step -----------------------------"); println!("Step: {:?}", 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!("===================================================================="); + println!("--------------------------------------------------------------------"); } Ok(())