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 "assertions.h"
9 #include "cbor.h"
10 #include "test_allocator.h"
11
12 cbor_item_t *tag;
13 struct cbor_load_result res;
14
15 unsigned char embedded_tag_data[] = {0xC0, 0x00};
16
test_refcounting(void ** _CBOR_UNUSED (_state))17 static void test_refcounting(void **_CBOR_UNUSED(_state)) {
18 tag = cbor_load(embedded_tag_data, 2, &res);
19 assert_true(cbor_refcount(tag) == 1);
20 cbor_item_t *item = cbor_tag_item(tag);
21 assert_true(cbor_refcount(item) == 2);
22 cbor_decref(&tag);
23 assert_null(tag);
24 assert_true(cbor_refcount(item) == 1);
25 cbor_decref(&item);
26 assert_null(item);
27 }
28
29 /* Tag 0 + uint 0 */
test_embedded_tag(void ** _CBOR_UNUSED (_state))30 static void test_embedded_tag(void **_CBOR_UNUSED(_state)) {
31 tag = cbor_load(embedded_tag_data, 2, &res);
32 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
33 assert_true(cbor_tag_value(tag) == 0);
34 assert_uint8(cbor_move(cbor_tag_item(tag)), 0);
35 cbor_decref(&tag);
36 assert_null(tag);
37 }
38
39 unsigned char int8_tag_data[] = {0xD8, 0xFF, 0x01};
40
41 /* Tag 255 + uint 1 */
test_int8_tag(void ** _CBOR_UNUSED (_state))42 static void test_int8_tag(void **_CBOR_UNUSED(_state)) {
43 tag = cbor_load(int8_tag_data, 3, &res);
44 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
45 assert_true(cbor_tag_value(tag) == 255);
46 assert_uint8(cbor_move(cbor_tag_item(tag)), 1);
47 cbor_decref(&tag);
48 assert_null(tag);
49 }
50
51 unsigned char int16_tag_data[] = {0xD9, 0xFF, 0x00, 0x02};
52
53 /* Tag 255 << 8 + uint 2 */
test_int16_tag(void ** _CBOR_UNUSED (_state))54 static void test_int16_tag(void **_CBOR_UNUSED(_state)) {
55 tag = cbor_load(int16_tag_data, 4, &res);
56 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
57 assert_true(cbor_tag_value(tag) == 255 << 8);
58 assert_uint8(cbor_move(cbor_tag_item(tag)), 2);
59 cbor_decref(&tag);
60 assert_null(tag);
61 }
62
63 unsigned char int32_tag_data[] = {0xDA, 0xFF, 0x00, 0x00, 0x00, 0x03};
64
65 /* uint 3 */
test_int32_tag(void ** _CBOR_UNUSED (_state))66 static void test_int32_tag(void **_CBOR_UNUSED(_state)) {
67 tag = cbor_load(int32_tag_data, 6, &res);
68 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
69 assert_true(cbor_tag_value(tag) == 4278190080ULL);
70 assert_uint8(cbor_move(cbor_tag_item(tag)), 3);
71 cbor_decref(&tag);
72 assert_null(tag);
73 }
74
75 unsigned char int64_tag_data[] = {0xDB, 0xFF, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x04};
77
78 /* uint 4 */
test_int64_tag(void ** _CBOR_UNUSED (_state))79 static void test_int64_tag(void **_CBOR_UNUSED(_state)) {
80 tag = cbor_load(int64_tag_data, 10, &res);
81 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
82 assert_true(cbor_tag_value(tag) == 18374686479671623680ULL);
83 assert_uint8(cbor_move(cbor_tag_item(tag)), 4);
84 cbor_decref(&tag);
85 assert_null(tag);
86 }
87
88 unsigned char nested_tag_data[] = {0xC0, 0xC1, 0x18, 0x2A};
89
90 /* Tag 0, tag 1 + uint 0 */
test_nested_tag(void ** _CBOR_UNUSED (_state))91 static void test_nested_tag(void **_CBOR_UNUSED(_state)) {
92 tag = cbor_load(nested_tag_data, 4, &res);
93 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
94 assert_true(cbor_tag_value(tag) == 0);
95 cbor_item_t *nested_tag = cbor_tag_item(tag);
96 assert_true(cbor_typeof(nested_tag) == CBOR_TYPE_TAG);
97 assert_true(cbor_tag_value(nested_tag) == 1);
98 assert_uint8(cbor_move(cbor_tag_item(nested_tag)), 42);
99 cbor_decref(&tag);
100 assert_null(tag);
101 cbor_decref(&nested_tag);
102 assert_null(nested_tag);
103 }
104
test_all_tag_values_supported(void ** _CBOR_UNUSED (_state))105 static void test_all_tag_values_supported(void **_CBOR_UNUSED(_state)) {
106 /* Test all items in the protected range of
107 * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml */
108 for (int64_t tag_value = 0; tag_value <= 32767; tag_value++) {
109 cbor_item_t *tag_item =
110 cbor_build_tag(tag_value, cbor_move(cbor_build_uint8(42)));
111 unsigned char *serialized_tag;
112 size_t serialized_tag_size =
113 cbor_serialize_alloc(tag_item, &serialized_tag, NULL);
114 assert_true(serialized_tag_size > 0);
115 tag = cbor_load(serialized_tag, serialized_tag_size, &res);
116 assert_true(res.read == serialized_tag_size);
117 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
118 assert_true(cbor_tag_value(tag) == tag_value);
119 cbor_decref(&tag);
120 assert_null(tag);
121 cbor_decref(&tag_item);
122 assert_null(tag_item);
123 free(serialized_tag);
124 }
125 }
126
test_build_tag(void ** _CBOR_UNUSED (_state))127 static void test_build_tag(void **_CBOR_UNUSED(_state)) {
128 tag = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
129
130 assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
131 assert_size_equal(cbor_tag_value(tag), 1);
132 assert_uint8(cbor_move(cbor_tag_item(tag)), 42);
133
134 cbor_decref(&tag);
135 }
136
test_build_tag_failure(void ** _CBOR_UNUSED (_state))137 static void test_build_tag_failure(void **_CBOR_UNUSED(_state)) {
138 cbor_item_t *tagged_item = cbor_build_uint8(42);
139
140 WITH_FAILING_MALLOC({ assert_null(cbor_build_tag(1, tagged_item)); });
141 assert_size_equal(cbor_refcount(tagged_item), 1);
142
143 cbor_decref(&tagged_item);
144 }
145
test_tag_creation(void ** _CBOR_UNUSED (_state))146 static void test_tag_creation(void **_CBOR_UNUSED(_state)) {
147 WITH_FAILING_MALLOC({ assert_null(cbor_new_tag(42)); });
148 }
149
main(void)150 int main(void) {
151 const struct CMUnitTest tests[] = {
152 cmocka_unit_test(test_refcounting),
153 cmocka_unit_test(test_embedded_tag),
154 cmocka_unit_test(test_int8_tag),
155 cmocka_unit_test(test_int16_tag),
156 cmocka_unit_test(test_int32_tag),
157 cmocka_unit_test(test_int64_tag),
158 cmocka_unit_test(test_nested_tag),
159 cmocka_unit_test(test_all_tag_values_supported),
160 cmocka_unit_test(test_build_tag),
161 cmocka_unit_test(test_build_tag_failure),
162 cmocka_unit_test(test_tag_creation),
163 };
164 return cmocka_run_group_tests(tests, NULL, NULL);
165 }
166