2023-10-16 18:20:08 +07:00

4531 lines
110 KiB
C

/*
* SPDX-License-Identifier: ISC
*
* Copyright (C) 2018-2021 Michael Drake <tlsa@netsurf-browser.org>
*/
#include <stdbool.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <cyaml/cyaml.h>
#include "../../src/data.h"
#include "ttest.h"
#include "test.h"
/** Macro to squash unused variable compiler warnings. */
#define UNUSED(_x) ((void)(_x))
/** Helper macro to count bytes of YAML input data. */
#define YAML_LEN(_y) (sizeof(_y) - 1)
/**
* Unit test context data.
*/
typedef struct test_data {
char **buffer;
const struct cyaml_config *config;
} test_data_t;
/**
* Common clean up function to free data allocated by tests.
*
* \param[in] data The unit test context data.
*/
static void cyaml_cleanup(void *data)
{
struct test_data *td = data;
if (td->config->mem_fn != NULL && td->buffer != NULL) {
td->config->mem_fn(td->config->mem_ctx, *(td->buffer), 0);
}
}
/**
* Test saving an unsigned integer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_uint(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_uint: 555\n"
"...\n";
static const struct target_struct {
unsigned test_uint;
} data = {
.test_uint = 555,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT("test_uint", CYAML_FLAG_DEFAULT,
struct target_struct, test_uint),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a float.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_float(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_float: 3.14\n"
"...\n";
static const struct target_struct {
float test_float;
} data = {
.test_float = 3.14f,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_FLOAT("test_float", CYAML_FLAG_DEFAULT,
struct target_struct, test_float),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a double.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_double(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_float: 3.1400000000000001e+00\n"
"...\n";
static const struct target_struct {
double test_float;
} data = {
.test_float = 3.14,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_FLOAT("test_float", CYAML_FLAG_DEFAULT,
struct target_struct, test_float),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_string: This is a test, of sorts.\n"
"...\n";
static const struct target_struct {
char test_string[32];
} data = {
.test_string = "This is a test, of sorts.",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING("test_string", CYAML_FLAG_DEFAULT,
struct target_struct, test_string, 0),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a positive signed integer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_int_pos(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_int: 90\n"
"...\n";
static const struct target_struct {
int test_int;
} data = {
.test_int = 90,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_INT("test_int", CYAML_FLAG_DEFAULT,
struct target_struct, test_int),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a negative signed integer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_int_neg(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_int: -14\n"
"...\n";
static const struct target_struct {
int test_int;
} data = {
.test_int = -14,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_INT("test_int", CYAML_FLAG_DEFAULT,
struct target_struct, test_int),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a negative signed 64-bit integer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_int_64(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_int: -9223372036854775800\n"
"...\n";
static const struct target_struct {
int64_t test_int;
} data = {
.test_int = -9223372036854775800,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_INT("test_int", CYAML_FLAG_DEFAULT,
struct target_struct, test_int),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a boolean.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_bool_true(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_bool: true\n"
"...\n";
static const struct target_struct {
bool test_bool;
} data = {
.test_bool = true,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_BOOL("test_bool", CYAML_FLAG_DEFAULT,
struct target_struct, test_bool),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a boolean.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_bool_false(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_bool: false\n"
"...\n";
static const struct target_struct {
bool test_bool;
} data = {
.test_bool = false,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_BOOL("test_bool", CYAML_FLAG_DEFAULT,
struct target_struct, test_bool),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string pointer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_string: This is a test, of sorts.\n"
"...\n";
static const struct target_struct {
const char *test_string;
} data = {
.test_string = "This is a test, of sorts.",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING_PTR("test_string", CYAML_FLAG_POINTER,
struct target_struct, test_string,
0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a strict enum.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_enum_strict(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_e {
FIRST, SECOND, THIRD, FOURTH, COUNT
};
static const cyaml_strval_t strings[COUNT] = {
{ "first", 0 },
{ "second", 1 },
{ "third", 2 },
{ "fourth", 3 },
};
static const unsigned char ref[] =
"---\n"
"test_enum: third\n"
"...\n";
static const struct target_struct {
enum test_e test_enum;
} data = {
.test_enum = THIRD,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_ENUM("test_enum", CYAML_FLAG_STRICT,
struct target_struct, test_enum, strings, 4),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a numerical enum.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_enum_number(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_e {
FIRST, SECOND, THIRD, FOURTH
};
static const cyaml_strval_t strings[] = {
{ "first", 0 },
{ "second", 1 },
{ "third", 2 },
{ "fourth", 3 },
};
static const unsigned char ref[] =
"---\n"
"test_enum: 99\n"
"...\n";
static const struct target_struct {
enum test_e test_enum;
} data = {
.test_enum = 99,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_ENUM("test_enum", CYAML_FLAG_DEFAULT,
struct target_struct, test_enum, strings, 4),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sparse, unordered enum.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_enum_sparse(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_e {
FIRST = -33,
SECOND = 1,
THIRD = 256,
FOURTH = 3,
FIFTH = 999,
};
static const cyaml_strval_t strings[] = {
{ "first", FIRST },
{ "second", SECOND },
{ "third", THIRD },
{ "fourth", FOURTH },
{ "fifth", FIFTH },
};
static const unsigned char ref[] =
"---\n"
"test_enum: third\n"
"...\n";
static const struct target_struct {
enum test_e test_enum;
} data = {
.test_enum = THIRD,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_ENUM("test_enum", CYAML_FLAG_STRICT,
struct target_struct, test_enum,
strings, CYAML_ARRAY_LEN(strings)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string pointer with plain style.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string_ptr_plain(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"str: This is a test!!\n"
"...\n";
static const struct target_struct {
const char *test_string;
} data = {
.test_string = "This is a test!!",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING_PTR("str",
CYAML_FLAG_POINTER | CYAML_FLAG_SCALAR_PLAIN,
struct target_struct, test_string,
0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string pointer with single quote style.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string_ptr_single(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"str: 'This is a test!!'\n"
"...\n";
static const struct target_struct {
const char *test_string;
} data = {
.test_string = "This is a test!!",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING_PTR("str",
CYAML_FLAG_POINTER |
CYAML_FLAG_SCALAR_QUOTE_SINGLE,
struct target_struct, test_string,
0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string pointer with double quote style.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string_ptr_double(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"str: \"This is a test!!\"\n"
"...\n";
static const struct target_struct {
const char *test_string;
} data = {
.test_string = "This is a test!!",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING_PTR("str",
CYAML_FLAG_POINTER |
CYAML_FLAG_SCALAR_QUOTE_DOUBLE,
struct target_struct, test_string,
0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string pointer with folded style.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string_ptr_folded(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"str: >-\n"
" This is a test!!\n"
"...\n";
static const struct target_struct {
const char *test_string;
} data = {
.test_string = "This is a test!!",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING_PTR("str",
CYAML_FLAG_POINTER |
CYAML_FLAG_SCALAR_FOLDED,
struct target_struct, test_string,
0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a string pointer with literal style.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_string_ptr_literal(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"str: |-\n"
" This is a test!!\n"
"...\n";
static const struct target_struct {
const char *test_string;
} data = {
.test_string = "This is a test!!",
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_STRING_PTR("str",
CYAML_FLAG_POINTER |
CYAML_FLAG_SCALAR_LITERAL,
struct target_struct, test_string,
0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a mapping.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_mapping(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
struct value_s {
short a;
long b;
};
static const unsigned char ref[] =
"---\n"
"mapping:\n"
" a: 123\n"
" b: 9999\n"
"...\n";
static const struct target_struct {
struct value_s test_mapping;
} data = {
.test_mapping = {
.a = 123,
.b = 9999
},
};
static const struct cyaml_schema_field test_mapping_schema[] = {
CYAML_FIELD_INT("a", CYAML_FLAG_DEFAULT, struct value_s, a),
CYAML_FIELD_INT("b", CYAML_FLAG_DEFAULT, struct value_s, b),
CYAML_FIELD_END
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_MAPPING("mapping", CYAML_FLAG_DEFAULT,
struct target_struct, test_mapping,
test_mapping_schema),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a mapping pointer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_mapping_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
struct value_s {
short a;
long b;
} value = {
.a = 123,
.b = 9999
};
static const unsigned char ref[] =
"---\n"
"mapping:\n"
" a: 123\n"
" b: 9999\n"
"...\n";
const struct target_struct {
struct value_s *test_mapping;
} data = {
.test_mapping = &value,
};
static const struct cyaml_schema_field test_mapping_schema[] = {
CYAML_FIELD_INT("a", CYAML_FLAG_DEFAULT, struct value_s, a),
CYAML_FIELD_INT("b", CYAML_FLAG_DEFAULT, struct value_s, b),
CYAML_FIELD_END
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_MAPPING_PTR("mapping", CYAML_FLAG_POINTER,
struct target_struct, test_mapping,
test_mapping_schema),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a strict flags value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_flags_strict(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_f {
NONE = 0,
FIRST = (1 << 0),
SECOND = (1 << 1),
THIRD = (1 << 2),
FOURTH = (1 << 3),
};
static const cyaml_strval_t strings[] = {
{ "first", (1 << 0) },
{ "second", (1 << 1) },
{ "third", (1 << 2) },
{ "fourth", (1 << 3) },
};
static const unsigned char ref[] =
"---\n"
"test_flags:\n"
"- first\n"
"- fourth\n"
"...\n";
static const struct target_struct {
enum test_f test_flags;
} data = {
.test_flags = FIRST | FOURTH,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_FLAGS("test_flags", CYAML_FLAG_STRICT,
struct target_struct, test_flags, strings, 4),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a numerical flags value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_flags_number(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_f {
NONE = 0,
FIRST = (1 << 0),
SECOND = (1 << 1),
THIRD = (1 << 2),
FOURTH = (1 << 3),
};
static const cyaml_strval_t strings[] = {
{ "first", (1 << 0) },
{ "second", (1 << 1) },
{ "third", (1 << 2) },
{ "fourth", (1 << 3) },
};
static const unsigned char ref[] =
"---\n"
"test_flags:\n"
"- first\n"
"- fourth\n"
"- 1024\n"
"...\n";
static const struct target_struct {
enum test_f test_flags;
} data = {
.test_flags = FIRST | FOURTH | 1024,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_FLAGS("test_flags", CYAML_FLAG_DEFAULT,
struct target_struct, test_flags, strings, 4),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sparse flags value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_flags_sparse(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_f {
NONE = 0,
FIRST = (1 << 3),
SECOND = (1 << 9),
THIRD = (1 << 10),
FOURTH = (1 << 21),
};
static const cyaml_strval_t strings[] = {
{ "none", NONE },
{ "first", FIRST },
{ "second", SECOND },
{ "third", THIRD },
{ "fourth", FOURTH },
};
static const unsigned char ref[] =
"---\n"
"test_flags:\n"
"- first\n"
"- fourth\n"
"...\n";
static const struct target_struct {
enum test_f test_flags;
} data = {
.test_flags = FIRST | FOURTH,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_FLAGS("test_flags", CYAML_FLAG_DEFAULT,
struct target_struct, test_flags,
strings, CYAML_ARRAY_LEN(strings)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a bitfield value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_bitfield(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const cyaml_bitdef_t bitvals[] = {
{ .name = "a", .offset = 0, .bits = 3 },
{ .name = "b", .offset = 3, .bits = 7 },
{ .name = "c", .offset = 10, .bits = 32 },
{ .name = "d", .offset = 42, .bits = 8 },
{ .name = "e", .offset = 50, .bits = 14 },
};
static const unsigned char ref[] =
"---\n"
"test_bitfield:\n"
" a: 0x7\n"
" b: 0x7f\n"
" c: 0xffffffff\n"
" d: 0xff\n"
" e: 0x3fff\n"
"...\n";
static const struct target_struct {
uint64_t test_bitfield;
} data = {
.test_bitfield = 0xFFFFFFFFFFFFFFFFu,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_BITFIELD("test_bitfield", CYAML_FLAG_DEFAULT,
struct target_struct, test_bitfield,
bitvals, CYAML_ARRAY_LEN(bitvals)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sparse bitfield value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_bitfield_sparse(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const cyaml_bitdef_t bitvals[] = {
{ .name = "a", .offset = 0, .bits = 3 },
{ .name = "b", .offset = 3, .bits = 7 },
{ .name = "c", .offset = 10, .bits = 32 },
{ .name = "d", .offset = 42, .bits = 8 },
{ .name = "e", .offset = 50, .bits = 14 },
};
static const unsigned char ref[] =
"---\n"
"test_bitfield:\n"
" a: 0x7\n"
" b: 0x7f\n"
" e: 0x3fff\n"
"...\n";
static const struct target_struct {
uint64_t test_bitfield;
} data = {
.test_bitfield = ( 0x7llu << 0) |
( 0x7Fllu << 3) |
(0x3FFFllu << 50),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_BITFIELD("test_bitfield", CYAML_FLAG_DEFAULT,
struct target_struct, test_bitfield,
bitvals, CYAML_ARRAY_LEN(bitvals)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of integers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- 1\n"
"- 1\n"
"- 2\n"
"- 3\n"
"- 5\n"
"- 8\n"
"...\n";
static const struct target_struct {
int seq[6];
uint32_t seq_count;
} data = {
.seq = { 1, 1, 2, 3, 5, 8 },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, *(data.seq)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of unsigned integers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_uint(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- 1\n"
"- 1\n"
"- 2\n"
"- 3\n"
"- 5\n"
"- 8\n"
"...\n";
static const struct target_struct {
unsigned seq[6];
uint32_t seq_count;
} data = {
.seq = { 1, 1, 2, 3, 5, 8 },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_UINT(CYAML_FLAG_DEFAULT, *(data.seq)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of enums.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_enum(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_enum {
TEST_ENUM_FIRST,
TEST_ENUM_SECOND,
TEST_ENUM_THIRD,
TEST_ENUM__COUNT,
};
static const cyaml_strval_t strings[TEST_ENUM__COUNT] = {
[TEST_ENUM_FIRST] = { "first", 0 },
[TEST_ENUM_SECOND] = { "second", 1 },
[TEST_ENUM_THIRD] = { "third", 2 },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- first\n"
"- second\n"
"- third\n"
"...\n";
static const struct target_struct {
enum test_enum seq[3];
uint32_t seq_count;
} data = {
.seq = { TEST_ENUM_FIRST, TEST_ENUM_SECOND, TEST_ENUM_THIRD },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_ENUM(CYAML_FLAG_DEFAULT, *(data.seq),
strings, TEST_ENUM__COUNT),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of boolean values.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_bool(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- true\n"
"- false\n"
"- true\n"
"- false\n"
"- true\n"
"- false\n"
"- true\n"
"- false\n"
"...\n";
static const struct target_struct {
bool seq[8];
uint32_t seq_count;
} data = {
.seq = { true, false, true, false, true, false, true, false },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_BOOL(CYAML_FLAG_DEFAULT, *(data.seq)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of flags.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_flags(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_flags {
TEST_FLAGS_NONE = 0,
TEST_FLAGS_FIRST = (1 << 0),
TEST_FLAGS_SECOND = (1 << 1),
TEST_FLAGS_THIRD = (1 << 2),
TEST_FLAGS_FOURTH = (1 << 3),
TEST_FLAGS_FIFTH = (1 << 4),
TEST_FLAGS_SIXTH = (1 << 5),
};
static const cyaml_strval_t strings[] = {
{ "none", TEST_FLAGS_NONE },
{ "first", TEST_FLAGS_FIRST },
{ "second", TEST_FLAGS_SECOND },
{ "third", TEST_FLAGS_THIRD },
{ "fourth", TEST_FLAGS_FOURTH },
{ "fifth", TEST_FLAGS_FIFTH },
{ "sixth", TEST_FLAGS_SIXTH },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - second\n"
" - fifth\n"
" - 1024\n"
"- - first\n"
"- - fourth\n"
" - sixth\n"
"...\n";
static const struct target_struct {
enum test_flags seq[3];
uint32_t seq_count;
} data = {
.seq = {
TEST_FLAGS_SECOND | TEST_FLAGS_FIFTH | 1024,
TEST_FLAGS_FIRST,
TEST_FLAGS_FOURTH | TEST_FLAGS_SIXTH },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_FLAGS(CYAML_FLAG_DEFAULT, *(data.seq),
strings, CYAML_ARRAY_LEN(strings)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of strings.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_string(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- This\n"
"- is\n"
"- merely\n"
"- a\n"
"- test\n"
"...\n";
static const struct target_struct {
char seq[5][7];
uint32_t seq_count;
} data = {
.seq = {
{ 'T', 'h', 'i', 's'},
{ 'i', 's', },
{ 'm', 'e', 'r', 'e', 'l', 'y', },
{ 'a', },
{ 't', 'e', 's', 't', },
},
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_STRING(CYAML_FLAG_DEFAULT, *(data.seq), 0, 6),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of strings.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_string_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- This\n"
"- is\n"
"- merely\n"
"- a\n"
"- test\n"
"...\n";
static const struct target_struct {
char *seq[5];
uint32_t seq_count;
} data = {
.seq = {
(char *) "This",
(char *) "is",
(char *) "merely",
(char *) "a",
(char *) "test", },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_STRING(CYAML_FLAG_POINTER, *(data.seq),
0, CYAML_UNLIMITED),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of mappings.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_mapping(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
struct value_s {
short a;
long b;
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- a: 123\n"
" b: 9999\n"
"- a: 4000\n"
" b: 62000\n"
"- a: 1\n"
" b: 765\n"
"...\n";
static const struct target_struct {
struct value_s seq[3];
uint32_t seq_count;
} data = {
.seq = {
[0] = { .a = 123, .b = 9999 },
[1] = { .a = 4000, .b = 62000 },
[2] = { .a = 1, .b = 765 }, },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_field test_mapping_schema[] = {
CYAML_FIELD_INT("a", CYAML_FLAG_DEFAULT, struct value_s, a),
CYAML_FIELD_INT("b", CYAML_FLAG_DEFAULT, struct value_s, b),
CYAML_FIELD_END
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT,
struct value_s, test_mapping_schema),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of mappings pointers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_mapping_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const struct value_s {
short a;
long b;
} v[3] = {
{ .a = 123, .b = 9999, },
{ .a = 4000, .b = 62000, },
{ .a = 1, .b = 765, },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- a: 123\n"
" b: 9999\n"
"- a: 4000\n"
" b: 62000\n"
"- a: 1\n"
" b: 765\n"
"...\n";
static const struct target_struct {
const struct value_s *seq[3];
uint32_t seq_count;
} data = {
.seq = {
[0] = &v[0],
[1] = &v[1],
[2] = &v[2], },
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_field test_mapping_schema[] = {
CYAML_FIELD_INT("a", CYAML_FLAG_DEFAULT, struct value_s, a),
CYAML_FIELD_INT("b", CYAML_FLAG_DEFAULT, struct value_s, b),
CYAML_FIELD_END
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct value_s, test_mapping_schema),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of fixed-length sequences.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_sequence_fixed_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - 1\n"
" - 2\n"
" - 3\n"
"- - 4\n"
" - 5\n"
" - 6\n"
"- - 7\n"
" - 8\n"
" - 9\n"
"- - 10\n"
" - 11\n"
" - 12\n"
"...\n";
static const struct target_struct {
int seq[4][3];
uint32_t seq_count;
} data = {
.seq = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 },
},
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema_int = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, **(data.seq)),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_SEQUENCE_FIXED(
CYAML_FLAG_DEFAULT, **(data.seq),
&entry_schema_int, CYAML_ARRAY_LEN(*data.seq))
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END,
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of fixed-length sequences pointers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_sequence_fixed_ptr_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const int v[4][3] = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - 1\n"
" - 2\n"
" - 3\n"
"- - 4\n"
" - 5\n"
" - 6\n"
"- - 7\n"
" - 8\n"
" - 9\n"
"- - 10\n"
" - 11\n"
" - 12\n"
"...\n";
static const struct target_struct {
const int *seq[4];
uint32_t seq_count;
} data = {
.seq = {
v[0],
v[1],
v[2],
v[3],
},
.seq_count = CYAML_ARRAY_LEN(data.seq),
};
static const struct cyaml_schema_value entry_schema_int = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, **(data.seq)),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_SEQUENCE_FIXED(
CYAML_FLAG_POINTER, **(data.seq),
&entry_schema_int, CYAML_ARRAY_LEN(*v))
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_DEFAULT,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END,
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a flattened sequence of fixed-length sequences.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_sequence_fixed_flat_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - 1\n"
" - 2\n"
" - 3\n"
"- - 4\n"
" - 5\n"
" - 6\n"
"- - 7\n"
" - 8\n"
" - 9\n"
"- - 10\n"
" - 11\n"
" - 12\n"
"...\n";
static const struct target_struct {
int seq[12];
uint32_t seq_count;
} data = {
.seq = {
1, 2, 3,
4, 5, 6,
7, 8, 9,
10, 11, 12,
},
/* Note: count is count of entries of the outer sequence
* entries, so, 4, not 12. */
.seq_count = CYAML_ARRAY_LEN(data.seq) / 3,
};
static const struct cyaml_schema_value entry_schema_int = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, int),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_SEQUENCE_FIXED(
CYAML_FLAG_DEFAULT, int,
&entry_schema_int, 3),
};
static const struct cyaml_schema_field mapping_schema[] = {
{
.key = "sequence",
.value = {
.type = CYAML_SEQUENCE,
.flags = CYAML_FLAG_DEFAULT,
.data_size = sizeof(int[3]),
.sequence = {
.entry = &entry_schema,
.min = 0,
.max = CYAML_UNLIMITED,
}
},
.data_offset = offsetof(struct target_struct, seq),
.count_size = sizeof(data.seq_count),
.count_offset = offsetof(struct target_struct, seq_count),
},
CYAML_FIELD_END,
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of integers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- 1\n"
"- 1\n"
"- 2\n"
"- 3\n"
"- 5\n"
"- 8\n"
"...\n";
static const int seq[6] = { 1, 1, 2, 3, 5, 8 };
static const struct target_struct {
const int *seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, *(data.seq)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of unsigned integers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_uint(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- 1\n"
"- 1\n"
"- 2\n"
"- 3\n"
"- 5\n"
"- 8\n"
"...\n";
static const unsigned seq[6] = { 1, 1, 2, 3, 5, 8 };
static const struct target_struct {
const unsigned *seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_UINT(CYAML_FLAG_DEFAULT, *(data.seq)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of enums.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_enum(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_enum {
TEST_ENUM_FIRST,
TEST_ENUM_SECOND,
TEST_ENUM_THIRD,
TEST_ENUM__COUNT,
};
static const cyaml_strval_t strings[TEST_ENUM__COUNT] = {
[TEST_ENUM_FIRST] = { "first", 0 },
[TEST_ENUM_SECOND] = { "second", 1 },
[TEST_ENUM_THIRD] = { "third", 2 },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- first\n"
"- second\n"
"- third\n"
"...\n";
static const enum test_enum seq[3] = {
TEST_ENUM_FIRST,
TEST_ENUM_SECOND,
TEST_ENUM_THIRD
};
static const struct target_struct {
const enum test_enum *seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_ENUM(CYAML_FLAG_DEFAULT, *(data.seq),
strings, TEST_ENUM__COUNT),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of boolean values.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_bool(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- true\n"
"- false\n"
"- true\n"
"- false\n"
"- true\n"
"- false\n"
"- true\n"
"- false\n"
"...\n";
static const bool seq[8] = {
true, false, true, false,
true, false, true, false
};
static const struct target_struct {
const bool *seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_BOOL(CYAML_FLAG_DEFAULT, *(data.seq)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of flags.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_flags(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
enum test_flags {
TEST_FLAGS_NONE = 0,
TEST_FLAGS_FIRST = (1 << 0),
TEST_FLAGS_SECOND = (1 << 1),
TEST_FLAGS_THIRD = (1 << 2),
TEST_FLAGS_FOURTH = (1 << 3),
TEST_FLAGS_FIFTH = (1 << 4),
TEST_FLAGS_SIXTH = (1 << 5),
};
static const cyaml_strval_t strings[] = {
{ "none", TEST_FLAGS_NONE },
{ "first", TEST_FLAGS_FIRST },
{ "second", TEST_FLAGS_SECOND },
{ "third", TEST_FLAGS_THIRD },
{ "fourth", TEST_FLAGS_FOURTH },
{ "fifth", TEST_FLAGS_FIFTH },
{ "sixth", TEST_FLAGS_SIXTH },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - second\n"
" - fifth\n"
" - 1024\n"
"- - first\n"
"- - fourth\n"
" - sixth\n"
"...\n";
static const enum test_flags seq[3] = {
TEST_FLAGS_SECOND | TEST_FLAGS_FIFTH | 1024,
TEST_FLAGS_FIRST,
TEST_FLAGS_FOURTH | TEST_FLAGS_SIXTH,
};
static const struct target_struct {
const enum test_flags *seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_FLAGS(CYAML_FLAG_DEFAULT, *(data.seq),
strings, CYAML_ARRAY_LEN(strings)),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of strings.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_string(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- This\n"
"- is\n"
"- merely\n"
"- a\n"
"- test\n"
"...\n";
static const char seq[][7] = {
"This",
"is",
"merely",
"a",
"test",
};
static const struct target_struct {
const char (*seq)[7];
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_STRING(CYAML_FLAG_DEFAULT, *(data.seq), 0, 6),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of strings.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_string_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- This\n"
"- is\n"
"- merely\n"
"- a\n"
"- test\n"
"...\n";
static const char *seq[] = {
"This",
"is",
"merely",
"a",
"test",
};
static const struct target_struct {
const char **seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_STRING(CYAML_FLAG_POINTER, *(data.seq),
0, CYAML_UNLIMITED),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of mappings.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_mapping(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
struct value_s {
short a;
long b;
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- a: 123\n"
" b: 9999\n"
"- a: 4000\n"
" b: 62000\n"
"- a: 1\n"
" b: 765\n"
"...\n";
static const struct value_s seq[3] = {
[0] = { .a = 123, .b = 9999 },
[1] = { .a = 4000, .b = 62000 },
[2] = { .a = 1, .b = 765 },
};
static const struct target_struct {
const struct value_s *seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_field test_mapping_schema[] = {
CYAML_FIELD_INT("a", CYAML_FLAG_DEFAULT, struct value_s, a),
CYAML_FIELD_INT("b", CYAML_FLAG_DEFAULT, struct value_s, b),
CYAML_FIELD_END
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT,
struct value_s, test_mapping_schema),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of mappings pointers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_mapping_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const struct value_s {
short a;
long b;
} v[3] = {
{ .a = 123, .b = 9999, },
{ .a = 4000, .b = 62000, },
{ .a = 1, .b = 765, },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- a: 123\n"
" b: 9999\n"
"- a: 4000\n"
" b: 62000\n"
"- a: 1\n"
" b: 765\n"
"...\n";
static const struct value_s *seq[3] = {
[0] = &v[0],
[1] = &v[1],
[2] = &v[2],
};
static const struct target_struct {
const struct value_s **seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_field test_mapping_schema[] = {
CYAML_FIELD_INT("a", CYAML_FLAG_DEFAULT, struct value_s, a),
CYAML_FIELD_INT("b", CYAML_FLAG_DEFAULT, struct value_s, b),
CYAML_FIELD_END
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct value_s, test_mapping_schema),
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of fixed-length sequences.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_sequence_fixed_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - 1\n"
" - 2\n"
" - 3\n"
"- - 4\n"
" - 5\n"
" - 6\n"
"- - 7\n"
" - 8\n"
" - 9\n"
"- - 10\n"
" - 11\n"
" - 12\n"
"...\n";
static const int seq[4][3] = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 },
};
static const struct target_struct {
const int (*seq)[3];
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema_int = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, **(data.seq)),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_SEQUENCE_FIXED(
CYAML_FLAG_DEFAULT, **(data.seq),
&entry_schema_int, CYAML_ARRAY_LEN(*data.seq))
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END,
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence of fixed-length sequences pointers.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_sequence_fixed_ptr_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const int v[4][3] = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 },
};
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - 1\n"
" - 2\n"
" - 3\n"
"- - 4\n"
" - 5\n"
" - 6\n"
"- - 7\n"
" - 8\n"
" - 9\n"
"- - 10\n"
" - 11\n"
" - 12\n"
"...\n";
static const int *seq[] = {
v[0],
v[1],
v[2],
v[3],
};
static const struct target_struct {
const int **seq;
uint32_t seq_count;
} data = {
.seq = seq,
.seq_count = CYAML_ARRAY_LEN(seq),
};
static const struct cyaml_schema_value entry_schema_int = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, **(data.seq)),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_SEQUENCE_FIXED(
CYAML_FLAG_POINTER, **(data.seq),
&entry_schema_int, CYAML_ARRAY_LEN(*v))
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_SEQUENCE("sequence", CYAML_FLAG_POINTER,
struct target_struct, seq, &entry_schema,
0, CYAML_ARRAY_LEN(ref)),
CYAML_FIELD_END,
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a flattened sequence of fixed-length sequences.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_sequence_ptr_sequence_fixed_flat_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"sequence:\n"
"- - 1\n"
" - 2\n"
" - 3\n"
"- - 4\n"
" - 5\n"
" - 6\n"
"- - 7\n"
" - 8\n"
" - 9\n"
"- - 10\n"
" - 11\n"
" - 12\n"
"...\n";
static const int seq[12] = {
1, 2, 3,
4, 5, 6,
7, 8, 9,
10, 11, 12,
};
static const struct target_struct {
const int *seq;
uint32_t seq_count;
} data = {
.seq = seq,
/* Note: count is count of entries of the outer sequence
* entries, so, 4, not 12. */
.seq_count = CYAML_ARRAY_LEN(seq) / 3,
};
static const struct cyaml_schema_value entry_schema_int = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, int),
};
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_SEQUENCE_FIXED(
CYAML_FLAG_DEFAULT, int,
&entry_schema_int, 3),
};
static const struct cyaml_schema_field mapping_schema[] = {
{
.key = "sequence",
.value = {
.type = CYAML_SEQUENCE,
.flags = CYAML_FLAG_POINTER,
.data_size = sizeof(int[3]),
.sequence = {
.entry = &entry_schema,
.min = 0,
.max = CYAML_UNLIMITED,
}
},
.data_offset = offsetof(struct target_struct, seq),
.count_size = sizeof(data.seq_count),
.count_offset = offsetof(struct target_struct, seq_count),
},
CYAML_FIELD_END,
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving optional mapping field.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_optional_uint(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_uint: 555\n"
"...\n";
static const struct target_struct {
unsigned test_uint;
} data = {
.test_uint = 555,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT("test_uint", CYAML_FLAG_OPTIONAL,
struct target_struct, test_uint),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer = NULL;
size_t len = 0;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving optional mapping field with pointer value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_optional_uint_ptr(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_uint: 555\n"
"...\n";
static unsigned test_uint = 555;
static const struct target_struct {
unsigned *test_uint;
} data = {
.test_uint = &test_uint,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT_PTR("test_uint",
CYAML_FLAG_OPTIONAL | CYAML_FLAG_POINTER,
struct target_struct, test_uint),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer = NULL;
size_t len = 0;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving optional mapping field with NULL pointer value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_optional_uint_ptr_null(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"--- {}\n"
"...\n";
static const struct target_struct {
unsigned *test_uint;
} data = {
.test_uint = NULL,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT_PTR("test_uint",
CYAML_FLAG_OPTIONAL | CYAML_FLAG_POINTER,
struct target_struct, test_uint),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer = NULL;
size_t len = 0;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving an unsigned integer.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_entry_ignored(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"test_uint: 555\n"
"...\n";
static const struct target_struct {
unsigned test_uint;
} data = {
.test_uint = 555,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT("test_uint", CYAML_FLAG_DEFAULT,
struct target_struct, test_uint),
CYAML_FIELD_IGNORE("foo", CYAML_FLAG_DEFAULT),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
char *buffer = NULL;
size_t len = 0;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence containing a NULL value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_sequence_null_values_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref1[] =
"---\n"
"- 7\n"
"- 6\n"
"- 5\n"
"- \n"
"- 3\n"
"- 2\n"
"- \n"
"- 0\n"
"...\n";
/* As of libyaml 0.2.5, trailing spaces are not emitted. */
static const unsigned char ref2[] =
"---\n"
"- 7\n"
"- 6\n"
"- 5\n"
"-\n"
"- 3\n"
"- 2\n"
"-\n"
"- 0\n"
"...\n";
static const int d[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
static const int *data[] = { d + 0, d + 1, d + 2, NULL,
d + 4, d + 5, NULL, d + 7, };
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_POINTER_NULL, int)
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_SEQUENCE(CYAML_FLAG_POINTER, int,
&entry_schema, 0, 3),
};
char *buffer = NULL;
size_t len = 0;
cyaml_config_t cfg = *config;
test_data_t td = {
.buffer = &buffer,
.config = &cfg,
};
cyaml_err_t err;
ttest_ctx_t tc;
cfg.flags |= CYAML_CFG_STYLE_BLOCK;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data,
CYAML_ARRAY_LEN(data));
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if ((len != YAML_LEN(ref1) || memcmp(ref1, buffer, len) != 0) &&
(len != YAML_LEN(ref2) || memcmp(ref2, buffer, len) != 0)) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref1), YAML_LEN(ref1), ref1,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence containing a NULL value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_sequence_null_str_values_int(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"- 7\n"
"- 6\n"
"- 5\n"
"- null\n"
"- 3\n"
"- 2\n"
"- 1\n"
"- 0\n"
"...\n";
static const int d[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
static const int *data[] = { d + 0, d + 1, d + 2, NULL,
d + 4, d + 5, d + 6, d + 7, };
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_POINTER_NULL_STR, int)
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_SEQUENCE(CYAML_FLAG_POINTER, int,
&entry_schema, 0, 3),
};
char *buffer = NULL;
size_t len = 0;
cyaml_config_t cfg = *config;
test_data_t td = {
.buffer = &buffer,
.config = &cfg,
};
cyaml_err_t err;
ttest_ctx_t tc;
cfg.flags |= CYAML_CFG_STYLE_BLOCK;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data,
CYAML_ARRAY_LEN(data));
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving with schema with sequence_fixed top level type.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_schema_top_level_sequence_fixed(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"- 7\n"
"- 6\n"
"- 5\n"
"...\n";
int data[3] = { 7, 6, 5 };
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, int)
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_SEQUENCE_FIXED(CYAML_FLAG_POINTER, int,
&entry_schema, 3)
};
char *buffer = NULL;
size_t len = 0;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema, data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence with flow style configured.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_sequence_config_flow_style(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"--- [7, 6, 5]\n"
"...\n";
int data[3] = { 7, 6, 5 };
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, int)
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_SEQUENCE(CYAML_FLAG_POINTER, int,
&entry_schema, 0, 3),
};
char *buffer = NULL;
size_t len = 0;
cyaml_config_t cfg = *config;
test_data_t td = {
.buffer = &buffer,
.config = &cfg,
};
cyaml_err_t err;
ttest_ctx_t tc;
cfg.flags |= CYAML_CFG_STYLE_FLOW;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, 3);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a sequence with block style configured.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_sequence_config_block_style(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"- 7\n"
"- 6\n"
"- 5\n"
"...\n";
int data[3] = { 7, 6, 5 };
static const struct cyaml_schema_value entry_schema = {
CYAML_VALUE_INT(CYAML_FLAG_DEFAULT, int)
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_SEQUENCE(CYAML_FLAG_POINTER, int,
&entry_schema, 0, 3),
};
char *buffer = NULL;
size_t len = 0;
cyaml_config_t cfg = *config;
test_data_t td = {
.buffer = &buffer,
.config = &cfg,
};
cyaml_err_t err;
ttest_ctx_t tc;
cfg.flags |= CYAML_CFG_STYLE_BLOCK;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, 3);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a mapping with flow style value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_value_flow_style(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const char ref[] =
"--- {a: 555, b: 99, c: 7}\n"
"...\n";
static const struct target_struct {
unsigned a;
unsigned b;
unsigned c;
} data = {
.a = 555,
.b = 99,
.c = 7,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT("a", CYAML_FLAG_DEFAULT,
struct target_struct, a),
CYAML_FIELD_UINT("b", CYAML_FLAG_DEFAULT,
struct target_struct, b),
CYAML_FIELD_UINT("c", CYAML_FLAG_DEFAULT,
struct target_struct, c),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER | CYAML_FLAG_FLOW,
struct target_struct, mapping_schema),
};
char *buffer = NULL;
size_t len = 0;
cyaml_config_t cfg = *config;
test_data_t td = {
.buffer = &buffer,
.config = &cfg,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving a mapping with block style value.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_mapping_value_block_style(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"---\n"
"a: 555\n"
"b: 99\n"
"c: 7\n"
"...\n";
static const struct target_struct {
unsigned a;
unsigned b;
unsigned c;
} data = {
.a = 555,
.b = 99,
.c = 7,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT("a", CYAML_FLAG_DEFAULT,
struct target_struct, a),
CYAML_FIELD_UINT("b", CYAML_FLAG_DEFAULT,
struct target_struct, b),
CYAML_FIELD_UINT("c", CYAML_FLAG_DEFAULT,
struct target_struct, c),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER | CYAML_FLAG_BLOCK,
struct target_struct, mapping_schema),
};
char *buffer = NULL;
size_t len = 0;
test_data_t td = {
.buffer = &buffer,
.config = config,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
err = cyaml_save_data(&buffer, &len, config, &top_schema,
&data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Test saving without document delimiters.
*
* \param[in] report The test report context.
* \param[in] config The CYAML config to use for the test.
* \return true if test passes, false otherwise.
*/
static bool test_save_no_document_delimiters(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
static const unsigned char ref[] =
"test_uint: 555\n";
static const struct target_struct {
unsigned test_uint;
} data = {
.test_uint = 555,
};
static const struct cyaml_schema_field mapping_schema[] = {
CYAML_FIELD_UINT("test_uint", CYAML_FLAG_DEFAULT,
struct target_struct, test_uint),
CYAML_FIELD_END
};
static const struct cyaml_schema_value top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
struct target_struct, mapping_schema),
};
cyaml_config_t cfg = *config;
char *buffer;
size_t len;
test_data_t td = {
.buffer = &buffer,
.config = &cfg,
};
cyaml_err_t err;
ttest_ctx_t tc;
if (!ttest_start(report, __func__, cyaml_cleanup, &td, &tc)) {
return true;
}
cfg.flags &= ~((unsigned)CYAML_CFG_DOCUMENT_DELIM);
err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, &data, 0);
if (err != CYAML_OK) {
return ttest_fail(&tc, cyaml_strerror(err));
}
if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) {
return ttest_fail(&tc, "Bad data:\n"
"EXPECTED (%zu):\n\n%.*s\n\n"
"GOT (%zu):\n\n%.*s\n",
YAML_LEN(ref), YAML_LEN(ref), ref,
len, len, buffer);
}
return ttest_pass(&tc);
}
/**
* Run the YAML saving unit tests.
*
* \param[in] rc The ttest report context.
* \param[in] log_level CYAML log level.
* \param[in] log_fn CYAML logging function, or NULL.
* \return true iff all unit tests pass, otherwise false.
*/
bool save_tests(
ttest_report_ctx_t *rc,
cyaml_log_t log_level,
cyaml_log_fn_t log_fn)
{
bool pass = true;
cyaml_config_t config = {
.log_fn = log_fn,
.mem_fn = cyaml_mem,
.log_level = log_level,
.flags = CYAML_CFG_DOCUMENT_DELIM,
};
ttest_heading(rc, "Save single entry mapping tests: simple types");
pass &= test_save_mapping_entry_uint(rc, &config);
pass &= test_save_mapping_entry_float(rc, &config);
pass &= test_save_mapping_entry_double(rc, &config);
pass &= test_save_mapping_entry_string(rc, &config);
pass &= test_save_mapping_entry_int_64(rc, &config);
pass &= test_save_mapping_entry_int_pos(rc, &config);
pass &= test_save_mapping_entry_int_neg(rc, &config);
pass &= test_save_mapping_entry_bool_true(rc, &config);
pass &= test_save_mapping_entry_bool_false(rc, &config);
pass &= test_save_mapping_entry_string_ptr(rc, &config);
pass &= test_save_mapping_entry_enum_strict(rc, &config);
pass &= test_save_mapping_entry_enum_number(rc, &config);
pass &= test_save_mapping_entry_enum_sparse(rc, &config);
ttest_heading(rc, "Save single entry mapping tests: scalar style");
pass &= test_save_mapping_entry_string_ptr_plain(rc, &config);
pass &= test_save_mapping_entry_string_ptr_single(rc, &config);
pass &= test_save_mapping_entry_string_ptr_double(rc, &config);
pass &= test_save_mapping_entry_string_ptr_folded(rc, &config);
pass &= test_save_mapping_entry_string_ptr_literal(rc, &config);
ttest_heading(rc, "Save single entry mapping tests: complex types");
pass &= test_save_mapping_entry_mapping(rc, &config);
pass &= test_save_mapping_entry_bitfield(rc, &config);
pass &= test_save_mapping_entry_mapping_ptr(rc, &config);
pass &= test_save_mapping_entry_flags_strict(rc, &config);
pass &= test_save_mapping_entry_flags_number(rc, &config);
pass &= test_save_mapping_entry_flags_sparse(rc, &config);
pass &= test_save_mapping_entry_bitfield_sparse(rc, &config);
ttest_heading(rc, "Save single entry mapping tests: sequences");
pass &= test_save_mapping_entry_sequence_int(rc, &config);
pass &= test_save_mapping_entry_sequence_uint(rc, &config);
pass &= test_save_mapping_entry_sequence_enum(rc, &config);
pass &= test_save_mapping_entry_sequence_bool(rc, &config);
pass &= test_save_mapping_entry_sequence_flags(rc, &config);
pass &= test_save_mapping_entry_sequence_string(rc, &config);
pass &= test_save_mapping_entry_sequence_mapping(rc, &config);
pass &= test_save_mapping_entry_sequence_string_ptr(rc, &config);
pass &= test_save_mapping_entry_sequence_mapping_ptr(rc, &config);
pass &= test_save_mapping_entry_sequence_sequence_fixed_int(rc, &config);
pass &= test_save_mapping_entry_sequence_sequence_fixed_ptr_int(rc, &config);
pass &= test_save_mapping_entry_sequence_sequence_fixed_flat_int(rc, &config);
ttest_heading(rc, "Save single entry mapping tests: ptr sequences");
pass &= test_save_mapping_entry_sequence_ptr_int(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_enum(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_uint(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_bool(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_flags(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_string(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_mapping(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_string_ptr(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_mapping_ptr(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_sequence_fixed_int(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_sequence_fixed_ptr_int(rc, &config);
pass &= test_save_mapping_entry_sequence_ptr_sequence_fixed_flat_int(rc, &config);
ttest_heading(rc, "Save tests: ptr sequence with null values");
pass &= test_save_sequence_null_values_int(rc, &config);
pass &= test_save_sequence_null_str_values_int(rc, &config);
ttest_heading(rc, "Save tests: optional mapping fields");
pass &= test_save_mapping_entry_optional_uint(rc, &config);
pass &= test_save_mapping_entry_optional_uint_ptr(rc, &config);
pass &= test_save_mapping_entry_optional_uint_ptr_null(rc, &config);
ttest_heading(rc, "Save tests: various");
pass &= test_save_mapping_entry_ignored(rc, &config);
pass &= test_save_no_document_delimiters(rc, &config);
pass &= test_save_mapping_value_flow_style(rc, &config);
pass &= test_save_mapping_value_block_style(rc, &config);
pass &= test_save_sequence_config_flow_style(rc, &config);
pass &= test_save_sequence_config_block_style(rc, &config);
pass &= test_save_schema_top_level_sequence_fixed(rc, &config);
return pass;
}