xref: /freebsd/contrib/libcbor/test/pretty_printer_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 #include <stdio.h>
9 #include <string.h>
10 
11 #include "assertions.h"
12 #include "cbor.h"
13 
14 void assert_describe_result(cbor_item_t *item, char *expected_result) {
15 #if CBOR_PRETTY_PRINTER
16   // We know the expected size based on `expected_result`, but read everything
17   // in order to get the full actual output in a useful error message.
18   const size_t buffer_size = 512;
19   FILE *outfile = tmpfile();
20   cbor_describe(item, outfile);
21   rewind(outfile);
22   // Treat string as null-terminated since cmocka doesn't have asserts
23   // for explicit length strings.
24   char *output = malloc(buffer_size);
25   assert_non_null(output);
26   size_t output_size = fread(output, sizeof(char), buffer_size, outfile);
27   output[output_size] = '\0';
28   assert_string_equal(output, expected_result);
29   assert_true(feof(outfile));
30   free(output);
31   fclose(outfile);
32 #endif
33 }
34 
35 static void test_uint(void **_CBOR_UNUSED(_state)) {
36   cbor_item_t *item = cbor_build_uint8(42);
37   assert_describe_result(item, "[CBOR_TYPE_UINT] Width: 1B, Value: 42\n");
38   cbor_decref(&item);
39 }
40 
41 static void test_negint(void **_CBOR_UNUSED(_state)) {
42   cbor_item_t *item = cbor_build_negint16(40);
43   assert_describe_result(item,
44                          "[CBOR_TYPE_NEGINT] Width: 2B, Value: -40 - 1\n");
45   cbor_decref(&item);
46 }
47 
48 static void test_definite_bytestring(void **_CBOR_UNUSED(_state)) {
49   unsigned char data[] = {0x01, 0x02, 0x03};
50   cbor_item_t *item = cbor_build_bytestring(data, 3);
51   assert_describe_result(item,
52                          "[CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
53                          "    010203\n");
54   cbor_decref(&item);
55 }
56 
57 static void test_indefinite_bytestring(void **_CBOR_UNUSED(_state)) {
58   unsigned char data[] = {0x01, 0x02, 0x03};
59   cbor_item_t *item = cbor_new_indefinite_bytestring();
60   assert_true(cbor_bytestring_add_chunk(
61       item, cbor_move(cbor_build_bytestring(data, 3))));
62   assert_true(cbor_bytestring_add_chunk(
63       item, cbor_move(cbor_build_bytestring(data, 2))));
64   assert_describe_result(
65       item,
66       "[CBOR_TYPE_BYTESTRING] Indefinite, Chunks: 2, Chunk data:\n"
67       "    [CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
68       "        010203\n"
69       "    [CBOR_TYPE_BYTESTRING] Definite, Length: 2B, Data:\n"
70       "        0102\n");
71   cbor_decref(&item);
72 }
73 
74 static void test_definite_string(void **_CBOR_UNUSED(_state)) {
75   char *string = "Hello!";
76   cbor_item_t *item = cbor_build_string(string);
77   assert_describe_result(
78       item,
79       "[CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
80       "    Hello!\n");
81   cbor_decref(&item);
82 }
83 
84 static void test_indefinite_string(void **_CBOR_UNUSED(_state)) {
85   char *string = "Hello!";
86   cbor_item_t *item = cbor_new_indefinite_string();
87   assert_true(
88       cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
89   assert_true(
90       cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
91   assert_describe_result(
92       item,
93       "[CBOR_TYPE_STRING] Indefinite, Chunks: 2, Chunk data:\n"
94       "    [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
95       "        Hello!\n"
96       "    [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
97       "        Hello!\n");
98   cbor_decref(&item);
99 }
100 
101 static void test_multibyte_string(void **_CBOR_UNUSED(_state)) {
102   // "Štěstíčko" in UTF-8
103   char *string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko";
104   cbor_item_t *item = cbor_build_string(string);
105   assert_describe_result(
106       item,
107       "[CBOR_TYPE_STRING] Definite, Length: 13B, Codepoints: 9, Data:\n"
108       "    \xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko\n");
109   cbor_decref(&item);
110 }
111 
112 static void test_definite_array(void **_CBOR_UNUSED(_state)) {
113   cbor_item_t *item = cbor_new_definite_array(2);
114   assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
115   assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
116   assert_describe_result(item,
117                          "[CBOR_TYPE_ARRAY] Definite, Size: 2, Contents:\n"
118                          "    [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
119                          "    [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
120   cbor_decref(&item);
121 }
122 
123 static void test_indefinite_array(void **_CBOR_UNUSED(_state)) {
124   cbor_item_t *item = cbor_new_indefinite_array();
125   assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
126   assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
127   assert_describe_result(item,
128                          "[CBOR_TYPE_ARRAY] Indefinite, Size: 2, Contents:\n"
129                          "    [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
130                          "    [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
131   cbor_decref(&item);
132 }
133 
134 static void test_definite_map(void **_CBOR_UNUSED(_state)) {
135   cbor_item_t *item = cbor_new_definite_map(1);
136   assert_true(cbor_map_add(
137       item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
138                                .value = cbor_move(cbor_build_uint8(2))}));
139   assert_describe_result(item,
140                          "[CBOR_TYPE_MAP] Definite, Size: 1, Contents:\n"
141                          "    Map entry 0\n"
142                          "        [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
143                          "        [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
144   cbor_decref(&item);
145 }
146 
147 static void test_indefinite_map(void **_CBOR_UNUSED(_state)) {
148   cbor_item_t *item = cbor_new_indefinite_map();
149   assert_true(cbor_map_add(
150       item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
151                                .value = cbor_move(cbor_build_uint8(2))}));
152   assert_describe_result(item,
153                          "[CBOR_TYPE_MAP] Indefinite, Size: 1, Contents:\n"
154                          "    Map entry 0\n"
155                          "        [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
156                          "        [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
157   cbor_decref(&item);
158 }
159 
160 static void test_tag(void **_CBOR_UNUSED(_state)) {
161   cbor_item_t *item = cbor_build_tag(42, cbor_move(cbor_build_uint8(1)));
162   assert_describe_result(item,
163                          "[CBOR_TYPE_TAG] Value: 42\n"
164                          "    [CBOR_TYPE_UINT] Width: 1B, Value: 1\n");
165   cbor_decref(&item);
166 }
167 
168 static void test_floats(void **_CBOR_UNUSED(_state)) {
169   cbor_item_t *item = cbor_new_indefinite_array();
170   assert_true(cbor_array_push(item, cbor_move(cbor_build_bool(true))));
171   assert_true(
172       cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_UNDEF))));
173   assert_true(
174       cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_NULL))));
175   assert_true(cbor_array_push(item, cbor_move(cbor_build_ctrl(24))));
176   assert_true(cbor_array_push(item, cbor_move(cbor_build_float4(3.14f))));
177   assert_describe_result(
178       item,
179       "[CBOR_TYPE_ARRAY] Indefinite, Size: 5, Contents:\n"
180       "    [CBOR_TYPE_FLOAT_CTRL] Bool: true\n"
181       "    [CBOR_TYPE_FLOAT_CTRL] Undefined\n"
182       "    [CBOR_TYPE_FLOAT_CTRL] Null\n"
183       "    [CBOR_TYPE_FLOAT_CTRL] Simple value: 24\n"
184       "    [CBOR_TYPE_FLOAT_CTRL] Width: 4B, Value: 3.140000\n");
185   cbor_decref(&item);
186 }
187 
188 int main(void) {
189   const struct CMUnitTest tests[] = {
190       cmocka_unit_test(test_uint),
191       cmocka_unit_test(test_negint),
192       cmocka_unit_test(test_definite_bytestring),
193       cmocka_unit_test(test_indefinite_bytestring),
194       cmocka_unit_test(test_definite_string),
195       cmocka_unit_test(test_indefinite_string),
196       cmocka_unit_test(test_multibyte_string),
197       cmocka_unit_test(test_definite_array),
198       cmocka_unit_test(test_indefinite_array),
199       cmocka_unit_test(test_definite_map),
200       cmocka_unit_test(test_indefinite_map),
201       cmocka_unit_test(test_tag),
202       cmocka_unit_test(test_floats),
203   };
204   return cmocka_run_group_tests(tests, NULL, NULL);
205 }
206