xref: /freebsd/contrib/atf/atf-c/detail/map_test.c (revision a5921bc3653e2e286715e6fe8d473ec0d02da38c)
1 /* Copyright (c) 2008 The NetBSD Foundation, Inc.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
25 
26 #include "atf-c/detail/map.h"
27 
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include <atf-c.h>
32 
33 #include "atf-c/detail/test_helpers.h"
34 #include "atf-c/utils.h"
35 
36 /* ---------------------------------------------------------------------
37  * Tests for the "atf_map" type.
38  * --------------------------------------------------------------------- */
39 
40 /*
41  * Constructors and destructors.
42  */
43 
44 ATF_TC(map_init);
45 ATF_TC_HEAD(map_init, tc)
46 {
47     atf_tc_set_md_var(tc, "descr", "Checks the atf_map_init function");
48 }
49 ATF_TC_BODY(map_init, tc)
50 {
51     atf_map_t map;
52 
53     RE(atf_map_init(&map));
54     ATF_REQUIRE_EQ(atf_map_size(&map), 0);
55     atf_map_fini(&map);
56 }
57 
58 ATF_TC_WITHOUT_HEAD(map_init_charpp_null);
59 ATF_TC_BODY(map_init_charpp_null, tc)
60 {
61     atf_map_t map;
62 
63     RE(atf_map_init_charpp(&map, NULL));
64     ATF_REQUIRE_EQ(atf_map_size(&map), 0);
65     atf_map_fini(&map);
66 }
67 
68 ATF_TC_WITHOUT_HEAD(map_init_charpp_empty);
69 ATF_TC_BODY(map_init_charpp_empty, tc)
70 {
71     const char *const array[] = { NULL };
72     atf_map_t map;
73 
74     RE(atf_map_init_charpp(&map, array));
75     ATF_REQUIRE_EQ(atf_map_size(&map), 0);
76     atf_map_fini(&map);
77 }
78 
79 ATF_TC_WITHOUT_HEAD(map_init_charpp_some);
80 ATF_TC_BODY(map_init_charpp_some, tc)
81 {
82     const char *const array[] = { "K1", "V1", "K2", "V2", NULL };
83     atf_map_t map;
84     atf_map_citer_t iter;
85 
86     RE(atf_map_init_charpp(&map, array));
87     ATF_REQUIRE_EQ(atf_map_size(&map), 2);
88 
89     iter = atf_map_find_c(&map, "K1");
90     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
91     ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K1") == 0);
92     ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V1") == 0);
93 
94     iter = atf_map_find_c(&map, "K2");
95     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
96     ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K2") == 0);
97     ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V2") == 0);
98 
99     atf_map_fini(&map);
100 }
101 
102 ATF_TC_WITHOUT_HEAD(map_init_charpp_short);
103 ATF_TC_BODY(map_init_charpp_short, tc)
104 {
105     const char *const array[] = { "K1", "V1", "K2", NULL };
106     atf_map_t map;
107 
108     atf_error_t err = atf_map_init_charpp(&map, array);
109     ATF_REQUIRE(atf_is_error(err));
110     ATF_REQUIRE(atf_error_is(err, "libc"));
111 }
112 
113 /*
114  * Getters.
115  */
116 
117 ATF_TC(find);
118 ATF_TC_HEAD(find, tc)
119 {
120     atf_tc_set_md_var(tc, "descr", "Checks the atf_map_find function");
121 }
122 ATF_TC_BODY(find, tc)
123 {
124     atf_map_t map;
125     char val1[] = "V1";
126     char val2[] = "V2";
127     atf_map_iter_t iter;
128 
129     RE(atf_map_init(&map));
130     RE(atf_map_insert(&map, "K1", val1, false));
131     RE(atf_map_insert(&map, "K2", val2, false));
132 
133     iter = atf_map_find(&map, "K0");
134     ATF_REQUIRE(atf_equal_map_iter_map_iter(iter, atf_map_end(&map)));
135 
136     iter = atf_map_find(&map, "K1");
137     ATF_REQUIRE(!atf_equal_map_iter_map_iter(iter, atf_map_end(&map)));
138     ATF_REQUIRE(strcmp(atf_map_iter_key(iter), "K1") == 0);
139     ATF_REQUIRE(strcmp(atf_map_iter_data(iter), "V1") == 0);
140     strcpy(atf_map_iter_data(iter), "Z1");
141 
142     iter = atf_map_find(&map, "K1");
143     ATF_REQUIRE(!atf_equal_map_iter_map_iter(iter, atf_map_end(&map)));
144     ATF_REQUIRE(strcmp(atf_map_iter_key(iter), "K1") == 0);
145     ATF_REQUIRE(strcmp(atf_map_iter_data(iter), "Z1") == 0);
146 
147     iter = atf_map_find(&map, "K2");
148     ATF_REQUIRE(!atf_equal_map_iter_map_iter(iter, atf_map_end(&map)));
149     ATF_REQUIRE(strcmp(atf_map_iter_key(iter), "K2") == 0);
150     ATF_REQUIRE(strcmp(atf_map_iter_data(iter), "V2") == 0);
151 
152     atf_map_fini(&map);
153 }
154 
155 ATF_TC(find_c);
156 ATF_TC_HEAD(find_c, tc)
157 {
158     atf_tc_set_md_var(tc, "descr", "Checks the atf_map_find_c function");
159 }
160 ATF_TC_BODY(find_c, tc)
161 {
162     atf_map_t map;
163     char val1[] = "V1";
164     char val2[] = "V2";
165     atf_map_citer_t iter;
166 
167     RE(atf_map_init(&map));
168     RE(atf_map_insert(&map, "K1", val1, false));
169     RE(atf_map_insert(&map, "K2", val2, false));
170 
171     iter = atf_map_find_c(&map, "K0");
172     ATF_REQUIRE(atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
173 
174     iter = atf_map_find_c(&map, "K1");
175     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
176     ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K1") == 0);
177     ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V1") == 0);
178 
179     iter = atf_map_find_c(&map, "K2");
180     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
181     ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K2") == 0);
182     ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V2") == 0);
183 
184     atf_map_fini(&map);
185 }
186 
187 ATF_TC_WITHOUT_HEAD(to_charpp_empty);
188 ATF_TC_BODY(to_charpp_empty, tc)
189 {
190     atf_map_t map;
191     char **array;
192 
193     RE(atf_map_init(&map));
194     ATF_REQUIRE((array = atf_map_to_charpp(&map)) != NULL);
195     atf_map_fini(&map);
196 
197     ATF_CHECK_EQ(NULL, array[0]);
198     atf_utils_free_charpp(array);
199 }
200 
201 ATF_TC_WITHOUT_HEAD(to_charpp_some);
202 ATF_TC_BODY(to_charpp_some, tc)
203 {
204     atf_map_t map;
205     char **array;
206 
207     char s1[] = "one";
208     char s2[] = "two";
209     char s3[] = "three";
210 
211     RE(atf_map_init(&map));
212     RE(atf_map_insert(&map, "K1", s1, false));
213     RE(atf_map_insert(&map, "K2", s2, false));
214     RE(atf_map_insert(&map, "K3", s3, false));
215     ATF_REQUIRE((array = atf_map_to_charpp(&map)) != NULL);
216     atf_map_fini(&map);
217 
218     ATF_CHECK_STREQ("K1", array[0]);
219     ATF_CHECK_STREQ("one", array[1]);
220     ATF_CHECK_STREQ("K2", array[2]);
221     ATF_CHECK_STREQ("two", array[3]);
222     ATF_CHECK_STREQ("K3", array[4]);
223     ATF_CHECK_STREQ("three", array[5]);
224     ATF_CHECK_EQ(NULL, array[6]);
225     atf_utils_free_charpp(array);
226 }
227 
228 /*
229  * Modifiers.
230  */
231 
232 ATF_TC(map_insert);
233 ATF_TC_HEAD(map_insert, tc)
234 {
235     atf_tc_set_md_var(tc, "descr", "Checks the atf_map_insert function");
236 }
237 ATF_TC_BODY(map_insert, tc)
238 {
239     atf_map_t map;
240     char buf[] = "1st test string";
241     char buf2[] = "2nd test string";
242     const char *ptr;
243     atf_map_citer_t iter;
244 
245     RE(atf_map_init(&map));
246 
247     printf("Inserting some values\n");
248     ATF_REQUIRE_EQ(atf_map_size(&map), 0);
249     RE(atf_map_insert(&map, "K1", buf, false));
250     ATF_REQUIRE_EQ(atf_map_size(&map), 1);
251     RE(atf_map_insert(&map, "K2", buf, false));
252     ATF_REQUIRE_EQ(atf_map_size(&map), 2);
253     RE(atf_map_insert(&map, "K3", buf, false));
254     ATF_REQUIRE_EQ(atf_map_size(&map), 3);
255 
256     printf("Replacing a value\n");
257     iter = atf_map_find_c(&map, "K3");
258     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
259     ptr = atf_map_citer_data(iter);
260     ATF_REQUIRE_EQ(ptr, buf);
261     RE(atf_map_insert(&map, "K3", buf2, false));
262     ATF_REQUIRE_EQ(atf_map_size(&map), 3);
263     iter = atf_map_find_c(&map, "K3");
264     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
265     ptr = atf_map_citer_data(iter);
266     ATF_REQUIRE_EQ(ptr, buf2);
267 
268     atf_map_fini(&map);
269 }
270 
271 /*
272  * Macros.
273  */
274 
275 ATF_TC(map_for_each);
276 ATF_TC_HEAD(map_for_each, tc)
277 {
278     atf_tc_set_md_var(tc, "descr", "Checks the atf_map_for_each macro");
279 }
280 ATF_TC_BODY(map_for_each, tc)
281 {
282     atf_map_t map;
283     atf_map_iter_t iter;
284     size_t count, i, size;
285     char keys[10][5];
286     int nums[10];
287 
288     printf("Iterating over empty map\n");
289     RE(atf_map_init(&map));
290     count = 0;
291     atf_map_for_each(iter, &map) {
292         count++;
293         printf("Item count is now %zd\n", count);
294     }
295     ATF_REQUIRE_EQ(count, 0);
296     atf_map_fini(&map);
297 
298     for (size = 0; size <= 10; size++) {
299         printf("Iterating over map of %zd elements\n", size);
300         RE(atf_map_init(&map));
301         for (i = 0; i < size; i++) {
302             nums[i] = i + 1;
303             snprintf(keys[i], sizeof(keys[i]), "%d", nums[i]);
304             RE(atf_map_insert(&map, keys[i], &nums[i], false));
305         }
306         count = 0;
307         atf_map_for_each(iter, &map) {
308             printf("Retrieved item: %d\n", *(int *)atf_map_iter_data(iter));
309             count++;
310         }
311         ATF_REQUIRE_EQ(count, size);
312         atf_map_fini(&map);
313     }
314 }
315 
316 ATF_TC(map_for_each_c);
317 ATF_TC_HEAD(map_for_each_c, tc)
318 {
319     atf_tc_set_md_var(tc, "descr", "Checks the atf_map_for_each_c macro");
320 }
321 ATF_TC_BODY(map_for_each_c, tc)
322 {
323     atf_map_t map;
324     atf_map_citer_t iter;
325     size_t count, i, size;
326     char keys[10][5];
327     int nums[10];
328 
329     printf("Iterating over empty map\n");
330     RE(atf_map_init(&map));
331     count = 0;
332     atf_map_for_each_c(iter, &map) {
333         count++;
334         printf("Item count is now %zd\n", count);
335     }
336     ATF_REQUIRE_EQ(count, 0);
337     atf_map_fini(&map);
338 
339     for (size = 0; size <= 10; size++) {
340         printf("Iterating over map of %zd elements\n", size);
341         RE(atf_map_init(&map));
342         for (i = 0; i < size; i++) {
343             nums[i] = i + 1;
344             snprintf(keys[i], sizeof(keys[i]), "%d", nums[i]);
345             RE(atf_map_insert(&map, keys[i], &nums[i], false));
346         }
347         count = 0;
348         atf_map_for_each_c(iter, &map) {
349             printf("Retrieved item: %d\n",
350                    *(const int *)atf_map_citer_data(iter));
351             count++;
352         }
353         ATF_REQUIRE_EQ(count, size);
354         atf_map_fini(&map);
355     }
356 }
357 
358 /*
359  * Other.
360  */
361 
362 ATF_TC(stable_keys);
363 ATF_TC_HEAD(stable_keys, tc)
364 {
365     atf_tc_set_md_var(tc, "descr", "Checks that the keys do not change "
366                       "even if their original values do");
367 }
368 ATF_TC_BODY(stable_keys, tc)
369 {
370     atf_map_t map;
371     atf_map_citer_t iter;
372     char key[] = "K1";
373 
374     RE(atf_map_init(&map));
375 
376     RE(atf_map_insert(&map, key, strdup("test-value"), true));
377     iter = atf_map_find_c(&map, "K1");
378     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
379     iter = atf_map_find_c(&map, "K2");
380     ATF_REQUIRE(atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
381 
382     strcpy(key, "K2");
383     iter = atf_map_find_c(&map, "K1");
384     ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
385     iter = atf_map_find_c(&map, "K2");
386     ATF_REQUIRE(atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map)));
387 
388     atf_map_fini(&map);
389 }
390 
391 /* ---------------------------------------------------------------------
392  * Main.
393  * --------------------------------------------------------------------- */
394 
395 ATF_TP_ADD_TCS(tp)
396 {
397     /* Constructors and destructors. */
398     ATF_TP_ADD_TC(tp, map_init);
399     ATF_TP_ADD_TC(tp, map_init_charpp_null);
400     ATF_TP_ADD_TC(tp, map_init_charpp_empty);
401     ATF_TP_ADD_TC(tp, map_init_charpp_some);
402     ATF_TP_ADD_TC(tp, map_init_charpp_short);
403 
404     /* Getters. */
405     ATF_TP_ADD_TC(tp, find);
406     ATF_TP_ADD_TC(tp, find_c);
407     ATF_TP_ADD_TC(tp, to_charpp_empty);
408     ATF_TP_ADD_TC(tp, to_charpp_some);
409 
410     /* Modifiers. */
411     ATF_TP_ADD_TC(tp, map_insert);
412 
413     /* Macros. */
414     ATF_TP_ADD_TC(tp, map_for_each);
415     ATF_TP_ADD_TC(tp, map_for_each_c);
416 
417     /* Other. */
418     ATF_TP_ADD_TC(tp, stable_keys);
419 
420     return atf_no_error();
421 }
422