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