diff --git a/bin/miden-cli/src/tests.rs b/bin/miden-cli/src/tests.rs index 3b29e84ba..a942e3ef2 100644 --- a/bin/miden-cli/src/tests.rs +++ b/bin/miden-cli/src/tests.rs @@ -6,7 +6,6 @@ use std::{ }; use assert_cmd::Command; -use config::RpcConfig; use miden_client::{ self, account::{ @@ -26,7 +25,7 @@ use miden_client::{ utils::Serializable, Client, Felt, }; -use miden_client_tests::common::{execute_tx_and_sync, insert_new_wallet}; +use miden_client_tests::common::{execute_tx_and_sync, get_client_config, insert_new_wallet}; use predicates::str::contains; use rand::Rng; use uuid::Uuid; @@ -62,8 +61,6 @@ fn test_init_without_params() { init_cmd.args(["init", "--network", "localhost"]); init_cmd.current_dir(&temp_dir).assert().success(); - sync_cli(&temp_dir); - // Trying to init twice should result in an error let mut init_cmd = Command::cargo_bin("miden").unwrap(); init_cmd.args(["init"]); @@ -90,13 +87,6 @@ fn test_init_with_params() { assert!(config_file_str.contains(store_path.to_str().unwrap())); assert!(config_file_str.contains("localhost")); - - sync_cli(&temp_dir); - - // Trying to init twice should result in an error - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args(["init", "--network", "localhost", "--store-path", store_path.to_str().unwrap()]); - init_cmd.current_dir(&temp_dir).assert().failure(); } // TX TESTS @@ -105,11 +95,6 @@ fn test_init_with_params() { /// This test tries to run a mint TX using the CLI for an account that isn't tracked. #[tokio::test] async fn test_mint_with_untracked_account() { - let store_path = create_test_store_path(); - let mut temp_dir = temp_dir(); - temp_dir.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir.clone()).unwrap(); - let target_account_id = { let other_store_path = create_test_store_path(); let mut client = create_test_client_with_store_path(&other_store_path).await; @@ -138,9 +123,7 @@ async fn test_mint_with_untracked_account() { }; // On CLI create the faucet and mint - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args(["init", "--network", "localhost", "--store-path", store_path.to_str().unwrap()]); - init_cmd.current_dir(&temp_dir).assert().success(); + let (temp_dir, store_path) = init_cli(); // Create faucet account let mut create_faucet_cmd = Command::cargo_bin("miden").unwrap(); @@ -188,10 +171,7 @@ const GENESIS_ACCOUNTS_FILENAMES: [&str; 1] = ["faucet.mac"]; #[tokio::test] #[ignore = "import genesis test gets ignored by default so integration tests can be ran with dockerized and remote nodes where we might not have the genesis data"] async fn test_import_genesis_accounts_can_be_used_for_transactions() { - let store_path = create_test_store_path(); - let mut temp_dir = temp_dir(); - temp_dir.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir.clone()).unwrap(); + let (temp_dir, store_path) = init_cli(); for genesis_account_filename in GENESIS_ACCOUNTS_FILENAMES { let mut new_file_path = temp_dir.clone(); @@ -207,10 +187,6 @@ async fn test_import_genesis_accounts_can_be_used_for_transactions() { std::fs::copy(source_path, new_file_path).unwrap(); } - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args(["init", "--network", "localhost", "--store-path", store_path.to_str().unwrap()]); - init_cmd.current_dir(&temp_dir).assert().success(); - // Import genesis accounts let mut args = vec!["import"]; for filename in GENESIS_ACCOUNTS_FILENAMES { @@ -266,26 +242,8 @@ async fn test_import_genesis_accounts_can_be_used_for_transactions() { async fn test_cli_export_import_note() { const NOTE_FILENAME: &str = "test_note.mno"; - let store_path_1 = create_test_store_path(); - let mut temp_dir_1 = temp_dir(); - temp_dir_1.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir_1.clone()).unwrap(); - - let store_path_2 = create_test_store_path(); - let mut temp_dir_2 = temp_dir(); - temp_dir_2.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir_2.clone()).unwrap(); - - // Init and create basic wallet on second client - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args([ - "init", - "--network", - "localhost", - "--store-path", - store_path_2.to_str().unwrap(), - ]); - init_cmd.current_dir(&temp_dir_2).assert().success(); + let (temp_dir_1, store_path_1) = init_cli(); + let (temp_dir_2, store_path_2) = init_cli(); // Create wallet account let mut create_wallet_cmd = Command::cargo_bin("miden").unwrap(); @@ -299,17 +257,6 @@ async fn test_cli_export_import_note() { accounts.first().unwrap().0.id().to_hex() }; - // On first client init, create a faucet and mint - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args([ - "init", - "--network", - "localhost", - "--store-path", - store_path_1.to_str().unwrap(), - ]); - init_cmd.current_dir(&temp_dir_1).assert().success(); - // Create faucet account let mut create_faucet_cmd = Command::cargo_bin("miden").unwrap(); create_faucet_cmd.args([ @@ -395,37 +342,8 @@ async fn test_cli_export_import_note() { async fn test_cli_export_import_account() { const ACCOUNT_FILENAME: &str = "test_account.acc"; - let store_path_1 = create_test_store_path(); - let mut temp_dir_1 = temp_dir(); - temp_dir_1.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir_1.clone()).unwrap(); - - let store_path_2 = create_test_store_path(); - let mut temp_dir_2 = temp_dir(); - temp_dir_2.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir_2.clone()).unwrap(); - - // Init the first client - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args([ - "init", - "--network", - "localhost", - "--store-path", - store_path_1.to_str().unwrap(), - ]); - init_cmd.current_dir(&temp_dir_1).assert().success(); - - // Init the second client - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args([ - "init", - "--network", - "localhost", - "--store-path", - store_path_2.to_str().unwrap(), - ]); - init_cmd.current_dir(&temp_dir_2).assert().success(); + let (temp_dir_1, store_path_1) = init_cli(); + let (temp_dir_2, store_path_2) = init_cli(); // Create wallet account let mut create_wallet_cmd = Command::cargo_bin("miden").unwrap(); @@ -472,15 +390,7 @@ async fn test_cli_export_import_account() { #[test] fn test_cli_empty_commands() { - let store_path = create_test_store_path(); - let mut temp_dir = temp_dir(); - temp_dir.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir.clone()).unwrap(); - - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - - init_cmd.args(["init", "--network", "localhost", "--store-path", store_path.to_str().unwrap()]); - init_cmd.current_dir(&temp_dir).assert().success(); + let (..) = init_cli(); let mut create_faucet_cmd = Command::cargo_bin("miden").unwrap(); assert_command_fails_but_does_not_panic(create_faucet_cmd.args(["new-faucet"])); @@ -500,14 +410,7 @@ fn test_cli_empty_commands() { #[tokio::test] async fn test_consume_unauthenticated_note() { - let store_path = create_test_store_path(); - let mut temp_dir = temp_dir(); - temp_dir.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir.clone()).unwrap(); - - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args(["init", "--network", "localhost", "--store-path", store_path.to_str().unwrap()]); - init_cmd.current_dir(&temp_dir).assert().success(); + let (temp_dir, store_path) = init_cli(); // Create wallet account let mut create_wallet_cmd = Command::cargo_bin("miden").unwrap(); @@ -558,9 +461,102 @@ async fn test_consume_unauthenticated_note() { consume_note_cli(&temp_dir, &wallet_account_id, &[¬e_id]); } +#[tokio::test] +async fn debug_mode_outputs_logs() { + const NOTE_FILENAME: &str = "test_note.mno"; + env::set_var("MIDEN_DEBUG", "true"); + let (temp_dir, store_path) = init_cli(); + + // Create a Client and a custom note + let mut client = create_test_client_with_store_path(&store_path).await; + let (account, _) = insert_new_wallet(&mut client, AccountStorageMode::Private).await.unwrap(); + + // Create the custom note + let note_script = " + begin + debug.stack + assert_eq + end + "; + let note_script = client.compile_note_script(note_script).unwrap(); + let inputs = NoteInputs::new(vec![]).unwrap(); + let serial_num = client.rng().draw_word(); + let note_metadata = NoteMetadata::new( + account.id(), + NoteType::Private, + NoteTag::from_account_id(account.id(), NoteExecutionMode::Local).unwrap(), + NoteExecutionHint::None, + Default::default(), + ) + .unwrap(); + let note_assets = NoteAssets::new(vec![]).unwrap(); + let note_recipient = NoteRecipient::new(serial_num, note_script, inputs); + let note = Note::new(note_assets, note_metadata, note_recipient); + + // Send transaction and wait for it to be committed + let transaction_request = TransactionRequestBuilder::new() + .with_own_output_notes(vec![OutputNote::Full(note.clone())]) + .unwrap() + .build(); + execute_tx_and_sync(&mut client, account.id(), transaction_request).await; + + // Export the note + let note_file: NoteFile = NoteFile::NoteDetails { + details: note.clone().into(), + after_block_num: 0.into(), + tag: Some(note.metadata().tag()), + }; + + // Serialize the note + let note_path = temp_dir.join(NOTE_FILENAME); + let mut file = File::create(note_path.clone()).unwrap(); + file.write_all(¬e_file.to_bytes()).unwrap(); + + // Import the note + let mut import_cmd = Command::cargo_bin("miden").unwrap(); + import_cmd.args(["import", note_path.to_str().unwrap()]); + import_cmd.current_dir(&temp_dir).assert().success(); + + sync_cli(&temp_dir); + + // Consume the note and check the output + let mut consume_note_cmd = Command::cargo_bin("miden").unwrap(); + let account_id = account.id().to_hex(); + let note_id = note.id().to_hex(); + let mut cli_args = vec!["consume-notes", "--account", &account_id[0..8], "--force"]; + cli_args.extend_from_slice(vec![note_id.as_str()].as_slice()); + consume_note_cmd.args(&cli_args); + consume_note_cmd + .current_dir(&temp_dir) + .assert() + .success() + .stdout(contains("Stack state")); +} + // HELPERS // ================================================================================================ +// Initializes the CLI on the given directory using the parameters from the test config files. +fn init_cli() -> (PathBuf, PathBuf) { + let mut temp_dir = temp_dir(); + temp_dir.push(format!("{}", uuid::Uuid::new_v4())); + std::fs::create_dir(temp_dir.clone()).unwrap(); + + let (endpoint, _, store_path) = get_client_config(); + + let mut init_cmd = Command::cargo_bin("miden").unwrap(); + init_cmd.args([ + "init", + "--network", + endpoint.to_string().as_str(), + "--store-path", + store_path.to_str().unwrap(), + ]); + init_cmd.current_dir(&temp_dir).assert().success(); + + (temp_dir, store_path) +} + // Syncs CLI on directory. It'll try syncing until the command executes successfully. If it never // executes successfully, eventually the test will time out (provided the nextest config has a // timeout set). @@ -652,7 +648,7 @@ pub fn create_test_store_path() -> std::path::PathBuf { pub type TestClient = Client; async fn create_test_client_with_store_path(store_path: &Path) -> TestClient { - let rpc_config = RpcConfig::default(); + let (endpoint, timeout, _) = get_client_config(); let store = { let sqlite_store = SqliteStore::new(PathBuf::from(store_path)).await.unwrap(); @@ -666,7 +662,7 @@ async fn create_test_client_with_store_path(store_path: &Path) -> TestClient { let authenticator = StoreAuthenticator::new_with_rng(store.clone(), rng); TestClient::new( - Box::new(TonicRpcClient::new(rpc_config.endpoint.into(), rpc_config.timeout_ms)), + Box::new(TonicRpcClient::new(endpoint, timeout)), rng, store, std::sync::Arc::new(authenticator), @@ -680,84 +676,3 @@ fn assert_command_fails_but_does_not_panic(command: &mut Command) { assert_ne!(exit_code, 0); // Command failed assert_ne!(exit_code, 101); // Command didn't panic } - -#[tokio::test] -async fn debug_mode_outputs_logs() { - const NOTE_FILENAME: &str = "test_note.mno"; - env::set_var("MIDEN_DEBUG", "true"); - - // Create a Client and a custom note - let store_path = create_test_store_path(); - let mut client = create_test_client_with_store_path(&store_path).await; - let (account, _) = insert_new_wallet(&mut client, AccountStorageMode::Private).await.unwrap(); - - // Create the custom note - let note_script = " - begin - debug.stack - assert_eq - end - "; - let note_script = client.compile_note_script(note_script).unwrap(); - let inputs = NoteInputs::new(vec![]).unwrap(); - let serial_num = client.rng().draw_word(); - let note_metadata = NoteMetadata::new( - account.id(), - NoteType::Private, - NoteTag::from_account_id(account.id(), NoteExecutionMode::Local).unwrap(), - NoteExecutionHint::None, - Default::default(), - ) - .unwrap(); - let note_assets = NoteAssets::new(vec![]).unwrap(); - let note_recipient = NoteRecipient::new(serial_num, note_script, inputs); - let note = Note::new(note_assets, note_metadata, note_recipient); - - // Send transaction and wait for it to be committed - let transaction_request = TransactionRequestBuilder::new() - .with_own_output_notes(vec![OutputNote::Full(note.clone())]) - .unwrap() - .build(); - execute_tx_and_sync(&mut client, account.id(), transaction_request).await; - - // Export the note - let note_file: NoteFile = NoteFile::NoteDetails { - details: note.clone().into(), - after_block_num: 0.into(), - tag: Some(note.metadata().tag()), - }; - - // Serialize the note - let mut temp_dir = temp_dir(); - let note_path = temp_dir.join(NOTE_FILENAME); - let mut file = File::create(note_path.clone()).unwrap(); - file.write_all(¬e_file.to_bytes()).unwrap(); - - // Use the Cli to import the note - temp_dir.push(format!("{}", uuid::Uuid::new_v4())); - std::fs::create_dir(temp_dir.clone()).unwrap(); - - let mut init_cmd = Command::cargo_bin("miden").unwrap(); - init_cmd.args(["init", "--network", "localhost", "--store-path", store_path.to_str().unwrap()]); - init_cmd.current_dir(&temp_dir).assert().success(); - - // Import the note - let mut import_cmd = Command::cargo_bin("miden").unwrap(); - import_cmd.args(["import", note_path.to_str().unwrap()]); - import_cmd.current_dir(&temp_dir).assert().success(); - - sync_cli(&temp_dir); - - // Consume the note and check the output - let mut consume_note_cmd = Command::cargo_bin("miden").unwrap(); - let account_id = account.id().to_hex(); - let note_id = note.id().to_hex(); - let mut cli_args = vec!["consume-notes", "--account", &account_id[0..8], "--force"]; - cli_args.extend_from_slice(vec![note_id.as_str()].as_slice()); - consume_note_cmd.args(&cli_args); - consume_note_cmd - .current_dir(&temp_dir) - .assert() - .success() - .stdout(contains("Stack state")); -} diff --git a/tests/config/miden-client-rpc.toml b/tests/config/miden-client-rpc.toml index 477687ce6..9f1e5108d 100644 --- a/tests/config/miden-client-rpc.toml +++ b/tests/config/miden-client-rpc.toml @@ -1,6 +1,8 @@ ## USAGE: ## ================================================================================================ -# - endpoint: tuple indicating the protocol (http, https), the host, and the port where the node is listening. +# - endpoint: tuple indicating the protocol (http, https), the host, and (optionally) the port where the node is listening. # - timeout: timeout in ms for the rpc requests against the node. + +# endpoint = { protocol = "https", host = "rpc.devnet.miden.io" } endpoint = { protocol = "http", host = "localhost", port = 57291 } timeout = 10000 diff --git a/tests/integration/common.rs b/tests/integration/common.rs index 0467776a0..cf2920bde 100644 --- a/tests/integration/common.rs +++ b/tests/integration/common.rs @@ -33,7 +33,7 @@ pub const ACCOUNT_ID_REGULAR: u128 = ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_O pub type TestClient = Client; -pub const TEST_CLIENT_RPC_CONFIG_FILE_PATH: &str = "./config/miden-client-rpc.toml"; +pub const TEST_CLIENT_RPC_CONFIG_FILE: &str = include_str!("../config/miden-client-rpc.toml"); /// Creates a `TestClient`. /// /// Creates the client using the config at `TEST_CLIENT_CONFIG_FILE_PATH`. The store's path is at a @@ -67,18 +67,18 @@ pub async fn create_test_client() -> TestClient { } pub fn get_client_config() -> (Endpoint, u64, PathBuf) { - let rpc_config_toml = std::fs::read_to_string(TEST_CLIENT_RPC_CONFIG_FILE_PATH) - .unwrap() - .parse::() - .unwrap(); + let rpc_config_toml = TEST_CLIENT_RPC_CONFIG_FILE.parse::
().unwrap(); let rpc_endpoint_toml = rpc_config_toml["endpoint"].as_table().unwrap(); - let endpoint = rpc_endpoint_toml["protocol"].as_str().unwrap().to_string() - + "://" - + rpc_endpoint_toml["host"].as_str().unwrap() - + ":" - + &rpc_endpoint_toml["port"].as_integer().unwrap().to_string(); - let endpoint = Endpoint::try_from(endpoint.as_str()).unwrap(); + let protocol = rpc_endpoint_toml["protocol"].as_str().unwrap().to_string(); + let host = rpc_endpoint_toml["host"].as_str().unwrap().to_string(); + let port = if rpc_endpoint_toml.contains_key("port") { + rpc_endpoint_toml["port"].as_integer().map(|port| port as u16) + } else { + None + }; + + let endpoint = Endpoint::new(protocol, host, port); let timeout_ms = rpc_config_toml["timeout"].as_integer().unwrap() as u64;