-
Notifications
You must be signed in to change notification settings - Fork 481
test: assets precompile integration test with node backend #2709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Daanvdplas
wants to merge
14
commits into
master
Choose a base branch
from
daan/test-assets_precompile_integration_test_node
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
4248b4b
fix: fmt
Daanvdplas a1e7650
feat: test events in sandbox environment
Daanvdplas 20c3fca
last minor changes
Daanvdplas d1ac701
refactor: account handling e2e framework
Daanvdplas fc64400
test: test macro helpers
Daanvdplas f6c128b
fix: remove benchmark in sandbox
Daanvdplas d92792d
small place changes
Daanvdplas 88c9942
test: assets precompile node backend
Daanvdplas 04d2970
refactor: move code from sandbox to e2e
Daanvdplas 1f7e216
rebase master
Daanvdplas 044d5c3
Merge branch 'master' into daan/test-assets_precompile_integration_te…
Daanvdplas 48807c7
Merge branch 'master' into daan/test-assets_precompile_integration_te…
Daanvdplas 6dced7c
Merge branch 'master' into daan/test-assets_precompile_integration_te…
Daanvdplas 2e365ad
refactor: macros
Daanvdplas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
| // Copyright (C) Use Ink (UK) Ltd. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| //! Assertion helpers for ink! E2E tests. | ||
| //! | ||
| //! These macros provide convenient assertions similar to FRAME's testing macros, | ||
| //! adapted for contract call results. | ||
|
|
||
| /// Assert that a contract call succeeded without reverting. | ||
| /// | ||
| /// This macro follows FRAME's `assert_ok!` convention for consistency across | ||
| /// the Polkadot ecosystem. It verifies that a contract call completed successfully | ||
| /// and did not revert. | ||
| /// | ||
| /// # Variants | ||
| /// | ||
| /// - `assert_ok!(result)` - Assert the call didn't revert | ||
| /// - `assert_ok!(result, expected)` - Assert the call didn't revert AND the return | ||
| /// value equals `expected` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```ignore | ||
| /// // Just assert success | ||
| /// let result = client.call(&alice, &contract_call.transfer(bob, amount)) | ||
| /// .submit() | ||
| /// .await?; | ||
| /// assert_ok!(result); | ||
| /// | ||
| /// // Assert success and check return value | ||
| /// let result = client.call(&alice, &contract_call.balance_of(bob)) | ||
| /// .dry_run() | ||
| /// .await?; | ||
| /// assert_ok!(result, expected_balance); | ||
| /// ``` | ||
| #[macro_export] | ||
| macro_rules! assert_ok { | ||
| ($result:expr $(,)?) => {{ | ||
| let result = $result; | ||
| if result.dry_run.did_revert() { | ||
| panic!( | ||
| "Expected call to succeed but it reverted.\nError: {:?}", | ||
| result.extract_error() | ||
| ); | ||
| } | ||
| result | ||
| }}; | ||
| ($result:expr, $expected:expr $(,)?) => {{ | ||
| let result = $result; | ||
| if result.dry_run.did_revert() { | ||
| panic!( | ||
| "Expected call to succeed but it reverted.\nError: {:?}", | ||
| result.extract_error() | ||
| ); | ||
| } | ||
| assert_eq!( | ||
| result.return_value(), | ||
| $expected, | ||
| "Return value mismatch" | ||
| ); | ||
| result | ||
| }}; | ||
| } | ||
|
|
||
| /// Assert that a contract call reverted with a specific error. | ||
| /// | ||
| /// This macro follows FRAME's `assert_noop!` convention, which stands for | ||
| /// "assert no operation" - meaning the call should fail without changing state. | ||
| /// Since reverted contract calls don't mutate state, this verifies the call | ||
| /// reverted with the expected error message. | ||
| /// | ||
| /// # Variants | ||
| /// | ||
| /// - `assert_noop!(result, expected_error)` - Assert the call reverted with an error | ||
| /// containing `expected_error` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```ignore | ||
| /// let result = client.call(&alice, &contract_call.transfer(bob, huge_amount)) | ||
| /// .submit() | ||
| /// .await?; | ||
| /// assert_noop!(result, "BalanceLow"); | ||
| /// ``` | ||
| #[macro_export] | ||
| macro_rules! assert_noop { | ||
| ($result:expr, $expected_error:expr $(,)?) => {{ | ||
| let result = $result; | ||
| if !result.dry_run.did_revert() { | ||
| panic!( | ||
| "Expected call to revert with '{}' but it succeeded.\nReturn value: {:?}", | ||
| $expected_error, | ||
| result.return_data() | ||
| ); | ||
| } | ||
|
|
||
| let actual_error = result.extract_error(); | ||
| if actual_error != Some($expected_error.to_string()) { | ||
| panic!( | ||
| "Expected error '{}' but got {:?}", | ||
| $expected_error, | ||
| actual_error | ||
| ); | ||
| } | ||
| result | ||
| }}; | ||
| } | ||
|
|
||
| /// Assert that the last event from a contract call matches the expected event. | ||
| /// | ||
| /// This macro extracts events from the contract result and compares the last | ||
| /// emitted event with the expected event structure by comparing encoded bytes. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```ignore | ||
| /// let result = client.call(&alice, &contract_call.transfer(bob_address, amount)) | ||
| /// .submit() | ||
| /// .await?; | ||
| /// | ||
| /// assert_last_event!( | ||
| /// &result, | ||
| /// Transfer { | ||
| /// from: contract.addr, | ||
| /// to: bob_address, | ||
| /// value: amount | ||
| /// } | ||
| /// ); | ||
| /// ``` | ||
| #[macro_export] | ||
| macro_rules! assert_last_event { | ||
| ($result:expr, $expected_event:expr) => {{ $crate::assert_last_event_internal($result, $expected_event) }}; | ||
| } | ||
|
|
||
| use crate::CallResult; | ||
| use ink_env::Environment; | ||
| use scale::{ | ||
| Decode, | ||
| Encode, | ||
| }; | ||
| use subxt::{ | ||
| blocks::ExtrinsicEvents, | ||
| config::HashFor, | ||
| }; | ||
|
|
||
| /// A trait for types that can expose the last contract-emitted event for assertions. | ||
| #[allow(dead_code)] | ||
| pub trait ContractEventReader { | ||
| fn fetch_last_contract_event(self) -> Result<Vec<u8>, String>; | ||
| } | ||
|
|
||
| impl<'a, E, V, C, Abi> ContractEventReader | ||
| for &'a CallResult<E, V, ExtrinsicEvents<C>, Abi> | ||
| where | ||
| E: Environment, | ||
| C: subxt::Config, | ||
| HashFor<C>: Into<sp_core::H256>, | ||
| { | ||
| fn fetch_last_contract_event(self) -> Result<Vec<u8>, String> { | ||
| let events = self | ||
| .contract_emitted_events() | ||
| .map_err(|err| format!("failed to get contract events: {err:?}"))?; | ||
|
|
||
| let last_event = events | ||
| .last() | ||
| .ok_or_else(|| "no contract events were emitted".to_string())?; | ||
|
|
||
| Ok(last_event.event.data.clone()) | ||
| } | ||
| } | ||
|
|
||
| /// Shared implementation that decodes the last contract event and compares it against the | ||
| /// expected value. | ||
| #[allow(dead_code)] | ||
| pub fn assert_last_event_internal<R, E>(reader: R, expected_event: E) | ||
| where | ||
| R: ContractEventReader, | ||
| E: Decode + Encode + core::fmt::Debug, | ||
| { | ||
| let last_event_data = reader | ||
| .fetch_last_contract_event() | ||
| .unwrap_or_else(|err| panic!("Contract event assertion failed: {err}")); | ||
|
|
||
| let expected_bytes = expected_event.encode(); | ||
|
|
||
| if expected_bytes != last_event_data { | ||
| let decoded_event = | ||
| E::decode(&mut &last_event_data[..]).unwrap_or_else(|error| { | ||
| panic!( | ||
| "failed to decode last contract event as {}: bytes={:?}, error={:?}", | ||
| core::any::type_name::<E>(), | ||
| last_event_data, | ||
| error | ||
| ); | ||
| }); | ||
|
|
||
| panic!( | ||
| "event mismatch!\nExpected: {:?}\nActual: {:?}", | ||
| expected_event, decoded_event | ||
| ); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| use crate::sr25519::Keypair; | ||
| use sp_core::crypto::AccountId32; | ||
|
|
||
| /// Trait for types that can be converted into an `AccountId`. | ||
| pub trait IntoAccountId<TargetAccountId> { | ||
| fn into_account_id(self) -> TargetAccountId; | ||
| } | ||
|
|
||
| impl IntoAccountId<AccountId32> for AccountId32 { | ||
| fn into_account_id(self) -> AccountId32 { | ||
| self | ||
| } | ||
| } | ||
|
|
||
| impl IntoAccountId<AccountId32> for &AccountId32 { | ||
| fn into_account_id(self) -> AccountId32 { | ||
| self.clone() | ||
| } | ||
| } | ||
|
|
||
| impl<AccountId> IntoAccountId<AccountId> for &ink_primitives::AccountId | ||
| where | ||
| AccountId: From<[u8; 32]>, | ||
| { | ||
| fn into_account_id(self) -> AccountId { | ||
| AccountId::from(*AsRef::<[u8; 32]>::as_ref(self)) | ||
| } | ||
| } | ||
|
|
||
| impl<AccountId> IntoAccountId<AccountId> for &Keypair | ||
| where | ||
| AccountId: From<[u8; 32]>, | ||
| { | ||
| fn into_account_id(self) -> AccountId { | ||
| AccountId::from(self.public_key().0) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe there are
Intoimplementations that you added in #2686 which could be used here.