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 <math.h>
9 #include "assertions.h"
10 #include "cbor.h"
11
12 unsigned char buffer[512];
13
test_bools(void ** _CBOR_UNUSED (_state))14 static void test_bools(void **_CBOR_UNUSED(_state)) {
15 assert_size_equal(1, cbor_encode_bool(false, buffer, 512));
16 assert_memory_equal(buffer, ((unsigned char[]){0xF4}), 1);
17 assert_size_equal(1, cbor_encode_bool(true, buffer, 512));
18 assert_memory_equal(buffer, ((unsigned char[]){0xF5}), 1);
19 }
20
test_null(void ** _CBOR_UNUSED (_state))21 static void test_null(void **_CBOR_UNUSED(_state)) {
22 assert_size_equal(1, cbor_encode_null(buffer, 512));
23 assert_memory_equal(buffer, ((unsigned char[]){0xF6}), 1);
24 }
25
test_undef(void ** _CBOR_UNUSED (_state))26 static void test_undef(void **_CBOR_UNUSED(_state)) {
27 assert_size_equal(1, cbor_encode_undef(buffer, 512));
28 assert_memory_equal(buffer, ((unsigned char[]){0xF7}), 1);
29 }
30
test_break(void ** _CBOR_UNUSED (_state))31 static void test_break(void **_CBOR_UNUSED(_state)) {
32 assert_size_equal(1, cbor_encode_break(buffer, 512));
33 assert_memory_equal(buffer, ((unsigned char[]){0xFF}), 1);
34 }
35
36 /* Check that encode(decode(buffer)) = buffer for a valid half-float in the
37 * buffer.*/
assert_half_float_codec_identity(void)38 static void assert_half_float_codec_identity(void) {
39 unsigned char secondary_buffer[3];
40 struct cbor_load_result res;
41 // Load and check data in buffer
42 cbor_item_t *half_float = cbor_load(buffer, 3, &res);
43 assert_size_equal(res.error.code, CBOR_ERR_NONE);
44 assert_true(cbor_isa_float_ctrl(half_float));
45 assert_true(cbor_is_float(half_float));
46 assert_size_equal(cbor_float_get_width(half_float), CBOR_FLOAT_16);
47 // Encode again and check equality
48 assert_size_equal(3, cbor_encode_half(cbor_float_get_float2(half_float),
49 secondary_buffer, 3));
50 assert_memory_equal(buffer, secondary_buffer, 3);
51 cbor_decref(&half_float);
52 }
53
test_half(void ** _CBOR_UNUSED (_state))54 static void test_half(void **_CBOR_UNUSED(_state)) {
55 assert_size_equal(3, cbor_encode_half(1.5f, buffer, 512));
56 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x3E, 0x00}), 3);
57 assert_half_float_codec_identity();
58
59 assert_size_equal(3, cbor_encode_half(-0.0f, buffer, 512));
60 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x80, 0x00}), 3);
61 assert_half_float_codec_identity();
62
63 assert_size_equal(3, cbor_encode_half(0.0f, buffer, 512));
64 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x00}), 3);
65 assert_half_float_codec_identity();
66
67 assert_size_equal(3, cbor_encode_half(65504.0f, buffer, 512));
68 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7B, 0xFF}), 3);
69 assert_half_float_codec_identity();
70
71 assert_size_equal(3, cbor_encode_half(0.00006103515625f, buffer, 512));
72 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x04, 0x00}), 3);
73 assert_half_float_codec_identity();
74
75 assert_size_equal(3, cbor_encode_half(-4.0f, buffer, 512));
76 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0xC4, 0x00}), 3);
77 assert_half_float_codec_identity();
78
79 /* Smallest representable value */
80 assert_size_equal(3, cbor_encode_half(5.960464477539063e-8f, buffer, 512));
81 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x01}), 3);
82 assert_half_float_codec_identity();
83
84 /* Smaller than the smallest, approximate magnitude representation */
85 assert_size_equal(3, cbor_encode_half(5.960464477539062e-8f, buffer, 512));
86 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x01}), 3);
87 assert_half_float_codec_identity();
88
89 assert_size_equal(3, cbor_encode_half(4.172325134277344e-7f, buffer, 512));
90 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x07}), 3);
91 assert_half_float_codec_identity();
92
93 assert_size_equal(3, cbor_encode_half(6.097555160522461e-5f, buffer, 512));
94 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x03, 0xff}), 3);
95 assert_half_float_codec_identity();
96
97 assert_size_equal(3, cbor_encode_half(6.100535392761231e-5f, buffer, 512));
98 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x04, 0x00}), 3);
99 assert_half_float_codec_identity();
100
101 /* Smaller than the smallest and even the magnitude cannot be represented,
102 round off to zero */
103 assert_size_equal(3, cbor_encode_half(1e-25f, buffer, 512));
104 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x00}), 3);
105 assert_half_float_codec_identity();
106
107 assert_size_equal(3, cbor_encode_half(1.1920928955078125e-7, buffer, 512));
108 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x02}), 3);
109 assert_half_float_codec_identity();
110
111 assert_size_equal(3, cbor_encode_half(-1.1920928955078124e-7, buffer, 512));
112 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x80, 0x02}), 3);
113 assert_half_float_codec_identity();
114
115 assert_size_equal(3, cbor_encode_half(INFINITY, buffer, 512));
116 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7C, 0x00}), 3);
117 assert_half_float_codec_identity();
118 }
119
test_half_special(void ** _CBOR_UNUSED (_state))120 static void test_half_special(void **_CBOR_UNUSED(_state)) {
121 assert_size_equal(3, cbor_encode_half(NAN, buffer, 512));
122 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7E, 0x00}), 3);
123 assert_half_float_codec_identity();
124
125 // We discard all information bits in half-float NaNs. This is
126 // not required for the core CBOR protocol (it is only a suggestion in
127 // Section 3.9).
128 // See https://github.com/PJK/libcbor/issues/215
129 assert_size_equal(3, cbor_encode_half(nanf("2"), buffer, 512));
130 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7E, 0x00}), 3);
131 assert_half_float_codec_identity();
132 }
133
test_half_infinity(void ** _CBOR_UNUSED (_state))134 static void test_half_infinity(void **_CBOR_UNUSED(_state)) {
135 assert_size_equal(3, cbor_encode_half(INFINITY, buffer, 512));
136 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7C, 0x00}), 3);
137 assert_half_float_codec_identity();
138
139 assert_size_equal(3, cbor_encode_half(-INFINITY, buffer, 512));
140 assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0xFC, 0x00}), 3);
141 assert_half_float_codec_identity();
142 }
143
test_float(void ** _CBOR_UNUSED (_state))144 static void test_float(void **_CBOR_UNUSED(_state)) {
145 assert_size_equal(5, cbor_encode_single(3.4028234663852886e+38, buffer, 512));
146 assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0x7F, 0xFF, 0xFF}),
147 5);
148
149 assert_size_equal(5, cbor_encode_single(NAN, buffer, 512));
150 assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0xC0, 0x00, 0x00}),
151 5);
152
153 #ifndef _WIN32
154 // TODO: https://github.com/PJK/libcbor/issues/271
155 assert_size_equal(5, cbor_encode_single(nanf("3"), buffer, 512));
156 assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0xC0, 0x00, 0x03}),
157 5);
158 #endif
159
160 assert_size_equal(5, cbor_encode_single(strtof("Inf", NULL), buffer, 512));
161 assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0x80, 0x00, 0x00}),
162 5);
163
164 assert_size_equal(5, cbor_encode_single(strtof("-Inf", NULL), buffer, 512));
165 assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0xFF, 0x80, 0x00, 0x00}),
166 5);
167 }
168
test_double(void ** _CBOR_UNUSED (_state))169 static void test_double(void **_CBOR_UNUSED(_state)) {
170 assert_size_equal(9, cbor_encode_double(1.0e+300, buffer, 512));
171 assert_memory_equal(
172 buffer,
173 ((unsigned char[]){0xFB, 0x7E, 0x37, 0xE4, 0x3C, 0x88, 0x00, 0x75, 0x9C}),
174 9);
175
176 assert_size_equal(9, cbor_encode_double(nan(""), buffer, 512));
177 assert_memory_equal(
178 buffer,
179 ((unsigned char[]){0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
180 9);
181
182 #ifndef _WIN32
183 // TODO: https://github.com/PJK/libcbor/issues/271
184 assert_size_equal(9, cbor_encode_double(nan("3"), buffer, 512));
185 assert_memory_equal(
186 buffer,
187 ((unsigned char[]){0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}),
188 9);
189 #endif
190
191 assert_size_equal(9, cbor_encode_double(strtod("Inf", NULL), buffer, 512));
192 assert_memory_equal(
193 buffer,
194 ((unsigned char[]){0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
195 9);
196
197 assert_size_equal(9, cbor_encode_double(strtod("-Inf", NULL), buffer, 512));
198 assert_memory_equal(
199 buffer,
200 ((unsigned char[]){0xFB, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
201 9);
202 }
203
main(void)204 int main(void) {
205 const struct CMUnitTest tests[] = {
206 cmocka_unit_test(test_bools), cmocka_unit_test(test_null),
207 cmocka_unit_test(test_undef), cmocka_unit_test(test_break),
208 cmocka_unit_test(test_half), cmocka_unit_test(test_float),
209 cmocka_unit_test(test_double), cmocka_unit_test(test_half_special),
210 cmocka_unit_test(test_half_infinity),
211 };
212 return cmocka_run_group_tests(tests, NULL, NULL);
213 }
214