map_test.c revision 275988
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
44ATF_TC(map_init);
45ATF_TC_HEAD(map_init, tc)
46{
47    atf_tc_set_md_var(tc, "descr", "Checks the atf_map_init function");
48}
49ATF_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
58ATF_TC_WITHOUT_HEAD(map_init_charpp_null);
59ATF_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
68ATF_TC_WITHOUT_HEAD(map_init_charpp_empty);
69ATF_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
79ATF_TC_WITHOUT_HEAD(map_init_charpp_some);
80ATF_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
102ATF_TC_WITHOUT_HEAD(map_init_charpp_short);
103ATF_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
117ATF_TC(find);
118ATF_TC_HEAD(find, tc)
119{
120    atf_tc_set_md_var(tc, "descr", "Checks the atf_map_find function");
121}
122ATF_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
155ATF_TC(find_c);
156ATF_TC_HEAD(find_c, tc)
157{
158    atf_tc_set_md_var(tc, "descr", "Checks the atf_map_find_c function");
159}
160ATF_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
187ATF_TC_WITHOUT_HEAD(to_charpp_empty);
188ATF_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
201ATF_TC_WITHOUT_HEAD(to_charpp_some);
202ATF_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
232ATF_TC(map_insert);
233ATF_TC_HEAD(map_insert, tc)
234{
235    atf_tc_set_md_var(tc, "descr", "Checks the atf_map_insert function");
236}
237ATF_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
275ATF_TC(map_for_each);
276ATF_TC_HEAD(map_for_each, tc)
277{
278    atf_tc_set_md_var(tc, "descr", "Checks the atf_map_for_each macro");
279}
280ATF_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
316ATF_TC(map_for_each_c);
317ATF_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}
321ATF_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
362ATF_TC(stable_keys);
363ATF_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}
368ATF_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
395ATF_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