diff --git a/substrate/frame/message-queue/src/integration_test.rs b/substrate/frame/message-queue/src/integration_test.rs index 4fc639101a01f085fed5c7bfa7b556791282c4f2..a1003edf3c92f20e57142ecb978cc62cfef28a28 100644 --- a/substrate/frame/message-queue/src/integration_test.rs +++ b/substrate/frame/message-queue/src/integration_test.rs @@ -22,8 +22,8 @@ use crate::{ mock::{ - new_test_ext, CountingMessageProcessor, IntoWeight, MockedWeightInfo, NumMessagesProcessed, - YieldingQueues, + build_and_execute, CountingMessageProcessor, IntoWeight, MockedWeightInfo, + NumMessagesProcessed, YieldingQueues, }, mock_helpers::MessageOrigin, *, @@ -123,7 +123,7 @@ fn stress_test_enqueue_and_service() { let max_msg_len = MaxMessageLenOf::<Test>::get(); let mut rng = StdRng::seed_from_u64(42); - new_test_ext::<Test>().execute_with(|| { + build_and_execute::<Test>(|| { let mut msgs_remaining = 0; for _ in 0..blocks { // Start by enqueuing a large number of messages. @@ -171,7 +171,7 @@ fn stress_test_queue_suspension() { let max_msg_len = MaxMessageLenOf::<Test>::get(); let mut rng = StdRng::seed_from_u64(41); - new_test_ext::<Test>().execute_with(|| { + build_and_execute::<Test>(|| { let mut suspended = BTreeSet::<u32>::new(); let mut msgs_remaining = 0; diff --git a/substrate/frame/message-queue/src/lib.rs b/substrate/frame/message-queue/src/lib.rs index 08795914ebe788a4838d7a9ab85adc5425045bf0..5acc3e9d5a1385245e5fbe95305fd24ad2436cd5 100644 --- a/substrate/frame/message-queue/src/lib.rs +++ b/substrate/frame/message-queue/src/lib.rs @@ -578,7 +578,12 @@ pub mod pallet { } } - /// Check all assumptions about [`crate::Config`]. + #[cfg(feature = "try-runtime")] + fn try_state(_: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> { + Self::do_try_state() + } + + /// Check all compile-time assumptions about [`crate::Config`]. fn integrity_test() { assert!(!MaxMessageLenOf::<T>::get().is_zero(), "HeapSize too low"); } @@ -1105,6 +1110,106 @@ impl<T: Config> Pallet<T> { ItemExecutionStatus::Executed(is_processed) } + /// Ensure the correctness of state of this pallet. + /// + /// # Assumptions- + /// + /// If `serviceHead` points to a ready Queue, then BookState of that Queue has: + /// + /// * `message_count` > 0 + /// * `size` > 0 + /// * `end` > `begin` + /// * Some(ready_neighbours) + /// * If `ready_neighbours.next` == self.origin, then `ready_neighbours.prev` == self.origin + /// (only queue in ring) + /// + /// For Pages(begin to end-1) in BookState: + /// + /// * `remaining` > 0 + /// * `remaining_size` > 0 + /// * `first` <= `last` + /// * Every page can be decoded into peek_* functions + #[cfg(any(test, feature = "try-runtime"))] + pub fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> { + // Checking memory corruption for BookStateFor + ensure!( + BookStateFor::<T>::iter_keys().count() == BookStateFor::<T>::iter_values().count(), + "Memory Corruption in BookStateFor" + ); + // Checking memory corruption for Pages + ensure!( + Pages::<T>::iter_keys().count() == Pages::<T>::iter_values().count(), + "Memory Corruption in Pages" + ); + + // No state to check + if ServiceHead::<T>::get().is_none() { + return Ok(()) + } + + //loop around this origin + let starting_origin = ServiceHead::<T>::get().unwrap(); + + while let Some(head) = Self::bump_service_head(&mut WeightMeter::max_limit()) { + ensure!( + BookStateFor::<T>::contains_key(&head), + "Service head must point to an existing book" + ); + + let head_book_state = BookStateFor::<T>::get(&head); + ensure!( + head_book_state.message_count > 0, + "There must be some messages if in ReadyRing" + ); + ensure!(head_book_state.size > 0, "There must be some message size if in ReadyRing"); + ensure!( + head_book_state.end > head_book_state.begin, + "End > Begin if unprocessed messages exists" + ); + ensure!( + head_book_state.ready_neighbours.is_some(), + "There must be neighbours if in ReadyRing" + ); + + if head_book_state.ready_neighbours.as_ref().unwrap().next == head { + ensure!( + head_book_state.ready_neighbours.as_ref().unwrap().prev == head, + "Can only happen if only queue in ReadyRing" + ); + } + + for page_index in head_book_state.begin..head_book_state.end { + let page = Pages::<T>::get(&head, page_index).unwrap(); + let remaining_messages = page.remaining; + let mut counted_remaining_messages = 0; + ensure!( + remaining_messages > 0.into(), + "These must be some messages that have not been processed yet!" + ); + + for i in 0..u32::MAX { + if let Some((_, processed, _)) = page.peek_index(i as usize) { + if !processed { + counted_remaining_messages += 1; + } + } else { + break + } + } + + ensure!( + remaining_messages == counted_remaining_messages.into(), + "Memory Corruption" + ); + } + + if head_book_state.ready_neighbours.as_ref().unwrap().next == starting_origin { + break + } + } + Ok(()) + } + /// Print the pages in each queue and the messages in each page. /// /// Processed messages are prefixed with a `*` and the current `begin`ning page with a `>`. diff --git a/substrate/frame/message-queue/src/mock.rs b/substrate/frame/message-queue/src/mock.rs index 04b763d59cffdbc7d29f40da904191ce0512c48f..473c5faac4c5d045cc18cca43b88afd11325c2d0 100644 --- a/substrate/frame/message-queue/src/mock.rs +++ b/substrate/frame/message-queue/src/mock.rs @@ -295,10 +295,15 @@ where ext } -/// Run this closure in test externalities. -pub fn test_closure<R>(f: impl FnOnce() -> R) -> R { - let mut ext = new_test_ext::<Test>(); - ext.execute_with(f) +/// Run the function pointer inside externalities and asserts the try_state hook at the end. +pub fn build_and_execute<T: Config>(test: impl FnOnce() -> ()) +where + BlockNumberFor<T>: From<u32>, +{ + new_test_ext::<T>().execute_with(|| { + test(); + MessageQueue::do_try_state().expect("All invariants must hold after a test"); + }); } /// Set the weight of a specific weight function. diff --git a/substrate/frame/message-queue/src/mock_helpers.rs b/substrate/frame/message-queue/src/mock_helpers.rs index 4e3cb323be729d989230960b4c41de2d065527e2..f6109c127be123c427e075d78bf80fbe04baada3 100644 --- a/substrate/frame/message-queue/src/mock_helpers.rs +++ b/substrate/frame/message-queue/src/mock_helpers.rs @@ -89,7 +89,7 @@ pub fn page<T: Config>(msg: &[u8]) -> PageOf<T> { } pub fn single_page_book<T: Config>() -> BookStateOf<T> { - BookState { begin: 0, end: 1, count: 1, ..Default::default() } + BookState { begin: 0, end: 1, count: 1, message_count: 1, size: 1, ..Default::default() } } pub fn empty_book<T: Config>() -> BookStateOf<T> { @@ -139,10 +139,8 @@ pub fn setup_bump_service_head<T: Config>( current: <<T as Config>::MessageProcessor as ProcessMessage>::Origin, next: <<T as Config>::MessageProcessor as ProcessMessage>::Origin, ) { - let mut book = single_page_book::<T>(); - book.ready_neighbours = Some(Neighbours::<MessageOriginOf<T>> { prev: next.clone(), next }); - ServiceHead::<T>::put(¤t); - BookStateFor::<T>::insert(¤t, &book); + crate::Pallet::<T>::enqueue_message(msg("1"), current); + crate::Pallet::<T>::enqueue_message(msg("1"), next); } /// Knit a queue into the ready-ring and write it back to storage. @@ -164,11 +162,8 @@ pub fn unknit<T: Config>(o: &<<T as Config>::MessageProcessor as ProcessMessage> pub fn build_ring<T: Config>( queues: &[<<T as Config>::MessageProcessor as ProcessMessage>::Origin], ) { - for queue in queues { - BookStateFor::<T>::insert(queue, empty_book::<T>()); - } - for queue in queues { - knit::<T>(queue); + for queue in queues.iter() { + crate::Pallet::<T>::enqueue_message(msg("1"), queue.clone()); } assert_ring::<T>(queues); } diff --git a/substrate/frame/message-queue/src/tests.rs b/substrate/frame/message-queue/src/tests.rs index 7b7b51efc66f2ab6fdb42e98d94d6129906bb7ac..bcb099a6accd12b29abe5a6865e551fab5c23627 100644 --- a/substrate/frame/message-queue/src/tests.rs +++ b/substrate/frame/message-queue/src/tests.rs @@ -27,22 +27,22 @@ use sp_core::blake2_256; #[test] fn mocked_weight_works() { - test_closure(|| { + build_and_execute::<Test>(|| { assert!(<Test as Config>::WeightInfo::service_queue_base().is_zero()); }); - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_queue_base", Weight::MAX); assert_eq!(<Test as Config>::WeightInfo::service_queue_base(), Weight::MAX); }); // The externalities reset it. - test_closure(|| { + build_and_execute::<Test>(|| { assert!(<Test as Config>::WeightInfo::service_queue_base().is_zero()); }); } #[test] fn enqueue_within_one_page_works() { - test_closure(|| { + build_and_execute::<Test>(|| { use MessageOrigin::*; MessageQueue::enqueue_message(msg("a"), Here); MessageQueue::enqueue_message(msg("b"), Here); @@ -77,7 +77,7 @@ fn enqueue_within_one_page_works() { #[test] fn queue_priority_retains() { - test_closure(|| { + build_and_execute::<Test>(|| { use MessageOrigin::*; assert_ring(&[]); MessageQueue::enqueue_message(msg("a"), Everywhere(1)); @@ -108,11 +108,13 @@ fn queue_priority_retains() { #[test] fn queue_priority_reset_once_serviced() { - test_closure(|| { + build_and_execute::<Test>(|| { use MessageOrigin::*; MessageQueue::enqueue_message(msg("a"), Everywhere(1)); MessageQueue::enqueue_message(msg("b"), Everywhere(2)); MessageQueue::enqueue_message(msg("c"), Everywhere(3)); + MessageQueue::do_try_state().unwrap(); + println!("{}", MessageQueue::debug_info()); // service head is 1, it will process a, leaving service head at 2. it also processes b and // empties queue 2, so service head will end at 3. assert_eq!(MessageQueue::service_queues(2.into_weight()), 2.into_weight()); @@ -135,7 +137,7 @@ fn queue_priority_reset_once_serviced() { #[test] fn service_queues_basic_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { MessageQueue::enqueue_messages(vec![msg("a"), msg("ab"), msg("abc")].into_iter(), Here); MessageQueue::enqueue_messages(vec![msg("x"), msg("xy"), msg("xyz")].into_iter(), There); assert_eq!(QueueChanges::take(), vec![(Here, 3, 6), (There, 3, 6)]); @@ -159,13 +161,14 @@ fn service_queues_basic_works() { assert_eq!(MessageQueue::service_queues(Weight::MAX), 2.into_weight()); assert_eq!(MessagesProcessed::take(), vec![(vmsg("xy"), There), (vmsg("xyz"), There)]); assert_eq!(QueueChanges::take(), vec![(There, 0, 0)]); + MessageQueue::do_try_state().unwrap(); }); } #[test] fn service_queues_failing_messages_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_page_item", 1.into_weight()); MessageQueue::enqueue_message(msg("badformat"), Here); MessageQueue::enqueue_message(msg("corrupt"), Here); @@ -211,7 +214,7 @@ fn service_queues_failing_messages_works() { #[test] fn service_queues_suspension_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { MessageQueue::enqueue_messages(vec![msg("a"), msg("b"), msg("c")].into_iter(), Here); MessageQueue::enqueue_messages(vec![msg("x"), msg("y"), msg("z")].into_iter(), There); MessageQueue::enqueue_messages( @@ -266,7 +269,7 @@ fn service_queues_suspension_works() { #[test] fn reap_page_permanent_overweight_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { // Create 10 pages more than the stale limit. let n = (MaxStale::get() + 10) as usize; for _ in 0..n { @@ -306,7 +309,7 @@ fn reaping_overweight_fails_properly() { use MessageOrigin::*; assert_eq!(MaxStale::get(), 2, "The stale limit is two"); - test_closure(|| { + build_and_execute::<Test>(|| { // page 0 MessageQueue::enqueue_message(msg("weight=4"), Here); MessageQueue::enqueue_message(msg("a"), Here); @@ -376,7 +379,7 @@ fn reaping_overweight_fails_properly() { #[test] fn service_queue_bails() { // Not enough weight for `service_queue_base`. - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_queue_base", 2.into_weight()); let mut meter = WeightMeter::from_limit(1.into_weight()); @@ -384,7 +387,7 @@ fn service_queue_bails() { assert!(meter.consumed().is_zero()); }); // Not enough weight for `ready_ring_unknit`. - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("ready_ring_unknit", 2.into_weight()); let mut meter = WeightMeter::from_limit(1.into_weight()); @@ -392,7 +395,7 @@ fn service_queue_bails() { assert!(meter.consumed().is_zero()); }); // Not enough weight for `service_queue_base` and `ready_ring_unknit`. - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_queue_base", 2.into_weight()); set_weight("ready_ring_unknit", 2.into_weight()); @@ -407,7 +410,7 @@ fn service_page_works() { use super::integration_test::Test; // Run with larger page size. use MessageOrigin::*; use PageExecutionStatus::*; - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_page_base_completion", 2.into_weight()); set_weight("service_page_item", 3.into_weight()); @@ -444,7 +447,7 @@ fn service_page_works() { #[test] fn service_page_bails() { // Not enough weight for `service_page_base_completion`. - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_page_base_completion", 2.into_weight()); let mut meter = WeightMeter::from_limit(1.into_weight()); @@ -461,7 +464,7 @@ fn service_page_bails() { assert!(meter.consumed().is_zero()); }); // Not enough weight for `service_page_base_no_completion`. - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("service_page_base_no_completion", 2.into_weight()); let mut meter = WeightMeter::from_limit(1.into_weight()); @@ -481,7 +484,7 @@ fn service_page_bails() { #[test] fn service_page_item_bails() { - test_closure(|| { + build_and_execute::<Test>(|| { let _guard = StorageNoopGuard::default(); let (mut page, _) = full_page::<Test>(); let mut weight = WeightMeter::from_limit(10.into_weight()); @@ -508,7 +511,7 @@ fn service_page_suspension_works() { use MessageOrigin::*; use PageExecutionStatus::*; - test_closure(|| { + build_and_execute::<Test>(|| { let (page, mut msgs) = full_page::<Test>(); assert!(msgs >= 10, "pre-condition: need at least 10 msgs per page"); let mut book = book_for::<Test>(&page); @@ -556,14 +559,8 @@ fn service_page_suspension_works() { #[test] fn bump_service_head_works() { use MessageOrigin::*; - test_closure(|| { - // Create a ready ring with three queues. - BookStateFor::<Test>::insert(Here, empty_book::<Test>()); - knit(&Here); - BookStateFor::<Test>::insert(There, empty_book::<Test>()); - knit(&There); - BookStateFor::<Test>::insert(Everywhere(0), empty_book::<Test>()); - knit(&Everywhere(0)); + build_and_execute::<Test>(|| { + build_triple_ring(); // Bump 99 times. for i in 0..99 { @@ -579,9 +576,9 @@ fn bump_service_head_works() { /// `bump_service_head` does nothing when called with an insufficient weight limit. #[test] fn bump_service_head_bails() { - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("bump_service_head", 2.into_weight()); - setup_bump_service_head::<Test>(0.into(), 10.into()); + setup_bump_service_head::<Test>(0.into(), 1.into()); let _guard = StorageNoopGuard::default(); let mut meter = WeightMeter::from_limit(1.into_weight()); @@ -592,7 +589,7 @@ fn bump_service_head_bails() { #[test] fn bump_service_head_trivial_works() { - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("bump_service_head", 2.into_weight()); let mut meter = WeightMeter::max_limit(); @@ -605,22 +602,15 @@ fn bump_service_head_trivial_works() { assert_eq!(ServiceHead::<Test>::get().unwrap(), 1.into(), "Bumped the head"); assert_eq!(meter.consumed(), 4.into_weight()); - assert_eq!(MessageQueue::bump_service_head(&mut meter), None, "Cannot bump"); + assert_eq!(MessageQueue::bump_service_head(&mut meter), Some(1.into()), "Its a ring"); assert_eq!(meter.consumed(), 6.into_weight()); }); } #[test] fn bump_service_head_no_head_noops() { - use MessageOrigin::*; - test_closure(|| { - // Create a ready ring with three queues. - BookStateFor::<Test>::insert(Here, empty_book::<Test>()); - knit(&Here); - BookStateFor::<Test>::insert(There, empty_book::<Test>()); - knit(&There); - BookStateFor::<Test>::insert(Everywhere(0), empty_book::<Test>()); - knit(&Everywhere(0)); + build_and_execute::<Test>(|| { + build_triple_ring(); // But remove the service head. ServiceHead::<Test>::kill(); @@ -632,7 +622,7 @@ fn bump_service_head_no_head_noops() { #[test] fn service_page_item_consumes_correct_weight() { - test_closure(|| { + build_and_execute::<Test>(|| { let mut page = page::<Test>(b"weight=3"); let mut weight = WeightMeter::from_limit(10.into_weight()); let overweight_limit = 0.into_weight(); @@ -656,7 +646,7 @@ fn service_page_item_consumes_correct_weight() { /// `service_page_item` skips a permanently `Overweight` message and marks it as `unprocessed`. #[test] fn service_page_item_skips_perm_overweight_message() { - test_closure(|| { + build_and_execute::<Test>(|| { let mut page = page::<Test>(b"TooMuch"); let mut weight = WeightMeter::from_limit(2.into_weight()); let overweight_limit = 0.into_weight(); @@ -695,7 +685,7 @@ fn service_page_item_skips_perm_overweight_message() { #[test] fn peek_index_works() { use super::integration_test::Test; // Run with larger page size. - test_closure(|| { + build_and_execute::<Test>(|| { // Fill a page with messages. let (mut page, msgs) = full_page::<Test>(); let msg_enc_len = ItemHeader::<<Test as Config>::Size>::max_encoded_len() + 4; @@ -716,7 +706,7 @@ fn peek_index_works() { #[test] fn peek_first_and_skip_first_works() { use super::integration_test::Test; // Run with larger page size. - test_closure(|| { + build_and_execute::<Test>(|| { // Fill a page with messages. let (mut page, msgs) = full_page::<Test>(); @@ -739,7 +729,7 @@ fn peek_first_and_skip_first_works() { #[test] fn note_processed_at_pos_works() { use super::integration_test::Test; // Run with larger page size. - test_closure(|| { + build_and_execute::<Test>(|| { let (mut page, msgs) = full_page::<Test>(); for i in 0..msgs { @@ -775,7 +765,7 @@ fn note_processed_at_pos_idempotent() { #[test] fn is_complete_works() { use super::integration_test::Test; // Run with larger page size. - test_closure(|| { + build_and_execute::<Test>(|| { let (mut page, msgs) = full_page::<Test>(); assert!(msgs > 3, "Boring"); let msg_enc_len = ItemHeader::<<Test as Config>::Size>::max_encoded_len() + 4; @@ -931,8 +921,9 @@ fn page_from_message_max_len_works() { #[test] fn sweep_queue_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { build_triple_ring(); + QueueChanges::take(); let book = BookStateFor::<Test>::get(Here); assert!(book.begin != book.end); @@ -967,9 +958,8 @@ fn sweep_queue_works() { #[test] fn sweep_queue_wraps_works() { use MessageOrigin::*; - test_closure(|| { - BookStateFor::<Test>::insert(Here, empty_book::<Test>()); - knit(&Here); + build_and_execute::<Test>(|| { + build_ring::<Test>(&[Here]); MessageQueue::sweep_queue(Here); let book = BookStateFor::<Test>::get(Here); @@ -980,14 +970,14 @@ fn sweep_queue_wraps_works() { #[test] fn sweep_queue_invalid_noops() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { assert_storage_noop!(MessageQueue::sweep_queue(Here)); }); } #[test] fn footprint_works() { - test_closure(|| { + build_and_execute::<Test>(|| { let origin = MessageOrigin::Here; let (page, msgs) = full_page::<Test>(); let book = book_for::<Test>(&page); @@ -1005,7 +995,7 @@ fn footprint_works() { /// The footprint of an invalid queue is the default footprint. #[test] fn footprint_invalid_works() { - test_closure(|| { + build_and_execute::<Test>(|| { let origin = MessageOrigin::Here; assert_eq!(MessageQueue::footprint(origin), Default::default()); }) @@ -1015,7 +1005,7 @@ fn footprint_invalid_works() { #[test] fn footprint_on_swept_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { let mut book = empty_book::<Test>(); book.message_count = 3; book.size = 10; @@ -1031,7 +1021,7 @@ fn footprint_on_swept_works() { #[test] fn execute_overweight_works() { - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("bump_service_head", 1.into_weight()); set_weight("service_queue_base", 1.into_weight()); set_weight("service_page_base_completion", 1.into_weight()); @@ -1091,7 +1081,7 @@ fn execute_overweight_works() { fn permanently_overweight_book_unknits() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("bump_service_head", 1.into_weight()); set_weight("service_queue_base", 1.into_weight()); set_weight("service_page_base_completion", 1.into_weight()); @@ -1128,7 +1118,7 @@ fn permanently_overweight_book_unknits() { fn permanently_overweight_book_unknits_multiple() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { set_weight("bump_service_head", 1.into_weight()); set_weight("service_queue_base", 1.into_weight()); set_weight("service_page_base_completion", 1.into_weight()); @@ -1167,7 +1157,7 @@ fn permanently_overweight_book_unknits_multiple() { fn ready_but_empty_does_not_panic() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { BookStateFor::<Test>::insert(Here, empty_book::<Test>()); BookStateFor::<Test>::insert(There, empty_book::<Test>()); @@ -1187,7 +1177,7 @@ fn ready_but_empty_does_not_panic() { fn ready_but_perm_overweight_does_not_panic() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { MessageQueue::enqueue_message(msg("weight=9"), Here); assert_eq!(MessageQueue::service_queues(8.into_weight()), 0.into_weight()); assert_ring(&[]); @@ -1207,7 +1197,7 @@ fn ready_but_perm_overweight_does_not_panic() { fn ready_ring_knit_basic_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { BookStateFor::<Test>::insert(Here, empty_book::<Test>()); for i in 0..10 { @@ -1227,7 +1217,7 @@ fn ready_ring_knit_basic_works() { fn ready_ring_knit_and_unknit_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { // Place three queues into the storage. BookStateFor::<Test>::insert(Here, empty_book::<Test>()); BookStateFor::<Test>::insert(There, empty_book::<Test>()); @@ -1261,7 +1251,7 @@ fn enqueue_message_works() { let max_msg_per_page = <Test as Config>::HeapSize::get() as u64 / (ItemHeader::<<Test as Config>::Size>::max_encoded_len() as u64 + 1); - test_closure(|| { + build_and_execute::<Test>(|| { // Enqueue messages which should fill three pages. let n = max_msg_per_page * 3; for i in 1..=n { @@ -1291,7 +1281,7 @@ fn enqueue_messages_works() { let max_msg_per_page = <Test as Config>::HeapSize::get() as u64 / (ItemHeader::<<Test as Config>::Size>::max_encoded_len() as u64 + 1); - test_closure(|| { + build_and_execute::<Test>(|| { // Enqueue messages which should fill three pages. let n = max_msg_per_page * 3; let msgs = vec![msg("a"); n as usize]; @@ -1320,7 +1310,7 @@ fn enqueue_messages_works() { #[test] fn service_queues_suspend_works() { use MessageOrigin::*; - test_closure(|| { + build_and_execute::<Test>(|| { MessageQueue::enqueue_messages(vec![msg("a"), msg("ab"), msg("abc")].into_iter(), Here); MessageQueue::enqueue_messages(vec![msg("x"), msg("xy"), msg("xyz")].into_iter(), There); assert_eq!(QueueChanges::take(), vec![(Here, 3, 6), (There, 3, 6)]); @@ -1387,7 +1377,7 @@ fn service_queues_suspend_works() { /// Tests that manual overweight execution on a suspended queue errors with `QueueSuspended`. #[test] fn execute_overweight_respects_suspension() { - test_closure(|| { + build_and_execute::<Test>(|| { let origin = MessageOrigin::Here; MessageQueue::enqueue_message(msg("weight=5"), origin); // Mark the message as permanently overweight. @@ -1433,7 +1423,7 @@ fn execute_overweight_respects_suspension() { #[test] fn service_queue_suspension_ready_ring_works() { - test_closure(|| { + build_and_execute::<Test>(|| { let origin = MessageOrigin::Here; PausedQueues::set(vec![origin]); MessageQueue::enqueue_message(msg("weight=5"), origin);