diff --git a/protocol-testing/entrypoint.sh b/protocol-testing/entrypoint.sh index 2c0c9ce..1235695 100644 --- a/protocol-testing/entrypoint.sh +++ b/protocol-testing/entrypoint.sh @@ -16,8 +16,8 @@ for test in "${args[@]}"; do protocol="${test%%=*}" filter="${test#*=}" if [[ "$test" == *"="* ]]; then - tycho-protocol-sdk --package-path "/app/substreams/$protocol" --db-url "$DATABASE_URL" --evm-path "/app/evm" --match-test "$filter" + tycho-protocol-sdk --package "$protocol" --db-url "$DATABASE_URL" --match-test "$filter" else - tycho-protocol-sdk --package-path "/app/substreams/$protocol" --db-url "$DATABASE_URL" --evm-path "/app/evm" + tycho-protocol-sdk --package "$protocol" --db-url "$DATABASE_URL" fi done diff --git a/protocol-testing/src/main.rs b/protocol-testing/src/main.rs index 5480ec0..9d4b9ec 100644 --- a/protocol-testing/src/main.rs +++ b/protocol-testing/src/main.rs @@ -7,10 +7,10 @@ mod tycho_rpc; mod tycho_runner; mod utils; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use clap::Parser; -use miette::miette; +use miette::{miette, IntoDiagnostic, WrapErr}; use tracing_subscriber::EnvFilter; use crate::test_runner::TestRunner; @@ -18,17 +18,14 @@ use crate::test_runner::TestRunner; #[derive(Parser, Debug)] #[command(version, about = "Run indexer within a specified range of blocks")] struct Args { - /// Name of the package to test - #[arg(long, required_unless_present = "package_path", conflicts_with = "package_path")] - package: Option, - - /// Path to the package to test - #[arg(long, required_unless_present = "package", conflicts_with = "package")] - package_path: Option, - - /// Path to the evm directory. If not provided, it will look for it in `../evm` + /// Path to the root directory containing all packages. If not provided, it will look for + /// packages in the current working directory. #[arg(long)] - evm_path: Option, + root_path: Option, + + /// Name of the package to test + #[arg(long)] + package: String, /// If provided, only run the tests with a matching name #[arg(long)] @@ -48,28 +45,30 @@ struct Args { } impl Args { - fn package_path(&self) -> miette::Result { - match (self.package_path.as_ref(), self.package.as_ref()) { - (Some(path), _) => Ok(Path::new(path).to_path_buf()), - (_, Some(package)) => Ok(Path::new("../substreams").join(package)), - _ => Err(miette!("Either package or package_path must be provided")), - } - } - - fn evm_path(&self) -> miette::Result { - match self.evm_path.as_ref() { + fn root_path(&self) -> miette::Result { + match self.root_path.as_ref() { Some(path) => Ok(path.clone()), None => { let current_dir = std::env::current_dir() - .map_err(|e| miette!("Failed to get current directory: {}", e))?; - let mut evm_dir = current_dir.join("../evm"); - if !evm_dir.exists() { - evm_dir = current_dir.join("evm"); - if !evm_dir.exists() { - return Err(miette!("evm directory not found")); - } + .into_diagnostic() + .wrap_err("Failed to get current directory")?; + let expected_child_dirs = ["evm", "proto", "substreams"]; + if expected_child_dirs + .iter() + .all(|dir| current_dir.join(dir).exists()) + { + return Ok(current_dir); } - Ok(evm_dir) + let parent_dir = current_dir + .parent() + .ok_or_else(|| miette!("Current directory has no parent directory"))?; + if expected_child_dirs + .iter() + .all(|dir| parent_dir.join(dir).exists()) + { + return Ok(parent_dir.to_path_buf()); + } + Err(miette!("Couldn't find a valid path from {}", current_dir.display())) } } } @@ -84,8 +83,8 @@ fn main() -> miette::Result<()> { let args = Args::parse(); let test_runner = TestRunner::new( - args.package_path()?, - args.evm_path()?, + args.root_path()?, + args.package, args.match_test, args.tycho_logs, args.db_url, diff --git a/protocol-testing/src/test_runner.rs b/protocol-testing/src/test_runner.rs index 8d87480..6db4483 100644 --- a/protocol-testing/src/test_runner.rs +++ b/protocol-testing/src/test_runner.rs @@ -11,7 +11,7 @@ use num_bigint::BigUint; use num_traits::Zero; use postgres::{Client, Error, NoTls}; use tokio::runtime::Runtime; -use tracing::{debug, error, info}; +use tracing::{debug, error, info, warn}; use tycho_client::feed::BlockHeader; use tycho_common::{ dto::{Chain, ProtocolComponent, ResponseAccount, ResponseProtocolState}, @@ -52,13 +52,17 @@ pub struct TestRunner { impl TestRunner { pub fn new( - substreams_path: PathBuf, - evm_path: PathBuf, + root_path: PathBuf, + protocol: String, match_test: Option, tycho_logs: bool, db_url: String, vm_traces: bool, ) -> Self { + let substreams_path = root_path + .join("substreams") + .join(protocol); + let evm_path = root_path.join("evm"); let adapter_contract_builder = AdapterContractBuilder::new(evm_path.to_string_lossy().to_string()); Self { @@ -81,6 +85,22 @@ impl TestRunner { .substreams_path .join("integration_test.tycho.yaml"); + // Skip if test files don't exist + if !config_yaml_path.exists() { + warn!( + "integration_test.tycho.yaml file not found at {}", + self.substreams_path.display() + ); + return Ok(()); + } + let substreams_yaml_path = self + .substreams_path + .join("substreams.yaml"); + if !substreams_yaml_path.exists() { + warn!("substreams.yaml file not found at {}", self.substreams_path.display()); + return Ok(()); + } + let config = Self::parse_config(&config_yaml_path)?; let tests = match &self.match_test { @@ -128,7 +148,7 @@ impl TestRunner { } fn parse_config(config_yaml_path: &PathBuf) -> miette::Result { - info!("Config YAML: {}", config_yaml_path.display()); + info!("Parsing config YAML at {}", config_yaml_path.display()); let yaml = Yaml::file(config_yaml_path); let figment = Figment::new().merge(yaml); let config = figment diff --git a/protocol-testing/src/utils.rs b/protocol-testing/src/utils.rs index 2463bd0..6f4a39c 100644 --- a/protocol-testing/src/utils.rs +++ b/protocol-testing/src/utils.rs @@ -9,11 +9,12 @@ use figment::{ value::Value, Figment, }; -use miette::IntoDiagnostic; -use tracing::error; +use miette::{miette, IntoDiagnostic}; +use tracing::{error, info}; /// Build a Substreams package with modifications to the YAML file. pub fn build_spkg(yaml_file_path: &PathBuf, initial_block: u64) -> miette::Result { + info!("Building spkg from {:?}", yaml_file_path); // Create a backup file of the unmodified Substreams protocol YAML config file. let backup_file_path = yaml_file_path.with_extension("backup"); fs::copy(yaml_file_path, &backup_file_path).into_diagnostic()?; @@ -55,7 +56,13 @@ pub fn build_spkg(yaml_file_path: &PathBuf, initial_block: u64) -> miette::Resul fs::write(yaml_file_path, yaml_string).into_diagnostic()?; // Run the substreams pack command to create the spkg - // WARNING: Ensure substreams is in the PATH + if Command::new("substreams") + .arg("--version") + .output() + .is_err() + { + return Err(miette!("Substreams CLI is not installed or not found in PATH")); + } match Command::new("substreams") .arg("pack") .arg(yaml_file_path) @@ -71,10 +78,7 @@ pub fn build_spkg(yaml_file_path: &PathBuf, initial_block: u64) -> miette::Resul } Err(e) => { error!( - "Error running substreams pack command: {}. \ - Ensure that the wasm target was built and that substreams CLI\ - is installed and exported on PATH", - e + "Error running substreams pack command. Ensure that the wasm target was built. {e}", ); } }