xref: /freebsd/contrib/libcbor/test/cbor_serialize_test.c (revision abd872540f24cfc7dbd1ea29b6918c7082a22108)
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 
25 unsigned char buffer[512];
26 
27 static 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 
36 static 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 
45 static 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 
54 static 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 
64 static 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 
76 static 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 
86 static 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 
96 static 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 
106 static 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 
117 static 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 
130 static 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 
142 static 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 
161 static 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 
175 static 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 
185 static 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 
206 static 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 
221 static 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 
234 static 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 
249 static 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 
270 static 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 
281 static 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 
303 static 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 
320 static 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 
339 static 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 
355 static 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 
372 static 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 
389 static 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 
413 static 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 
425 static 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 
441 static 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 
451 static 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 
462 static 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 
475 static 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 
484 static 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 
494 static 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 
510 static 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 
521 static 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 
541 static 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 
555 static 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 
567 static 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 
578 static 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 
593 static 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 
607 static 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 
618 static 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 
630 static 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 
641 static 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 
653 int 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