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 <stdio.h> 9 #include <string.h> 10 11 #include "assertions.h" 12 #include "cbor.h" 13 14 void assert_describe_result(cbor_item_t *item, char *expected_result) { 15 #if CBOR_PRETTY_PRINTER 16 // We know the expected size based on `expected_result`, but read everything 17 // in order to get the full actual output in a useful error message. 18 const size_t buffer_size = 512; 19 FILE *outfile = tmpfile(); 20 cbor_describe(item, outfile); 21 rewind(outfile); 22 // Treat string as null-terminated since cmocka doesn't have asserts 23 // for explicit length strings. 24 char *output = malloc(buffer_size); 25 assert_non_null(output); 26 size_t output_size = fread(output, sizeof(char), buffer_size, outfile); 27 output[output_size] = '\0'; 28 assert_string_equal(output, expected_result); 29 assert_true(feof(outfile)); 30 free(output); 31 fclose(outfile); 32 #endif 33 } 34 35 static void test_uint(void **_CBOR_UNUSED(_state)) { 36 cbor_item_t *item = cbor_build_uint8(42); 37 assert_describe_result(item, "[CBOR_TYPE_UINT] Width: 1B, Value: 42\n"); 38 cbor_decref(&item); 39 } 40 41 static void test_negint(void **_CBOR_UNUSED(_state)) { 42 cbor_item_t *item = cbor_build_negint16(40); 43 assert_describe_result(item, 44 "[CBOR_TYPE_NEGINT] Width: 2B, Value: -40 - 1\n"); 45 cbor_decref(&item); 46 } 47 48 static void test_definite_bytestring(void **_CBOR_UNUSED(_state)) { 49 unsigned char data[] = {0x01, 0x02, 0x03}; 50 cbor_item_t *item = cbor_build_bytestring(data, 3); 51 assert_describe_result(item, 52 "[CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n" 53 " 010203\n"); 54 cbor_decref(&item); 55 } 56 57 static void test_indefinite_bytestring(void **_CBOR_UNUSED(_state)) { 58 unsigned char data[] = {0x01, 0x02, 0x03}; 59 cbor_item_t *item = cbor_new_indefinite_bytestring(); 60 assert_true(cbor_bytestring_add_chunk( 61 item, cbor_move(cbor_build_bytestring(data, 3)))); 62 assert_true(cbor_bytestring_add_chunk( 63 item, cbor_move(cbor_build_bytestring(data, 2)))); 64 assert_describe_result( 65 item, 66 "[CBOR_TYPE_BYTESTRING] Indefinite, Chunks: 2, Chunk data:\n" 67 " [CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n" 68 " 010203\n" 69 " [CBOR_TYPE_BYTESTRING] Definite, Length: 2B, Data:\n" 70 " 0102\n"); 71 cbor_decref(&item); 72 } 73 74 static void test_definite_string(void **_CBOR_UNUSED(_state)) { 75 char *string = "Hello!"; 76 cbor_item_t *item = cbor_build_string(string); 77 assert_describe_result( 78 item, 79 "[CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n" 80 " Hello!\n"); 81 cbor_decref(&item); 82 } 83 84 static void test_indefinite_string(void **_CBOR_UNUSED(_state)) { 85 char *string = "Hello!"; 86 cbor_item_t *item = cbor_new_indefinite_string(); 87 assert_true( 88 cbor_string_add_chunk(item, cbor_move(cbor_build_string(string)))); 89 assert_true( 90 cbor_string_add_chunk(item, cbor_move(cbor_build_string(string)))); 91 assert_describe_result( 92 item, 93 "[CBOR_TYPE_STRING] Indefinite, Chunks: 2, Chunk data:\n" 94 " [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n" 95 " Hello!\n" 96 " [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n" 97 " Hello!\n"); 98 cbor_decref(&item); 99 } 100 101 static void test_multibyte_string(void **_CBOR_UNUSED(_state)) { 102 // "Štěstíčko" in UTF-8 103 char *string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko"; 104 cbor_item_t *item = cbor_build_string(string); 105 assert_describe_result( 106 item, 107 "[CBOR_TYPE_STRING] Definite, Length: 13B, Codepoints: 9, Data:\n" 108 " \xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko\n"); 109 cbor_decref(&item); 110 } 111 112 static void test_definite_array(void **_CBOR_UNUSED(_state)) { 113 cbor_item_t *item = cbor_new_definite_array(2); 114 assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1)))); 115 assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2)))); 116 assert_describe_result(item, 117 "[CBOR_TYPE_ARRAY] Definite, Size: 2, Contents:\n" 118 " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n" 119 " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n"); 120 cbor_decref(&item); 121 } 122 123 static void test_indefinite_array(void **_CBOR_UNUSED(_state)) { 124 cbor_item_t *item = cbor_new_indefinite_array(); 125 assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1)))); 126 assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2)))); 127 assert_describe_result(item, 128 "[CBOR_TYPE_ARRAY] Indefinite, Size: 2, Contents:\n" 129 " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n" 130 " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n"); 131 cbor_decref(&item); 132 } 133 134 static void test_definite_map(void **_CBOR_UNUSED(_state)) { 135 cbor_item_t *item = cbor_new_definite_map(1); 136 assert_true(cbor_map_add( 137 item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)), 138 .value = cbor_move(cbor_build_uint8(2))})); 139 assert_describe_result(item, 140 "[CBOR_TYPE_MAP] Definite, Size: 1, Contents:\n" 141 " Map entry 0\n" 142 " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n" 143 " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n"); 144 cbor_decref(&item); 145 } 146 147 static void test_indefinite_map(void **_CBOR_UNUSED(_state)) { 148 cbor_item_t *item = cbor_new_indefinite_map(); 149 assert_true(cbor_map_add( 150 item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)), 151 .value = cbor_move(cbor_build_uint8(2))})); 152 assert_describe_result(item, 153 "[CBOR_TYPE_MAP] Indefinite, Size: 1, Contents:\n" 154 " Map entry 0\n" 155 " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n" 156 " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n"); 157 cbor_decref(&item); 158 } 159 160 static void test_tag(void **_CBOR_UNUSED(_state)) { 161 cbor_item_t *item = cbor_build_tag(42, cbor_move(cbor_build_uint8(1))); 162 assert_describe_result(item, 163 "[CBOR_TYPE_TAG] Value: 42\n" 164 " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"); 165 cbor_decref(&item); 166 } 167 168 static void test_floats(void **_CBOR_UNUSED(_state)) { 169 cbor_item_t *item = cbor_new_indefinite_array(); 170 assert_true(cbor_array_push(item, cbor_move(cbor_build_bool(true)))); 171 assert_true( 172 cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_UNDEF)))); 173 assert_true( 174 cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_NULL)))); 175 assert_true(cbor_array_push(item, cbor_move(cbor_build_ctrl(24)))); 176 assert_true(cbor_array_push(item, cbor_move(cbor_build_float4(3.14f)))); 177 assert_describe_result( 178 item, 179 "[CBOR_TYPE_ARRAY] Indefinite, Size: 5, Contents:\n" 180 " [CBOR_TYPE_FLOAT_CTRL] Bool: true\n" 181 " [CBOR_TYPE_FLOAT_CTRL] Undefined\n" 182 " [CBOR_TYPE_FLOAT_CTRL] Null\n" 183 " [CBOR_TYPE_FLOAT_CTRL] Simple value: 24\n" 184 " [CBOR_TYPE_FLOAT_CTRL] Width: 4B, Value: 3.140000\n"); 185 cbor_decref(&item); 186 } 187 188 int main(void) { 189 const struct CMUnitTest tests[] = { 190 cmocka_unit_test(test_uint), 191 cmocka_unit_test(test_negint), 192 cmocka_unit_test(test_definite_bytestring), 193 cmocka_unit_test(test_indefinite_bytestring), 194 cmocka_unit_test(test_definite_string), 195 cmocka_unit_test(test_indefinite_string), 196 cmocka_unit_test(test_multibyte_string), 197 cmocka_unit_test(test_definite_array), 198 cmocka_unit_test(test_indefinite_array), 199 cmocka_unit_test(test_definite_map), 200 cmocka_unit_test(test_indefinite_map), 201 cmocka_unit_test(test_tag), 202 cmocka_unit_test(test_floats), 203 }; 204 return cmocka_run_group_tests(tests, NULL, NULL); 205 } 206