1 /* mutest-matchers.c: Matching functions
2  *
3  * µTest - Copyright 2019  Emmanuele Bassi
4  *
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "mutest-private.h"
9 
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <math.h>
14 
15 bool
mutest_not(mutest_expect_t * e MUTEST_UNUSED,mutest_expect_res_t * check MUTEST_UNUSED)16 mutest_not (mutest_expect_t *e MUTEST_UNUSED,
17             mutest_expect_res_t *check MUTEST_UNUSED)
18 {
19   return true;
20 }
21 
22 bool
mutest_skip(mutest_expect_t * e MUTEST_UNUSED,mutest_expect_res_t * check MUTEST_UNUSED)23 mutest_skip (mutest_expect_t *e MUTEST_UNUSED,
24              mutest_expect_res_t *check MUTEST_UNUSED)
25 {
26   return true;
27 }
28 
29 static bool
mutest_to_be_boolean(mutest_expect_t * e,mutest_expect_res_t * check)30 mutest_to_be_boolean (mutest_expect_t *e,
31                       mutest_expect_res_t *check)
32 {
33   mutest_expect_res_t *value = e->value;
34 
35   if (value->expect_type == MUTEST_EXPECT_BOOLEAN &&
36       check->expect_type == MUTEST_EXPECT_BOOLEAN)
37     return value->expect.v_bool == check->expect.v_bool;
38 
39   return false;
40 }
41 
42 static inline bool
int_near_equal(int a,int b,int epsilon)43 int_near_equal (int a,
44                 int b,
45                 int epsilon)
46 {
47   return (a > b ? (a - b) : (b - a)) <= epsilon;
48 }
49 
50 static bool
mutest_to_be_int_value(mutest_expect_t * e,mutest_expect_res_t * check)51 mutest_to_be_int_value (mutest_expect_t *e,
52                         mutest_expect_res_t *check)
53 {
54   mutest_expect_res_t *value = e->value;
55 
56   if (value->expect_type == MUTEST_EXPECT_INT &&
57       check->expect_type == MUTEST_EXPECT_INT)
58     {
59       return int_near_equal (value->expect.v_int.value,
60                              check->expect.v_int.value,
61                              check->expect.v_int.tolerance);
62     }
63 
64   return false;
65 }
66 
67 static bool
mutest_to_be_in_int_range(mutest_expect_t * e,mutest_expect_res_t * check)68 mutest_to_be_in_int_range (mutest_expect_t *e,
69                            mutest_expect_res_t *check)
70 {
71   if (e->value->expect_type == MUTEST_EXPECT_INT &&
72       check->expect_type == MUTEST_EXPECT_INT_RANGE)
73     {
74       if (e->value->expect.v_int.value >= check->expect.v_irange.min &&
75           e->value->expect.v_int.value <= check->expect.v_irange.max)
76         return true;
77     }
78 
79   return false;
80 }
81 
82 static inline bool
float_near_equal(double a,double b,double epsilon)83 float_near_equal (double a,
84                   double b,
85                   double epsilon)
86 {
87   return (a > b ? (a - b) : (b - a)) <= epsilon;
88 }
89 
90 static bool
mutest_to_be_float_value(mutest_expect_t * e,mutest_expect_res_t * check)91 mutest_to_be_float_value (mutest_expect_t *e,
92                           mutest_expect_res_t *check)
93 {
94   mutest_expect_res_t *value = e->value;
95 
96   if (value->expect_type == MUTEST_EXPECT_FLOAT &&
97       check->expect_type == MUTEST_EXPECT_FLOAT)
98     {
99       return float_near_equal (value->expect.v_float.value,
100                                check->expect.v_float.value,
101                                check->expect.v_float.tolerance);
102     }
103 
104   return false;
105 }
106 
107 static bool
mutest_to_be_in_float_range(mutest_expect_t * e,mutest_expect_res_t * check)108 mutest_to_be_in_float_range (mutest_expect_t *e,
109                              mutest_expect_res_t *check)
110 {
111   if (e->value->expect_type == MUTEST_EXPECT_FLOAT &&
112       check->expect_type == MUTEST_EXPECT_FLOAT_RANGE)
113     {
114       if (e->value->expect.v_float.value >= check->expect.v_frange.min &&
115           e->value->expect.v_float.value <= check->expect.v_frange.max)
116         return true;
117     }
118 
119   return false;
120 }
121 
122 static bool
mutest_to_be_pointer(mutest_expect_t * e,mutest_expect_res_t * check)123 mutest_to_be_pointer (mutest_expect_t *e,
124                       mutest_expect_res_t *check)
125 {
126   mutest_expect_res_t *value = e->value;
127 
128   if (value->expect_type == MUTEST_EXPECT_POINTER &&
129       check->expect_type == MUTEST_EXPECT_POINTER)
130     return value->expect.v_pointer == check->expect.v_pointer;
131 
132   return false;
133 }
134 
135 static bool
mutest_to_be_string(mutest_expect_t * e,mutest_expect_res_t * check)136 mutest_to_be_string (mutest_expect_t *e,
137                      mutest_expect_res_t *check)
138 {
139   if (e->value->expect_type == MUTEST_EXPECT_STR &&
140       check->expect_type == MUTEST_EXPECT_STR)
141     {
142       if (e->value->expect.v_str.len != check->expect.v_str.len)
143         return false;
144 
145       if (e->value->expect.v_str.str == NULL && check->expect.v_str.str == NULL)
146         return true;
147 
148       if (e->value->expect.v_str.str != NULL &&
149           check->expect.v_str.str != NULL &&
150           strcmp (e->value->expect.v_str.str, check->expect.v_str.str) == 0)
151         return true;
152     }
153 
154   return false;
155 }
156 
157 bool
mutest_to_be(mutest_expect_t * e,mutest_expect_res_t * check)158 mutest_to_be (mutest_expect_t *e,
159               mutest_expect_res_t *check)
160 {
161   mutest_expect_res_t *value = e->value;
162 
163   if (value->expect_type != check->expect_type)
164     return false;
165 
166   switch (value->expect_type)
167     {
168     case MUTEST_EXPECT_BOOLEAN:
169       return mutest_to_be_boolean (e, check);
170 
171     case MUTEST_EXPECT_INT:
172       return mutest_to_be_int_value (e, check);
173 
174     case MUTEST_EXPECT_INT_RANGE:
175       return mutest_to_be_in_int_range (e, check);
176 
177     case MUTEST_EXPECT_FLOAT:
178       return mutest_to_be_float_value (e, check);
179 
180     case MUTEST_EXPECT_FLOAT_RANGE:
181       return mutest_to_be_in_float_range (e, check);
182 
183     case MUTEST_EXPECT_POINTER:
184       return mutest_to_be_pointer (e, check);
185 
186     case MUTEST_EXPECT_STR:
187       return mutest_to_be_string (e, check);
188 
189     case MUTEST_EXPECT_INVALID:
190       mutest_assert_if_reached ("invalid expect value");
191       break;
192     }
193 
194   return false;
195 }
196 
197 bool
mutest_to_be_close_to(mutest_expect_t * e,mutest_expect_res_t * check)198 mutest_to_be_close_to (mutest_expect_t *e,
199                        mutest_expect_res_t *check)
200 {
201   mutest_expect_res_t *value = e->value;
202 
203   if (value->expect_type == MUTEST_EXPECT_FLOAT)
204     return mutest_to_be_float_value (e, check);
205 
206   if (value->expect_type == MUTEST_EXPECT_INT)
207     return mutest_to_be_int_value (e, check);
208 
209   return false;
210 }
211 
212 bool
mutest_to_be_nan(mutest_expect_t * e,mutest_expect_res_t * check MUTEST_UNUSED)213 mutest_to_be_nan (mutest_expect_t *e,
214                   mutest_expect_res_t *check MUTEST_UNUSED)
215 {
216   mutest_expect_res_t *value = e->value;
217 
218   if (value->expect_type == MUTEST_EXPECT_FLOAT)
219     return isnan (value->expect.v_float.value) != 0;
220 
221   return false;
222 }
223 
224 bool
mutest_to_be_positive_infinity(mutest_expect_t * e,mutest_expect_res_t * check MUTEST_UNUSED)225 mutest_to_be_positive_infinity (mutest_expect_t *e,
226                                 mutest_expect_res_t *check MUTEST_UNUSED)
227 {
228   mutest_expect_res_t *value = e->value;
229 
230   if (value->expect_type == MUTEST_EXPECT_FLOAT)
231     return isinf (value->expect.v_float.value) != 0 && signbit (value->expect.v_float.value) == 0;
232 
233   return false;
234 }
235 
236 bool
mutest_to_be_negative_infinity(mutest_expect_t * e,mutest_expect_res_t * check MUTEST_UNUSED)237 mutest_to_be_negative_infinity (mutest_expect_t *e,
238                                 mutest_expect_res_t *check MUTEST_UNUSED)
239 {
240   mutest_expect_res_t *value = e->value;
241 
242   if (value->expect_type == MUTEST_EXPECT_FLOAT)
243     return isinf (value->expect.v_float.value) != 0 && signbit (value->expect.v_float.value) != 0;
244 
245   return false;
246 }
247 
248 bool
mutest_to_be_true(mutest_expect_t * e,mutest_expect_res_t * check MUTEST_UNUSED)249 mutest_to_be_true (mutest_expect_t *e,
250                    mutest_expect_res_t *check MUTEST_UNUSED)
251 {
252   mutest_expect_res_t *value = e->value;
253 
254   if (value->expect_type == MUTEST_EXPECT_BOOLEAN)
255     return value->expect.v_bool;
256 
257   if (value->expect_type == MUTEST_EXPECT_INT)
258     return value->expect.v_int.value != 0;
259 
260   return false;
261 }
262 
263 bool
mutest_to_be_false(mutest_expect_t * e,mutest_expect_res_t * check MUTEST_UNUSED)264 mutest_to_be_false (mutest_expect_t *e,
265                     mutest_expect_res_t *check MUTEST_UNUSED)
266 {
267   mutest_expect_res_t *value = e->value;
268 
269   if (value->expect_type == MUTEST_EXPECT_BOOLEAN)
270     return !value->expect.v_bool;
271 
272   if (value->expect_type == MUTEST_EXPECT_INT)
273     return value->expect.v_int.value == 0;
274 
275   return false;
276 }
277 
278 bool
mutest_to_be_null(mutest_expect_t * e,mutest_expect_res_t * check MUTEST_UNUSED)279 mutest_to_be_null (mutest_expect_t *e,
280                    mutest_expect_res_t *check MUTEST_UNUSED)
281 {
282   mutest_expect_res_t *value = e->value;
283 
284   if (value->expect_type == MUTEST_EXPECT_POINTER)
285     return value->expect.v_pointer == NULL;
286 
287   return false;
288 }
289 
290 bool
mutest_to_be_greater_than(mutest_expect_t * e,mutest_expect_res_t * check)291 mutest_to_be_greater_than (mutest_expect_t *e,
292                            mutest_expect_res_t *check)
293 {
294   mutest_expect_res_t *value = e->value;
295 
296   if (value->expect_type == MUTEST_EXPECT_INT && check->expect_type == MUTEST_EXPECT_INT)
297     return value->expect.v_int.value > check->expect.v_int.value;
298 
299   if (value->expect_type == MUTEST_EXPECT_FLOAT && check->expect_type == MUTEST_EXPECT_FLOAT)
300     return value->expect.v_float.value > check->expect.v_float.value;
301 
302   return false;
303 }
304 
305 bool
mutest_to_be_greater_than_or_equal(mutest_expect_t * e,mutest_expect_res_t * check)306 mutest_to_be_greater_than_or_equal (mutest_expect_t *e,
307                                     mutest_expect_res_t *check)
308 {
309   mutest_expect_res_t *value = e->value;
310 
311   if (value->expect_type == MUTEST_EXPECT_INT && check->expect_type == MUTEST_EXPECT_INT)
312     return value->expect.v_int.value >= check->expect.v_int.value;
313 
314   if (value->expect_type == MUTEST_EXPECT_FLOAT && check->expect_type == MUTEST_EXPECT_FLOAT)
315     return value->expect.v_float.value >= check->expect.v_float.value;
316 
317   return false;
318 }
319 
320 bool
mutest_to_be_less_than_or_equal(mutest_expect_t * e,mutest_expect_res_t * check)321 mutest_to_be_less_than_or_equal (mutest_expect_t *e,
322                                  mutest_expect_res_t *check)
323 {
324   mutest_expect_res_t *value = e->value;
325 
326   if (value->expect_type == MUTEST_EXPECT_INT && check->expect_type == MUTEST_EXPECT_INT)
327     return value->expect.v_int.value <= check->expect.v_int.value;
328 
329   if (value->expect_type == MUTEST_EXPECT_FLOAT && check->expect_type == MUTEST_EXPECT_FLOAT)
330     return value->expect.v_float.value <= check->expect.v_float.value;
331 
332   return false;
333 }
334 
335 bool
mutest_to_be_less_than(mutest_expect_t * e,mutest_expect_res_t * check)336 mutest_to_be_less_than (mutest_expect_t *e,
337                         mutest_expect_res_t *check)
338 {
339   mutest_expect_res_t *value = e->value;
340 
341   if (value->expect_type == MUTEST_EXPECT_INT && check->expect_type == MUTEST_EXPECT_INT)
342     return value->expect.v_int.value < check->expect.v_int.value;
343 
344   if (value->expect_type == MUTEST_EXPECT_FLOAT && check->expect_type == MUTEST_EXPECT_FLOAT)
345     return value->expect.v_float.value < check->expect.v_float.value;
346 
347   return false;
348 }
349 
350 bool
mutest_to_be_in_range(mutest_expect_t * e,mutest_expect_res_t * check)351 mutest_to_be_in_range (mutest_expect_t *e,
352                        mutest_expect_res_t *check)
353 {
354   mutest_expect_res_t *value = e->value;
355 
356   if (value->expect_type == MUTEST_EXPECT_INT)
357     return mutest_to_be_in_int_range (e, check);
358 
359   if (value->expect_type == MUTEST_EXPECT_FLOAT)
360     return mutest_to_be_in_float_range (e, check);
361 
362   return false;
363 }
364 
365 bool
mutest_to_contain(mutest_expect_t * e,mutest_expect_res_t * check)366 mutest_to_contain (mutest_expect_t *e,
367                    mutest_expect_res_t *check)
368 {
369   mutest_expect_res_t *value = e->value;
370 
371   if (value->expect_type == MUTEST_EXPECT_INT_RANGE &&
372       check->expect_type == MUTEST_EXPECT_INT)
373     {
374       if (check->expect.v_int.value >= value->expect.v_irange.min &&
375           check->expect.v_int.value <= value->expect.v_irange.max)
376         return true;
377 
378       return false;
379     }
380 
381   if (value->expect_type == MUTEST_EXPECT_FLOAT_RANGE &&
382       check->expect_type == MUTEST_EXPECT_FLOAT)
383     {
384       if (check->expect.v_float.value >= value->expect.v_frange.min &&
385           check->expect.v_float.value <= value->expect.v_frange.max)
386         return true;
387 
388       return false;
389     }
390 
391   if (value->expect_type == MUTEST_EXPECT_STR &&
392       check->expect_type == MUTEST_EXPECT_STR)
393     {
394       if (value->expect.v_str.len < check->expect.v_str.len)
395         return false;
396 
397       if (strstr (value->expect.v_str.str, check->expect.v_str.str) != NULL)
398         return true;
399     }
400 
401   return false;
402 }
403 
404 bool
mutest_to_contain_string(mutest_expect_t * e,mutest_expect_res_t * check)405 mutest_to_contain_string (mutest_expect_t *e,
406                           mutest_expect_res_t *check)
407 {
408   if (e->value->expect_type == MUTEST_EXPECT_STR &&
409       check->expect_type == MUTEST_EXPECT_STR)
410     {
411       if (e->value->expect.v_str.len < check->expect.v_str.len)
412         return false;
413 
414       if (strstr (e->value->expect.v_str.str, check->expect.v_str.str) != NULL)
415         return true;
416     }
417 
418   return false;
419 }
420 
421 bool
mutest_to_start_with_string(mutest_expect_t * e,mutest_expect_res_t * check)422 mutest_to_start_with_string (mutest_expect_t *e,
423                              mutest_expect_res_t *check)
424 {
425   if (e->value->expect_type == MUTEST_EXPECT_STR &&
426       check->expect_type == MUTEST_EXPECT_STR)
427     {
428       if (e->value->expect.v_str.len < check->expect.v_str.len)
429         return false;
430 
431       const char *str = e->value->expect.v_str.str;
432       const char *prefix = check->expect.v_str.str;
433 
434       size_t prefix_len = check->expect.v_str.len;
435 
436       return strncmp (str, prefix, prefix_len) == 0;
437     }
438 
439   return false;
440 }
441 
442 bool
mutest_to_end_with_string(mutest_expect_t * e,mutest_expect_res_t * check)443 mutest_to_end_with_string (mutest_expect_t *e,
444                            mutest_expect_res_t *check)
445 {
446   if (e->value->expect_type == MUTEST_EXPECT_STR &&
447       check->expect_type == MUTEST_EXPECT_STR)
448     {
449       if (e->value->expect.v_str.len < check->expect.v_str.len)
450         return false;
451 
452       const char *str = e->value->expect.v_str.str;
453       const char *suffix = check->expect.v_str.str;
454 
455       size_t str_len = e->value->expect.v_str.len;
456       size_t suffix_len = check->expect.v_str.len;
457 
458       return strcmp (str + str_len - suffix_len, suffix) == 0;
459     }
460 
461   return false;
462 }
463