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// cbor_serialize_alloc
9#pragma clang diagnostic ignored "-Wdeprecated-declarations"
10#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
11
12#include <math.h>
13#include <setjmp.h>
14#include <stdarg.h>
15#include <stddef.h>
16#include <stdint.h>
17#include <string.h>
18
19#include <cmocka.h>
20
21#include "assertions.h"
22#include "cbor.h"
23#include "test_allocator.h"
24
25unsigned char buffer[512];
26
27static void test_serialize_uint8_embed(void **_CBOR_UNUSED(_state)) {
28  cbor_item_t *item = cbor_new_int8();
29  cbor_set_uint8(item, 0);
30  assert_size_equal(1, cbor_serialize(item, buffer, 512));
31  assert_memory_equal(buffer, (unsigned char[]){0x00}, 1);
32  assert_size_equal(cbor_serialized_size(item), 1);
33  cbor_decref(&item);
34}
35
36static void test_serialize_uint8(void **_CBOR_UNUSED(_state)) {
37  cbor_item_t *item = cbor_new_int8();
38  cbor_set_uint8(item, 42);
39  assert_size_equal(2, cbor_serialize(item, buffer, 512));
40  assert_memory_equal(buffer, ((unsigned char[]){0x18, 0x2a}), 2);
41  assert_size_equal(cbor_serialized_size(item), 2);
42  cbor_decref(&item);
43}
44
45static void test_serialize_uint16(void **_CBOR_UNUSED(_state)) {
46  cbor_item_t *item = cbor_new_int16();
47  cbor_set_uint16(item, 1000);
48  assert_size_equal(3, cbor_serialize(item, buffer, 512));
49  assert_memory_equal(buffer, ((unsigned char[]){0x19, 0x03, 0xE8}), 3);
50  assert_size_equal(cbor_serialized_size(item), 3);
51  cbor_decref(&item);
52}
53
54static void test_serialize_uint32(void **_CBOR_UNUSED(_state)) {
55  cbor_item_t *item = cbor_new_int32();
56  cbor_set_uint32(item, 1000000);
57  assert_size_equal(5, cbor_serialize(item, buffer, 512));
58  assert_memory_equal(buffer, ((unsigned char[]){0x1A, 0x00, 0x0F, 0x42, 0x40}),
59                      5);
60  assert_size_equal(cbor_serialized_size(item), 5);
61  cbor_decref(&item);
62}
63
64static void test_serialize_uint64(void **_CBOR_UNUSED(_state)) {
65  cbor_item_t *item = cbor_new_int64();
66  cbor_set_uint64(item, 1000000000000);
67  assert_size_equal(9, cbor_serialize(item, buffer, 512));
68  assert_memory_equal(
69      buffer,
70      ((unsigned char[]){0x1B, 0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x10, 0x00}),
71      9);
72  assert_size_equal(cbor_serialized_size(item), 9);
73  cbor_decref(&item);
74}
75
76static void test_serialize_negint8_embed(void **_CBOR_UNUSED(_state)) {
77  cbor_item_t *item = cbor_new_int8();
78  cbor_set_uint8(item, 0);
79  cbor_mark_negint(item);
80  assert_size_equal(1, cbor_serialize(item, buffer, 512));
81  assert_memory_equal(buffer, (unsigned char[]){0x20}, 1);
82  assert_size_equal(cbor_serialized_size(item), 1);
83  cbor_decref(&item);
84}
85
86static void test_serialize_negint8(void **_CBOR_UNUSED(_state)) {
87  cbor_item_t *item = cbor_new_int8();
88  cbor_set_uint8(item, 42);
89  cbor_mark_negint(item);
90  assert_size_equal(2, cbor_serialize(item, buffer, 512));
91  assert_memory_equal(buffer, ((unsigned char[]){0x38, 0x2a}), 2);
92  assert_size_equal(cbor_serialized_size(item), 2);
93  cbor_decref(&item);
94}
95
96static void test_serialize_negint16(void **_CBOR_UNUSED(_state)) {
97  cbor_item_t *item = cbor_new_int16();
98  cbor_set_uint16(item, 1000);
99  cbor_mark_negint(item);
100  assert_size_equal(3, cbor_serialize(item, buffer, 512));
101  assert_memory_equal(buffer, ((unsigned char[]){0x39, 0x03, 0xE8}), 3);
102  assert_size_equal(cbor_serialized_size(item), 3);
103  cbor_decref(&item);
104}
105
106static void test_serialize_negint32(void **_CBOR_UNUSED(_state)) {
107  cbor_item_t *item = cbor_new_int32();
108  cbor_set_uint32(item, 1000000);
109  cbor_mark_negint(item);
110  assert_size_equal(5, cbor_serialize(item, buffer, 512));
111  assert_memory_equal(buffer, ((unsigned char[]){0x3A, 0x00, 0x0F, 0x42, 0x40}),
112                      5);
113  assert_size_equal(cbor_serialized_size(item), 5);
114  cbor_decref(&item);
115}
116
117static void test_serialize_negint64(void **_CBOR_UNUSED(_state)) {
118  cbor_item_t *item = cbor_new_int64();
119  cbor_set_uint64(item, 1000000000000);
120  cbor_mark_negint(item);
121  assert_size_equal(9, cbor_serialize(item, buffer, 512));
122  assert_memory_equal(
123      buffer,
124      ((unsigned char[]){0x3B, 0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x10, 0x00}),
125      9);
126  assert_size_equal(cbor_serialized_size(item), 9);
127  cbor_decref(&item);
128}
129
130static void test_serialize_definite_bytestring(void **_CBOR_UNUSED(_state)) {
131  cbor_item_t *item = cbor_new_definite_bytestring();
132  unsigned char *data = malloc(256);
133  cbor_bytestring_set_handle(item, data, 256);
134  memset(data, 0, 256); /* Prevent undefined behavior in comparison */
135  assert_size_equal(256 + 3, cbor_serialize(item, buffer, 512));
136  assert_memory_equal(buffer, ((unsigned char[]){0x59, 0x01, 0x00}), 3);
137  assert_memory_equal(buffer + 3, data, 256);
138  assert_size_equal(cbor_serialized_size(item), 259);
139  cbor_decref(&item);
140}
141
142static void test_serialize_indefinite_bytestring(void **_CBOR_UNUSED(_state)) {
143  cbor_item_t *item = cbor_new_indefinite_bytestring();
144
145  cbor_item_t *chunk = cbor_new_definite_bytestring();
146  unsigned char *data = malloc(256);
147  memset(data, 0, 256); /* Prevent undefined behavior in comparison */
148  cbor_bytestring_set_handle(chunk, data, 256);
149
150  assert_true(cbor_bytestring_add_chunk(item, cbor_move(chunk)));
151  assert_size_equal(cbor_bytestring_chunk_count(item), 1);
152
153  assert_size_equal(1 + 3 + 256 + 1, cbor_serialize(item, buffer, 512));
154  assert_memory_equal(buffer, ((unsigned char[]){0x5F, 0x59, 0x01, 0x00}), 4);
155  assert_memory_equal(buffer + 4, data, 256);
156  assert_memory_equal(buffer + 4 + 256, ((unsigned char[]){0xFF}), 1);
157  assert_size_equal(cbor_serialized_size(item), 261);
158  cbor_decref(&item);
159}
160
161static void test_serialize_bytestring_size_overflow(
162    void **_CBOR_UNUSED(_state)) {
163  cbor_item_t *item = cbor_new_definite_bytestring();
164
165  // Fake having a huge chunk of data
166  unsigned char *data = malloc(1);
167  cbor_bytestring_set_handle(item, data, SIZE_MAX);
168
169  // Would require 1 + 8 + SIZE_MAX bytes, which overflows size_t
170  assert_size_equal(cbor_serialize(item, buffer, 512), 0);
171  assert_size_equal(cbor_serialized_size(item), 0);
172  cbor_decref(&item);
173}
174
175static void test_serialize_bytestring_no_space(void **_CBOR_UNUSED(_state)) {
176  cbor_item_t *item = cbor_new_definite_bytestring();
177  unsigned char *data = malloc(12);
178  cbor_bytestring_set_handle(item, data, 12);
179
180  assert_size_equal(cbor_serialize(item, buffer, 1), 0);
181
182  cbor_decref(&item);
183}
184
185static void test_serialize_indefinite_bytestring_no_space(
186    void **_CBOR_UNUSED(_state)) {
187  cbor_item_t *item = cbor_new_indefinite_bytestring();
188  cbor_item_t *chunk = cbor_new_definite_bytestring();
189  unsigned char *data = malloc(256);
190  cbor_bytestring_set_handle(chunk, data, 256);
191  assert_true(cbor_bytestring_add_chunk(item, cbor_move(chunk)));
192
193  // Not enough space for the leading byte
194  assert_size_equal(cbor_serialize(item, buffer, 0), 0);
195
196  // Not enough space for the chunk
197  assert_size_equal(cbor_serialize(item, buffer, 30), 0);
198
199  // Not enough space for the indef break
200  assert_size_equal(
201      cbor_serialize(item, buffer, 1 + cbor_serialized_size(chunk)), 0);
202
203  cbor_decref(&item);
204}
205
206static void test_serialize_definite_string(void **_CBOR_UNUSED(_state)) {
207  cbor_item_t *item = cbor_new_definite_string();
208  unsigned char *data = malloc(12);
209  strncpy((char *)data, "Hello world!", 12);
210  cbor_string_set_handle(item, data, 12);
211  assert_size_equal(1 + 12, cbor_serialize(item, buffer, 512));
212  assert_memory_equal(
213      buffer,
214      ((unsigned char[]){0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
215                         0x72, 0x6C, 0x64, 0x21}),
216      13);
217  assert_size_equal(cbor_serialized_size(item), 13);
218  cbor_decref(&item);
219}
220
221static void test_serialize_definite_string_4b_header(
222    void **_CBOR_UNUSED(_state)) {
223#if SIZE_MAX > UINT16_MAX
224  cbor_item_t *item = cbor_new_definite_string();
225  const size_t size = (size_t)UINT16_MAX + 1;
226  unsigned char *data = malloc(size);
227  memset(data, 0, size);
228  cbor_string_set_handle(item, data, size);
229  assert_size_equal(cbor_serialized_size(item), 1 + 4 + size);
230  cbor_decref(&item);
231#endif
232}
233
234static void test_serialize_definite_string_8b_header(
235    void **_CBOR_UNUSED(_state)) {
236#if SIZE_MAX > UINT32_MAX
237  cbor_item_t *item = cbor_new_definite_string();
238  const size_t size = (size_t)UINT32_MAX + 1;
239  unsigned char *data = malloc(1);
240  data[0] = '\0';
241  cbor_string_set_handle(item, data, 1);
242  // Pretend that we have a big item to avoid the huge malloc
243  item->metadata.string_metadata.length = size;
244  assert_size_equal(cbor_serialized_size(item), 1 + 8 + size);
245  cbor_decref(&item);
246#endif
247}
248
249static void test_serialize_indefinite_string(void **_CBOR_UNUSED(_state)) {
250  cbor_item_t *item = cbor_new_indefinite_string();
251  cbor_item_t *chunk = cbor_new_definite_string();
252
253  unsigned char *data = malloc(12);
254  strncpy((char *)data, "Hello world!", 12);
255  cbor_string_set_handle(chunk, data, 12);
256
257  assert_true(cbor_string_add_chunk(item, cbor_move(chunk)));
258  assert_size_equal(cbor_string_chunk_count(item), 1);
259
260  assert_size_equal(15, cbor_serialize(item, buffer, 512));
261  assert_memory_equal(
262      buffer,
263      ((unsigned char[]){0x7F, 0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77,
264                         0x6F, 0x72, 0x6C, 0x64, 0x21, 0xFF}),
265      15);
266  assert_size_equal(cbor_serialized_size(item), 15);
267  cbor_decref(&item);
268}
269
270static void test_serialize_string_no_space(void **_CBOR_UNUSED(_state)) {
271  cbor_item_t *item = cbor_new_definite_string();
272  unsigned char *data = malloc(12);
273  memset(data, 0, 12);
274  cbor_string_set_handle(item, data, 12);
275
276  assert_size_equal(cbor_serialize(item, buffer, 1), 0);
277
278  cbor_decref(&item);
279}
280
281static void test_serialize_indefinite_string_no_space(
282    void **_CBOR_UNUSED(_state)) {
283  cbor_item_t *item = cbor_new_indefinite_string();
284  cbor_item_t *chunk = cbor_new_definite_string();
285  unsigned char *data = malloc(256);
286  memset(data, 0, 256);
287  cbor_string_set_handle(chunk, data, 256);
288  assert_true(cbor_string_add_chunk(item, cbor_move(chunk)));
289
290  // Not enough space for the leading byte
291  assert_size_equal(cbor_serialize(item, buffer, 0), 0);
292
293  // Not enough space for the chunk
294  assert_size_equal(cbor_serialize(item, buffer, 30), 0);
295
296  // Not enough space for the indef break
297  assert_size_equal(
298      cbor_serialize(item, buffer, 1 + cbor_serialized_size(chunk)), 0);
299
300  cbor_decref(&item);
301}
302
303static void test_serialize_definite_array(void **_CBOR_UNUSED(_state)) {
304  cbor_item_t *item = cbor_new_definite_array(2);
305  cbor_item_t *one = cbor_build_uint8(1);
306  cbor_item_t *two = cbor_build_uint8(2);
307
308  assert_true(cbor_array_push(item, one));
309  assert_true(cbor_array_set(item, 1, two));
310  assert_true(cbor_array_replace(item, 0, one));
311
312  assert_size_equal(3, cbor_serialize(item, buffer, 512));
313  assert_memory_equal(buffer, ((unsigned char[]){0x82, 0x01, 0x02}), 3);
314  assert_size_equal(cbor_serialized_size(item), 3);
315  cbor_decref(&item);
316  cbor_decref(&one);
317  cbor_decref(&two);
318}
319
320static void test_serialize_array_no_space(void **_CBOR_UNUSED(_state)) {
321  cbor_item_t *item = cbor_new_indefinite_array();
322  cbor_item_t *one = cbor_build_uint8(1);
323  assert_true(cbor_array_push(item, one));
324  assert_size_equal(cbor_serialized_size(item), 3);
325
326  // Not enough space for the leading byte
327  assert_size_equal(0, cbor_serialize(item, buffer, 0));
328
329  // Not enough space for the item
330  assert_size_equal(0, cbor_serialize(item, buffer, 1));
331
332  // Not enough space for the indef break
333  assert_size_equal(0, cbor_serialize(item, buffer, 2));
334
335  cbor_decref(&item);
336  cbor_decref(&one);
337}
338
339static void test_serialize_indefinite_array(void **_CBOR_UNUSED(_state)) {
340  cbor_item_t *item = cbor_new_indefinite_array();
341  cbor_item_t *one = cbor_build_uint8(1);
342  cbor_item_t *two = cbor_build_uint8(2);
343
344  assert_true(cbor_array_push(item, one));
345  assert_true(cbor_array_push(item, two));
346
347  assert_size_equal(4, cbor_serialize(item, buffer, 512));
348  assert_memory_equal(buffer, ((unsigned char[]){0x9F, 0x01, 0x02, 0xFF}), 4);
349  assert_size_equal(cbor_serialized_size(item), 4);
350  cbor_decref(&item);
351  cbor_decref(&one);
352  cbor_decref(&two);
353}
354
355static void test_serialize_definite_map(void **_CBOR_UNUSED(_state)) {
356  cbor_item_t *item = cbor_new_definite_map(2);
357  cbor_item_t *one = cbor_build_uint8(1);
358  cbor_item_t *two = cbor_build_uint8(2);
359
360  assert_true(cbor_map_add(item, (struct cbor_pair){.key = one, .value = two}));
361  assert_true(cbor_map_add(item, (struct cbor_pair){.key = two, .value = one}));
362
363  assert_size_equal(5, cbor_serialize(item, buffer, 512));
364  assert_memory_equal(buffer, ((unsigned char[]){0xA2, 0x01, 0x02, 0x02, 0x01}),
365                      5);
366  assert_size_equal(cbor_serialized_size(item), 5);
367  cbor_decref(&item);
368  cbor_decref(&one);
369  cbor_decref(&two);
370}
371
372static void test_serialize_indefinite_map(void **_CBOR_UNUSED(_state)) {
373  cbor_item_t *item = cbor_new_indefinite_map();
374  cbor_item_t *one = cbor_build_uint8(1);
375  cbor_item_t *two = cbor_build_uint8(2);
376
377  assert_true(cbor_map_add(item, (struct cbor_pair){.key = one, .value = two}));
378  assert_true(cbor_map_add(item, (struct cbor_pair){.key = two, .value = one}));
379
380  assert_size_equal(6, cbor_serialize(item, buffer, 512));
381  assert_memory_equal(
382      buffer, ((unsigned char[]){0xBF, 0x01, 0x02, 0x02, 0x01, 0xFF}), 6);
383  assert_size_equal(cbor_serialized_size(item), 6);
384  cbor_decref(&item);
385  cbor_decref(&one);
386  cbor_decref(&two);
387}
388
389static void test_serialize_map_no_space(void **_CBOR_UNUSED(_state)) {
390  cbor_item_t *item = cbor_new_indefinite_map();
391  cbor_item_t *one = cbor_build_uint8(1);
392  cbor_item_t *two = cbor_build_uint8(2);
393  assert_true(cbor_map_add(item, (struct cbor_pair){.key = one, .value = two}));
394  assert_size_equal(cbor_serialized_size(item), 4);
395
396  // Not enough space for the leading byte
397  assert_size_equal(cbor_serialize(item, buffer, 0), 0);
398
399  // Not enough space for the key
400  assert_size_equal(cbor_serialize(item, buffer, 1), 0);
401
402  // Not enough space for the value
403  assert_size_equal(cbor_serialize(item, buffer, 2), 0);
404
405  // Not enough space for the indef break
406  assert_size_equal(cbor_serialize(item, buffer, 3), 0);
407
408  cbor_decref(&item);
409  cbor_decref(&one);
410  cbor_decref(&two);
411}
412
413static void test_serialize_tags(void **_CBOR_UNUSED(_state)) {
414  cbor_item_t *item = cbor_new_tag(21);
415  cbor_item_t *one = cbor_build_uint8(1);
416  cbor_tag_set_item(item, one);
417
418  assert_size_equal(2, cbor_serialize(item, buffer, 512));
419  assert_memory_equal(buffer, ((unsigned char[]){0xD5, 0x01}), 2);
420  assert_size_equal(cbor_serialized_size(item), 2);
421  cbor_decref(&item);
422  cbor_decref(&one);
423}
424
425static void test_serialize_tags_no_space(void **_CBOR_UNUSED(_state)) {
426  cbor_item_t *item = cbor_new_tag(21);
427  cbor_item_t *one = cbor_build_uint8(1);
428  cbor_tag_set_item(item, one);
429  assert_size_equal(cbor_serialized_size(item), 2);
430
431  // Not enough space for the leading byte
432  assert_size_equal(cbor_serialize(item, buffer, 0), 0);
433
434  // Not enough space for the item
435  assert_size_equal(cbor_serialize(item, buffer, 1), 0);
436
437  cbor_decref(&item);
438  cbor_decref(&one);
439}
440
441static void test_serialize_half(void **_CBOR_UNUSED(_state)) {
442  cbor_item_t *item = cbor_new_float2();
443  cbor_set_float2(item, NAN);
444
445  assert_size_equal(3, cbor_serialize(item, buffer, 512));
446  assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7E, 0x00}), 3);
447  assert_size_equal(cbor_serialized_size(item), 3);
448  cbor_decref(&item);
449}
450
451static void test_serialize_single(void **_CBOR_UNUSED(_state)) {
452  cbor_item_t *item = cbor_new_float4();
453  cbor_set_float4(item, 100000.0f);
454
455  assert_size_equal(5, cbor_serialize(item, buffer, 512));
456  assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x47, 0xC3, 0x50, 0x00}),
457                      5);
458  assert_size_equal(cbor_serialized_size(item), 5);
459  cbor_decref(&item);
460}
461
462static void test_serialize_double(void **_CBOR_UNUSED(_state)) {
463  cbor_item_t *item = cbor_new_float8();
464  cbor_set_float8(item, -4.1);
465
466  assert_size_equal(9, cbor_serialize(item, buffer, 512));
467  assert_memory_equal(
468      buffer,
469      ((unsigned char[]){0xFB, 0xC0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}),
470      9);
471  assert_size_equal(cbor_serialized_size(item), 9);
472  cbor_decref(&item);
473}
474
475static void test_serialize_ctrl(void **_CBOR_UNUSED(_state)) {
476  cbor_item_t *item = cbor_new_undef();
477
478  assert_size_equal(1, cbor_serialize(item, buffer, 512));
479  assert_memory_equal(buffer, ((unsigned char[]){0xF7}), 1);
480  assert_size_equal(cbor_serialized_size(item), 1);
481  cbor_decref(&item);
482}
483
484static void test_serialize_long_ctrl(void **_CBOR_UNUSED(_state)) {
485  cbor_item_t *item = cbor_new_ctrl();
486  cbor_set_ctrl(item, 254);
487
488  assert_size_equal(2, cbor_serialize(item, buffer, 512));
489  assert_memory_equal(buffer, ((unsigned char[]){0xF8, 0xFE}), 2);
490  assert_size_equal(cbor_serialized_size(item), 2);
491  cbor_decref(&item);
492}
493
494static void test_auto_serialize(void **_CBOR_UNUSED(_state)) {
495  cbor_item_t *item = cbor_new_definite_array(4);
496  for (size_t i = 0; i < 4; i++) {
497    assert_true(cbor_array_push(item, cbor_move(cbor_build_uint64(0))));
498  }
499
500  unsigned char *output;
501  size_t output_size;
502  assert_size_equal(cbor_serialize_alloc(item, &output, &output_size), 37);
503  assert_size_equal(output_size, 37);
504  assert_size_equal(cbor_serialized_size(item), 37);
505  assert_memory_equal(output, ((unsigned char[]){0x84, 0x1B}), 2);
506  cbor_decref(&item);
507  _cbor_free(output);
508}
509
510static void test_auto_serialize_no_size(void **_CBOR_UNUSED(_state)) {
511  cbor_item_t *item = cbor_build_uint8(1);
512
513  unsigned char *output;
514  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
515  assert_memory_equal(output, ((unsigned char[]){0x01}), 1);
516  assert_size_equal(cbor_serialized_size(item), 1);
517  cbor_decref(&item);
518  _cbor_free(output);
519}
520
521static void test_auto_serialize_too_large(void **_CBOR_UNUSED(_state)) {
522  cbor_item_t *item = cbor_new_indefinite_string();
523  cbor_item_t *chunk = cbor_new_definite_string();
524  assert_true(cbor_string_add_chunk(item, chunk));
525
526  // Pretend the chunk is huge
527  chunk->metadata.string_metadata.length = SIZE_MAX;
528  assert_true(SIZE_MAX + 2 == 1);
529  assert_size_equal(cbor_serialized_size(item), 0);
530  unsigned char *output;
531  size_t output_size;
532  assert_size_equal(cbor_serialize_alloc(item, &output, &output_size), 0);
533  assert_size_equal(output_size, 0);
534  assert_null(output);
535
536  chunk->metadata.string_metadata.length = 0;
537  cbor_decref(&chunk);
538  cbor_decref(&item);
539}
540
541static void test_auto_serialize_alloc_fail(void **_CBOR_UNUSED(_state)) {
542  cbor_item_t *item = cbor_build_uint8(42);
543
544  WITH_FAILING_MALLOC({
545    unsigned char *output;
546    size_t output_size;
547    assert_size_equal(cbor_serialize_alloc(item, &output, &output_size), 0);
548    assert_size_equal(output_size, 0);
549    assert_null(output);
550  });
551
552  cbor_decref(&item);
553}
554
555static void test_auto_serialize_zero_len_bytestring(
556    void **_CBOR_UNUSED(_state)) {
557  cbor_item_t *item = cbor_build_bytestring((cbor_data) "", 0);
558
559  unsigned char *output;
560  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
561  assert_memory_equal(output, ((unsigned char[]){0x40}), 1);
562  assert_size_equal(cbor_serialized_size(item), 1);
563  cbor_decref(&item);
564  _cbor_free(output);
565}
566
567static void test_auto_serialize_zero_len_string(void **_CBOR_UNUSED(_state)) {
568  cbor_item_t *item = cbor_build_string("");
569
570  unsigned char *output;
571  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
572  assert_memory_equal(output, ((unsigned char[]){0x60}), 1);
573  assert_size_equal(cbor_serialized_size(item), 1);
574  cbor_decref(&item);
575  _cbor_free(output);
576}
577
578static void test_auto_serialize_zero_len_bytestring_chunk(
579    void **_CBOR_UNUSED(_state)) {
580  cbor_item_t *item = cbor_new_indefinite_bytestring();
581
582  assert_true(cbor_bytestring_add_chunk(
583      item, cbor_move(cbor_build_bytestring((cbor_data) "", 0))));
584
585  unsigned char *output;
586  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 3);
587  assert_memory_equal(output, ((unsigned char[]){0x5f, 0x40, 0xff}), 3);
588  assert_size_equal(cbor_serialized_size(item), 3);
589  cbor_decref(&item);
590  _cbor_free(output);
591}
592
593static void test_auto_serialize_zero_len_string_chunk(
594    void **_CBOR_UNUSED(_state)) {
595  cbor_item_t *item = cbor_new_indefinite_string();
596
597  assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string(""))));
598
599  unsigned char *output;
600  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 3);
601  assert_memory_equal(output, ((unsigned char[]){0x7f, 0x60, 0xff}), 3);
602  assert_size_equal(cbor_serialized_size(item), 3);
603  cbor_decref(&item);
604  _cbor_free(output);
605}
606
607static void test_auto_serialize_zero_len_array(void **_CBOR_UNUSED(_state)) {
608  cbor_item_t *item = cbor_new_definite_array(0);
609
610  unsigned char *output;
611  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
612  assert_memory_equal(output, ((unsigned char[]){0x80}), 1);
613  assert_size_equal(cbor_serialized_size(item), 1);
614  cbor_decref(&item);
615  _cbor_free(output);
616}
617
618static void test_auto_serialize_zero_len_indef_array(
619    void **_CBOR_UNUSED(_state)) {
620  cbor_item_t *item = cbor_new_indefinite_array();
621
622  unsigned char *output;
623  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 2);
624  assert_memory_equal(output, ((unsigned char[]){0x9f, 0xff}), 2);
625  assert_size_equal(cbor_serialized_size(item), 2);
626  cbor_decref(&item);
627  _cbor_free(output);
628}
629
630static void test_auto_serialize_zero_len_map(void **_CBOR_UNUSED(_state)) {
631  cbor_item_t *item = cbor_new_definite_map(0);
632
633  unsigned char *output;
634  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
635  assert_memory_equal(output, ((unsigned char[]){0xa0}), 1);
636  assert_size_equal(cbor_serialized_size(item), 1);
637  cbor_decref(&item);
638  _cbor_free(output);
639}
640
641static void test_auto_serialize_zero_len_indef_map(
642    void **_CBOR_UNUSED(_state)) {
643  cbor_item_t *item = cbor_new_indefinite_map();
644
645  unsigned char *output;
646  assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 2);
647  assert_memory_equal(output, ((unsigned char[]){0xbf, 0xff}), 2);
648  assert_size_equal(cbor_serialized_size(item), 2);
649  cbor_decref(&item);
650  _cbor_free(output);
651}
652
653int main(void) {
654  const struct CMUnitTest tests[] = {
655      cmocka_unit_test(test_serialize_uint8_embed),
656      cmocka_unit_test(test_serialize_uint8),
657      cmocka_unit_test(test_serialize_uint16),
658      cmocka_unit_test(test_serialize_uint32),
659      cmocka_unit_test(test_serialize_uint64),
660      cmocka_unit_test(test_serialize_negint8_embed),
661      cmocka_unit_test(test_serialize_negint8),
662      cmocka_unit_test(test_serialize_negint16),
663      cmocka_unit_test(test_serialize_negint32),
664      cmocka_unit_test(test_serialize_negint64),
665      cmocka_unit_test(test_serialize_definite_bytestring),
666      cmocka_unit_test(test_serialize_indefinite_bytestring),
667      cmocka_unit_test(test_serialize_bytestring_size_overflow),
668      cmocka_unit_test(test_serialize_bytestring_no_space),
669      cmocka_unit_test(test_serialize_indefinite_bytestring_no_space),
670      cmocka_unit_test(test_serialize_definite_string),
671      cmocka_unit_test(test_serialize_definite_string_4b_header),
672      cmocka_unit_test(test_serialize_definite_string_8b_header),
673      cmocka_unit_test(test_serialize_indefinite_string),
674      cmocka_unit_test(test_serialize_string_no_space),
675      cmocka_unit_test(test_serialize_indefinite_string_no_space),
676      cmocka_unit_test(test_serialize_definite_array),
677      cmocka_unit_test(test_serialize_indefinite_array),
678      cmocka_unit_test(test_serialize_array_no_space),
679      cmocka_unit_test(test_serialize_definite_map),
680      cmocka_unit_test(test_serialize_indefinite_map),
681      cmocka_unit_test(test_serialize_map_no_space),
682      cmocka_unit_test(test_serialize_tags),
683      cmocka_unit_test(test_serialize_tags_no_space),
684      cmocka_unit_test(test_serialize_half),
685      cmocka_unit_test(test_serialize_single),
686      cmocka_unit_test(test_serialize_double),
687      cmocka_unit_test(test_serialize_ctrl),
688      cmocka_unit_test(test_serialize_long_ctrl),
689      cmocka_unit_test(test_auto_serialize),
690      cmocka_unit_test(test_auto_serialize_no_size),
691      cmocka_unit_test(test_auto_serialize_too_large),
692      cmocka_unit_test(test_auto_serialize_alloc_fail),
693      cmocka_unit_test(test_auto_serialize_zero_len_bytestring),
694      cmocka_unit_test(test_auto_serialize_zero_len_string),
695      cmocka_unit_test(test_auto_serialize_zero_len_bytestring_chunk),
696      cmocka_unit_test(test_auto_serialize_zero_len_string_chunk),
697      cmocka_unit_test(test_auto_serialize_zero_len_array),
698      cmocka_unit_test(test_auto_serialize_zero_len_indef_array),
699      cmocka_unit_test(test_auto_serialize_zero_len_map),
700      cmocka_unit_test(test_auto_serialize_zero_len_indef_map),
701  };
702  return cmocka_run_group_tests(tests, NULL, NULL);
703}
704