diff --git a/pallets/distance/src/tests.rs b/pallets/distance/src/tests.rs index d030f114e0cadd816ec14f22ea177b30fdfd6e13..8aff91a5723a950e142591b4247e762dc9b5ed48 100644 --- a/pallets/distance/src/tests.rs +++ b/pallets/distance/src/tests.rs @@ -15,6 +15,7 @@ // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. use crate::mock::*; +use crate::DistanceStatus::{Pending, Valid}; use crate::{pallet, Error, MedianAcc, MedianResult}; use frame_support::traits::Len; use frame_support::{assert_err, assert_noop, assert_ok}; @@ -27,22 +28,27 @@ type Distance = pallet::Pallet<Test, ()>; type Identity = pallet_identity::Pallet<Test>; type Cert = pallet_certification::Pallet<Test>; +const IDTY_0: &u64 = &1; // Identity of account 0 const AUTHOR0: &u64 = &0; const AUTHOR1: &u64 = &1; const AUTHOR2: &u64 = &2; // SESSION_LENGTH = 5 -const SESSION_0_START: u64 = 0; -const SESSION_1_START: u64 = 5; -const SESSION_2_START: u64 = 10; +const SESSION_0_START: u64 = 0; // S+0 +const SESSION_1_START: u64 = 5; // S+1 +const SESSION_2_START: u64 = 10; // S+2 +const SESSION_3_START: u64 = 15; // S+3 + +/// Notation: +/// S+0 is the session during which distance evaluation is asked (`evaluate_distance` extrinsic) +/// S+1 is the session during which distance is computed +/// S+2 is the session during which S+1 computation results get accumulated in the blockchain +/// S+3 is the session at which distance is officialized on first block of the session. #[test] fn basic_single_distance() { new_test_ext().execute_with(|| { - // Session 0: distance is asked run_to_block(SESSION_0_START); assert_ok!(Distance::evaluate_distance(RuntimeOrigin::signed(0))); - // Session 1: distance is being computed - // Session 2: results publication run_to_block(SESSION_2_START); assert_ok!(Distance::update_evaluation( RuntimeOrigin::none(), @@ -65,8 +71,13 @@ fn basic_single_distance() { #[test] fn multiple_authors() { new_test_ext().execute_with(|| { + assert!(pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0).is_none()); // not known run_to_block(SESSION_0_START); assert_ok!(Distance::evaluate_distance(RuntimeOrigin::signed(0))); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Pending) + ); // asking for evaluation changes the status // Evaluation #1 run_to_block(SESSION_2_START); @@ -81,13 +92,17 @@ fn multiple_authors() { assert_eq!(authors_tree.get(AUTHOR0), None); assert_eq!(authors_tree.get(AUTHOR1), Some(AUTHOR1)); assert_eq!(authors_tree.get(AUTHOR2), None); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Pending) + ); // still pending // Evaluation #2 run_to_block(SESSION_2_START + 1); // to change author assert_ok!(Distance::update_evaluation( RuntimeOrigin::none(), ComputationResult { - distances: vec![Perbill::from_percent(60)] + distances: vec![Perbill::from_percent(80)] } )); let authors_tree = pallet::EvaluationPool2::<Test>::get().1; @@ -95,13 +110,17 @@ fn multiple_authors() { assert_eq!(authors_tree.get(AUTHOR0), None); assert_eq!(authors_tree.get(AUTHOR1), Some(AUTHOR1)); assert_eq!(authors_tree.get(AUTHOR2), Some(AUTHOR2)); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Pending) + ); // still pending // Evaluation #3 run_to_block(SESSION_2_START + 2); // to change author assert_ok!(Distance::update_evaluation( RuntimeOrigin::none(), ComputationResult { - distances: vec![Perbill::from_percent(20)] + distances: vec![Perbill::from_percent(60)] } )); let authors_tree = pallet::EvaluationPool2::<Test>::get().1; @@ -109,6 +128,10 @@ fn multiple_authors() { assert_eq!(authors_tree.get(AUTHOR0), Some(AUTHOR0)); assert_eq!(authors_tree.get(AUTHOR1), Some(AUTHOR1)); assert_eq!(authors_tree.get(AUTHOR2), Some(AUTHOR2)); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Pending) + ); // still pending // Other pools have never been used (because of session number) assert_eq!(pallet::EvaluationPool0::<Test>::get().0.len(), 0); @@ -136,6 +159,48 @@ fn multiple_authors() { ), pallet::Error::<Test>::ManyEvaluationsByAuthor ); + + run_to_block(SESSION_3_START); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Valid) + ); // now valid! + }); +} + +#[test] +fn distance_failure() { + new_test_ext().execute_with(|| { + run_to_block(SESSION_0_START); + assert_ok!(Distance::evaluate_distance(RuntimeOrigin::signed(0))); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Pending) + ); + + // Evaluation #1 + run_to_block(SESSION_2_START); + assert_ok!(Distance::update_evaluation( + RuntimeOrigin::none(), + ComputationResult { + distances: vec![Perbill::from_percent(50)] + } + )); + let authors_tree = pallet::EvaluationPool2::<Test>::get().1; + assert_eq!(authors_tree.len(), 1); + assert_eq!(authors_tree.get(AUTHOR0), None); + assert_eq!(authors_tree.get(AUTHOR1), Some(AUTHOR1)); + assert_eq!(authors_tree.get(AUTHOR2), None); + assert_eq!( + pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), + Some(Pending) + ); // still pending + + // Finally session 4 + run_to_block(SESSION_3_START); + assert_eq!(pallet::IdentitiesDistanceStatus::<Test>::get(IDTY_0), None); + // distance failure + // TODO: test: variant Two }); } @@ -143,3 +208,20 @@ fn multiple_authors() { // #[test] // fn evaluation_for_non_asked() { // } + +// TODO: evaluate_distance => Err::NoIdentity +// TODO: evaluate_distance => Err::AlreadyInEvaluation +// TODO: evaluate_distance => Err::QueueFull (1) +// TODO: evaluate_distance => Err::QueueFull (2) +// TODO: Err::ManyEvaluationsInBlock +// TODO: Err::WrongResultLength ==> faire l'update_evaluation à la mauvaise session (par le bon modulo 3) +// TODO: Err::NoAuthor ==> AuthorGiven => renvoyer None sous certaines conditions +// TODO: Err::TooManyEvaluators => constante de conf +// TODO: test not only length, but accountIds and idtyIndexes +// TODO: test EvaluationBlock +// TODO: test IdentitiesDistanceStatus +// TODO: test DidUpdate +// TODO: test EvaluationSuccess + +// TODO: Error::CannotReserve, +// TODO: Error::NonEligibleForEvaluation, diff --git a/pallets/distance/src/types.rs b/pallets/distance/src/types.rs index ab629ec482290350863cadfb8a85de3273a67b13..f93b851f4223b0f406254f6e15fc303cc665715c 100644 --- a/pallets/distance/src/types.rs +++ b/pallets/distance/src/types.rs @@ -31,7 +31,9 @@ pub enum DistanceStatus { } pub type EvaluationPool<AccountId, IdtyIndex, MaxEvaluationsPerSession, MaxEvaluatorsPerSession> = ( + // List of evaluation results (IdtyIndex => Median) BoundedVec<(IdtyIndex, MedianAcc<Perbill, MaxEvaluatorsPerSession>), MaxEvaluationsPerSession>, + // List of evaluators (block authors) BoundedBTreeSet<AccountId, MaxEvaluatorsPerSession>, );