difftreelog
fix scheduler warnings
in: master
3 files changed
pallets/scheduler-v2/src/lib.rsdiffbeforeafterboth--- a/pallets/scheduler-v2/src/lib.rs
+++ b/pallets/scheduler-v2/src/lib.rs
@@ -77,13 +77,13 @@
use codec::{Codec, Decode, Encode, MaxEncodedLen};
use frame_support::{
- dispatch::{DispatchError, DispatchResult, Dispatchable, GetDispatchInfo, Parameter},
+ dispatch::{DispatchError, DispatchResult, Dispatchable, GetDispatchInfo, Parameter, PostDispatchInfo},
traits::{
schedule::{self, DispatchTime, LOWEST_PRIORITY},
EnsureOrigin, Get, IsType, OriginTrait, PrivilegeCmp, StorageVersion, PreimageRecipient,
ConstU32, UnfilteredDispatchable,
},
- weights::{Weight, PostDispatchInfo}, unsigned::TransactionValidityError,
+ weights::Weight, unsigned::TransactionValidityError,
};
use frame_system::{self as system};
pallets/scheduler-v2/src/mock.rsdiffbeforeafterboth--- a/pallets/scheduler-v2/src/mock.rs
+++ b/pallets/scheduler-v2/src/mock.rs
@@ -40,11 +40,11 @@
use frame_support::{
ord_parameter_types, parameter_types,
traits::{
- ConstU32, ConstU64, Contains, EitherOfDiverse, EqualPrivilegeOnly, OnFinalize, OnInitialize,
+ ConstU32, ConstU64, Contains, EqualPrivilegeOnly, OnFinalize, OnInitialize,
},
weights::constants::RocksDbWeight,
};
-use frame_system::{EnsureRoot, EnsureSignedBy, RawOrigin};
+use frame_system::{EnsureRoot, RawOrigin};
use sp_core::H256;
use sp_runtime::{
testing::Header,
pallets/scheduler-v2/src/tests.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license:18// This file is part of Substrate.1920// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd.21// SPDX-License-Identifier: Apache-2.02223// Licensed under the Apache License, Version 2.0 (the "License");24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at26//27// http://www.apache.org/licenses/LICENSE-2.028//29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and33// limitations under the License.3435//! # Scheduler tests.3637use super::*;38use crate::mock::{39 logger, new_test_ext, root, run_to_block, LoggerCall, RuntimeCall, Scheduler, Test, *,40};41use frame_support::{42 assert_noop, assert_ok,43 traits::{Contains, GetStorageVersion, OnInitialize},44 Hashable,45};4647#[test]48fn basic_scheduling_works() {49 new_test_ext().execute_with(|| {50 let call =51 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });52 assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));53 assert_ok!(Scheduler::do_schedule(54 DispatchTime::At(4),55 None,56 127,57 root(),58 <ScheduledCall<Test>>::new(call).unwrap(),59 ));60 run_to_block(3);61 assert!(logger::log().is_empty());62 run_to_block(4);63 assert_eq!(logger::log(), vec![(root(), 42u32)]);64 run_to_block(100);65 assert_eq!(logger::log(), vec![(root(), 42u32)]);66 });67}6869#[test]70fn schedule_after_works() {71 new_test_ext().execute_with(|| {72 run_to_block(2);73 let call =74 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });75 assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));76 // This will schedule the call 3 blocks after the next block... so block 3 + 3 = 677 assert_ok!(Scheduler::do_schedule(78 DispatchTime::After(3),79 None,80 127,81 root(),82 <ScheduledCall<Test>>::new(call).unwrap(),83 ));84 run_to_block(5);85 assert!(logger::log().is_empty());86 run_to_block(6);87 assert_eq!(logger::log(), vec![(root(), 42u32)]);88 run_to_block(100);89 assert_eq!(logger::log(), vec![(root(), 42u32)]);90 });91}9293#[test]94fn schedule_after_zero_works() {95 new_test_ext().execute_with(|| {96 run_to_block(2);97 let call =98 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });99 assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));100 assert_ok!(Scheduler::do_schedule(101 DispatchTime::After(0),102 None,103 127,104 root(),105 <ScheduledCall<Test>>::new(call).unwrap(),106 ));107 // Will trigger on the next block.108 run_to_block(3);109 assert_eq!(logger::log(), vec![(root(), 42u32)]);110 run_to_block(100);111 assert_eq!(logger::log(), vec![(root(), 42u32)]);112 });113}114115#[test]116fn periodic_scheduling_works() {117 new_test_ext().execute_with(|| {118 // at #4, every 3 blocks, 3 times.119 assert_ok!(Scheduler::do_schedule(120 DispatchTime::At(4),121 Some((3, 3)),122 127,123 root(),124 <ScheduledCall<Test>>::new(RuntimeCall::Logger(logger::Call::log {125 i: 42,126 weight: Weight::from_ref_time(10)127 }))128 .unwrap()129 ));130 run_to_block(3);131 assert!(logger::log().is_empty());132 run_to_block(4);133 assert_eq!(logger::log(), vec![(root(), 42u32)]);134 run_to_block(6);135 assert_eq!(logger::log(), vec![(root(), 42u32)]);136 run_to_block(7);137 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]);138 run_to_block(9);139 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]);140 run_to_block(10);141 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]);142 run_to_block(100);143 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]);144 });145}146147#[test]148fn cancel_named_scheduling_works_with_normal_cancel() {149 new_test_ext().execute_with(|| {150 // at #4.151 Scheduler::do_schedule_named(152 [1u8; 32],153 DispatchTime::At(4),154 None,155 127,156 root(),157 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {158 i: 69,159 weight: Weight::from_ref_time(10),160 }))161 .unwrap(),162 )163 .unwrap();164 let i = Scheduler::do_schedule(165 DispatchTime::At(4),166 None,167 127,168 root(),169 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {170 i: 42,171 weight: Weight::from_ref_time(10),172 }))173 .unwrap(),174 )175 .unwrap();176 run_to_block(3);177 assert!(logger::log().is_empty());178 assert_ok!(Scheduler::do_cancel_named(None, [1u8; 32]));179 assert_ok!(Scheduler::do_cancel(None, i));180 run_to_block(100);181 assert!(logger::log().is_empty());182 });183}184185#[test]186fn cancel_named_periodic_scheduling_works() {187 new_test_ext().execute_with(|| {188 // at #4, every 3 blocks, 3 times.189 Scheduler::do_schedule_named(190 [1u8; 32],191 DispatchTime::At(4),192 Some((3, 3)),193 127,194 root(),195 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {196 i: 42,197 weight: Weight::from_ref_time(10),198 }))199 .unwrap(),200 )201 .unwrap();202 // same id results in error.203 assert!(Scheduler::do_schedule_named(204 [1u8; 32],205 DispatchTime::At(4),206 None,207 127,208 root(),209 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {210 i: 69,211 weight: Weight::from_ref_time(10)212 }))213 .unwrap(),214 )215 .is_err());216 // different id is ok.217 Scheduler::do_schedule_named(218 [2u8; 32],219 DispatchTime::At(8),220 None,221 127,222 root(),223 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {224 i: 69,225 weight: Weight::from_ref_time(10),226 }))227 .unwrap(),228 )229 .unwrap();230 run_to_block(3);231 assert!(logger::log().is_empty());232 run_to_block(4);233 assert_eq!(logger::log(), vec![(root(), 42u32)]);234 run_to_block(6);235 assert_ok!(Scheduler::do_cancel_named(None, [1u8; 32]));236 run_to_block(100);237 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]);238 });239}240241#[test]242fn scheduler_respects_weight_limits() {243 let max_weight: Weight = <Test as Config>::MaximumWeight::get();244 new_test_ext().execute_with(|| {245 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 * 2 });246 assert_ok!(Scheduler::do_schedule(247 DispatchTime::At(4),248 None,249 127,250 root(),251 <ScheduledCall<Test>>::new(call).unwrap(),252 ));253 let call = RuntimeCall::Logger(LoggerCall::log { i: 69, weight: max_weight / 3 * 2 });254 assert_ok!(Scheduler::do_schedule(255 DispatchTime::At(4),256 None,257 127,258 root(),259 <ScheduledCall<Test>>::new(call).unwrap(),260 ));261 // 69 and 42 do not fit together262 run_to_block(4);263 assert_eq!(logger::log(), vec![(root(), 42u32)]);264 run_to_block(5);265 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]);266 });267}268269/// Permanently overweight calls are not deleted but also not executed.270#[test]271fn scheduler_does_not_delete_permanently_overweight_call() {272 let max_weight: Weight = <Test as Config>::MaximumWeight::get();273 new_test_ext().execute_with(|| {274 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight });275 assert_ok!(Scheduler::do_schedule(276 DispatchTime::At(4),277 None,278 127,279 root(),280 <ScheduledCall<Test>>::new(call).unwrap(),281 ));282 // Never executes.283 run_to_block(100);284 assert_eq!(logger::log(), vec![]);285286 // Assert the `PermanentlyOverweight` event.287 assert_eq!(288 System::events().last().unwrap().event,289 crate::Event::PermanentlyOverweight { task: (4, 0), id: None }.into(),290 );291 // The call is still in the agenda.292 assert!(Agenda::<Test>::get(4)[0].is_some());293 });294}295296#[test]297fn scheduler_handles_periodic_failure() {298 let max_weight: Weight = <Test as Config>::MaximumWeight::get();299 let max_per_block = <Test as Config>::MaxScheduledPerBlock::get();300301 new_test_ext().execute_with(|| {302 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: (max_weight / 3) * 2 });303 let call = <ScheduledCall<Test>>::new(call).unwrap();304305 assert_ok!(Scheduler::do_schedule(306 DispatchTime::At(4),307 Some((4, u32::MAX)),308 127,309 root(),310 call.clone(),311 ));312 // Executes 5 times till block 20.313 run_to_block(20);314 assert_eq!(logger::log().len(), 5);315316 // Block 28 will already be full.317 for _ in 0..max_per_block {318 assert_ok!(Scheduler::do_schedule(319 DispatchTime::At(28),320 None,321 120,322 root(),323 call.clone(),324 ));325 }326327 // Going to block 24 will emit a `PeriodicFailed` event.328 run_to_block(24);329 assert_eq!(logger::log().len(), 6);330331 assert_eq!(332 System::events().last().unwrap().event,333 crate::Event::PeriodicFailed { task: (24, 0), id: None }.into(),334 );335 });336}337338#[test]339fn scheduler_respects_priority_ordering() {340 let max_weight: Weight = <Test as Config>::MaximumWeight::get();341 new_test_ext().execute_with(|| {342 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 });343 assert_ok!(Scheduler::do_schedule(344 DispatchTime::At(4),345 None,346 1,347 root(),348 <ScheduledCall<Test>>::new(call).unwrap(),349 ));350 let call = RuntimeCall::Logger(LoggerCall::log { i: 69, weight: max_weight / 3 });351 assert_ok!(Scheduler::do_schedule(352 DispatchTime::At(4),353 None,354 0,355 root(),356 <ScheduledCall<Test>>::new(call).unwrap(),357 ));358 run_to_block(4);359 assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]);360 });361}362363#[test]364fn scheduler_respects_priority_ordering_with_soft_deadlines() {365 new_test_ext().execute_with(|| {366 let max_weight: Weight = <Test as Config>::MaximumWeight::get();367 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 5 * 2 });368 assert_ok!(Scheduler::do_schedule(369 DispatchTime::At(4),370 None,371 255,372 root(),373 <ScheduledCall<Test>>::new(call).unwrap(),374 ));375 let call = RuntimeCall::Logger(LoggerCall::log { i: 69, weight: max_weight / 5 * 2 });376 assert_ok!(Scheduler::do_schedule(377 DispatchTime::At(4),378 None,379 127,380 root(),381 <ScheduledCall<Test>>::new(call).unwrap(),382 ));383 let call = RuntimeCall::Logger(LoggerCall::log { i: 2600, weight: max_weight / 5 * 4 });384 assert_ok!(Scheduler::do_schedule(385 DispatchTime::At(4),386 None,387 126,388 root(),389 <ScheduledCall<Test>>::new(call).unwrap(),390 ));391392 // 2600 does not fit with 69 or 42, but has higher priority, so will go through393 run_to_block(4);394 assert_eq!(logger::log(), vec![(root(), 2600u32)]);395 // 69 and 42 fit together396 run_to_block(5);397 assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]);398 });399}400401#[test]402fn on_initialize_weight_is_correct() {403 new_test_ext().execute_with(|| {404 let call_weight = Weight::from_ref_time(25);405406 // Named407 let call = RuntimeCall::Logger(LoggerCall::log {408 i: 3,409 weight: call_weight + Weight::from_ref_time(1),410 });411 assert_ok!(Scheduler::do_schedule_named(412 [1u8; 32],413 DispatchTime::At(3),414 None,415 255,416 root(),417 <ScheduledCall<Test>>::new(call).unwrap(),418 ));419 let call = RuntimeCall::Logger(LoggerCall::log {420 i: 42,421 weight: call_weight + Weight::from_ref_time(2),422 });423 // Anon Periodic424 assert_ok!(Scheduler::do_schedule(425 DispatchTime::At(2),426 Some((1000, 3)),427 128,428 root(),429 <ScheduledCall<Test>>::new(call).unwrap(),430 ));431 let call = RuntimeCall::Logger(LoggerCall::log {432 i: 69,433 weight: call_weight + Weight::from_ref_time(3),434 });435 // Anon436 assert_ok!(Scheduler::do_schedule(437 DispatchTime::At(2),438 None,439 127,440 root(),441 <ScheduledCall<Test>>::new(call).unwrap(),442 ));443 // Named Periodic444 let call = RuntimeCall::Logger(LoggerCall::log {445 i: 2600,446 weight: call_weight + Weight::from_ref_time(4),447 });448 assert_ok!(Scheduler::do_schedule_named(449 [2u8; 32],450 DispatchTime::At(1),451 Some((1000, 3)),452 126,453 root(),454 <ScheduledCall<Test>>::new(call).unwrap(),455 ));456457 // Will include the named periodic only458 assert_eq!(459 Scheduler::on_initialize(1),460 TestWeightInfo::service_agendas_base() +461 TestWeightInfo::service_agenda_base(1) +462 <TestWeightInfo as MarginalWeightInfo>::service_task(None, true, true) +463 TestWeightInfo::execute_dispatch_unsigned() +464 call_weight + Weight::from_ref_time(4)465 );466 assert_eq!(IncompleteSince::<Test>::get(), None);467 assert_eq!(logger::log(), vec![(root(), 2600u32)]);468469 // Will include anon and anon periodic470 assert_eq!(471 Scheduler::on_initialize(2),472 TestWeightInfo::service_agendas_base() +473 TestWeightInfo::service_agenda_base(2) +474 <TestWeightInfo as MarginalWeightInfo>::service_task(None, false, true) +475 TestWeightInfo::execute_dispatch_unsigned() +476 call_weight + Weight::from_ref_time(3) +477 <TestWeightInfo as MarginalWeightInfo>::service_task(None, false, false) +478 TestWeightInfo::execute_dispatch_unsigned() +479 call_weight + Weight::from_ref_time(2)480 );481 assert_eq!(IncompleteSince::<Test>::get(), None);482 assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]);483484 // Will include named only485 assert_eq!(486 Scheduler::on_initialize(3),487 TestWeightInfo::service_agendas_base() +488 TestWeightInfo::service_agenda_base(1) +489 <TestWeightInfo as MarginalWeightInfo>::service_task(None, true, false) +490 TestWeightInfo::execute_dispatch_unsigned() +491 call_weight + Weight::from_ref_time(1)492 );493 assert_eq!(IncompleteSince::<Test>::get(), None);494 assert_eq!(495 logger::log(),496 vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32), (root(), 3u32)]497 );498499 // Will contain none500 let actual_weight = Scheduler::on_initialize(4);501 assert_eq!(502 actual_weight,503 TestWeightInfo::service_agendas_base() + TestWeightInfo::service_agenda_base(0)504 );505 });506}507508#[test]509fn root_calls_works() {510 new_test_ext().execute_with(|| {511 let call = Box::new(RuntimeCall::Logger(LoggerCall::log {512 i: 69,513 weight: Weight::from_ref_time(10),514 }));515 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {516 i: 42,517 weight: Weight::from_ref_time(10),518 }));519 assert_ok!(520 Scheduler::schedule_named(RuntimeOrigin::root(), [1u8; 32], 4, None, Some(127), call,)521 );522 assert_ok!(Scheduler::schedule(RuntimeOrigin::root(), 4, None, Some(127), call2));523 run_to_block(3);524 // Scheduled calls are in the agenda.525 assert_eq!(Agenda::<Test>::get(4).len(), 2);526 assert!(logger::log().is_empty());527 assert_ok!(Scheduler::cancel_named(RuntimeOrigin::root(), [1u8; 32]));528 assert_ok!(Scheduler::cancel(RuntimeOrigin::root(), 4, 1));529 // Scheduled calls are made NONE, so should not effect state530 run_to_block(100);531 assert!(logger::log().is_empty());532 });533}534535#[test]536fn fails_to_schedule_task_in_the_past() {537 new_test_ext().execute_with(|| {538 run_to_block(3);539540 let call1 = Box::new(RuntimeCall::Logger(LoggerCall::log {541 i: 69,542 weight: Weight::from_ref_time(10),543 }));544 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {545 i: 42,546 weight: Weight::from_ref_time(10),547 }));548 let call3 = Box::new(RuntimeCall::Logger(LoggerCall::log {549 i: 42,550 weight: Weight::from_ref_time(10),551 }));552553 assert_noop!(554 Scheduler::schedule_named(RuntimeOrigin::root(), [1u8; 32], 2, None, Some(127), call1),555 Error::<Test>::TargetBlockNumberInPast,556 );557558 assert_noop!(559 Scheduler::schedule(RuntimeOrigin::root(), 2, None, Some(127), call2),560 Error::<Test>::TargetBlockNumberInPast,561 );562563 assert_noop!(564 Scheduler::schedule(RuntimeOrigin::root(), 3, None, Some(127), call3),565 Error::<Test>::TargetBlockNumberInPast,566 );567 });568}569570#[test]571fn should_use_origin() {572 new_test_ext().execute_with(|| {573 let call = Box::new(RuntimeCall::Logger(LoggerCall::log {574 i: 69,575 weight: Weight::from_ref_time(10),576 }));577 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {578 i: 42,579 weight: Weight::from_ref_time(10),580 }));581 assert_ok!(Scheduler::schedule_named(582 system::RawOrigin::Signed(1).into(),583 [1u8; 32],584 4,585 None,586 None,587 call,588 ));589 assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, None, call2,));590 run_to_block(3);591 // Scheduled calls are in the agenda.592 assert_eq!(Agenda::<Test>::get(4).len(), 2);593 assert!(logger::log().is_empty());594 assert_ok!(Scheduler::cancel_named(system::RawOrigin::Signed(1).into(), [1u8; 32]));595 assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1));596 // Scheduled calls are made NONE, so should not effect state597 run_to_block(100);598 assert!(logger::log().is_empty());599 });600}601602#[test]603fn should_check_origin() {604 new_test_ext().execute_with(|| {605 let call = Box::new(RuntimeCall::Logger(LoggerCall::log {606 i: 69,607 weight: Weight::from_ref_time(10),608 }));609 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {610 i: 42,611 weight: Weight::from_ref_time(10),612 }));613 assert_noop!(614 Scheduler::schedule_named(615 system::RawOrigin::Signed(2).into(),616 [1u8; 32],617 4,618 None,619 None,620 call621 ),622 BadOrigin623 );624 assert_noop!(625 Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, None, call2),626 BadOrigin627 );628 });629}630631#[test]632fn should_check_origin_for_cancel() {633 new_test_ext().execute_with(|| {634 let call = Box::new(RuntimeCall::Logger(LoggerCall::log_without_filter {635 i: 69,636 weight: Weight::from_ref_time(10),637 }));638 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log_without_filter {639 i: 42,640 weight: Weight::from_ref_time(10),641 }));642 assert_ok!(Scheduler::schedule_named(643 system::RawOrigin::Signed(1).into(),644 [1u8; 32],645 4,646 None,647 None,648 call,649 ));650 assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, None, call2,));651 run_to_block(3);652 // Scheduled calls are in the agenda.653 assert_eq!(Agenda::<Test>::get(4).len(), 2);654 assert!(logger::log().is_empty());655 assert_noop!(656 Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), [1u8; 32]),657 BadOrigin658 );659 assert_noop!(Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), BadOrigin);660 assert_noop!(Scheduler::cancel_named(system::RawOrigin::Root.into(), [1u8; 32]), BadOrigin);661 assert_noop!(Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), BadOrigin);662 run_to_block(5);663 assert_eq!(664 logger::log(),665 vec![666 (system::RawOrigin::Signed(1).into(), 69u32),667 (system::RawOrigin::Signed(1).into(), 42u32)668 ]669 );670 });671}672673/// Cancelling a call and then scheduling a second call for the same674/// block results in different addresses.675#[test]676fn schedule_does_not_resuse_addr() {677 new_test_ext().execute_with(|| {678 let call =679 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });680681 // Schedule both calls.682 let addr_1 = Scheduler::do_schedule(683 DispatchTime::At(4),684 None,685 127,686 root(),687 <ScheduledCall<Test>>::new(call.clone()).unwrap(),688 )689 .unwrap();690 // Cancel the call.691 assert_ok!(Scheduler::do_cancel(None, addr_1));692 let addr_2 = Scheduler::do_schedule(693 DispatchTime::At(4),694 None,695 127,696 root(),697 <ScheduledCall<Test>>::new(call).unwrap(),698 )699 .unwrap();700701 // Should not re-use the address.702 assert!(addr_1 != addr_2);703 });704}705706#[test]707fn schedule_agenda_overflows() {708 let max: u32 = <Test as Config>::MaxScheduledPerBlock::get();709710 new_test_ext().execute_with(|| {711 let call =712 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });713 let call = <ScheduledCall<Test>>::new(call).unwrap();714715 // Schedule the maximal number allowed per block.716 for _ in 0..max {717 Scheduler::do_schedule(718 DispatchTime::At(4),719 None,720 127,721 root(),722 call.clone(),723 )724 .unwrap();725 }726727 // One more time and it errors.728 assert_noop!(729 Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call,),730 <Error<Test>>::AgendaIsExhausted,731 );732733 run_to_block(4);734 // All scheduled calls are executed.735 assert_eq!(logger::log().len() as u32, max);736 });737}738739/// Cancelling and scheduling does not overflow the agenda but fills holes.740#[test]741fn cancel_and_schedule_fills_holes() {742 let max: u32 = <Test as Config>::MaxScheduledPerBlock::get();743 assert!(max > 3, "This test only makes sense for MaxScheduledPerBlock > 3");744745 new_test_ext().execute_with(|| {746 let call =747 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });748 let call = <ScheduledCall<Test>>::new(call).unwrap();749 let mut addrs = Vec::<_>::default();750751 // Schedule the maximal number allowed per block.752 for _ in 0..max {753 addrs.push(754 Scheduler::do_schedule(755 DispatchTime::At(4),756 None,757 127,758 root(),759 call.clone(),760 )761 .unwrap(),762 );763 }764 // Cancel three of them.765 for addr in addrs.into_iter().take(3) {766 Scheduler::do_cancel(None, addr).unwrap();767 }768 // Schedule three new ones.769 for i in 0..3 {770 let (_block, index) = Scheduler::do_schedule(771 DispatchTime::At(4),772 None,773 127,774 root(),775 call.clone(),776 )777 .unwrap();778 assert_eq!(i, index);779 }780781 run_to_block(4);782 // Maximum number of calls are executed.783 assert_eq!(logger::log().len() as u32, max);784 });785}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license:18// This file is part of Substrate.1920// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd.21// SPDX-License-Identifier: Apache-2.02223// Licensed under the Apache License, Version 2.0 (the "License");24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at26//27// http://www.apache.org/licenses/LICENSE-2.028//29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and33// limitations under the License.3435//! # Scheduler tests.3637use super::*;38use crate::mock::{39 logger, new_test_ext, root, run_to_block, LoggerCall, RuntimeCall, Scheduler, Test, *,40};41use frame_support::{42 assert_noop, assert_ok,43 traits::{Contains, OnInitialize},44};4546#[test]47fn basic_scheduling_works() {48 new_test_ext().execute_with(|| {49 let call =50 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });51 assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));52 assert_ok!(Scheduler::do_schedule(53 DispatchTime::At(4),54 None,55 127,56 root(),57 <ScheduledCall<Test>>::new(call).unwrap(),58 ));59 run_to_block(3);60 assert!(logger::log().is_empty());61 run_to_block(4);62 assert_eq!(logger::log(), vec![(root(), 42u32)]);63 run_to_block(100);64 assert_eq!(logger::log(), vec![(root(), 42u32)]);65 });66}6768#[test]69fn schedule_after_works() {70 new_test_ext().execute_with(|| {71 run_to_block(2);72 let call =73 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });74 assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));75 // This will schedule the call 3 blocks after the next block... so block 3 + 3 = 676 assert_ok!(Scheduler::do_schedule(77 DispatchTime::After(3),78 None,79 127,80 root(),81 <ScheduledCall<Test>>::new(call).unwrap(),82 ));83 run_to_block(5);84 assert!(logger::log().is_empty());85 run_to_block(6);86 assert_eq!(logger::log(), vec![(root(), 42u32)]);87 run_to_block(100);88 assert_eq!(logger::log(), vec![(root(), 42u32)]);89 });90}9192#[test]93fn schedule_after_zero_works() {94 new_test_ext().execute_with(|| {95 run_to_block(2);96 let call =97 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });98 assert!(!<Test as frame_system::Config>::BaseCallFilter::contains(&call));99 assert_ok!(Scheduler::do_schedule(100 DispatchTime::After(0),101 None,102 127,103 root(),104 <ScheduledCall<Test>>::new(call).unwrap(),105 ));106 // Will trigger on the next block.107 run_to_block(3);108 assert_eq!(logger::log(), vec![(root(), 42u32)]);109 run_to_block(100);110 assert_eq!(logger::log(), vec![(root(), 42u32)]);111 });112}113114#[test]115fn periodic_scheduling_works() {116 new_test_ext().execute_with(|| {117 // at #4, every 3 blocks, 3 times.118 assert_ok!(Scheduler::do_schedule(119 DispatchTime::At(4),120 Some((3, 3)),121 127,122 root(),123 <ScheduledCall<Test>>::new(RuntimeCall::Logger(logger::Call::log {124 i: 42,125 weight: Weight::from_ref_time(10)126 }))127 .unwrap()128 ));129 run_to_block(3);130 assert!(logger::log().is_empty());131 run_to_block(4);132 assert_eq!(logger::log(), vec![(root(), 42u32)]);133 run_to_block(6);134 assert_eq!(logger::log(), vec![(root(), 42u32)]);135 run_to_block(7);136 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]);137 run_to_block(9);138 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]);139 run_to_block(10);140 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]);141 run_to_block(100);142 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)]);143 });144}145146#[test]147fn cancel_named_scheduling_works_with_normal_cancel() {148 new_test_ext().execute_with(|| {149 // at #4.150 Scheduler::do_schedule_named(151 [1u8; 32],152 DispatchTime::At(4),153 None,154 127,155 root(),156 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {157 i: 69,158 weight: Weight::from_ref_time(10),159 }))160 .unwrap(),161 )162 .unwrap();163 let i = Scheduler::do_schedule(164 DispatchTime::At(4),165 None,166 127,167 root(),168 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {169 i: 42,170 weight: Weight::from_ref_time(10),171 }))172 .unwrap(),173 )174 .unwrap();175 run_to_block(3);176 assert!(logger::log().is_empty());177 assert_ok!(Scheduler::do_cancel_named(None, [1u8; 32]));178 assert_ok!(Scheduler::do_cancel(None, i));179 run_to_block(100);180 assert!(logger::log().is_empty());181 });182}183184#[test]185fn cancel_named_periodic_scheduling_works() {186 new_test_ext().execute_with(|| {187 // at #4, every 3 blocks, 3 times.188 Scheduler::do_schedule_named(189 [1u8; 32],190 DispatchTime::At(4),191 Some((3, 3)),192 127,193 root(),194 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {195 i: 42,196 weight: Weight::from_ref_time(10),197 }))198 .unwrap(),199 )200 .unwrap();201 // same id results in error.202 assert!(Scheduler::do_schedule_named(203 [1u8; 32],204 DispatchTime::At(4),205 None,206 127,207 root(),208 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {209 i: 69,210 weight: Weight::from_ref_time(10)211 }))212 .unwrap(),213 )214 .is_err());215 // different id is ok.216 Scheduler::do_schedule_named(217 [2u8; 32],218 DispatchTime::At(8),219 None,220 127,221 root(),222 <ScheduledCall<Test>>::new(RuntimeCall::Logger(LoggerCall::log {223 i: 69,224 weight: Weight::from_ref_time(10),225 }))226 .unwrap(),227 )228 .unwrap();229 run_to_block(3);230 assert!(logger::log().is_empty());231 run_to_block(4);232 assert_eq!(logger::log(), vec![(root(), 42u32)]);233 run_to_block(6);234 assert_ok!(Scheduler::do_cancel_named(None, [1u8; 32]));235 run_to_block(100);236 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]);237 });238}239240#[test]241fn scheduler_respects_weight_limits() {242 let max_weight: Weight = <Test as Config>::MaximumWeight::get();243 new_test_ext().execute_with(|| {244 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 * 2 });245 assert_ok!(Scheduler::do_schedule(246 DispatchTime::At(4),247 None,248 127,249 root(),250 <ScheduledCall<Test>>::new(call).unwrap(),251 ));252 let call = RuntimeCall::Logger(LoggerCall::log { i: 69, weight: max_weight / 3 * 2 });253 assert_ok!(Scheduler::do_schedule(254 DispatchTime::At(4),255 None,256 127,257 root(),258 <ScheduledCall<Test>>::new(call).unwrap(),259 ));260 // 69 and 42 do not fit together261 run_to_block(4);262 assert_eq!(logger::log(), vec![(root(), 42u32)]);263 run_to_block(5);264 assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]);265 });266}267268/// Permanently overweight calls are not deleted but also not executed.269#[test]270fn scheduler_does_not_delete_permanently_overweight_call() {271 let max_weight: Weight = <Test as Config>::MaximumWeight::get();272 new_test_ext().execute_with(|| {273 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight });274 assert_ok!(Scheduler::do_schedule(275 DispatchTime::At(4),276 None,277 127,278 root(),279 <ScheduledCall<Test>>::new(call).unwrap(),280 ));281 // Never executes.282 run_to_block(100);283 assert_eq!(logger::log(), vec![]);284285 // Assert the `PermanentlyOverweight` event.286 assert_eq!(287 System::events().last().unwrap().event,288 crate::Event::PermanentlyOverweight { task: (4, 0), id: None }.into(),289 );290 // The call is still in the agenda.291 assert!(Agenda::<Test>::get(4)[0].is_some());292 });293}294295#[test]296fn scheduler_handles_periodic_failure() {297 let max_weight: Weight = <Test as Config>::MaximumWeight::get();298 let max_per_block = <Test as Config>::MaxScheduledPerBlock::get();299300 new_test_ext().execute_with(|| {301 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: (max_weight / 3) * 2 });302 let call = <ScheduledCall<Test>>::new(call).unwrap();303304 assert_ok!(Scheduler::do_schedule(305 DispatchTime::At(4),306 Some((4, u32::MAX)),307 127,308 root(),309 call.clone(),310 ));311 // Executes 5 times till block 20.312 run_to_block(20);313 assert_eq!(logger::log().len(), 5);314315 // Block 28 will already be full.316 for _ in 0..max_per_block {317 assert_ok!(Scheduler::do_schedule(318 DispatchTime::At(28),319 None,320 120,321 root(),322 call.clone(),323 ));324 }325326 // Going to block 24 will emit a `PeriodicFailed` event.327 run_to_block(24);328 assert_eq!(logger::log().len(), 6);329330 assert_eq!(331 System::events().last().unwrap().event,332 crate::Event::PeriodicFailed { task: (24, 0), id: None }.into(),333 );334 });335}336337#[test]338fn scheduler_respects_priority_ordering() {339 let max_weight: Weight = <Test as Config>::MaximumWeight::get();340 new_test_ext().execute_with(|| {341 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 });342 assert_ok!(Scheduler::do_schedule(343 DispatchTime::At(4),344 None,345 1,346 root(),347 <ScheduledCall<Test>>::new(call).unwrap(),348 ));349 let call = RuntimeCall::Logger(LoggerCall::log { i: 69, weight: max_weight / 3 });350 assert_ok!(Scheduler::do_schedule(351 DispatchTime::At(4),352 None,353 0,354 root(),355 <ScheduledCall<Test>>::new(call).unwrap(),356 ));357 run_to_block(4);358 assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]);359 });360}361362#[test]363fn scheduler_respects_priority_ordering_with_soft_deadlines() {364 new_test_ext().execute_with(|| {365 let max_weight: Weight = <Test as Config>::MaximumWeight::get();366 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 5 * 2 });367 assert_ok!(Scheduler::do_schedule(368 DispatchTime::At(4),369 None,370 255,371 root(),372 <ScheduledCall<Test>>::new(call).unwrap(),373 ));374 let call = RuntimeCall::Logger(LoggerCall::log { i: 69, weight: max_weight / 5 * 2 });375 assert_ok!(Scheduler::do_schedule(376 DispatchTime::At(4),377 None,378 127,379 root(),380 <ScheduledCall<Test>>::new(call).unwrap(),381 ));382 let call = RuntimeCall::Logger(LoggerCall::log { i: 2600, weight: max_weight / 5 * 4 });383 assert_ok!(Scheduler::do_schedule(384 DispatchTime::At(4),385 None,386 126,387 root(),388 <ScheduledCall<Test>>::new(call).unwrap(),389 ));390391 // 2600 does not fit with 69 or 42, but has higher priority, so will go through392 run_to_block(4);393 assert_eq!(logger::log(), vec![(root(), 2600u32)]);394 // 69 and 42 fit together395 run_to_block(5);396 assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]);397 });398}399400#[test]401fn on_initialize_weight_is_correct() {402 new_test_ext().execute_with(|| {403 let call_weight = Weight::from_ref_time(25);404405 // Named406 let call = RuntimeCall::Logger(LoggerCall::log {407 i: 3,408 weight: call_weight + Weight::from_ref_time(1),409 });410 assert_ok!(Scheduler::do_schedule_named(411 [1u8; 32],412 DispatchTime::At(3),413 None,414 255,415 root(),416 <ScheduledCall<Test>>::new(call).unwrap(),417 ));418 let call = RuntimeCall::Logger(LoggerCall::log {419 i: 42,420 weight: call_weight + Weight::from_ref_time(2),421 });422 // Anon Periodic423 assert_ok!(Scheduler::do_schedule(424 DispatchTime::At(2),425 Some((1000, 3)),426 128,427 root(),428 <ScheduledCall<Test>>::new(call).unwrap(),429 ));430 let call = RuntimeCall::Logger(LoggerCall::log {431 i: 69,432 weight: call_weight + Weight::from_ref_time(3),433 });434 // Anon435 assert_ok!(Scheduler::do_schedule(436 DispatchTime::At(2),437 None,438 127,439 root(),440 <ScheduledCall<Test>>::new(call).unwrap(),441 ));442 // Named Periodic443 let call = RuntimeCall::Logger(LoggerCall::log {444 i: 2600,445 weight: call_weight + Weight::from_ref_time(4),446 });447 assert_ok!(Scheduler::do_schedule_named(448 [2u8; 32],449 DispatchTime::At(1),450 Some((1000, 3)),451 126,452 root(),453 <ScheduledCall<Test>>::new(call).unwrap(),454 ));455456 // Will include the named periodic only457 assert_eq!(458 Scheduler::on_initialize(1),459 TestWeightInfo::service_agendas_base() +460 TestWeightInfo::service_agenda_base(1) +461 <TestWeightInfo as MarginalWeightInfo>::service_task(None, true, true) +462 TestWeightInfo::execute_dispatch_unsigned() +463 call_weight + Weight::from_ref_time(4)464 );465 assert_eq!(IncompleteSince::<Test>::get(), None);466 assert_eq!(logger::log(), vec![(root(), 2600u32)]);467468 // Will include anon and anon periodic469 assert_eq!(470 Scheduler::on_initialize(2),471 TestWeightInfo::service_agendas_base() +472 TestWeightInfo::service_agenda_base(2) +473 <TestWeightInfo as MarginalWeightInfo>::service_task(None, false, true) +474 TestWeightInfo::execute_dispatch_unsigned() +475 call_weight + Weight::from_ref_time(3) +476 <TestWeightInfo as MarginalWeightInfo>::service_task(None, false, false) +477 TestWeightInfo::execute_dispatch_unsigned() +478 call_weight + Weight::from_ref_time(2)479 );480 assert_eq!(IncompleteSince::<Test>::get(), None);481 assert_eq!(logger::log(), vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)]);482483 // Will include named only484 assert_eq!(485 Scheduler::on_initialize(3),486 TestWeightInfo::service_agendas_base() +487 TestWeightInfo::service_agenda_base(1) +488 <TestWeightInfo as MarginalWeightInfo>::service_task(None, true, false) +489 TestWeightInfo::execute_dispatch_unsigned() +490 call_weight + Weight::from_ref_time(1)491 );492 assert_eq!(IncompleteSince::<Test>::get(), None);493 assert_eq!(494 logger::log(),495 vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32), (root(), 3u32)]496 );497498 // Will contain none499 let actual_weight = Scheduler::on_initialize(4);500 assert_eq!(501 actual_weight,502 TestWeightInfo::service_agendas_base() + TestWeightInfo::service_agenda_base(0)503 );504 });505}506507#[test]508fn root_calls_works() {509 new_test_ext().execute_with(|| {510 let call = Box::new(RuntimeCall::Logger(LoggerCall::log {511 i: 69,512 weight: Weight::from_ref_time(10),513 }));514 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {515 i: 42,516 weight: Weight::from_ref_time(10),517 }));518 assert_ok!(519 Scheduler::schedule_named(RuntimeOrigin::root(), [1u8; 32], 4, None, Some(127), call,)520 );521 assert_ok!(Scheduler::schedule(RuntimeOrigin::root(), 4, None, Some(127), call2));522 run_to_block(3);523 // Scheduled calls are in the agenda.524 assert_eq!(Agenda::<Test>::get(4).len(), 2);525 assert!(logger::log().is_empty());526 assert_ok!(Scheduler::cancel_named(RuntimeOrigin::root(), [1u8; 32]));527 assert_ok!(Scheduler::cancel(RuntimeOrigin::root(), 4, 1));528 // Scheduled calls are made NONE, so should not effect state529 run_to_block(100);530 assert!(logger::log().is_empty());531 });532}533534#[test]535fn fails_to_schedule_task_in_the_past() {536 new_test_ext().execute_with(|| {537 run_to_block(3);538539 let call1 = Box::new(RuntimeCall::Logger(LoggerCall::log {540 i: 69,541 weight: Weight::from_ref_time(10),542 }));543 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {544 i: 42,545 weight: Weight::from_ref_time(10),546 }));547 let call3 = Box::new(RuntimeCall::Logger(LoggerCall::log {548 i: 42,549 weight: Weight::from_ref_time(10),550 }));551552 assert_noop!(553 Scheduler::schedule_named(RuntimeOrigin::root(), [1u8; 32], 2, None, Some(127), call1),554 Error::<Test>::TargetBlockNumberInPast,555 );556557 assert_noop!(558 Scheduler::schedule(RuntimeOrigin::root(), 2, None, Some(127), call2),559 Error::<Test>::TargetBlockNumberInPast,560 );561562 assert_noop!(563 Scheduler::schedule(RuntimeOrigin::root(), 3, None, Some(127), call3),564 Error::<Test>::TargetBlockNumberInPast,565 );566 });567}568569#[test]570fn should_use_origin() {571 new_test_ext().execute_with(|| {572 let call = Box::new(RuntimeCall::Logger(LoggerCall::log {573 i: 69,574 weight: Weight::from_ref_time(10),575 }));576 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {577 i: 42,578 weight: Weight::from_ref_time(10),579 }));580 assert_ok!(Scheduler::schedule_named(581 system::RawOrigin::Signed(1).into(),582 [1u8; 32],583 4,584 None,585 None,586 call,587 ));588 assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, None, call2,));589 run_to_block(3);590 // Scheduled calls are in the agenda.591 assert_eq!(Agenda::<Test>::get(4).len(), 2);592 assert!(logger::log().is_empty());593 assert_ok!(Scheduler::cancel_named(system::RawOrigin::Signed(1).into(), [1u8; 32]));594 assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1));595 // Scheduled calls are made NONE, so should not effect state596 run_to_block(100);597 assert!(logger::log().is_empty());598 });599}600601#[test]602fn should_check_origin() {603 new_test_ext().execute_with(|| {604 let call = Box::new(RuntimeCall::Logger(LoggerCall::log {605 i: 69,606 weight: Weight::from_ref_time(10),607 }));608 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log {609 i: 42,610 weight: Weight::from_ref_time(10),611 }));612 assert_noop!(613 Scheduler::schedule_named(614 system::RawOrigin::Signed(2).into(),615 [1u8; 32],616 4,617 None,618 None,619 call620 ),621 BadOrigin622 );623 assert_noop!(624 Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, None, call2),625 BadOrigin626 );627 });628}629630#[test]631fn should_check_origin_for_cancel() {632 new_test_ext().execute_with(|| {633 let call = Box::new(RuntimeCall::Logger(LoggerCall::log_without_filter {634 i: 69,635 weight: Weight::from_ref_time(10),636 }));637 let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log_without_filter {638 i: 42,639 weight: Weight::from_ref_time(10),640 }));641 assert_ok!(Scheduler::schedule_named(642 system::RawOrigin::Signed(1).into(),643 [1u8; 32],644 4,645 None,646 None,647 call,648 ));649 assert_ok!(Scheduler::schedule(system::RawOrigin::Signed(1).into(), 4, None, None, call2,));650 run_to_block(3);651 // Scheduled calls are in the agenda.652 assert_eq!(Agenda::<Test>::get(4).len(), 2);653 assert!(logger::log().is_empty());654 assert_noop!(655 Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), [1u8; 32]),656 BadOrigin657 );658 assert_noop!(Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), BadOrigin);659 assert_noop!(Scheduler::cancel_named(system::RawOrigin::Root.into(), [1u8; 32]), BadOrigin);660 assert_noop!(Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), BadOrigin);661 run_to_block(5);662 assert_eq!(663 logger::log(),664 vec![665 (system::RawOrigin::Signed(1).into(), 69u32),666 (system::RawOrigin::Signed(1).into(), 42u32)667 ]668 );669 });670}671672/// Cancelling a call and then scheduling a second call for the same673/// block results in different addresses.674#[test]675fn schedule_does_not_resuse_addr() {676 new_test_ext().execute_with(|| {677 let call =678 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });679680 // Schedule both calls.681 let addr_1 = Scheduler::do_schedule(682 DispatchTime::At(4),683 None,684 127,685 root(),686 <ScheduledCall<Test>>::new(call.clone()).unwrap(),687 )688 .unwrap();689 // Cancel the call.690 assert_ok!(Scheduler::do_cancel(None, addr_1));691 let addr_2 = Scheduler::do_schedule(692 DispatchTime::At(4),693 None,694 127,695 root(),696 <ScheduledCall<Test>>::new(call).unwrap(),697 )698 .unwrap();699700 // Should not re-use the address.701 assert!(addr_1 != addr_2);702 });703}704705#[test]706fn schedule_agenda_overflows() {707 let max: u32 = <Test as Config>::MaxScheduledPerBlock::get();708709 new_test_ext().execute_with(|| {710 let call =711 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });712 let call = <ScheduledCall<Test>>::new(call).unwrap();713714 // Schedule the maximal number allowed per block.715 for _ in 0..max {716 Scheduler::do_schedule(717 DispatchTime::At(4),718 None,719 127,720 root(),721 call.clone(),722 )723 .unwrap();724 }725726 // One more time and it errors.727 assert_noop!(728 Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call,),729 <Error<Test>>::AgendaIsExhausted,730 );731732 run_to_block(4);733 // All scheduled calls are executed.734 assert_eq!(logger::log().len() as u32, max);735 });736}737738/// Cancelling and scheduling does not overflow the agenda but fills holes.739#[test]740fn cancel_and_schedule_fills_holes() {741 let max: u32 = <Test as Config>::MaxScheduledPerBlock::get();742 assert!(max > 3, "This test only makes sense for MaxScheduledPerBlock > 3");743744 new_test_ext().execute_with(|| {745 let call =746 RuntimeCall::Logger(LoggerCall::log { i: 42, weight: Weight::from_ref_time(10) });747 let call = <ScheduledCall<Test>>::new(call).unwrap();748 let mut addrs = Vec::<_>::default();749750 // Schedule the maximal number allowed per block.751 for _ in 0..max {752 addrs.push(753 Scheduler::do_schedule(754 DispatchTime::At(4),755 None,756 127,757 root(),758 call.clone(),759 )760 .unwrap(),761 );762 }763 // Cancel three of them.764 for addr in addrs.into_iter().take(3) {765 Scheduler::do_cancel(None, addr).unwrap();766 }767 // Schedule three new ones.768 for i in 0..3 {769 let (_block, index) = Scheduler::do_schedule(770 DispatchTime::At(4),771 None,772 127,773 root(),774 call.clone(),775 )776 .unwrap();777 assert_eq!(i, index);778 }779780 run_to_block(4);781 // Maximum number of calls are executed.782 assert_eq!(logger::log().len() as u32, max);783 });784}