From 1d20f087a695d5acc22606eebed51f0eada6587f Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Sat, 23 Sep 2023 10:37:55 -0400 Subject: [PATCH] chore: add way to invoke cargo from go code in effort to reuse rust tests (#967) * feat: use sim preamble to restore needed entries Currently the test uses a sleep because it has been a struggle to get an entry's expiration * Stop using a magic wait time and clean-up the code * feat: run cargo tests from go First example of using `cargo test` from the go code. * feat: add all tests from hello_world tests * fix: remove failing and overlapping tests * chore: add wrap test to show contract is created successfully * chore: remove comment * feat: organize CLI tests so that they can be invoked programatically * feat: use sim preamble to restore needed entries Currently the test uses a sleep because it has been a struggle to get an entry's expiration * Stop using a magic wait time and clean-up the code * fix: remove extraneous test Since other tests will deploy hello_world this adds nothing --------- Co-authored-by: Alfonso Acosta --- cmd/crates/soroban-test/src/lib.rs | 6 +- .../{contract_sandbox.rs => hello_world.rs} | 201 ++++++++-------- .../tests/it/integration_and_sandbox.rs | 222 ++++++++++++++++++ cmd/crates/soroban-test/tests/it/main.rs | 3 +- cmd/crates/soroban-test/tests/it/util.rs | 48 ++++ .../src/commands/config/identity/generate.rs | 8 +- cmd/soroban-rpc/internal/test/cli_test.go | 40 ++++ 7 files changed, 420 insertions(+), 108 deletions(-) rename cmd/crates/soroban-test/tests/it/{contract_sandbox.rs => hello_world.rs} (76%) create mode 100644 cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 8116e191b..7cf95c5b6 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -124,7 +124,11 @@ impl TestEnv { /// A convenience method for using the invoke command. pub fn invoke>(&self, command_str: &[I]) -> Result { let cmd = contract::invoke::Cmd::parse_arg_vec( - &command_str.iter().map(AsRef::as_ref).collect::>(), + &command_str + .iter() + .map(AsRef::as_ref) + .filter(|s| !s.is_empty()) + .collect::>(), ) .unwrap(); self.invoke_cmd(cmd) diff --git a/cmd/crates/soroban-test/tests/it/contract_sandbox.rs b/cmd/crates/soroban-test/tests/it/hello_world.rs similarity index 76% rename from cmd/crates/soroban-test/tests/it/contract_sandbox.rs rename to cmd/crates/soroban-test/tests/it/hello_world.rs index 5acfe90d4..30ee8c907 100644 --- a/cmd/crates/soroban-test/tests/it/contract_sandbox.rs +++ b/cmd/crates/soroban-test/tests/it/hello_world.rs @@ -6,14 +6,21 @@ use soroban_test::TestEnv; use std::path::PathBuf; use crate::util::{ - add_test_seed, DEFAULT_PUB_KEY, DEFAULT_PUB_KEY_1, DEFAULT_SECRET_KEY, DEFAULT_SEED_PHRASE, - HELLO_WORLD, + 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 hash = HELLO_WORLD.hash().unwrap(); 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") @@ -23,19 +30,25 @@ fn install_wasm_then_deploy_contract() { .success() .stdout(format!("{hash}\n")); - sandbox - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm-hash") - .arg(&format!("{hash}")) - .arg("--id=1") - .assert() + 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("CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM\n"); + .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") @@ -50,15 +63,7 @@ fn deploy_contract_with_wasm_file() { #[test] fn invoke_hello_world_with_deploy_first() { let sandbox = TestEnv::default(); - let res = sandbox - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success(); - let stdout = String::from_utf8(res.get_output().stdout.clone()).unwrap(); - let id = stdout.trim_end(); + let id = deploy_hello(&sandbox); println!("{id}"); sandbox .new_assert_cmd("contract") @@ -76,10 +81,12 @@ fn invoke_hello_world_with_deploy_first() { #[test] fn invoke_hello_world() { let sandbox = TestEnv::default(); + let id = deploy_hello(&sandbox); sandbox .new_assert_cmd("contract") .arg("invoke") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--wasm") .arg(HELLO_WORLD.path()) .arg("--") @@ -95,10 +102,12 @@ 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=1") + .arg("--id") + .arg(id) .arg("--wasm") .arg(HELLO_WORLD.path()) .arg("--") @@ -115,10 +124,12 @@ 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=1") + .arg("--id") + .arg(id) .arg("--wasm") .arg(HELLO_WORLD.path()) .arg("--") @@ -134,12 +145,16 @@ fn invoke_hello_world_from_file_fail() { #[test] fn invoke_hello_world_with_lib() { TestEnv::with_default(|e| { - let cmd = contract::invoke::Cmd { - contract_id: "1".to_string(), - wasm: Some(HELLO_WORLD.path()), + 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"]"#); }); @@ -148,16 +163,19 @@ fn invoke_hello_world_with_lib() { #[test] fn invoke_hello_world_with_lib_two() { TestEnv::with_default(|e| { - let res = e - .invoke(&[ - "--id=1", - "--wasm", - &HELLO_WORLD.to_string(), - "--", - "hello", - "--world=world", - ]) - .unwrap(); + 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"]"#); }); } @@ -172,10 +190,12 @@ fn invoke_hello_world_with_lib_two() { #[test] fn invoke_auth() { let sandbox = TestEnv::default(); + let id = &deploy_hello(&sandbox); sandbox .new_assert_cmd("contract") .arg("invoke") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--wasm") .arg(HELLO_WORLD.path()) .arg("--") @@ -190,7 +210,8 @@ fn invoke_auth() { sandbox .new_assert_cmd("contract") .arg("invoke") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--") .arg("auth") .arg(&format!("--addr={DEFAULT_PUB_KEY}")) @@ -203,16 +224,17 @@ fn invoke_auth() { #[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=1") + .arg("--id") + .arg(id) .arg("--wasm") .arg(HELLO_WORLD.path()) .arg("--") @@ -227,11 +249,13 @@ async fn invoke_auth_with_identity() { #[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=1") + .arg("--id") + .arg(id) .arg("--wasm") .arg(HELLO_WORLD.path()) .arg("--") @@ -245,31 +269,14 @@ fn invoke_auth_with_different_test_account() { #[test] fn contract_data_read_failure() { - let hash = HELLO_WORLD.hash().unwrap(); let sandbox = TestEnv::default(); - sandbox - .new_assert_cmd("contract") - .arg("install") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success() - .stdout(format!("{hash}\n")); - - sandbox - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm-hash") - .arg(&format!("{hash}")) - .arg("--id=1") - .assert() - .success() - .stdout("CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM\n"); + let id = deploy_hello(&sandbox); sandbox .new_assert_cmd("contract") .arg("read") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--key=COUNTER") .arg("--durability=persistent") .assert() @@ -281,31 +288,14 @@ fn contract_data_read_failure() { #[test] fn contract_data_read() { - let hash = HELLO_WORLD.hash().unwrap(); let sandbox = TestEnv::default(); - sandbox - .new_assert_cmd("contract") - .arg("install") - .arg("--wasm") - .arg(HELLO_WORLD.path()) - .assert() - .success() - .stdout(format!("{hash}\n")); - - sandbox - .new_assert_cmd("contract") - .arg("deploy") - .arg("--wasm-hash") - .arg(&format!("{hash}")) - .arg("--id=1") - .assert() - .success() - .stdout("CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM\n"); + let id = &deploy_hello(&sandbox); sandbox .new_assert_cmd("contract") .arg("invoke") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--") .arg("inc") .assert() @@ -314,7 +304,8 @@ fn contract_data_read() { sandbox .new_assert_cmd("contract") .arg("read") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--key=COUNTER") .arg("--durability=persistent") .assert() @@ -324,7 +315,8 @@ fn contract_data_read() { sandbox .new_assert_cmd("contract") .arg("invoke") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--") .arg("inc") .assert() @@ -333,7 +325,8 @@ fn contract_data_read() { sandbox .new_assert_cmd("contract") .arg("read") - .arg("--id=1") + .arg("--id") + .arg(id) .arg("--key=COUNTER") .arg("--durability=persistent") .assert() @@ -344,12 +337,15 @@ fn contract_data_read() { #[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=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}"), @@ -391,12 +387,16 @@ fn invoke_with_sk() { } fn invoke_with_source(sandbox: &TestEnv, source: &str) { + let id = &deploy_hello(sandbox); let cmd = sandbox.invoke(&[ "--source-account", source, - "--id=1", + "--id", + id, "--wasm", HELLO_WORLD.path().to_str().unwrap(), + &rpc_url_arg().unwrap_or_default(), + &network_passphrase_arg().unwrap_or_default(), "--", "hello", "--world=world", @@ -407,7 +407,8 @@ fn invoke_with_source(sandbox: &TestEnv, source: &str) { let cmd = sandbox.invoke(&[ "--source-account", source, - "--id=1", + "--id", + id, "--", "hello", "--world=world", @@ -417,9 +418,12 @@ fn invoke_with_source(sandbox: &TestEnv, source: &str) { #[test] fn handles_kebab_case() { - assert!(TestEnv::default() + let e = TestEnv::default(); + let id = deploy_hello(&e); + assert!(e .invoke(&[ - "--id=1", + "--id", + &id, "--wasm", HELLO_WORLD.path().to_str().unwrap(), "--", @@ -429,22 +433,15 @@ fn handles_kebab_case() { .is_ok()); } -#[ignore] #[tokio::test] async fn fetch() { - // TODO: Currently this test fetches a live contract from futurenet. This obviously depends on - // futurenet for the test to work, which is not great. But also means that if we are upgrading - // the XDR ahead of a futurenet upgrade, this test will pass. Oof. :( + if !is_rpc() { + return; + } let e = TestEnv::default(); let f = e.dir().join("contract.wasm"); - let cmd = e.cmd_arr::(&[ - "--id", - "bc074f0f03934d0189653bc15af9a83170411e103b4c48a63888306cfba41ac8", - "--network", - "futurenet", - "--out-file", - f.to_str().unwrap(), - ]); + 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/integration_and_sandbox.rs b/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs new file mode 100644 index 000000000..0beff5a78 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration_and_sandbox.rs @@ -0,0 +1,222 @@ +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] +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") + .arg("--durability=persistent") + .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") + .arg("--durability=persistent") + .assert() + .success() + .stdout("COUNTER,1,4096\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") + .arg("--durability=persistent") + .assert() + .success() + .stdout("COUNTER,2,4096\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 1d3af2cb6..e822b7740 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 ecd95ef8a..68c2e31ac 100644 --- a/cmd/crates/soroban-test/tests/it/util.rs +++ b/cmd/crates/soroban-test/tests/it/util.rs @@ -84,6 +84,10 @@ where }); } +pub fn is_rpc() -> bool { + std::env::var("SOROBAN_RPC_URL").is_ok() +} + pub const DEFAULT_SEED_PHRASE: &str = "coral light army gather adapt blossom school alcohol coral light army giggle"; @@ -91,3 +95,47 @@ pub const DEFAULT_PUB_KEY: &str = "GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2 pub const DEFAULT_SECRET_KEY: &str = "SC36BWNUOCZAO7DMEJNNKFV6BOTPJP7IG5PSHLUOLT6DZFRU3D3XGIXW"; pub const DEFAULT_PUB_KEY_1: &str = "GCKZUJVUNEFGD4HLFBUNVYM2QY2P5WQQZMGRA3DDL4HYVT5MW5KG3ODV"; +pub const TEST_SALT: &str = "f55ff16f66f43360266b95db6f8fec01d76031054306ae4a4b380598f6cfd114"; + +pub fn rpc_url() -> Option { + std::env::var("SOROBAN_RPC_URL").ok() +} + +pub fn rpc_url_arg() -> Option { + rpc_url().map(|url| format!("--rpc-url={url}")) +} + +pub fn network_passphrase() -> Option { + std::env::var("SOROBAN_NETWORK_PASSPHRASE").ok() +} + +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-cli/src/commands/config/identity/generate.rs b/cmd/soroban-cli/src/commands/config/identity/generate.rs index c07fe3d21..76a6073d8 100644 --- a/cmd/soroban-cli/src/commands/config/identity/generate.rs +++ b/cmd/soroban-cli/src/commands/config/identity/generate.rs @@ -64,10 +64,10 @@ impl Cmd { self.config_locator.write_identity(&self.name, &secret)?; if !self.network.is_no_network() { let addr = secret.public_key(self.hd_path)?; - self.network - .get(&self.config_locator)? - .fund_address(&addr) - .await?; + let network = self.network.get(&self.config_locator)?; + network.fund_address(&addr).await.unwrap_or_else(|_| { + tracing::warn!("Failed to fund address: {addr} on at {}", network.rpc_url); + }); } Ok(()) } diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index 8ceb2f213..bb3a789ac 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -21,6 +21,46 @@ import ( "gotest.tools/v3/icmd" ) +func cargoTest(t *testing.T, name string) { + NewCLITest(t) + c := icmd.Command("cargo", "test", "--package", "soroban-test", "--test", "it", "--", name, "--exact", "--nocapture") + c.Env = append(os.Environ(), + fmt.Sprintf("SOROBAN_RPC_URL=http://localhost:%d/", sorobanRPCPort), + fmt.Sprintf("SOROBAN_NETWORK_PASSPHRASE=%s", StandaloneNetworkPassphrase), + ) + res := icmd.RunCmd(c) + require.NoError(t, res.Error, res.Stdout(), res.Stderr()) +} + +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) { + NewCLITest(t) + testAccount := getCLIDefaultAccount(t) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("lab token wrap --asset=deadbeef:%s", testAccount)) + require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) + runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- mint --to=%s --amount 1", strkeyContractID, testAccount)) +} + +func TestCLIWrapNative(t *testing.T) { + NewCLITest(t) + testAccount := getCLIDefaultAccount(t) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("lab token wrap --asset=native:%s", testAccount)) + require.Equal(t, "CAMTHSPKXZJIRTUXQP5QWJIFH3XIDMKLFAWVQOFOXPTKAW5GKV37ZC4N", strkeyContractID) + require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) + require.Equal(t, "\"9223372036854775807\"", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- balance --id %s", strkeyContractID, testAccount))) +} + func TestCLIContractInstall(t *testing.T) { NewCLITest(t) output := runSuccessfulCLICmd(t, "contract install --wasm "+helloWorldContractPath)