1058aa793SEd Maste /*
2058aa793SEd Maste * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
3058aa793SEd Maste *
4058aa793SEd Maste * libcbor is free software; you can redistribute it and/or modify
5058aa793SEd Maste * it under the terms of the MIT license. See LICENSE for details.
6058aa793SEd Maste */
7058aa793SEd Maste
8058aa793SEd Maste #include "assertions.h"
9058aa793SEd Maste #include "cbor.h"
10058aa793SEd Maste #include "test_allocator.h"
11058aa793SEd Maste
12058aa793SEd Maste cbor_item_t *arr;
13058aa793SEd Maste struct cbor_load_result res;
14058aa793SEd Maste
15058aa793SEd Maste unsigned char data1[] = {0x80, 0xFF};
16058aa793SEd Maste
test_empty_array(void ** _CBOR_UNUSED (_state))17058aa793SEd Maste static void test_empty_array(void **_CBOR_UNUSED(_state)) {
18058aa793SEd Maste arr = cbor_load(data1, 2, &res);
19058aa793SEd Maste assert_non_null(arr);
20058aa793SEd Maste assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
21058aa793SEd Maste assert_true(cbor_isa_array(arr));
22058aa793SEd Maste assert_true(cbor_array_size(arr) == 0);
23058aa793SEd Maste assert_true(res.read == 1);
24058aa793SEd Maste cbor_decref(&arr);
25058aa793SEd Maste assert_null(arr);
26058aa793SEd Maste }
27058aa793SEd Maste
28058aa793SEd Maste unsigned char data2[] = {0x81, 0x01, 0xFF};
29058aa793SEd Maste
test_simple_array(void ** _CBOR_UNUSED (_state))30058aa793SEd Maste static void test_simple_array(void **_CBOR_UNUSED(_state)) {
31058aa793SEd Maste arr = cbor_load(data2, 3, &res);
32058aa793SEd Maste assert_non_null(arr);
33058aa793SEd Maste assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
34058aa793SEd Maste assert_true(cbor_isa_array(arr));
35058aa793SEd Maste assert_size_equal(cbor_array_size(arr), 1);
36058aa793SEd Maste assert_true(res.read == 2);
37058aa793SEd Maste assert_size_equal(cbor_array_allocated(arr), 1);
38058aa793SEd Maste /* Check the values */
39058aa793SEd Maste assert_uint8(cbor_array_handle(arr)[0], 1);
40058aa793SEd Maste cbor_item_t *intermediate = cbor_array_get(arr, 0);
41058aa793SEd Maste assert_uint8(intermediate, 1);
42058aa793SEd Maste
43058aa793SEd Maste cbor_item_t *new_val = cbor_build_uint8(10);
44058aa793SEd Maste assert_false(cbor_array_set(arr, 1, new_val));
45058aa793SEd Maste assert_false(cbor_array_set(arr, 3, new_val));
46058aa793SEd Maste cbor_decref(&new_val);
47058aa793SEd Maste
48058aa793SEd Maste cbor_decref(&arr);
49058aa793SEd Maste cbor_decref(&intermediate);
50058aa793SEd Maste assert_null(arr);
51058aa793SEd Maste assert_null(intermediate);
52058aa793SEd Maste }
53058aa793SEd Maste
54058aa793SEd Maste unsigned char data3[] = {0x82, 0x01, 0x81, 0x01, 0xFF};
55058aa793SEd Maste
test_nested_arrays(void ** _CBOR_UNUSED (_state))56058aa793SEd Maste static void test_nested_arrays(void **_CBOR_UNUSED(_state)) {
57058aa793SEd Maste arr = cbor_load(data3, 5, &res);
58058aa793SEd Maste assert_non_null(arr);
59058aa793SEd Maste assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
60058aa793SEd Maste assert_true(cbor_isa_array(arr));
61058aa793SEd Maste assert_true(cbor_array_size(arr) == 2);
62058aa793SEd Maste assert_true(res.read == 4);
63058aa793SEd Maste /* Check the values */
64058aa793SEd Maste assert_uint8(cbor_array_handle(arr)[0], 1);
65058aa793SEd Maste
66058aa793SEd Maste cbor_item_t *nested = cbor_array_handle(arr)[1];
67058aa793SEd Maste assert_true(cbor_isa_array(nested));
68058aa793SEd Maste assert_true(cbor_array_size(nested) == 1);
69058aa793SEd Maste assert_uint8(cbor_array_handle(nested)[0], 1);
70058aa793SEd Maste
71058aa793SEd Maste cbor_decref(&arr);
72058aa793SEd Maste assert_null(arr);
73058aa793SEd Maste }
74058aa793SEd Maste
75058aa793SEd Maste unsigned char test_indef_arrays_data[] = {0x9f, 0x01, 0x02, 0xFF};
76058aa793SEd Maste
test_indef_arrays(void ** _CBOR_UNUSED (_state))77058aa793SEd Maste static void test_indef_arrays(void **_CBOR_UNUSED(_state)) {
78058aa793SEd Maste arr = cbor_load(test_indef_arrays_data, 4, &res);
79058aa793SEd Maste assert_non_null(arr);
80058aa793SEd Maste assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
81058aa793SEd Maste assert_true(cbor_isa_array(arr));
82058aa793SEd Maste assert_true(cbor_array_size(arr) == 2);
83058aa793SEd Maste assert_true(res.read == 4);
84058aa793SEd Maste /* Check the values */
85058aa793SEd Maste assert_uint8(cbor_array_handle(arr)[0], 1);
86058aa793SEd Maste assert_uint8(cbor_array_handle(arr)[1], 2);
87058aa793SEd Maste
88058aa793SEd Maste assert_true(cbor_array_set(arr, 1, cbor_move(cbor_build_uint8(10))));
89058aa793SEd Maste
90058aa793SEd Maste cbor_decref(&arr);
91058aa793SEd Maste assert_null(arr);
92058aa793SEd Maste }
93058aa793SEd Maste
94058aa793SEd Maste unsigned char test_nested_indef_arrays_data[] = {0x9f, 0x01, 0x9f, 0x02,
95058aa793SEd Maste 0xFF, 0x03, 0xFF};
96058aa793SEd Maste
test_nested_indef_arrays(void ** _CBOR_UNUSED (_state))97058aa793SEd Maste static void test_nested_indef_arrays(void **_CBOR_UNUSED(_state)) {
98058aa793SEd Maste arr = cbor_load(test_nested_indef_arrays_data, 7, &res);
99058aa793SEd Maste assert_non_null(arr);
100058aa793SEd Maste assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
101058aa793SEd Maste assert_true(cbor_isa_array(arr));
102058aa793SEd Maste assert_size_equal(cbor_array_size(arr), 3);
103058aa793SEd Maste assert_true(res.read == 7);
104058aa793SEd Maste /* Check the values */
105058aa793SEd Maste assert_uint8(cbor_array_handle(arr)[0], 1);
106058aa793SEd Maste
107058aa793SEd Maste cbor_item_t *nested = cbor_array_handle(arr)[1];
108058aa793SEd Maste assert_true(cbor_isa_array(nested));
109058aa793SEd Maste assert_true(cbor_array_size(nested) == 1);
110058aa793SEd Maste assert_uint8(cbor_array_handle(nested)[0], 2);
111058aa793SEd Maste
112058aa793SEd Maste cbor_decref(&arr);
113058aa793SEd Maste assert_null(arr);
114058aa793SEd Maste }
115058aa793SEd Maste
test_array_replace(void ** _CBOR_UNUSED (_state))116058aa793SEd Maste static void test_array_replace(void **_CBOR_UNUSED(_state)) {
117058aa793SEd Maste cbor_item_t *array = cbor_new_definite_array(2);
118058aa793SEd Maste assert_size_equal(cbor_array_size(array), 0);
119058aa793SEd Maste cbor_item_t *one = cbor_build_uint8(1);
120058aa793SEd Maste cbor_item_t *three = cbor_build_uint8(3);
121058aa793SEd Maste assert_size_equal(cbor_refcount(one), 1);
122058aa793SEd Maste assert_size_equal(cbor_refcount(three), 1);
123058aa793SEd Maste
124058aa793SEd Maste // No item to replace
125058aa793SEd Maste assert_false(cbor_array_replace(array, 0, three));
126058aa793SEd Maste assert_size_equal(cbor_refcount(three), 1);
127058aa793SEd Maste
128058aa793SEd Maste // Add items [1, 2]
129058aa793SEd Maste assert_true(cbor_array_push(array, one));
130058aa793SEd Maste assert_true(cbor_array_push(array, cbor_move(cbor_build_uint8(2))));
131058aa793SEd Maste assert_size_equal(cbor_refcount(one), 2);
132058aa793SEd Maste assert_size_equal(cbor_array_size(array), 2);
133058aa793SEd Maste
134058aa793SEd Maste // Array has only two items
135058aa793SEd Maste assert_false(cbor_array_replace(array, 2, three));
136058aa793SEd Maste assert_size_equal(cbor_refcount(three), 1);
137058aa793SEd Maste
138058aa793SEd Maste // Change [1, 2] to [3, 2]
139058aa793SEd Maste assert_true(cbor_array_replace(array, 0, three));
140058aa793SEd Maste assert_size_equal(cbor_refcount(one), 1);
141058aa793SEd Maste assert_size_equal(cbor_refcount(three), 2);
142058aa793SEd Maste assert_uint8(cbor_move(cbor_array_get(array, 0)), 3);
143058aa793SEd Maste assert_uint8(cbor_move(cbor_array_get(array, 1)), 2);
144058aa793SEd Maste
145058aa793SEd Maste cbor_decref(&one);
146058aa793SEd Maste cbor_decref(&three);
147058aa793SEd Maste cbor_decref(&array);
148058aa793SEd Maste }
149058aa793SEd Maste
test_array_push_overflow(void ** _CBOR_UNUSED (_state))150058aa793SEd Maste static void test_array_push_overflow(void **_CBOR_UNUSED(_state)) {
151058aa793SEd Maste cbor_item_t *array = cbor_new_indefinite_array();
152058aa793SEd Maste cbor_item_t *one = cbor_build_uint8(1);
153058aa793SEd Maste struct _cbor_array_metadata *metadata =
154058aa793SEd Maste (struct _cbor_array_metadata *)&array->metadata;
155058aa793SEd Maste // Pretend we already have a huge block allocated
156058aa793SEd Maste metadata->allocated = SIZE_MAX;
157058aa793SEd Maste metadata->end_ptr = SIZE_MAX;
158058aa793SEd Maste
159058aa793SEd Maste assert_false(cbor_array_push(array, one));
160058aa793SEd Maste assert_size_equal(cbor_refcount(one), 1);
161058aa793SEd Maste
162058aa793SEd Maste cbor_decref(&one);
163058aa793SEd Maste metadata->allocated = 0;
164058aa793SEd Maste metadata->end_ptr = 0;
165058aa793SEd Maste cbor_decref(&array);
166058aa793SEd Maste }
167058aa793SEd Maste
test_array_creation(void ** _CBOR_UNUSED (_state))168058aa793SEd Maste static void test_array_creation(void **_CBOR_UNUSED(_state)) {
169058aa793SEd Maste WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_array(42)); });
170058aa793SEd Maste WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_array(42)); }, 2, MALLOC,
171058aa793SEd Maste MALLOC_FAIL);
172058aa793SEd Maste
173058aa793SEd Maste WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_array()); });
174058aa793SEd Maste }
175058aa793SEd Maste
test_array_push(void ** _CBOR_UNUSED (_state))176058aa793SEd Maste static void test_array_push(void **_CBOR_UNUSED(_state)) {
177058aa793SEd Maste WITH_MOCK_MALLOC(
178058aa793SEd Maste {
179058aa793SEd Maste cbor_item_t *array = cbor_new_indefinite_array();
180058aa793SEd Maste cbor_item_t *string = cbor_build_string("Hello!");
181058aa793SEd Maste
182058aa793SEd Maste assert_false(cbor_array_push(array, string));
183058aa793SEd Maste assert_size_equal(cbor_array_allocated(array), 0);
184058aa793SEd Maste assert_null(array->data);
185058aa793SEd Maste assert_size_equal(array->metadata.array_metadata.end_ptr, 0);
186058aa793SEd Maste
187058aa793SEd Maste cbor_decref(&string);
188058aa793SEd Maste cbor_decref(&array);
189058aa793SEd Maste },
190058aa793SEd Maste 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
191058aa793SEd Maste }
192058aa793SEd Maste
193058aa793SEd Maste static unsigned char simple_indef_array[] = {0x9F, 0x01, 0x02, 0xFF};
test_indef_array_decode(void ** _CBOR_UNUSED (_state))194058aa793SEd Maste static void test_indef_array_decode(void **_CBOR_UNUSED(_state)) {
195058aa793SEd Maste WITH_MOCK_MALLOC(
196058aa793SEd Maste {
197058aa793SEd Maste cbor_item_t *array;
198058aa793SEd Maste struct cbor_load_result res;
199058aa793SEd Maste array = cbor_load(simple_indef_array, 4, &res);
200058aa793SEd Maste
201058aa793SEd Maste assert_null(array);
202058aa793SEd Maste assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
203058aa793SEd Maste },
204058aa793SEd Maste 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
205058aa793SEd Maste }
206058aa793SEd Maste
main(void)207058aa793SEd Maste int main(void) {
208058aa793SEd Maste const struct CMUnitTest tests[] = {
209058aa793SEd Maste cmocka_unit_test(test_empty_array),
210058aa793SEd Maste cmocka_unit_test(test_simple_array),
211058aa793SEd Maste cmocka_unit_test(test_nested_arrays),
212058aa793SEd Maste cmocka_unit_test(test_indef_arrays),
213058aa793SEd Maste cmocka_unit_test(test_nested_indef_arrays),
214058aa793SEd Maste cmocka_unit_test(test_array_replace),
215058aa793SEd Maste cmocka_unit_test(test_array_push_overflow),
216058aa793SEd Maste cmocka_unit_test(test_array_creation),
217058aa793SEd Maste cmocka_unit_test(test_array_push),
218058aa793SEd Maste cmocka_unit_test(test_indef_array_decode),
219058aa793SEd Maste };
220058aa793SEd Maste
221058aa793SEd Maste return cmocka_run_group_tests(tests, NULL, NULL);
222058aa793SEd Maste }
223