From ba969cca4f51c240a7bdfe8a89c125cf54e23066 Mon Sep 17 00:00:00 2001 From: loloicci Date: Mon, 23 May 2022 12:25:09 +0900 Subject: [PATCH 1/5] fix: fix query-queue with clippy --- contracts/query-queue/src/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/query-queue/src/contract.rs b/contracts/query-queue/src/contract.rs index 3f50a8e3d..f92855416 100644 --- a/contracts/query-queue/src/contract.rs +++ b/contracts/query-queue/src/contract.rs @@ -150,7 +150,7 @@ mod tests { let res = instantiate( deps.as_mut(), mock_env(), - info.clone(), + info, InstantiateMsg { queue_address: QUEUE_ADDRESS.to_string(), }, From b480df520be01a1a07c70366e444fa2dc6892221 Mon Sep 17 00:00:00 2001 From: loloicci Date: Mon, 23 May 2022 12:26:06 +0900 Subject: [PATCH 2/5] feat: add checks for query-queue to workflow --- .github/workflows/tests.yml | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5080fdc80..95453b111 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -462,6 +462,52 @@ jobs: exit 1 fi + contract_query_queue: + name: contract_query_queue + runs-on: ubuntu-latest + env: + working-directory: ./contracts/query-queue + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.57.0 + target: wasm32-unknown-unknown + profile: minimal + override: true + - name: Cache cargo + uses: actions/cache@v2 + with: + path: ~/.cargo + key: cargocache-v2-contract_query_queue-rust:1.57.0-${{ hashFiles('Cargo.lock') }} + - name: Version information + run: rustc --version; cargo --version; rustup --version; rustup target list --installed + - name: Add wasm32 target + run: rustup target add wasm32-unknown-unknown && rustup target list --installed + - name: Build wasm binary + working-directory: ${{env.working-directory}} + run: cargo wasm --locked + - name: Unit tests + working-directory: ${{env.working-directory}} + run: cargo unit-test --locked + - name: Integration tests (singlepass backend) + working-directory: ${{env.working-directory}} + run: cargo integration-test --locked --no-default-features + - name: Build and run schema generator + working-directory: ${{env.working-directory}} + run: cargo schema --locked + - name: Ensure schemas are up-to-date + working-directory: ${{env.working-directory}} + run: | + CHANGES_IN_REPO=$(git status --porcelain) + if [[ -n "$CHANGES_IN_REPO" ]]; then + echo "Repository is dirty. Showing 'git status' and 'git --no-pager diff' for debugging now:" + git status && git --no-pager diff + exit 1 + fi + contract_reflect: name: contract_reflect runs-on: ubuntu-latest @@ -595,6 +641,9 @@ jobs: - name: Check formatting of contract queue working-directory: ${{env.root-directory}}/queue run: cargo fmt -- --check + - name: Check formatting of contract query-queue + working-directory: ${{env.root-directory}}/query-queue + run: cargo fmt -- --check - name: Check formatting of contract staking working-directory: ${{env.root-directory}}/staking run: cargo fmt -- --check @@ -687,6 +736,12 @@ jobs: mkdir -p target/wasm32-unknown-unknown/release touch target/wasm32-unknown-unknown/release/queue.wasm cargo clippy --tests -- -D warnings + - name: Clippy linting on query-queue + working-directory: ${{env.contracts}}/query-queue + run: | + mkdir -p target/wasm32-unknown-unknown/release + touch target/wasm32-unknown-unknown/release/query_queue.wasm + cargo clippy --tests -- -D warnings - name: Clippy linting on reflect working-directory: ${{env.contracts}}/reflect run: | From b7aa30dc31d3ff0da7883441e9f6585fe8742e03 Mon Sep 17 00:00:00 2001 From: loloicci Date: Tue, 24 May 2022 19:50:03 +0900 Subject: [PATCH 3/5] feat: add a simple integration test for query-queue --- contracts/query-queue/tests/integration.rs | 101 +++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 contracts/query-queue/tests/integration.rs diff --git a/contracts/query-queue/tests/integration.rs b/contracts/query-queue/tests/integration.rs new file mode 100644 index 000000000..4753f79b7 --- /dev/null +++ b/contracts/query-queue/tests/integration.rs @@ -0,0 +1,101 @@ +//! This integration test tries to run and call the generated wasm. +//! It depends on a Wasm build being available, which you can create with `cargo wasm`. +//! Then running `cargo integration-test` will validate we can properly call into that generated Wasm. +//! +//! You can easily convert unit tests to integration tests as follows: +//! 1. Copy them over verbatim +//! 2. Then change +//! let mut deps = mock_dependencies(20, &[]); +//! to +//! let mut deps = mock_instance(WASM, &[]); +//! 3. If you access raw storage, where ever you see something like: +//! deps.storage.get(CONFIG_KEY).expect("no data stored"); +//! replace it with: +//! deps.with_storage(|store| { +//! let data = store.get(CONFIG_KEY).expect("no data stored"); +//! //... +//! }); +//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...) + +use cosmwasm_std::{from_binary, from_slice, MessageInfo, Response, SystemError, SystemResult, ContractResult, WasmQuery, to_binary}; +use cosmwasm_vm::{ + testing::{ + execute, instantiate, mock_env, mock_info, query, + MockApi, MockQuerier, MockStorage, + }, + Backend, Instance, InstanceOptions +}; + +use query_queue::contract::{ + SumResponse, +}; +use query_queue::msg::{InstantiateMsg, QueryMsg, ExecuteMsg}; + +static WASM: &[u8] = include_bytes!("../target/wasm32-unknown-unknown/release/query_queue.wasm"); + +fn create_contract() -> (Instance, MessageInfo) { + let gas_limit = 500_000_000; // enough for many executions within one instance + let instance_options = InstanceOptions { + gas_limit, + print_debug: false, + }; + let mut deps = Backend{ + api: MockApi::default(), + storage: MockStorage::new(), + querier: MockQuerier::new(&[]), + }; + let info = mock_info("creator", &[]); + deps.querier.update_wasm(|query| match query { + WasmQuery::Smart { + contract_addr, + msg, + } => { + if contract_addr != "queue_address" { + return SystemResult::Err(SystemError::NoSuchContract {addr: contract_addr.to_string() }) + }; + let q_msg: QueryMsg = from_slice(msg).unwrap(); + match q_msg { + QueryMsg::Sum {} => SystemResult::Ok(ContractResult::Ok( + to_binary(&SumResponse { sum: 42 }).unwrap(), + )), + _ => SystemResult::Err(SystemError::Unknown {}), + } + } + _ => SystemResult::Err(SystemError::Unknown {}), + }); + let mut instance = Instance::from_code(WASM, deps, instance_options, None).unwrap(); + let res: Response = instantiate( + &mut instance, + mock_env(), + info.clone(), + InstantiateMsg { + queue_address: "queue_address".to_string(), + }, + ) + .unwrap(); + assert_eq!(0, res.messages.len()); + (instance, info) +} + +#[test] +fn instantiate_and_query() { + let (mut deps, _) = create_contract(); + let data = query(&mut deps, mock_env(), QueryMsg::Sum {}).unwrap(); + let res: SumResponse = from_binary(&data).unwrap(); + assert_eq!(res.sum, 42); +} + +#[test] +fn instantiate_and_change_queue_address() { + let (mut deps, info) = create_contract(); + let _: Response = execute( + &mut deps, + mock_env(), + info, + ExecuteMsg::ChangeAddress{ queue_address: "non_existing_address".to_string() } + ) + .unwrap(); + let res = query(&mut deps, mock_env(), QueryMsg::Sum {}); + let expected = ContractResult::Err("Generic error: Querier system error: No such contract: non_existing_address".to_string()); + assert_eq!(res, expected); +} From c6ebad4c524c738754ff69817bfa5c3c7a93c839 Mon Sep 17 00:00:00 2001 From: loloicci Date: Tue, 24 May 2022 21:39:25 +0900 Subject: [PATCH 4/5] feat: add an integration test using contract query --- contracts/query-queue/src/contract.rs | 10 +- contracts/query-queue/tests/integration.rs | 160 ++++++++++++++++++--- 2 files changed, 144 insertions(+), 26 deletions(-) diff --git a/contracts/query-queue/src/contract.rs b/contracts/query-queue/src/contract.rs index f92855416..8cf09791c 100644 --- a/contracts/query-queue/src/contract.rs +++ b/contracts/query-queue/src/contract.rs @@ -102,7 +102,9 @@ fn query_raw(deps: Deps, key: u8) -> StdResult { .querier .query_wasm_raw(address, (vec![key]).as_slice())?; let response_string = std::str::from_utf8(response.unwrap_or_default().as_slice())?.to_string(); - Ok(RawResponse { response: response_string }) + Ok(RawResponse { + response: response_string, + }) } fn query_count(deps: Deps, msg: QueryMsg) -> StdResult { @@ -141,7 +143,7 @@ mod tests { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] struct RawQueryResponse { - value: u32 + value: u32, } fn create_contract() -> OwnedDeps { @@ -190,7 +192,9 @@ mod tests { WasmQuery::Raw { contract_addr: _, key: _, - } => SystemResult::Ok(ContractResult::Ok(to_binary(&RawQueryResponse{value: 42}).unwrap())), + } => SystemResult::Ok(ContractResult::Ok( + to_binary(&RawQueryResponse { value: 42 }).unwrap(), + )), _ => SystemResult::Err(SystemError::Unknown {}), }); deps diff --git a/contracts/query-queue/tests/integration.rs b/contracts/query-queue/tests/integration.rs index 4753f79b7..b44ceb3d8 100644 --- a/contracts/query-queue/tests/integration.rs +++ b/contracts/query-queue/tests/integration.rs @@ -17,21 +17,27 @@ //! }); //! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...) -use cosmwasm_std::{from_binary, from_slice, MessageInfo, Response, SystemError, SystemResult, ContractResult, WasmQuery, to_binary}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::{ + from_binary, from_slice, to_binary, Binary, ContractResult, MessageInfo, Response, SystemError, + SystemResult, WasmQuery, +}; use cosmwasm_vm::{ testing::{ - execute, instantiate, mock_env, mock_info, query, - MockApi, MockQuerier, MockStorage, + execute, instantiate, mock_env, mock_info, mock_instance_with_gas_limit, query, MockApi, + MockQuerier, MockStorage, }, - Backend, Instance, InstanceOptions + Backend, Instance, InstanceOptions, Storage, VmResult, }; -use query_queue::contract::{ - SumResponse, -}; -use query_queue::msg::{InstantiateMsg, QueryMsg, ExecuteMsg}; +use query_queue::contract::{RawResponse, SumResponse}; +use query_queue::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; static WASM: &[u8] = include_bytes!("../target/wasm32-unknown-unknown/release/query_queue.wasm"); +static QUEUE_WASM: &[u8] = + include_bytes!("../../queue/target/wasm32-unknown-unknown/release/queue.wasm"); fn create_contract() -> (Instance, MessageInfo) { let gas_limit = 500_000_000; // enough for many executions within one instance @@ -39,19 +45,18 @@ fn create_contract() -> (Instance, MessageInf gas_limit, print_debug: false, }; - let mut deps = Backend{ + let mut deps = Backend { api: MockApi::default(), storage: MockStorage::new(), querier: MockQuerier::new(&[]), }; let info = mock_info("creator", &[]); - deps.querier.update_wasm(|query| match query { - WasmQuery::Smart { - contract_addr, - msg, - } => { + deps.querier.update_wasm(|query_msg| match query_msg { + WasmQuery::Smart { contract_addr, msg } => { if contract_addr != "queue_address" { - return SystemResult::Err(SystemError::NoSuchContract {addr: contract_addr.to_string() }) + return SystemResult::Err(SystemError::NoSuchContract { + addr: contract_addr.to_string(), + }); }; let q_msg: QueryMsg = from_slice(msg).unwrap(); match q_msg { @@ -72,30 +77,139 @@ fn create_contract() -> (Instance, MessageInf queue_address: "queue_address".to_string(), }, ) - .unwrap(); + .unwrap(); assert_eq!(0, res.messages.len()); (instance, info) } #[test] fn instantiate_and_query() { - let (mut deps, _) = create_contract(); - let data = query(&mut deps, mock_env(), QueryMsg::Sum {}).unwrap(); + let (mut instance, _) = create_contract(); + let data = query(&mut instance, mock_env(), QueryMsg::Sum {}).unwrap(); let res: SumResponse = from_binary(&data).unwrap(); assert_eq!(res.sum, 42); } #[test] fn instantiate_and_change_queue_address() { - let (mut deps, info) = create_contract(); + let (mut instance, info) = create_contract(); let _: Response = execute( - &mut deps, + &mut instance, mock_env(), info, - ExecuteMsg::ChangeAddress{ queue_address: "non_existing_address".to_string() } + ExecuteMsg::ChangeAddress { + queue_address: "non_existing_address".to_string(), + }, ) .unwrap(); - let res = query(&mut deps, mock_env(), QueryMsg::Sum {}); - let expected = ContractResult::Err("Generic error: Querier system error: No such contract: non_existing_address".to_string()); + let res = query(&mut instance, mock_env(), QueryMsg::Sum {}); + let expected = ContractResult::Err( + "Generic error: Querier system error: No such contract: non_existing_address".to_string(), + ); assert_eq!(res, expected); } + +fn create_queue_contract_and_push_42() -> (Instance, MessageInfo) +{ + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] + struct InstantiateMsg {} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] + #[serde(rename_all = "snake_case")] + enum ExecuteMsg { + Enqueue { value: i32 }, + } + + let gas_limit = 500_000_000; // enough for many executions within one instance + let mut deps = mock_instance_with_gas_limit(QUEUE_WASM, gas_limit); + let creator = String::from("creator"); + let info = mock_info(&creator, &[]); + let res: Response = + instantiate(&mut deps, mock_env(), info.clone(), InstantiateMsg {}).unwrap(); + assert_eq!(0, res.messages.len()); + let res: Response = execute( + &mut deps, + mock_env(), + info.clone(), + ExecuteMsg::Enqueue { value: 42 }, + ) + .unwrap(); + assert_eq!(0, res.messages.len()); + (deps, info) +} + +fn create_integrated_query_contract() -> (Instance, MessageInfo) +{ + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] + #[serde(rename_all = "snake_case")] + pub enum QueryMsg { + Count {}, + Sum {}, + Reducer {}, + List {}, + } + + let gas_limit = 500_000_000; // enough for many executions within one instance + let instance_options = InstanceOptions { + gas_limit, + print_debug: false, + }; + let mut deps = Backend { + api: MockApi::default(), + storage: MockStorage::new(), + querier: MockQuerier::new(&[]), + }; + let info = mock_info("creator", &[]); + deps.querier.update_wasm(|query_msg| { + let (mut queue_instance, _) = create_queue_contract_and_push_42(); + match query_msg { + WasmQuery::Smart { contract_addr, msg } => { + if contract_addr != "queue_address" { + return SystemResult::Err(SystemError::NoSuchContract { + addr: contract_addr.to_string(), + }); + }; + let q_msg: QueryMsg = from_slice(msg).unwrap(); + let res = query(&mut queue_instance, mock_env(), q_msg); + SystemResult::Ok(res) + } + WasmQuery::Raw { contract_addr, key } => { + if contract_addr != "queue_address" { + return SystemResult::Err(SystemError::NoSuchContract { + addr: contract_addr.to_string(), + }); + }; + let data = queue_instance + .with_storage(|storage| VmResult::Ok(storage.get(key).0.unwrap())) + .unwrap(); + if data.is_none() { + return SystemResult::Err(SystemError::Unknown {}); + }; + SystemResult::Ok(ContractResult::Ok(Binary::from(data.unwrap()))) + } + _ => SystemResult::Err(SystemError::Unknown {}), + } + }); + let mut instance = Instance::from_code(WASM, deps, instance_options, None).unwrap(); + let res: Response = instantiate( + &mut instance, + mock_env(), + info.clone(), + InstantiateMsg { + queue_address: "queue_address".to_string(), + }, + ) + .unwrap(); + assert_eq!(0, res.messages.len()); + (instance, info) +} + +#[test] +fn integration_query_contract_queue() { + let (mut query_instance, _) = create_integrated_query_contract(); + let data = query(&mut query_instance, mock_env(), QueryMsg::Sum {}).unwrap(); + let res: SumResponse = from_binary(&data).unwrap(); + assert_eq!(res.sum, 42); + let data = query(&mut query_instance, mock_env(), QueryMsg::Raw { key: 0 }).unwrap(); + let res: RawResponse = from_binary(&data).unwrap(); + assert_eq!(res.response, "{\"value\":42}".to_string()); +} From 33e87f3c213187088e2307e2800328bdd6e5455a Mon Sep 17 00:00:00 2001 From: loloicci Date: Wed, 25 May 2022 05:58:19 +0900 Subject: [PATCH 5/5] fix: fix workflow to build queue before integration test of query-queue --- .github/workflows/tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 95453b111..b95f8a500 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -467,6 +467,7 @@ jobs: runs-on: ubuntu-latest env: working-directory: ./contracts/query-queue + queue-directory: ./contracts/queue steps: - name: Checkout uses: actions/checkout@v2 @@ -492,6 +493,9 @@ jobs: - name: Unit tests working-directory: ${{env.working-directory}} run: cargo unit-test --locked + - name: Build queue wasm binary for integration tests + working-directory: ${{env.queue-directory}} + run: cargo wasm --locked - name: Integration tests (singlepass backend) working-directory: ${{env.working-directory}} run: cargo integration-test --locked --no-default-features