1 /*
2  * bitset_test.c
3  * Test for bitset.
4  *
5  * Copyright (C) 2001-2017 Cosmin Truta.
6  *
7  * This software is distributed under the zlib license.
8  * Please see the accompanying LICENSE file.
9  */
10 
11 #include "bitset.h"
12 
13 #include <errno.h>
14 #include <limits.h>
15 #include <stdio.h>
16 
17 
18 static int num_tests = 0;
19 static int num_errors = 0;
20 
21 #define EMPTY   OPNG_BITSET_EMPTY
22 #define FULL    OPNG_BITSET_FULL
23 #define ELT_MIN OPNG_BITSET_ELT_MIN
24 #define ELT_MAX OPNG_BITSET_ELT_MAX
25 
26 #define TEST_BOOL(expr) \
27     test_int_impl("!!(" #expr ")", !!(expr), 1)
28 
29 #define TEST_INT(expr, expected) \
30     test_int_impl(#expr, expr, expected)
31 
32 #define TEST_BITSET(expr, expected) \
33     test_bitset_impl(#expr, expr, expected)
34 
35 static void
test_int_impl(const char * expr_str,int result,int expected)36 test_int_impl(const char *expr_str, int result, int expected)
37 {
38     ++num_tests;
39     if (result != expected)
40     {
41         ++num_errors;
42         printf("FAILED: %s, result: %d, expected: %d\n",
43                expr_str, result, expected);
44     }
45 }
46 
47 static void
test_bitset_impl(const char * expr_str,opng_bitset_t result,opng_bitset_t expected)48 test_bitset_impl(const char *expr_str,
49                  opng_bitset_t result, opng_bitset_t expected)
50 {
51     ++num_tests;
52     if (result != expected)
53     {
54         ++num_errors;
55         printf("FAILED: %s, result: 0x%lx, expected: 0x%lx\n",
56                expr_str, (unsigned long)result, (unsigned long)expected);
57     }
58 }
59 
60 static void
test_bitset_const()61 test_bitset_const()
62 {
63     printf("Testing: bitset constants\n");
64 
65     TEST_BITSET(EMPTY, 0);
66     TEST_BITSET(FULL,  ~EMPTY);
67 
68     TEST_INT(ELT_MIN, 0);
69     TEST_INT(ELT_MAX, (int)OPNG_BITSIZEOF(opng_bitset_t) - 1);
70     TEST_INT(ELT_MAX, (int)(sizeof(opng_bitset_t) * CHAR_BIT) - 1);
71 }
72 
73 static void
test_bitset_obs()74 test_bitset_obs()
75 {
76     printf("Testing: bitset observers\n");
77 
78     TEST_INT(opng_bitset_test(EMPTY,  ELT_MIN), 0);
79     TEST_INT(opng_bitset_test(EMPTY,  ELT_MAX), 0);
80     TEST_INT(opng_bitset_test(FULL,   ELT_MIN), 1);
81     TEST_INT(opng_bitset_test(FULL,   ELT_MAX), 1);
82     TEST_INT(opng_bitset_test(0x0002, ELT_MIN), 0);
83     TEST_INT(opng_bitset_test(0x0ff0, ELT_MAX), 0);
84     TEST_INT(opng_bitset_test(EMPTY,  1),       0);
85     TEST_INT(opng_bitset_test(FULL,   1),       1);
86     TEST_INT(opng_bitset_test(0x0002, 1),       1);
87     TEST_INT(opng_bitset_test(0x0ff0, 1),       0);
88 
89     TEST_INT(opng_bitset_test_all_in_range(EMPTY,  ELT_MIN, ELT_MAX), 0);
90     TEST_INT(opng_bitset_test_all_in_range(FULL,   ELT_MIN, ELT_MAX), 1);
91     TEST_INT(opng_bitset_test_all_in_range(0x0002, ELT_MIN, ELT_MAX), 0);
92     TEST_INT(opng_bitset_test_all_in_range(0x0ff0, ELT_MIN, ELT_MAX), 0);
93     TEST_INT(opng_bitset_test_all_in_range(EMPTY,  1,       1),       0);
94     TEST_INT(opng_bitset_test_all_in_range(FULL,   1,       1),       1);
95     TEST_INT(opng_bitset_test_all_in_range(0x0002, 1,       1),       1);
96     TEST_INT(opng_bitset_test_all_in_range(0x0ff0, 1,       1),       0);
97 
98     TEST_INT(opng_bitset_test_any_in_range(EMPTY,  ELT_MIN, ELT_MAX), 0);
99     TEST_INT(opng_bitset_test_any_in_range(FULL,   ELT_MIN, ELT_MAX), 1);
100     TEST_INT(opng_bitset_test_any_in_range(0x0002, ELT_MIN, ELT_MAX), 1);
101     TEST_INT(opng_bitset_test_any_in_range(0x0ff0, ELT_MIN, ELT_MAX), 1);
102     TEST_INT(opng_bitset_test_any_in_range(EMPTY,  1,       1),       0);
103     TEST_INT(opng_bitset_test_any_in_range(FULL,   1,       1),       1);
104     TEST_INT(opng_bitset_test_any_in_range(0x0002, 1,       1),       1);
105     TEST_INT(opng_bitset_test_any_in_range(0x0ff0, 1,       1),       0);
106 
107     TEST_INT(opng_bitset_count(EMPTY),  0);
108     TEST_INT(opng_bitset_count(FULL),   OPNG_BITSIZEOF(opng_bitset_t));
109     TEST_INT(opng_bitset_count(0x0002), 1);
110     TEST_INT(opng_bitset_count(0x0ff0), 8);
111 }
112 
113 static void
test_bitset_mod()114 test_bitset_mod()
115 {
116     opng_bitset_t set;
117 
118     printf("Testing: bitset modifiers\n");
119 
120     set = 0x0002;
121     opng_bitset_set(&set, 1);
122     opng_bitset_set(&set, 2);
123     TEST_BITSET(set, 0x06);
124     opng_bitset_reset(&set, 2);
125     opng_bitset_reset(&set, 3);
126     TEST_BITSET(set, 0x0002);
127     opng_bitset_flip(&set, 3);
128     opng_bitset_flip(&set, 1);
129     TEST_BITSET(set, 0x08);
130 
131     set = 0x0ff0;
132     opng_bitset_set_range(&set, 0, 7);
133     TEST_BITSET(set, 0x0fff);
134     opng_bitset_set_range(&set, ELT_MIN, ELT_MAX);
135     TEST_BITSET(set, FULL);
136     set = 0x0ff0;
137     opng_bitset_reset_range(&set, 0, 7);
138     TEST_BITSET(set, 0x0f00);
139     opng_bitset_reset_range(&set, ELT_MIN, ELT_MAX);
140     TEST_BITSET(set, EMPTY);
141     set = 0x0ff0;
142     opng_bitset_flip_range(&set, 0, 7);
143     TEST_BITSET(set, 0x0f0f);
144     opng_bitset_flip_range(&set, ELT_MIN, ELT_MAX);
145     TEST_BITSET(set, FULL ^ 0x0f0f);
146 }
147 
148 static void
test_bitset_find_forward_impl(opng_bitset_t bitset)149 test_bitset_find_forward_impl(opng_bitset_t bitset)
150 {
151     opng_bitset_t check_bitset;
152     int check_count;
153     int elt, prev_elt;
154 
155     check_bitset = EMPTY;
156     check_count = 0;
157     prev_elt = -1;
158     for (elt = opng_bitset_find_first(bitset);
159          elt >= 0;
160          elt = opng_bitset_find_next(bitset, elt))
161     {
162         if (elt < ELT_MIN || elt > ELT_MAX || elt <= prev_elt)
163         {
164             /* Fail. */
165             TEST_INT(check_count, -1);
166             return;
167         }
168         opng_bitset_set(&check_bitset, elt);
169         ++check_count;
170         prev_elt = elt;
171     }
172     TEST_BITSET(check_bitset, bitset);
173     TEST_INT(check_count, opng_bitset_count(bitset));
174 }
175 
176 static void
test_bitset_find_reverse_impl(opng_bitset_t bitset)177 test_bitset_find_reverse_impl(opng_bitset_t bitset)
178 {
179     opng_bitset_t check_bitset;
180     int check_count;
181     int elt, prev_elt;
182 
183     check_bitset = EMPTY;
184     check_count = 0;
185     prev_elt = INT_MAX;
186     for (elt = opng_bitset_find_last(bitset);
187          elt >= 0;
188          elt = opng_bitset_find_prev(bitset, elt))
189     {
190         if (elt < ELT_MIN || elt > ELT_MAX || elt >= prev_elt)
191         {
192             /* Fail. */
193             TEST_INT(check_count, -1);
194             return;
195         }
196         opng_bitset_set(&check_bitset, elt);
197         ++check_count;
198         prev_elt = elt;
199     }
200     TEST_BITSET(check_bitset, bitset);
201     TEST_INT(check_count, opng_bitset_count(bitset));
202 }
203 
204 static void
test_bitset_iter()205 test_bitset_iter()
206 {
207     printf("Testing: bitset iterators\n");
208 
209     TEST_INT(opng_bitset_find_first(EMPTY),  -1);
210     TEST_INT(opng_bitset_find_first(FULL),   ELT_MIN);
211     TEST_INT(opng_bitset_find_first(0x0002), 1);
212     TEST_INT(opng_bitset_find_first(0x0ff0), 4);
213 
214     TEST_INT(opng_bitset_find_next(EMPTY,  0),       -1);
215     TEST_INT(opng_bitset_find_next(FULL,   0),       1);
216     TEST_INT(opng_bitset_find_next(0x0002, 0),       1);
217     TEST_INT(opng_bitset_find_next(0x0ff0, 0),       4);
218     TEST_INT(opng_bitset_find_next(EMPTY,  1),       -1);
219     TEST_INT(opng_bitset_find_next(FULL,   1),       2);
220     TEST_INT(opng_bitset_find_next(0x0002, 1),       -1);
221     TEST_INT(opng_bitset_find_next(0x0ff0, 1),       4);
222     TEST_INT(opng_bitset_find_next(EMPTY,  2),       -1);
223     TEST_INT(opng_bitset_find_next(FULL,   2),       3);
224     TEST_INT(opng_bitset_find_next(0x0002, 2),       -1);
225     TEST_INT(opng_bitset_find_next(0x0ff0, 2),       4);
226     TEST_INT(opng_bitset_find_next(EMPTY,  ELT_MAX), -1);
227     TEST_INT(opng_bitset_find_next(FULL,   ELT_MAX), -1);
228     TEST_INT(opng_bitset_find_next(0x0002, ELT_MAX), -1);
229     TEST_INT(opng_bitset_find_next(0x0ff0, ELT_MAX), -1);
230 
231     TEST_INT(opng_bitset_find_last(EMPTY),  -1);
232     TEST_INT(opng_bitset_find_last(FULL),   ELT_MAX);
233     TEST_INT(opng_bitset_find_last(0x0002), 1);
234     TEST_INT(opng_bitset_find_last(0x0ff0), 11);
235 
236     TEST_INT(opng_bitset_find_prev(EMPTY,  0),       -1);
237     TEST_INT(opng_bitset_find_prev(FULL,   0),       -1);
238     TEST_INT(opng_bitset_find_prev(0x0002, 0),       -1);
239     TEST_INT(opng_bitset_find_prev(0x0ff0, 0),       -1);
240     TEST_INT(opng_bitset_find_prev(EMPTY,  1),       -1);
241     TEST_INT(opng_bitset_find_prev(FULL,   1),       0);
242     TEST_INT(opng_bitset_find_prev(0x0002, 1),       -1);
243     TEST_INT(opng_bitset_find_prev(0x0ff0, 1),       -1);
244     TEST_INT(opng_bitset_find_prev(EMPTY,  2),       -1);
245     TEST_INT(opng_bitset_find_prev(FULL,   2),       1);
246     TEST_INT(opng_bitset_find_prev(0x0002, 2),       1);
247     TEST_INT(opng_bitset_find_prev(0x0ff0, 2),       -1);
248     TEST_INT(opng_bitset_find_prev(EMPTY,  ELT_MAX), -1);
249     TEST_INT(opng_bitset_find_prev(FULL,   ELT_MAX), ELT_MAX - 1);
250     TEST_INT(opng_bitset_find_prev(0x0002, ELT_MAX), 1);
251     TEST_INT(opng_bitset_find_prev(0x0ff0, ELT_MAX), 11);
252 
253     test_bitset_find_forward_impl(EMPTY);
254     test_bitset_find_forward_impl(FULL);
255     test_bitset_find_forward_impl(0x0002);
256     test_bitset_find_forward_impl(0x0ff0);
257 
258     test_bitset_find_reverse_impl(EMPTY);
259     test_bitset_find_reverse_impl(FULL);
260     test_bitset_find_reverse_impl(0x0002);
261     test_bitset_find_reverse_impl(0x0ff0);
262 }
263 
264 static void
test_strparse_rangeset_impl(const char * rangeset,opng_bitset_t mask,opng_bitset_t expected_bitset,int expected_errno)265 test_strparse_rangeset_impl(const char *rangeset,
266                             opng_bitset_t mask,
267                             opng_bitset_t expected_bitset,
268                             int expected_errno)
269 {
270     opng_bitset_t bitset;
271     int parse_result, expected_parse_result;
272 
273     ++num_tests;
274     errno = 0;
275     expected_parse_result = (expected_errno == 0) ? 0 : -1;
276     parse_result = opng_strparse_rangeset_to_bitset(&bitset, rangeset, mask);
277     if (parse_result != expected_parse_result ||
278         bitset != expected_bitset ||
279         errno != expected_errno)
280     {
281         ++num_errors;
282         printf("FAILED: opng_strparse_rangeset_to_bitset(\"%s\", 0x%lx)\n",
283                rangeset, (unsigned long)mask);
284         printf("        bitset: 0x%lx, expected: 0x%lx\n",
285                (unsigned long)bitset, (unsigned long)expected_bitset);
286         printf("        result: %d, expected: %d\n",
287                parse_result, expected_parse_result);
288         printf("        errno: %d, expected: %d\n",
289                errno, expected_errno);
290     }
291 }
292 
293 static void
test_rangeset_parse()294 test_rangeset_parse()
295 {
296     static const opng_bitset_t mask_full    = FULL;
297     static const opng_bitset_t mask_byte    = 0x00ff;
298     static const opng_bitset_t mask_pattern = 0x5555;
299     static const opng_bitset_t mask_empty   = EMPTY;
300 
301     printf("Testing: rangeset parser\n");
302 
303     test_strparse_rangeset_impl("",            mask_full,    EMPTY,  0);
304     test_strparse_rangeset_impl(" ",           mask_byte,    EMPTY,  0);
305     test_strparse_rangeset_impl("   ",         mask_pattern, EMPTY,  0);
306     test_strparse_rangeset_impl(" ,;  ;, ",    mask_empty,   EMPTY,  0);
307     test_strparse_rangeset_impl("0",           mask_full,    0x0001, 0);
308     test_strparse_rangeset_impl("0,",          mask_byte,    0x0001, 0);
309     test_strparse_rangeset_impl(",0",          mask_pattern, 0x0001, 0);
310     test_strparse_rangeset_impl(",0,",         mask_empty,   FULL,   ERANGE);
311     test_strparse_rangeset_impl("0-",          mask_full,    FULL,   0);
312     test_strparse_rangeset_impl("0-;",         mask_pattern, 0x5555, 0);
313     test_strparse_rangeset_impl(";0-",         mask_byte,    0x00ff, 0);
314     test_strparse_rangeset_impl(";0-;",        mask_empty,   FULL,   ERANGE);
315     test_strparse_rangeset_impl(" 01 ",        mask_full,    0x0002, 0);
316     test_strparse_rangeset_impl(" 01,; ",      mask_byte,    0x0002, 0);
317     test_strparse_rangeset_impl(" ,;01 ",      mask_pattern, FULL,   ERANGE);
318     test_strparse_rangeset_impl(" ,;01,; ",    mask_empty,   FULL,   ERANGE);
319     test_strparse_rangeset_impl(" 012 , ;",    mask_full,    0x1000, 0);
320     test_strparse_rangeset_impl(", ; 012 ",    mask_byte,    FULL,   ERANGE);
321     test_strparse_rangeset_impl(",;012,;",     mask_pattern, 0x1000, 0);
322     test_strparse_rangeset_impl("1, 1",        mask_full,    0x0002, 0);
323     test_strparse_rangeset_impl("1- 1",        mask_byte,    0x0002, 0);
324     test_strparse_rangeset_impl("1 ;2",        mask_full,    0x0006, 0);
325     test_strparse_rangeset_impl("1 -2",        mask_byte,    0x0006, 0);
326     test_strparse_rangeset_impl("1 - 2",       mask_pattern, FULL,   ERANGE);
327     test_strparse_rangeset_impl("2-1",         mask_full,    FULL,   ERANGE);
328     test_strparse_rangeset_impl("2-1",         mask_byte,    FULL,   ERANGE);
329     test_strparse_rangeset_impl("124",         mask_full,    FULL,   ERANGE);
330     test_strparse_rangeset_impl("12-4",        mask_full,    FULL,   ERANGE);
331     test_strparse_rangeset_impl("1-2,4",       mask_full,    0x0016, 0);
332     test_strparse_rangeset_impl("1-2,4-",      mask_byte,    0x00f6, 0);
333     test_strparse_rangeset_impl("1,2,4",       mask_full,    0x0016, 0);
334     test_strparse_rangeset_impl("1,2,4-",      mask_pattern, FULL,   ERANGE);
335     test_strparse_rangeset_impl("1,2,4",       mask_byte,    0x0016, 0);
336     test_strparse_rangeset_impl("1,2-4",       mask_full,    0x001e, 0);
337     test_strparse_rangeset_impl("12,4",        mask_full,    0x1010, 0);
338     test_strparse_rangeset_impl("12,4",        mask_byte,    FULL,   ERANGE);
339     test_strparse_rangeset_impl("2-4,1",       mask_full,    0x001e, 0);
340     test_strparse_rangeset_impl("4-2,1",       mask_full,    FULL,   ERANGE);
341     test_strparse_rangeset_impl("4-,2-1",      mask_byte,    FULL,   ERANGE);
342     test_strparse_rangeset_impl("4-,1-2",      mask_full,    FULL ^ 0x0009, 0);
343     test_strparse_rangeset_impl("9999999999",  mask_full,    FULL,   ERANGE);
344     test_strparse_rangeset_impl("9999999999-", mask_byte,    FULL,   ERANGE);
345 
346     test_strparse_rangeset_impl("-",           mask_full,    EMPTY, EINVAL);
347     test_strparse_rangeset_impl(" - ",         mask_pattern, EMPTY, EINVAL);
348     test_strparse_rangeset_impl("--",          mask_byte,    EMPTY, EINVAL);
349     test_strparse_rangeset_impl("- -",         mask_empty,   EMPTY, EINVAL);
350     test_strparse_rangeset_impl("0--",         mask_full,    EMPTY, EINVAL);
351     test_strparse_rangeset_impl("0 -- ",       mask_pattern, EMPTY, EINVAL);
352     test_strparse_rangeset_impl("0- -",        mask_byte,    EMPTY, EINVAL);
353     test_strparse_rangeset_impl("0 --- ",      mask_empty,   EMPTY, EINVAL);
354     test_strparse_rangeset_impl("-0",          mask_full,    EMPTY, EINVAL);
355     test_strparse_rangeset_impl("-0-",         mask_pattern, EMPTY, EINVAL);
356     test_strparse_rangeset_impl("1k",          mask_full,    EMPTY, EINVAL);
357     test_strparse_rangeset_impl("1 k",         mask_pattern, EMPTY, EINVAL);
358     test_strparse_rangeset_impl("A1",          mask_full,    EMPTY, EINVAL);
359     test_strparse_rangeset_impl("0xA1",        mask_pattern, EMPTY, EINVAL);
360     test_strparse_rangeset_impl(".1",          mask_full,    EMPTY, EINVAL);
361     test_strparse_rangeset_impl("1.",          mask_pattern, EMPTY, EINVAL);
362     test_strparse_rangeset_impl("1.2",         mask_byte,    EMPTY, EINVAL);
363     test_strparse_rangeset_impl("1 2",         mask_full,    EMPTY, EINVAL);
364     test_strparse_rangeset_impl("2 1",         mask_pattern, EMPTY, EINVAL);
365     test_strparse_rangeset_impl("1--2",        mask_full,    EMPTY, EINVAL);
366     test_strparse_rangeset_impl("1--2-",       mask_pattern, EMPTY, EINVAL);
367     test_strparse_rangeset_impl("1- -2",       mask_byte,    EMPTY, EINVAL);
368     test_strparse_rangeset_impl("1- -2-",      mask_empty,   EMPTY, EINVAL);
369     test_strparse_rangeset_impl("-1--2",       mask_full,    EMPTY, EINVAL);
370     test_strparse_rangeset_impl("-1--2-",      mask_pattern, EMPTY, EINVAL);
371     test_strparse_rangeset_impl("-1- -2",      mask_byte,    EMPTY, EINVAL);
372     test_strparse_rangeset_impl("-1- -2-",     mask_empty,   EMPTY, EINVAL);
373     test_strparse_rangeset_impl("1-2-4",       mask_full,    EMPTY, EINVAL);
374     test_strparse_rangeset_impl("1-2-4-",      mask_pattern, EMPTY, EINVAL);
375     test_strparse_rangeset_impl("1-2-4-",      mask_byte,    EMPTY, EINVAL);
376     test_strparse_rangeset_impl("-1-2-4",      mask_empty,   EMPTY, EINVAL);
377     test_strparse_rangeset_impl("1-4-2,",      mask_full,    EMPTY, EINVAL);
378     test_strparse_rangeset_impl("1-4-2-,",     mask_pattern, EMPTY, EINVAL);
379     test_strparse_rangeset_impl("1-4-2-,",     mask_byte,    EMPTY, EINVAL);
380     test_strparse_rangeset_impl("-1-4-2,",     mask_empty,   EMPTY, EINVAL);
381     test_strparse_rangeset_impl(",4-2-1;",     mask_full,    EMPTY, EINVAL);
382     test_strparse_rangeset_impl(",4-2-1-;",    mask_pattern, EMPTY, EINVAL);
383     test_strparse_rangeset_impl(",4-2-1-;",    mask_byte,    EMPTY, EINVAL);
384     test_strparse_rangeset_impl(",-4-2-1;",    mask_empty,   EMPTY, EINVAL);
385     test_strparse_rangeset_impl("-9999999999", mask_full,    EMPTY, EINVAL);
386 }
387 
388 static void
run_tests()389 run_tests()
390 {
391     test_bitset_const();
392     test_bitset_obs();
393     test_bitset_mod();
394     test_bitset_iter();
395     test_rangeset_parse();
396 }
397 
398 int
main()399 main()
400 {
401     run_tests();
402     if (num_errors != 0)
403     {
404         printf("** %d/%d tests FAILED **\n", num_errors, num_tests);
405         return 1;
406     }
407     else
408     {
409         printf("** %d tests passed **\n", num_tests);
410         return 0;
411     }
412 }
413