1#[cfg(feature = "debug_refill")]
10use log::debug;
11
12use crate::error;
13use log::warn;
14
15#[cfg(not(test))]
16use log::info;
17
18#[cfg(all(not(test), target_os = "linux"))]
19use nix::unistd::gettid;
20
21use spin_sleep::SpinSleeper;
22use std::sync::{Arc, Mutex};
23use std::time::{Duration, Instant};
24
25use crate::database::sql_interface_refill::DatabaseInterfaceRefillTrait;
26use crate::sensors::tank_level_switch::TankLevelSwitchSignals;
27use crate::utilities::acknowledge_signal_handler::AcknowledgeSignalHandlerTrait;
28use crate::utilities::channel_content::InternalCommand;
29use crate::utilities::database_ping_trait::DatabasePingTrait;
30use crate::utilities::proc_ext_req::ProcessExternalRequestTrait;
31use crate::utilities::wait_for_termination::WaitForTerminationTrait;
32use crate::water::refill_channels::RefillChannels;
33use crate::water::refill_config::RefillConfig;
34use crate::water::refill_error_states::RefillErrorStates;
35use crate::water::refill_monitor_view::RefillMonitorView;
36use crate::water::refill_stats_data::RefillStatsData;
37use crate::water::water_injection::WaterInjectionTrait;
38use crate::{log_error_chain, perform_schedule_check};
39
40const MILLIS_PER_SEC: u64 = 1000;
41
42pub struct RefillStatus {
44 pub refill_in_progress_live: bool,
46
47 pub refill_in_progress_for_database: bool,
51}
52
53#[cfg_attr(doc, aquamarine::aquamarine)]
55pub struct Refill {
90 pub config: RefillConfig,
93
94 pub refill_errors: RefillErrorStates,
96
97 lock_info_stop_command_received: bool,
99
100 lock_info_start_command_received: bool,
102
103 lock_info_refill_check_volume_last_24h: bool,
105
106 lock_info_refill_check_count_last_24h: bool,
108
109 lock_info_refill_check_volume_last_hour: bool,
111
112 lock_info_refill_check_count_last_hour: bool,
114
115 lock_info_refill_check_interval_last_refill: bool,
117
118 lock_error_read_duration_since_last_refill: bool,
120
121 lock_error_check_empty: bool,
123
124 lock_error_read_refill_volume_last_24h: bool,
126
127 lock_error_read_refill_count_last_24h: bool,
129
130 lock_error_read_refill_volume_last_hour: bool,
132
133 lock_error_read_refill_count_last_hour: bool,
135
136 lock_error_channel_send_schedule_check: bool,
138
139 lock_error_channel_receive_schedule_check: bool,
141
142 lock_error_channel_send_monitors: bool,
144
145 pub lock_warn_inapplicable_command_signal_handler: bool,
147
148 pub lock_error_channel_receive_termination: bool,
150
151 pub last_ping_instant: Instant,
153
154 pub database_ping_interval: Duration,
156
157 last_sent_monitor_view: Option<RefillMonitorView>,
159}
160
161impl Refill {
162 pub fn new(config: RefillConfig, database_ping_interval: Duration) -> Refill {
178 Self {
179 config,
180 refill_errors: RefillErrorStates {
181 error_switch_stuck_high: false,
182 error_switch_stuck_low: false,
183 error_receive_tank_level_switch_position: false,
184 error_sql_update_failed: false,
185 error_sql_get_historic_data_failed: false,
186 },
187 lock_info_stop_command_received: false,
188 lock_info_start_command_received: false,
189 lock_info_refill_check_volume_last_24h: false,
190 lock_info_refill_check_count_last_24h: false,
191 lock_info_refill_check_volume_last_hour: false,
192 lock_info_refill_check_count_last_hour: false,
193 lock_info_refill_check_interval_last_refill: false,
194 lock_error_read_duration_since_last_refill: false,
195 lock_error_check_empty: false,
196 lock_error_read_refill_volume_last_24h: false,
197 lock_error_read_refill_count_last_24h: false,
198 lock_error_read_refill_volume_last_hour: false,
199 lock_error_read_refill_count_last_hour: false,
200 lock_error_channel_send_schedule_check: false,
201 lock_error_channel_receive_schedule_check: false,
202 lock_error_channel_send_monitors: false,
203 lock_warn_inapplicable_command_signal_handler: false,
204 lock_error_channel_receive_termination: false,
205 last_ping_instant: Instant::now(),
206 database_ping_interval,
207 last_sent_monitor_view: None,
208 }
209 }
210
211 #[cfg(test)]
212 pub fn new_with_errors(config: RefillConfig, refill_errors: RefillErrorStates) -> Refill {
228 Self {
229 config,
230 refill_errors,
231 lock_info_stop_command_received: false,
232 lock_info_start_command_received: false,
233 lock_info_refill_check_volume_last_24h: false,
234 lock_info_refill_check_count_last_24h: false,
235 lock_info_refill_check_volume_last_hour: false,
236 lock_info_refill_check_count_last_hour: false,
237 lock_info_refill_check_interval_last_refill: false,
238 lock_error_read_duration_since_last_refill: false,
239 lock_error_check_empty: false,
240 lock_error_read_refill_volume_last_24h: false,
241 lock_error_read_refill_count_last_24h: false,
242 lock_error_read_refill_volume_last_hour: false,
243 lock_error_read_refill_count_last_hour: false,
244 lock_error_channel_send_schedule_check: false,
245 lock_error_channel_receive_schedule_check: false,
246 lock_error_channel_send_monitors: false,
247 lock_warn_inapplicable_command_signal_handler: false,
248 lock_error_channel_receive_termination: false,
249 last_ping_instant: Instant::now(),
250 database_ping_interval: Duration::from_secs(1000),
251 last_sent_monitor_view: None,
252 }
253 }
254
255 fn get_refill_stats_data(
271 &mut self,
272 refill_stats_data: &mut RefillStatsData,
273 sql_interface_refill: &mut dyn DatabaseInterfaceRefillTrait,
274 ) {
275 match sql_interface_refill.check_empty() {
276 Ok(0) => {
277 self.lock_error_check_empty = false;
278 refill_stats_data.duration_since_last_refill =
279 self.config.min_interval_last_refill.saturating_add(1);
280 }
281 Ok(_) => {
282 self.lock_error_check_empty = false;
283 match sql_interface_refill.get_duration_since_last_refill() {
284 Ok(duration) => {
285 self.lock_error_read_duration_since_last_refill = false;
286 refill_stats_data.duration_since_last_refill = duration;
287 }
288 Err(_e) => {
289 self.refill_errors.error_sql_get_historic_data_failed = true;
290 #[cfg(not(test))]
291 if !self.lock_error_read_duration_since_last_refill {
292 log_error_chain(
293 module_path!(),
294 "could not get duration since last refill event",
295 _e,
296 );
297 self.lock_error_read_duration_since_last_refill = true;
298 }
299 }
300 }
301 }
302 Err(_e) => {
303 self.refill_errors.error_sql_get_historic_data_failed = true;
304 #[cfg(not(test))]
305 if !self.lock_error_check_empty {
306 log_error_chain(
307 module_path!(),
308 "could not check if refill table is empty or not",
309 _e,
310 );
311 self.lock_error_check_empty = true;
312 }
313 }
314 };
315
316 match sql_interface_refill.get_refill_volume_of_last_24h() {
317 Ok(volume) => {
318 self.lock_error_read_refill_volume_last_24h = false;
319 refill_stats_data.refill_volume_last_24h = volume;
320 }
321 Err(_e) => {
322 self.refill_errors.error_sql_get_historic_data_failed = true;
323 #[cfg(not(test))]
324 if !self.lock_error_read_refill_volume_last_24h {
325 log_error_chain(
326 module_path!(),
327 "could not get refill volume of last 24 hours",
328 _e,
329 );
330 self.lock_error_read_refill_volume_last_24h = true;
331 }
332 }
333 };
334
335 match sql_interface_refill.get_refill_count_of_last_24h() {
336 Ok(count) => {
337 self.lock_error_read_refill_count_last_24h = false;
338 refill_stats_data.refill_count_last_24h = count;
339 }
340 Err(_e) => {
341 self.refill_errors.error_sql_get_historic_data_failed = true;
342 #[cfg(not(test))]
343 if !self.lock_error_read_refill_count_last_24h {
344 log_error_chain(
345 module_path!(),
346 "could not get refill count of last 24 hours",
347 _e,
348 );
349 self.lock_error_read_refill_count_last_24h = true;
350 }
351 }
352 };
353
354 match sql_interface_refill.get_refill_volume_of_last_hour() {
355 Ok(volume) => {
356 self.lock_error_read_refill_volume_last_hour = false;
357 refill_stats_data.refill_volume_last_hour = volume;
358 }
359 Err(_e) => {
360 self.refill_errors.error_sql_get_historic_data_failed = true;
361 #[cfg(not(test))]
362 if !self.lock_error_read_refill_volume_last_hour {
363 log_error_chain(
364 module_path!(),
365 "Could not get refill volume of last hour",
366 _e,
367 );
368 self.lock_error_read_refill_volume_last_hour = true;
369 }
370 }
371 };
372
373 match sql_interface_refill.get_refill_count_of_last_hour() {
374 Ok(count) => {
375 self.lock_error_read_refill_count_last_hour = false;
376 refill_stats_data.refill_count_last_hour = count;
377 }
378 Err(_e) => {
379 self.refill_errors.error_sql_get_historic_data_failed = true;
380 #[cfg(not(test))]
381 if !self.lock_error_read_refill_count_last_hour {
382 log_error_chain(
383 module_path!(),
384 "Could not get refill count of last hour",
385 _e,
386 );
387 self.lock_error_read_refill_count_last_hour = true;
388 }
389 }
390 };
391 }
392
393 fn check_error_condition_switch_stuck_high(&mut self, duration_since_last_refill: u64) {
403 self.refill_errors.error_switch_stuck_high =
404 duration_since_last_refill > self.config.max_duration_since_last_refill;
405 }
406
407 fn calc_inhibition_flag(
422 &mut self,
423 current_state: bool,
424 start_command_received: bool,
425 stop_command_received: bool,
426 ) -> bool {
427 let mut new_state: bool = current_state;
429
430 if stop_command_received {
431 if !self.lock_info_stop_command_received {
432 #[cfg(not(test))]
433 info!(
434 target: module_path!(),
435 "received Stop command. Inhibiting refill control."
436 );
437
438 self.lock_info_stop_command_received = true;
439 }
440 new_state = true;
441 } else {
442 self.lock_info_stop_command_received = false;
443 }
444 if start_command_received {
447 if !self.lock_info_start_command_received {
448 #[cfg(not(test))]
449 info!(
450 target: module_path!(),
451 "received Start command. Restarting refill control."
452 );
453
454 self.lock_info_start_command_received = true;
455 } else {
456 self.lock_info_start_command_received = true;
457 }
458 new_state = false;
459 }
460 new_state
461 }
462
463 fn check_volume_count_time_limits(
484 &mut self,
485 sql_refill_data: &RefillStatsData,
486 refill_channels: &mut RefillChannels,
487 ) -> bool {
488 #[cfg(feature = "debug_refill")]
489 debug!(
490 target: module_path!(),
491 "check_volume_count_time_limits called.",
492 );
493 let refill_check_volume_last_24h =
494 sql_refill_data.refill_volume_last_24h > self.config.max_refill_volume_24h;
495
496 if refill_check_volume_last_24h {
497 if !self.lock_info_refill_check_volume_last_24h {
498 #[cfg(not(test))]
499 info!(
500 target: module_path!(),
501 "refill volume of last 24h exceeds permissible refill volume per 24h of {} L",
502 self.config.max_refill_volume_24h
503 );
504
505 self.lock_info_refill_check_volume_last_24h = true;
506 }
507 } else {
508 self.lock_info_refill_check_volume_last_24h = false;
509 }
510
511 let refill_check_count_last_24h =
512 sql_refill_data.refill_count_last_24h > self.config.max_refill_count_24h;
513 if refill_check_count_last_24h {
514 if !self.lock_info_refill_check_count_last_24h {
515 #[cfg(not(test))]
516 info!(
517 target: module_path!(),
518 "refill count of last 24h exceeds permissible refill count per 24h of {} L",
519 self.config.max_refill_count_24h
520 );
521
522 self.lock_info_refill_check_count_last_24h = true;
523 }
524 } else {
525 self.lock_info_refill_check_count_last_24h = false;
526 }
527
528 let refill_check_volume_last_hour =
529 sql_refill_data.refill_volume_last_hour > self.config.max_refill_volume_hour;
530 if refill_check_volume_last_hour {
531 if !self.lock_info_refill_check_volume_last_hour {
532 #[cfg(not(test))]
533 info!(
534 target: module_path!(),
535 "refill volume of last hour exceeds permissible refill volume per hour of {}",
536 self.config.max_refill_volume_hour
537 );
538
539 self.lock_info_refill_check_volume_last_hour = true;
540 }
541 } else {
542 self.lock_info_refill_check_volume_last_hour = false;
543 }
544
545 let refill_check_count_last_hour =
546 sql_refill_data.refill_count_last_hour > self.config.max_refill_count_hour;
547 if refill_check_count_last_hour {
548 if !self.lock_info_refill_check_count_last_hour {
549 #[cfg(not(test))]
550 info!(
551 target: module_path!(),
552 "refill count of last 24h exceeds permissible refill count per hour of {}",
553 self.config.max_refill_count_hour
554 );
555
556 self.lock_info_refill_check_count_last_hour = true;
557 }
558 } else {
559 self.lock_info_refill_check_count_last_hour = false;
560 }
561
562 let refill_check_interval_last_refill =
563 sql_refill_data.duration_since_last_refill < self.config.min_interval_last_refill;
564 if refill_check_interval_last_refill {
565 if !self.lock_info_refill_check_interval_last_refill {
566 #[cfg(not(test))]
567 info!(
568 target: module_path!(),
569 "time interval since last refill {} is too small (limit={}).",
570 sql_refill_data.duration_since_last_refill, self.config.min_interval_last_refill
571 );
572
573 self.lock_info_refill_check_interval_last_refill = true;
574 }
575 } else {
576 self.lock_info_refill_check_interval_last_refill = false;
577 }
578
579 let refill_monitor_view = RefillMonitorView {
580 refill_check_volume_last_24h,
581 refill_check_count_last_24h,
582 refill_check_volume_last_hour,
583 refill_check_count_last_hour,
584 refill_check_interval_last_refill,
585 };
586
587 let mut monitor_view_is_different = true;
589 if self.last_sent_monitor_view.is_some() {
590 let previous_monitor_view = self.last_sent_monitor_view.clone().unwrap();
591 if refill_monitor_view == previous_monitor_view {
592 monitor_view_is_different = false;
593 }
594 }
595 if monitor_view_is_different {
596 match refill_channels.send_to_monitor(refill_monitor_view) {
597 Ok(_) => {
598 self.lock_error_channel_send_monitors = false;
599 }
600 Err(e) => {
601 if !self.lock_error_channel_send_monitors {
602 log_error_chain(module_path!(), "sending view to monitor failed", e);
603 self.lock_error_channel_send_monitors = true;
604 }
605 }
606 }
607 }
608
609 refill_check_volume_last_24h
610 | refill_check_count_last_24h
611 | refill_check_volume_last_hour
612 | refill_check_count_last_hour
613 | refill_check_interval_last_refill
614 }
615
616 pub fn execute(
645 &mut self,
646 mutex_device_scheduler_refill: Arc<Mutex<i32>>,
647 refill_channels: &mut RefillChannels,
648 water_injection: &mut impl WaterInjectionTrait,
649 mutex_tank_level_switch_signals_clone_for_refill: Arc<Mutex<TankLevelSwitchSignals>>,
650 mutex_refill_status: Arc<Mutex<RefillStatus>>,
651 mut sql_interface_refill: Box<dyn DatabaseInterfaceRefillTrait + Sync + Send>,
652 ) {
653 #[cfg(all(target_os = "linux", not(test)))]
654 info!(target: module_path!(), "Thread started with TID: {}", gettid());
655
656 let cycle_time_duration =
657 Duration::from_millis(self.config.check_interval * MILLIS_PER_SEC);
658 let sleep_duration_hundred_millis = Duration::from_millis(100);
659 let mut i = 0;
660 let spin_sleeper = SpinSleeper::default();
661
662 let mut schedule_check_result: bool;
663 #[cfg(feature = "debug_refill")]
664 {
665 schedule_check_result = false;
666 }
667
668 let mut tank_level_switch_invalid: bool = false;
669 let mut tank_level_switch_position_stabilized: bool = true;
670
671 #[cfg(feature = "debug_refill")]
672 {
673 tank_level_switch_invalid = false;
674 tank_level_switch_position_stabilized = true;
675 }
676
677 let mut lock_warn_cycle_time_exceeded: bool = false;
678 let mut cycle_time_exceeded: bool; let mut refill_stats_data = RefillStatsData::new();
682 self.get_refill_stats_data(&mut refill_stats_data, &mut *sql_interface_refill);
683
684 let mut refill_inhibited = false; let mut quit_command_received = false; let mut start_command_received; let mut stop_command_received; if self.config.initial_wait_interval > 0 {
691 while i < self.config.initial_wait_interval * 10 {
692 match i.checked_add(1) {
693 Some(c) => i = c,
694 None => {
695 break;
697 }
698 }
699
700 (
701 quit_command_received,
702 start_command_received,
703 stop_command_received,
704 ) = self.process_external_request(
705 &mut refill_channels.rx_refill_from_signal_handler,
706 refill_channels.rx_refill_from_messaging_opt.as_mut(),
707 );
708 refill_inhibited = self.calc_inhibition_flag(
709 refill_inhibited,
710 start_command_received,
711 stop_command_received,
712 );
713 if quit_command_received {
714 break;
715 }
716 spin_sleeper.sleep(sleep_duration_hundred_millis);
717 }
718 }
719
720 refill_stats_data.duration_since_last_refill = refill_stats_data
722 .duration_since_last_refill
723 .saturating_add(self.config.initial_wait_interval);
724
725 let mut start_time = Instant::now();
726
727 loop {
729 if quit_command_received {
731 break; }
733
734 if self.config.active {
735 self.check_error_condition_switch_stuck_high(
738 refill_stats_data.duration_since_last_refill,
739 );
740
741 if !quit_command_received && !refill_inhibited {
742 {
744 match mutex_tank_level_switch_signals_clone_for_refill.lock() {
745 Ok(c) => {
746 tank_level_switch_position_stabilized =
747 c.tank_level_switch_position_stabilized;
748 tank_level_switch_invalid = c.tank_level_switch_invalid;
749 }
750 Err(_) => {
751 }
753 }
754 }
755
756 self.get_refill_stats_data(&mut refill_stats_data, &mut *sql_interface_refill);
757
758 if !self.check_volume_count_time_limits(&refill_stats_data, refill_channels)
760 && !self.refill_errors.error_switch_stuck_low
761 && !self.refill_errors.error_sql_update_failed
762 && !self.refill_errors.error_sql_get_historic_data_failed
763 {
764 perform_schedule_check!(
765 refill_channels,
766 schedule_check_result,
767 self.lock_error_channel_send_schedule_check,
768 self.lock_error_channel_receive_schedule_check,
769 module_path!()
770 );
771
772 if schedule_check_result
773 && !tank_level_switch_position_stabilized
774 && !tank_level_switch_invalid
775 {
776 #[cfg(feature = "debug_refill")]
777 debug!(
778 target: module_path!(),
779 "acquiring semaphore...",
780 );
781
782 let mut mutex_data = mutex_device_scheduler_refill.lock().unwrap();
784 #[cfg(feature = "debug_refill")]
787 debug!(
788 target: module_path!(),
789 "mutex_data = {}",
790 mutex_data
791 );
792
793 {
794 match mutex_refill_status.lock() {
796 Ok(mut refill_status) => {
797 refill_status.refill_in_progress_live = true;
798 refill_status.refill_in_progress_for_database = true;
799 }
800 Err(e) => {
801 log_error_chain(
802 module_path!(),
803 "error locking mutex for refill status",
804 e,
805 );
806 }
807 };
808 }
809
810 quit_command_received = water_injection.inject_water(
811 refill_channels,
812 &mut self.refill_errors,
813 &mut sql_interface_refill,
814 &mutex_tank_level_switch_signals_clone_for_refill,
815 );
816 *mutex_data = mutex_data.saturating_add(1);
817
818 {
819 match mutex_refill_status.lock() {
821 Ok(mut refill_status) => {
822 refill_status.refill_in_progress_live = false;
823 }
824 Err(e) => {
825 log_error_chain(
826 module_path!(),
827 "error locking mutex for refill status",
828 e,
829 );
830 }
831 };
832 }
833
834 #[cfg(feature = "debug_refill")]
835 debug!(
836 target: module_path!(),
837 "releasing semaphore..."
838 );
839 }
840 }
841 }
842 }
843
844 #[cfg(feature = "debug_refill")]
845 debug!(
846 target: module_path!(),
847 "refill_inhibited = {}, error_switch_stuck_low={}, error_sql_update_failed={}, error_sql_get_historic_data_failed={}, schedule_check_result={}, tank_level_switch_position_stabilized={}, tank_level_switch_invalid={}",
848 refill_inhibited,
849 self.refill_errors.error_switch_stuck_low,
850 self.refill_errors.error_sql_update_failed,
851 self.refill_errors.error_sql_get_historic_data_failed,
852 schedule_check_result,
853 tank_level_switch_position_stabilized,
854 tank_level_switch_invalid
855 );
856
857 let stop_time = Instant::now();
858 let execution_duration = stop_time.duration_since(start_time);
859
860 let mut remaining_sleep_time_millis: u64 = 0;
861 if execution_duration >= cycle_time_duration {
862 if !lock_warn_cycle_time_exceeded {
863 warn!(target: module_path!(),
864 "execution duration of {} ms exceeds cycle time of {} ms",
865 execution_duration.as_millis(),
866 cycle_time_duration.as_millis()
867 );
868 lock_warn_cycle_time_exceeded = true;
869 }
870 cycle_time_exceeded = true;
871 } else {
872 let remaining_sleep_time_duration = cycle_time_duration - execution_duration;
875 remaining_sleep_time_millis = remaining_sleep_time_duration.as_millis() as u64;
876 cycle_time_exceeded = false;
877 lock_warn_cycle_time_exceeded = false;
878 }
879
880 #[cfg(feature = "debug_refill")]
881 debug!(
882 target: module_path!(),
883 "execution duration = {}, cycle time = {}, remaining_sleep_time_millis = {}",
884 execution_duration_millis,
885 self.config.check_interval * MILLIS_PER_SEC,
886 remaining_sleep_time_millis
887 );
888
889 if !quit_command_received {
891 i = 0;
894 while (i < remaining_sleep_time_millis) || cycle_time_exceeded {
895 match i.checked_add(100) {
896 Some(c) => i = c,
897 None => {
898 break;
900 }
901 }
902
903 (
904 quit_command_received,
905 start_command_received,
906 stop_command_received,
907 ) = self.process_external_request(
908 &mut refill_channels.rx_refill_from_signal_handler,
909 refill_channels.rx_refill_from_messaging_opt.as_mut(),
910 );
911 refill_inhibited = self.calc_inhibition_flag(
912 refill_inhibited,
913 start_command_received,
914 stop_command_received,
915 );
916 if quit_command_received {
917 break;
918 }
919 spin_sleeper.sleep(sleep_duration_hundred_millis);
920
921 self.check_timing_and_ping_database(&mut *sql_interface_refill);
922
923 cycle_time_exceeded = false;
924 }
925 }
926
927 start_time = Instant::now();
928
929 refill_stats_data.duration_since_last_refill = refill_stats_data
930 .duration_since_last_refill
931 .saturating_add(self.config.check_interval);
932 }
933
934 #[cfg(test)]
937 println!(
938 "{}: sending Quit confirmation to signal handler.",
939 module_path!()
940 );
941
942 refill_channels.acknowledge_signal_handler();
943
944 self.wait_for_termination(
948 &mut refill_channels.rx_refill_from_signal_handler,
949 sleep_duration_hundred_millis,
950 module_path!(),
951 );
952 }
953}
954
955#[cfg(test)]
956pub mod tests {
957 use crate::database::{sql_interface::SqlInterface, sql_interface_refill::SqlInterfaceRefill};
958 use crate::launch::channels::{channel, AquaChannelError, AquaReceiver, AquaSender, Channels};
959 use crate::sensors::tank_level_switch::TankLevelSwitchSignals;
960 use crate::utilities::channel_content::InternalCommand;
961 use crate::utilities::config::{
962 read_config_file, read_config_file_with_test_database, ConfigData,
963 };
964 use crate::utilities::proc_ext_req::ProcessExternalRequestTrait;
965 use crate::water::refill::Refill;
966 use crate::water::refill::RefillErrorStates;
967 use crate::water::refill::RefillStatus;
968 use all_asserts::{assert_ge, assert_le};
969 use spin_sleep::SpinSleeper;
970 use std::sync::{Arc, Mutex};
971 use std::thread;
972 use std::time::{Duration, Instant};
973
974 use crate::mocks::mock_monitors::tests::MockMonitors;
975 use crate::mocks::mock_schedule_check::tests::mock_schedule_check;
976 use crate::mocks::mock_sql_interface_refill::tests::MockSqlInterfaceRefill;
977 use crate::mocks::mock_water_injection::tests::MockWaterInjection;
978 use crate::mocks::test_command::tests::TestCommand;
979
980 use crate::utilities::logger::setup_logger;
981 use crate::utilities::logger_config::LoggerConfig;
982 use crate::water::refill_stats_data::RefillStatsData;
983
984 pub fn prepare_refill_tests(
1014 refill_errors: Option<RefillErrorStates>,
1015 initial_wait_interval: u64,
1016 check_interval: u64,
1017 test_db_number_opt: Option<u32>,
1018 ) -> (ConfigData, Refill, SqlInterface, SqlInterfaceRefill) {
1019 let config_file_name = "/config/aquarium_control_test_generic.toml";
1020
1021 let mut config: ConfigData = match test_db_number_opt {
1023 Some(test_db_number) => {
1024 read_config_file_with_test_database(config_file_name.to_string(), test_db_number)
1025 }
1026 None => read_config_file(config_file_name.to_string()).unwrap(),
1027 };
1028
1029 config.refill.initial_wait_interval = initial_wait_interval;
1030 config.refill.check_interval = check_interval;
1031
1032 let max_rows_refill = config.sql_interface.max_rows_data;
1033
1034 println!("Testing with database {}", config.sql_interface.db_name);
1035 let sql_interface = match SqlInterface::new(config.sql_interface.clone()) {
1036 Ok(c) => c,
1037 Err(e) => {
1038 panic!("Could not connect to SQL database: {e:?}");
1039 }
1040 };
1041 let sql_interface_refill =
1042 SqlInterfaceRefill::new(sql_interface.get_connection().unwrap(), max_rows_refill)
1043 .unwrap();
1044 let refill_config = config.refill.clone();
1045 (
1046 config,
1047 match refill_errors.is_some() {
1048 true => Refill::new_with_errors(refill_config, refill_errors.unwrap()),
1049 false => Refill::new(refill_config, Duration::from_millis(1000)),
1050 },
1051 sql_interface,
1052 *Box::new(sql_interface_refill),
1053 )
1054 }
1055
1056 pub fn prepare_refill_tests_with_mock_database_interface(
1085 refill_errors: Option<RefillErrorStates>,
1086 initial_wait_interval: u64,
1087 check_interval: u64,
1088 test_db_number: u32,
1089 ) -> (ConfigData, Refill, MockSqlInterfaceRefill) {
1090 let config_file_name = "/config/aquarium_control_test_generic.toml";
1091
1092 let mut config: ConfigData =
1094 read_config_file_with_test_database(config_file_name.to_string(), test_db_number);
1095
1096 config.refill.initial_wait_interval = initial_wait_interval;
1097 config.refill.check_interval = check_interval;
1098
1099 let sql_interface_refill = MockSqlInterfaceRefill {};
1100
1101 let refill_config = config.refill.clone();
1102 (
1103 config,
1104 match refill_errors.is_some() {
1105 true => Refill::new_with_errors(refill_config, refill_errors.unwrap()),
1106 false => Refill::new(refill_config, Duration::from_millis(1000)),
1107 },
1108 sql_interface_refill,
1109 )
1110 }
1111
1112 #[test]
1113 pub fn test_refill_process_external_request_empty_channel() {
1116 let refill_errors = RefillErrorStates {
1117 error_switch_stuck_high: false,
1118 error_switch_stuck_low: false,
1119 error_receive_tank_level_switch_position: false,
1120 error_sql_update_failed: false,
1121 error_sql_get_historic_data_failed: false,
1122 };
1123 let (_, mut refill, _, _) = prepare_refill_tests(Some(refill_errors), 2, 60, Some(46));
1124
1125 let (_, mut rx_refill_from_signal_handler): (
1126 AquaSender<InternalCommand>,
1127 AquaReceiver<InternalCommand>,
1128 ) = channel(1);
1129
1130 let (_, mut rx_refill_from_messaging): (
1131 AquaSender<InternalCommand>,
1132 AquaReceiver<InternalCommand>,
1133 ) = channel(1);
1134
1135 let (quit_command_received, start_command_received, stop_command_received) = refill
1136 .process_external_request(
1137 &mut rx_refill_from_signal_handler,
1138 Some(&mut rx_refill_from_messaging),
1139 );
1140
1141 assert_eq!(quit_command_received, false);
1142 assert_eq!(start_command_received, false);
1143 assert_eq!(stop_command_received, false);
1144 }
1145
1146 #[test]
1147 pub fn test_refill_trigger_water_injection() {
1150 let sleep_duration_50_millis = Duration::from_millis(50);
1151 let spin_sleeper = SpinSleeper::default();
1152
1153 let (_, mut refill, mut sql_interface, sql_interface_refill) =
1154 prepare_refill_tests(None, 1, 1, Some(20));
1155
1156 let mut channels = Channels::new_for_test();
1157
1158 let (
1160 tx_mock_water_injection_to_test_environment,
1161 mut rx_test_environment_from_mock_water_injection,
1162 ) = channel(1);
1163 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
1164 channel::<InternalCommand>(1);
1165
1166 let mutex_tank_level_switch_signals =
1167 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
1168 let mutex_tank_level_switch_signals_for_refill = mutex_tank_level_switch_signals.clone();
1169 let refill_status = RefillStatus {
1170 refill_in_progress_live: false,
1171 refill_in_progress_for_database: false,
1172 };
1173 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
1174
1175 let mut mock_monitors = MockMonitors::new();
1176
1177 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
1179 Ok(_) => {}
1180 Err(e) => {
1181 panic!("Could not prepare test case: {e:?}")
1182 }
1183 }
1184
1185 let mutex_device_scheduler = Arc::new(Mutex::new(0));
1186
1187 let mut mock_water_injection = MockWaterInjection::new(
1188 Some(tx_mock_water_injection_to_test_environment),
1189 RefillErrorStates {
1190 error_switch_stuck_high: false,
1191 error_switch_stuck_low: false,
1192 error_receive_tank_level_switch_position: false,
1193 error_sql_update_failed: false,
1194 error_sql_get_historic_data_failed: false,
1195 },
1196 );
1197
1198 let join_handle_mock_monitors = thread::Builder::new()
1200 .name("mock_monitor".to_string())
1201 .spawn(move || {
1202 mock_monitors.execute(
1203 channels.monitors.rx_monitors_from_refill,
1204 rx_monitors_from_test_environment,
1205 );
1206 })
1207 .unwrap();
1208
1209 let join_handle_mock_schedule_check = thread::Builder::new()
1211 .name("mock_schedule_check".to_string())
1212 .spawn(move || {
1213 mock_schedule_check(
1214 &mut channels.schedule_check.tx_schedule_check_to_refill,
1215 &mut channels.schedule_check.rx_schedule_check_from_refill,
1216 None,
1217 true,
1218 );
1219 })
1220 .unwrap();
1221
1222 let join_handle_test_environment = thread::Builder::new()
1223 .name("test_environment".to_string())
1224 .spawn(move || {
1225 let sleep_duration_two_secs = Duration::from_secs(2);
1226 let spin_sleeper = SpinSleeper::default();
1227
1228 let _ = rx_test_environment_from_mock_water_injection
1230 .recv()
1231 .unwrap();
1232
1233 {
1235 let mut mutex_tank_level_switch_signals =
1236 mutex_tank_level_switch_signals.lock().unwrap();
1237 mutex_tank_level_switch_signals.tank_level_switch_position_stabilized = true;
1238 mutex_tank_level_switch_signals.tank_level_switch_position = true;
1239 }
1240
1241 let start_time = Instant::now();
1242 spin_sleeper.sleep(sleep_duration_two_secs);
1243
1244 let _ = channels
1245 .signal_handler
1246 .send_to_refill(InternalCommand::Quit);
1247 channels.signal_handler.receive_from_refill().unwrap();
1248
1249 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
1250 let _ = channels
1251 .signal_handler
1252 .send_to_refill(InternalCommand::Terminate);
1253 let finish_time = Instant::now();
1254 let finalization_duration_millis =
1255 finish_time.duration_since(start_time).as_millis();
1256
1257 assert_ge!(finalization_duration_millis, 2000u128);
1258 assert_le!(finalization_duration_millis, 2150u128);
1259
1260 spin_sleeper.sleep(sleep_duration_two_secs);
1263 })
1264 .unwrap();
1265
1266 spin_sleeper.sleep(sleep_duration_50_millis);
1268
1269 let join_handle_test_object = thread::Builder::new()
1271 .name("test_object".to_string())
1272 .spawn(move || {
1273 let mut tx_refill_to_schedule_check_for_test_case_finish =
1274 channels.refill.tx_refill_to_schedule_check.clone();
1275
1276 refill.execute(
1277 mutex_device_scheduler,
1278 &mut channels.refill,
1279 &mut mock_water_injection,
1280 mutex_tank_level_switch_signals_for_refill,
1281 mutex_refill_status,
1282 Box::new(sql_interface_refill),
1283 );
1284
1285 let _ =
1287 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
1288 })
1289 .unwrap();
1290
1291 join_handle_mock_monitors
1292 .join()
1293 .expect("Mock monitor check did not finish.");
1294 join_handle_mock_schedule_check
1295 .join()
1296 .expect("Mock schedule check did not finish.");
1297 join_handle_test_environment
1298 .join()
1299 .expect("Test environment thread did not finish.");
1300 join_handle_test_object
1301 .join()
1302 .expect("Test object thread did not finish.");
1303 }
1304
1305 #[test]
1306 pub fn test_refill_trigger_water_injection_switch_stuck_high() {
1309 let sleep_duration_50_millis = Duration::from_millis(50);
1310 let spin_sleeper = SpinSleeper::default();
1311
1312 let (_, mut refill, mut sql_interface, sql_interface_refill) =
1313 prepare_refill_tests(None, 1, 1, Some(47));
1314
1315 let mut channels = Channels::new_for_test();
1316
1317 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
1319 channel::<InternalCommand>(1);
1320 let (
1321 tx_mock_water_injection_to_test_environment,
1322 mut rx_test_environment_from_mock_water_injection,
1323 ) = channel(1);
1324
1325 setup_logger(LoggerConfig::default()).unwrap();
1327
1328 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
1330 Ok(_) => {}
1331 Err(e) => {
1332 panic!("Could not prepare test case: {e:?}")
1333 }
1334 }
1335
1336 let mutex_device_scheduler = Arc::new(Mutex::new(0));
1337 let mutex_tank_level_switch_signals =
1338 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
1339 let refill_status = RefillStatus {
1340 refill_in_progress_live: false,
1341 refill_in_progress_for_database: false,
1342 };
1343 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
1344
1345 let mut mock_monitors = MockMonitors::new();
1346
1347 let mut mock_water_injection = MockWaterInjection::new(
1348 Some(tx_mock_water_injection_to_test_environment),
1349 RefillErrorStates {
1350 error_switch_stuck_high: false,
1351 error_switch_stuck_low: true,
1352 error_receive_tank_level_switch_position: false,
1353 error_sql_update_failed: false,
1354 error_sql_get_historic_data_failed: false,
1355 },
1356 );
1357
1358 let join_handle_mock_monitors = thread::Builder::new()
1360 .name("mock_monitor".to_string())
1361 .spawn(move || {
1362 mock_monitors.execute(
1363 channels.monitors.rx_monitors_from_refill,
1364 rx_monitors_from_test_environment,
1365 );
1366 })
1367 .unwrap();
1368
1369 let join_handle_mock_schedule_check = thread::Builder::new()
1371 .name("mock_schedule_check".to_string())
1372 .spawn(move || {
1373 mock_schedule_check(
1374 &mut channels.schedule_check.tx_schedule_check_to_refill,
1375 &mut channels.schedule_check.rx_schedule_check_from_refill,
1376 None,
1377 true,
1378 );
1379 })
1380 .unwrap();
1381
1382 let join_handle_test_environment = thread::Builder::new()
1383 .name("test_environment".to_string())
1384 .spawn(move || {
1385 let sleep_duration_two_secs = Duration::from_secs(2);
1386 let spin_sleeper = SpinSleeper::default();
1387
1388 let _ = rx_test_environment_from_mock_water_injection
1390 .recv()
1391 .unwrap();
1392
1393 let start_time = Instant::now();
1394 spin_sleeper.sleep(sleep_duration_two_secs);
1395
1396 let _ = channels
1397 .signal_handler
1398 .send_to_refill(InternalCommand::Quit);
1399 channels.signal_handler.receive_from_refill().unwrap();
1400 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
1401
1402 let _ = channels
1403 .signal_handler
1404 .send_to_refill(InternalCommand::Terminate);
1405 let finish_time = Instant::now();
1406 let finalization_duration_millis =
1407 finish_time.duration_since(start_time).as_millis();
1408
1409 println!(
1410 "finalization_duration_millis = {}",
1411 finalization_duration_millis
1412 );
1413
1414 assert_ge!(finalization_duration_millis, 2000u128);
1415 assert_le!(finalization_duration_millis, 2150u128);
1416
1417 spin_sleeper.sleep(sleep_duration_two_secs);
1420 })
1421 .unwrap();
1422
1423 spin_sleeper.sleep(sleep_duration_50_millis);
1425
1426 let join_handle_test_object = thread::Builder::new()
1428 .name("test_object".to_string())
1429 .spawn(move || {
1430 let mut tx_refill_to_schedule_check_for_test_case_finish =
1431 channels.refill.tx_refill_to_schedule_check.clone();
1432
1433 refill.execute(
1434 mutex_device_scheduler,
1435 &mut channels.refill,
1436 &mut mock_water_injection,
1437 mutex_tank_level_switch_signals,
1438 mutex_refill_status,
1439 Box::new(sql_interface_refill),
1440 );
1441
1442 let _ =
1444 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
1445 })
1446 .unwrap();
1447
1448 join_handle_mock_monitors
1449 .join()
1450 .expect("Mock monitor check did not finish.");
1451 join_handle_mock_schedule_check
1452 .join()
1453 .expect("Mock schedule check did not finish.");
1454 join_handle_test_environment
1455 .join()
1456 .expect("Test environment thread did not finish.");
1457 join_handle_test_object
1458 .join()
1459 .expect("Test object thread did not finish.");
1460 }
1461
1462 #[test]
1463 pub fn test_refill_initial_waiting_time() {
1467 let sleep_duration_50_millis = Duration::from_millis(50);
1468 let spin_sleeper = SpinSleeper::default();
1469
1470 let (config, mut refill, mut sql_interface, sql_interface_refill) =
1471 prepare_refill_tests(None, 2, 60, Some(21));
1472
1473 let mut channels = Channels::new_for_test();
1474
1475 let (
1477 tx_mock_water_injection_to_test_environment,
1478 mut rx_test_environment_from_mock_water_injection,
1479 ) = channel(1);
1480 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
1481 channel::<InternalCommand>(1);
1482
1483 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
1485 Ok(_) => {}
1486 Err(e) => {
1487 panic!("Could not prepare test case: {e:?}")
1488 }
1489 }
1490
1491 let mutex_device_scheduler = Arc::new(Mutex::new(0));
1492 let mutex_tank_level_switch_signals =
1493 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
1494 let refill_status = RefillStatus {
1495 refill_in_progress_live: false,
1496 refill_in_progress_for_database: false,
1497 };
1498 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
1499
1500 let mut mock_monitors = MockMonitors::new();
1501
1502 let mut mock_water_injection = MockWaterInjection::new(
1503 Some(tx_mock_water_injection_to_test_environment),
1504 RefillErrorStates {
1505 error_switch_stuck_high: false,
1506 error_switch_stuck_low: false,
1507 error_receive_tank_level_switch_position: false,
1508 error_sql_update_failed: false,
1509 error_sql_get_historic_data_failed: false,
1510 },
1511 );
1512
1513 let join_handle_mock_monitors = thread::Builder::new()
1515 .name("mock_monitor".to_string())
1516 .spawn(move || {
1517 mock_monitors.execute(
1518 channels.monitors.rx_monitors_from_refill,
1519 rx_monitors_from_test_environment,
1520 );
1521 })
1522 .unwrap();
1523
1524 let join_handle_mock_schedule_check = thread::Builder::new()
1526 .name("mock_schedule_check".to_string())
1527 .spawn(move || {
1528 mock_schedule_check(
1529 &mut channels.schedule_check.tx_schedule_check_to_refill,
1530 &mut channels.schedule_check.rx_schedule_check_from_refill,
1531 None,
1532 true,
1533 );
1534 })
1535 .unwrap();
1536
1537 let join_handle_test_environment = thread::Builder::new()
1538 .name("test_environment".to_string())
1539 .spawn(move || {
1540 let start_time = Instant::now();
1541
1542 let _ = rx_test_environment_from_mock_water_injection
1544 .recv()
1545 .unwrap();
1546
1547 let initial_waiting_time_passed = Instant::now();
1549
1550 let _ = channels
1552 .signal_handler
1553 .send_to_refill(InternalCommand::Quit);
1554 channels.signal_handler.receive_from_refill().unwrap();
1555 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
1556 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
1557
1558 let _ = channels
1559 .signal_handler
1560 .send_to_refill(InternalCommand::Terminate);
1561 let finish_time = Instant::now();
1562 let initial_wait_duration_millis = initial_waiting_time_passed
1563 .duration_since(start_time)
1564 .as_millis();
1565 let finalization_duration_millis = finish_time
1566 .duration_since(initial_waiting_time_passed)
1567 .as_millis();
1568
1569 assert_le!(
1570 initial_wait_duration_millis,
1571 (config.refill.initial_wait_interval * 1000 + 200) as u128
1572 );
1573 assert_ge!(
1574 initial_wait_duration_millis,
1575 (config.refill.initial_wait_interval * 1000) as u128
1576 );
1577 assert_le!(finalization_duration_millis, 150u128);
1578 })
1579 .unwrap();
1580
1581 spin_sleeper.sleep(sleep_duration_50_millis);
1583
1584 let join_handle_test_object = thread::Builder::new()
1586 .name("test_object".to_string())
1587 .spawn(move || {
1588 let mut tx_refill_to_schedule_check_for_test_case_finish =
1589 channels.refill.tx_refill_to_schedule_check.clone();
1590
1591 refill.execute(
1592 mutex_device_scheduler,
1593 &mut channels.refill,
1594 &mut mock_water_injection,
1595 mutex_tank_level_switch_signals,
1596 mutex_refill_status,
1597 Box::new(sql_interface_refill),
1598 );
1599
1600 let _ =
1602 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
1603 })
1604 .unwrap();
1605
1606 join_handle_mock_monitors
1607 .join()
1608 .expect("Mock monitor check did not finish.");
1609 join_handle_mock_schedule_check
1610 .join()
1611 .expect("Mock schedule check did not finish.");
1612 join_handle_test_environment
1613 .join()
1614 .expect("Test environment thread did not finish.");
1615 join_handle_test_object
1616 .join()
1617 .expect("Test object thread did not finish.");
1618 }
1619
1620 #[test]
1621 pub fn test_refill_conditions_historic_data_error_switch_stuck_low() {
1626 let sleep_duration_50_millis = Duration::from_millis(50);
1627 let spin_sleeper = SpinSleeper::default();
1628 let (_, mut refill, mut sql_interface, sql_interface_refill) =
1629 prepare_refill_tests(None, 1, 1, Some(22));
1630
1631 refill.refill_errors.error_switch_stuck_low = true;
1633
1634 let mut channels = Channels::new_for_test();
1635
1636 let (
1638 tx_mock_water_injection_to_test_environment,
1639 mut rx_test_environment_from_mock_water_injection,
1640 ) = channel(1);
1641 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
1642 channel::<InternalCommand>(1);
1643
1644 let refill_status = RefillStatus {
1645 refill_in_progress_live: false,
1646 refill_in_progress_for_database: false,
1647 };
1648 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
1649
1650 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
1652 Ok(_) => {}
1653 Err(e) => {
1654 panic!("Could not prepare test case: {e:?}")
1655 }
1656 }
1657
1658 let mutex_device_scheduler = Arc::new(Mutex::new(0));
1659 let mutex_tank_level_switch_signals =
1660 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
1661 let mutex_tank_level_switch_signals_clone_for_test_environment =
1662 mutex_tank_level_switch_signals.clone();
1663
1664 let mut mock_monitors = MockMonitors::new();
1665
1666 let mut mock_water_injection = MockWaterInjection::new(
1667 Some(tx_mock_water_injection_to_test_environment),
1668 RefillErrorStates {
1669 error_switch_stuck_high: false,
1670 error_switch_stuck_low: false,
1671 error_receive_tank_level_switch_position: false,
1672 error_sql_update_failed: false,
1673 error_sql_get_historic_data_failed: false,
1674 },
1675 );
1676
1677 let join_handle_mock_monitors = thread::Builder::new()
1679 .name("mock_monitor".to_string())
1680 .spawn(move || {
1681 mock_monitors.execute(
1682 channels.monitors.rx_monitors_from_refill,
1683 rx_monitors_from_test_environment,
1684 );
1685 })
1686 .unwrap();
1687
1688 let join_handle_mock_schedule_check = thread::Builder::new()
1690 .name("mock_schedule_check".to_string())
1691 .spawn(move || {
1692 mock_schedule_check(
1693 &mut channels.schedule_check.tx_schedule_check_to_refill,
1694 &mut channels.schedule_check.rx_schedule_check_from_refill,
1695 None,
1696 true,
1697 );
1698 })
1699 .unwrap();
1700
1701 let join_handle_test_environment = thread::Builder::new()
1702 .name("test_environment".to_string())
1703 .spawn(move || {
1704 let sleep_duration_two_secs = Duration::from_secs(2);
1705 let sleep_duration_two_millis = Duration::from_millis(2);
1706 let spin_sleeper = SpinSleeper::default();
1707
1708 spin_sleeper.sleep(sleep_duration_two_secs);
1709
1710 for _ in 0..999 {
1711 assert!(matches!(
1712 rx_test_environment_from_mock_water_injection.try_recv(),
1713 Err(AquaChannelError::Empty)
1714 ));
1715 spin_sleeper.sleep(sleep_duration_two_millis);
1716 }
1717
1718 println!("resetting errors...");
1720 match channels
1721 .messaging
1722 .tx_messaging_to_refill
1723 .send(InternalCommand::ResetAllErrors)
1724 {
1725 Ok(_) => { }
1726 Err(e) => {
1727 panic!(
1728 "test_refill_conditions_historic_data_error_recent_refill_event:\
1729 error when trying to reset refill errors from previous test runs: {e:?}"
1730 );
1731 }
1732 }
1733
1734 println!("waiting for water injection...");
1736 let _ = rx_test_environment_from_mock_water_injection
1737 .recv()
1738 .unwrap();
1739
1740 spin_sleeper.sleep(sleep_duration_two_secs);
1741
1742 println!("updating tank level switch...");
1744 {
1745 let mut tank_level_switch_signals =
1746 mutex_tank_level_switch_signals_clone_for_test_environment
1747 .lock()
1748 .unwrap();
1749 tank_level_switch_signals.tank_level_switch_position = true;
1750 tank_level_switch_signals.tank_level_switch_position_stabilized = true;
1751 }
1752
1753 spin_sleeper.sleep(sleep_duration_two_secs);
1754
1755 println!("sending quit signal to test object...");
1756 let _ = channels
1757 .signal_handler
1758 .send_to_refill(InternalCommand::Quit);
1759 channels.signal_handler.receive_from_refill().unwrap();
1760 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
1761
1762 let _ = channels
1763 .signal_handler
1764 .send_to_refill(InternalCommand::Terminate);
1765
1766 spin_sleeper.sleep(sleep_duration_two_secs);
1769 })
1770 .unwrap();
1771
1772 spin_sleeper.sleep(sleep_duration_50_millis);
1774
1775 let join_handle_test_object = thread::Builder::new()
1777 .name("test_object".to_string())
1778 .spawn(move || {
1779 let mut tx_refill_to_schedule_check_for_test_case_finish =
1780 channels.refill.tx_refill_to_schedule_check.clone();
1781
1782 refill.execute(
1783 mutex_device_scheduler,
1784 &mut channels.refill,
1785 &mut mock_water_injection,
1786 mutex_tank_level_switch_signals,
1787 mutex_refill_status,
1788 Box::new(sql_interface_refill),
1789 );
1790
1791 assert_eq!(mock_water_injection.injection_recorder.is_empty(), false);
1793
1794 let _ =
1796 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
1797 })
1798 .unwrap();
1799
1800 join_handle_mock_monitors
1801 .join()
1802 .expect("Mock monitor check did not finish.");
1803 join_handle_mock_schedule_check
1804 .join()
1805 .expect("Mock schedule check did not finish.");
1806 join_handle_test_environment
1807 .join()
1808 .expect("Test environment thread did not finish.");
1809 join_handle_test_object
1810 .join()
1811 .expect("Test object thread did not finish.");
1812 }
1813
1814 #[test]
1815 pub fn test_refill_conditions_error_sql_update_failed() {
1819 let sleep_duration_50_millis = Duration::from_millis(50);
1820 let spin_sleeper = SpinSleeper::default();
1821 let (_, mut refill, mut sql_interface, sql_interface_refill) =
1822 prepare_refill_tests(None, 1, 1, Some(23));
1823
1824 refill.refill_errors.error_sql_update_failed = true;
1826
1827 let mut channels = Channels::new_for_test();
1828
1829 let (
1831 tx_mock_water_injection_to_test_environment,
1832 mut rx_test_environment_from_mock_water_injection,
1833 ) = channel(1);
1834 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
1835 channel::<InternalCommand>(1);
1836
1837 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
1839 Ok(_) => {}
1840 Err(e) => {
1841 panic!("Could not prepare test case: {e:?}")
1842 }
1843 }
1844
1845 let mutex_device_scheduler = Arc::new(Mutex::new(0));
1846 let mutex_tank_level_switch_signals =
1847 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
1848 let refill_status = RefillStatus {
1849 refill_in_progress_live: false,
1850 refill_in_progress_for_database: false,
1851 };
1852 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
1853
1854 let mut mock_monitors = MockMonitors::new();
1855
1856 let mut mock_water_injection = MockWaterInjection::new(
1857 Some(tx_mock_water_injection_to_test_environment),
1858 RefillErrorStates {
1859 error_switch_stuck_high: false,
1860 error_switch_stuck_low: false,
1861 error_receive_tank_level_switch_position: false,
1862 error_sql_update_failed: false,
1863 error_sql_get_historic_data_failed: false,
1864 },
1865 );
1866
1867 let join_handle_mock_monitors = thread::Builder::new()
1869 .name("mock_monitor".to_string())
1870 .spawn(move || {
1871 mock_monitors.execute(
1872 channels.monitors.rx_monitors_from_refill,
1873 rx_monitors_from_test_environment,
1874 );
1875 })
1876 .unwrap();
1877
1878 let join_handle_mock_schedule_check = thread::Builder::new()
1880 .name("mock_schedule_check".to_string())
1881 .spawn(move || {
1882 mock_schedule_check(
1883 &mut channels.schedule_check.tx_schedule_check_to_refill,
1884 &mut channels.schedule_check.rx_schedule_check_from_refill,
1885 None,
1886 true,
1887 );
1888 })
1889 .unwrap();
1890
1891 let join_handle_test_environment = thread::Builder::new()
1893 .name("test_environment".to_string())
1894 .spawn(move || {
1895 let sleep_duration_two_secs = Duration::from_secs(2);
1896 let sleep_duration_two_millis = Duration::from_millis(2);
1897 let spin_sleeper = SpinSleeper::default();
1898
1899 spin_sleeper.sleep(sleep_duration_two_secs);
1900
1901 for _ in 0..999 {
1902 assert!(matches!(
1903 rx_test_environment_from_mock_water_injection.try_recv(),
1904 Err(AquaChannelError::Empty)
1905 ));
1906 spin_sleeper.sleep(sleep_duration_two_millis);
1907 }
1908
1909 println!("sending quit signal to test object...");
1910 let _ = channels
1911 .signal_handler
1912 .send_to_refill(InternalCommand::Quit);
1913 channels.signal_handler.receive_from_refill().unwrap();
1914 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
1915
1916 let _ = channels
1917 .signal_handler
1918 .send_to_refill(InternalCommand::Terminate);
1919
1920 spin_sleeper.sleep(sleep_duration_two_secs);
1923 })
1924 .unwrap();
1925
1926 spin_sleeper.sleep(sleep_duration_50_millis);
1928
1929 let join_handle_test_object = thread::Builder::new()
1931 .name("test_object".to_string())
1932 .spawn(move || {
1933 let sleep_duration_two_millis = Duration::from_millis(2);
1934 let spin_sleeper = SpinSleeper::default();
1935
1936 let mut tx_refill_to_schedule_check_for_test_case_finish =
1937 channels.refill.tx_refill_to_schedule_check.clone();
1938
1939 refill.execute(
1940 mutex_device_scheduler,
1941 &mut channels.refill,
1942 &mut mock_water_injection,
1943 mutex_tank_level_switch_signals,
1944 mutex_refill_status,
1945 Box::new(sql_interface_refill),
1946 );
1947
1948 assert_eq!(mock_water_injection.injection_recorder.is_empty(), true);
1950
1951 let _ =
1953 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
1954
1955 spin_sleeper.sleep(sleep_duration_two_millis);
1956 })
1957 .unwrap();
1958
1959 join_handle_mock_monitors
1960 .join()
1961 .expect("Mock monitor check did not finish.");
1962 join_handle_mock_schedule_check
1963 .join()
1964 .expect("Mock schedule check did not finish.");
1965 join_handle_test_environment
1966 .join()
1967 .expect("Test environment thread did not finish.");
1968 join_handle_test_object
1969 .join()
1970 .expect("Test object thread did not finish.");
1971 }
1972
1973 #[test]
1974 pub fn test_refill_process_external_request_reset_all_errors_command() {
1979 let refill_errors = RefillErrorStates {
1981 error_switch_stuck_high: true,
1982 error_switch_stuck_low: true,
1983 error_receive_tank_level_switch_position: true,
1984 error_sql_update_failed: true,
1985 error_sql_get_historic_data_failed: true,
1986 };
1987
1988 let (_, mut refill, mut sql_interface, sql_interface_refill) =
1989 prepare_refill_tests(Some(refill_errors), 2, 60, Some(24));
1990
1991 let sleep_duration_50_millis = Duration::from_millis(50);
1992 let spin_sleeper = SpinSleeper::default();
1993
1994 let mut channels = Channels::new_for_test();
1995
1996 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
1997 channel::<InternalCommand>(1);
1998 let (
1999 tx_mock_water_injection_to_test_environment,
2000 _rx_test_environment_from_mock_water_injection,
2001 ) = channel(1);
2002
2003 let mut mock_monitors = MockMonitors::new();
2004
2005 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
2007 Ok(_) => {}
2008 Err(e) => {
2009 panic!("Could not prepare test case: {e:?}")
2010 }
2011 }
2012
2013 let mutex_device_scheduler = Arc::new(Mutex::new(0));
2014 let mutex_tank_level_switch_signals =
2015 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
2016 let refill_status = RefillStatus {
2017 refill_in_progress_live: false,
2018 refill_in_progress_for_database: false,
2019 };
2020 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
2021
2022 let mut mock_water_injection = MockWaterInjection::new(
2023 Some(tx_mock_water_injection_to_test_environment),
2024 RefillErrorStates {
2025 error_switch_stuck_high: false,
2026 error_switch_stuck_low: false,
2027 error_receive_tank_level_switch_position: false,
2028 error_sql_update_failed: false,
2029 error_sql_get_historic_data_failed: false,
2030 },
2031 );
2032
2033 let join_handle_mock_monitors = thread::Builder::new()
2035 .name("mock_monitor".to_string())
2036 .spawn(move || {
2037 mock_monitors.execute(
2038 channels.monitors.rx_monitors_from_refill,
2039 rx_monitors_from_test_environment,
2040 );
2041 })
2042 .unwrap();
2043
2044 let join_handle_mock_schedule_check = thread::Builder::new()
2046 .name("mock_schedule_check".to_string())
2047 .spawn(move || {
2048 mock_schedule_check(
2049 &mut channels.schedule_check.tx_schedule_check_to_refill,
2050 &mut channels.schedule_check.rx_schedule_check_from_refill,
2051 None,
2052 true,
2053 );
2054 })
2055 .unwrap();
2056
2057 let join_handle_test_environment = thread::Builder::new()
2058 .name("test_environment".to_string())
2059 .spawn(move || {
2060 let sleep_duration_two_secs = Duration::from_secs(2);
2061 let spin_sleeper = SpinSleeper::default();
2062
2063 spin_sleeper.sleep(sleep_duration_two_secs);
2064 let result = channels
2065 .messaging
2066 .tx_messaging_to_refill
2067 .send(InternalCommand::ResetAllErrors);
2068 assert!(result.is_ok());
2069 spin_sleeper.sleep(sleep_duration_two_secs);
2070
2071 let _ = channels
2072 .signal_handler
2073 .send_to_refill(InternalCommand::Quit);
2074 channels.signal_handler.receive_from_refill().unwrap();
2075 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
2076
2077 let _ = channels
2078 .signal_handler
2079 .send_to_refill(InternalCommand::Terminate);
2080
2081 spin_sleeper.sleep(sleep_duration_two_secs);
2084 })
2085 .unwrap();
2086
2087 spin_sleeper.sleep(sleep_duration_50_millis);
2089
2090 let join_handle_test_object = thread::Builder::new()
2092 .name("test_object".to_string())
2093 .spawn(move || {
2094 let sleep_duration_two_millis = Duration::from_millis(2);
2095 let spin_sleeper = SpinSleeper::default();
2096
2097 assert_eq!(refill.refill_errors.has_error(), true);
2099
2100 let mut tx_refill_to_schedule_check_for_test_case_finish =
2101 channels.refill.tx_refill_to_schedule_check.clone();
2102
2103 refill.execute(
2104 mutex_device_scheduler,
2105 &mut channels.refill,
2106 &mut mock_water_injection,
2107 mutex_tank_level_switch_signals,
2108 mutex_refill_status,
2109 Box::new(sql_interface_refill),
2110 );
2111
2112 let _ =
2114 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
2115
2116 println!("{}", refill.refill_errors);
2117
2118 assert_eq!(refill.refill_errors.has_error(), false);
2120
2121 spin_sleeper.sleep(sleep_duration_two_millis);
2122 })
2123 .unwrap();
2124
2125 join_handle_mock_monitors
2126 .join()
2127 .expect("Mock monitor check did not finish.");
2128 join_handle_mock_schedule_check
2129 .join()
2130 .expect("Mock schedule check did not finish.");
2131 join_handle_test_environment
2132 .join()
2133 .expect("Test environment thread did not finish.");
2134 join_handle_test_object
2135 .join()
2136 .expect("Test object thread did not finish.");
2137 }
2138
2139 #[test]
2140 pub fn test_refill_blocked_by_schedule() {
2144 let sleep_duration_50_millis = Duration::from_millis(50);
2145 let spin_sleeper = SpinSleeper::default();
2146 let (_, mut refill, mut sql_interface, sql_interface_refill) =
2147 prepare_refill_tests(None, 1, 1, Some(25));
2148
2149 let mut channels = Channels::new_for_test();
2150
2151 let (
2152 tx_mock_water_injection_to_test_environment,
2153 mut rx_test_environment_from_mock_water_injection,
2154 ) = channel(1);
2155 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
2156 channel::<InternalCommand>(1);
2157
2158 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
2160 Ok(_) => {}
2161 Err(e) => {
2162 panic!("Could not prepare test case: {e:?}")
2163 }
2164 }
2165
2166 let mutex_device_scheduler = Arc::new(Mutex::new(0));
2167 let mutex_tank_level_switch_signals =
2168 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
2169 let refill_status = RefillStatus {
2170 refill_in_progress_live: false,
2171 refill_in_progress_for_database: false,
2172 };
2173 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
2174
2175 let mut mock_monitors = MockMonitors::new();
2176
2177 let mut mock_water_injection = MockWaterInjection::new(
2178 Some(tx_mock_water_injection_to_test_environment),
2179 RefillErrorStates {
2180 error_switch_stuck_high: false,
2181 error_switch_stuck_low: false,
2182 error_receive_tank_level_switch_position: false,
2183 error_sql_update_failed: false,
2184 error_sql_get_historic_data_failed: false,
2185 },
2186 );
2187
2188 let join_handle_mock_monitors = thread::Builder::new()
2190 .name("mock_monitor".to_string())
2191 .spawn(move || {
2192 mock_monitors.execute(
2193 channels.monitors.rx_monitors_from_refill,
2194 rx_monitors_from_test_environment,
2195 );
2196 })
2197 .unwrap();
2198
2199 let join_handle_mock_schedule_check = thread::Builder::new()
2201 .name("mock_schedule_check".to_string())
2202 .spawn(move || {
2203 mock_schedule_check(
2204 &mut channels.schedule_check.tx_schedule_check_to_refill,
2205 &mut channels.schedule_check.rx_schedule_check_from_refill,
2206 None,
2207 false,
2208 );
2209 })
2210 .unwrap();
2211
2212 let join_handle_test_environment = thread::Builder::new()
2213 .name("test_environment".to_string())
2214 .spawn(move || {
2215 let sleep_duration_two_secs = Duration::from_secs(2);
2216 let sleep_duration_two_millis = Duration::from_millis(2);
2217 let spin_sleeper = SpinSleeper::default();
2218
2219 spin_sleeper.sleep(sleep_duration_two_secs);
2220
2221 for _ in 0..999 {
2222 assert!(matches!(
2223 rx_test_environment_from_mock_water_injection.try_recv(),
2224 Err(AquaChannelError::Empty)
2225 ));
2226 spin_sleeper.sleep(sleep_duration_two_millis);
2227 }
2228
2229 println!("sending quit signal to test object...");
2230 let _ = channels
2231 .signal_handler
2232 .send_to_refill(InternalCommand::Quit);
2233 channels.signal_handler.receive_from_refill().unwrap();
2234 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
2235
2236 let _ = channels
2237 .signal_handler
2238 .send_to_refill(InternalCommand::Terminate);
2239
2240 spin_sleeper.sleep(sleep_duration_two_secs);
2243 })
2244 .unwrap();
2245
2246 spin_sleeper.sleep(sleep_duration_50_millis);
2248
2249 let join_handle_test_object = thread::Builder::new()
2251 .name("test_object".to_string())
2252 .spawn(move || {
2253 let sleep_duration_two_millis = Duration::from_millis(2);
2254 let spin_sleeper = SpinSleeper::default();
2255
2256 let mut tx_refill_to_schedule_check_for_test_case_finish =
2257 channels.refill.tx_refill_to_schedule_check.clone();
2258
2259 refill.execute(
2260 mutex_device_scheduler,
2261 &mut channels.refill,
2262 &mut mock_water_injection,
2263 mutex_tank_level_switch_signals,
2264 mutex_refill_status,
2265 Box::new(sql_interface_refill),
2266 );
2267
2268 assert_eq!(mock_water_injection.injection_recorder.is_empty(), true);
2270
2271 let _ =
2273 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
2274
2275 spin_sleeper.sleep(sleep_duration_two_millis);
2276 })
2277 .unwrap();
2278
2279 join_handle_mock_monitors
2280 .join()
2281 .expect("Mock monitor check did not finish.");
2282 join_handle_mock_schedule_check
2283 .join()
2284 .expect("Mock schedule check did not finish.");
2285 join_handle_test_environment
2286 .join()
2287 .expect("Test environment thread did not finish.");
2288 join_handle_test_object
2289 .join()
2290 .expect("Test object thread did not finish.");
2291 }
2292
2293 #[test]
2294 pub fn test_messaging_stops_starts_refill() {
2299 let sleep_duration_50_millis = Duration::from_millis(50);
2300 let spin_sleeper = SpinSleeper::default();
2301 let (_, mut refill, mut sql_interface, sql_interface_refill) =
2302 prepare_refill_tests(None, 10, 60, Some(26));
2303
2304 let mut channels = Channels::new_for_test();
2305
2306 let (
2307 tx_mock_water_injection_to_test_environment,
2308 mut rx_test_environment_from_mock_water_injection,
2309 ) = channel(1);
2310 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
2311 channel::<InternalCommand>(1);
2312
2313 match SqlInterface::truncate_table(&mut sql_interface, "refill".to_string()) {
2315 Ok(_) => {}
2316 Err(e) => {
2317 panic!("Could not prepare test case: {e:?}")
2318 }
2319 }
2320
2321 let mut mock_monitors = MockMonitors::new();
2322
2323 let mutex_device_scheduler = Arc::new(Mutex::new(0));
2324 let mutex_tank_level_switch_signals =
2325 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
2326 let mutex_tank_level_switch_signals_clone_for_test_environment =
2327 mutex_tank_level_switch_signals.clone();
2328 let refill_status = RefillStatus {
2329 refill_in_progress_live: false,
2330 refill_in_progress_for_database: false,
2331 };
2332 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
2333
2334 let mut mock_water_injection = MockWaterInjection::new(
2335 Some(tx_mock_water_injection_to_test_environment),
2336 RefillErrorStates {
2337 error_switch_stuck_high: false,
2338 error_switch_stuck_low: false,
2339 error_receive_tank_level_switch_position: false,
2340 error_sql_update_failed: false,
2341 error_sql_get_historic_data_failed: false,
2342 },
2343 );
2344
2345 let join_handle_mock_monitors = thread::Builder::new()
2347 .name("mock_monitor".to_string())
2348 .spawn(move || {
2349 mock_monitors.execute(
2350 channels.monitors.rx_monitors_from_refill,
2351 rx_monitors_from_test_environment,
2352 );
2353 })
2354 .unwrap();
2355
2356 let join_handle_mock_schedule_check = thread::Builder::new()
2358 .name("mock_schedule_check".to_string())
2359 .spawn(move || {
2360 mock_schedule_check(
2361 &mut channels.schedule_check.tx_schedule_check_to_refill,
2362 &mut channels.schedule_check.rx_schedule_check_from_refill,
2363 None,
2364 true,
2365 );
2366 })
2367 .unwrap();
2368
2369 let join_handle_test_environment = thread::Builder::new()
2370 .name("test_environment".to_string())
2371 .spawn(move || {
2372 let sleep_duration_one_sec = Duration::from_secs(1);
2373 let sleep_duration_two_secs = Duration::from_secs(2);
2374 let sleep_duration_two_millis = Duration::from_millis(2);
2375 let spin_sleeper = SpinSleeper::default();
2376
2377 spin_sleeper.sleep(sleep_duration_one_sec);
2378
2379 match channels
2380 .messaging
2381 .tx_messaging_to_refill
2382 .send(InternalCommand::Stop)
2383 {
2384 Ok(()) => { }
2385 Err(e) => {
2386 panic!(
2387 "{}: could not send stop command to refill ({e:?})",
2388 module_path!()
2389 );
2390 }
2391 }
2392
2393 spin_sleeper.sleep(sleep_duration_one_sec);
2394
2395 {
2396 let mut tank_level_switch_signals =
2397 mutex_tank_level_switch_signals_clone_for_test_environment
2398 .lock()
2399 .unwrap();
2400 tank_level_switch_signals.tank_level_switch_position = false;
2401 tank_level_switch_signals.tank_level_switch_position_stabilized = false;
2402 }
2403
2404 for _ in 0..999 {
2406 assert!(matches!(
2407 rx_test_environment_from_mock_water_injection.try_recv(),
2408 Err(AquaChannelError::Empty)
2409 ));
2410 spin_sleeper.sleep(sleep_duration_two_millis);
2411 }
2412
2413 spin_sleeper.sleep(sleep_duration_one_sec);
2414
2415 match channels
2416 .messaging
2417 .tx_messaging_to_refill
2418 .send(InternalCommand::Start)
2419 {
2420 Ok(()) => { }
2421 Err(e) => {
2422 panic!(
2423 "{}: could not send start command to refill ({e:?})",
2424 module_path!()
2425 );
2426 }
2427 }
2428
2429 assert!(matches!(
2431 rx_test_environment_from_mock_water_injection.recv(),
2432 Ok(TestCommand::InformWaterInjectionEvent)
2433 ));
2434
2435 println!("sending quit signal to test object...");
2436 let _ = channels
2437 .signal_handler
2438 .send_to_refill(InternalCommand::Quit);
2439 channels.signal_handler.receive_from_refill().unwrap();
2440 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
2441
2442 let _ = channels
2443 .signal_handler
2444 .send_to_refill(InternalCommand::Terminate);
2445
2446 spin_sleeper.sleep(sleep_duration_two_secs);
2449 })
2450 .unwrap();
2451
2452 spin_sleeper.sleep(sleep_duration_50_millis);
2454
2455 let join_handle_test_object = thread::Builder::new()
2457 .name("test_object".to_string())
2458 .spawn(move || {
2459 let sleep_duration_two_millis = Duration::from_millis(2);
2460 let spin_sleeper = SpinSleeper::default();
2461
2462 let mut tx_refill_to_schedule_check_for_test_case_finish =
2463 channels.refill.tx_refill_to_schedule_check.clone();
2464
2465 refill.execute(
2466 mutex_device_scheduler,
2467 &mut channels.refill,
2468 &mut mock_water_injection,
2469 mutex_tank_level_switch_signals,
2470 mutex_refill_status,
2471 Box::new(sql_interface_refill),
2472 );
2473
2474 assert_eq!(mock_water_injection.injection_recorder.len(), 1);
2476
2477 let _ =
2479 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
2480
2481 spin_sleeper.sleep(sleep_duration_two_millis);
2482 })
2483 .unwrap();
2484
2485 join_handle_mock_monitors
2486 .join()
2487 .expect("Mock monitor check did not finish.");
2488 join_handle_mock_schedule_check
2489 .join()
2490 .expect("Mock schedule check did not finish.");
2491 join_handle_test_environment
2492 .join()
2493 .expect("Test environment thread did not finish.");
2494 join_handle_test_object
2495 .join()
2496 .expect("Test object thread did not finish.");
2497 }
2498
2499 #[test]
2500 pub fn test_refill_conditions_error_get_historic_data_failed() {
2505 let sleep_duration_50_millis = Duration::from_millis(50);
2506 let spin_sleeper = SpinSleeper::default();
2507 let (_, mut refill, sql_interface_refill) =
2508 prepare_refill_tests_with_mock_database_interface(None, 1, 1, 27);
2509 let mut channels = Channels::new_for_test();
2513
2514 let (
2515 tx_mock_water_injection_to_test_environment,
2516 mut rx_test_environment_from_mock_water_injection,
2517 ) = channel(1);
2518 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
2519 channel::<InternalCommand>(1);
2520
2521 let mutex_device_scheduler = Arc::new(Mutex::new(0));
2522 let mutex_tank_level_switch_signals =
2523 Arc::new(Mutex::new(TankLevelSwitchSignals::new(false, false, false)));
2524 let refill_status = RefillStatus {
2525 refill_in_progress_live: false,
2526 refill_in_progress_for_database: false,
2527 };
2528 let mutex_refill_status = Arc::new(Mutex::new(refill_status));
2529
2530 let mut mock_monitors = MockMonitors::new();
2531
2532 let mut mock_water_injection = MockWaterInjection::new(
2533 Some(tx_mock_water_injection_to_test_environment),
2534 RefillErrorStates {
2535 error_switch_stuck_high: false,
2536 error_switch_stuck_low: false,
2537 error_receive_tank_level_switch_position: false,
2538 error_sql_update_failed: false,
2539 error_sql_get_historic_data_failed: false,
2540 },
2541 );
2542
2543 let join_handle_mock_monitors = thread::Builder::new()
2545 .name("mock_monitor".to_string())
2546 .spawn(move || {
2547 mock_monitors.execute(
2548 channels.monitors.rx_monitors_from_refill,
2549 rx_monitors_from_test_environment,
2550 );
2551 })
2552 .unwrap();
2553
2554 let join_handle_mock_schedule_check = thread::Builder::new()
2556 .name("mock_schedule_check".to_string())
2557 .spawn(move || {
2558 mock_schedule_check(
2559 &mut channels.schedule_check.tx_schedule_check_to_refill,
2560 &mut channels.schedule_check.rx_schedule_check_from_refill,
2561 None,
2562 true,
2563 );
2564 })
2565 .unwrap();
2566
2567 let join_handle_test_environment = thread::Builder::new()
2569 .name("test_environment".to_string())
2570 .spawn(move || {
2571 let sleep_duration_two_secs = Duration::from_secs(2);
2572 let sleep_duration_two_millis = Duration::from_millis(2);
2573 let spin_sleeper = SpinSleeper::default();
2574
2575 spin_sleeper.sleep(sleep_duration_two_secs);
2576
2577 for _ in 0..999 {
2578 assert!(matches!(
2579 rx_test_environment_from_mock_water_injection.try_recv(),
2580 Err(AquaChannelError::Empty)
2581 ));
2582 spin_sleeper.sleep(sleep_duration_two_millis);
2583 }
2584
2585 println!("sending quit signal to test object...");
2586 let _ = channels
2587 .signal_handler
2588 .send_to_refill(InternalCommand::Quit);
2589 channels.signal_handler.receive_from_refill().unwrap();
2590 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
2591
2592 let _ = channels
2593 .signal_handler
2594 .send_to_refill(InternalCommand::Terminate);
2595
2596 spin_sleeper.sleep(sleep_duration_two_secs);
2599 })
2600 .unwrap();
2601
2602 spin_sleeper.sleep(sleep_duration_50_millis);
2604
2605 let join_handle_test_object = thread::Builder::new()
2607 .name("test_object".to_string())
2608 .spawn(move || {
2609 let sleep_duration_two_millis = Duration::from_millis(2);
2610 let spin_sleeper = SpinSleeper::default();
2611
2612 let mut tx_refill_to_schedule_check_for_test_case_finish =
2613 channels.refill.tx_refill_to_schedule_check.clone();
2614
2615 refill.execute(
2616 mutex_device_scheduler,
2617 &mut channels.refill,
2618 &mut mock_water_injection,
2619 mutex_tank_level_switch_signals,
2620 mutex_refill_status,
2621 Box::new(sql_interface_refill),
2622 );
2623
2624 assert_eq!(mock_water_injection.injection_recorder.is_empty(), true);
2626
2627 let _ =
2629 tx_refill_to_schedule_check_for_test_case_finish.send(InternalCommand::Quit);
2630
2631 spin_sleeper.sleep(sleep_duration_two_millis);
2632 })
2633 .unwrap();
2634
2635 join_handle_mock_monitors
2636 .join()
2637 .expect("Mock monitor check did not finish.");
2638 join_handle_mock_schedule_check
2639 .join()
2640 .expect("Mock schedule check did not finish.");
2641 join_handle_test_environment
2642 .join()
2643 .expect("Test environment thread did not finish.");
2644 join_handle_test_object
2645 .join()
2646 .expect("Test object thread did not finish.");
2647 }
2648
2649 #[test]
2650 pub fn test_refill_check_volume_count_time_limits() {
2653 let mut mock_monitors = MockMonitors::new();
2654 let sleep_duration_200_millis = Duration::from_millis(200);
2655 let spin_sleeper = SpinSleeper::default();
2656
2657 let mut channels = Channels::new_for_test();
2658
2659 let (mut tx_test_environment_to_monitors, rx_monitors_from_test_environment) =
2660 channel::<InternalCommand>(1);
2661
2662 let join_handle_mock_monitors = thread::Builder::new()
2664 .name("mock_monitor".to_string())
2665 .spawn(move || {
2666 mock_monitors.execute(
2667 channels.monitors.rx_monitors_from_refill,
2668 rx_monitors_from_test_environment,
2669 );
2670 println!("{}", mock_monitors);
2671 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2672 refill_monitor_view.assert_refill_monitor_view(false, false, false, false, false);
2673
2674 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2675 refill_monitor_view.assert_refill_monitor_view(false, false, false, false, true);
2676
2677 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2678 refill_monitor_view.assert_refill_monitor_view(false, false, true, false, false);
2679
2680 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2681 refill_monitor_view.assert_refill_monitor_view(true, false, false, false, false);
2682
2683 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2684 refill_monitor_view.assert_refill_monitor_view(false, false, false, true, false);
2685
2686 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2687 refill_monitor_view.assert_refill_monitor_view(false, true, false, false, false);
2688
2689 let (_, refill_monitor_view) = mock_monitors.refill_monitor_views.pop().unwrap();
2690 refill_monitor_view.assert_refill_monitor_view(false, false, false, false, false);
2691 })
2692 .unwrap();
2693
2694 let (config, mut refill, _sql_interface_refill) =
2695 prepare_refill_tests_with_mock_database_interface(None, 1, 1, 27);
2696 let mut sql_refill_stats_data = RefillStatsData::new();
2700 sql_refill_stats_data.duration_since_last_refill =
2701 config.refill.min_interval_last_refill + 1;
2702
2703 assert_eq!(
2705 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2706 false
2707 );
2708 spin_sleeper.sleep(sleep_duration_200_millis);
2709
2710 sql_refill_stats_data.refill_count_last_24h = config.refill.max_refill_count_24h + 1;
2712
2713 assert_eq!(
2714 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2715 true
2716 );
2717 spin_sleeper.sleep(sleep_duration_200_millis);
2718
2719 sql_refill_stats_data.refill_count_last_24h = 0;
2721 sql_refill_stats_data.refill_count_last_hour = config.refill.max_refill_count_hour + 1;
2722
2723 assert_eq!(
2724 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2725 true
2726 );
2727 spin_sleeper.sleep(sleep_duration_200_millis);
2728
2729 sql_refill_stats_data.refill_count_last_hour = 0;
2731 sql_refill_stats_data.refill_volume_last_24h = config.refill.max_refill_volume_24h + 1.0;
2732
2733 assert_eq!(
2734 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2735 true
2736 );
2737 spin_sleeper.sleep(sleep_duration_200_millis);
2738
2739 sql_refill_stats_data.refill_volume_last_24h = 0.0;
2741 sql_refill_stats_data.refill_volume_last_hour = config.refill.max_refill_volume_hour + 1.0;
2742
2743 assert_eq!(
2744 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2745 true
2746 );
2747 spin_sleeper.sleep(sleep_duration_200_millis);
2748
2749 sql_refill_stats_data.refill_volume_last_hour = 0.0;
2751 sql_refill_stats_data.duration_since_last_refill =
2752 config.refill.min_interval_last_refill - 1;
2753
2754 assert_eq!(
2755 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2756 true
2757 );
2758 spin_sleeper.sleep(sleep_duration_200_millis);
2759
2760 sql_refill_stats_data.duration_since_last_refill =
2762 config.refill.min_interval_last_refill + 1;
2763 assert_eq!(
2764 refill.check_volume_count_time_limits(&sql_refill_stats_data, &mut channels.refill),
2765 false
2766 );
2767 spin_sleeper.sleep(sleep_duration_200_millis);
2768
2769 let _ = tx_test_environment_to_monitors.send(InternalCommand::Quit);
2770 spin_sleeper.sleep(sleep_duration_200_millis);
2772
2773 join_handle_mock_monitors
2774 .join()
2775 .expect("Mock monitor check did not finish.");
2776 }
2777}