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
12cbor_item_t *item, *copy, *tmp;
13
14static void test_uints(void **_CBOR_UNUSED(_state)) {
15  item = cbor_build_uint8(10);
16  assert_uint8(copy = cbor_copy(item), 10);
17  cbor_decref(&item);
18  cbor_decref(&copy);
19
20  item = cbor_build_uint16(10);
21  assert_uint16(copy = cbor_copy(item), 10);
22  cbor_decref(&item);
23  cbor_decref(&copy);
24
25  item = cbor_build_uint32(10);
26  assert_uint32(copy = cbor_copy(item), 10);
27  cbor_decref(&item);
28  cbor_decref(&copy);
29
30  item = cbor_build_uint64(10);
31  assert_uint64(copy = cbor_copy(item), 10);
32  cbor_decref(&item);
33  cbor_decref(&copy);
34}
35
36static void test_negints(void **_CBOR_UNUSED(_state)) {
37  item = cbor_build_negint8(10);
38  assert_true(cbor_get_uint8(copy = cbor_copy(item)) == 10);
39  cbor_decref(&item);
40  cbor_decref(&copy);
41
42  item = cbor_build_negint16(10);
43  assert_true(cbor_get_uint16(copy = cbor_copy(item)) == 10);
44  cbor_decref(&item);
45  cbor_decref(&copy);
46
47  item = cbor_build_negint32(10);
48  assert_true(cbor_get_uint32(copy = cbor_copy(item)) == 10);
49  cbor_decref(&item);
50  cbor_decref(&copy);
51
52  item = cbor_build_negint64(10);
53  assert_true(cbor_get_uint64(copy = cbor_copy(item)) == 10);
54  cbor_decref(&item);
55  cbor_decref(&copy);
56}
57
58static void test_def_bytestring(void **_CBOR_UNUSED(_state)) {
59  item = cbor_build_bytestring((cbor_data) "abc", 3);
60  assert_memory_equal(cbor_bytestring_handle(copy = cbor_copy(item)),
61                      cbor_bytestring_handle(item), 3);
62  cbor_decref(&item);
63  cbor_decref(&copy);
64}
65
66static void test_indef_bytestring(void **_CBOR_UNUSED(_state)) {
67  item = cbor_new_indefinite_bytestring();
68  assert_true(cbor_bytestring_add_chunk(
69      item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
70  copy = cbor_copy(item);
71
72  assert_size_equal(cbor_bytestring_chunk_count(item),
73                    cbor_bytestring_chunk_count(copy));
74
75  assert_memory_equal(
76      cbor_bytestring_handle(cbor_bytestring_chunks_handle(copy)[0]), "abc", 3);
77  cbor_decref(&item);
78  cbor_decref(&copy);
79}
80
81static void test_def_string(void **_CBOR_UNUSED(_state)) {
82  item = cbor_build_string("abc");
83  assert_memory_equal(cbor_string_handle(copy = cbor_copy(item)),
84                      cbor_string_handle(item), 3);
85  cbor_decref(&item);
86  cbor_decref(&copy);
87}
88
89static void test_indef_string(void **_CBOR_UNUSED(_state)) {
90  item = cbor_new_indefinite_string();
91  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
92  copy = cbor_copy(item);
93
94  assert_size_equal(cbor_string_chunk_count(item),
95                    cbor_string_chunk_count(copy));
96
97  assert_memory_equal(cbor_string_handle(cbor_string_chunks_handle(copy)[0]),
98                      "abc", 3);
99  cbor_decref(&item);
100  cbor_decref(&copy);
101}
102
103static void test_def_array(void **_CBOR_UNUSED(_state)) {
104  item = cbor_new_definite_array(1);
105  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
106
107  assert_uint8(tmp = cbor_array_get(copy = cbor_copy(item), 0), 42);
108  cbor_decref(&item);
109  cbor_decref(&copy);
110  cbor_decref(&tmp);
111}
112
113static void test_indef_array(void **_CBOR_UNUSED(_state)) {
114  item = cbor_new_indefinite_array();
115  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
116
117  assert_uint8(tmp = cbor_array_get(copy = cbor_copy(item), 0), 42);
118  cbor_decref(&item);
119  cbor_decref(&copy);
120  cbor_decref(&tmp);
121}
122
123static void test_def_map(void **_CBOR_UNUSED(_state)) {
124  item = cbor_new_definite_map(1);
125  assert_true(cbor_map_add(item, (struct cbor_pair){
126                                     .key = cbor_move(cbor_build_uint8(42)),
127                                     .value = cbor_move(cbor_build_uint8(43)),
128                                 }));
129
130  assert_uint8(cbor_map_handle(copy = cbor_copy(item))[0].key, 42);
131
132  cbor_decref(&item);
133  cbor_decref(&copy);
134}
135
136static void test_indef_map(void **_CBOR_UNUSED(_state)) {
137  item = cbor_new_indefinite_map();
138  assert_true(cbor_map_add(item, (struct cbor_pair){
139                                     .key = cbor_move(cbor_build_uint8(42)),
140                                     .value = cbor_move(cbor_build_uint8(43)),
141                                 }));
142
143  assert_uint8(cbor_map_handle(copy = cbor_copy(item))[0].key, 42);
144
145  cbor_decref(&item);
146  cbor_decref(&copy);
147}
148
149static void test_tag(void **_CBOR_UNUSED(_state)) {
150  item = cbor_build_tag(10, cbor_move(cbor_build_uint8(42)));
151
152  assert_uint8(cbor_move(cbor_tag_item(copy = cbor_copy(item))), 42);
153
154  cbor_decref(&item);
155  cbor_decref(&copy);
156}
157
158static void test_ctrls(void **_CBOR_UNUSED(_state)) {
159  item = cbor_new_null();
160  assert_true(cbor_is_null(copy = cbor_copy(item)));
161  cbor_decref(&item);
162  cbor_decref(&copy);
163}
164
165static void test_floats(void **_CBOR_UNUSED(_state)) {
166  item = cbor_build_float2(3.14f);
167  assert_true(cbor_float_get_float2(copy = cbor_copy(item)) ==
168              cbor_float_get_float2(item));
169  cbor_decref(&item);
170  cbor_decref(&copy);
171
172  item = cbor_build_float4(3.14f);
173  assert_true(cbor_float_get_float4(copy = cbor_copy(item)) ==
174              cbor_float_get_float4(item));
175  cbor_decref(&item);
176  cbor_decref(&copy);
177
178  item = cbor_build_float8(3.14);
179  assert_true(cbor_float_get_float8(copy = cbor_copy(item)) ==
180              cbor_float_get_float8(item));
181  cbor_decref(&item);
182  cbor_decref(&copy);
183}
184
185static void test_alloc_failure_simple(void **_CBOR_UNUSED(_state)) {
186  item = cbor_build_uint8(10);
187
188  WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
189  assert_size_equal(cbor_refcount(item), 1);
190
191  cbor_decref(&item);
192}
193
194static void test_bytestring_alloc_failure(void **_CBOR_UNUSED(_state)) {
195  item = cbor_new_indefinite_bytestring();
196  assert_true(cbor_bytestring_add_chunk(
197      item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
198
199  WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
200  assert_size_equal(cbor_refcount(item), 1);
201
202  cbor_decref(&item);
203}
204
205static void test_bytestring_chunk_alloc_failure(void **_CBOR_UNUSED(_state)) {
206  item = cbor_new_indefinite_bytestring();
207  assert_true(cbor_bytestring_add_chunk(
208      item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
209
210  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2, MALLOC, MALLOC_FAIL);
211  assert_size_equal(cbor_refcount(item), 1);
212
213  cbor_decref(&item);
214}
215
216static void test_bytestring_chunk_append_failure(void **_CBOR_UNUSED(_state)) {
217  item = cbor_new_indefinite_bytestring();
218  assert_true(cbor_bytestring_add_chunk(
219      item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
220
221  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 5,
222                   // New indef string, cbor_indefinite_string_data, chunk item,
223                   // chunk data, extend cbor_indefinite_string_data.chunks
224                   MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
225  assert_size_equal(cbor_refcount(item), 1);
226
227  cbor_decref(&item);
228}
229
230static void test_bytestring_second_chunk_alloc_failure(
231    void **_CBOR_UNUSED(_state)) {
232  item = cbor_new_indefinite_bytestring();
233  assert_true(cbor_bytestring_add_chunk(
234      item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
235  assert_true(cbor_bytestring_add_chunk(
236      item, cbor_move(cbor_build_bytestring((cbor_data) "def", 3))));
237
238  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 6,
239                   // New indef string, cbor_indefinite_string_data, chunk item,
240                   // chunk data, extend cbor_indefinite_string_data.chunks,
241                   // second chunk item
242                   MALLOC, MALLOC, MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
243  assert_size_equal(cbor_refcount(item), 1);
244
245  cbor_decref(&item);
246}
247
248static void test_string_alloc_failure(void **_CBOR_UNUSED(_state)) {
249  item = cbor_new_indefinite_string();
250  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
251
252  WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
253  assert_size_equal(cbor_refcount(item), 1);
254
255  cbor_decref(&item);
256}
257
258static void test_string_chunk_alloc_failure(void **_CBOR_UNUSED(_state)) {
259  item = cbor_new_indefinite_string();
260  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
261
262  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2, MALLOC, MALLOC_FAIL);
263  assert_size_equal(cbor_refcount(item), 1);
264
265  cbor_decref(&item);
266}
267
268static void test_string_chunk_append_failure(void **_CBOR_UNUSED(_state)) {
269  item = cbor_new_indefinite_string();
270  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
271
272  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 5,
273                   // New indef string, cbor_indefinite_string_data, chunk item,
274                   // chunk data, extend cbor_indefinite_string_data.chunks
275                   MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
276  assert_size_equal(cbor_refcount(item), 1);
277
278  cbor_decref(&item);
279}
280
281static void test_string_second_chunk_alloc_failure(
282    void **_CBOR_UNUSED(_state)) {
283  item = cbor_new_indefinite_string();
284  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
285  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("def"))));
286
287  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 6,
288                   // New indef string, cbor_indefinite_string_data, chunk item,
289                   // chunk data, extend cbor_indefinite_string_data.chunks,
290                   // second chunk item
291                   MALLOC, MALLOC, MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
292  assert_size_equal(cbor_refcount(item), 1);
293
294  cbor_decref(&item);
295}
296
297static void test_array_alloc_failure(void **_CBOR_UNUSED(_state)) {
298  item = cbor_new_indefinite_array();
299  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
300
301  WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
302  assert_size_equal(cbor_refcount(item), 1);
303
304  cbor_decref(&item);
305}
306
307static void test_array_item_alloc_failure(void **_CBOR_UNUSED(_state)) {
308  item = cbor_new_indefinite_array();
309  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
310
311  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2,
312                   // New array, item copy
313                   MALLOC, MALLOC_FAIL);
314
315  assert_size_equal(cbor_refcount(item), 1);
316
317  cbor_decref(&item);
318}
319
320static void test_array_push_failure(void **_CBOR_UNUSED(_state)) {
321  item = cbor_new_indefinite_array();
322  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
323
324  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 3,
325                   // New array, item copy, array reallocation
326                   MALLOC, MALLOC, REALLOC_FAIL);
327
328  assert_size_equal(cbor_refcount(item), 1);
329
330  cbor_decref(&item);
331}
332
333static void test_array_second_item_alloc_failure(void **_CBOR_UNUSED(_state)) {
334  item = cbor_new_indefinite_array();
335  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
336  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(43))));
337
338  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 4,
339                   // New array, item copy, array reallocation, second item copy
340                   MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
341
342  assert_size_equal(cbor_refcount(item), 1);
343
344  cbor_decref(&item);
345}
346
347static void test_map_alloc_failure(void **_CBOR_UNUSED(_state)) {
348  item = cbor_new_indefinite_map();
349  assert_true(
350      cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
351                                            cbor_move(cbor_build_bool(true))}));
352
353  WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
354  assert_size_equal(cbor_refcount(item), 1);
355
356  cbor_decref(&item);
357}
358
359static void test_map_key_alloc_failure(void **_CBOR_UNUSED(_state)) {
360  item = cbor_new_indefinite_map();
361  assert_true(
362      cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
363                                            cbor_move(cbor_build_bool(true))}));
364
365  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2,
366                   // New map, key copy
367                   MALLOC, MALLOC_FAIL);
368  assert_size_equal(cbor_refcount(item), 1);
369
370  cbor_decref(&item);
371}
372
373static void test_map_value_alloc_failure(void **_CBOR_UNUSED(_state)) {
374  item = cbor_new_indefinite_map();
375  assert_true(
376      cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
377                                            cbor_move(cbor_build_bool(true))}));
378
379  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 3,
380                   // New map, key copy, value copy
381                   MALLOC, MALLOC, MALLOC_FAIL);
382  assert_size_equal(cbor_refcount(item), 1);
383
384  cbor_decref(&item);
385}
386
387static void test_map_add_failure(void **_CBOR_UNUSED(_state)) {
388  item = cbor_new_indefinite_map();
389  assert_true(
390      cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
391                                            cbor_move(cbor_build_bool(true))}));
392
393  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 4,
394                   // New map, key copy, value copy, add
395                   MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
396  assert_size_equal(cbor_refcount(item), 1);
397
398  cbor_decref(&item);
399}
400
401static void test_map_second_key_failure(void **_CBOR_UNUSED(_state)) {
402  item = cbor_new_indefinite_map();
403  assert_true(
404      cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
405                                            cbor_move(cbor_build_bool(true))}));
406  assert_true(cbor_map_add(
407      item, (struct cbor_pair){cbor_move(cbor_build_uint8(43)),
408                               cbor_move(cbor_build_bool(false))}));
409
410  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 5,
411                   // New map, key copy, value copy, add, second key copy
412                   MALLOC, MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
413  assert_size_equal(cbor_refcount(item), 1);
414
415  cbor_decref(&item);
416}
417
418static void test_tag_item_alloc_failure(void **_CBOR_UNUSED(_state)) {
419  item = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
420
421  WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
422  assert_size_equal(cbor_refcount(item), 1);
423
424  cbor_decref(&item);
425}
426
427static void test_tag_alloc_failure(void **_CBOR_UNUSED(_state)) {
428  item = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
429
430  WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2,
431                   // Item copy, tag
432                   MALLOC, MALLOC_FAIL);
433  assert_size_equal(cbor_refcount(item), 1);
434
435  cbor_decref(&item);
436}
437
438int main(void) {
439  const struct CMUnitTest tests[] = {
440      cmocka_unit_test(test_uints),
441      cmocka_unit_test(test_negints),
442      cmocka_unit_test(test_def_bytestring),
443      cmocka_unit_test(test_indef_bytestring),
444      cmocka_unit_test(test_def_string),
445      cmocka_unit_test(test_indef_string),
446      cmocka_unit_test(test_def_array),
447      cmocka_unit_test(test_indef_array),
448      cmocka_unit_test(test_def_map),
449      cmocka_unit_test(test_indef_map),
450      cmocka_unit_test(test_tag),
451      cmocka_unit_test(test_ctrls),
452      cmocka_unit_test(test_floats),
453      cmocka_unit_test(test_alloc_failure_simple),
454      cmocka_unit_test(test_bytestring_alloc_failure),
455      cmocka_unit_test(test_bytestring_chunk_alloc_failure),
456      cmocka_unit_test(test_bytestring_chunk_append_failure),
457      cmocka_unit_test(test_bytestring_second_chunk_alloc_failure),
458      cmocka_unit_test(test_string_alloc_failure),
459      cmocka_unit_test(test_string_chunk_alloc_failure),
460      cmocka_unit_test(test_string_chunk_append_failure),
461      cmocka_unit_test(test_string_second_chunk_alloc_failure),
462      cmocka_unit_test(test_array_alloc_failure),
463      cmocka_unit_test(test_array_item_alloc_failure),
464      cmocka_unit_test(test_array_push_failure),
465      cmocka_unit_test(test_array_second_item_alloc_failure),
466      cmocka_unit_test(test_map_alloc_failure),
467      cmocka_unit_test(test_map_key_alloc_failure),
468      cmocka_unit_test(test_map_value_alloc_failure),
469      cmocka_unit_test(test_map_add_failure),
470      cmocka_unit_test(test_map_second_key_failure),
471      cmocka_unit_test(test_tag_item_alloc_failure),
472      cmocka_unit_test(test_tag_alloc_failure),
473  };
474  return cmocka_run_group_tests(tests, NULL, NULL);
475}
476