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

301 lines
6.8 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/mem.h"
#include "../../src/util.h"
#include "ttest.h"
#include "test.h"
/**
* Test cyaml memory functions.
*
* \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_util_memory_funcs(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
ttest_ctx_t tc;
unsigned char *mem, *tmp;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
/* Create test allocation */
mem = cyaml__alloc(config, 0xff, true);
if (mem == NULL) {
return ttest_fail(&tc, "Memory allocation failed.");
}
/* Check allocation was zeroed. */
for (unsigned i = 0; i < 0x7f; i++) {
if (mem[i] != 0) {
return ttest_fail(&tc, "Allocation not cleaned.");
}
}
/* Set our own known values */
for (unsigned i = 0; i < 0xff; i++) {
mem[i] = 0xff;
}
/* Shrink allocation */
tmp = cyaml__realloc(config, mem, 0xff, 0x7f, true);
if (tmp == NULL) {
return ttest_fail(&tc, "Allocation shrink failed.");
}
mem = tmp;
/* Check for our own values. */
for (unsigned i = 0; i < 0x7f; i++) {
if (mem[i] != 0xff) {
return ttest_fail(&tc, "Data trampled by realloc.");
}
}
/* Free test allocation. */
cyaml__free(config, mem);
return ttest_pass(&tc);
}
/**
* Test cyaml memory functions.
*
* \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_util_strdup(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
ttest_ctx_t tc;
const char *orig = "Hello!";
char *copy;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
/* Create test allocation */
copy = cyaml__strdup(config, orig, NULL);
if (copy == NULL) {
return ttest_fail(&tc, "Memory allocation failed.");
}
/* Confirm string duplication. */
if (strcmp(orig, copy) != 0) {
return ttest_fail(&tc, "String not copied correctly.");
}
/* Free test allocation. */
cyaml__free(config, copy);
return ttest_pass(&tc);
}
/**
* Test cyaml memory functions.
*
* \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_util_strdup_len(
ttest_report_ctx_t *report,
const cyaml_config_t *config)
{
ttest_ctx_t tc;
const char *orig = "Hello!";
char *copy;
size_t len;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
/* Create test allocation */
copy = cyaml__strdup(config, orig, &len);
if (copy == NULL) {
return ttest_fail(&tc, "Memory allocation failed.");
}
/* Confirm string duplication. */
if (strcmp(orig, copy) != 0) {
return ttest_fail(&tc, "String not copied correctly.");
}
/* Confirm string length. */
if (strlen(orig) != len) {
return ttest_fail(&tc, "Bad string length.");
}
/* Free test allocation. */
cyaml__free(config, copy);
return ttest_pass(&tc);
}
/**
* Test invalid state machine state.
*
* \param[in] report The test report context.
* \return true if test passes, false otherwise.
*/
static bool test_util_state_invalid(
ttest_report_ctx_t *report)
{
ttest_ctx_t tc;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
if (strcmp(cyaml__state_to_str(CYAML_STATE__COUNT),
"<invalid>") != 0) {
return ttest_fail(&tc, "Wrong string for invalid state.");
}
if (strcmp(cyaml__state_to_str(CYAML_STATE__COUNT + 1),
"<invalid>") != 0) {
return ttest_fail(&tc, "Wrong string for invalid state.");
}
return ttest_pass(&tc);
}
/**
* Test CYAML_OK error code.
*
* \param[in] report The test report context.
* \return true if test passes, false otherwise.
*/
static bool test_util_err_success_zero(
ttest_report_ctx_t *report)
{
ttest_ctx_t tc;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
if (CYAML_OK != 0) {
return ttest_fail(&tc, "CYAML_OK value not zero");
}
return ttest_pass(&tc);
}
/**
* Test valid cyaml_strerror strings.
*
* \param[in] report The test report context.
* \return true if test passes, false otherwise.
*/
static bool test_util_err_strings_valid(
ttest_report_ctx_t *report)
{
ttest_ctx_t tc;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
if (cyaml_strerror(CYAML_OK) == NULL) {
return ttest_fail(&tc, "CYAML_OK string is NULL");
}
if (strcmp(cyaml_strerror(CYAML_OK), "Success") != 0) {
return ttest_fail(&tc, "CYAML_OK string not 'Success'");
}
for (unsigned i = 1; i <= CYAML_ERR__COUNT; i++) {
if (cyaml_strerror(i) == NULL) {
return ttest_fail(&tc, "Error code %u string is NULL",
i);
}
for (unsigned j = 0; j < i; j++) {
if (strcmp(cyaml_strerror(j), cyaml_strerror(i)) == 0) {
return ttest_fail(&tc, "Two error codes "
"have same string (%u and %u)",
i, j);
}
}
}
return ttest_pass(&tc);
}
/**
* Test invalid cyaml_strerror strings.
*
* \param[in] report The test report context.
* \return true if test passes, false otherwise.
*/
static bool test_util_err_strings_invalid(
ttest_report_ctx_t *report)
{
ttest_ctx_t tc;
if (!ttest_start(report, __func__, NULL, NULL, &tc)) return true;
if (strcmp(cyaml_strerror(CYAML_ERR__COUNT),
"Invalid error code") != 0) {
return ttest_fail(&tc, "CYAML_ERR__COUNT string not "
"'Invalid error code'");
}
if (strcmp(cyaml_strerror(CYAML_ERR__COUNT + 1),
"Invalid error code") != 0) {
return ttest_fail(&tc, "CYAML_ERR__COUNT + 1 string not "
"'Invalid error code'");
}
if (strcmp(cyaml_strerror((cyaml_err_t)-1), "Invalid error code") != 0) {
return ttest_fail(&tc, "-1 string not 'Invalid error code'");
}
return ttest_pass(&tc);
}
/**
* Run the CYAML util 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 util_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_DEFAULT,
};
ttest_heading(rc, "Memory utility functions");
pass &= test_util_strdup(rc, &config);
pass &= test_util_strdup_len(rc, &config);
pass &= test_util_memory_funcs(rc, &config);
ttest_heading(rc, "Error code tests");
pass &= test_util_state_invalid(rc);
pass &= test_util_err_success_zero(rc);
pass &= test_util_err_strings_valid(rc);
pass &= test_util_err_strings_invalid(rc);
return pass;
}