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