295 lines
13 KiB
C
295 lines
13 KiB
C
/*
|
|
* Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
|
|
*
|
|
* libcbor is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "assertions.h"
|
|
#include "cbor.h"
|
|
#include "test_allocator.h"
|
|
|
|
cbor_item_t *string;
|
|
struct cbor_load_result res;
|
|
|
|
unsigned char empty_string_data[] = {0x60};
|
|
|
|
static void test_empty_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(empty_string_data, 1, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 0);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 0);
|
|
assert_true(res.read == 1);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char short_string_data[] = {0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20,
|
|
0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21};
|
|
|
|
/* 0x60 + 12 | Hello world! */
|
|
static void test_short_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(short_string_data, 13, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 12);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 12);
|
|
assert_memory_equal(&"Hello world!", cbor_string_handle(string), 12);
|
|
assert_true(res.read == 13);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char short_multibyte_string_data[] = {
|
|
0x6F, 0xC4, 0x8C, 0x61, 0x75, 0x65, 0x73, 0x20,
|
|
0xC3, 0x9F, 0x76, 0xC4, 0x9B, 0x74, 0x65, 0x21};
|
|
|
|
/* 0x60 + 15 | Čaues ßvěte! */
|
|
static void test_short_multibyte_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(short_multibyte_string_data, 16, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 15);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 12);
|
|
assert_memory_equal(&"Čaues ßvěte!", cbor_string_handle(string), 15);
|
|
assert_true(res.read == 16);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char int8_string_data[] = {
|
|
0x78, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 0x75,
|
|
0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20,
|
|
0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63,
|
|
0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73,
|
|
0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 0x44,
|
|
0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 0x6C,
|
|
0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 0x20,
|
|
0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6C,
|
|
0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 0x72,
|
|
0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x66,
|
|
0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 0x6E,
|
|
0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 0x20,
|
|
0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E};
|
|
|
|
/* 150 | Lorem ....*/
|
|
static void test_int8_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(int8_string_data, 152, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 150);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 150);
|
|
assert_memory_equal(
|
|
&"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
|
|
cbor_string_handle(string),
|
|
150
|
|
);
|
|
assert_true(res.read == 152);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char int16_string_data[] = {
|
|
0x79, 0x00, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73,
|
|
0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74,
|
|
0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65,
|
|
0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69,
|
|
0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20,
|
|
0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C,
|
|
0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73,
|
|
0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75,
|
|
0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65,
|
|
0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20,
|
|
0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65,
|
|
0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F,
|
|
0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E};
|
|
/* 150 | Lorem ....*/
|
|
/* This valid but not realistic - length 150 could be encoded in a single
|
|
* uint8_t (but we need to keep the test files reasonably compact) */
|
|
static void test_int16_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(int16_string_data, 153, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 150);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 150);
|
|
assert_memory_equal(
|
|
&"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
|
|
cbor_string_handle(string),
|
|
150
|
|
);
|
|
assert_true(res.read == 153);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char int32_string_data[] = {
|
|
0x7A, 0x00, 0x00, 0x00, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69,
|
|
0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73,
|
|
0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E,
|
|
0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69,
|
|
0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74,
|
|
0x2E, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74,
|
|
0x65, 0x6C, 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C,
|
|
0x69, 0x73, 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69,
|
|
0x62, 0x75, 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20,
|
|
0x66, 0x65, 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F,
|
|
0x6E, 0x20, 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65,
|
|
0x63, 0x65, 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73,
|
|
0x74, 0x6F, 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E};
|
|
|
|
/* 150 | Lorem ....*/
|
|
static void test_int32_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(int32_string_data, 155, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 150);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 150);
|
|
assert_memory_equal(
|
|
&"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
|
|
cbor_string_handle(string),
|
|
150
|
|
);
|
|
assert_true(res.read == 155);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char int64_string_data[] = {
|
|
0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x4C, 0x6F, 0x72,
|
|
0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C,
|
|
0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C,
|
|
0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72,
|
|
0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20,
|
|
0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20,
|
|
0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69,
|
|
0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76,
|
|
0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75,
|
|
0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75,
|
|
0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E,
|
|
0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74,
|
|
0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65,
|
|
0x72, 0x65, 0x2E};
|
|
|
|
/* 150 | Lorem ....*/
|
|
static void test_int64_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(int64_string_data, 159, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_size_equal(cbor_string_length(string), 150);
|
|
assert_size_equal(cbor_string_codepoint_count(string), 150);
|
|
assert_memory_equal(
|
|
&"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
|
|
cbor_string_handle(string),
|
|
150
|
|
);
|
|
assert_true(res.read == 159);
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
unsigned char short_indef_string_data[] = {0x7F, 0x78, 0x01, 0x65, 0xFF, 0xFF};
|
|
|
|
/* start | string | break| extra
|
|
*/
|
|
|
|
static void test_short_indef_string(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_load(short_indef_string_data, 6, &res);
|
|
assert_non_null(string);
|
|
assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
|
|
assert_true(cbor_isa_string(string));
|
|
assert_true(cbor_string_length(string) == 0);
|
|
assert_true(cbor_string_is_indefinite(string));
|
|
assert_true(cbor_string_chunk_count(string) == 1);
|
|
assert_true(res.read == 5);
|
|
assert_true(cbor_isa_string(cbor_string_chunks_handle(string)[0]));
|
|
assert_true(cbor_string_length(cbor_string_chunks_handle(string)[0]) == 1);
|
|
assert_true(*cbor_string_handle(cbor_string_chunks_handle(string)[0]) == 'e');
|
|
cbor_decref(&string);
|
|
assert_null(string);
|
|
}
|
|
|
|
static void test_inline_creation(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_build_string("Hello!");
|
|
assert_memory_equal(cbor_string_handle(string), "Hello!", strlen("Hello!"));
|
|
cbor_decref(&string);
|
|
}
|
|
|
|
static void test_string_creation(void **_CBOR_UNUSED(_state)) {
|
|
WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_string()); });
|
|
|
|
WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_string()); });
|
|
WITH_MOCK_MALLOC({ assert_null(cbor_new_indefinite_string()); }, 2, MALLOC,
|
|
MALLOC_FAIL);
|
|
|
|
WITH_FAILING_MALLOC({ assert_null(cbor_build_string("Test")); });
|
|
WITH_MOCK_MALLOC({ assert_null(cbor_build_string("Test")); }, 2, MALLOC,
|
|
MALLOC_FAIL);
|
|
|
|
WITH_FAILING_MALLOC({ assert_null(cbor_build_stringn("Test", 4)); });
|
|
WITH_MOCK_MALLOC({ assert_null(cbor_build_stringn("Test", 4)); }, 2, MALLOC,
|
|
MALLOC_FAIL);
|
|
}
|
|
|
|
static void test_string_add_chunk(void **_CBOR_UNUSED(_state)) {
|
|
WITH_MOCK_MALLOC(
|
|
{
|
|
cbor_item_t *string = cbor_new_indefinite_string();
|
|
cbor_item_t *chunk = cbor_build_string("Hello!");
|
|
|
|
assert_false(cbor_string_add_chunk(string, chunk));
|
|
assert_size_equal(cbor_string_chunk_count(string), 0);
|
|
assert_size_equal(((struct cbor_indefinite_string_data *)string->data)
|
|
->chunk_capacity,
|
|
0);
|
|
|
|
cbor_decref(&chunk);
|
|
cbor_decref(&string);
|
|
},
|
|
5, MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
|
|
}
|
|
|
|
static void test_add_chunk_reallocation_overflow(void **_CBOR_UNUSED(_state)) {
|
|
string = cbor_new_indefinite_string();
|
|
cbor_item_t *chunk = cbor_build_string("Hello!");
|
|
struct cbor_indefinite_string_data *metadata =
|
|
(struct cbor_indefinite_string_data *)string->data;
|
|
// Pretend we already have many chunks allocated
|
|
metadata->chunk_count = SIZE_MAX;
|
|
metadata->chunk_capacity = SIZE_MAX;
|
|
|
|
assert_false(cbor_string_add_chunk(string, chunk));
|
|
assert_size_equal(cbor_refcount(chunk), 1);
|
|
|
|
metadata->chunk_count = 0;
|
|
metadata->chunk_capacity = 0;
|
|
cbor_decref(&chunk);
|
|
cbor_decref(&string);
|
|
}
|
|
|
|
int main(void) {
|
|
const struct CMUnitTest tests[] = {
|
|
cmocka_unit_test(test_empty_string),
|
|
cmocka_unit_test(test_short_string),
|
|
cmocka_unit_test(test_short_multibyte_string),
|
|
cmocka_unit_test(test_int8_string),
|
|
cmocka_unit_test(test_int16_string),
|
|
cmocka_unit_test(test_int32_string),
|
|
cmocka_unit_test(test_int64_string),
|
|
cmocka_unit_test(test_short_indef_string),
|
|
cmocka_unit_test(test_inline_creation),
|
|
cmocka_unit_test(test_string_creation),
|
|
cmocka_unit_test(test_string_add_chunk),
|
|
cmocka_unit_test(test_add_chunk_reallocation_overflow),
|
|
};
|
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
}
|