1 /* mutest-wrappers.c: Value wrappers
2  *
3  * µTest - Copyright 2019  Emmanuele Bassi
4  *
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "mutest-private.h"
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <math.h>
15 #include <float.h>
16 
17 void
mutest_expect_res_free(mutest_expect_res_t * res)18 mutest_expect_res_free (mutest_expect_res_t *res)
19 {
20   if (res == NULL)
21     return;
22 
23   switch (res->expect_type)
24     {
25     case MUTEST_EXPECT_INVALID:
26       mutest_assert_if_reached ("invalid value");
27       break;
28 
29     case MUTEST_EXPECT_BOOLEAN:
30     case MUTEST_EXPECT_INT:
31     case MUTEST_EXPECT_INT_RANGE:
32     case MUTEST_EXPECT_FLOAT:
33     case MUTEST_EXPECT_FLOAT_RANGE:
34     case MUTEST_EXPECT_POINTER:
35       break;
36 
37     case MUTEST_EXPECT_STR:
38       free (res->expect.v_str.str);
39       break;
40     }
41 
42   free (res);
43 }
44 
45 void
mutest_expect_res_to_string(mutest_expect_res_t * res,char * buf,size_t len)46 mutest_expect_res_to_string (mutest_expect_res_t *res,
47                              char *buf,
48                              size_t len)
49 {
50   if (res == NULL)
51     return;
52 
53   switch (res->expect_type)
54     {
55     case MUTEST_EXPECT_INVALID:
56       snprintf (buf, len, "invalid");
57       break;
58 
59     case MUTEST_EXPECT_BOOLEAN:
60       snprintf (buf, len, "%s", res->expect.v_bool ? "true" : "false");
61       break;
62 
63     case MUTEST_EXPECT_INT:
64       if (res->expect.v_int.tolerance == 0)
65         snprintf (buf, len, "%d", res->expect.v_int.value);
66       else
67         snprintf (buf, len, "%d (± %d)",
68                   res->expect.v_int.value,
69                   res->expect.v_int.tolerance);
70       break;
71 
72     case MUTEST_EXPECT_INT_RANGE:
73       snprintf (buf, len, "[ %d, %d ]",
74                 res->expect.v_irange.min,
75                 res->expect.v_irange.max);
76       break;
77 
78     case MUTEST_EXPECT_FLOAT:
79       if (isnan (res->expect.v_float.value))
80         {
81           snprintf (buf, len, "%s", "NaN");
82         }
83       else if (isinf (res->expect.v_float.value) && signbit (res->expect.v_float.value) == 0)
84         {
85           snprintf (buf, len, "%s", "+∞");
86         }
87       else if (isinf (res->expect.v_float.value) && signbit (res->expect.v_float.value) != 0)
88         {
89           snprintf (buf, len, "%s", "-∞");
90         }
91       else
92         {
93           snprintf (buf, len, "%g (± %g)",
94                     res->expect.v_float.value,
95                     res->expect.v_float.tolerance);
96         }
97       break;
98 
99     case MUTEST_EXPECT_FLOAT_RANGE:
100       snprintf (buf, len, "[ %g, %g ]",
101                 res->expect.v_frange.min,
102                 res->expect.v_frange.max);
103       break;
104 
105     case MUTEST_EXPECT_POINTER:
106       if (res->expect.v_pointer != NULL)
107         snprintf (buf, len, "%p", res->expect.v_pointer);
108       else
109         snprintf (buf, len, "%s", "null");
110       break;
111 
112     case MUTEST_EXPECT_STR:
113       snprintf (buf, len, "%s", res->expect.v_str.str);
114       break;
115     }
116 }
117 
118 mutest_expect_res_t *
mutest_expect_res_alloc(mutest_expect_type_t type)119 mutest_expect_res_alloc (mutest_expect_type_t type)
120 {
121   mutest_expect_res_t *retval = calloc (1, sizeof (mutest_expect_res_t));
122   if (retval == NULL)
123     mutest_oom_abort ();
124 
125   retval->expect_type = type;
126 
127   return retval;
128 }
129 
130 mutest_expect_res_t *
mutest_bool_value(bool value)131 mutest_bool_value (bool value)
132 {
133   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_BOOLEAN);
134   if (res == NULL)
135     mutest_oom_abort ();
136 
137   res->expect.v_bool = value;
138 
139   return res;
140 }
141 
142 bool
mutest_get_bool_value(const mutest_expect_res_t * res)143 mutest_get_bool_value (const mutest_expect_res_t *res)
144 {
145   if (res->expect_type != MUTEST_EXPECT_BOOLEAN)
146     mutest_assert_if_reached ("invalid boolean value");
147 
148   return res->expect.v_bool;
149 }
150 
151 mutest_expect_res_t *
mutest_int_value(int value)152 mutest_int_value (int value)
153 {
154   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_INT);
155 
156   res->expect.v_int.value = value;
157   res->expect.v_int.tolerance = 0;
158 
159   return res;
160 }
161 
162 int
mutest_get_int_value(const mutest_expect_res_t * res)163 mutest_get_int_value (const mutest_expect_res_t *res)
164 {
165   if (res->expect_type != MUTEST_EXPECT_INT)
166     mutest_assert_if_reached ("invalid integer value");
167 
168   return res->expect.v_int.value;
169 }
170 
171 mutest_expect_res_t *
mutest_string_value(const char * value)172 mutest_string_value (const char *value)
173 {
174   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_STR);
175 
176   res->expect.v_str.str = mutest_strdup_and_len (value, &(res->expect.v_str.len));
177 
178   return res;
179 }
180 
181 const char *
mutest_get_string_value(const mutest_expect_res_t * res)182 mutest_get_string_value (const mutest_expect_res_t *res)
183 {
184   if (res->expect_type != MUTEST_EXPECT_STR)
185     mutest_assert_if_reached ("invalid string value");
186 
187   return res->expect.v_str.str;
188 }
189 
190 mutest_expect_res_t *
mutest_float_value(double value)191 mutest_float_value (double value)
192 {
193   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_FLOAT);
194 
195   res->expect.v_float.value = value;
196   res->expect.v_float.tolerance = DBL_EPSILON;
197 
198   return res;
199 }
200 
201 double
mutest_get_float_value(const mutest_expect_res_t * res)202 mutest_get_float_value (const mutest_expect_res_t *res)
203 {
204   if (res->expect_type != MUTEST_EXPECT_FLOAT)
205     mutest_assert_if_reached ("invalid floating point value");
206 
207   return res->expect.v_float.value;
208 }
209 
210 mutest_expect_res_t *
mutest_int_range(int min,int max)211 mutest_int_range (int min,
212                   int max)
213 {
214   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_INT_RANGE);
215 
216   res->expect.v_irange.min = min;
217   res->expect.v_irange.max = max;
218 
219   return res;
220 }
221 
222 void
mutest_get_int_range(const mutest_expect_res_t * res,int * min,int * max)223 mutest_get_int_range (const mutest_expect_res_t *res,
224                       int *min,
225                       int *max)
226 {
227   if (res->expect_type != MUTEST_EXPECT_INT_RANGE)
228     mutest_assert_if_reached ("invalid integer range");
229 
230   if (min != NULL)
231     *min = res->expect.v_irange.min;
232   if (max != NULL)
233     *max = res->expect.v_irange.max;
234 }
235 
236 mutest_expect_res_t *
mutest_float_range(double min,double max)237 mutest_float_range (double min,
238                     double max)
239 {
240   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_FLOAT_RANGE);
241 
242   res->expect.v_frange.min = min;
243   res->expect.v_frange.max = max;
244 
245   return res;
246 }
247 
248 void
mutest_get_float_range(const mutest_expect_res_t * res,double * min,double * max)249 mutest_get_float_range (const mutest_expect_res_t *res,
250                         double *min,
251                         double *max)
252 {
253   if (res->expect_type != MUTEST_EXPECT_FLOAT_RANGE)
254     mutest_assert_if_reached ("invalid floating point range");
255 
256   if (min != NULL)
257     *min = res->expect.v_frange.min;
258   if (max != NULL)
259     *max = res->expect.v_frange.max;
260 }
261 
262 mutest_expect_res_t *
mutest_pointer(const void * pointer)263 mutest_pointer (const void *pointer)
264 {
265   mutest_expect_res_t *res = mutest_expect_res_alloc (MUTEST_EXPECT_POINTER);
266 
267   res->expect.v_pointer = (void *) pointer;
268 
269   return res;
270 }
271 
272 const void *
mutest_get_pointer(const mutest_expect_res_t * res)273 mutest_get_pointer (const mutest_expect_res_t *res)
274 {
275   if (res->expect_type != MUTEST_EXPECT_POINTER)
276     mutest_assert_if_reached ("invalid pointer");
277 
278   return res->expect.v_pointer;
279 }
280 
281 #if 0
282 mutest_expect_res_t *
283 mutest_byte_array (void *data,
284                    size_t element_size,
285                    size_t length)
286 {
287   mutest_expect_res_t *res = malloc (sizeof (mutest_expect_res_t));
288   if (res == NULL)
289     mutest_oom_abort ();
290 
291   res->expect_type = MUTEST_EXPECT_BYTE_ARRAY;
292   res->expect.v_bytearray.data = NULL;
293   res->expect.v_bytearray.element_size = element_size;
294   res->expect.v_bytearray.length = length;
295 
296   if (element_size == 0 || length == 0)
297     return res;
298 
299   size_t max_size = (size_t) -1;
300 
301   if (element_size > 0 && length > max_size / element_size)
302     mutest_assert_if_reached ("overflow");
303 
304   size_t total_size = element_size * length;
305 
306   res->expect.v_bytearray.data = malloc (total_size);
307   if (res->expect.v_bytearray.data == NULL)
308     mutest_oom_abort ();
309 
310   memcpy (res->expect.v_bytearray.data, data, total_size);
311 
312   return res;
313 }
314 
315 mutest_expect_res_t *
316 mutest_closure (mutest_expect_closure_func_t func,
317                 void *data)
318 {
319   mutest_expect_res_t *res = malloc (sizeof (mutest_expect_res_t));
320   if (res == NULL)
321     mutest_oom_abort ();
322 
323   res->expect_type = MUTEST_EXPECT_CLOSURE;
324   res->expect.v_closure.func = func;
325   res->expect.v_closure.data = data;
326 
327   return res;
328 }
329 #endif
330