From 3a113fa492a9ff35384b04f3133761241e88e28a Mon Sep 17 00:00:00 2001 From: Alexandros Theodotou Date: Sun, 14 Mar 2021 16:20:26 +0000 Subject: [PATCH] apply float overflow fix from upstream --- Makefile | 7 +- include/cyaml/cyaml.h | 5 +- src/data.h | 10 +- src/load.c | 95 +++++++++++++--- src/util.h | 12 +- test/units/errs.c | 243 +++++++++++++++++++++++++++++++++++++--- test/units/file.c | 1 + test/units/free.c | 1 + test/units/load.c | 255 +++++++++++++++++++++++++++++++++++++++--- test/units/save.c | 53 ++++++--- test/units/test.c | 45 +------- test/units/test.h | 52 +++++++++ test/units/utf8.c | 1 + test/units/util.c | 1 + 14 files changed, 657 insertions(+), 124 deletions(-) create mode 100644 test/units/test.h diff --git a/Makefile b/Makefile index eee229d..488a6b0 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ VERSION_MAJOR = 1 VERSION_MINOR = 1 VERSION_PATCH = 0 -VERSION_DEVEL = 0 +VERSION_DEVEL = 1 VERSION_STR = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) # Default variant depends on whether it's a development build. @@ -56,7 +56,10 @@ LIBYAML_LIBS := $(if $(PKG_CONFIG),$(shell $(PKG_CONFIG) --libs $(LIBYAML)),-lya INCLUDE = -I include CFLAGS += $(INCLUDE) $(VERSION_FLAGS) $(LIBYAML_CFLAGS) -CFLAGS += -std=c11 -Wall -Wextra -pedantic -Wconversion +CFLAGS += -std=c11 -Wall -Wextra -pedantic \ + -Wconversion -Wwrite-strings -Wcast-align -Wpointer-arith \ + -Winit-self -Wshadow -Wstrict-prototypes -Wmissing-prototypes \ + -Wredundant-decls -Wundef -Wvla -Wdeclaration-after-statement LDFLAGS += $(LIBYAML_LIBS) LDFLAGS_SHARED += -Wl,-soname=$(LIB_SH_MAJ) -shared diff --git a/include/cyaml/cyaml.h b/include/cyaml/cyaml.h index 3804fbf..ffe207e 100644 --- a/include/cyaml/cyaml.h +++ b/include/cyaml/cyaml.h @@ -183,7 +183,10 @@ typedef enum cyaml_flag { * * For \ref CYAML_ENUM, the value becomes the value of the enum. * The numerical value is treated as signed. * * For \ref CYAML_FLAGS, the values are bitwise ORed together. - * The numerical values are treated as unsigned, + * The numerical values are treated as unsigned. + * + * For \ref CYAML_FLOAT types, in strict mode floating point values + * that would cause overflow or underflow are not permitted. */ CYAML_FLAG_STRICT = (1 << 4), /** diff --git a/src/data.h b/src/data.h index 17fab32..723d322 100644 --- a/src/data.h +++ b/src/data.h @@ -58,8 +58,9 @@ static inline void cyaml_data_write_pointer( { /* Refuse to build on platforms where sizeof pointer would * lead to \ref CYAML_ERR_INVALID_DATA_SIZE. */ - cyaml_static_assert(sizeof(char *) > 0); - cyaml_static_assert(sizeof(char *) <= sizeof(uint64_t)); + static_assert(sizeof(char *) > 0, "Incompatible pointer size."); + static_assert(sizeof(char *) <= sizeof(uint64_t), + "Incompatible pointer size."); CYAML_UNUSED(cyaml_data_write((uint64_t)ptr, sizeof(ptr), data_target)); @@ -115,8 +116,9 @@ static inline uint8_t * cyaml_data_read_pointer( /* Refuse to build on platforms where sizeof pointer would * lead to \ref CYAML_ERR_INVALID_DATA_SIZE. */ - cyaml_static_assert(sizeof(char *) > 0); - cyaml_static_assert(sizeof(char *) <= sizeof(uint64_t)); + static_assert(sizeof(char *) > 0, "Incompatible pointer size."); + static_assert(sizeof(char *) <= sizeof(uint64_t), + "Incompatible pointer size."); return (void *)cyaml_data_read(sizeof(char *), data, &err); } diff --git a/src/load.c b/src/load.c index e850c84..ec32a3a 100644 --- a/src/load.c +++ b/src/load.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include @@ -639,7 +641,6 @@ static void cyaml__handle_replay( * object. * * \param[in] ctx The CYAML loading context. - * \return \ref CYAML_OK on success, or appropriate error otherwise. */ static void cyaml__delete_yaml_event( cyaml_ctx_t *ctx) @@ -879,17 +880,20 @@ static cyaml_err_t cyaml__mapping_bitfieid_create( cyaml_ctx_t *ctx, cyaml_state_t *state) { - cyaml_bitfield_t *bitfield; unsigned count = state->mapping.fields_count; - size_t size = ((count + CYAML_BITFIELD_BITS - 1) / CYAML_BITFIELD_BITS) - * sizeof(*bitfield); - bitfield = cyaml__alloc(ctx->config, size, true); - if (bitfield == NULL) { - return CYAML_ERR_OOM; - } + if (count != 0) { + cyaml_bitfield_t *bitfield; + size_t size = ((count + CYAML_BITFIELD_BITS - 1) / + CYAML_BITFIELD_BITS) * sizeof(*bitfield); - state->mapping.fields_set = bitfield; + bitfield = cyaml__alloc(ctx->config, size, true); + if (bitfield == NULL) { + return CYAML_ERR_OOM; + } + + state->mapping.fields_set = bitfield; + } return CYAML_OK; } @@ -1312,6 +1316,9 @@ static cyaml_err_t cyaml__read_int( if (end == value || errno == ERANGE || temp < min || temp > max) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: Invalid INT value: '%s'\n", + value); return CYAML_ERR_INVALID_VALUE; } @@ -1321,11 +1328,13 @@ static cyaml_err_t cyaml__read_int( /** * Helper to read a number into a uint64_t. * + * \param[in] ctx The CYAML loading context. * \param[in] value String containing scaler value. * \param[in] out The place to write the value in the output data. * \return \ref CYAML_OK on success, or appropriate error code otherwise. */ static inline cyaml_err_t cyaml__read_uint64_t( + const cyaml_ctx_t *ctx, const char *value, uint64_t *out) { @@ -1336,6 +1345,9 @@ static inline cyaml_err_t cyaml__read_uint64_t( temp = strtoull(value, &end, 0); if (end == value || errno == ERANGE) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: Invalid uint64_t value: '%s'\n", + value); return CYAML_ERR_INVALID_VALUE; } @@ -1368,13 +1380,16 @@ static cyaml_err_t cyaml__read_uint( return CYAML_ERR_INVALID_DATA_SIZE; } - err = cyaml__read_uint64_t(value, &temp); + err = cyaml__read_uint64_t(ctx, value, &temp); if (err != CYAML_OK) { return err; } max = (~(uint64_t)0) >> ((8 - schema->data_size) * 8); if (temp > max) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: Invalid UINT value: '%s'\n", + value); return CYAML_ERR_INVALID_VALUE; } @@ -1398,7 +1413,7 @@ static cyaml_err_t cyaml__read_bool( { bool temp = true; static const char * const false_strings[] = { - "false", "no", "disable", "0", + "false", "no", "off", "disable", "0", }; CYAML_UNUSED(ctx); @@ -1440,11 +1455,14 @@ static cyaml_err_t cyaml__read_enum( if (schema->flags & CYAML_FLAG_STRICT) { cyaml__log(ctx->config, CYAML_LOG_ERROR, - "Load: Invalid enumeration value: %s\n", value); + "Load: Invalid ENUM value: %s\n", value); return CYAML_ERR_INVALID_VALUE; } + cyaml__log(ctx->config, CYAML_LOG_DEBUG, + "Load: Attempt numerical fallback for ENUM: " + "'%s'\n", value); return cyaml__read_int(ctx, schema, value, data); } @@ -1474,8 +1492,31 @@ static cyaml_err_t cyaml__read_float_f( errno = 0; temp = strtof(value, &end); - if (end == value || errno == ERANGE) { + if (end == value) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: Invalid FLOAT value: %s\n", value); return CYAML_ERR_INVALID_VALUE; + + } else if (errno == ERANGE) { + cyaml_log_t level = CYAML_LOG_ERROR; + + if (!cyaml__flag_check_all(schema->flags, CYAML_FLAG_STRICT)) { + level = CYAML_LOG_NOTICE; + } + + if (temp == HUGE_VALF || temp == -HUGE_VALF) { + cyaml__log(ctx->config, level, + "Load: FLOAT overflow: %s\n", value); + + } else { + assert(temp < FLT_MIN || temp > FLT_MAX); + cyaml__log(ctx->config, level, + "Load: FLOAT underflow: %s\n", value); + } + + if (cyaml__flag_check_all(schema->flags, CYAML_FLAG_STRICT)) { + return CYAML_ERR_INVALID_VALUE; + } } memcpy(data, &temp, sizeof(temp)); @@ -1509,8 +1550,24 @@ static cyaml_err_t cyaml__read_float_d( errno = 0; temp = strtod(value, &end); - if (end == value || errno == ERANGE) { + if (end == value) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: Invalid FLOAT value: %s\n", value); return CYAML_ERR_INVALID_VALUE; + + } else if (errno == ERANGE) { + cyaml_log_t level = CYAML_LOG_ERROR; + + if (!cyaml__flag_check_all(schema->flags, CYAML_FLAG_STRICT)) { + level = CYAML_LOG_NOTICE; + } + + cyaml__log(ctx->config, level, + "Load: FLOAT overflow/overflow: %s\n", value); + + if (cyaml__flag_check_all(schema->flags, CYAML_FLAG_STRICT)) { + return CYAML_ERR_INVALID_VALUE; + } } memcpy(data, &temp, sizeof(temp)); @@ -1591,8 +1648,14 @@ static cyaml_err_t cyaml__read_string( if (schema->string.min > schema->string.max) { return CYAML_ERR_BAD_MIN_MAX_SCHEMA; } else if (str_len < schema->string.min) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: STRING length < %"PRIu32": %s\n", + schema->string.min, value); return CYAML_ERR_STRING_LENGTH_MIN; } else if (str_len > schema->string.max) { + cyaml__log(ctx->config, CYAML_LOG_ERROR, + "Load: STRING length > %"PRIu32": %s\n", + schema->string.max, value); return CYAML_ERR_STRING_LENGTH_MAX; } @@ -1818,7 +1881,7 @@ static cyaml_err_t cyaml__set_bitval( switch (cyaml__get_event_type(event)) { case CYAML_EVT_SCALAR: - err = cyaml__read_uint64_t( + err = cyaml__read_uint64_t(ctx, (const char *)event->data.scalar.value, &value); if (err != CYAML_OK) { return err; @@ -2206,7 +2269,7 @@ static cyaml_err_t cyaml__map_key( cyaml_event_t cyaml_event; if (!(ctx->config->flags & CYAML_CFG_IGNORE_UNKNOWN_KEYS)) { - cyaml__log(ctx->config, CYAML_LOG_DEBUG, + cyaml__log(ctx->config, CYAML_LOG_ERROR, "Load: Unexpected key: %s\n", key); return CYAML_ERR_INVALID_KEY; } diff --git a/src/util.h b/src/util.h index f8c80cb..e450bc1 100644 --- a/src/util.h +++ b/src/util.h @@ -15,14 +15,6 @@ #include "cyaml/cyaml.h" #include "utf8.h" -/** Compile time assertion macro. */ -#define cyaml_static_assert(e) \ -{ \ - enum { \ - cyaml_static_assert_check = 1 / (!!(e)) \ - }; \ -} - /** Macro to squash unused variable compiler warnings. */ #define CYAML_UNUSED(_x) ((void)(_x)) @@ -37,7 +29,7 @@ static inline bool cyaml__host_is_little_endian(void) { static const uint16_t test = 1; - return ((uint8_t *) &test)[0] == 1; + return ((const uint8_t *) &test)[0] == 1; } /** @@ -129,7 +121,7 @@ static inline const char * cyaml__type_to_str(cyaml_type_e type) static inline void cyaml__log( const cyaml_config_t *cfg, cyaml_log_t level, - char *fmt, ...) + const char *fmt, ...) { if (level >= cfg->log_level && cfg->log_fn != NULL) { va_list args; diff --git a/test/units/errs.c b/test/units/errs.c index d7615e1..89356f8 100644 --- a/test/units/errs.c +++ b/test/units/errs.c @@ -12,6 +12,7 @@ #include #include "ttest.h" +#include "test.h" /** Macro to squash unused variable compiler warnings. */ #define UNUSED(_x) ((void)(_x)) @@ -243,10 +244,11 @@ static bool test_err_load_null_mem_fn( .schema = NULL, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.mem_fn = NULL; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, NULL, (cyaml_data_t **) NULL, NULL); @@ -294,10 +296,11 @@ static bool test_err_save_null_mem_fn( .config = &cfg, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.mem_fn = NULL; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, &data, 0); if (err != CYAML_ERR_BAD_CONFIG_NULL_MEMFN) { @@ -2445,9 +2448,10 @@ static bool test_err_save_schema_invalid_value_null_ptr( .config = &cfg, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_STYLE_BLOCK; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, CYAML_ARRAY_LEN(data)); @@ -2881,7 +2885,7 @@ static bool test_err_save_schema_bad_bitfield( * \param[in] config The CYAML config to use for the test. * \return true if test passes, false otherwise. */ -static bool test_err_load_schema_invalid_value_float_range( +static bool test_err_load_schema_invalid_value_float_range1( ttest_report_ctx_t *report, const cyaml_config_t *config) { @@ -2891,7 +2895,152 @@ static bool test_err_load_schema_invalid_value_float_range( float a; } *data_tgt = NULL; static const struct cyaml_schema_field mapping_schema[] = { - CYAML_FIELD_FLOAT("a", CYAML_FLAG_DEFAULT, + CYAML_FIELD_FLOAT("a", + CYAML_FLAG_DEFAULT | CYAML_FLAG_STRICT, + struct target_struct, a), + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_ERR_INVALID_VALUE) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt != NULL) { + return ttest_fail(&tc, "Data non-NULL on error."); + } + + return ttest_pass(&tc); +} + +/** + * Test loading when schema expects float but value is out of range. + * + * \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_err_load_schema_invalid_value_float_range2( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + static const unsigned char yaml[] = + "a: -3.5e+38\n"; + struct target_struct { + float a; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_FLOAT("a", + CYAML_FLAG_DEFAULT | CYAML_FLAG_STRICT, + struct target_struct, a), + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_ERR_INVALID_VALUE) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt != NULL) { + return ttest_fail(&tc, "Data non-NULL on error."); + } + + return ttest_pass(&tc); +} + +/** + * Test loading when schema expects float but value is out of range. + * + * \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_err_load_schema_invalid_value_float_range3( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + static const unsigned char yaml[] = + "a: 1.55331e-40f\n"; + struct target_struct { + float a; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_FLOAT("a", + CYAML_FLAG_DEFAULT | CYAML_FLAG_STRICT, + struct target_struct, a), + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_ERR_INVALID_VALUE) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt != NULL) { + return ttest_fail(&tc, "Data non-NULL on error."); + } + + return ttest_pass(&tc); +} + +/** + * Test loading when schema expects float but value is out of range. + * + * \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_err_load_schema_invalid_value_float_range4( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + static const unsigned char yaml[] = + "a: -1.55331e-40f\n"; + struct target_struct { + float a; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_FLOAT("a", + CYAML_FLAG_DEFAULT | CYAML_FLAG_STRICT, struct target_struct, a), CYAML_FIELD_END }; @@ -2975,17 +3124,66 @@ static bool test_err_load_schema_invalid_value_float_invalid( * \param[in] config The CYAML config to use for the test. * \return true if test passes, false otherwise. */ -static bool test_err_load_schema_invalid_value_double_range( +static bool test_err_load_schema_invalid_value_double_range1( ttest_report_ctx_t *report, const cyaml_config_t *config) { static const unsigned char yaml[] = - "a: 1.8e+308\n"; + "a: 1.8e+4999\n"; struct target_struct { double a; } *data_tgt = NULL; static const struct cyaml_schema_field mapping_schema[] = { - CYAML_FIELD_FLOAT("a", CYAML_FLAG_DEFAULT, + CYAML_FIELD_FLOAT("a", + CYAML_FLAG_DEFAULT | CYAML_FLAG_STRICT, + struct target_struct, a), + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_ERR_INVALID_VALUE) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt != NULL) { + return ttest_fail(&tc, "Data non-NULL on error."); + } + + return ttest_pass(&tc); +} + +/** + * Test loading when schema expects double but value is out of range. + * + * \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_err_load_schema_invalid_value_double_range2( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + static const unsigned char yaml[] = + "a: -1.8e+4999\n"; + struct target_struct { + double a; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_FLOAT("a", + CYAML_FLAG_DEFAULT | CYAML_FLAG_STRICT, struct target_struct, a), CYAML_FIELD_END }; @@ -5310,10 +5508,11 @@ static bool test_err_load_flag_value_alias( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5380,10 +5579,11 @@ static bool test_err_load_bitfield_value_alias_1( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5450,10 +5650,11 @@ static bool test_err_load_bitfield_value_alias_2( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5509,10 +5710,11 @@ static bool test_err_load_mapping_key_alias( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5568,10 +5770,11 @@ static bool test_err_load_mapping_value_alias_1( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5624,10 +5827,11 @@ static bool test_err_load_mapping_value_alias_2( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS | CYAML_CFG_IGNORE_UNKNOWN_KEYS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5677,10 +5881,11 @@ static bool test_err_load_mapping_value_alias_3( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_NO_ALIAS; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5898,13 +6103,17 @@ bool errs_tests( pass &= test_err_load_schema_invalid_value_int_range_3(rc, &config); pass &= test_err_load_schema_invalid_value_int_range_4(rc, &config); pass &= test_err_load_schema_invalid_value_int_range_5(rc, &config); - pass &= test_err_load_schema_invalid_value_float_range(rc, &config); - pass &= test_err_load_schema_invalid_value_double_range(rc, &config); pass &= test_err_load_schema_invalid_value_uint_range_1(rc, &config); pass &= test_err_load_schema_invalid_value_uint_range_2(rc, &config); pass &= test_err_load_schema_invalid_value_uint_range_3(rc, &config); pass &= test_err_load_schema_invalid_value_uint_range_4(rc, &config); pass &= test_err_load_schema_invalid_value_uint_range_5(rc, &config); + pass &= test_err_load_schema_invalid_value_float_range1(rc, &config); + pass &= test_err_load_schema_invalid_value_float_range2(rc, &config); + pass &= test_err_load_schema_invalid_value_float_range3(rc, &config); + pass &= test_err_load_schema_invalid_value_float_range4(rc, &config); + pass &= test_err_load_schema_invalid_value_double_range1(rc, &config); + pass &= test_err_load_schema_invalid_value_double_range2(rc, &config); pass &= test_err_load_schema_invalid_value_float_invalid(rc, &config); pass &= test_err_load_schema_invalid_value_double_invalid(rc, &config); diff --git a/test/units/file.c b/test/units/file.c index f5a5919..4f9e4a7 100644 --- a/test/units/file.c +++ b/test/units/file.c @@ -11,6 +11,7 @@ #include #include "ttest.h" +#include "test.h" /** * Unit test context data. diff --git a/test/units/free.c b/test/units/free.c index 9d34eff..9bac03b 100644 --- a/test/units/free.c +++ b/test/units/free.c @@ -11,6 +11,7 @@ #include #include "ttest.h" +#include "test.h" /** Macro to squash unused variable compiler warnings. */ #define UNUSED(_x) ((void)(_x)) diff --git a/test/units/load.c b/test/units/load.c index 48efd19..dfb8cb4 100644 --- a/test/units/load.c +++ b/test/units/load.c @@ -13,6 +13,7 @@ #include "../../src/data.h" #include "ttest.h" +#include "test.h" /** Macro to squash unused variable compiler warnings. */ #define UNUSED(_x) ((void)(_x)) @@ -387,6 +388,56 @@ static bool test_load_mapping_entry_float( return ttest_pass(&tc); } +/** + * Test loading a floating point value as 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_load_mapping_entry_float_underflow( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + float value = 1.55331e-40f; + static const unsigned char yaml[] = + "test_fp: 1.55331e-40\n"; + struct target_struct { + float test_value_fp; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_FLOAT("test_fp", CYAML_FLAG_DEFAULT, + struct target_struct, test_value_fp), + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_OK) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt->test_value_fp != value) { + return ttest_fail(&tc, "Incorrect value: " + "expected: %e, got: %e", + value, data_tgt->test_value_fp); + } + + return ttest_pass(&tc); +} + /** * Test loading a floating point value as a pointer to float. * @@ -487,6 +538,57 @@ static bool test_load_mapping_entry_double( return ttest_pass(&tc); } +/** + * Test loading a floating point value as 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_load_mapping_entry_double_underflow( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + double value = 1.79769e+308; + static const unsigned char yaml[] = + "test_fp: 1.79769e+309\n"; + struct target_struct { + double test_value_fp; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_FLOAT("test_fp", CYAML_FLAG_DEFAULT, + struct target_struct, test_value_fp), + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + value *= 10; + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_OK) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt->test_value_fp != value) { + return ttest_fail(&tc, "Incorrect value: " + "expected: %lf, got: %lf", + value, data_tgt->test_value_fp); + } + + return ttest_pass(&tc); +} + /** * Test loading a floating point value as a pointer to double. * @@ -907,6 +1009,66 @@ static bool test_load_mapping_entry_enum_sparse( return ttest_pass(&tc); } +/** + * Test loading an enumeration with numerical fallback. + * + * \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_load_mapping_entry_enum_fallback( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + enum test_enum { + TEST_ENUM_FIRST = 3, + TEST_ENUM_SECOND = 77, + TEST_ENUM_THIRD = 183, + TEST_ENUM_FOURTH = 9900, + } value = TEST_ENUM_SECOND; + static const cyaml_strval_t strings[] = { + { "first", TEST_ENUM_FIRST }, + { "second", TEST_ENUM_SECOND }, + { "third", TEST_ENUM_THIRD }, + { "fourth", TEST_ENUM_FOURTH }, + }; + static const unsigned char yaml[] = + "test_enum: 77\n"; + struct target_struct { + enum test_enum test_value_enum; + } *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_ENUM("test_enum", CYAML_FLAG_DEFAULT, + struct target_struct, test_value_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), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_OK) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt->test_value_enum != value) { + return ttest_fail(&tc, "Incorrect value"); + } + + return ttest_pass(&tc); +} + /** * Test loading a string to a character array. * @@ -1707,12 +1869,13 @@ static bool test_load_mapping_entry_mapping( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; memset(&value, 0, sizeof(value)); value.a = 123; value.b = 9999; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -1770,12 +1933,13 @@ static bool test_load_mapping_entry_mapping_ptr( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; memset(&value, 0, sizeof(value)); value.a = 123; value.b = 9999; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -2350,6 +2514,7 @@ static bool test_load_mapping_entry_sequence_mapping( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; memset(ref, 0, sizeof(ref)); ref[0].a = 123; @@ -2359,7 +2524,7 @@ static bool test_load_mapping_entry_sequence_mapping( ref[2].a = 1; ref[2].b = 765; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -4865,7 +5030,7 @@ static bool test_load_mapping_with_optional_fields( const cyaml_config_t *config) { long values[] = { 4, 3, 2, 1 }; - struct target_struct { + const struct target_struct { char *a; char b[10]; int c; @@ -4880,12 +5045,12 @@ static bool test_load_mapping_with_optional_fields( long *k; unsigned k_count; } data = { - .a = "Hello", + .a = (char *) "Hello", .b = "World!", .c = 0, .d = { 0, 0, 0, 0 }, .e = values, - .f = "Required!", + .f = (char *) "Required!", .g = NULL, .h = "\0", .i = 9876, @@ -5056,6 +5221,56 @@ static bool test_load_mapping_only_optional_fields( return ttest_pass(&tc); } +/** + * Test loading a mapping with only optional fields. + * + * \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_load_mapping_without_any_fields( + ttest_report_ctx_t *report, + const cyaml_config_t *config) +{ + struct target_struct { + int i; + }; + static const unsigned char yaml[] = + "{}\n"; + struct target_struct *data_tgt = NULL; + static const struct cyaml_schema_field mapping_schema[] = { + CYAML_FIELD_END + }; + static const struct cyaml_schema_value top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, + struct target_struct, mapping_schema), + }; + test_data_t td = { + .data = (cyaml_data_t **) &data_tgt, + .config = config, + .schema = &top_schema, + }; + cyaml_err_t err; + + ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + + err = cyaml_load_data(yaml, YAML_LEN(yaml), config, &top_schema, + (cyaml_data_t **) &data_tgt, NULL); + if (err != CYAML_OK) { + return ttest_fail(&tc, cyaml_strerror(err)); + } + + if (data_tgt == NULL) { + return ttest_fail(&tc, "Should have allocated empty structure"); + } + + if (data_tgt->i != 0) { + return ttest_fail(&tc, "Value should be initialied to 0"); + } + + return ttest_pass(&tc); +} + /** * Test loading a mapping with unknown keys ignored by config. * @@ -5246,9 +5461,10 @@ static bool test_load_no_log( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.log_fn = NULL; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5430,9 +5646,10 @@ static bool test_load_enum_insensitive( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5483,9 +5700,10 @@ static bool test_load_flags_insensitive( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5555,9 +5773,10 @@ static bool test_load_mapping_fields_cfg_insensitive_1( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5639,9 +5858,10 @@ static bool test_load_mapping_fields_cfg_insensitive_2( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5723,9 +5943,10 @@ static bool test_load_mapping_fields_cfg_insensitive_3( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5808,9 +6029,10 @@ static bool test_load_mapping_fields_value_sensitive_1( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -5894,9 +6116,10 @@ static bool test_load_mapping_fields_value_insensitive_1( .schema = &top_schema, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_CASE_INSENSITIVE; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_load_data(yaml, YAML_LEN(yaml), &cfg, &top_schema, (cyaml_data_t **) &data_tgt, NULL); @@ -6569,8 +6792,11 @@ bool load_tests( pass &= test_load_mapping_entry_enum_sparse(rc, &config); pass &= test_load_mapping_entry_ignore_deep(rc, &config); pass &= test_load_mapping_entry_ignore_scalar(rc, &config); + pass &= test_load_mapping_entry_enum_fallback(rc, &config); pass &= test_load_mapping_entry_bool_true_ptr(rc, &config); pass &= test_load_mapping_entry_bool_false_ptr(rc, &config); + pass &= test_load_mapping_entry_float_underflow(rc, &config); + pass &= test_load_mapping_entry_double_underflow(rc, &config); pass &= test_load_mapping_entry_string_ptr_empty(rc, &config); pass &= test_load_mapping_entry_string_ptr_null_str(rc, &config); pass &= test_load_mapping_entry_string_ptr_null_empty(rc, &config); @@ -6642,6 +6868,7 @@ bool load_tests( pass &= test_load_schema_top_level_string(rc, &config); pass &= test_load_schema_top_level_sequence(rc, &config); pass &= test_load_multiple_documents_ignored(rc, &config); + pass &= test_load_mapping_without_any_fields(rc, &config); pass &= test_load_mapping_with_multiple_fields(rc, &config); pass &= test_load_mapping_with_optional_fields(rc, &config); pass &= test_load_mapping_only_optional_fields(rc, &config); diff --git a/test/units/save.c b/test/units/save.c index 7866ac3..4c9b8d5 100644 --- a/test/units/save.c +++ b/test/units/save.c @@ -13,6 +13,7 @@ #include "../../src/data.h" #include "ttest.h" +#include "test.h" /** Macro to squash unused variable compiler warnings. */ #define UNUSED(_x) ((void)(_x)) @@ -1698,11 +1699,12 @@ static bool test_save_mapping_entry_sequence_string( uint32_t seq_count; } data = { .seq = { - "This", - "is", - "merely", - "a", - "test", }, + { '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 = { @@ -1770,11 +1772,11 @@ static bool test_save_mapping_entry_sequence_string_ptr( uint32_t seq_count; } data = { .seq = { - "This", - "is", - "merely", - "a", - "test", }, + (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 = { @@ -3476,7 +3478,7 @@ static bool test_save_sequence_null_values_int( ttest_report_ctx_t *report, const cyaml_config_t *config) { - static const unsigned char ref[] = + static const unsigned char ref1[] = "---\n" "- 7\n" "- 6\n" @@ -3487,6 +3489,18 @@ static bool test_save_sequence_null_values_int( "- \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, }; @@ -3505,9 +3519,10 @@ static bool test_save_sequence_null_values_int( .config = &cfg, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_STYLE_BLOCK; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, CYAML_ARRAY_LEN(data)); @@ -3515,11 +3530,12 @@ static bool test_save_sequence_null_values_int( return ttest_fail(&tc, cyaml_strerror(err)); } - if (len != YAML_LEN(ref) || memcmp(ref, buffer, len) != 0) { + 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(ref), YAML_LEN(ref), ref, + YAML_LEN(ref1), YAML_LEN(ref1), ref1, len, len, buffer); } @@ -3566,9 +3582,10 @@ static bool test_save_sequence_null_str_values_int( .config = &cfg, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_STYLE_BLOCK; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, CYAML_ARRAY_LEN(data)); @@ -3668,9 +3685,10 @@ static bool test_save_sequence_config_flow_style( .config = &cfg, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_STYLE_FLOW; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, 3); if (err != CYAML_OK) { @@ -3721,9 +3739,10 @@ static bool test_save_sequence_config_block_style( .config = &cfg, }; cyaml_err_t err; + ttest_ctx_t tc; cfg.flags |= CYAML_CFG_STYLE_BLOCK; - ttest_ctx_t tc = ttest_start(report, __func__, cyaml_cleanup, &td); + tc = ttest_start(report, __func__, cyaml_cleanup, &td); err = cyaml_save_data(&buffer, &len, &cfg, &top_schema, data, 3); if (err != CYAML_OK) { diff --git a/test/units/test.c b/test/units/test.c index 6cd2718..ec655bb 100644 --- a/test/units/test.c +++ b/test/units/test.c @@ -13,55 +13,14 @@ #include #include "ttest.h" - -/** In load.c */ -extern bool load_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); - -/** In file.c */ -extern bool file_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); - -/** In free.c */ -extern bool free_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); - -/** In utf8.c */ -extern bool utf8_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); - -/** In util.c */ -extern bool util_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); - -/** In errs.c */ -extern bool errs_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); - -/** In save.c */ -extern bool save_tests( - ttest_report_ctx_t *rc, - cyaml_log_t log_level, - cyaml_log_fn_t log_fn); +#include "test.h" /** * Print program usage * * \param[in] prog_name Name of program. */ -void usage(const char *prog_name) +static void usage(const char *prog_name) { fprintf(stderr, "Usage: %s [-q|-v|-d]\n", prog_name); } diff --git a/test/units/test.h b/test/units/test.h new file mode 100644 index 0000000..2445750 --- /dev/null +++ b/test/units/test.h @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (C) 2021 Michael Drake + */ + +#ifndef TEST_H +#define TEST_H + +/** In load.c */ +extern bool load_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +/** In file.c */ +extern bool file_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +/** In free.c */ +extern bool free_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +/** In utf8.c */ +extern bool utf8_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +/** In util.c */ +extern bool util_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +/** In errs.c */ +extern bool errs_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +/** In save.c */ +extern bool save_tests( + ttest_report_ctx_t *rc, + cyaml_log_t log_level, + cyaml_log_fn_t log_fn); + +#endif diff --git a/test/units/utf8.c b/test/units/utf8.c index 2e57d62..b20e455 100644 --- a/test/units/utf8.c +++ b/test/units/utf8.c @@ -13,6 +13,7 @@ #include "../../src/utf8.h" #include "ttest.h" +#include "test.h" /** Helper macro to squash unused variable warnings. */ #define UNUSED(_x) ((void)(_x)) diff --git a/test/units/util.c b/test/units/util.c index b60f904..2221add 100644 --- a/test/units/util.c +++ b/test/units/util.c @@ -15,6 +15,7 @@ #include "../../src/util.h" #include "ttest.h" +#include "test.h" /** * Test cyaml memory functions. -- 2.45.2