xref: /freebsd/contrib/libcbor/test/map_test.c (revision 5d3e7166)
1 /*
2  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
3  *
4  * libcbor is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7 
8 #include <setjmp.h>
9 #include <stdarg.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13 
14 #include <cmocka.h>
15 
16 #include "assertions.h"
17 #include "cbor.h"
18 #include "test_allocator.h"
19 
20 cbor_item_t *map;
21 struct cbor_load_result res;
22 
23 unsigned char empty_map[] = {0xA0};
24 
test_empty_map(void ** _CBOR_UNUSED (_state))25 static void test_empty_map(void **_CBOR_UNUSED(_state)) {
26   map = cbor_load(empty_map, 1, &res);
27   assert_non_null(map);
28   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
29   assert_true(cbor_isa_map(map));
30   assert_true(cbor_map_size(map) == 0);
31   assert_true(res.read == 1);
32   assert_size_equal(cbor_map_allocated(map), 0);
33   cbor_decref(&map);
34   assert_null(map);
35 }
36 
37 unsigned char simple_map[] = {0xA2, 0x01, 0x02, 0x03, 0x04};
38 
39 /* {1: 2, 3: 4} */
test_simple_map(void ** _CBOR_UNUSED (_state))40 static void test_simple_map(void **_CBOR_UNUSED(_state)) {
41   map = cbor_load(simple_map, 5, &res);
42   assert_non_null(map);
43   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
44   assert_true(cbor_isa_map(map));
45   assert_true(cbor_map_is_definite(map));
46   assert_true(cbor_map_size(map) == 2);
47   assert_true(res.read == 5);
48   struct cbor_pair *handle = cbor_map_handle(map);
49   assert_uint8(handle[0].key, 1);
50   assert_uint8(handle[0].value, 2);
51   assert_uint8(handle[1].key, 3);
52   assert_uint8(handle[1].value, 4);
53   cbor_decref(&map);
54   assert_null(map);
55 }
56 
57 unsigned char simple_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF};
58 
59 /* {_ 1: 2, 3: 4} */
test_indef_simple_map(void ** _CBOR_UNUSED (_state))60 static void test_indef_simple_map(void **_CBOR_UNUSED(_state)) {
61   map = cbor_load(simple_indef_map, 6, &res);
62   assert_non_null(map);
63   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
64   assert_true(cbor_isa_map(map));
65   assert_true(cbor_map_is_indefinite(map));
66   assert_true(cbor_map_size(map) == 2);
67   assert_true(res.read == 6);
68   struct cbor_pair *handle = cbor_map_handle(map);
69   assert_uint8(handle[0].key, 1);
70   assert_uint8(handle[0].value, 2);
71   assert_uint8(handle[1].key, 3);
72   assert_uint8(handle[1].value, 4);
73   cbor_decref(&map);
74   assert_null(map);
75 }
76 
77 //{
78 //	"glossary": {
79 //		"title": "example glossary"
80 //	}
81 //}
82 unsigned char def_nested_map[] = {
83     0xA1, 0x68, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79, 0xA1, 0x65,
84     0x74, 0x69, 0x74, 0x6C, 0x65, 0x70, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C,
85     0x65, 0x20, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79};
86 
test_def_nested_map(void ** _CBOR_UNUSED (_state))87 static void test_def_nested_map(void **_CBOR_UNUSED(_state)) {
88   map = cbor_load(def_nested_map, 34, &res);
89   assert_non_null(map);
90   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
91   assert_true(cbor_isa_map(map));
92   assert_true(cbor_map_is_definite(map));
93   assert_true(cbor_map_size(map) == 1);
94   assert_true(res.read == 34);
95   struct cbor_pair *handle = cbor_map_handle(map);
96   assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
97   assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_MAP);
98   struct cbor_pair *inner_handle = cbor_map_handle(handle[0].value);
99   assert_true(cbor_typeof(inner_handle[0].key) == CBOR_TYPE_STRING);
100   assert_true(cbor_typeof(inner_handle[0].value) == CBOR_TYPE_STRING);
101   assert_memory_equal(cbor_string_handle(inner_handle[0].value),
102                       "example glossary", strlen("example glossary"));
103   cbor_decref(&map);
104   assert_null(map);
105 }
106 
107 unsigned char streamed_key_map[] = {0xA1, 0x7F, 0x61, 0x61,
108                                     0x61, 0x62, 0xFF, 0xA0};
109 
110 /* '{ (_"a" "b"): {}}' */
test_streamed_key_map(void ** _CBOR_UNUSED (_state))111 static void test_streamed_key_map(void **_CBOR_UNUSED(_state)) {
112   map = cbor_load(streamed_key_map, 8, &res);
113   assert_non_null(map);
114   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
115   assert_true(cbor_isa_map(map));
116   assert_true(cbor_map_is_definite(map));
117   assert_true(cbor_map_size(map) == 1);
118   assert_true(res.read == 8);
119   struct cbor_pair *handle = cbor_map_handle(map);
120   assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
121   assert_true(cbor_string_is_indefinite(handle[0].key));
122   assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
123   assert_true(cbor_isa_map(handle[0].value));
124   assert_size_equal(cbor_map_size(handle[0].value), 0);
125   cbor_decref(&map);
126   assert_null(map);
127 }
128 
129 unsigned char streamed_kv_map[] = {0xA1, 0x7F, 0x61, 0x61, 0x61, 0x62, 0xFF,
130                                    0x7F, 0x61, 0x63, 0x61, 0x64, 0xFF};
131 
132 /* '{ (_"a" "b"): (_"c", "d")}' */
test_streamed_kv_map(void ** _CBOR_UNUSED (_state))133 static void test_streamed_kv_map(void **_CBOR_UNUSED(_state)) {
134   map = cbor_load(streamed_kv_map, 13, &res);
135   assert_non_null(map);
136   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
137   assert_true(cbor_isa_map(map));
138   assert_true(cbor_map_is_definite(map));
139   assert_size_equal(cbor_map_size(map), 1);
140   assert_size_equal(res.read, 13);
141   struct cbor_pair *handle = cbor_map_handle(map);
142   assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
143   assert_true(cbor_string_is_indefinite(handle[0].key));
144   assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
145   assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING);
146   assert_true(cbor_string_is_indefinite(handle[0].value));
147   assert_size_equal(cbor_string_chunk_count(handle[0].value), 2);
148   assert_memory_equal(
149       cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d",
150       1);
151   cbor_decref(&map);
152   assert_null(map);
153 }
154 
155 unsigned char streamed_streamed_kv_map[] = {0xBF, 0x7F, 0x61, 0x61, 0x61,
156                                             0x62, 0xFF, 0x7F, 0x61, 0x63,
157                                             0x61, 0x64, 0xFF, 0xFF};
158 
159 /* '{_ (_"a" "b"): (_"c", "d")}' */
test_streamed_streamed_kv_map(void ** _CBOR_UNUSED (_state))160 static void test_streamed_streamed_kv_map(void **_CBOR_UNUSED(_state)) {
161   map = cbor_load(streamed_streamed_kv_map, 14, &res);
162   assert_non_null(map);
163   assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
164   assert_true(cbor_isa_map(map));
165   assert_true(cbor_map_is_indefinite(map));
166   assert_size_equal(cbor_map_size(map), 1);
167   assert_size_equal(res.read, 14);
168   struct cbor_pair *handle = cbor_map_handle(map);
169   assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
170   assert_true(cbor_string_is_indefinite(handle[0].key));
171   assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
172   assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING);
173   assert_true(cbor_string_is_indefinite(handle[0].value));
174   assert_size_equal(cbor_string_chunk_count(handle[0].value), 2);
175   assert_memory_equal(
176       cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d",
177       1);
178   cbor_decref(&map);
179   assert_null(map);
180 }
181 
test_map_add_full(void ** _CBOR_UNUSED (_state))182 static void test_map_add_full(void **_CBOR_UNUSED(_state)) {
183   map = cbor_new_definite_map(0);
184   cbor_item_t *one = cbor_build_uint8(1);
185   cbor_item_t *two = cbor_build_uint8(2);
186 
187   assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two}));
188 
189   cbor_decref(&map);
190   cbor_decref(&one);
191   cbor_decref(&two);
192 }
193 
test_map_add_too_big_to_realloc(void ** _CBOR_UNUSED (_state))194 static void test_map_add_too_big_to_realloc(void **_CBOR_UNUSED(_state)) {
195   map = cbor_new_indefinite_map();
196   struct _cbor_map_metadata *metadata =
197       (struct _cbor_map_metadata *)&map->metadata;
198   // Pretend we already have a huge memory block
199   metadata->allocated = SIZE_MAX;
200   metadata->end_ptr = SIZE_MAX;
201   cbor_item_t *one = cbor_build_uint8(1);
202   cbor_item_t *two = cbor_build_uint8(2);
203 
204   assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two}));
205 
206   metadata->allocated = 0;
207   metadata->end_ptr = 0;
208   cbor_decref(&map);
209   cbor_decref(&one);
210   cbor_decref(&two);
211 }
212 
test_map_creation(void ** _CBOR_UNUSED (_state))213 static void test_map_creation(void **_CBOR_UNUSED(_state)) {
214   WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_map(42)); });
215   WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_map(42)); }, 2, MALLOC,
216                    MALLOC_FAIL);
217 
218   WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_map()); });
219 }
220 
test_map_add(void ** _CBOR_UNUSED (_state))221 static void test_map_add(void **_CBOR_UNUSED(_state)) {
222   WITH_MOCK_MALLOC(
223       {
224         cbor_item_t *map = cbor_new_indefinite_map();
225         cbor_item_t *key = cbor_build_uint8(0);
226         cbor_item_t *value = cbor_build_bool(true);
227 
228         assert_false(
229             cbor_map_add(map, (struct cbor_pair){.key = key, .value = value}));
230         assert_size_equal(cbor_map_allocated(map), 0);
231         assert_null(map->data);
232 
233         cbor_decref(&map);
234         cbor_decref(&key);
235         cbor_decref(&value);
236       },
237       4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
238 }
239 
240 static unsigned char test_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF};
test_indef_map_decode(void ** _CBOR_UNUSED (_state))241 static void test_indef_map_decode(void **_CBOR_UNUSED(_state)) {
242   WITH_MOCK_MALLOC(
243       {
244         cbor_item_t *map;
245         struct cbor_load_result res;
246         map = cbor_load(test_indef_map, 6, &res);
247 
248         assert_null(map);
249         assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
250       },
251       4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
252 }
253 
main(void)254 int main(void) {
255   const struct CMUnitTest tests[] = {
256       cmocka_unit_test(test_empty_map),
257       cmocka_unit_test(test_simple_map),
258       cmocka_unit_test(test_indef_simple_map),
259       cmocka_unit_test(test_def_nested_map),
260       cmocka_unit_test(test_streamed_key_map),
261       cmocka_unit_test(test_streamed_kv_map),
262       cmocka_unit_test(test_streamed_streamed_kv_map),
263       cmocka_unit_test(test_map_add_full),
264       cmocka_unit_test(test_map_add_too_big_to_realloc),
265       cmocka_unit_test(test_map_creation),
266       cmocka_unit_test(test_map_add),
267       cmocka_unit_test(test_indef_map_decode),
268   };
269   return cmocka_run_group_tests(tests, NULL, NULL);
270 }
271