1use crate::mock_runtime::{MockRuntime, MockStorage};
7use neo_types::*;
8use num_traits::{Signed, ToPrimitive};
9
10fn saturating_i64(value: &NeoInteger) -> i64 {
11 value.as_bigint().to_i64().unwrap_or_else(|| {
12 if value.as_bigint().is_negative() {
13 i64::MIN
14 } else {
15 i64::MAX
16 }
17 })
18}
19
20pub struct MethodCallResult {
22 result: Result<NeoValue, NeoError>,
23}
24
25impl MethodCallResult {
26 pub fn new(result: Result<NeoValue, NeoError>) -> Self {
27 Self { result }
28 }
29
30 pub fn ok(result: NeoValue) -> Self {
31 Self { result: Ok(result) }
32 }
33
34 pub fn err(error: NeoError) -> Self {
35 Self { result: Err(error) }
36 }
37
38 pub fn assert_ok(&self) {
39 assert!(
40 self.result.is_ok(),
41 "Expected Ok, got Err: {:?}",
42 self.result.as_ref().err()
43 );
44 }
45
46 pub fn assert_err(&self) {
47 assert!(
48 self.result.is_err(),
49 "Expected Err, got Ok: {:?}",
50 self.result.as_ref().ok()
51 );
52 }
53
54 pub fn assert_returns(&self, expected: i64) {
55 let value = self.expect_ok_value();
56 let integer = value
57 .as_integer()
58 .unwrap_or_else(|| panic!("Expected integer return value, got {:?}", value));
59 let actual = saturating_i64(integer);
60 assert_eq!(
61 actual, expected,
62 "Expected return value {}, got {}",
63 expected, actual
64 );
65 }
66
67 pub fn assert_returns_bool(&self, expected: bool) {
68 let value = self.expect_ok_value();
69 let actual = value
70 .as_boolean()
71 .unwrap_or_else(|| panic!("Expected boolean return value, got {:?}", value))
72 .as_bool();
73 assert_eq!(
74 actual, expected,
75 "Expected return value {}, got {}",
76 expected, actual
77 );
78 }
79
80 pub fn assert_returns_slice(&self, expected: &[u8]) {
81 let value = self.expect_ok_value();
82 let actual = value
83 .as_byte_string()
84 .unwrap_or_else(|| panic!("Expected byte string return value, got {:?}", value))
85 .as_slice();
86 assert_eq!(
87 actual, expected,
88 "Expected return value {:?}, got {:?}",
89 expected, actual
90 );
91 }
92
93 pub fn assert_returns_string(&self, expected: &str) {
94 let value = self.expect_ok_value();
95 let actual = value
96 .as_string()
97 .unwrap_or_else(|| panic!("Expected string return value, got {:?}", value))
98 .as_str();
99 assert_eq!(
100 actual, expected,
101 "Expected return value '{}', got '{}'",
102 expected, actual
103 );
104 }
105
106 pub fn assert_error(&self, expected: NeoError) {
107 match self.result.as_ref() {
108 Ok(value) => panic!("Expected Err({:?}), got Ok({:?})", expected, value),
109 Err(actual) => {
110 assert_eq!(
111 actual, &expected,
112 "Expected error {:?}, got {:?}",
113 expected, actual
114 )
115 }
116 }
117 }
118
119 pub fn value(&self) -> &NeoValue {
120 self.expect_ok_value()
121 }
122
123 pub fn error(&self) -> Option<&NeoError> {
124 self.result.as_ref().err()
125 }
126
127 fn expect_ok_value(&self) -> &NeoValue {
128 match self.result.as_ref() {
129 Ok(value) => value,
130 Err(error) => panic!("Expected Ok result, got Err: {:?}", error),
131 }
132 }
133}
134
135impl<T: Into<NeoValue>> From<Result<T, NeoError>> for MethodCallResult {
136 fn from(result: Result<T, NeoError>) -> Self {
137 Self::new(result.map(|v| v.into()))
138 }
139}
140
141pub struct StorageAssertions<'a> {
143 storage: &'a MockStorage,
144}
145
146impl<'a> StorageAssertions<'a> {
147 pub fn new(storage: &'a MockStorage) -> Self {
148 Self { storage }
149 }
150
151 pub fn contains(&self, key: &[u8]) -> bool {
152 self.storage.contains(key)
153 }
154
155 pub fn assert_contains(&self, key: &[u8]) {
156 assert!(
157 self.storage.contains(key),
158 "Expected storage to contain key {:?}",
159 key
160 );
161 }
162
163 pub fn assert_not_contains(&self, key: &[u8]) {
164 assert!(
165 !self.storage.contains(key),
166 "Expected storage to NOT contain key {:?}",
167 key
168 );
169 }
170
171 pub fn assert_value(&self, key: &[u8], expected: &[u8]) {
172 let actual = self.storage.get(key);
173 assert_eq!(
174 actual.as_deref(),
175 Some(expected),
176 "Expected storage key {:?} to have value {:?}, got {:?}",
177 key,
178 expected,
179 actual
180 );
181 }
182
183 pub fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
184 self.storage.get(key)
185 }
186}
187
188pub struct RuntimeAssertions<'a> {
190 runtime: &'a MockRuntime,
191}
192
193impl<'a> RuntimeAssertions<'a> {
194 pub fn new(runtime: &'a MockRuntime) -> Self {
195 Self { runtime }
196 }
197
198 pub fn assert_log_contains(&self, message: &str) {
199 let logs: &[String] = self.runtime.logs();
200 assert!(
201 logs.iter().any(|l: &String| l.contains(message)),
202 "Expected log to contain '{}', got {:?}",
203 message,
204 logs
205 );
206 }
207
208 pub fn assert_log_count(&self, count: usize) {
209 assert_eq!(
210 self.runtime.logs().len(),
211 count,
212 "Expected {} logs, got {}",
213 count,
214 self.runtime.logs().len()
215 );
216 }
217
218 pub fn assert_notification_count(&self, count: usize) {
219 assert_eq!(
220 self.runtime.notifications().len(),
221 count,
222 "Expected {} notifications, got {}",
223 count,
224 self.runtime.notifications().len()
225 );
226 }
227
228 pub fn assert_witness(&self, address: &[u8]) {
229 assert!(
230 self.runtime.check_witness(address),
231 "Expected witness for address {:?}",
232 address
233 );
234 }
235
236 pub fn logs(&self) -> &[String] {
237 self.runtime.logs()
238 }
239
240 pub fn notifications(&self) -> &[(NeoString, NeoArray<NeoValue>)] {
241 self.runtime.notifications()
242 }
243}