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

Extend ContractData in multi-test #360

Merged
merged 5 commits into from
Jul 29, 2021
Merged

Extend ContractData in multi-test #360

merged 5 commits into from
Jul 29, 2021

Conversation

hashedone
Copy link
Contributor

One thing I would like to improve later about this is to make unit test to actually using Wasm<C> interface instead of internal private functions.

There are two reasons for that:

  1. Such tests would be more stable so easier to maintain - internal private functions and layouts might change as it is their nature, but every such change requires tests update. Public API (which Wasm<C> is for WasmKeeper) should probably not change almost at all (possibly might be extended, but unless some serious breaking change is made, it should not affect existing code, including tests).

  2. Wasm<C> implementation of WasmKeeper are not just recalls to internall private functions, they actually have some orchestration logic. Testing basing on private calls, completely excludes this functonality from being tested.

@hashedone hashedone requested a review from ethanfrey July 28, 2021 14:57
@ethanfrey
Copy link
Member

I agree.
Feel free to add a function or two to Wasm public interface. It is meant to capture all entry points we want people to use

Copy link
Member

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

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

Good stuff. Some cleanup suggestions, mainly on the test code I didn't update earlier.

Please make load_contract public and expose it as part of the PR, that's the one really important change I see.

fn new(code_id: usize) -> Self {
ContractData { code_id }
}
/// Address of node who initially instantiated the contract
Copy link
Member

Choose a reason for hiding this comment

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

s/node/account/

A node is an observer who creates blocks.
A user or account is an actor who authorises tx
(I would use user, but contracts can also instantiate other contracts and have accounts)

}
/// Address of node who initially instantiated the contract
pub creator: Addr,
/// Optional address of node who can execute migrations
Copy link
Member

Choose a reason for hiding this comment

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

Again, change node

pub creator: Addr,
/// Optional address of node who can execute migrations
pub admin: Option<Addr>,
/// Optional metadata passed while contract instantiation
Copy link
Member

Choose a reason for hiding this comment

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

It is not so optional. You could add a validation that this is a non-empty string (but that is another PR)

Copy link
Contributor Author

@hashedone hashedone Jul 28, 2021

Choose a reason for hiding this comment

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

I actually based those descriptions on protobuf message related to this issue, where it is optional, but ok, i will remove the "Optional" from it.

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm.. bug in protobuf comment. I will fix.

pub admin: Option<Addr>,
/// Optional metadata passed while contract instantiation
pub label: String,
/// Blockchain height in the moment of instanciating the contract
Copy link
Member

Choose a reason for hiding this comment

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

s/instanciating/instantiating/

} => {
let contract_addr =
Addr::unchecked(self.register_contract(storage, code_id as usize)?);
let contract_addr = Addr::unchecked(self.register_contract(
Copy link
Member

Choose a reason for hiding this comment

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

Maybe register_contract should just return Addr?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, It does. This Addr::unchecked is completely unnecessary (remnant of old times)

@@ -647,48 +666,82 @@ mod test {
let block = mock_env().block;
let code_id = keeper.store_code(contract_error());

let mut cache = StorageTransaction::new(&wasm_storage);
let contract_addr = transactional(&mut wasm_storage, |cache, _| {
// cannot register contract with unregistered codeId
Copy link
Member

Choose a reason for hiding this comment

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

This could actually be in another transactional block.
To ensure it didn't make any changes when it returns an error.

Since they are simpler, we can do more.

// we can register a new instance of this code
let contract_addr = keeper.register_contract(&mut cache, code_id).unwrap();
// now, we call this contract and see the error message from the contract
let info = mock_info("foobar", &[]);
Copy link
Member

Choose a reason for hiding this comment

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

yeah, each of these calls could be it's own transaction. And only the register_contract returns the contract_address successfully

code_id,
Addr::unchecked("foobar"),
None,
"".to_owned(),
Copy link
Member

Choose a reason for hiding this comment

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

This is actually illegal in wasmd and will be illegal in the near future in multi-test. Let's avoid that except for tests that should fail.

@@ -798,7 +860,16 @@ mod test {
let mut cache = StorageTransaction::new(&wasm_storage);

// set contract 1 and commit (on router)
let contract1 = keeper.register_contract(&mut cache, code_id).unwrap();
let contract1 = keeper
Copy link
Member

Choose a reason for hiding this comment

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

This could also be transactional. I missed this in my refactor.

// and flush
cache.prepare().commit(&mut wasm_storage);
// verify contract data are as expected
let contract_data = CONTRACTS
Copy link
Member

Choose a reason for hiding this comment

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

We should not do this in test code. Actually WasmKeeper.load_contract() does this.

We should make it public and expose it in the Wasm interface (and exposed in App as well, so we can use it in higher-level tests).

It might also be nice to have a query that returns an Iterator of all ContractData (but we can add that later if needed). This is a query we have in wasmd, but no need to add it yet

Copy link
Member

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

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

Great updates.

@hashedone
Copy link
Contributor Author

I didn't refactor tests to use Wasm<T> interface, to not blow up the PR, instead I created issue about that - CosmWasm/cw-multi-test#3

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.

None yet

2 participants