xref: /freebsd/contrib/libcbor/test/array_test.c (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
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 "assertions.h"
9 #include "cbor.h"
10 #include "test_allocator.h"
11 
12 cbor_item_t *arr;
13 struct cbor_load_result res;
14 
15 unsigned char data1[] = {0x80, 0xFF};
16 
17 static void test_empty_array(void **_CBOR_UNUSED(_state)) {
18   arr = cbor_load(data1, 2, &res);
19   assert_non_null(arr);
20   assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
21   assert_true(cbor_isa_array(arr));
22   assert_true(cbor_array_size(arr) == 0);
23   assert_true(res.read == 1);
24   cbor_decref(&arr);
25   assert_null(arr);
26 }
27 
28 unsigned char data2[] = {0x81, 0x01, 0xFF};
29 
30 static void test_simple_array(void **_CBOR_UNUSED(_state)) {
31   arr = cbor_load(data2, 3, &res);
32   assert_non_null(arr);
33   assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
34   assert_true(cbor_isa_array(arr));
35   assert_size_equal(cbor_array_size(arr), 1);
36   assert_true(res.read == 2);
37   assert_size_equal(cbor_array_allocated(arr), 1);
38   /* Check the values */
39   assert_uint8(cbor_array_handle(arr)[0], 1);
40   cbor_item_t *intermediate = cbor_array_get(arr, 0);
41   assert_uint8(intermediate, 1);
42 
43   cbor_item_t *new_val = cbor_build_uint8(10);
44   assert_false(cbor_array_set(arr, 1, new_val));
45   assert_false(cbor_array_set(arr, 3, new_val));
46   cbor_decref(&new_val);
47 
48   cbor_decref(&arr);
49   cbor_decref(&intermediate);
50   assert_null(arr);
51   assert_null(intermediate);
52 }
53 
54 unsigned char data3[] = {0x82, 0x01, 0x81, 0x01, 0xFF};
55 
56 static void test_nested_arrays(void **_CBOR_UNUSED(_state)) {
57   arr = cbor_load(data3, 5, &res);
58   assert_non_null(arr);
59   assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
60   assert_true(cbor_isa_array(arr));
61   assert_true(cbor_array_size(arr) == 2);
62   assert_true(res.read == 4);
63   /* Check the values */
64   assert_uint8(cbor_array_handle(arr)[0], 1);
65 
66   cbor_item_t *nested = cbor_array_handle(arr)[1];
67   assert_true(cbor_isa_array(nested));
68   assert_true(cbor_array_size(nested) == 1);
69   assert_uint8(cbor_array_handle(nested)[0], 1);
70 
71   cbor_decref(&arr);
72   assert_null(arr);
73 }
74 
75 unsigned char test_indef_arrays_data[] = {0x9f, 0x01, 0x02, 0xFF};
76 
77 static void test_indef_arrays(void **_CBOR_UNUSED(_state)) {
78   arr = cbor_load(test_indef_arrays_data, 4, &res);
79   assert_non_null(arr);
80   assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
81   assert_true(cbor_isa_array(arr));
82   assert_true(cbor_array_size(arr) == 2);
83   assert_true(res.read == 4);
84   /* Check the values */
85   assert_uint8(cbor_array_handle(arr)[0], 1);
86   assert_uint8(cbor_array_handle(arr)[1], 2);
87 
88   assert_true(cbor_array_set(arr, 1, cbor_move(cbor_build_uint8(10))));
89 
90   cbor_decref(&arr);
91   assert_null(arr);
92 }
93 
94 unsigned char test_nested_indef_arrays_data[] = {0x9f, 0x01, 0x9f, 0x02,
95                                                  0xFF, 0x03, 0xFF};
96 
97 static void test_nested_indef_arrays(void **_CBOR_UNUSED(_state)) {
98   arr = cbor_load(test_nested_indef_arrays_data, 7, &res);
99   assert_non_null(arr);
100   assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
101   assert_true(cbor_isa_array(arr));
102   assert_size_equal(cbor_array_size(arr), 3);
103   assert_true(res.read == 7);
104   /* Check the values */
105   assert_uint8(cbor_array_handle(arr)[0], 1);
106 
107   cbor_item_t *nested = cbor_array_handle(arr)[1];
108   assert_true(cbor_isa_array(nested));
109   assert_true(cbor_array_size(nested) == 1);
110   assert_uint8(cbor_array_handle(nested)[0], 2);
111 
112   cbor_decref(&arr);
113   assert_null(arr);
114 }
115 
116 static void test_array_replace(void **_CBOR_UNUSED(_state)) {
117   cbor_item_t *array = cbor_new_definite_array(2);
118   assert_size_equal(cbor_array_size(array), 0);
119   cbor_item_t *one = cbor_build_uint8(1);
120   cbor_item_t *three = cbor_build_uint8(3);
121   assert_size_equal(cbor_refcount(one), 1);
122   assert_size_equal(cbor_refcount(three), 1);
123 
124   // No item to replace
125   assert_false(cbor_array_replace(array, 0, three));
126   assert_size_equal(cbor_refcount(three), 1);
127 
128   // Add items [1, 2]
129   assert_true(cbor_array_push(array, one));
130   assert_true(cbor_array_push(array, cbor_move(cbor_build_uint8(2))));
131   assert_size_equal(cbor_refcount(one), 2);
132   assert_size_equal(cbor_array_size(array), 2);
133 
134   // Array has only two items
135   assert_false(cbor_array_replace(array, 2, three));
136   assert_size_equal(cbor_refcount(three), 1);
137 
138   // Change [1, 2] to [3, 2]
139   assert_true(cbor_array_replace(array, 0, three));
140   assert_size_equal(cbor_refcount(one), 1);
141   assert_size_equal(cbor_refcount(three), 2);
142   assert_uint8(cbor_move(cbor_array_get(array, 0)), 3);
143   assert_uint8(cbor_move(cbor_array_get(array, 1)), 2);
144 
145   cbor_decref(&one);
146   cbor_decref(&three);
147   cbor_decref(&array);
148 }
149 
150 static void test_array_push_overflow(void **_CBOR_UNUSED(_state)) {
151   cbor_item_t *array = cbor_new_indefinite_array();
152   cbor_item_t *one = cbor_build_uint8(1);
153   struct _cbor_array_metadata *metadata =
154       (struct _cbor_array_metadata *)&array->metadata;
155   // Pretend we already have a huge block allocated
156   metadata->allocated = SIZE_MAX;
157   metadata->end_ptr = SIZE_MAX;
158 
159   assert_false(cbor_array_push(array, one));
160   assert_size_equal(cbor_refcount(one), 1);
161 
162   cbor_decref(&one);
163   metadata->allocated = 0;
164   metadata->end_ptr = 0;
165   cbor_decref(&array);
166 }
167 
168 static void test_array_creation(void **_CBOR_UNUSED(_state)) {
169   WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_array(42)); });
170   WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_array(42)); }, 2, MALLOC,
171                    MALLOC_FAIL);
172 
173   WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_array()); });
174 }
175 
176 static void test_array_push(void **_CBOR_UNUSED(_state)) {
177   WITH_MOCK_MALLOC(
178       {
179         cbor_item_t *array = cbor_new_indefinite_array();
180         cbor_item_t *string = cbor_build_string("Hello!");
181 
182         assert_false(cbor_array_push(array, string));
183         assert_size_equal(cbor_array_allocated(array), 0);
184         assert_null(array->data);
185         assert_size_equal(array->metadata.array_metadata.end_ptr, 0);
186 
187         cbor_decref(&string);
188         cbor_decref(&array);
189       },
190       4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
191 }
192 
193 static unsigned char simple_indef_array[] = {0x9F, 0x01, 0x02, 0xFF};
194 static void test_indef_array_decode(void **_CBOR_UNUSED(_state)) {
195   WITH_MOCK_MALLOC(
196       {
197         cbor_item_t *array;
198         struct cbor_load_result res;
199         array = cbor_load(simple_indef_array, 4, &res);
200 
201         assert_null(array);
202         assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
203       },
204       4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
205 }
206 
207 int main(void) {
208   const struct CMUnitTest tests[] = {
209       cmocka_unit_test(test_empty_array),
210       cmocka_unit_test(test_simple_array),
211       cmocka_unit_test(test_nested_arrays),
212       cmocka_unit_test(test_indef_arrays),
213       cmocka_unit_test(test_nested_indef_arrays),
214       cmocka_unit_test(test_array_replace),
215       cmocka_unit_test(test_array_push_overflow),
216       cmocka_unit_test(test_array_creation),
217       cmocka_unit_test(test_array_push),
218       cmocka_unit_test(test_indef_array_decode),
219   };
220 
221   return cmocka_run_group_tests(tests, NULL, NULL);
222 }
223