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 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 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 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 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.*/ 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 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 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 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 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 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 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