Skip to content
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

feat(test): unit test external call mock #423

Open
wants to merge 68 commits into
base: main
Choose a base branch
from

Conversation

qalisander
Copy link
Member

This pr contains corresponding improvements for motsu and two new test cases on_erc721_received and ping_pong_works.
Other test cases are commented. And should be refactored once the final design will be approved.

Resolves OpenZeppelin/stylus-test-helpers#8 OpenZeppelin/stylus-test-helpers#12

PR Checklist

  • Tests
  • Documentation
  • Changelog

Copy link

netlify bot commented Nov 28, 2024

Deploy Preview for contracts-stylus ready!

Name Link
🔨 Latest commit 297b574
🔍 Latest deploy log https://app.netlify.com/sites/contracts-stylus/deploys/6769b913bec71a00084f6e63
😎 Deploy Preview https://deploy-preview-423--contracts-stylus.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Comment on lines 6 to 17
#[cfg(test)]
pub fn msg_sender() -> Address {
motsu::prelude::Context::current()
.get_msg_sender()
.expect("msg_sender should be set")
}

/// Returns the address of the message sender.
#[cfg(not(test))]
pub fn msg_sender() -> Address {
msg::sender()
}
Copy link
Member Author

@qalisander qalisander Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an example how msg_sender mock can be declared. This design is not perfect since motsu users should implement this mock for their own library manually or through macro.
Calling stylus sdk api msg::sender() won't work inside a test without mock due to this limitation.

Comment on lines 2547 to 2562
#[motsu::test]
fn on_erc721_received(
erc721: Contract<Erc721>,
receiver: Contract<Erc721ReceiverMock>,
) {
let alice = Account::random();
let token_id = random_token_id();
erc721
.sender(alice)
._safe_mint(receiver.address(), token_id, vec![0, 1, 2, 3].into())
.unwrap();

let received_token_id = receiver.sender(alice).received_token_id();

assert_eq!(received_token_id, token_id);
}
Copy link
Member Author

@qalisander qalisander Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall the test case for Erc721Receiver can look like this

@qalisander qalisander marked this pull request as ready for review November 28, 2024 05:59
…eta.1

# Conflicts:
#	contracts/src/token/erc20/extensions/permit.rs
#	contracts/src/utils/math/storage.rs
#	lib/e2e/src/lib.rs
@bidzyyys
Copy link
Collaborator

This change should be common with #441

Copy link
Collaborator

@0xNeshi 0xNeshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo the API is very good, especially as it conforms to existing conventions for writing code that mocks senders, values etc.

I think the builder pattern is the right choice here, as we might need to extend the functionality at a later point (e.g. to add .with_block_timestamp, but there may be others, who knows).

Good job! 🔥

Once clippy warnings are addressed I'll give this a final review, as the PR is too cluttered with warnings atm

…eta.1

# Conflicts:
#	contracts/src/access/control.rs
#	contracts/src/finance/vesting_wallet.rs
#	contracts/src/token/erc1155/mod.rs
#	contracts/src/token/erc1155/receiver.rs
#	contracts/src/token/erc20/extensions/capped.rs
#	contracts/src/token/erc20/extensions/metadata.rs
#	contracts/src/token/erc721/extensions/enumerable.rs
#	contracts/src/token/erc721/mod.rs
#	contracts/src/utils/metadata.rs
#	contracts/src/utils/pausable.rs
…ntract-deployment-v0.7.0-beta

# Conflicts:
#	contracts/src/token/erc1155/extensions/uri_storage.rs
#	contracts/src/token/erc721/mod.rs
#	lib/motsu-proc/src/test.rs
@qalisander qalisander force-pushed the unit-tests/multiple-contract-deployment branch from 35b1c5f to f27aed9 Compare December 13, 2024 17:01
…ontract-deployment

# Conflicts:
#	Cargo.lock
#	contracts/src/finance/vesting_wallet.rs
#	contracts/src/token/erc1155/mod.rs
#	lib/motsu-proc/src/test.rs
#	lib/motsu/Cargo.toml
#	lib/motsu/src/context.rs
#	lib/motsu/src/lib.rs
#	lib/motsu/src/prelude.rs
#	lib/motsu/src/shims.rs
keccak-const.workspace = true
openzeppelin-stylus-proc.workspace = true

[dev-dependencies]
alloy-primitives = { workspace = true, features = ["arbitrary"] }
motsu.workspace = true
rand.workspace = true
stylus-sdk.workspace = true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stylus-sdk is listed both in dependencies and in dev-dependencies

Copy link
Member Author

@qalisander qalisander Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since OL agreed to have a default feature for ENABLING hostio caching, now we should write stylus-sdk = { version = "0.7.0", default-features = false } on the workspace level, and stylus-sdk = { workspace = true, default-features = true } for [dependencies]. Because we need this caching for wasm compiled contracts, but can not run motsu tests with it.
And use it without default features for unit tests [dev-dependencies]

Copy link
Member Author

@qalisander qalisander Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would better add a feature for disabling caching (not enabling). It would be more simple

@@ -41,6 +41,8 @@
//! accounts that have been granted it. We recommend using
//! `AccessControlDefaultAdminRules` to enforce additional security measures for
//! this role.
use alloc::vec::Vec;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we adding this import?

Comment on lines -92 to +98
pub use token::IErc20;
mod token {
#![allow(missing_docs)]
#![cfg_attr(coverage_nightly, coverage(off))]
stylus_sdk::stylus_proc::sol_interface! {
/// Interface of the ERC-20 token.
interface IErc20 {
function balanceOf(address account) external view returns (uint256);
}
sol_interface! {
/// Interface of the ERC-20 token.
#[allow(missing_docs)]
interface IErc20 {
function balanceOf(address account) external view returns (uint256);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't coverage be reduced by including this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap. It will be reduced, currently the simplest way to compile it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't compile if you do:

pub use token::IErc20;
mod token {
    #![allow(missing_docs)]
    #![cfg_attr(coverage_nightly, coverage(off))]
    stylus_sdk::prelude::sol_interface! {
        /// Interface of the ERC-20 token.
        interface IErc20 {
            function balanceOf(address account) external view returns (uint256);
        }
    }
}

? 😮

Copy link
Member Author

@qalisander qalisander Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IErc20 now made private. So it will de-sugar to struct IErc20, instead of pub struct IErc20. And visibility level will be just module wise

Copy link
Member Author

@qalisander qalisander Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be try to change it again in stylus sdk.. pr

@qalisander qalisander changed the title feat(test): unit test external call mock POC feat(test): unit test external call mock Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature]: Mock another contract in #[motsu::test]
3 participants