1208625Sjkim/*
2208625Sjkim * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
3208625Sjkim *
4208625Sjkim * libcbor is free software; you can redistribute it and/or modify
5208625Sjkim * it under the terms of the MIT license. See LICENSE for details.
6208625Sjkim */
7208625Sjkim
8208625Sjkim#include <stdio.h>
9208625Sjkim#include <string.h>
10208625Sjkim
11208625Sjkim#include "assertions.h"
12208625Sjkim#include "cbor.h"
13208625Sjkim
14208625Sjkimvoid assert_describe_result(cbor_item_t *item, char *expected_result) {
15208625Sjkim#if CBOR_PRETTY_PRINTER
16208625Sjkim  // We know the expected size based on `expected_result`, but read everything
17208625Sjkim  // in order to get the full actual output in a useful error message.
18208625Sjkim  const size_t buffer_size = 512;
19208625Sjkim  FILE *outfile = tmpfile();
20208625Sjkim  cbor_describe(item, outfile);
21208625Sjkim  rewind(outfile);
22208625Sjkim  // Treat string as null-terminated since cmocka doesn't have asserts
23208625Sjkim  // for explicit length strings.
24208625Sjkim  char *output = malloc(buffer_size);
25208625Sjkim  assert_non_null(output);
26208625Sjkim  size_t output_size = fread(output, sizeof(char), buffer_size, outfile);
27208625Sjkim  output[output_size] = '\0';
28208625Sjkim  assert_string_equal(output, expected_result);
29208625Sjkim  assert_true(feof(outfile));
30208625Sjkim  free(output);
31208625Sjkim  fclose(outfile);
32208625Sjkim#endif
33208625Sjkim}
34208625Sjkim
35208625Sjkimstatic void test_uint(void **_CBOR_UNUSED(_state)) {
36208625Sjkim  cbor_item_t *item = cbor_build_uint8(42);
37208625Sjkim  assert_describe_result(item, "[CBOR_TYPE_UINT] Width: 1B, Value: 42\n");
38208625Sjkim  cbor_decref(&item);
39208625Sjkim}
40208625Sjkim
41208625Sjkimstatic void test_negint(void **_CBOR_UNUSED(_state)) {
42208625Sjkim  cbor_item_t *item = cbor_build_negint16(40);
43208625Sjkim  assert_describe_result(item,
44208625Sjkim                         "[CBOR_TYPE_NEGINT] Width: 2B, Value: -40 - 1\n");
45208625Sjkim  cbor_decref(&item);
46208625Sjkim}
47208625Sjkim
48208625Sjkimstatic void test_definite_bytestring(void **_CBOR_UNUSED(_state)) {
49208625Sjkim  unsigned char data[] = {0x01, 0x02, 0x03};
50208625Sjkim  cbor_item_t *item = cbor_build_bytestring(data, 3);
51208625Sjkim  assert_describe_result(item,
52208625Sjkim                         "[CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
53208625Sjkim                         "    010203\n");
54208625Sjkim  cbor_decref(&item);
55208625Sjkim}
56208625Sjkim
57208625Sjkimstatic void test_indefinite_bytestring(void **_CBOR_UNUSED(_state)) {
58208625Sjkim  unsigned char data[] = {0x01, 0x02, 0x03};
59208625Sjkim  cbor_item_t *item = cbor_new_indefinite_bytestring();
60208625Sjkim  assert_true(cbor_bytestring_add_chunk(
61208625Sjkim      item, cbor_move(cbor_build_bytestring(data, 3))));
62208625Sjkim  assert_true(cbor_bytestring_add_chunk(
63208625Sjkim      item, cbor_move(cbor_build_bytestring(data, 2))));
64208625Sjkim  assert_describe_result(
65208625Sjkim      item,
66208625Sjkim      "[CBOR_TYPE_BYTESTRING] Indefinite, Chunks: 2, Chunk data:\n"
67208625Sjkim      "    [CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
68208625Sjkim      "        010203\n"
69208625Sjkim      "    [CBOR_TYPE_BYTESTRING] Definite, Length: 2B, Data:\n"
70208625Sjkim      "        0102\n");
71208625Sjkim  cbor_decref(&item);
72208625Sjkim}
73208625Sjkim
74208625Sjkimstatic void test_definite_string(void **_CBOR_UNUSED(_state)) {
75208625Sjkim  char *string = "Hello!";
76208625Sjkim  cbor_item_t *item = cbor_build_string(string);
77208625Sjkim  assert_describe_result(
78208625Sjkim      item,
79208625Sjkim      "[CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
80208625Sjkim      "    Hello!\n");
81208625Sjkim  cbor_decref(&item);
82208625Sjkim}
83208625Sjkim
84208625Sjkimstatic void test_indefinite_string(void **_CBOR_UNUSED(_state)) {
85208625Sjkim  char *string = "Hello!";
86208625Sjkim  cbor_item_t *item = cbor_new_indefinite_string();
87208625Sjkim  assert_true(
88208625Sjkim      cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
89208625Sjkim  assert_true(
90208625Sjkim      cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
91208625Sjkim  assert_describe_result(
92208625Sjkim      item,
93208625Sjkim      "[CBOR_TYPE_STRING] Indefinite, Chunks: 2, Chunk data:\n"
94208625Sjkim      "    [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
95208625Sjkim      "        Hello!\n"
96208625Sjkim      "    [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
97208625Sjkim      "        Hello!\n");
98208625Sjkim  cbor_decref(&item);
99208625Sjkim}
100208625Sjkim
101208625Sjkimstatic void test_multibyte_string(void **_CBOR_UNUSED(_state)) {
102208625Sjkim  // "��t��st����ko" in UTF-8
103208625Sjkim  char *string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko";
104208625Sjkim  cbor_item_t *item = cbor_build_string(string);
105208625Sjkim  assert_describe_result(
106208625Sjkim      item,
107208625Sjkim      "[CBOR_TYPE_STRING] Definite, Length: 13B, Codepoints: 9, Data:\n"
108208625Sjkim      "    \xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko\n");
109208625Sjkim  cbor_decref(&item);
110208625Sjkim}
111208625Sjkim
112208625Sjkimstatic void test_definite_array(void **_CBOR_UNUSED(_state)) {
113208625Sjkim  cbor_item_t *item = cbor_new_definite_array(2);
114208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
115208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
116208625Sjkim  assert_describe_result(item,
117208625Sjkim                         "[CBOR_TYPE_ARRAY] Definite, Size: 2, Contents:\n"
118209746Sjkim                         "    [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
119209746Sjkim                         "    [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
120208625Sjkim  cbor_decref(&item);
121208625Sjkim}
122208625Sjkim
123208625Sjkimstatic void test_indefinite_array(void **_CBOR_UNUSED(_state)) {
124208625Sjkim  cbor_item_t *item = cbor_new_indefinite_array();
125208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
126208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
127208625Sjkim  assert_describe_result(item,
128208625Sjkim                         "[CBOR_TYPE_ARRAY] Indefinite, Size: 2, Contents:\n"
129208625Sjkim                         "    [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
130208625Sjkim                         "    [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
131208625Sjkim  cbor_decref(&item);
132208625Sjkim}
133208625Sjkim
134209734Sjkimstatic void test_definite_map(void **_CBOR_UNUSED(_state)) {
135209734Sjkim  cbor_item_t *item = cbor_new_definite_map(1);
136209734Sjkim  assert_true(cbor_map_add(
137208625Sjkim      item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
138208625Sjkim                               .value = cbor_move(cbor_build_uint8(2))}));
139208625Sjkim  assert_describe_result(item,
140208625Sjkim                         "[CBOR_TYPE_MAP] Definite, Size: 1, Contents:\n"
141208625Sjkim                         "    Map entry 0\n"
142208625Sjkim                         "        [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
143208625Sjkim                         "        [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
144208625Sjkim  cbor_decref(&item);
145208625Sjkim}
146208625Sjkim
147208625Sjkimstatic void test_indefinite_map(void **_CBOR_UNUSED(_state)) {
148208625Sjkim  cbor_item_t *item = cbor_new_indefinite_map();
149208625Sjkim  assert_true(cbor_map_add(
150208625Sjkim      item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
151208625Sjkim                               .value = cbor_move(cbor_build_uint8(2))}));
152208625Sjkim  assert_describe_result(item,
153208625Sjkim                         "[CBOR_TYPE_MAP] Indefinite, Size: 1, Contents:\n"
154208625Sjkim                         "    Map entry 0\n"
155208625Sjkim                         "        [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
156208625Sjkim                         "        [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
157208625Sjkim  cbor_decref(&item);
158208625Sjkim}
159208625Sjkim
160208625Sjkimstatic void test_tag(void **_CBOR_UNUSED(_state)) {
161208625Sjkim  cbor_item_t *item = cbor_build_tag(42, cbor_move(cbor_build_uint8(1)));
162208625Sjkim  assert_describe_result(item,
163208625Sjkim                         "[CBOR_TYPE_TAG] Value: 42\n"
164208625Sjkim                         "    [CBOR_TYPE_UINT] Width: 1B, Value: 1\n");
165208625Sjkim  cbor_decref(&item);
166208625Sjkim}
167208625Sjkim
168208625Sjkimstatic void test_floats(void **_CBOR_UNUSED(_state)) {
169208625Sjkim  cbor_item_t *item = cbor_new_indefinite_array();
170208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_bool(true))));
171208625Sjkim  assert_true(
172208625Sjkim      cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_UNDEF))));
173208625Sjkim  assert_true(
174208625Sjkim      cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_NULL))));
175208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_ctrl(24))));
176208625Sjkim  assert_true(cbor_array_push(item, cbor_move(cbor_build_float4(3.14f))));
177208625Sjkim  assert_describe_result(
178208625Sjkim      item,
179208625Sjkim      "[CBOR_TYPE_ARRAY] Indefinite, Size: 5, Contents:\n"
180208625Sjkim      "    [CBOR_TYPE_FLOAT_CTRL] Bool: true\n"
181208625Sjkim      "    [CBOR_TYPE_FLOAT_CTRL] Undefined\n"
182208625Sjkim      "    [CBOR_TYPE_FLOAT_CTRL] Null\n"
183208625Sjkim      "    [CBOR_TYPE_FLOAT_CTRL] Simple value: 24\n"
184208625Sjkim      "    [CBOR_TYPE_FLOAT_CTRL] Width: 4B, Value: 3.140000\n");
185208625Sjkim  cbor_decref(&item);
186208625Sjkim}
187208625Sjkim
188208625Sjkimint main(void) {
189208625Sjkim  const struct CMUnitTest tests[] = {
190208625Sjkim      cmocka_unit_test(test_uint),
191208625Sjkim      cmocka_unit_test(test_negint),
192208625Sjkim      cmocka_unit_test(test_definite_bytestring),
193208625Sjkim      cmocka_unit_test(test_indefinite_bytestring),
194208625Sjkim      cmocka_unit_test(test_definite_string),
195208625Sjkim      cmocka_unit_test(test_indefinite_string),
196208625Sjkim      cmocka_unit_test(test_multibyte_string),
197208625Sjkim      cmocka_unit_test(test_definite_array),
198208625Sjkim      cmocka_unit_test(test_indefinite_array),
199208625Sjkim      cmocka_unit_test(test_definite_map),
200208625Sjkim      cmocka_unit_test(test_indefinite_map),
201208625Sjkim      cmocka_unit_test(test_tag),
202208625Sjkim      cmocka_unit_test(test_floats),
203208625Sjkim  };
204208625Sjkim  return cmocka_run_group_tests(tests, NULL, NULL);
205208625Sjkim}
206208625Sjkim