From d52e3c24353dbaea8b55d078cc421a501a071cc4 Mon Sep 17 00:00:00 2001 From: Bert Date: Wed, 27 Apr 2022 00:17:16 +0200 Subject: [PATCH 1/3] GH-595: first, probably wrong version --- node/src/accountant/tools.rs | 10 ++-- node/src/sub_lib/utils.rs | 107 +++++++++++++++++++++++++++++------ node/src/test_utils/mod.rs | 23 +++++--- 3 files changed, 109 insertions(+), 31 deletions(-) diff --git a/node/src/accountant/tools.rs b/node/src/accountant/tools.rs index 293fe6c72..6db991cfb 100644 --- a/node/src/accountant/tools.rs +++ b/node/src/accountant/tools.rs @@ -125,11 +125,11 @@ pub(in crate::accountant) mod accountant_tools { #[derive(Default)] pub struct TransactionConfirmationTools { pub notify_later_scan_for_pending_payable: - Box>, - pub notify_later_scan_for_payable: Box>, - pub notify_later_scan_for_receivable: Box>, - pub notify_confirm_transaction: Box>, - pub notify_cancel_failed_transaction: Box>, + Box>, + pub notify_later_scan_for_payable: Box>, + pub notify_later_scan_for_receivable: Box>, + pub notify_confirm_transaction: Box>, + pub notify_cancel_failed_transaction: Box>, pub request_transaction_receipts_subs_opt: Option>, } } diff --git a/node/src/sub_lib/utils.rs b/node/src/sub_lib/utils.rs index 3de4920d8..e144f0198 100644 --- a/node/src/sub_lib/utils.rs +++ b/node/src/sub_lib/utils.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use actix::{Message, SpawnHandle}; +use actix::{Actor, AsyncContext, Context, Handler, Message, SpawnHandle}; use clap::App; use masq_lib::logger::Logger; use masq_lib::messages::{FromMessageBody, UiCrashRequest}; @@ -139,12 +139,12 @@ fn crash_request_analyzer( } } -pub trait NotifyLaterHandle { - fn notify_later<'a>( - &'a self, +pub trait NotifyLaterHandle>> { + fn notify_later( + &self, msg: T, interval: Duration, - closure: Box SpawnHandle + 'a>, + ctx: &mut Context, ) -> SpawnHandle; as_any_dcl!(); } @@ -153,7 +153,10 @@ pub struct NotifyLaterHandleReal { phantom: PhantomData, } -impl Default for Box> { +impl Default for Box> +where M: Message + 'static, + A: Actor> + Handler +{ fn default() -> Self { Box::new(NotifyLaterHandleReal { phantom: PhantomData::default(), @@ -161,24 +164,30 @@ impl Default for Box> { } } -impl NotifyLaterHandle for NotifyLaterHandleReal { - fn notify_later<'a>( - &'a self, - msg: T, +impl NotifyLaterHandle for NotifyLaterHandleReal +where M: Message + 'static, + A: Actor> + Handler +{ + fn notify_later( + &self, + msg: M, interval: Duration, - mut closure: Box SpawnHandle + 'a>, + ctx: &mut Context ) -> SpawnHandle { - closure(msg, interval) + ctx.notify_later(msg,interval) } as_any_impl!(); } -pub trait NotifyHandle { - fn notify<'a>(&'a self, msg: T, closure: Box); +pub trait NotifyHandle>> { + fn notify<'a>(&'a self, msg: T, ctx: &'a mut Context); as_any_dcl!(); } -impl Default for Box> { +impl Default for Box> +where M: Message + 'static, + A: Actor> + Handler +{ fn default() -> Self { Box::new(NotifyHandleReal { phantom: PhantomData::default(), @@ -190,9 +199,11 @@ pub struct NotifyHandleReal { phantom: PhantomData, } -impl NotifyHandle for NotifyHandleReal { - fn notify<'a>(&'a self, msg: T, mut closure: Box) { - closure(msg) +impl NotifyHandle for NotifyHandleReal +where M: Message + 'static, + A: Actor> + Handler { + fn notify<'a>(&'a self, msg: M, ctx: &'a mut Context) { + ctx.notify(msg) } as_any_impl!(); } @@ -207,12 +218,15 @@ pub fn make_new_test_multi_config<'a>( #[cfg(test)] mod tests { + use std::ops::Add; + use actix::{Addr, AsyncContext, Handler, Running, System}; use super::*; use crate::apps::app_node; use log::Level; use masq_lib::messages::ToMessageBody; use masq_lib::multi_config::CommandLineVcl; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; + use crate::sub_lib::peer_actors::StartMessage; #[test] fn indicates_dead_stream_identifies_dead_stream_errors() { @@ -375,4 +389,61 @@ mod tests { let _ = make_new_multi_config(&app, vcls); } + + struct NotifyHandlesTestActor { + notify_later_handle_real_opt: Option>, + notify_handle_real_opt: Option> + } + + impl Actor for NotifyHandlesTestActor { + type Context = Context; + + fn started(&mut self, ctx: &mut Self::Context) { + if let Some(handle) = self.notify_handle_real_opt.as_ref(){ + handle.notify(NotifyHandlesProbeMessage::new(None),ctx); + } else if let Some(handle) = self.notify_later_handle_real_opt.as_ref(){ + let interval = Duration::from_millis(333); + handle.notify_later(NotifyHandlesProbeMessage::new(Some(interval)),interval,ctx); + } else { + panic!( "One handle must be picked to be tested!") + } + } + } + + #[derive(Message)] + struct NotifyHandlesProbeMessage{ + interval_opt: Option, + start_time: SystemTime + } + + impl NotifyHandlesProbeMessage{ + fn new(interval_opt: Option)->Self{ + Self{ interval_opt, start_time: SystemTime::now() } + } + } + + impl Handler for NotifyHandlesTestActor{ + type Result = (); + + fn handle(&mut self, msg: NotifyHandlesProbeMessage, ctx: &mut Self::Context) -> Self::Result { + let now = SystemTime::now(); + let start_time = msg.start_time; + if let Some(interval) = msg.interval_opt { + assert!(now > start_time.add(interval)) + } else { + let with_margin = start_time * 1.3; + assert!(with_margin > now) + } + System::current().stop() + } + } + + #[test] + fn notify_handle_real_sends_the_message_correctly(){ + let test_actor = NotifyHandlesTestActor{ notify_later_handle_real_opt: None, notify_handle_real_opt: Some(Default::default()) }; + let address = test_actor.start(); + let system = System::new("notify_handle_test"); + + assert_eq!(system.run(),0) + } } diff --git a/node/src/test_utils/mod.rs b/node/src/test_utils/mod.rs index cde71c74d..0c3b5b128 100644 --- a/node/src/test_utils/mod.rs +++ b/node/src/test_utils/mod.rs @@ -516,7 +516,7 @@ pub mod unshared_test_utils { use crate::sub_lib::neighborhood::DEFAULT_RATE_PACK; use crate::sub_lib::utils::{NotifyHandle, NotifyLaterHandle}; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; - use actix::{Actor, Addr, Context, Handler, System}; + use actix::{Actor, Addr, AsyncContext, Context, Handler, System}; use actix::{Message, SpawnHandle}; use crossbeam_channel::{Receiver, Sender}; use masq_lib::messages::{ToMessageBody, UiCrashRequest}; @@ -731,12 +731,15 @@ pub mod unshared_test_utils { } } - impl NotifyLaterHandle for NotifyLaterHandleMock { + impl NotifyLaterHandle for NotifyLaterHandleMock + where M: Message + Clone, + A: Actor> + { fn notify_later<'a>( &'a self, - msg: T, + msg: M, interval: Duration, - mut closure: Box SpawnHandle + 'a>, + ctx:&'a mut Context , ) -> SpawnHandle { self.notify_later_params .lock() @@ -745,7 +748,8 @@ pub mod unshared_test_utils { if !cfg!(test) { panic!("this shouldn't run outside a test") } - closure(msg, interval) + ctx.notify_later(msg,interval) + //TODO what about adding conditional sending? with bool } } @@ -771,14 +775,17 @@ pub mod unshared_test_utils { } } - impl NotifyHandle for NotifyHandleMock { - fn notify<'a>(&'a self, msg: T, mut closure: Box) { + impl NotifyHandle for NotifyHandleMock + where M: Message + Clone, + A: Actor> + { + fn notify<'a>(&'a self, msg: M, ctx: &'a mut Context) { self.notify_params.lock().unwrap().push(msg.clone()); if !cfg!(test) { panic!("this shouldn't run outside a test") } if self.do_you_want_to_proceed_after { - closure(msg) + ctx.notify(msg) } } } From 2e6fcff55f39299b5c6c1425a8afa2b5cb2210ea Mon Sep 17 00:00:00 2001 From: Bert Date: Wed, 27 Apr 2022 11:01:06 +0200 Subject: [PATCH 2/3] GH-595: finishing the new design: arrangement and cleaness --- node/src/accountant/mod.rs | 36 +++---- node/src/accountant/tools.rs | 77 +++++++-------- node/src/sub_lib/utils.rs | 185 +++++++++++++++++++++++++---------- node/src/test_utils/mod.rs | 59 ++++++++--- 4 files changed, 230 insertions(+), 127 deletions(-) diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 6753e896f..bbe7c8752 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -1021,11 +1021,9 @@ impl Accountant { transaction_id: PendingPayableId, ctx: &mut Context, ) { - let closure = |msg: CancelFailedPendingTransaction| ctx.notify(msg); - self.tools.notify_cancel_failed_transaction.notify( - CancelFailedPendingTransaction { id: transaction_id }, - Box::new(closure), - ) + self.tools + .notify_cancel_failed_transaction + .notify(CancelFailedPendingTransaction { id: transaction_id }, ctx) } fn order_confirm_transaction( @@ -1033,12 +1031,11 @@ impl Accountant { pending_payable_fingerprint: PendingPayableFingerprint, ctx: &mut Context, ) { - let closure = |msg: ConfirmPendingTransaction| ctx.notify(msg); self.tools.notify_confirm_transaction.notify( ConfirmPendingTransaction { pending_payable_fingerprint, }, - Box::new(closure), + ctx, ); } @@ -1820,7 +1817,8 @@ mod tests { subject.scanners.payables = Box::new(NullScanner); subject.tools.notify_later_scan_for_receivable = Box::new( NotifyLaterHandleMock::default() - .notify_later_params(¬ify_later_receivable_params_arc), + .notify_later_params(¬ify_later_receivable_params_arc) + .enable_proceeding(), ); let peer_actors = peer_actors_builder() .blockchain_bridge(blockchain_bridge) @@ -1922,7 +1920,8 @@ mod tests { subject.scanners.payables = Box::new(NullScanner); //skipping subject.tools.notify_later_scan_for_pending_payable = Box::new( NotifyLaterHandleMock::default() - .notify_later_params(¬ify_later_pending_payable_params_arc), + .notify_later_params(¬ify_later_pending_payable_params_arc) + .enable_proceeding(), ); let subject_addr: Addr = subject.start(); let subject_subs = Accountant::make_subs_from(&subject_addr); @@ -2007,7 +2006,9 @@ mod tests { subject.scanners.pending_payables = Box::new(NullScanner); //skipping subject.scanners.receivables = Box::new(NullScanner); //skipping subject.tools.notify_later_scan_for_payable = Box::new( - NotifyLaterHandleMock::default().notify_later_params(¬ify_later_payables_params_arc), + NotifyLaterHandleMock::default() + .notify_later_params(¬ify_later_payables_params_arc) + .enable_proceeding(), ); let subject_addr = subject.start(); let subject_subs = Accountant::make_subs_from(&subject_addr); @@ -3582,16 +3583,17 @@ mod tests { .build(); subject.scanners.receivables = Box::new(NullScanner); let notify_later_half_mock = NotifyLaterHandleMock::default() - .notify_later_params(¬ify_later_scan_for_pending_payable_arc_cloned); + .notify_later_params(¬ify_later_scan_for_pending_payable_arc_cloned) + .enable_proceeding(); subject.tools.notify_later_scan_for_pending_payable = Box::new(notify_later_half_mock); - let mut notify_half_mock = NotifyHandleMock::default() - .notify_params(¬ify_cancel_failed_transaction_params_arc_cloned); - notify_half_mock.do_you_want_to_proceed_after = true; + let notify_half_mock = NotifyHandleMock::default() + .notify_params(¬ify_cancel_failed_transaction_params_arc_cloned) + .enable_proceeding(); subject.tools.notify_cancel_failed_transaction = Box::new(notify_half_mock); - let mut notify_half_mock = NotifyHandleMock::default() - .notify_params(¬ify_confirm_transaction_params_arc_cloned); - notify_half_mock.do_you_want_to_proceed_after = true; + let notify_half_mock = NotifyHandleMock::default() + .notify_params(¬ify_confirm_transaction_params_arc_cloned) + .enable_proceeding(); subject.tools.notify_confirm_transaction = Box::new(notify_half_mock); subject }); diff --git a/node/src/accountant/tools.rs b/node/src/accountant/tools.rs index 6db991cfb..6e6206094 100644 --- a/node/src/accountant/tools.rs +++ b/node/src/accountant/tools.rs @@ -6,22 +6,9 @@ pub(in crate::accountant) mod accountant_tools { RequestTransactionReceipts, ScanForPayables, ScanForPendingPayable, ScanForReceivables, }; use crate::sub_lib::utils::{NotifyHandle, NotifyLaterHandle}; - use actix::{AsyncContext, Context, Recipient}; + use actix::{Context, Recipient}; #[cfg(test)] use std::any::Any; - use std::time::Duration; - - macro_rules! notify_later_assertable { - ($accountant: expr, $ctx: expr, $message_type: ident, $notify_later_handle_field: ident,$scan_interval_field: ident) => { - let closure = - Box::new(|msg: $message_type, interval: Duration| $ctx.notify_later(msg, interval)); - let _ = $accountant.tools.$notify_later_handle_field.notify_later( - $message_type {}, - $accountant.config.scan_intervals.$scan_interval_field, - closure, - ); - }; - } pub struct Scanners { pub pending_payables: Box, @@ -32,7 +19,7 @@ pub(in crate::accountant) mod accountant_tools { impl Default for Scanners { fn default() -> Self { Scanners { - pending_payables: Box::new(PendingPaymentsScanner), + pending_payables: Box::new(PendingPayablesScanner), payables: Box::new(PayablesScanner), receivables: Box::new(ReceivablesScanner), } @@ -46,20 +33,24 @@ pub(in crate::accountant) mod accountant_tools { } #[derive(Debug, PartialEq)] - pub struct PendingPaymentsScanner; + pub struct PendingPayablesScanner; - impl Scanner for PendingPaymentsScanner { + impl Scanner for PendingPayablesScanner { fn scan(&self, accountant: &Accountant) { accountant.scan_for_pending_payable() } fn notify_later_assertable(&self, accountant: &Accountant, ctx: &mut Context) { - notify_later_assertable!( - accountant, - ctx, - ScanForPendingPayable, - notify_later_scan_for_pending_payable, - pending_payable_scan_interval - ); + let _ = accountant + .tools + .notify_later_scan_for_pending_payable + .notify_later( + ScanForPendingPayable {}, + accountant + .config + .scan_intervals + .pending_payable_scan_interval, + ctx, + ); } as_any_impl!(); } @@ -73,12 +64,10 @@ pub(in crate::accountant) mod accountant_tools { } fn notify_later_assertable(&self, accountant: &Accountant, ctx: &mut Context) { - notify_later_assertable!( - accountant, + let _ = accountant.tools.notify_later_scan_for_payable.notify_later( + ScanForPayables {}, + accountant.config.scan_intervals.payable_scan_interval, ctx, - ScanForPayables, - notify_later_scan_for_payable, - payable_scan_interval ); } @@ -95,13 +84,14 @@ pub(in crate::accountant) mod accountant_tools { } fn notify_later_assertable(&self, accountant: &Accountant, ctx: &mut Context) { - notify_later_assertable!( - accountant, - ctx, - ScanForReceivables, - notify_later_scan_for_receivable, - receivable_scan_interval - ); + let _ = accountant + .tools + .notify_later_scan_for_receivable + .notify_later( + ScanForReceivables {}, + accountant.config.scan_intervals.receivable_scan_interval, + ctx, + ); } as_any_impl!(); @@ -126,10 +116,13 @@ pub(in crate::accountant) mod accountant_tools { pub struct TransactionConfirmationTools { pub notify_later_scan_for_pending_payable: Box>, - pub notify_later_scan_for_payable: Box>, - pub notify_later_scan_for_receivable: Box>, - pub notify_confirm_transaction: Box>, - pub notify_cancel_failed_transaction: Box>, + pub notify_later_scan_for_payable: Box>, + pub notify_later_scan_for_receivable: + Box>, + pub notify_confirm_transaction: + Box>, + pub notify_cancel_failed_transaction: + Box>, pub request_transaction_receipts_subs_opt: Option>, } } @@ -137,7 +130,7 @@ pub(in crate::accountant) mod accountant_tools { #[cfg(test)] mod tests { use crate::accountant::tools::accountant_tools::{ - PayablesScanner, PendingPaymentsScanner, ReceivablesScanner, Scanners, + PayablesScanner, PendingPayablesScanner, ReceivablesScanner, Scanners, }; #[test] @@ -146,7 +139,7 @@ mod tests { assert_eq!( subject.pending_payables.as_any().downcast_ref(), - Some(&PendingPaymentsScanner) + Some(&PendingPayablesScanner) ); assert_eq!( subject.payables.as_any().downcast_ref(), diff --git a/node/src/sub_lib/utils.rs b/node/src/sub_lib/utils.rs index e144f0198..83608e530 100644 --- a/node/src/sub_lib/utils.rs +++ b/node/src/sub_lib/utils.rs @@ -145,7 +145,7 @@ pub trait NotifyLaterHandle>> { msg: T, interval: Duration, ctx: &mut Context, - ) -> SpawnHandle; + ) -> Box; as_any_dcl!(); } @@ -153,9 +153,10 @@ pub struct NotifyLaterHandleReal { phantom: PhantomData, } -impl Default for Box> -where M: Message + 'static, - A: Actor> + Handler +impl Default for Box> +where + M: Message + 'static, + A: Actor> + Handler, { fn default() -> Self { Box::new(NotifyLaterHandleReal { @@ -164,29 +165,32 @@ where M: Message + 'static, } } -impl NotifyLaterHandle for NotifyLaterHandleReal -where M: Message + 'static, - A: Actor> + Handler +impl NotifyLaterHandle for NotifyLaterHandleReal +where + M: Message + 'static, + A: Actor> + Handler, { fn notify_later( &self, msg: M, interval: Duration, - ctx: &mut Context - ) -> SpawnHandle { - ctx.notify_later(msg,interval) + ctx: &mut Context, + ) -> Box { + let handle = ctx.notify_later(msg, interval); + Box::new(NLSpawnHandleWrapperReal::new(handle)) } as_any_impl!(); } -pub trait NotifyHandle>> { +pub trait NotifyHandle>> { fn notify<'a>(&'a self, msg: T, ctx: &'a mut Context); as_any_dcl!(); } -impl Default for Box> -where M: Message + 'static, - A: Actor> + Handler +impl Default for Box> +where + M: Message + 'static, + A: Actor> + Handler, { fn default() -> Self { Box::new(NotifyHandleReal { @@ -195,13 +199,35 @@ where M: Message + 'static, } } +pub trait NLSpawnHandleWrapper { + fn handle(self) -> SpawnHandle; +} + +pub struct NLSpawnHandleWrapperReal { + handle: SpawnHandle, +} + +impl NLSpawnHandleWrapperReal { + pub fn new(handle: SpawnHandle) -> Self { + Self { handle } + } +} + +impl NLSpawnHandleWrapper for NLSpawnHandleWrapperReal { + fn handle(self) -> SpawnHandle { + self.handle + } +} + pub struct NotifyHandleReal { phantom: PhantomData, } -impl NotifyHandle for NotifyHandleReal -where M: Message + 'static, - A: Actor> + Handler { +impl NotifyHandle for NotifyHandleReal +where + M: Message + 'static, + A: Actor> + Handler, +{ fn notify<'a>(&'a self, msg: M, ctx: &'a mut Context) { ctx.notify(msg) } @@ -218,15 +244,15 @@ pub fn make_new_test_multi_config<'a>( #[cfg(test)] mod tests { - use std::ops::Add; - use actix::{Addr, AsyncContext, Handler, Running, System}; use super::*; use crate::apps::app_node; + use actix::{Handler, System}; + use crossbeam_channel::{unbounded, Sender}; use log::Level; use masq_lib::messages::ToMessageBody; use masq_lib::multi_config::CommandLineVcl; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; - use crate::sub_lib::peer_actors::StartMessage; + use std::ops::Sub; #[test] fn indicates_dead_stream_identifies_dead_stream_errors() { @@ -391,59 +417,114 @@ mod tests { } struct NotifyHandlesTestActor { - notify_later_handle_real_opt: Option>, - notify_handle_real_opt: Option> + responder: Sender, + message_counter: usize, + notify_later_handle_real: NotifyLaterHandleReal, + notify_handle_real: NotifyHandleReal, + } + + struct FindingInfo { + id: usize, + started: SystemTime, + received: SystemTime, } + impl NotifyHandlesTestActor { + fn new(responder: Sender) -> Self { + Self { + responder, + message_counter: 0, + notify_later_handle_real: NotifyLaterHandleReal { + phantom: Default::default(), + }, + notify_handle_real: NotifyHandleReal { + phantom: Default::default(), + }, + } + } + } + + const DELAYED: u64 = 55; + impl Actor for NotifyHandlesTestActor { type Context = Context; fn started(&mut self, ctx: &mut Self::Context) { - if let Some(handle) = self.notify_handle_real_opt.as_ref(){ - handle.notify(NotifyHandlesProbeMessage::new(None),ctx); - } else if let Some(handle) = self.notify_later_handle_real_opt.as_ref(){ - let interval = Duration::from_millis(333); - handle.notify_later(NotifyHandlesProbeMessage::new(Some(interval)),interval,ctx); - } else { - panic!( "One handle must be picked to be tested!") - } + self.notify_handle_real + .notify(NotifyHandlesProbeMessage::new(0), ctx); + let interval = Duration::from_millis(DELAYED); + self.notify_later_handle_real.notify_later( + NotifyHandlesProbeMessage::new(1), + interval, + ctx, + ); } } #[derive(Message)] - struct NotifyHandlesProbeMessage{ - interval_opt: Option, - start_time: SystemTime + struct NotifyHandlesProbeMessage { + id: usize, + start_time: SystemTime, } - impl NotifyHandlesProbeMessage{ - fn new(interval_opt: Option)->Self{ - Self{ interval_opt, start_time: SystemTime::now() } + impl NotifyHandlesProbeMessage { + fn new(id: usize) -> Self { + Self { + id, + start_time: SystemTime::now(), + } } } - impl Handler for NotifyHandlesTestActor{ + impl Handler for NotifyHandlesTestActor { type Result = (); - fn handle(&mut self, msg: NotifyHandlesProbeMessage, ctx: &mut Self::Context) -> Self::Result { - let now = SystemTime::now(); - let start_time = msg.start_time; - if let Some(interval) = msg.interval_opt { - assert!(now > start_time.add(interval)) - } else { - let with_margin = start_time * 1.3; - assert!(with_margin > now) + fn handle( + &mut self, + msg: NotifyHandlesProbeMessage, + _ctx: &mut Self::Context, + ) -> Self::Result { + let info = FindingInfo { + id: msg.id, + started: msg.start_time, + received: SystemTime::now(), + }; + self.responder.send(info).unwrap(); + self.message_counter += 1; + if self.message_counter == 2 { + System::current().stop() } - System::current().stop() } } #[test] - fn notify_handle_real_sends_the_message_correctly(){ - let test_actor = NotifyHandlesTestActor{ notify_later_handle_real_opt: None, notify_handle_real_opt: Some(Default::default()) }; - let address = test_actor.start(); - let system = System::new("notify_handle_test"); - - assert_eq!(system.run(),0) + fn notify_handles_real_sends_their_messages_correctly() { + let (sender, receiver) = unbounded(); + let test_actor = NotifyHandlesTestActor::new(sender); + let _ = test_actor.start(); + let system = System::new("notify_handles_test"); + + system.run(); + + let mut data = Vec::new(); + (0..2).for_each(|_| data.push(receiver.recv().unwrap())); + let first_message = data.remove(0); + assert_eq!(first_message.id, 0); + let notify_exec_duration = first_message + .received + .duration_since(first_message.started) + .unwrap(); + let second_message = data.remove(0); + let notify_later_exec_duration = second_message + .received + .duration_since(second_message.started) + .unwrap(); + let safe_assumption = DELAYED - (DELAYED as f64 * 0.1) as u64; + assert!( + notify_exec_duration + < notify_later_exec_duration.sub(Duration::from_millis(safe_assumption)) + ); + assert!(notify_exec_duration < Duration::from_millis(DELAYED)); + assert!(notify_later_exec_duration >= Duration::from_millis(DELAYED)); } } diff --git a/node/src/test_utils/mod.rs b/node/src/test_utils/mod.rs index 0c3b5b128..de8e72b51 100644 --- a/node/src/test_utils/mod.rs +++ b/node/src/test_utils/mod.rs @@ -514,10 +514,12 @@ pub mod unshared_test_utils { AccountantConfig, DEFAULT_PAYMENT_THRESHOLDS, DEFAULT_SCAN_INTERVALS, }; use crate::sub_lib::neighborhood::DEFAULT_RATE_PACK; - use crate::sub_lib::utils::{NotifyHandle, NotifyLaterHandle}; + use crate::sub_lib::utils::{ + NLSpawnHandleWrapper, NLSpawnHandleWrapperReal, NotifyHandle, NotifyLaterHandle, + }; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; - use actix::{Actor, Addr, AsyncContext, Context, Handler, System}; - use actix::{Message, SpawnHandle}; + use actix::Message; + use actix::{Actor, Addr, AsyncContext, Context, Handler, SpawnHandle, System}; use crossbeam_channel::{Receiver, Sender}; use masq_lib::messages::{ToMessageBody, UiCrashRequest}; use masq_lib::multi_config::MultiConfig; @@ -713,13 +715,15 @@ pub mod unshared_test_utils { } pub struct NotifyLaterHandleMock { - notify_later_params: Arc>>, //I care only about the params; realize that it's hard to test self addressed messages if you cannot mock yourself + notify_later_params: Arc>>, + do_you_want_to_proceed_after: bool, } impl Default for NotifyLaterHandleMock { fn default() -> Self { Self { notify_later_params: Arc::new(Mutex::new(vec![])), + do_you_want_to_proceed_after: false, } } } @@ -729,18 +733,24 @@ pub mod unshared_test_utils { self.notify_later_params = params.clone(); self } + + pub fn enable_proceeding(mut self) -> Self { + self.do_you_want_to_proceed_after = true; + self + } } - impl NotifyLaterHandle for NotifyLaterHandleMock - where M: Message + Clone, - A: Actor> + impl NotifyLaterHandle for NotifyLaterHandleMock + where + M: Message + 'static + Clone, + A: Actor> + Handler, { fn notify_later<'a>( &'a self, msg: M, interval: Duration, - ctx:&'a mut Context , - ) -> SpawnHandle { + ctx: &'a mut Context, + ) -> Box { self.notify_later_params .lock() .unwrap() @@ -748,15 +758,26 @@ pub mod unshared_test_utils { if !cfg!(test) { panic!("this shouldn't run outside a test") } - ctx.notify_later(msg,interval) - //TODO what about adding conditional sending? with bool + if self.do_you_want_to_proceed_after { + let handle = ctx.notify_later(msg, interval); + Box::new(NLSpawnHandleWrapperReal::new(handle)) + } else { + Box::new(NLSpawnHandleWrapperNull {}) + } + } + } + + pub struct NLSpawnHandleWrapperNull {} + + impl NLSpawnHandleWrapper for NLSpawnHandleWrapperNull { + fn handle(self) -> SpawnHandle { + intentionally_blank!() } } pub struct NotifyHandleMock { - //I care only about the params; realize that it's hard to test self addressed messages if you cannot mock yourself as the subject notify_params: Arc>>, - pub do_you_want_to_proceed_after: bool, + do_you_want_to_proceed_after: bool, } impl Default for NotifyHandleMock { @@ -773,11 +794,17 @@ pub mod unshared_test_utils { self.notify_params = params.clone(); self } + + pub fn enable_proceeding(mut self) -> Self { + self.do_you_want_to_proceed_after = true; + self + } } - impl NotifyHandle for NotifyHandleMock - where M: Message + Clone, - A: Actor> + impl NotifyHandle for NotifyHandleMock + where + M: Message + 'static + Clone, + A: Actor> + Handler, { fn notify<'a>(&'a self, msg: M, ctx: &'a mut Context) { self.notify_params.lock().unwrap().push(msg.clone()); From bd65efaa8096e283937d1b902f5e4400e97cd0c9 Mon Sep 17 00:00:00 2001 From: Bert Date: Wed, 27 Apr 2022 11:11:04 +0200 Subject: [PATCH 3/3] GH-595: adding where clauses to traits --- node/src/sub_lib/utils.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/node/src/sub_lib/utils.rs b/node/src/sub_lib/utils.rs index 83608e530..6216f9f62 100644 --- a/node/src/sub_lib/utils.rs +++ b/node/src/sub_lib/utils.rs @@ -139,7 +139,10 @@ fn crash_request_analyzer( } } -pub trait NotifyLaterHandle>> { +pub trait NotifyLaterHandle +where + A: Actor>, +{ fn notify_later( &self, msg: T, @@ -182,7 +185,10 @@ where as_any_impl!(); } -pub trait NotifyHandle>> { +pub trait NotifyHandle +where + A: Actor>, +{ fn notify<'a>(&'a self, msg: T, ctx: &'a mut Context); as_any_dcl!(); }