Skip to content

Commit

Permalink
[refactor] hyperledger#4423: Add a test using a query filter in a sma…
Browse files Browse the repository at this point in the history
…rt contract

Signed-off-by: Nikita Strygin <dcnick3@users.noreply.github.com>
  • Loading branch information
DCNick3 committed May 2, 2024
1 parent 55a305e commit e900abc
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 46 deletions.
46 changes: 2 additions & 44 deletions client/tests/integration/queries/mod.rs
@@ -1,11 +1,8 @@
use std::str::FromStr as _;

use eyre::Result;
use iroha_client::{
client::{self, ClientQueryError},
data_model::{
prelude::*,
query::{cursor::ForwardCursor, error::QueryExecutionFail, MAX_FETCH_SIZE},
query::{error::QueryExecutionFail, MAX_FETCH_SIZE},
},
};
use test_network::*;
Expand All @@ -14,6 +11,7 @@ mod account;
mod asset;
mod query_errors;
mod role;
mod smart_contract;

#[test]
fn too_big_fetch_size_is_not_allowed() {
Expand All @@ -33,43 +31,3 @@ fn too_big_fetch_size_is_not_allowed() {
))
));
}

#[test]
fn live_query_is_dropped_after_smart_contract_end() -> Result<()> {
let (_rt, _peer, client) = <PeerBuilder>::new().with_port(11_140).start_with_runtime();
wait_for_genesis_committed(&[client.clone()], 0);

let wasm = iroha_wasm_builder::Builder::new(
"tests/integration/smartcontracts/query_assets_and_save_cursor",
)
.show_output()
.build()?
.optimize()?
.into_bytes()?;

let transaction = client.build_transaction(
WasmSmartContract::from_compiled(wasm),
UnlimitedMetadata::default(),
);
client.submit_transaction_blocking(&transaction)?;

let metadata_value = client.request(FindAccountKeyValueByIdAndKey::new(
client.account_id.clone(),
Name::from_str("cursor").unwrap(),
))?;
let cursor: String = metadata_value.try_into()?;
let asset_cursor = serde_json::from_str::<ForwardCursor>(&cursor)?;

let err = client
.request_with_cursor::<Vec<Asset>>(asset_cursor)
.expect_err("Request with cursor from smart contract should fail");

assert!(matches!(
err,
ClientQueryError::Validation(ValidationFail::QueryFailed(
QueryExecutionFail::UnknownCursor
))
));

Ok(())
}
73 changes: 73 additions & 0 deletions client/tests/integration/queries/smart_contract.rs
@@ -0,0 +1,73 @@
use std::str::FromStr as _;

use eyre::Result;
use iroha_client::{
client::ClientQueryError,
data_model::{
prelude::*,
query::{cursor::ForwardCursor, error::QueryExecutionFail},
},
};
use test_network::*;

#[test]
fn live_query_is_dropped_after_smart_contract_end() -> Result<()> {
let (_rt, _peer, client) = <PeerBuilder>::new().with_port(11_140).start_with_runtime();
wait_for_genesis_committed(&[client.clone()], 0);

let wasm = iroha_wasm_builder::Builder::new(
"tests/integration/smartcontracts/query_assets_and_save_cursor",
)
.show_output()
.build()?
.optimize()?
.into_bytes()?;

let transaction = client.build_transaction(
WasmSmartContract::from_compiled(wasm),
UnlimitedMetadata::default(),
);
client.submit_transaction_blocking(&transaction)?;

let metadata_value = client.request(FindAccountKeyValueByIdAndKey::new(
client.account_id.clone(),
Name::from_str("cursor").unwrap(),
))?;
let cursor: String = metadata_value.try_into()?;
let asset_cursor = serde_json::from_str::<ForwardCursor>(&cursor)?;

let err = client
.request_with_cursor::<Vec<Asset>>(asset_cursor)
.expect_err("Request with cursor from smart contract should fail");

assert!(matches!(
err,
ClientQueryError::Validation(ValidationFail::QueryFailed(
QueryExecutionFail::UnknownCursor
))
));

Ok(())
}

