From ff0b50dd28c744aaafc3850cf91598262e1acbee Mon Sep 17 00:00:00 2001
From: zjb0807 <zjb0807@qq.com>
Date: Wed, 19 Aug 2020 07:11:20 +0800
Subject: [PATCH] add authority tests (#250)

---
 authority/src/mock.rs  |  31 ++++--
 authority/src/tests.rs | 222 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 246 insertions(+), 7 deletions(-)

diff --git a/authority/src/mock.rs b/authority/src/mock.rs
index 241e88b..1c699f3 100644
--- a/authority/src/mock.rs
+++ b/authority/src/mock.rs
@@ -2,7 +2,10 @@
 
 #![cfg(test)]
 
-use frame_support::parameter_types;
+use frame_support::{
+	parameter_types,
+	traits::{OnFinalize, OnInitialize},
+};
 use frame_system::{ensure_root, ensure_signed, EnsureRoot};
 use sp_core::H256;
 use sp_runtime::{
@@ -12,7 +15,7 @@ use sp_runtime::{
 };
 
 use super::*;
-use crate as authority;
+pub use crate as authority;
 
 pub type AccountId = u128;
 pub type BlockNumber = u64;
@@ -34,7 +37,7 @@ impl frame_system::Trait for Runtime {
 	type AccountId = AccountId;
 	type Lookup = IdentityLookup<Self::AccountId>;
 	type Header = Header;
-	type Event = ();
+	type Event = Event;
 	type BlockHashCount = BlockHashCount;
 	type MaximumBlockWeight = MaximumBlockWeight;
 	type MaximumBlockLength = MaximumBlockLength;
@@ -56,7 +59,7 @@ parameter_types! {
 	pub MaximumSchedulerWeight: u32 = Perbill::from_percent(80) * MaximumBlockWeight::get();
 }
 impl pallet_scheduler::Trait for Runtime {
-	type Event = ();
+	type Event = Event;
 	type Origin = Origin;
 	type PalletsOrigin = OriginCaller;
 	type Call = Call;
@@ -122,6 +125,14 @@ impl AsOriginId<Origin, OriginCaller> for MockAsOriginId {
 	}
 	fn check_dispatch_from(&self, origin: Origin) -> DispatchResult {
 		ensure_root(origin.clone()).or_else(|_| {
+			if let OriginCaller::authority(ref sign) = origin.caller() {
+				if sign.origin == Box::new(Origin::root().caller().clone()) {
+					return Ok(());
+				} else {
+					return Err(BadOrigin.into());
+				}
+			}
+
 			let ok = match self {
 				MockAsOriginId::Root => false,
 				MockAsOriginId::Account1 => ensure_signed(origin)? == 1,
@@ -133,7 +144,7 @@ impl AsOriginId<Origin, OriginCaller> for MockAsOriginId {
 }
 
 impl Trait for Runtime {
-	type Event = ();
+	type Event = Event;
 	type Origin = Origin;
 	type PalletsOrigin = OriginCaller;
 	type Scheduler = Scheduler;
@@ -152,7 +163,7 @@ frame_support::construct_runtime!(
 		UncheckedExtrinsic = UncheckedExtrinsic
 	{
 		System: frame_system::{Module, Call, Event<T>},
-		Authority: authority::{Module, Call, Origin<T>},
+		Authority: authority::{Module, Call, Origin<T>, Event<T>},
 		Scheduler: pallet_scheduler::{Module, Call, Storage, Event<T>},
 	}
 );
@@ -174,3 +185,11 @@ impl ExtBuilder {
 		t.into()
 	}
 }
+
+pub fn run_to_block(n: u64) {
+	while System::block_number() < n {
+		Scheduler::on_finalize(System::block_number());
+		System::set_block_number(System::block_number() + 1);
+		Scheduler::on_initialize(System::block_number());
+	}
+}
diff --git a/authority/src/tests.rs b/authority/src/tests.rs
index f39e51f..fcaad9f 100644
--- a/authority/src/tests.rs
+++ b/authority/src/tests.rs
@@ -4,7 +4,11 @@
 
 use super::*;
 use frame_support::{assert_noop, assert_ok};
-use mock::{Authority, Call, ExtBuilder, MockAsOriginId, Origin};
+use frame_system::RawOrigin;
+use mock::{
+	authority, run_to_block, Authority, BlockNumber, Call, ExtBuilder, MockAsOriginId, Origin, OriginCaller, Runtime,
+	System,
+};
 use sp_runtime::{traits::BadOrigin, Perbill};
 
 #[test]
@@ -45,3 +49,219 @@ fn dispatch_as_work() {
 		);
 	});
 }
+
+#[test]
+fn schedule_dispatch_at_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let ensure_root_call = Call::System(frame_system::Call::fill_block(Perbill::one()));
+		let call = Call::Authority(authority::Call::dispatch_as(
+			MockAsOriginId::Root,
+			Box::new(ensure_root_call.clone()),
+		));
+		run_to_block(1);
+		assert_eq!(
+			Authority::schedule_dispatch(Origin::root(), DispatchTime::At(1), 0, true, Box::new(call.clone())),
+			Err(Error::<Runtime>::FailedToSchedule.into())
+		);
+
+		assert_ok!(Authority::schedule_dispatch(
+			Origin::root(),
+			DispatchTime::At(2),
+			0,
+			true,
+			Box::new(call.clone())
+		));
+		let event = mock::Event::authority(RawEvent::Scheduled(
+			OriginCaller::authority(DelayedOrigin {
+				delay: 1,
+				origin: Box::new(OriginCaller::system(RawOrigin::Root)),
+			}),
+			1,
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		run_to_block(2);
+		let event = mock::Event::pallet_scheduler(pallet_scheduler::RawEvent::Dispatched(
+			(2, 0),
+			Some([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0].to_vec()),
+			Ok(()),
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		// with_delayed_origin = false
+		assert_ok!(Authority::schedule_dispatch(
+			Origin::root(),
+			DispatchTime::At(3),
+			0,
+			false,
+			Box::new(call.clone())
+		));
+		let event = mock::Event::authority(RawEvent::Scheduled(OriginCaller::system(RawOrigin::Root), 2));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		run_to_block(3);
+		let event = mock::Event::pallet_scheduler(pallet_scheduler::RawEvent::Dispatched(
+			(3, 0),
+			Some([0, 0, 2, 0, 0, 0].to_vec()),
+			Ok(()),
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+	});
+}
+
+#[test]
+fn schedule_dispatch_after_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let ensure_root_call = Call::System(frame_system::Call::fill_block(Perbill::one()));
+		let call = Call::Authority(authority::Call::dispatch_as(
+			MockAsOriginId::Root,
+			Box::new(ensure_root_call.clone()),
+		));
+		run_to_block(1);
+		assert_eq!(
+			Authority::schedule_dispatch(Origin::root(), DispatchTime::After(0), 0, true, Box::new(call.clone())),
+			Err(Error::<Runtime>::FailedToSchedule.into())
+		);
+
+		assert_ok!(Authority::schedule_dispatch(
+			Origin::root(),
+			DispatchTime::After(1),
+			0,
+			true,
+			Box::new(call.clone())
+		));
+		let event = mock::Event::authority(RawEvent::Scheduled(
+			OriginCaller::authority(DelayedOrigin {
+				delay: 1,
+				origin: Box::new(OriginCaller::system(RawOrigin::Root)),
+			}),
+			1,
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		run_to_block(2);
+		let event = mock::Event::pallet_scheduler(pallet_scheduler::RawEvent::Dispatched(
+			(2, 0),
+			Some([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0].to_vec()),
+			Ok(()),
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		// with_delayed_origin = false
+		assert_ok!(Authority::schedule_dispatch(
+			Origin::root(),
+			DispatchTime::After(1),
+			0,
+			false,
+			Box::new(call.clone())
+		));
+		let event = mock::Event::authority(RawEvent::Scheduled(OriginCaller::system(RawOrigin::Root), 2));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		run_to_block(3);
+		let event = mock::Event::pallet_scheduler(pallet_scheduler::RawEvent::Dispatched(
+			(3, 0),
+			Some([0, 0, 2, 0, 0, 0].to_vec()),
+			Ok(()),
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+	});
+}
+
+#[test]
+fn fast_track_scheduled_dispatch_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		System::set_block_number(1);
+		//let ensure_root_call =
+		// Call::System(frame_system::Call::fill_block(Perbill::one()));
+		// let ensure_signed_call = Call::System(frame_system::Call::remark(vec![]));
+		assert_ok!(Authority::fast_track_scheduled_dispatch(
+			Origin::root(),
+			frame_system::RawOrigin::Root.into(),
+			0,
+			DispatchTime::At(4),
+		));
+	});
+}
+
+#[test]
+fn delay_scheduled_dispatch_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		//let ensure_root_call =
+		// Call::System(frame_system::Call::fill_block(Perbill::one()));
+		// let ensure_signed_call = Call::System(frame_system::Call::remark(vec![]));
+		assert_ok!(Authority::delay_scheduled_dispatch(
+			Origin::root(),
+			frame_system::RawOrigin::Root.into(),
+			0,
+			5,
+		));
+	});
+}
+
+#[test]
+fn cancel_scheduled_dispatch_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let ensure_root_call = Call::System(frame_system::Call::fill_block(Perbill::one()));
+		let call = Call::Authority(authority::Call::dispatch_as(
+			MockAsOriginId::Root,
+			Box::new(ensure_root_call.clone()),
+		));
+		run_to_block(1);
+		assert_ok!(Authority::schedule_dispatch(
+			Origin::root(),
+			DispatchTime::At(2),
+			0,
+			true,
+			Box::new(call.clone())
+		));
+		let event = mock::Event::authority(RawEvent::Scheduled(
+			OriginCaller::authority(DelayedOrigin {
+				delay: 1,
+				origin: Box::new(OriginCaller::system(RawOrigin::Root)),
+			}),
+			0,
+		));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		let schedule_origin = {
+			let origin: <Runtime as Trait>::Origin = From::from(Origin::root());
+			let origin: <Runtime as Trait>::Origin =
+				From::from(DelayedOrigin::<BlockNumber, <Runtime as Trait>::PalletsOrigin> {
+					delay: 1,
+					origin: Box::new(origin.caller().clone()),
+				});
+			origin
+		};
+
+		let pallets_origin = schedule_origin.caller().clone();
+		assert_ok!(Authority::cancel_scheduled_dispatch(Origin::root(), pallets_origin, 0));
+		let event = mock::Event::authority(RawEvent::Cancelled(
+			OriginCaller::authority(DelayedOrigin {
+				delay: 1,
+				origin: Box::new(OriginCaller::system(RawOrigin::Root)),
+			}),
+			0,
+		));
+		println!("{:?}", System::events());
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		assert_ok!(Authority::schedule_dispatch(
+			Origin::root(),
+			DispatchTime::At(2),
+			0,
+			false,
+			Box::new(call.clone())
+		));
+		let event = mock::Event::authority(RawEvent::Scheduled(OriginCaller::system(RawOrigin::Root), 1));
+		assert!(System::events().iter().any(|record| record.event == event));
+
+		assert_ok!(Authority::cancel_scheduled_dispatch(
+			Origin::root(),
+			frame_system::RawOrigin::Root.into(),
+			1
+		));
+		let event = mock::Event::authority(RawEvent::Cancelled(OriginCaller::system(RawOrigin::Root), 1));
+		assert!(System::events().iter().any(|record| record.event == event));
+	});
+}
-- 
GitLab