1106 lines
36 KiB
C
1106 lines
36 KiB
C
/*
|
|
* test_yaml.c — Tests for foundation/yaml YAML parser.
|
|
*/
|
|
#include "test_framework.h"
|
|
#include "../src/foundation/yaml.h"
|
|
|
|
/* ── Parsing: NULL and empty input ─────────────────────────────── */
|
|
|
|
TEST(yaml_parse_null_input) {
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(NULL, 0);
|
|
ASSERT_NOT_NULL(root); /* returns empty map on NULL */
|
|
ASSERT_FALSE(cbm_yaml_has(root, "anything"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_parse_empty_string) {
|
|
cbm_yaml_node_t *root = cbm_yaml_parse("", 0);
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FALSE(cbm_yaml_has(root, "key"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_parse_negative_len) {
|
|
cbm_yaml_node_t *root = cbm_yaml_parse("key: val", -1);
|
|
ASSERT_NOT_NULL(root);
|
|
/* Negative len treated as empty */
|
|
ASSERT_FALSE(cbm_yaml_has(root, "key"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_free_null) {
|
|
/* Must not crash */
|
|
cbm_yaml_free(NULL);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: single key-value pair ────────────────────────────── */
|
|
|
|
TEST(yaml_single_kv) {
|
|
const char *yaml = "name: hello";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "name"), "hello");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_single_kv_trailing_newline) {
|
|
const char *yaml = "name: hello\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "name"), "hello");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: multiple key-value pairs ─────────────────────────── */
|
|
|
|
TEST(yaml_multiple_kv) {
|
|
const char *yaml =
|
|
"name: myproject\n"
|
|
"version: 1.2.3\n"
|
|
"author: someone\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "name"), "myproject");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "version"), "1.2.3");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "author"), "someone");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: nested maps ──────────────────────────────────────── */
|
|
|
|
TEST(yaml_nested_map_2_levels) {
|
|
const char *yaml =
|
|
"database:\n"
|
|
" host: localhost\n"
|
|
" port: 5432\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "database.host"), "localhost");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "database.port"), "5432");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_nested_map_3_levels) {
|
|
const char *yaml =
|
|
"level1:\n"
|
|
" level2:\n"
|
|
" level3: deep_value\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "level1.level2.level3"), "deep_value");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_nested_siblings) {
|
|
const char *yaml =
|
|
"server:\n"
|
|
" host: 0.0.0.0\n"
|
|
" port: 8080\n"
|
|
"database:\n"
|
|
" host: db.local\n"
|
|
" port: 3306\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "server.host"), "0.0.0.0");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "server.port"), "8080");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "database.host"), "db.local");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "database.port"), "3306");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: string lists ─────────────────────────────────────── */
|
|
|
|
TEST(yaml_string_list) {
|
|
const char *yaml =
|
|
"fruits:\n"
|
|
" - apple\n"
|
|
" - banana\n"
|
|
" - cherry\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *items[8];
|
|
int count = cbm_yaml_get_str_list(root, "fruits", items, 8);
|
|
ASSERT_EQ(count, 3);
|
|
ASSERT_STR_EQ(items[0], "apple");
|
|
ASSERT_STR_EQ(items[1], "banana");
|
|
ASSERT_STR_EQ(items[2], "cherry");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_list_max_out_limit) {
|
|
const char *yaml =
|
|
"items:\n"
|
|
" - a\n"
|
|
" - b\n"
|
|
" - c\n"
|
|
" - d\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *items[2];
|
|
int count = cbm_yaml_get_str_list(root, "items", items, 2);
|
|
ASSERT_EQ(count, 2);
|
|
ASSERT_STR_EQ(items[0], "a");
|
|
ASSERT_STR_EQ(items[1], "b");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: comments ─────────────────────────────────────────── */
|
|
|
|
TEST(yaml_comment_only) {
|
|
const char *yaml =
|
|
"# This is a comment\n"
|
|
"# Another comment\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FALSE(cbm_yaml_has(root, "#"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_inline_comment) {
|
|
const char *yaml = "name: hello # this is a comment\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "name"), "hello");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_comment_between_keys) {
|
|
const char *yaml =
|
|
"a: 1\n"
|
|
"# skip me\n"
|
|
"b: 2\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "a"), "1");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "b"), "2");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: mixed maps and lists ─────────────────────────────── */
|
|
|
|
TEST(yaml_mixed_maps_and_lists) {
|
|
const char *yaml =
|
|
"project:\n"
|
|
" name: myapp\n"
|
|
" tags:\n"
|
|
" - web\n"
|
|
" - api\n"
|
|
" version: 2.0\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "project.name"), "myapp");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "project.version"), "2.0");
|
|
const char *tags[4];
|
|
int count = cbm_yaml_get_str_list(root, "project.tags", tags, 4);
|
|
ASSERT_EQ(count, 2);
|
|
ASSERT_STR_EQ(tags[0], "web");
|
|
ASSERT_STR_EQ(tags[1], "api");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: colons in values ─────────────────────────────────── */
|
|
|
|
TEST(yaml_url_value) {
|
|
/* Only the first colon is the separator */
|
|
const char *yaml = "url: https://example.com:8080/path\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "url"), "https://example.com:8080/path");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_multiple_colons) {
|
|
const char *yaml = "time: 12:30:45\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "time"), "12:30:45");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Parsing: empty values ─────────────────────────────────────── */
|
|
|
|
TEST(yaml_empty_value_becomes_map) {
|
|
/* "key:" with nothing after becomes a map node (if next line isn't "- ...") */
|
|
const char *yaml =
|
|
"parent:\n"
|
|
" child: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_has(root, "parent"));
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "parent.child"), "val");
|
|
/* parent itself is a map, not a scalar */
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "parent"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Query: get_str ────────────────────────────────────────────── */
|
|
|
|
TEST(yaml_get_str_scalar) {
|
|
const char *yaml = "key: value\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "key"), "value");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_missing) {
|
|
const char *yaml = "key: value\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "nonexistent"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_nested) {
|
|
const char *yaml =
|
|
"a:\n"
|
|
" b:\n"
|
|
" c: found\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "a.b.c"), "found");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_on_map_node) {
|
|
/* Querying a map node (not scalar) returns NULL */
|
|
const char *yaml =
|
|
"group:\n"
|
|
" key: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "group"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_null_root) {
|
|
ASSERT_NULL(cbm_yaml_get_str(NULL, "key"));
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_null_path) {
|
|
const char *yaml = "key: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_NULL(cbm_yaml_get_str(root, NULL));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Query: get_float ──────────────────────────────────────────── */
|
|
|
|
TEST(yaml_get_float_valid) {
|
|
const char *yaml = "confidence: 0.85\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "confidence", -1.0), 0.85, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_float_integer) {
|
|
const char *yaml = "count: 42\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "count", -1.0), 42.0, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_float_negative) {
|
|
const char *yaml = "offset: -3.14\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "offset", 0.0), -3.14, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_float_invalid_string) {
|
|
const char *yaml = "val: not_a_number\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "val", 99.0), 99.0, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_float_missing_key) {
|
|
const char *yaml = "a: 1\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "missing", 77.7), 77.7, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_float_zero) {
|
|
const char *yaml = "val: 0.0\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "val", -1.0), 0.0, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Query: get_bool ───────────────────────────────────────────── */
|
|
|
|
TEST(yaml_get_bool_true_false) {
|
|
const char *yaml =
|
|
"enabled: true\n"
|
|
"disabled: false\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "enabled", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "disabled", true));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_bool_yes_no) {
|
|
const char *yaml =
|
|
"feature_a: yes\n"
|
|
"feature_b: no\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "feature_a", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "feature_b", true));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_bool_on_off) {
|
|
const char *yaml =
|
|
"logging: on\n"
|
|
"debug: off\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "logging", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "debug", true));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_bool_1_0) {
|
|
const char *yaml =
|
|
"flag_on: 1\n"
|
|
"flag_off: 0\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "flag_on", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "flag_off", true));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_bool_case_insensitive) {
|
|
const char *yaml =
|
|
"a: TRUE\n"
|
|
"b: False\n"
|
|
"c: YES\n"
|
|
"d: No\n"
|
|
"e: ON\n"
|
|
"f: Off\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "a", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "b", true));
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "c", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "d", true));
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "e", false));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "f", true));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_bool_missing_returns_default) {
|
|
const char *yaml = "a: 1\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "missing", true));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "missing", false));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_bool_unrecognized_returns_default) {
|
|
const char *yaml = "val: maybe\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "val", true));
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "val", false));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Query: get_str_list ───────────────────────────────────────── */
|
|
|
|
TEST(yaml_get_str_list_non_list_path) {
|
|
const char *yaml = "scalar: hello\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *items[4];
|
|
int count = cbm_yaml_get_str_list(root, "scalar", items, 4);
|
|
ASSERT_EQ(count, 0);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_list_missing_path) {
|
|
const char *yaml = "key: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *items[4];
|
|
int count = cbm_yaml_get_str_list(root, "nonexistent", items, 4);
|
|
ASSERT_EQ(count, 0);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_get_str_list_null_root) {
|
|
const char *items[4];
|
|
int count = cbm_yaml_get_str_list(NULL, "key", items, 4);
|
|
ASSERT_EQ(count, 0);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Query: has() ──────────────────────────────────────────────── */
|
|
|
|
TEST(yaml_has_existing) {
|
|
const char *yaml = "key: value\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_has(root, "key"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_has_missing) {
|
|
const char *yaml = "key: value\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_FALSE(cbm_yaml_has(root, "nope"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_has_nested) {
|
|
const char *yaml =
|
|
"a:\n"
|
|
" b: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_TRUE(cbm_yaml_has(root, "a"));
|
|
ASSERT_TRUE(cbm_yaml_has(root, "a.b"));
|
|
ASSERT_FALSE(cbm_yaml_has(root, "a.c"));
|
|
ASSERT_FALSE(cbm_yaml_has(root, "a.b.c"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_has_null_root) {
|
|
ASSERT_FALSE(cbm_yaml_has(NULL, "key"));
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: long values ───────────────────────────────────── */
|
|
|
|
TEST(yaml_long_value) {
|
|
char yaml[1200];
|
|
char expected[1025];
|
|
memset(expected, 'x', 1024);
|
|
expected[1024] = '\0';
|
|
int n = snprintf(yaml, sizeof(yaml), "longkey: %s\n", expected);
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, n);
|
|
ASSERT_NOT_NULL(root);
|
|
const char *val = cbm_yaml_get_str(root, "longkey");
|
|
ASSERT_NOT_NULL(val);
|
|
ASSERT_EQ((int)strlen(val), 1024);
|
|
ASSERT_STR_EQ(val, expected);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: special characters ────────────────────────────── */
|
|
|
|
TEST(yaml_special_chars_in_value) {
|
|
const char *yaml = "pattern: [a-z]+(foo|bar)*\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "pattern"), "[a-z]+(foo|bar)*");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_equals_in_value) {
|
|
const char *yaml = "query: SELECT * FROM t WHERE x=1\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "query"), "SELECT * FROM t WHERE x=1");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: deeply nested (4+ levels) ─────────────────────── */
|
|
|
|
TEST(yaml_deeply_nested) {
|
|
const char *yaml =
|
|
"l1:\n"
|
|
" l2:\n"
|
|
" l3:\n"
|
|
" l4:\n"
|
|
" l5: bottom\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "l1.l2.l3.l4.l5"), "bottom");
|
|
/* Intermediate nodes exist but are not scalars */
|
|
ASSERT_TRUE(cbm_yaml_has(root, "l1.l2.l3.l4"));
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "l1.l2.l3.l4"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: non-existent intermediate path ────────────────── */
|
|
|
|
TEST(yaml_missing_intermediate) {
|
|
const char *yaml = "a: 1\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "x.y.z"));
|
|
ASSERT_FALSE(cbm_yaml_has(root, "x.y.z"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: tab characters ────────────────────────────────── */
|
|
|
|
TEST(yaml_tab_not_indentation) {
|
|
/* Tabs are not treated as indentation by leading_spaces() */
|
|
const char *yaml =
|
|
"key1: val1\n"
|
|
"\tkey2: val2\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "key1"), "val1");
|
|
/* tab-indented line has 0 leading spaces, parsed as top-level */
|
|
/* The key will be "key2" after trim_dup strips the tab from the key */
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: carriage return ───────────────────────────────── */
|
|
|
|
TEST(yaml_crlf_line_endings) {
|
|
const char *yaml = "name: hello\r\nversion: 1.0\r\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "name"), "hello");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "version"), "1.0");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: quoted strings with # ─────────────────────────── */
|
|
|
|
TEST(yaml_quoted_string_with_hash) {
|
|
/* Quoted strings: inline comment stripping is skipped for quoted values */
|
|
const char *yaml = "color: \"#ff0000\"\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *val = cbm_yaml_get_str(root, "color");
|
|
ASSERT_NOT_NULL(val);
|
|
/* Parser preserves quotes in value since it doesn't strip them */
|
|
ASSERT_STR_EQ(val, "\"#ff0000\"");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
TEST(yaml_single_quoted_with_hash) {
|
|
const char *yaml = "regex: '# not a comment'\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *val = cbm_yaml_get_str(root, "regex");
|
|
ASSERT_NOT_NULL(val);
|
|
/* Single-quoted values are also preserved with quotes */
|
|
ASSERT_STR_EQ(val, "'# not a comment'");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: empty lines between content ───────────────────── */
|
|
|
|
TEST(yaml_empty_lines_between_keys) {
|
|
const char *yaml =
|
|
"a: 1\n"
|
|
"\n"
|
|
"\n"
|
|
"b: 2\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "a"), "1");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "b"), "2");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: whitespace-only value ─────────────────────────── */
|
|
|
|
TEST(yaml_whitespace_after_colon) {
|
|
/* "key: " with only spaces after colon -> empty value -> map node */
|
|
const char *yaml = "bare: \n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
/* after_len is 0 after trimming spaces, so this becomes a map/list node */
|
|
ASSERT_TRUE(cbm_yaml_has(root, "bare"));
|
|
/* Not a scalar, so get_str returns NULL */
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "bare"));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: value is just a number ────────────────────────── */
|
|
|
|
TEST(yaml_numeric_string_value) {
|
|
const char *yaml = "port: 8080\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
/* Everything is stored as a string */
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "port"), "8080");
|
|
/* But can be retrieved as float */
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "port", -1.0), 8080.0, 0.001);
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: no trailing newline ───────────────────────────── */
|
|
|
|
TEST(yaml_no_trailing_newline) {
|
|
const char *yaml = "key: value";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "key"), "value");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: line with no colon ────────────────────────────── */
|
|
|
|
TEST(yaml_line_without_colon_skipped) {
|
|
const char *yaml =
|
|
"valid: yes\n"
|
|
"this line has no colon\n"
|
|
"also_valid: sure\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "valid"), "yes");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "also_valid"), "sure");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: hash at start of value (no space before it) ───── */
|
|
|
|
TEST(yaml_hash_no_preceding_space) {
|
|
/* "#" only stripped as inline comment when preceded by space */
|
|
const char *yaml = "channel: #general\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "channel"), "#general");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: list after comment lines ──────────────────────── */
|
|
|
|
TEST(yaml_list_after_comments) {
|
|
const char *yaml =
|
|
"paths:\n"
|
|
" # some paths to exclude\n"
|
|
" - /tmp\n"
|
|
" - /var/log\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *items[4];
|
|
int count = cbm_yaml_get_str_list(root, "paths", items, 4);
|
|
ASSERT_EQ(count, 2);
|
|
ASSERT_STR_EQ(items[0], "/tmp");
|
|
ASSERT_STR_EQ(items[1], "/var/log");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: navigate() path segment > 255 chars ───────────── */
|
|
|
|
TEST(yaml_path_segment_overflow) {
|
|
/* navigate() uses buf[256]; segment >= 256 chars returns NULL */
|
|
char long_path[300];
|
|
memset(long_path, 'a', 260);
|
|
long_path[260] = '\0';
|
|
|
|
const char *yaml = "key: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_NULL(cbm_yaml_get_str(root, long_path));
|
|
ASSERT_FALSE(cbm_yaml_has(root, long_path));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: empty path string ─────────────────────────────── */
|
|
|
|
TEST(yaml_empty_path) {
|
|
const char *yaml = "key: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
/* Empty path -> navigate returns root (seg_len 0 -> NULL) */
|
|
ASSERT_NULL(cbm_yaml_get_str(root, ""));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: path with trailing dot ────────────────────────── */
|
|
|
|
TEST(yaml_path_trailing_dot) {
|
|
const char *yaml =
|
|
"a:\n"
|
|
" b: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
/* "a." -> segment "a", then empty segment -> seg_len 0 -> NULL */
|
|
ASSERT_NULL(cbm_yaml_get_str(root, "a."));
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: duplicate keys ────────────────────────────────── */
|
|
|
|
TEST(yaml_duplicate_keys) {
|
|
/* Parser stores both; find_child returns the first match */
|
|
const char *yaml =
|
|
"key: first\n"
|
|
"key: second\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "key"), "first");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: indentation jump ──────────────────────────────── */
|
|
|
|
TEST(yaml_indentation_dedent) {
|
|
/* After deep nesting, dedent back to top level */
|
|
const char *yaml =
|
|
"outer:\n"
|
|
" inner: deep\n"
|
|
"top: level\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "outer.inner"), "deep");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "top"), "level");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Smoke: real-world .cgrconfig format ───────────────────────── */
|
|
|
|
TEST(yaml_smoke_cgrconfig) {
|
|
const char *yaml =
|
|
"# codebase-memory config\n"
|
|
"mode: fast\n"
|
|
"\n"
|
|
"http_linker:\n"
|
|
" enabled: true\n"
|
|
" min_confidence: 0.7\n"
|
|
" exclude_paths:\n"
|
|
" - /health\n"
|
|
" - /metrics\n"
|
|
" - /internal/debug\n"
|
|
"\n"
|
|
"pipeline:\n"
|
|
" workers: 4\n"
|
|
" verbose: false\n"
|
|
"\n"
|
|
"# End of config\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
|
|
/* Top-level scalar */
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "mode"), "fast");
|
|
|
|
/* Nested bool */
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "http_linker.enabled", false));
|
|
|
|
/* Nested float */
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "http_linker.min_confidence", 0.0), 0.7, 0.001);
|
|
|
|
/* Nested list */
|
|
const char *paths[8];
|
|
int count = cbm_yaml_get_str_list(root, "http_linker.exclude_paths", paths, 8);
|
|
ASSERT_EQ(count, 3);
|
|
ASSERT_STR_EQ(paths[0], "/health");
|
|
ASSERT_STR_EQ(paths[1], "/metrics");
|
|
ASSERT_STR_EQ(paths[2], "/internal/debug");
|
|
|
|
/* Another nested section */
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "pipeline.workers"), "4");
|
|
ASSERT_FALSE(cbm_yaml_get_bool(root, "pipeline.verbose", true));
|
|
|
|
/* Non-existent */
|
|
ASSERT_FALSE(cbm_yaml_has(root, "pipeline.timeout"));
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "pipeline.timeout", 30.0), 30.0, 0.001);
|
|
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Smoke: parse, query many paths, free ──────────────────────── */
|
|
|
|
TEST(yaml_smoke_multi_query) {
|
|
const char *yaml =
|
|
"app:\n"
|
|
" name: testapp\n"
|
|
" debug: yes\n"
|
|
" port: 9090\n"
|
|
" features:\n"
|
|
" - auth\n"
|
|
" - logging\n"
|
|
" db:\n"
|
|
" host: pghost\n"
|
|
" ssl: on\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
|
|
/* Scalars at different depths */
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "app.name"), "testapp");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "app.db.host"), "pghost");
|
|
|
|
/* Bools */
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "app.debug", false));
|
|
ASSERT_TRUE(cbm_yaml_get_bool(root, "app.db.ssl", false));
|
|
|
|
/* Float */
|
|
ASSERT_FLOAT_EQ(cbm_yaml_get_float(root, "app.port", 0.0), 9090.0, 0.001);
|
|
|
|
/* List */
|
|
const char *feats[4];
|
|
int count = cbm_yaml_get_str_list(root, "app.features", feats, 4);
|
|
ASSERT_EQ(count, 2);
|
|
ASSERT_STR_EQ(feats[0], "auth");
|
|
ASSERT_STR_EQ(feats[1], "logging");
|
|
|
|
/* has() checks */
|
|
ASSERT_TRUE(cbm_yaml_has(root, "app"));
|
|
ASSERT_TRUE(cbm_yaml_has(root, "app.features"));
|
|
ASSERT_TRUE(cbm_yaml_has(root, "app.db"));
|
|
ASSERT_FALSE(cbm_yaml_has(root, "app.cache"));
|
|
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: len shorter than string ───────────────────────── */
|
|
|
|
TEST(yaml_partial_len) {
|
|
/* Only parse first 7 bytes: "key: va" */
|
|
const char *yaml = "key: value\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, 7);
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "key"), "va");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: list at top level via map last-child promotion ── */
|
|
|
|
TEST(yaml_top_level_list_items) {
|
|
/* List items after a "key:" become children of that key's list node */
|
|
const char *yaml =
|
|
"colors:\n"
|
|
"- red\n"
|
|
"- green\n"
|
|
"- blue\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
const char *items[4];
|
|
int count = cbm_yaml_get_str_list(root, "colors", items, 4);
|
|
ASSERT_EQ(count, 3);
|
|
ASSERT_STR_EQ(items[0], "red");
|
|
ASSERT_STR_EQ(items[1], "green");
|
|
ASSERT_STR_EQ(items[2], "blue");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: mixed indentation levels (2 vs 4 spaces) ──────── */
|
|
|
|
TEST(yaml_inconsistent_indentation) {
|
|
/* Parser tracks indentation levels via stack, not fixed width */
|
|
const char *yaml =
|
|
"a:\n"
|
|
" b:\n"
|
|
" c: deep\n"
|
|
" d: shallow\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "a.b.c"), "deep");
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "a.d"), "shallow");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: value with leading/trailing whitespace ─────────── */
|
|
|
|
TEST(yaml_value_whitespace_trimmed) {
|
|
const char *yaml = "key: spaced \n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
/* trim_dup trims leading and trailing whitespace */
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "key"), "spaced");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Edge cases: key with leading whitespace at top level ──────── */
|
|
|
|
TEST(yaml_indented_top_level) {
|
|
/* Leading spaces make the parser think it's nested */
|
|
const char *yaml = " indented_key: val\n";
|
|
cbm_yaml_node_t *root = cbm_yaml_parse(yaml, (int)strlen(yaml));
|
|
ASSERT_NOT_NULL(root);
|
|
/* With indent=2, stack pops until parent.indent < 2; root.indent=-1 qualifies */
|
|
ASSERT_STR_EQ(cbm_yaml_get_str(root, "indented_key"), "val");
|
|
cbm_yaml_free(root);
|
|
PASS();
|
|
}
|
|
|
|
/* ── Suite registration ────────────────────────────────────────── */
|
|
|
|
SUITE(yaml) {
|
|
/* Parsing: NULL / empty */
|
|
RUN_TEST(yaml_parse_null_input);
|
|
RUN_TEST(yaml_parse_empty_string);
|
|
RUN_TEST(yaml_parse_negative_len);
|
|
RUN_TEST(yaml_free_null);
|
|
|
|
/* Parsing: key-value */
|
|
RUN_TEST(yaml_single_kv);
|
|
RUN_TEST(yaml_single_kv_trailing_newline);
|
|
RUN_TEST(yaml_multiple_kv);
|
|
|
|
/* Parsing: nested maps */
|
|
RUN_TEST(yaml_nested_map_2_levels);
|
|
RUN_TEST(yaml_nested_map_3_levels);
|
|
RUN_TEST(yaml_nested_siblings);
|
|
|
|
/* Parsing: lists */
|
|
RUN_TEST(yaml_string_list);
|
|
RUN_TEST(yaml_list_max_out_limit);
|
|
|
|
/* Parsing: comments */
|
|
RUN_TEST(yaml_comment_only);
|
|
RUN_TEST(yaml_inline_comment);
|
|
RUN_TEST(yaml_comment_between_keys);
|
|
|
|
/* Parsing: mixed */
|
|
RUN_TEST(yaml_mixed_maps_and_lists);
|
|
|
|
/* Parsing: colons */
|
|
RUN_TEST(yaml_url_value);
|
|
RUN_TEST(yaml_multiple_colons);
|
|
|
|
/* Parsing: empty values */
|
|
RUN_TEST(yaml_empty_value_becomes_map);
|
|
|
|
/* Query: get_str */
|
|
RUN_TEST(yaml_get_str_scalar);
|
|
RUN_TEST(yaml_get_str_missing);
|
|
RUN_TEST(yaml_get_str_nested);
|
|
RUN_TEST(yaml_get_str_on_map_node);
|
|
RUN_TEST(yaml_get_str_null_root);
|
|
RUN_TEST(yaml_get_str_null_path);
|
|
|
|
/* Query: get_float */
|
|
RUN_TEST(yaml_get_float_valid);
|
|
RUN_TEST(yaml_get_float_integer);
|
|
RUN_TEST(yaml_get_float_negative);
|
|
RUN_TEST(yaml_get_float_invalid_string);
|
|
RUN_TEST(yaml_get_float_missing_key);
|
|
RUN_TEST(yaml_get_float_zero);
|
|
|
|
/* Query: get_bool */
|
|
RUN_TEST(yaml_get_bool_true_false);
|
|
RUN_TEST(yaml_get_bool_yes_no);
|
|
RUN_TEST(yaml_get_bool_on_off);
|
|
RUN_TEST(yaml_get_bool_1_0);
|
|
RUN_TEST(yaml_get_bool_case_insensitive);
|
|
RUN_TEST(yaml_get_bool_missing_returns_default);
|
|
RUN_TEST(yaml_get_bool_unrecognized_returns_default);
|
|
|
|
/* Query: get_str_list */
|
|
RUN_TEST(yaml_get_str_list_non_list_path);
|
|
RUN_TEST(yaml_get_str_list_missing_path);
|
|
RUN_TEST(yaml_get_str_list_null_root);
|
|
|
|
/* Query: has() */
|
|
RUN_TEST(yaml_has_existing);
|
|
RUN_TEST(yaml_has_missing);
|
|
RUN_TEST(yaml_has_nested);
|
|
RUN_TEST(yaml_has_null_root);
|
|
|
|
/* Edge cases */
|
|
RUN_TEST(yaml_long_value);
|
|
RUN_TEST(yaml_special_chars_in_value);
|
|
RUN_TEST(yaml_equals_in_value);
|
|
RUN_TEST(yaml_deeply_nested);
|
|
RUN_TEST(yaml_missing_intermediate);
|
|
RUN_TEST(yaml_tab_not_indentation);
|
|
RUN_TEST(yaml_crlf_line_endings);
|
|
RUN_TEST(yaml_quoted_string_with_hash);
|
|
RUN_TEST(yaml_single_quoted_with_hash);
|
|
RUN_TEST(yaml_empty_lines_between_keys);
|
|
RUN_TEST(yaml_whitespace_after_colon);
|
|
RUN_TEST(yaml_numeric_string_value);
|
|
RUN_TEST(yaml_no_trailing_newline);
|
|
RUN_TEST(yaml_line_without_colon_skipped);
|
|
RUN_TEST(yaml_hash_no_preceding_space);
|
|
RUN_TEST(yaml_list_after_comments);
|
|
RUN_TEST(yaml_path_segment_overflow);
|
|
RUN_TEST(yaml_empty_path);
|
|
RUN_TEST(yaml_path_trailing_dot);
|
|
RUN_TEST(yaml_duplicate_keys);
|
|
RUN_TEST(yaml_indentation_dedent);
|
|
RUN_TEST(yaml_partial_len);
|
|
RUN_TEST(yaml_top_level_list_items);
|
|
RUN_TEST(yaml_inconsistent_indentation);
|
|
RUN_TEST(yaml_value_whitespace_trimmed);
|
|
RUN_TEST(yaml_indented_top_level);
|
|
|
|
/* Smoke tests */
|
|
RUN_TEST(yaml_smoke_cgrconfig);
|
|
RUN_TEST(yaml_smoke_multi_query);
|
|
}
|