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 <setjmp.h> 9 #include <stdarg.h> 10 #include <stddef.h> 11 #include <stdint.h> 12 #include <string.h> 13 14 #include <cmocka.h> 15 16 #include "assertions.h" 17 #include "cbor.h" 18 #include "test_allocator.h" 19 20 cbor_item_t *map; 21 struct cbor_load_result res; 22 23 unsigned char empty_map[] = {0xA0}; 24 25 static void test_empty_map(void **_CBOR_UNUSED(_state)) { 26 map = cbor_load(empty_map, 1, &res); 27 assert_non_null(map); 28 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 29 assert_true(cbor_isa_map(map)); 30 assert_true(cbor_map_size(map) == 0); 31 assert_true(res.read == 1); 32 assert_size_equal(cbor_map_allocated(map), 0); 33 cbor_decref(&map); 34 assert_null(map); 35 } 36 37 unsigned char simple_map[] = {0xA2, 0x01, 0x02, 0x03, 0x04}; 38 39 /* {1: 2, 3: 4} */ 40 static void test_simple_map(void **_CBOR_UNUSED(_state)) { 41 map = cbor_load(simple_map, 5, &res); 42 assert_non_null(map); 43 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 44 assert_true(cbor_isa_map(map)); 45 assert_true(cbor_map_is_definite(map)); 46 assert_true(cbor_map_size(map) == 2); 47 assert_true(res.read == 5); 48 struct cbor_pair *handle = cbor_map_handle(map); 49 assert_uint8(handle[0].key, 1); 50 assert_uint8(handle[0].value, 2); 51 assert_uint8(handle[1].key, 3); 52 assert_uint8(handle[1].value, 4); 53 cbor_decref(&map); 54 assert_null(map); 55 } 56 57 unsigned char simple_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF}; 58 59 /* {_ 1: 2, 3: 4} */ 60 static void test_indef_simple_map(void **_CBOR_UNUSED(_state)) { 61 map = cbor_load(simple_indef_map, 6, &res); 62 assert_non_null(map); 63 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 64 assert_true(cbor_isa_map(map)); 65 assert_true(cbor_map_is_indefinite(map)); 66 assert_true(cbor_map_size(map) == 2); 67 assert_true(res.read == 6); 68 struct cbor_pair *handle = cbor_map_handle(map); 69 assert_uint8(handle[0].key, 1); 70 assert_uint8(handle[0].value, 2); 71 assert_uint8(handle[1].key, 3); 72 assert_uint8(handle[1].value, 4); 73 cbor_decref(&map); 74 assert_null(map); 75 } 76 77 //{ 78 // "glossary": { 79 // "title": "example glossary" 80 // } 81 //} 82 unsigned char def_nested_map[] = { 83 0xA1, 0x68, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79, 0xA1, 0x65, 84 0x74, 0x69, 0x74, 0x6C, 0x65, 0x70, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 85 0x65, 0x20, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79}; 86 87 static void test_def_nested_map(void **_CBOR_UNUSED(_state)) { 88 map = cbor_load(def_nested_map, 34, &res); 89 assert_non_null(map); 90 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 91 assert_true(cbor_isa_map(map)); 92 assert_true(cbor_map_is_definite(map)); 93 assert_true(cbor_map_size(map) == 1); 94 assert_true(res.read == 34); 95 struct cbor_pair *handle = cbor_map_handle(map); 96 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING); 97 assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_MAP); 98 struct cbor_pair *inner_handle = cbor_map_handle(handle[0].value); 99 assert_true(cbor_typeof(inner_handle[0].key) == CBOR_TYPE_STRING); 100 assert_true(cbor_typeof(inner_handle[0].value) == CBOR_TYPE_STRING); 101 assert_memory_equal(cbor_string_handle(inner_handle[0].value), 102 "example glossary", strlen("example glossary")); 103 cbor_decref(&map); 104 assert_null(map); 105 } 106 107 unsigned char streamed_key_map[] = {0xA1, 0x7F, 0x61, 0x61, 108 0x61, 0x62, 0xFF, 0xA0}; 109 110 /* '{ (_"a" "b"): {}}' */ 111 static void test_streamed_key_map(void **_CBOR_UNUSED(_state)) { 112 map = cbor_load(streamed_key_map, 8, &res); 113 assert_non_null(map); 114 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 115 assert_true(cbor_isa_map(map)); 116 assert_true(cbor_map_is_definite(map)); 117 assert_true(cbor_map_size(map) == 1); 118 assert_true(res.read == 8); 119 struct cbor_pair *handle = cbor_map_handle(map); 120 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING); 121 assert_true(cbor_string_is_indefinite(handle[0].key)); 122 assert_size_equal(cbor_string_chunk_count(handle[0].key), 2); 123 assert_true(cbor_isa_map(handle[0].value)); 124 assert_size_equal(cbor_map_size(handle[0].value), 0); 125 cbor_decref(&map); 126 assert_null(map); 127 } 128 129 unsigned char streamed_kv_map[] = {0xA1, 0x7F, 0x61, 0x61, 0x61, 0x62, 0xFF, 130 0x7F, 0x61, 0x63, 0x61, 0x64, 0xFF}; 131 132 /* '{ (_"a" "b"): (_"c", "d")}' */ 133 static void test_streamed_kv_map(void **_CBOR_UNUSED(_state)) { 134 map = cbor_load(streamed_kv_map, 13, &res); 135 assert_non_null(map); 136 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 137 assert_true(cbor_isa_map(map)); 138 assert_true(cbor_map_is_definite(map)); 139 assert_size_equal(cbor_map_size(map), 1); 140 assert_size_equal(res.read, 13); 141 struct cbor_pair *handle = cbor_map_handle(map); 142 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING); 143 assert_true(cbor_string_is_indefinite(handle[0].key)); 144 assert_size_equal(cbor_string_chunk_count(handle[0].key), 2); 145 assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING); 146 assert_true(cbor_string_is_indefinite(handle[0].value)); 147 assert_size_equal(cbor_string_chunk_count(handle[0].value), 2); 148 assert_memory_equal( 149 cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d", 150 1); 151 cbor_decref(&map); 152 assert_null(map); 153 } 154 155 unsigned char streamed_streamed_kv_map[] = {0xBF, 0x7F, 0x61, 0x61, 0x61, 156 0x62, 0xFF, 0x7F, 0x61, 0x63, 157 0x61, 0x64, 0xFF, 0xFF}; 158 159 /* '{_ (_"a" "b"): (_"c", "d")}' */ 160 static void test_streamed_streamed_kv_map(void **_CBOR_UNUSED(_state)) { 161 map = cbor_load(streamed_streamed_kv_map, 14, &res); 162 assert_non_null(map); 163 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP); 164 assert_true(cbor_isa_map(map)); 165 assert_true(cbor_map_is_indefinite(map)); 166 assert_size_equal(cbor_map_size(map), 1); 167 assert_size_equal(res.read, 14); 168 struct cbor_pair *handle = cbor_map_handle(map); 169 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING); 170 assert_true(cbor_string_is_indefinite(handle[0].key)); 171 assert_size_equal(cbor_string_chunk_count(handle[0].key), 2); 172 assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING); 173 assert_true(cbor_string_is_indefinite(handle[0].value)); 174 assert_size_equal(cbor_string_chunk_count(handle[0].value), 2); 175 assert_memory_equal( 176 cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d", 177 1); 178 cbor_decref(&map); 179 assert_null(map); 180 } 181 182 static void test_map_add_full(void **_CBOR_UNUSED(_state)) { 183 map = cbor_new_definite_map(0); 184 cbor_item_t *one = cbor_build_uint8(1); 185 cbor_item_t *two = cbor_build_uint8(2); 186 187 assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two})); 188 189 cbor_decref(&map); 190 cbor_decref(&one); 191 cbor_decref(&two); 192 } 193 194 static void test_map_add_too_big_to_realloc(void **_CBOR_UNUSED(_state)) { 195 map = cbor_new_indefinite_map(); 196 struct _cbor_map_metadata *metadata = 197 (struct _cbor_map_metadata *)&map->metadata; 198 // Pretend we already have a huge memory block 199 metadata->allocated = SIZE_MAX; 200 metadata->end_ptr = SIZE_MAX; 201 cbor_item_t *one = cbor_build_uint8(1); 202 cbor_item_t *two = cbor_build_uint8(2); 203 204 assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two})); 205 206 metadata->allocated = 0; 207 metadata->end_ptr = 0; 208 cbor_decref(&map); 209 cbor_decref(&one); 210 cbor_decref(&two); 211 } 212 213 static void test_map_creation(void **_CBOR_UNUSED(_state)) { 214 WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_map(42)); }); 215 WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_map(42)); }, 2, MALLOC, 216 MALLOC_FAIL); 217 218 WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_map()); }); 219 } 220 221 static void test_map_add(void **_CBOR_UNUSED(_state)) { 222 WITH_MOCK_MALLOC( 223 { 224 cbor_item_t *map = cbor_new_indefinite_map(); 225 cbor_item_t *key = cbor_build_uint8(0); 226 cbor_item_t *value = cbor_build_bool(true); 227 228 assert_false( 229 cbor_map_add(map, (struct cbor_pair){.key = key, .value = value})); 230 assert_size_equal(cbor_map_allocated(map), 0); 231 assert_null(map->data); 232 233 cbor_decref(&map); 234 cbor_decref(&key); 235 cbor_decref(&value); 236 }, 237 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL); 238 } 239 240 static unsigned char test_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF}; 241 static void test_indef_map_decode(void **_CBOR_UNUSED(_state)) { 242 WITH_MOCK_MALLOC( 243 { 244 cbor_item_t *map; 245 struct cbor_load_result res; 246 map = cbor_load(test_indef_map, 6, &res); 247 248 assert_null(map); 249 assert_size_equal(res.error.code, CBOR_ERR_MEMERROR); 250 }, 251 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL); 252 } 253 254 int main(void) { 255 const struct CMUnitTest tests[] = { 256 cmocka_unit_test(test_empty_map), 257 cmocka_unit_test(test_simple_map), 258 cmocka_unit_test(test_indef_simple_map), 259 cmocka_unit_test(test_def_nested_map), 260 cmocka_unit_test(test_streamed_key_map), 261 cmocka_unit_test(test_streamed_kv_map), 262 cmocka_unit_test(test_streamed_streamed_kv_map), 263 cmocka_unit_test(test_map_add_full), 264 cmocka_unit_test(test_map_add_too_big_to_realloc), 265 cmocka_unit_test(test_map_creation), 266 cmocka_unit_test(test_map_add), 267 cmocka_unit_test(test_indef_map_decode), 268 }; 269 return cmocka_run_group_tests(tests, NULL, NULL); 270 } 271