From d836b83be5ed4c5028bad0db41769f07fb473b48 Mon Sep 17 00:00:00 2001 From: DenisRybas Date: Mon, 12 Feb 2024 23:27:40 +0300 Subject: [PATCH] processed comments Signed-off-by: DenisRybas --- vdr/Cargo.lock | 42 +++ vdr/Cargo.toml | 1 + vdr/src/client/client.rs | 149 +++------ .../client/implementation/web3/contract.rs | 11 +- vdr/src/contracts/auth/role_control.rs | 107 +----- .../contracts/network/validator_control.rs | 16 + vdr/src/types/transaction.rs | 316 +++++++----------- 7 files changed, 229 insertions(+), 413 deletions(-) diff --git a/vdr/Cargo.lock b/vdr/Cargo.lock index 54a6490a..9ae21d12 100644 --- a/vdr/Cargo.lock +++ b/vdr/Cargo.lock @@ -943,6 +943,12 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "gloo-timers" version = "0.2.6" @@ -1252,6 +1258,7 @@ dependencies = [ "mockall", "once_cell", "rand", + "rstest", "secp256k1 0.28.0", "serde", "serde_derive", @@ -1978,6 +1985,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "relative-path" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" + [[package]] name = "reqwest" version = "0.11.23" @@ -2048,6 +2061,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rstest" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.37", + "unicode-ident", +] + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/vdr/Cargo.toml b/vdr/Cargo.toml index 5414aca7..6e96254a 100644 --- a/vdr/Cargo.toml +++ b/vdr/Cargo.toml @@ -46,6 +46,7 @@ web-sys = { version = "0.3.64", optional = true, features = ["Window"] } web3-wasm = { package = "web3", version = "0.19.0", default-features = false, features = ["wasm", "http", "http-tls"], optional = true } [dev-dependencies] +rstest = "0.18.2" mockall = "0.12.0" env_logger = "0.10.0" rand = "0.8.5" \ No newline at end of file diff --git a/vdr/src/client/client.rs b/vdr/src/client/client.rs index 76689f06..a7023b36 100644 --- a/vdr/src/client/client.rs +++ b/vdr/src/client/client.rs @@ -214,28 +214,11 @@ impl Debug for LedgerClient { pub mod test { use super::*; use crate::{ - client::MockClient, signer::basic_signer::test::basic_signer, types::EventLog, Role, + client::MockClient, signer::basic_signer::test::basic_signer, }; - use async_trait::async_trait; use once_cell::sync::Lazy; use std::{env, fs, sync::RwLock}; - pub const CONTRACT_NAME_EXAMPLE: &str = "ValidatorControl"; - pub const CONTRACT_METHOD_EXAMPLE: &str = "addValidator"; - pub const VALIDATOR_LIST_BYTES: Lazy> = Lazy::new(|| { - vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 145, 124, 173, 186, 206, 93, - 252, 225, 50, 185, 145, 115, 44, 108, 218, 155, 204, 91, 138, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 39, 169, 124, 154, 175, 4, 241, 143, 48, 20, 195, 46, 3, 109, 208, 172, - 118, 218, 95, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 65, 47, 152, 131, 119, 227, - 31, 77, 15, 241, 45, 116, 223, 115, 181, 28, 66, 208, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 152, 193, 51, 68, 150, 97, 74, 237, 73, 210, 232, 21, 38, 208, 137, 247, 38, - 79, 237, 156, - ] - }); - pub const CHAIN_ID: u64 = 1337; pub const CONTRACTS_SPEC_BASE_PATH: &str = "../smart_contracts/artifacts/contracts/"; pub const SCHEMA_REGISTRY_SPEC_PATH: &str = "cl/SchemaRegistry.sol/SchemaRegistry.json"; @@ -253,8 +236,7 @@ pub mod test { "http://127.0.0.1:21004", ]; pub const DEFAULT_NONCE: u64 = 0; - pub static ACCOUNT_ROLES: [Role; 4] = - [Role::Empty, Role::Trustee, Role::Steward, Role::Endorser]; + pub const INVALID_ADDRESS: &str = "123"; pub static SCHEMA_REGISTRY_ADDRESS: Lazy
= Lazy::new(|| Address::from("0x0000000000000000000000000000000000005555")); @@ -262,7 +244,7 @@ pub mod test { pub static CRED_DEF_REGISTRY_ADDRESS: Lazy
= Lazy::new(|| Address::from("0x0000000000000000000000000000000000004444")); - pub static VALIDATOR_CONTROL_ADDRESS: Lazy
= + pub const VALIDATOR_CONTROL_ADDRESS: Lazy
= Lazy::new(|| Address::from("0x0000000000000000000000000000000000007777")); pub static ROLE_CONTROL_ADDRESS: Lazy
= @@ -384,7 +366,9 @@ pub mod test { } mod create { + use crate::validator_control::test::VALIDATOR_CONTROL_NAME; use mockall::predicate::eq; + use rstest::rstest; use serde_json::Value; use super::*; @@ -394,26 +378,6 @@ pub mod test { client(); } - #[test] - fn create_client_invalid_contract_data() { - let contract_config = vec![ContractConfig { - address: VALIDATOR_CONTROL_ADDRESS.to_string(), - spec_path: None, - spec: Some(ContractSpec { - name: CONTRACT_NAME_EXAMPLE.to_string(), - abi: Value::String("".to_string()), - }), - }]; - - let client_err = LedgerClient::new(CHAIN_ID, RPC_NODE_ADDRESS, &contract_config, None) - .err() - .unwrap(); - - assert!(matches!( - client_err, | VdrError::ContractInvalidInputData { .. } - )); - } - #[test] fn create_client_invalid_node_address() { let client_err = LedgerClient::new(CHAIN_ID, "..", &contracts(), None) @@ -425,88 +389,55 @@ pub mod test { )); } - #[test] - fn create_client_contract_path_and_spec_provided() { - let contract_config = vec![ContractConfig { - address: VALIDATOR_CONTROL_ADDRESS.to_string(), - spec_path: Some(build_contract_path(VALIDATOR_CONTROL_PATH)), - spec: Some(ContractSpec { - name: CONTRACT_NAME_EXAMPLE.to_string(), - abi: Value::Array(vec![]), + #[rstest] + #[case::invalid_contract_data(&VALIDATOR_CONTROL_ADDRESS, None, Some(VALIDATOR_CONTROL_NAME), Some(""), VdrError::ContractInvalidInputData)] + #[case::both_contract_path_and_spec_provided(&VALIDATOR_CONTROL_ADDRESS, Some(VALIDATOR_CONTROL_PATH), Some(VALIDATOR_CONTROL_NAME), None, VdrError::ContractInvalidSpec("".to_string()))] + #[case::non_existent_spec_path(&VALIDATOR_CONTROL_ADDRESS, Some(""), None, None, VdrError::ContractInvalidSpec("".to_string()))] + #[case::empty_contract_spec(&VALIDATOR_CONTROL_ADDRESS, None, None, None, VdrError::ContractInvalidSpec("".to_string()))] + fn test_create_client_errors( + #[case] address: &Address, + #[case] spec_path: Option<&str>, + #[case] name: Option<&str>, + #[case] abi: Option<&str>, + #[case] expected_error: VdrError, + ) { + let spec = match (name, abi) { + (Some(n), Some(a)) => Some(ContractSpec { + name: n.to_string(), + abi: Value::String(a.to_string()), }), - }]; - - let client_err = LedgerClient::new(CHAIN_ID, RPC_NODE_ADDRESS, &contract_config, None) - .err() - .unwrap(); - - assert!(matches!( - client_err, | VdrError::ContractInvalidSpec { .. } - )); - } - - #[test] - fn create_client_empty_contract_spec() { - let contract_config = vec![ContractConfig { - address: VALIDATOR_CONTROL_ADDRESS.to_string(), - spec_path: None, - spec: None, - }]; - - let client_err = LedgerClient::new(CHAIN_ID, RPC_NODE_ADDRESS, &contract_config, None) - .err() - .unwrap(); - - assert!(matches!( - client_err, | VdrError::ContractInvalidSpec { .. } - )); - } + _ => None, + }; - #[async_std::test] - async fn create_client_invalid_contract_address() { let contract_config = vec![ContractConfig { - address: "123".to_string(), - spec_path: Some(build_contract_path(VALIDATOR_CONTROL_PATH)), - spec: None, + address: address.to_string(), + spec_path: spec_path.map(|sp| sp.to_string()), + spec, }]; let client_err = LedgerClient::new(CHAIN_ID, RPC_NODE_ADDRESS, &contract_config, None) .err() .unwrap(); - assert!(matches!( - client_err, | VdrError::CommonInvalidData { .. } - )); - } - - #[async_std::test] - async fn call_transaction_empty_recipient_address() { - let transaction = Transaction { - to: Address::from(""), - ..read_transaction() - }; - let client = client(); - - let submit_err = client.submit_transaction(&transaction).await.unwrap_err(); - - assert!(matches!( - submit_err, | VdrError::ClientInvalidTransaction { .. } - )); + assert!(matches!(client_err, expected_error)); } - #[async_std::test] - async fn call_transaction_invalid_recipient_address() { + #[rstest] + #[case::empty_recipient_address("", VdrError::ClientInvalidTransaction("".to_string()))] + #[case::invalid_recipient_address(INVALID_ADDRESS, VdrError::ClientInvalidTransaction("".to_string()))] + async fn call_transaction_various_recipient_addresses( + #[case] recipient_address: &str, + #[case] expected_error: VdrError, + ) { let transaction = Transaction { - to: Address::from("123"), + to: Address::from(recipient_address), ..read_transaction() }; let client = client(); - let call_err = client.submit_transaction(&transaction).await.unwrap_err(); + let error = client.submit_transaction(&transaction).await.unwrap_err(); - assert!(matches!( - call_err, | VdrError::ClientInvalidTransaction { .. } - )); + assert!(matches!(error, expected_error)); } #[async_std::test] @@ -522,7 +453,7 @@ pub mod test { } #[async_std::test] - async fn get_receipt_transcation_does_not_exist() { + async fn get_receipt_transaction_does_not_exist() { let mut client_mock = MockClient::new(); let txn_hash = vec![1; 32]; client_mock @@ -562,7 +493,7 @@ pub mod test { let client = client(); let get_nonce_err = client - .get_transaction_count(&Address::from("123")) + .get_transaction_count(&Address::from(INVALID_ADDRESS)) .await .unwrap_err(); @@ -575,7 +506,7 @@ pub mod test { async fn get_contract_does_not_exist() { let client = client(); - let contract_err = client.contract("123").err().unwrap(); + let contract_err = client.contract(INVALID_ADDRESS).err().unwrap(); assert!(matches!( contract_err, | VdrError::ContractInvalidName { .. } diff --git a/vdr/src/client/implementation/web3/contract.rs b/vdr/src/client/implementation/web3/contract.rs index 97f485b7..125af635 100644 --- a/vdr/src/client/implementation/web3/contract.rs +++ b/vdr/src/client/implementation/web3/contract.rs @@ -118,15 +118,20 @@ impl Debug for Web3Contract { #[cfg(test)] pub mod test { - use crate::client::client::test::{mock_client, CONTRACT_NAME_EXAMPLE}; + use crate::{ + client::client::test::{mock_client, INVALID_ADDRESS}, + validator_control::test::VALIDATOR_CONTROL_NAME, + }; use super::*; #[async_std::test] async fn function_method_does_not_exist() { let client = mock_client(); - let contract = client.contract(&CONTRACT_NAME_EXAMPLE.to_string()).unwrap(); + let contract = client + .contract(&VALIDATOR_CONTROL_NAME.to_string()) + .unwrap(); - let err = contract.function("123").unwrap_err(); + let err = contract.function(INVALID_ADDRESS).unwrap_err(); assert!(matches!( err, | VdrError::ContractInvalidName { .. } diff --git a/vdr/src/contracts/auth/role_control.rs b/vdr/src/contracts/auth/role_control.rs index c49d6fdd..97c662f7 100644 --- a/vdr/src/contracts/auth/role_control.rs +++ b/vdr/src/contracts/auth/role_control.rs @@ -158,12 +158,15 @@ pub mod test { use super::*; use crate::{ client::client::test::{ - mock_client, ACCOUNT_ROLES, CHAIN_ID, DEFAULT_NONCE, ROLE_CONTROL_ADDRESS, TRUSTEE_ACC, + mock_client, CHAIN_ID, DEFAULT_NONCE, ROLE_CONTROL_ADDRESS, TRUSTEE_ACC, }, utils::init_env_logger, }; use std::sync::RwLock; + pub static ACCOUNT_ROLES: [Role; 4] = + [Role::Empty, Role::Trustee, Role::Steward, Role::Endorser]; + pub const NEW_ACCOUNT: &str = "0x0886328869e4e1f401e1052a5f4aae8b45f42610"; fn account() -> Address { @@ -201,45 +204,10 @@ pub mod test { assert_eq!(expected_transaction, transaction); } - - #[async_std::test] - async fn build_assign_role_transaction_all_roles_test() { - init_env_logger(); - let client = mock_client(); - let account = account(); - - for role in ACCOUNT_ROLES.iter() { - let transaction = - build_assign_role_transaction(&client, &TRUSTEE_ACC, &role, &account) - .await - .unwrap(); - - let contract = client.contract(CONTRACT_NAME).unwrap(); - let expected_data = contract - .function(METHOD_ASSIGN_ROLE) - .unwrap() - .encode_input(&[role.try_into().unwrap(), (&account).try_into().unwrap()]) - .unwrap(); - - let expected_transaction = Transaction { - type_: TransactionType::Write, - from: Some(TRUSTEE_ACC.clone()), - to: ROLE_CONTROL_ADDRESS.clone(), - nonce: Some(DEFAULT_NONCE.clone()), - chain_id: CHAIN_ID, - data: expected_data, - signature: RwLock::new(None), - hash: None, - }; - - assert_eq!(expected_transaction, transaction); - } - } } mod build_revoke_role_transaction { use super::*; - use crate::types::ContractParam; #[async_std::test] async fn build_revoke_role_transaction_test() { @@ -269,40 +237,6 @@ pub mod test { assert_eq!(expected_transaction, transaction); } - - #[async_std::test] - async fn build_revoke_role_transaction_all_roles_test() { - init_env_logger(); - let client = mock_client(); - let account = account(); - - for role in ACCOUNT_ROLES.iter() { - let transaction = - build_revoke_role_transaction(&client, &TRUSTEE_ACC, &role, &account) - .await - .unwrap(); - - let contract = client.contract(CONTRACT_NAME).unwrap(); - let expected_data = contract - .function(METHOD_REVOKE_ROLE) - .unwrap() - .encode_input(&[role.try_into().unwrap(), (&account).try_into().unwrap()]) - .unwrap(); - - let expected_transaction = Transaction { - type_: TransactionType::Write, - from: Some(TRUSTEE_ACC.clone()), - to: ROLE_CONTROL_ADDRESS.clone(), - nonce: Some(DEFAULT_NONCE.clone()), - chain_id: CHAIN_ID, - data: expected_data, - signature: RwLock::new(None), - hash: None, - }; - - assert_eq!(expected_transaction, transaction); - } - } } mod build_get_role_transaction { @@ -382,39 +316,6 @@ pub mod test { assert_eq!(expected_transaction, transaction); } - - #[async_std::test] - async fn build_revoke_role_transaction_all_roles_test() { - init_env_logger(); - let client = mock_client(); - let account = account(); - - for role in ACCOUNT_ROLES.iter() { - let transaction = build_has_role_transaction(&client, &role, &account) - .await - .unwrap(); - - let contract = client.contract(CONTRACT_NAME).unwrap(); - let expected_data = contract - .function(METHOD_HAS_ROLE) - .unwrap() - .encode_input(&[role.try_into().unwrap(), (&account).try_into().unwrap()]) - .unwrap(); - - let expected_transaction = Transaction { - type_: TransactionType::Read, - from: None, - to: ROLE_CONTROL_ADDRESS.clone(), - nonce: None, - chain_id: CHAIN_ID, - data: expected_data, - signature: RwLock::new(None), - hash: None, - }; - - assert_eq!(expected_transaction, transaction); - } - } } mod parse_has_role_result { diff --git a/vdr/src/contracts/network/validator_control.rs b/vdr/src/contracts/network/validator_control.rs index 8a95956a..115c8467 100644 --- a/vdr/src/contracts/network/validator_control.rs +++ b/vdr/src/contracts/network/validator_control.rs @@ -118,6 +118,22 @@ pub mod test { pub static VALIDATOR_ADDRESS: Lazy
= Lazy::new(|| Address::from("0x93917cadbace5dfce132b991732c6cda9bcc5b8a")); + pub const VALIDATOR_CONTROL_NAME: &str = "ValidatorControl"; + pub const ADD_VALIDATOR_METHOD: &str = "addValidator"; + pub const VALIDATOR_LIST_BYTES: Lazy> = Lazy::new(|| { + vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 145, 124, 173, 186, 206, 93, + 252, 225, 50, 185, 145, 115, 44, 108, 218, 155, 204, 91, 138, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 39, 169, 124, 154, 175, 4, 241, 143, 48, 20, 195, 46, 3, 109, 208, 172, + 118, 218, 95, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 65, 47, 152, 131, 119, 227, + 31, 77, 15, 241, 45, 116, 223, 115, 181, 28, 66, 208, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 152, 193, 51, 68, 150, 97, 74, 237, 73, 210, 232, 21, 38, 208, 137, 247, 38, + 79, 237, 156, + ] + }); + mod build_add_validator_transaction { use super::*; diff --git a/vdr/src/types/transaction.rs b/vdr/src/types/transaction.rs index b1288998..453fc10c 100644 --- a/vdr/src/types/transaction.rs +++ b/vdr/src/types/transaction.rs @@ -500,16 +500,22 @@ pub struct BlockDetails { pub mod test { use super::*; use crate::{ - client::client::test::{ - client, mock_client, write_transaction, CONTRACT_METHOD_EXAMPLE, CONTRACT_NAME_EXAMPLE, - VALIDATOR_LIST_BYTES, - }, - contracts::{ - cl::types::credential_definition::test::_CREDENTIAL_DEFINITION_ID, - network::ValidatorAddresses, + client::client::test::{mock_client, write_transaction, INVALID_ADDRESS}, + contracts::network::test::{ + ADD_VALIDATOR_METHOD, VALIDATOR_ADDRESS, VALIDATOR_CONTROL_NAME, VALIDATOR_LIST_BYTES, }, }; + const INVALID_METHOD: Option<&str> = Some(INVALID_ADDRESS); + const INVALID_CONTRACT: Option<&str> = Some(INVALID_ADDRESS); + const INVALID_ACC_ADDRESS: Option<&str> = Some(INVALID_ADDRESS); + const CONTRACT_METHOD_EXAMPLE: Option<&str> = Some(ADD_VALIDATOR_METHOD); + const CONTRACT_NAME_EXAMPLE: Option<&str> = Some(VALIDATOR_CONTROL_NAME); + + fn matches_error_type(actual_error: VdrError, expected_error: VdrError) -> bool { + std::mem::discriminant(&actual_error) == std::mem::discriminant(&expected_error) + } + #[cfg(test)] pub mod txn_test { use super::*; @@ -517,7 +523,7 @@ pub mod test { #[async_std::test] async fn get_to_invalid() { let transaction = Transaction { - to: Address::from("123"), + to: Address::from(INVALID_ADDRESS), ..write_transaction() }; @@ -578,12 +584,8 @@ pub mod test { #[cfg(test)] pub mod txn_builder_test { use super::*; - - const INVALID_METHOD: Option<&str> = Some("123"); - const VALIDATOR_ADDRESS: &str = "0x93917cadbace5dfce132b991732c6cda9bcc5b8a"; - const INVALID_ACC_ADDRESS: Option<&str> = Some("123"); - const CONTRACT_METHOD_EXAMPLE: Option<&str> = Some(test::CONTRACT_METHOD_EXAMPLE); - const CONTRACT_NAME_EXAMPLE: Option<&str> = Some(test::CONTRACT_NAME_EXAMPLE); + use rstest::rstest; + use std::ops::Deref; async fn setup_transaction_builder( contract: Option<&str>, @@ -592,9 +594,10 @@ pub mod test { from: Option<&str>, ) -> VdrResult { let client = mock_client(); - let address = Address::from(VALIDATOR_ADDRESS); - let mut builder = TransactionBuilder::new().add_param(&address).unwrap(); + let mut builder = TransactionBuilder::new() + .add_param(VALIDATOR_ADDRESS.deref()) + .unwrap(); if let Some(contract) = contract { builder = builder.set_contract(contract); @@ -615,131 +618,69 @@ pub mod test { builder.build(&client).await } - #[async_std::test] - async fn build_txn_contract_name_does_not_set() { - let err = setup_transaction_builder( - None, - CONTRACT_METHOD_EXAMPLE, - Some(TransactionType::Read), - None, - ) - .await - .unwrap_err(); - - assert!(matches!(err, VdrError::ContractInvalidName { .. })); - } - - #[async_std::test] - async fn build_txn_contract_method_does_not_set() { - let err = setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - None, - Some(TransactionType::Read), - None, - ) - .await - .unwrap_err(); - - assert!(matches!(err, VdrError::ContractInvalidName { .. })); - } - - #[async_std::test] - async fn build_txn_contract_method_does_not_exist() { - let err = setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - INVALID_METHOD, - Some(TransactionType::Read), - None, - ) - .await - .unwrap_err(); - - assert!(matches!(err, VdrError::ContractInvalidName { .. })); - } - - #[async_std::test] - async fn build_txn_write_sender_does_not_set() { - let err = setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - CONTRACT_METHOD_EXAMPLE, - Some(TransactionType::Write), - None, - ) - .await - .unwrap_err(); - - assert!(matches!(err, VdrError::ClientInvalidTransaction { .. })); - } - - #[async_std::test] - #[ignore] - async fn build_txn_invalid_from_address() { - let err = setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - CONTRACT_METHOD_EXAMPLE, - Some(TransactionType::Write), - INVALID_ACC_ADDRESS, - ) - .await - .unwrap_err(); - - assert!(matches!(err, VdrError::ClientInvalidTransaction { .. })); - } - - #[async_std::test] - async fn build_txn_valid_transactions_with_0x_prefix() { - setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - CONTRACT_METHOD_EXAMPLE, - Some(TransactionType::Write), - Some(&Address::default().to_string()), - ) - .await - .unwrap(); - } - - #[async_std::test] - async fn build_txn_valid_transactions_without_0x_prefix() { - let address_without_prefix = VALIDATOR_ADDRESS.trim_start_matches("0x"); - setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - CONTRACT_METHOD_EXAMPLE, - Some(TransactionType::Write), - Some(address_without_prefix), - ) - .await - .unwrap(); - } - - #[async_std::test] - async fn build_txn_type_does_not_set() { - let txn = setup_transaction_builder( - CONTRACT_NAME_EXAMPLE, - CONTRACT_METHOD_EXAMPLE, - None, - None, - ) - .await - .unwrap(); - - assert_eq!(TransactionType::Read, txn.type_); + #[rstest] + #[case::contract_name_does_not_set( + None, + CONTRACT_METHOD_EXAMPLE, + Some(TransactionType::Read), + None, + VdrError::ContractInvalidName("".to_string()) + )] + #[case::contract_method_does_not_set( + CONTRACT_NAME_EXAMPLE, + None, + Some(TransactionType::Read), + None, + VdrError::ContractInvalidName("".to_string()) + )] + #[case::contract_method_does_not_exist( + CONTRACT_NAME_EXAMPLE, + INVALID_METHOD, + Some(TransactionType::Read), + None, + VdrError::ContractInvalidName("".to_string()) + )] + #[case::write_sender_does_not_set( + CONTRACT_NAME_EXAMPLE, + CONTRACT_METHOD_EXAMPLE, + Some(TransactionType::Write), + None, + VdrError::ClientInvalidTransaction("".to_string()) + )] + #[case::invalid_from_address( + CONTRACT_NAME_EXAMPLE, + CONTRACT_METHOD_EXAMPLE, + Some(TransactionType::Write), + INVALID_ACC_ADDRESS, + VdrError::ClientInvalidTransaction("".to_string()) + )] + async fn transaction_builder_tests( + #[case] contract: Option<&str>, + #[case] method: Option<&str>, + #[case] txn_type: Option, + #[case] from: Option<&str>, + #[case] expected_error: VdrError, + ) { + let result = setup_transaction_builder(contract, method, txn_type.clone(), from).await; + + match result { + Ok(ref txn) => assert_eq!(result.unwrap().type_, txn_type.unwrap()), + Err(ref err) => assert!(matches_error_type(result.unwrap_err(), expected_error)), + } } } #[cfg(test)] pub mod txn_parser_test { use super::*; - use futures::future::Lazy; - use std::{ops::Deref, sync::Arc}; + use crate::contracts::network::ValidatorAddresses; + use once_cell::sync::Lazy; + use rstest::rstest; + use std::{ops::Deref}; - const CONTRACT_NAME_EXAMPLE: Option<&str> = Some(test::CONTRACT_NAME_EXAMPLE); - const CONTRACT_METHOD_EXAMPLE: Option<&str> = Some(test::CONTRACT_METHOD_EXAMPLE); - const INVALID_METHOD: Option<&str> = Some("123"); - const INVALID_CONTRACT: Option<&str> = Some("123"); + const EMPTY_RESPONSE: Lazy> = Lazy::new(|| Vec::new()); - async fn test_transaction_parser_setup< - T: TryFrom + Debug, - >( + fn test_transaction_parser_setup + Debug>( contract: Option<&str>, method: Option<&str>, response: &[u8], @@ -759,72 +700,51 @@ pub mod test { parser.parse::(&client, response) } - #[async_std::test] - async fn parse_txn_empty_response_bytes() { - let error = test_transaction_parser_setup::( - CONTRACT_NAME_EXAMPLE, - CONTRACT_METHOD_EXAMPLE, - &[], - ) - .await - .unwrap_err(); - - assert!(matches!( - error, - VdrError::ContractInvalidResponseData { .. } - )); - } - - #[async_std::test] - async fn parse_txn_contract_not_set() { - let error = test_transaction_parser_setup::( - None, - CONTRACT_METHOD_EXAMPLE, - VALIDATOR_LIST_BYTES.as_slice(), - ) - .await - .unwrap_err(); - - assert!(matches!(error, VdrError::ContractInvalidName { .. })); - } - - #[async_std::test] - async fn parse_txn_contract_does_not_exist() { - let error = test_transaction_parser_setup::( - INVALID_CONTRACT, - CONTRACT_METHOD_EXAMPLE, - VALIDATOR_LIST_BYTES.as_slice(), - ) - .await - .unwrap_err(); - - assert!(matches!(error, VdrError::ContractInvalidName { .. })); - } - - #[async_std::test] - async fn parse_txn_contract_method_not_set() { - let error = test_transaction_parser_setup::( - CONTRACT_NAME_EXAMPLE, - None, - VALIDATOR_LIST_BYTES.as_slice(), - ) - .await - .unwrap_err(); - - assert!(matches!(error, VdrError::ContractInvalidName { .. })); - } + #[rstest] + #[case::empty_response_bytes( + CONTRACT_NAME_EXAMPLE, + CONTRACT_METHOD_EXAMPLE, + EMPTY_RESPONSE, + VdrError::ContractInvalidResponseData("".to_string()) + )] + #[case::contract_not_set( + None, + CONTRACT_METHOD_EXAMPLE, + VALIDATOR_LIST_BYTES, + VdrError::ContractInvalidName("".to_string()) + )] + #[case::contract_does_not_exist( + INVALID_CONTRACT, + CONTRACT_METHOD_EXAMPLE, + VALIDATOR_LIST_BYTES, + VdrError::ContractInvalidName("".to_string()) + )] + #[case::contract_method_not_set( + CONTRACT_NAME_EXAMPLE, + None, + VALIDATOR_LIST_BYTES, + VdrError::ContractInvalidName("".to_string()) + )] + #[case::contract_method_does_not_exist( + CONTRACT_NAME_EXAMPLE, + INVALID_METHOD, + VALIDATOR_LIST_BYTES, + VdrError::ContractInvalidName("".to_string()) + )] + async fn transaction_parser_tests( + #[case] contract: Option<&str>, + #[case] method: Option<&str>, + #[case] response: Lazy, fn() -> Vec>, + #[case] expected_error: VdrError, + ) { + let client = mock_client(); + let parser_result = test_transaction_parser_setup::( + contract, + method, + response.as_slice(), + ); - #[async_std::test] - async fn parse_txn_contract_method_does_not_exist() { - let error = test_transaction_parser_setup::( - CONTRACT_NAME_EXAMPLE, - INVALID_METHOD, - VALIDATOR_LIST_BYTES.as_slice(), - ) - .await - .unwrap_err(); - - assert!(matches!(error, VdrError::ContractInvalidName { .. })); + assert!(matches!(parser_result.unwrap_err(), expected_error)); } } }