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