#[test]
fn smart_contract_can_filter_queries() -> Result<()> {
let (_rt, _peer, client) = <PeerBuilder>::new().with_port(11_260).start_with_runtime();
wait_for_genesis_committed(&[client.clone()], 0);

let wasm = iroha_wasm_builder::Builder::new(
"tests/integration/smartcontracts/smart_contract_can_filter_queries",
)
.show_output()
.build()?
.optimize()?
.into_bytes()?;

let transaction = client.build_transaction(
WasmSmartContract::from_compiled(wasm),
UnlimitedMetadata::default(),
);
client.submit_transaction_blocking(&transaction)?;

Ok(())
}
5 changes: 3 additions & 2 deletions client/tests/integration/smartcontracts/Cargo.toml
Expand Up @@ -16,6 +16,7 @@ members = [
"executor_remove_token",
"executor_with_migration_fail",
"query_assets_and_save_cursor",
"smart_contract_can_filter_queries",
]

[profile.dev]
Expand All @@ -29,8 +30,8 @@ opt-level = "z" # Optimize for size vs speed with "s"/"z"(removes vectorizat
codegen-units = 1 # Further reduces binary size but increases compilation time

[workspace.dependencies]
iroha_smart_contract = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract", features = ["debug"]}
iroha_trigger = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract/trigger", features = ["debug"]}
iroha_smart_contract = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract", features = ["debug"] }
iroha_trigger = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract/trigger", features = ["debug"] }
iroha_executor = { version = "=2.0.0-pre-rc.21", path = "../../../../smart_contract/executor" }
iroha_schema = { version = "=2.0.0-pre-rc.21", path = "../../../../schema" }

Expand Down
@@ -0,0 +1,21 @@
[package]
name = "smart_contract_can_filter_queries"

edition.workspace = true
version.workspace = true
authors.workspace = true

license.workspace = true

[lib]
crate-type = ['cdylib']

[dependencies]
iroha_smart_contract.workspace = true

panic-halt.workspace = true
lol_alloc.workspace = true
getrandom.workspace = true
parity-scale-codec.workspace = true
nonzero_ext.workspace = true
serde_json = { workspace = true, default-features = false }
@@ -0,0 +1,50 @@
//! Smart contract which executes [`FindAllAssets`] and saves cursor to the owner's metadata.

#![no_std]

#[cfg(not(test))]
extern crate panic_halt;

extern crate alloc;

use alloc::{collections::BTreeSet, string::ToString, vec::Vec};

use iroha_smart_contract::{
data_model::query::predicate::{string::StringPredicate, value::QueryOutputPredicate},
prelude::*,
QueryOutputCursor,
};
use lol_alloc::{FreeListAllocator, LockedAllocator};

#[global_allocator]
static ALLOC: LockedAllocator<FreeListAllocator> = LockedAllocator::new(FreeListAllocator::new());

getrandom::register_custom_getrandom!(iroha_smart_contract::stub_getrandom);

/// Query all accounts, but filter them to only be in the wonderland domain
#[iroha_smart_contract::main]
fn main(_owner: AccountId) {
// our genesis contains alice & bob accounts in the wonderland domain and a carpenter account in the garden_of_live_flowers domain
// with this filter we expect to only get alice and bob
let cursor: QueryOutputCursor<Vec<Account>> = FindAllAccounts
.filter(QueryOutputPredicate::Identifiable(
StringPredicate::EndsWith("@wonderland".to_string()),
))
.execute()
.dbg_unwrap();

let mut account_ids = BTreeSet::new();

for account in cursor {
let account = account.dbg_unwrap();
account_ids.insert(account.id().to_string());
}

assert_eq!(
account_ids,
["alice@wonderland", "bob@wonderland"]
.into_iter()
.map(ToString::to_string)
.collect()
);
}

0 comments on commit e900abc

Please sign in to comment.