1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
#[macro_export]
18
macro_rules! assert_expected_events {
19
	( $chain:ident, vec![$( $event_pat:pat => { $($attr:ident : $condition:expr, )* }, )*] ) => {
20
		let mut message: Vec<String> = Vec::new();
21
		let mut events = <$chain as xcm_emulator::Chain>::events();
22

            
23
		$(
24
			let mut event_received = false;
25
			let mut meet_conditions = true;
26
			let mut index_match = 0;
27
			let mut event_message: Vec<String> = Vec::new();
28

            
29
			for (index, event) in events.iter().enumerate() {
30
				// Variable to record current event's meet conditions
31
                #[allow(unused_mut)] // To suppress warning in case no conditions are declared
32
				let mut current_event_meet_conditions = true;
33
				match event {
34
					$event_pat => {
35
						event_received = true;
36

            
37
                        #[allow(unused_mut)] // To suppress warning in case no conditions are declared
38
						let mut conditions_message: Vec<String> = Vec::new();
39

            
40
						$(
41
							// We only want to record condition error messages in case it did not happened before
42
							// Only the first partial match is recorded
43
							if !$condition && event_message.is_empty() {
44
								conditions_message.push(
45
									format!(
46
										" - The attribute {:?} = {:?} did not met the condition {:?}\n",
47
										stringify!($attr),
48
										$attr,
49
										stringify!($condition)
50
									)
51
								);
52
							}
53
							current_event_meet_conditions &= $condition;
54
						)*
55

            
56
						// Set the variable to latest matched event's condition evaluation result
57
						meet_conditions = current_event_meet_conditions;
58

            
59
						// Set the index where we found a perfect match
60
						if event_received && meet_conditions {
61
							index_match = index;
62
							break;
63
						} else {
64
							event_message.extend(conditions_message);
65
						}
66
					},
67
					_ => {}
68
				}
69
			}
70

            
71
			if event_received && !meet_conditions  {
72
				message.push(
73
					format!(
74
						"\n\n{}::\x1b[31m{}\x1b[0m was received but some of its attributes did not meet the conditions:\n{}",
75
						stringify!($chain),
76
						stringify!($event_pat),
77
						event_message.concat()
78
					)
79
				);
80
			} else if !event_received {
81
				message.push(
82
					format!(
83
						"\n\n{}::\x1b[31m{}\x1b[0m was never received. All events:\n{:#?}",
84
						stringify!($chain),
85
						stringify!($event_pat),
86
						<$chain as xcm_emulator::Chain>::events(),
87
					)
88
				);
89
			} else {
90
				// If we find a perfect match we remove the event to avoid being potentially assessed multiple times
91
				events.remove(index_match);
92
			}
93
		)*
94

            
95
		if !message.is_empty() {
96
			// Log events as they will not be logged after the panic
97
			<$chain as xcm_emulator::Chain>::events().iter().for_each(|event| {
98
				log::debug!(target: concat!("events::", stringify!($chain)), "{:?}", event);
99
			});
100
			panic!("{}", message.concat())
101
		}
102
	}
103
}