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