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
assert_describe_result(cbor_item_t * item,char * expected_result)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
test_uint(void ** _CBOR_UNUSED (_state))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
test_negint(void ** _CBOR_UNUSED (_state))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
test_definite_bytestring(void ** _CBOR_UNUSED (_state))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
test_indefinite_bytestring(void ** _CBOR_UNUSED (_state))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
test_definite_string(void ** _CBOR_UNUSED (_state))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
test_indefinite_string(void ** _CBOR_UNUSED (_state))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
test_multibyte_string(void ** _CBOR_UNUSED (_state))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
test_definite_array(void ** _CBOR_UNUSED (_state))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
test_indefinite_array(void ** _CBOR_UNUSED (_state))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
test_definite_map(void ** _CBOR_UNUSED (_state))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
test_indefinite_map(void ** _CBOR_UNUSED (_state))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
test_tag(void ** _CBOR_UNUSED (_state))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
test_floats(void ** _CBOR_UNUSED (_state))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
main(void)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