-
Notifications
You must be signed in to change notification settings - Fork 47
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
chore: add sanity tests #512
Conversation
…e into chore/sanity-tests
pallets/delegation/src/lib.rs
Outdated
@@ -87,7 +87,7 @@ use frame_support::{ | |||
use kilt_support::traits::StorageDepositCollector; | |||
use parity_scale_codec::Encode; | |||
use sp_runtime::{traits::Hash, DispatchError}; | |||
use sp_std::{marker::PhantomData, vec::Vec}; | |||
use sp_std::{marker::PhantomData, vec, vec::Vec}; |
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.
This dependendency is only used in try-runtime
, right? In this case it should not be pulled in regardless, and also it could either be used directly with sp_std::vec
, or imported inside the function that needs it.
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.
A second round of comments! I love the solution that runs integrity tests after every unit test case. Nevertheless, I would still like to see the following:
- Clearer error messages when tests fail, especially (but not only) when inside loops, since otherwise it becomes much harder to find out when the test failed
- A separate
try_state.rs
module for each pallet, with a singlepub(crate) try_state()
function, which then internally calls several different functions, if needed.
Other than that, this looks like a very very very nice improvement, which will be completed once we have cross-pallet checks in place, especially regarding deposits and locked balances.
pallets/pallet-did-lookup/src/lib.rs
Outdated
ConnectedAccounts::<T>::iter().try_for_each( | ||
|(did_identifier, linked_account_id, _)| -> Result<(), &'static str> { | ||
let connected_did = ConnectedDids::<T>::get(linked_account_id); | ||
ensure!(connected_did.is_some(), "Unknown did"); |
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.
This can still be simplified by checking against Some(...)
.
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.
Are you sure? I want to check a property of connected_did
.
Doing something like:
connected_did == Some(ConnectionRecord {
did: did_identifier,
deposit: deposit
})
looks to me over-engineered.
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 also do not know the deposit – I needed to copy it from the connected_did
variable -> I have to unwrap it...
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 see, then probably calling .expect(...)
on ConnectedDids::::get()` and then matching the DID is a better option, in my opinion. All cases panic anyway.
pallets/pallet-web3-names/src/lib.rs
Outdated
// check if for each owner there is a name stored. | ||
Owner::<T>::iter().try_for_each( | ||
|(w3n, ownership): (Web3NameOf<T>, Web3OwnershipOf<T>)| -> Result<(), &'static str> { | ||
ensure!(Names::<T>::contains_key(ownership.owner.clone()), "W3n unknown"); |
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.
This check seems redundant, given the line below, no?
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.
Well, Names
and Owner
should have a 1to1 relation. It can happen that a name record is pointing to an owner, which does not exist. The check_claiming_preconditions
ensures, that the relation is correct, but I think testing it does not hurt.
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.
Owner and names should have a 1 to 1 relation. It might happen, that an owner is pointing to a name which does not exist. Iterating over only one of these storage, would not reveal these issues.
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.
No I meant that having contains_key
and get
is redundant, since you are checking for the same thing. But I see that is gone now, so I'll mark this as resolved 👍
pallets/attestation/src/lib.rs
Outdated
if let Some(authorization_id) = attestation_details.authorization_id { | ||
ensure!( | ||
ExternalAttestations::<T>::get(authorization_id, claim_hash), | ||
"Unknown external attestation" |
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.
What about including some more information in the error strings? Something like format!("External attestation entry does not exist for attestation with authorization ID {:?}", authorization_id)
. This will save us a lot of time in case something does actually break in the future. Probably the same could be applied to most of the error messages.
All requested changes should be resolved now. |
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.
Apart from the offline discussion about better errors, I just have a couple more suggestions, then it looks good for me!
@ntn-x2 I am always happy to see your suggestions! |
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.
still some minor requests that need changing. I'm not a fan of convert_error_message
. Is this the result of a discussion with @ntn-x2?
|
||
// total stake should be the sum of delegators stake + colator stake. | ||
ensure!( | ||
sum_delegations.saturating_add(candidate.stake) == candidate.total, |
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.
In theory we want to notice a wrap here. While the normal +
should panic when it overflows in debug builds, we could use checked_add with an expected(...)
to ensure no overflows happen.
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.
Few more suggestions 😄 The bigger ones are about 1. the new utility function to return static strings for testing, 2. better error messages, that also include the failed condition, where it makes sense, so that it's easier to see what failed and for which reason. Other minor points include the way of importing the required types for this new feature.
support/src/test.rs
Outdated
|
||
// If you feel like getting in touch with us, you can do so at [email protected] | ||
|
||
use scale_info::prelude::{boxed::Box, string::String}; |
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 think taking them from sp_std
would be cleaner, as that's supposed to be the replacement of the standard library in Substrate.
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 import the Box struct from sp_std
now. I think sp_std
has no String struct…
support/src/lib.rs
Outdated
@@ -20,6 +20,9 @@ | |||
pub mod deposit; | |||
pub use deposit::{free_deposit, reserve_deposit}; | |||
|
|||
#[cfg(any(feature = "try-runtime", test))] | |||
pub mod test; |
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.
Not sure this is the best nemaing. This is a testing utility, right? Maybe test_utils
or test_utilities
would be better? We usually use test
for actual tests.
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.
Also the function name itself is not very indicative, and a comment would not hurt about its expected usage.
let stake_total = sum_delegations.saturating_add(candidate.stake); | ||
ensure!( | ||
stake_total == candidate.total, | ||
convert_error_message(format!("Total stake of collator {:?} does not match", candidate.id)) |
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.
Should we add what the expected and returned values are? In general if we are testing a condition, we might want to also want to output, in the case of a failure, what the expected condition was and what was actually returned.
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 updated all possible error messages
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.
Sehr gut!
fixes KILTProtocol/ticket#312
The sanity tests are executed after each unit test, to validate the pallets state.
One bug could be detected in the staking pallet.
Finding good variable names is difficult: If a sanity test fails, I return
DispatchError::Other("Test")
. I appreciate suggestions 😆 .