From c222e1d44c18de85cb93db1c3c77ee8a10ba9824 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Mon, 18 Sep 2023 10:57:22 -0400 Subject: [PATCH] feat: organize CLI tests so that they can be invoked programatically --- .../soroban-test/tests/it/contract_sandbox.rs | 464 ------------------ .../soroban-test/tests/it/hello_world.rs | 232 +++++++++ .../tests/it/integration_and_sandbox.rs | 225 +++++++++ cmd/crates/soroban-test/tests/it/main.rs | 3 +- cmd/crates/soroban-test/tests/it/util.rs | 27 + cmd/soroban-rpc/internal/test/cli_test.go | 45 +- 6 files changed, 496 insertions(+), 500 deletions(-) delete mode 100644 cmd/crates/soroban-test/tests/it/contract_sandbox.rs create mode 100644 cmd/crates/soroban-test/tests/it/hello_world.rs create mode 100644 cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs diff --git a/cmd/crates/soroban-test/tests/it/contract_sandbox.rs b/cmd/crates/soroban-test/tests/it/contract_sandbox.rs deleted file mode 100644 index ea2af861ca..0000000000 --- a/cmd/crates/soroban-test/tests/it/contract_sandbox.rs +++ /dev/null @@ -1,464 +0,0 @@ -use soroban_cli::commands::{ - config::identity, - contract::{self, fetch}, -}; -use soroban_test::TestEnv; -use std::path::PathBuf; - -use crate::util::{ - add_test_seed, is_rpc, network_passphrase, network_passphrase_arg, rpc_url, rpc_url_arg, - DEFAULT_PUB_KEY, DEFAULT_PUB_KEY_1, DEFAULT_SECRET_KEY, DEFAULT_SEED_PHRASE, HELLO_WORLD, - TEST_SALT, -}; - -#[test] -fn install_wasm_then_deploy_contract() { - let sandbox = TestEnv::default(); - assert_eq!(deploy_hello(&sandbox), TEST_CONTRACT_ID); -} - -const TEST_CONTRACT_ID: &str = "CBVTIVBYWAO2HNPNGKDCZW4OZYYESTKNGD7IPRTDGQSFJS4QBDQQJX3T"; - -fn deploy_hello(sandbox: &TestEnv) -> String { - let hash = HELLO_WORLD.hash().unwrap(); - sandbox - .new_assert_cmd("contract") - .arg("install") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success() - .stdout(format!("{hash}\n")); - - let mut cmd: &mut assert_cmd::Command = &mut sandbox.new_assert_cmd("contract"); - - cmd = cmd.arg("deploy").arg("--wasm-hash").arg(&format!("{hash}")); - if is_rpc() { - cmd = cmd.arg("--salt").arg(TEST_SALT); - } else { - cmd = cmd.arg("--id").arg(TEST_CONTRACT_ID); - } - cmd.assert() - .success() - .stdout(format!("{TEST_CONTRACT_ID}\n")); - TEST_CONTRACT_ID.to_string() -} - -#[test] -fn deploy_contract_with_wasm_file() { - if is_rpc() { - return; - } - TestEnv::default() - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--id=1") - .assert() - .success() - .stdout("CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM\n"); -} - -#[test] -fn invoke_hello_world_with_deploy_first() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - println!("{id}"); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("hello") - .arg("--world=world") - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); -} - -#[test] -fn invoke_hello_world() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("hello") - .arg("--world=world") - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); -} - -#[test] -fn invoke_hello_world_from_file() { - let sandbox = TestEnv::default(); - let tmp_file = sandbox.temp_dir.join("world.txt"); - std::fs::write(&tmp_file, "world").unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("hello") - .arg("--world-file-path") - .arg(&tmp_file) - .assert() - .stdout("[\"Hello\",\"world\"]\n") - .success(); -} - -#[test] -fn invoke_hello_world_from_file_fail() { - let sandbox = TestEnv::default(); - let tmp_file = sandbox.temp_dir.join("world.txt"); - std::fs::write(&tmp_file, "world").unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("hello") - .arg("--world-file-path") - .arg(&tmp_file) - .arg("--world=hello") - .assert() - .stderr(predicates::str::contains("error: the argument '--world-file-path ' cannot be used with '--world '")) - .failure(); -} - -#[test] -fn invoke_hello_world_with_lib() { - TestEnv::with_default(|e| { - let id = deploy_hello(e); - let mut cmd = contract::invoke::Cmd { - contract_id: id, - slop: vec!["hello".into(), "--world=world".into()], - ..Default::default() - }; - - cmd.config.network.rpc_url = rpc_url(); - cmd.config.network.network_passphrase = network_passphrase(); - - let res = e.invoke_cmd(cmd).unwrap(); - assert_eq!(res, r#"["Hello","world"]"#); - }); -} - -#[test] -fn invoke_hello_world_with_lib_two() { - TestEnv::with_default(|e| { - let id = deploy_hello(e); - let hello_world = HELLO_WORLD.to_string(); - let mut invoke_args = vec!["--id", &id, "--wasm", hello_world.as_str()]; - let args = vec!["--", "hello", "--world=world"]; - let res = if let (Some(rpc), Some(network_passphrase)) = - (rpc_url_arg(), network_passphrase_arg()) - { - invoke_args.push(&rpc); - invoke_args.push(&network_passphrase); - e.invoke(&[invoke_args, args].concat()).unwrap() - } else { - e.invoke(&[invoke_args, args].concat()).unwrap() - }; - assert_eq!(res, r#"["Hello","world"]"#); - }); -} -// #[test] -// fn invoke_hello_world_with_lib_three() { -// let sandbox = TestEnv::default(); -// let builder = invoke::CmdBuilder::new().contract_id("1").wasm(HELLO_WORLD.path()).function("hello").slop(["--hello=world"]).build(); -// std::env::set_current_dir(sandbox.dir()).unwrap(); -// assert_eq!(res.run_in_sandbox().unwrap(), r#"["Hello","world"]"#); -// } - -#[test] -fn invoke_auth() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); - - // Invoke it again without providing the contract, to exercise the deployment - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); -} - -#[tokio::test] -async fn invoke_auth_with_identity() { - let sandbox = TestEnv::default(); - sandbox - .cmd::("test -d ") - .run() - .await - .unwrap(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg("--addr=test") - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) - .success(); -} - -#[test] -fn invoke_auth_with_different_test_account() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--hd-path=1") - .arg("--id") - .arg(id) - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .arg("--") - .arg("auth") - .arg(&format!("--addr={DEFAULT_PUB_KEY_1}")) - .arg("--world=world") - .assert() - .stdout(format!("\"{DEFAULT_PUB_KEY_1}\"\n")) - .success(); -} - -#[test] -fn contract_data_read_failure() { - let sandbox = TestEnv::default(); - let id = deploy_hello(&sandbox); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .assert() - .failure() - .stderr( - "error: no matching contract data entries were found for the specified contract id\n", - ); -} - -#[test] -fn contract_data_read() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("inc") - .assert() - .success(); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .assert() - .success() - .stdout("COUNTER,1\n"); - - sandbox - .new_assert_cmd("contract") - .arg("invoke") - .arg("--id") - .arg(id) - .arg("--") - .arg("inc") - .assert() - .success(); - - sandbox - .new_assert_cmd("contract") - .arg("read") - .arg("--id") - .arg(id) - .arg("--key=COUNTER") - .assert() - .success() - .stdout("COUNTER,2\n"); -} - -#[test] -fn invoke_auth_with_different_test_account_fail() { - let sandbox = TestEnv::default(); - let id = &deploy_hello(&sandbox); - let res = sandbox.invoke(&[ - "--hd-path=1", - "--id", - id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - &rpc_url_arg().unwrap_or_default(), - &network_passphrase_arg().unwrap_or_default(), - "--", - "auth", - &format!("--addr={DEFAULT_PUB_KEY}"), - "--world=world", - ]); - assert!(res.is_err()); - if let Err(e) = res { - assert!( - matches!(e, contract::invoke::Error::Host(_)), - "Expected host error got {e:?}" - ); - }; -} - -#[test] -fn invoke_hello_world_with_seed() { - let sandbox = TestEnv::default(); - let identity = add_test_seed(sandbox.dir()); - invoke_with_source(&sandbox, &identity); -} - -#[test] -fn invoke_with_seed() { - let sandbox = TestEnv::default(); - invoke_with_source(&sandbox, DEFAULT_SEED_PHRASE); -} - -#[test] -fn invoke_with_id() { - let sandbox = TestEnv::default(); - let identity = add_test_seed(sandbox.dir()); - invoke_with_source(&sandbox, &identity); -} - -#[test] -fn invoke_with_sk() { - let sandbox = TestEnv::default(); - invoke_with_source(&sandbox, DEFAULT_SECRET_KEY); -} - -fn invoke_with_source(sandbox: &TestEnv, source: &str) { - let id = &deploy_hello(sandbox); - let cmd = sandbox.invoke(&[ - "--source-account", - source, - "--id", - id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - &rpc_url_arg().unwrap_or_default(), - &network_passphrase_arg().unwrap_or_default(), - "--", - "hello", - "--world=world", - ]); - assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); - - // Invoke it again without providing the contract, to exercise the deployment - let cmd = sandbox.invoke(&[ - "--source-account", - source, - "--id", - id, - "--", - "hello", - "--world=world", - ]); - assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); -} - -#[test] -fn handles_kebab_case() { - let e = TestEnv::default(); - let id = deploy_hello(&e); - assert!(e - .invoke(&[ - "--id", - &id, - "--wasm", - HELLO_WORLD.path().to_str().unwrap(), - "--", - "multi-word-cmd", - "--contract-owner=world", - ]) - .is_ok()); -} - -#[tokio::test] -async fn fetch() { - if !is_rpc() { - return; - } - let e = TestEnv::default(); - let f = e.dir().join("contract.wasm"); - let id = deploy_hello(&e); - let cmd = e.cmd_arr::(&["--id", &id, "--out-file", f.to_str().unwrap()]); - cmd.run().await.unwrap(); - assert!(f.exists()); -} - -#[test] -fn build() { - let sandbox = TestEnv::default(); - - let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let hello_world_contract_path = - cargo_dir.join("tests/fixtures/test-wasms/hello_world/Cargo.toml"); - sandbox - .new_assert_cmd("contract") - .arg("build") - .arg("--manifest-path") - .arg(hello_world_contract_path) - .arg("--profile") - .arg("test-wasms") - .arg("--package") - .arg("test_hello_world") - .assert() - .success(); -} diff --git a/cmd/crates/soroban-test/tests/it/hello_world.rs b/cmd/crates/soroban-test/tests/it/hello_world.rs new file mode 100644 index 0000000000..46f6f9f338 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/hello_world.rs @@ -0,0 +1,232 @@ +use soroban_cli::commands::contract; +use soroban_test::TestEnv; +use std::path::PathBuf; + +use crate::util::{ + deploy_hello, is_rpc, network_passphrase, network_passphrase_arg, rpc_url, rpc_url_arg, + DEFAULT_PUB_KEY, DEFAULT_PUB_KEY_1, HELLO_WORLD, TEST_CONTRACT_ID, +}; + +#[test] +fn install_wasm_then_deploy_contract() { + let sandbox = TestEnv::default(); + assert_eq!(deploy_hello(&sandbox), TEST_CONTRACT_ID); +} + +#[test] +fn deploy_contract_with_wasm_file() { + if is_rpc() { + return; + } + TestEnv::default() + .new_assert_cmd("contract") + .arg("deploy") + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--id=1") + .assert() + .success() + .stdout("CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM\n"); +} + +#[test] +fn invoke_hello_world_with_deploy_first() { + let sandbox = TestEnv::default(); + let id = deploy_hello(&sandbox); + println!("{id}"); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("hello") + .arg("--world=world") + .assert() + .stdout("[\"Hello\",\"world\"]\n") + .success(); +} + +#[test] +fn invoke_hello_world() { + let sandbox = TestEnv::default(); + let id = deploy_hello(&sandbox); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("hello") + .arg("--world=world") + .assert() + .stdout("[\"Hello\",\"world\"]\n") + .success(); +} + +#[test] +fn invoke_hello_world_from_file() { + let sandbox = TestEnv::default(); + let tmp_file = sandbox.temp_dir.join("world.txt"); + std::fs::write(&tmp_file, "world").unwrap(); + let id = deploy_hello(&sandbox); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("hello") + .arg("--world-file-path") + .arg(&tmp_file) + .assert() + .stdout("[\"Hello\",\"world\"]\n") + .success(); +} + +#[test] +fn invoke_hello_world_from_file_fail() { + let sandbox = TestEnv::default(); + let tmp_file = sandbox.temp_dir.join("world.txt"); + std::fs::write(&tmp_file, "world").unwrap(); + let id = deploy_hello(&sandbox); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("hello") + .arg("--world-file-path") + .arg(&tmp_file) + .arg("--world=hello") + .assert() + .stderr(predicates::str::contains("error: the argument '--world-file-path ' cannot be used with '--world '")) + .failure(); +} + +#[test] +fn invoke_hello_world_with_lib() { + TestEnv::with_default(|e| { + let id = deploy_hello(e); + let mut cmd = contract::invoke::Cmd { + contract_id: id, + slop: vec!["hello".into(), "--world=world".into()], + ..Default::default() + }; + + cmd.config.network.rpc_url = rpc_url(); + cmd.config.network.network_passphrase = network_passphrase(); + + let res = e.invoke_cmd(cmd).unwrap(); + assert_eq!(res, r#"["Hello","world"]"#); + }); +} + +#[test] +fn invoke_auth_with_different_test_account() { + let sandbox = TestEnv::default(); + let id = deploy_hello(&sandbox); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--hd-path=1") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("auth") + .arg(&format!("--addr={DEFAULT_PUB_KEY_1}")) + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY_1}\"\n")) + .success(); +} + +#[test] +fn contract_data_read_failure() { + let sandbox = TestEnv::default(); + let id = deploy_hello(&sandbox); + + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key=COUNTER") + .assert() + .failure() + .stderr( + "error: no matching contract data entries were found for the specified contract id\n", + ); +} + +#[test] +fn invoke_auth_with_different_test_account_fail() { + let sandbox = TestEnv::default(); + let id = &deploy_hello(&sandbox); + let res = sandbox.invoke(&[ + "--hd-path=1", + "--id", + id, + "--wasm", + HELLO_WORLD.path().to_str().unwrap(), + &rpc_url_arg().unwrap_or_default(), + &network_passphrase_arg().unwrap_or_default(), + "--", + "auth", + &format!("--addr={DEFAULT_PUB_KEY}"), + "--world=world", + ]); + assert!(res.is_err()); + if let Err(e) = res { + assert!( + matches!(e, contract::invoke::Error::Host(_)), + "Expected host error got {e:?}" + ); + }; +} + +#[test] +fn handles_kebab_case() { + let e = TestEnv::default(); + let id = deploy_hello(&e); + assert!(e + .invoke(&[ + "--id", + &id, + "--wasm", + HELLO_WORLD.path().to_str().unwrap(), + "--", + "multi-word-cmd", + "--contract-owner=world", + ]) + .is_ok()); +} + +#[test] +fn build() { + let sandbox = TestEnv::default(); + + let cargo_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let hello_world_contract_path = + cargo_dir.join("tests/fixtures/test-wasms/hello_world/Cargo.toml"); + sandbox + .new_assert_cmd("contract") + .arg("build") + .arg("--manifest-path") + .arg(hello_world_contract_path) + .arg("--profile") + .arg("test-wasms") + .arg("--package") + .arg("test_hello_world") + .assert() + .success(); +} diff --git a/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs b/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs new file mode 100644 index 0000000000..a87e60cb53 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs @@ -0,0 +1,225 @@ +use soroban_cli::commands::{config::identity, contract::fetch}; +use soroban_test::TestEnv; + +use crate::util::{ + add_test_seed, deploy_hello, is_rpc, network_passphrase_arg, rpc_url_arg, DEFAULT_PUB_KEY, + DEFAULT_SECRET_KEY, DEFAULT_SEED_PHRASE, HELLO_WORLD, TEST_CONTRACT_ID, +}; + +#[test] +fn install_wasm_then_deploy_contract() { + let sandbox = TestEnv::default(); + assert_eq!(deploy_hello(&sandbox), TEST_CONTRACT_ID); +} + +#[test] +fn invoke_hello_world_with_lib_two() { + TestEnv::with_default(|e| { + let id = deploy_hello(e); + let hello_world = HELLO_WORLD.to_string(); + let mut invoke_args = vec!["--id", &id, "--wasm", hello_world.as_str()]; + let args = vec!["--", "hello", "--world=world"]; + let res = if let (Some(rpc), Some(network_passphrase)) = + (rpc_url_arg(), network_passphrase_arg()) + { + invoke_args.push(&rpc); + invoke_args.push(&network_passphrase); + e.invoke(&[invoke_args, args].concat()).unwrap() + } else { + e.invoke(&[invoke_args, args].concat()).unwrap() + }; + assert_eq!(res, r#"["Hello","world"]"#); + }); +} + +#[test] +fn invoke_auth() { + let sandbox = TestEnv::default(); + let id = &deploy_hello(&sandbox); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("auth") + .arg(&format!("--addr={DEFAULT_PUB_KEY}")) + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) + .success(); + + // Invoke it again without providing the contract, to exercise the deployment + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("auth") + .arg(&format!("--addr={DEFAULT_PUB_KEY}")) + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) + .success(); +} + +#[tokio::test] +async fn invoke_auth_with_identity() { + let sandbox = TestEnv::default(); + sandbox + .cmd::("test -d ") + .run() + .await + .unwrap(); + let id = deploy_hello(&sandbox); + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .arg("--") + .arg("auth") + .arg("--addr=test") + .arg("--world=world") + .assert() + .stdout(format!("\"{DEFAULT_PUB_KEY}\"\n")) + .success(); +} + +#[test] +fn contract_data_read_failure() { + let sandbox = TestEnv::default(); + let id = deploy_hello(&sandbox); + + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key=COUNTER") + .assert() + .failure() + .stderr( + "error: no matching contract data entries were found for the specified contract id\n", + ); +} + +#[test] +fn contract_data_read() { + let sandbox = TestEnv::default(); + let id = &deploy_hello(&sandbox); + + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("inc") + .assert() + .success(); + + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key=COUNTER") + .assert() + .success() + .stdout("COUNTER,1\n"); + + sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(id) + .arg("--") + .arg("inc") + .assert() + .success(); + + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key=COUNTER") + .assert() + .success() + .stdout("COUNTER,2\n"); +} + +#[test] +fn invoke_hello_world_with_seed() { + let sandbox = TestEnv::default(); + let identity = add_test_seed(sandbox.dir()); + invoke_with_source(&sandbox, &identity); +} + +#[test] +fn invoke_with_seed() { + let sandbox = TestEnv::default(); + invoke_with_source(&sandbox, DEFAULT_SEED_PHRASE); +} + +#[test] +fn invoke_with_id() { + let sandbox = TestEnv::default(); + let identity = add_test_seed(sandbox.dir()); + invoke_with_source(&sandbox, &identity); +} + +#[test] +fn invoke_with_sk() { + let sandbox = TestEnv::default(); + invoke_with_source(&sandbox, DEFAULT_SECRET_KEY); +} + +fn invoke_with_source(sandbox: &TestEnv, source: &str) { + let id = &deploy_hello(sandbox); + let cmd = sandbox.invoke(&[ + "--source-account", + source, + "--id", + id, + "--wasm", + HELLO_WORLD.path().to_str().unwrap(), + &rpc_url_arg().unwrap_or_default(), + &network_passphrase_arg().unwrap_or_default(), + "--", + "hello", + "--world=world", + ]); + assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); + + // Invoke it again without providing the contract, to exercise the deployment + let cmd = sandbox.invoke(&[ + "--source-account", + source, + "--id", + id, + "--", + "hello", + "--world=world", + ]); + assert_eq!(cmd.unwrap(), "[\"Hello\",\"world\"]"); +} + +#[tokio::test] +async fn fetch() { + if !is_rpc() { + return; + } + let e = TestEnv::default(); + let f = e.dir().join("contract.wasm"); + let id = deploy_hello(&e); + let cmd = e.cmd_arr::(&["--id", &id, "--out-file", f.to_str().unwrap()]); + cmd.run().await.unwrap(); + assert!(f.exists()); +} diff --git a/cmd/crates/soroban-test/tests/it/main.rs b/cmd/crates/soroban-test/tests/it/main.rs index 1d3af2cb6f..e822b7740d 100644 --- a/cmd/crates/soroban-test/tests/it/main.rs +++ b/cmd/crates/soroban-test/tests/it/main.rs @@ -1,9 +1,10 @@ mod arg_parsing; mod config; -mod contract_sandbox; mod custom_types; mod dotenv; +mod hello_world; +mod integration_and_sandbox; mod lab; mod plugin; mod util; diff --git a/cmd/crates/soroban-test/tests/it/util.rs b/cmd/crates/soroban-test/tests/it/util.rs index 56990ec54b..68c2e31acb 100644 --- a/cmd/crates/soroban-test/tests/it/util.rs +++ b/cmd/crates/soroban-test/tests/it/util.rs @@ -112,3 +112,30 @@ pub fn network_passphrase() -> Option { pub fn network_passphrase_arg() -> Option { network_passphrase().map(|p| format!("--network-passphrase={p}")) } + +pub const TEST_CONTRACT_ID: &str = "CBVTIVBYWAO2HNPNGKDCZW4OZYYESTKNGD7IPRTDGQSFJS4QBDQQJX3T"; + +pub fn deploy_hello(sandbox: &TestEnv) -> String { + let hash = HELLO_WORLD.hash().unwrap(); + sandbox + .new_assert_cmd("contract") + .arg("install") + .arg("--wasm") + .arg(HELLO_WORLD.path()) + .assert() + .success() + .stdout(format!("{hash}\n")); + + let mut cmd: &mut assert_cmd::Command = &mut sandbox.new_assert_cmd("contract"); + + cmd = cmd.arg("deploy").arg("--wasm-hash").arg(&format!("{hash}")); + if is_rpc() { + cmd = cmd.arg("--salt").arg(TEST_SALT); + } else { + cmd = cmd.arg("--id").arg(TEST_CONTRACT_ID); + } + cmd.assert() + .success() + .stdout(format!("{TEST_CONTRACT_ID}\n")); + TEST_CONTRACT_ID.to_string() +} diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index d7cf7363e1..8517e6421b 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -31,41 +31,16 @@ func cargoTest(t *testing.T, name string) { require.NoError(t, res.Error, res.Stdout(), res.Stderr()) } -func TestCLIfetch(t *testing.T) { - cargoTest(t, "contract_sandbox::fetch") -} -func TestCLIcontract_data_read_failure(t *testing.T) { - cargoTest(t, "contract_sandbox::contract_data_read_failure") -} -func TestCLIinvoke_auth(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_auth") -} -func TestCLIcontract_data_read(t *testing.T) { - cargoTest(t, "contract_sandbox::contract_data_read") -} -func TestCLIinvoke_hello_world_from_file(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_hello_world_from_file") -} -func TestCLIinvoke_hello_world_from_file_fail(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_hello_world_from_file_fail") -} -func TestCLIinvoke_hello_world_with_lib_two(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_hello_world_with_lib_two") -} -func TestCLIinvoke_hello_world_with_seed(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_hello_world_with_seed") -} -func TestCLIinvoke_with_sk(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_with_sk") -} -func TestCLIinvoke_auth_with_identity(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_auth_with_identity") -} -func TestCLIinvoke_with_id(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_with_id") -} -func TestCLIinvoke_with_seed(t *testing.T) { - cargoTest(t, "contract_sandbox::invoke_with_seed") +func TestCLICargoTest(t *testing.T) { + names := icmd.RunCmd(icmd.Command("cargo", "-q", "test", "integration_and_sandbox::", "--package", "soroban-test", "--", "--list")) + input := names.Stdout() + lines := strings.Split(input, "\n") + for _, line := range lines { + testName := strings.TrimSuffix(line, ": test") + t.Run(testName, func(t *testing.T) { + cargoTest(t, testName) + }) + } } func TestCLIWrapCustom(t *testing.T) {