aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2023-05-05 11:09:01 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2023-05-05 11:09:01 +0300
commitb5a989b16cafa8a3b3bc076f1097a0eda6f48c06 (patch)
tree4da744117a5aab37758921fa43b95a3068e5aec1 /library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp
parentfc1cffcfa7f0497a1f97b384a24bcbf23362f3be (diff)
downloadydb-b5a989b16cafa8a3b3bc076f1097a0eda6f48c06.tar.gz
Ydb stable 23-1-2623.1.26
x-stable-origin-commit: 22184a7e157553d447f17a2dffc4ea2d32dfd74d
Diffstat (limited to 'library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp')
-rw-r--r--library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp1838
1 files changed, 1838 insertions, 0 deletions
diff --git a/library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp b/library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp
new file mode 100644
index 0000000000..d5e28cf98e
--- /dev/null
+++ b/library/cpp/yaml/fyamlcpp/libfyaml_ut.cpp
@@ -0,0 +1,1838 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+#include <span>
+
+#include <contrib/libs/libfyaml/include/libfyaml.h>
+#include <library/cpp/testing/unittest/registar.h>
+
+/*
+These tests are ported from https://github.com/pantoniou/libfyaml/blob/master/test/libfyaml-test-core.c
+To check windows compatibility and avoid possible internal patch issues
+*/
+
+Y_UNIT_TEST_SUITE(LibFyamlCore) {
+
+Y_UNIT_TEST(doc_build_simple) {
+ struct fy_document *fyd;
+
+ /* setup */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* cleanup */
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_build_parse_check) {
+ struct fy_document *fyd;
+ char *buf;
+
+ /* build document (with comments, newlines etc) */
+ fyd = fy_document_build_from_string(NULL, "#comment\n[ 42, \n 12 ] # comment\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* convert to string */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString("[42, 12]\n"));
+
+ free(buf);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_build_scalar) {
+ struct fy_document *fyd;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "plain scalar # comment", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_document_root(fyd)), TString("plain scalar"));
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_build_sequence) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int count;
+ void *iter;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "[ 10, 11, foo ] # comment", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* check for correct count value */
+ count = fy_node_sequence_item_count(fy_document_root(fyd));
+ UNIT_ASSERT_EQUAL(count, 3);
+
+ /* try forward iterator first */
+ iter = NULL;
+
+ /* 0 */
+ fyn = fy_node_sequence_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("10"));
+
+ /* 1 */
+ fyn = fy_node_sequence_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("11"));
+
+ /* 2 */
+ fyn = fy_node_sequence_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("foo"));
+
+ /* final, iterator must return NULL */
+ fyn = fy_node_sequence_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_EQUAL(fyn, NULL);
+
+ /* reverse iterator */
+ iter = NULL;
+
+ /* 2 */
+ fyn = fy_node_sequence_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("foo"));
+
+ /* 1 */
+ fyn = fy_node_sequence_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("11"));
+
+ /* 0 */
+ fyn = fy_node_sequence_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("10"));
+
+ /* final, iterator must return NULL */
+ fyn = fy_node_sequence_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_EQUAL(fyn, NULL);
+
+ /* do forward index based accesses */
+
+ /* 0 */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), 0);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("10"));
+
+ /* 1 */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), 1);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("11"));
+
+ /* 2 */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), 2);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("foo"));
+
+ /* 3, it must not exist */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), 3);
+ UNIT_ASSERT_EQUAL(fyn, NULL);
+
+ /* do backward index based accesses */
+
+ /* 2 */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), -1);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("foo"));
+
+ /* 1 */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), -2);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("11"));
+
+ /* 0 */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), -3);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn), TString("10"));
+
+ /* -1, it must not exist */
+ fyn = fy_node_sequence_get_by_index(fy_document_root(fyd), -4);
+ UNIT_ASSERT_EQUAL(fyn, NULL);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_build_mapping) {
+ struct fy_document *fyd;
+ struct fy_node_pair *fynp;
+ int count;
+ void *iter;
+
+ fyd = fy_document_build_from_string(NULL, "{ foo: 10, bar : 20, baz: [100, 101], [frob, 1]: boo }", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* check for correct count value */
+ count = fy_node_mapping_item_count(fy_document_root(fyd));
+ UNIT_ASSERT_EQUAL(count, 4);
+
+ /* forward iterator first */
+ iter = NULL;
+
+ /* 0 */
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_key(fynp)), TString("foo"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), TString("10"));
+
+ /* 1 */
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_key(fynp)), TString("bar"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), TString("20"));
+
+ /* 2 */
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_key(fynp)), TString("baz"));
+ UNIT_ASSERT_EQUAL(fy_node_sequence_item_count(fy_node_pair_value(fynp)), 2);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_value(fynp), 0)), TString("100"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_value(fynp), 1)), TString("101"));
+
+ /* 3 */
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_EQUAL(fy_node_sequence_item_count(fy_node_pair_key(fynp)), 2);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_key(fynp), 0)), TString("frob"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_key(fynp), 1)), TString("1"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), TString("boo"));
+
+ /* 4, it must not exist */
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_EQUAL(fynp, NULL);
+
+ /* reverse iterator */
+ iter = NULL;
+
+ /* 3 */
+ fynp = fy_node_mapping_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_EQUAL(fy_node_sequence_item_count(fy_node_pair_key(fynp)), 2);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_key(fynp), 0)), TString("frob"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_key(fynp), 1)), TString("1"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), TString("boo"));
+
+ /* 2 */
+ fynp = fy_node_mapping_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_key(fynp)), TString("baz"));
+ UNIT_ASSERT_EQUAL(fy_node_sequence_item_count(fy_node_pair_value(fynp)), 2);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_value(fynp), 0)), TString("100"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_sequence_get_by_index(fy_node_pair_value(fynp), 1)), TString("101"));
+
+ /* 1 */
+ fynp = fy_node_mapping_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_key(fynp)), TString("bar"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), TString("20"));
+
+ /* 0 */
+ fynp = fy_node_mapping_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_key(fynp)), TString("foo"));
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), TString("10"));
+
+ /* -1, it must not exist */
+ fynp = fy_node_mapping_reverse_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_EQUAL(fynp, NULL);
+
+ /* key lookups (note how only the contents are compared) */
+ UNIT_ASSERT(fy_node_compare_string(fy_node_mapping_lookup_by_string(fy_document_root(fyd), "foo", FY_NT), "10", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_mapping_lookup_by_string(fy_document_root(fyd), "bar", FY_NT), "20", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_mapping_lookup_by_string(fy_document_root(fyd), "baz", FY_NT), "- 100\n- 101", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_mapping_lookup_by_string(fy_document_root(fyd), "- 'frob'\n- \"\x31\"", FY_NT), "boo", FY_NT) == true);
+
+ fy_document_destroy(fyd);
+ fyd = NULL;
+}
+
+Y_UNIT_TEST(doc_path_access) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "{ "
+ "foo: 10, bar : 20, baz:{ frob: boo }, "
+ "frooz: [ seq1, { key: value} ], \"zero\\0zero\" : 0, "
+ "{ key2: value2 }: { key3: value3 } "
+ "}", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* check that getting root node works */
+ fyn = fy_node_by_path(fy_document_root(fyd), "/", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fy_document_root(fyd));
+
+ /* check access to scalars */
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/foo", FY_NT, FYNWF_DONT_FOLLOW), "10", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "bar", FY_NT, FYNWF_DONT_FOLLOW), "20", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "baz/frob", FY_NT, FYNWF_DONT_FOLLOW), "boo", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/frooz/0", FY_NT, FYNWF_DONT_FOLLOW), "seq1", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/frooz/1/key", FY_NT, FYNWF_DONT_FOLLOW), "value", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "\"zero\\0zero\"", FY_NT, FYNWF_DONT_FOLLOW), "0", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/{ key2: value2 }/key3", FY_NT, FYNWF_DONT_FOLLOW), "value3", FY_NT) == true);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_path_node) {
+ struct fy_document *fyd;
+ char *path;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "{ "
+ "foo: 10, bar : 20, baz:{ frob: boo }, "
+ "frooz: [ seq1, { key: value} ], \"zero\\0zero\" : 0, "
+ "{ key2: value2 }: { key3: value3 } "
+ "}", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ path = fy_node_get_path(fy_node_by_path(fy_document_root(fyd), "/", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("/"));
+ free(path);
+
+ path = fy_node_get_path(fy_node_by_path(fy_document_root(fyd), "/frooz", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("/frooz"));
+ free(path);
+
+ path = fy_node_get_path(fy_node_by_path(fy_document_root(fyd), "/frooz/0", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("/frooz/0"));
+ free(path);
+
+ path = fy_node_get_path(fy_node_by_path(fy_document_root(fyd), "/{ key2: value2 }/key3", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("/{key2: value2}/key3"));
+ free(path);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_path_parent) {
+ struct fy_document *fyd;
+ struct fy_node *fyn_root, *fyn_foo, *fyn_bar, *fyn_baz, *fyn_frob, *fyn_ten;
+ struct fy_node *fyn_deep, *fyn_deeper;
+ char *path;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "{ "
+ "foo: 10, bar : [ ten, 20 ], baz:{ frob: boo, deep: { deeper: yet } }, "
+ "}", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ fyn_foo = fy_node_by_path(fyn_root, "/foo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+
+ fyn_bar = fy_node_by_path(fyn_root, "/bar", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_bar, NULL);
+
+ fyn_baz = fy_node_by_path(fyn_root, "/baz", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_baz, NULL);
+
+ fyn_frob = fy_node_by_path(fyn_root, "/baz/frob", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_frob, NULL);
+
+ fyn_ten = fy_node_by_path(fyn_root, "/bar/0", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_ten, NULL);
+
+ fyn_deep = fy_node_by_path(fyn_root, "/baz/deep", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_deep, NULL);
+
+ fyn_deeper = fy_node_by_path(fyn_root, "/baz/deep/deeper", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_deeper, NULL);
+
+ /* check parent paths of foo, frob, ten */
+ path = fy_node_get_parent_address(fyn_foo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("foo"));
+ free(path);
+
+ path = fy_node_get_parent_address(fyn_frob);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("frob"));
+ free(path);
+
+ path = fy_node_get_parent_address(fyn_ten);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("0"));
+ free(path);
+
+ /* check relative paths to root */
+ path = fy_node_get_path_relative_to(NULL, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("foo"));
+ free(path);
+
+ path = fy_node_get_path_relative_to(fyn_root, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("foo"));
+ free(path);
+
+ path = fy_node_get_path_relative_to(fyn_root, fyn_frob);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("baz/frob"));
+ free(path);
+
+ path = fy_node_get_path_relative_to(fyn_root, fyn_ten);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("bar/0"));
+ free(path);
+
+ /* check relative paths to other parents */
+ path = fy_node_get_path_relative_to(fyn_baz, fyn_frob);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("frob"));
+ free(path);
+
+ path = fy_node_get_path_relative_to(fyn_bar, fyn_ten);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("0"));
+ free(path);
+
+ path = fy_node_get_path_relative_to(fyn_baz, fyn_deeper);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("deep/deeper"));
+ free(path);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_short_path) {
+ struct fy_document *fyd;
+ struct fy_node *fyn_root, *fyn_foo, *fyn_notfoo, *fyn_bar, *fyn_baz;
+ const char *str;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL,
+ "--- &r\n"
+ " foo: &f\n"
+ " bar: [ 0, two, baz: what ]\n"
+ " frob: true\n"
+ " notfoo: false\n"
+ , FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ fyn_foo = fy_node_by_path(fyn_root, "/foo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+
+ fyn_notfoo = fy_node_by_path(fyn_root, "/notfoo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_notfoo, NULL);
+
+ fyn_bar = fy_node_by_path(fyn_root, "/foo/bar", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_bar, NULL);
+
+ fyn_baz = fy_node_by_path(fyn_root, "/foo/bar/2/baz", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_baz, NULL);
+
+ str = fy_node_get_short_path(fyn_root);
+ UNIT_ASSERT_UNEQUAL(str, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(str, "*r");
+ UNIT_ASSERT_EQUAL(fy_node_by_path(fy_document_root(fyd), str, FY_NT, FYNWF_FOLLOW), fyn_root);
+ free((void*)str);
+
+ str = fy_node_get_short_path(fyn_foo);
+ UNIT_ASSERT_UNEQUAL(str, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(str, "*f");
+ UNIT_ASSERT_EQUAL(fy_node_by_path(fy_document_root(fyd), str, FY_NT, FYNWF_FOLLOW), fyn_foo);
+ free((void*)str);
+
+ str = fy_node_get_short_path(fyn_notfoo);
+ UNIT_ASSERT_UNEQUAL(str, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(str, "*r/notfoo");
+ UNIT_ASSERT_EQUAL(fy_node_by_path(fy_document_root(fyd), str, FY_NT, FYNWF_FOLLOW), fyn_notfoo);
+ free((void*)str);
+
+ str = fy_node_get_short_path(fyn_bar);
+ UNIT_ASSERT_UNEQUAL(str, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(str, "*f/bar");
+ UNIT_ASSERT_EQUAL(fy_node_by_path(fy_document_root(fyd), str, FY_NT, FYNWF_FOLLOW), fyn_bar);
+ free((void*)str);
+
+ str = fy_node_get_short_path(fyn_baz);
+ UNIT_ASSERT_UNEQUAL(str, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(str, "*f/bar/2/baz");
+ UNIT_ASSERT_EQUAL(fy_node_by_path(fy_document_root(fyd), str, FY_NT, FYNWF_FOLLOW), fyn_baz);
+ free((void*)str);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_scalar_path) {
+ struct fy_document *fyd;
+ struct fy_node *fyn_root, *fyn_foo;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "--- foo\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ /* get the scalar root and verify */
+ fyn_foo = fy_node_by_path(fyn_root, "/", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fyn_foo), "foo");
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_scalar_path_array) {
+ struct fy_document *fyd;
+ struct fy_node *fyn_root, *fynt;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "--- [ foo, bar, baz ]\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ /* get the scalars in the array and verify */
+ fynt = fy_node_by_path(fyn_root, "/0", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fynt, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fynt), "foo");
+
+ fynt = fy_node_by_path(fyn_root, "/1", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fynt, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fynt), "bar");
+
+ fynt = fy_node_by_path(fyn_root, "/2", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fynt, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fynt), "baz");
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_nearest_anchor) {
+ struct fy_document *fyd;
+ struct fy_node *fyn, *fyn_root, *fyn_foo, *fyn_notfoo, *fyn_bar, *fyn_baz;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL,
+ "--- &r\n"
+ " foo: &f\n"
+ " bar: [ 0, two, baz: what ]\n"
+ " frob: true\n"
+ " notfoo: false\n"
+ , FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ fyn_foo = fy_node_by_path(fyn_root, "/foo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+
+ fyn_notfoo = fy_node_by_path(fyn_root, "/notfoo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_notfoo, NULL);
+
+ fyn_bar = fy_node_by_path(fyn_root, "/foo/bar", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_bar, NULL);
+
+ fyn_baz = fy_node_by_path(fyn_root, "/foo/bar/2/baz", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_baz, NULL);
+
+ /* get nearest anchor of root (is root) */
+ fyn = fy_anchor_node(fy_node_get_nearest_anchor(fyn_root));
+ UNIT_ASSERT_EQUAL(fyn, fyn_root);
+
+ /* get nearest anchor of notfoo (is root) */
+ fyn = fy_anchor_node(fy_node_get_nearest_anchor(fyn_notfoo));
+ UNIT_ASSERT_EQUAL(fyn, fyn_root);
+
+ /* get nearest anchor of baz (is foo) */
+ fyn = fy_anchor_node(fy_node_get_nearest_anchor(fyn_baz));
+ UNIT_ASSERT_EQUAL(fyn, fyn_foo);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_references) {
+ struct fy_document *fyd;
+ struct fy_node *fyn, *fyn_ref, *fyn_root, *fyn_foo, *fyn_notfoo, *fyn_bar, *fyn_baz;
+ char *path;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL,
+ "---\n"
+ " foo: &f\n"
+ " bar: [ 0, two, baz: what ]\n"
+ " frob: true\n"
+ " notfoo: false\n"
+ , FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ fyn_foo = fy_node_by_path(fyn_root, "/foo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+
+ fyn_notfoo = fy_node_by_path(fyn_root, "/notfoo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_notfoo, NULL);
+
+ fyn_bar = fy_node_by_path(fyn_root, "/foo/bar", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_bar, NULL);
+
+ fyn_baz = fy_node_by_path(fyn_root, "/foo/bar/2/baz", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_baz, NULL);
+
+ /* get reference to root */
+ path = fy_node_get_reference(fyn_root);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*/"));
+ free(path);
+
+ /* get reference to /foo */
+ path = fy_node_get_reference(fyn_foo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*f"));
+ free(path);
+
+ /* get reference to /notfoo */
+ path = fy_node_get_reference(fyn_notfoo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*/notfoo"));
+ free(path);
+
+ /* get reference to /foo/bar/2/baz */
+ path = fy_node_get_reference(fyn_baz);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*/foo/bar/2/baz"));
+ free(path);
+
+ /* create reference to root and verify it points there */
+ fyn_ref = fy_node_create_reference(fyn_root);
+ UNIT_ASSERT_UNEQUAL(fyn_ref, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_root);
+ fy_node_free(fyn_ref);
+
+ /* get reference to /foo */
+ fyn_ref = fy_node_create_reference(fyn_foo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_foo);
+ fy_node_free(fyn_ref);
+
+ /* get reference to /notfoo */
+ fyn_ref = fy_node_create_reference(fyn_notfoo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_notfoo);
+ fy_node_free(fyn_ref);
+
+ /* get reference to /bar */
+ fyn_ref = fy_node_create_reference(fyn_bar);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_bar);
+ fy_node_free(fyn_ref);
+
+ /* get reference to /baz */
+ fyn_ref = fy_node_create_reference(fyn_baz);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_baz);
+ fy_node_free(fyn_ref);
+
+ /* get relative reference to /foo starting at / */
+ path = fy_node_get_relative_reference(fyn_root, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*/foo"));
+ free(path);
+
+ /* get relative reference to /foo/bar/2/baz starting at / */
+ path = fy_node_get_relative_reference(fyn_root, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*/foo/bar/2/baz"));
+ free(path);
+
+ /* get relative reference to /foo/bar/2/baz starting at /foo */
+ path = fy_node_get_relative_reference(fyn_foo, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*f/bar/2/baz"));
+ free(path);
+
+ /* get relative reference to /notfoo at /foo (will return absolute) */
+ path = fy_node_get_relative_reference(fyn_foo, fyn_notfoo);
+ UNIT_ASSERT_UNEQUAL(path, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(path, TString("*/notfoo"));
+ free(path);
+
+ /* create relative reference to /foo starting at / */
+ fyn_ref = fy_node_create_relative_reference(fyn_root, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(fyn_ref, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_foo);
+ fy_node_free(fyn_ref);
+
+ /* create relative reference to /foo/bar/2/baz starting at / */
+ fyn_ref = fy_node_create_relative_reference(fyn_root, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(fyn_ref, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_baz);
+ fy_node_free(fyn_ref);
+
+ /* create relative reference to /foo/bar/2/baz starting at /foo */
+ fyn_ref = fy_node_create_relative_reference(fyn_foo, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(fyn_ref, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_baz);
+ fy_node_free(fyn_ref);
+
+ /* create relative reference to /notfoo starting at /foo (will use absolute) */
+ fyn_ref = fy_node_create_relative_reference(fyn_foo, fyn_notfoo);
+ UNIT_ASSERT_UNEQUAL(fyn_ref, NULL);
+ fyn = fy_node_resolve_alias(fyn_ref);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_notfoo);
+ fy_node_free(fyn_ref);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_nearest_child_of) {
+ struct fy_document *fyd;
+ struct fy_node *fyn, *fyn_root, *fyn_foo, *fyn_bar, *fyn_baz;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL,
+ "foo:\n"
+ " bar:\n"
+ " barz: [ zero, baz: true ]\n"
+ " frooz: notfoo\n"
+ , FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ fyn_foo = fy_node_by_path(fyn_root, "/foo", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+
+ fyn_bar = fy_node_by_path(fyn_root, "/foo/bar", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_bar, NULL);
+
+ fyn_baz = fy_node_by_path(fyn_root, "/foo/bar/barz/1/baz", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_baz, NULL);
+
+ /* nearest child to the root of /foo is /foo */
+ fyn = fy_node_get_nearest_child_of(fyn_root, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_foo);
+
+ /* nearest child to the root of /foo/bar/barz/1/baz is /foo */
+ fyn = fy_node_get_nearest_child_of(fyn_root, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_foo);
+
+ /* nearest child to foo of /foo/bar/barz/1/baz is /foo/bar */
+ fyn = fy_node_get_nearest_child_of(fyn_foo, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+ UNIT_ASSERT_EQUAL(fyn, fyn_bar);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_create_empty_seq1) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_build_from_string(fyd, "[ ]", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ /* convert to string */
+ buf = fy_emit_node_to_string(fy_document_root(fyd), FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString("[]"));
+
+ free(buf);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_create_empty_seq2) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ /* convert to string */
+ buf = fy_emit_node_to_string(fy_document_root(fyd), FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString("[]"));
+
+ free(buf);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_create_empty_map1) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_build_from_string(fyd, "{ }", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ /* convert to string */
+ buf = fy_emit_node_to_string(fy_document_root(fyd), FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString("{}"));
+
+ free(buf);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_create_empty_map2) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_mapping(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ /* convert to string */
+ buf = fy_emit_node_to_string(fy_document_root(fyd), FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString("{}"));
+
+ free(buf);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_create_test_seq1) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int ret;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ ret = fy_node_sequence_append(fyn, fy_node_create_scalar(fyd, "foo", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_sequence_append(fyn, fy_node_create_scalar(fyd, "bar", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_sequence_append(fyn, fy_node_build_from_string(fyd, "{ baz: frooz }", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fy_document_set_root(fyd, fyn);
+
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/0", FY_NT, FYNWF_DONT_FOLLOW), "foo", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/1", FY_NT, FYNWF_DONT_FOLLOW), "bar", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/2/baz", FY_NT, FYNWF_DONT_FOLLOW), "frooz", FY_NT) == true);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_create_test_map1) {
+ struct fy_document *fyd;
+ struct fy_node *fyn, *fyn1, *fyn2, *fyn3;
+ int ret;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_mapping(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ ret = fy_node_mapping_append(fyn,
+ fy_node_build_from_string(fyd, "seq", FY_NT),
+ fy_node_build_from_string(fyd, "[ zero, one ]", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_mapping_append(fyn, NULL,
+ fy_node_build_from_string(fyd, "value-of-null-key", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_mapping_append(fyn,
+ fy_node_build_from_string(fyd, "key-of-null-value", FY_NT), NULL);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fy_document_set_root(fyd, fyn);
+
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/seq/0", FY_NT, FYNWF_DONT_FOLLOW), "zero", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/seq/1", FY_NT, FYNWF_DONT_FOLLOW), "one", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/''", FY_NT, FYNWF_DONT_FOLLOW), "value-of-null-key", FY_NT) == true);
+
+ fyn1 = fy_node_by_path(fy_document_root(fyd), "/key-of-null-value", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_EQUAL(fyn1, NULL);
+
+ /* try to append duplicate key (it should fail) */
+ fyn2 = fy_node_build_from_string(fyd, "seq", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn2, NULL);
+ fyn3 = fy_node_create_scalar(fyd, "dupl", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn3, NULL);
+ ret = fy_node_mapping_append(fyn, fyn2, fyn3);
+ UNIT_ASSERT_UNEQUAL(ret, 0);
+
+ fy_node_free(fyn3);
+ fy_node_free(fyn2);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_insert_remove_seq) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int ret;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fy_document_set_root(fyd, fy_node_build_from_string(fyd, "[ one, two, four ]", FY_NT));
+
+ /* check that the order is correct */
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/0", FY_NT, FYNWF_DONT_FOLLOW), "one", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/1", FY_NT, FYNWF_DONT_FOLLOW), "two", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/2", FY_NT, FYNWF_DONT_FOLLOW), "four", FY_NT) == true);
+
+ ret = fy_node_sequence_append(fy_document_root(fyd), fy_node_build_from_string(fyd, "five", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_sequence_prepend(fy_document_root(fyd), fy_node_build_from_string(fyd, "zero", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_sequence_insert_after(fy_document_root(fyd),
+ fy_node_by_path(fy_document_root(fyd), "/2", FY_NT, FYNWF_DONT_FOLLOW),
+ fy_node_build_from_string(fyd, "three", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_node_sequence_insert_before(fy_document_root(fyd),
+ fy_node_by_path(fy_document_root(fyd), "/3", FY_NT, FYNWF_DONT_FOLLOW),
+ fy_node_build_from_string(fyd, "two-and-a-half", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fyn = fy_node_sequence_remove(fy_document_root(fyd),
+ fy_node_by_path(fy_document_root(fyd), "/3", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_node_free(fyn);
+
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/0", FY_NT, FYNWF_DONT_FOLLOW), "zero", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/1", FY_NT, FYNWF_DONT_FOLLOW), "one", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/2", FY_NT, FYNWF_DONT_FOLLOW), "two", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/3", FY_NT, FYNWF_DONT_FOLLOW), "three", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/4", FY_NT, FYNWF_DONT_FOLLOW), "four", FY_NT) == true);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_insert_remove_map) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int ret;
+
+ fyd = fy_document_build_from_string(NULL, "{ one: 1, two: 2, four: 4 }", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* check that the order is correct */
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/one", FY_NT, FYNWF_DONT_FOLLOW), "1", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/two", FY_NT, FYNWF_DONT_FOLLOW), "2", FY_NT) == true);
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/four", FY_NT, FYNWF_DONT_FOLLOW), "4", FY_NT) == true);
+
+ ret = fy_node_mapping_append(fy_document_root(fyd),
+ fy_node_build_from_string(fyd, "three", FY_NT),
+ fy_node_build_from_string(fyd, "3", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/three", FY_NT, FYNWF_DONT_FOLLOW), "3", FY_NT) == true);
+
+ ret = fy_node_mapping_prepend(fy_document_root(fyd),
+ fy_node_build_from_string(fyd, "zero", FY_NT),
+ fy_node_build_from_string(fyd, "0", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/zero", FY_NT, FYNWF_DONT_FOLLOW), "0", FY_NT) == true);
+
+ ret = fy_node_mapping_append(fy_document_root(fyd),
+ fy_node_build_from_string(fyd, "two-and-a-half", FY_NT),
+ fy_node_build_from_string(fyd, "2.5", FY_NT));
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ UNIT_ASSERT(fy_node_compare_string(fy_node_by_path(fy_document_root(fyd), "/two-and-a-half", FY_NT, FYNWF_DONT_FOLLOW), "2.5", FY_NT) == true);
+
+ fyn = fy_node_mapping_remove_by_key(fy_document_root(fyd),
+ fy_node_build_from_string(fyd, "two-and-a-half", FY_NT));
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_node_free(fyn);
+
+ /* it must be removed */
+ fyn = fy_node_by_path(fy_document_root(fyd), "/two-and-a-half", FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_EQUAL(fyn, NULL);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_sort) {
+ struct fy_document *fyd;
+ fy_node_pair *fynp;
+ void *iter;
+ int ret, count;
+
+ fyd = fy_document_build_from_string(NULL, "{ a: 5, { z: bar }: 1, z: 7, "
+ "[ a, b, c] : 3, { a: whee } : 2 , "
+ "b: 6, [ z ]: 4 }", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ ret = fy_node_sort(fy_document_root(fyd), NULL, NULL);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ /* check for correct count value */
+ count = fy_node_mapping_item_count(fy_document_root(fyd));
+ UNIT_ASSERT_EQUAL(count, 7);
+
+ /* forward iterator first */
+ iter = NULL;
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "1");
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "2");
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "3");
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "4");
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "5");
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "6");
+
+ fynp = fy_node_mapping_iterate(fy_document_root(fyd), &iter);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_pair_value(fynp)), "7");
+
+ fy_document_destroy(fyd);
+}
+
+static char *join_docs(const char *tgt_text, const char *tgt_path,
+ const char *src_text, const char *src_path,
+ const char *emit_path)
+{
+ struct fy_document *fyd_tgt, *fyd_src;
+ struct fy_node *fyn_tgt, *fyn_src, *fyn_emit;
+ char *output;
+ int ret;
+
+ /* insert which overwrites root ( <map> <- <scalar> ) */
+ fyd_tgt = fy_document_build_from_string(NULL, tgt_text, FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd_tgt, NULL);
+
+ fyd_src = fy_document_build_from_string(NULL, src_text, FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd_src, NULL);
+
+ fyn_tgt = fy_node_by_path(fy_document_root(fyd_tgt), tgt_path, FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_tgt, NULL);
+
+ fyn_src = fy_node_by_path(fy_document_root(fyd_src), src_path, FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_src, NULL);
+
+ ret = fy_node_insert(fyn_tgt, fyn_src);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ ret = fy_document_set_parent(fyd_tgt, fyd_src);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fyn_emit = fy_node_by_path(fy_document_root(fyd_tgt), emit_path, FY_NT, FYNWF_DONT_FOLLOW);
+ UNIT_ASSERT_UNEQUAL(fyn_emit, NULL);
+
+ output = fy_emit_node_to_string(fyn_emit, (fy_emitter_cfg_flags) (FYECF_MODE_FLOW_ONELINE | FYECF_WIDTH_INF));
+ UNIT_ASSERT_UNEQUAL(output, NULL);
+
+ fy_document_destroy(fyd_tgt);
+
+ return output;
+}
+
+Y_UNIT_TEST(doc_join_scalar_to_scalar) {
+ char *output;
+
+ output = join_docs(
+ "foo", "/", /* target */
+ "bar", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("bar"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_scalar_to_map) {
+ char *output;
+
+ output = join_docs(
+ "{ foo: baz }", "/", /* target */
+ "bar", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("bar"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_scalar_to_seq) {
+ char *output;
+
+ output = join_docs(
+ "[ foo, baz ]", "/", /* target */
+ "bar", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("bar"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_map_to_scalar) {
+ char *output;
+
+ output = join_docs(
+ "foo", "/", /* target */
+ "{bar: baz}", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("{bar: baz}"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_map_to_seq) {
+ char *output;
+
+ output = join_docs(
+ "[foo, frooz]", "/", /* target */
+ "{bar: baz}", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("{bar: baz}"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_map_to_map) {
+ char *output;
+
+ output = join_docs(
+ "{foo: frooz}", "/", /* target */
+ "{bar: baz}", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("{foo: frooz, bar: baz}"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_seq_to_scalar) {
+ char *output;
+
+ output = join_docs(
+ "foo", "/", /* target */
+ "[bar, baz]", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("[bar, baz]"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_seq_to_seq) {
+ char *output;
+
+ output = join_docs(
+ "[foo, frooz]", "/", /* target */
+ "[bar, baz]", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("[foo, frooz, bar, baz]"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_seq_to_map) {
+ char *output;
+
+ output = join_docs(
+ "{foo: frooz}", "/", /* target */
+ "[bar, baz]", "/", /* source */
+ "/"); /* emit path */
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("[bar, baz]"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_join_tags) {
+ char *output;
+
+ output = join_docs(
+ "%TAG !a! tag:a.com,2019:\n"
+ "---\n"
+ "- !a!foo\n"
+ " foo: bar\n", "/",
+ "%TAG !b! tag:b.com,2019:\n"
+ "---\n"
+ "- !b!bar\n"
+ " something: other\n", "/",
+ "/");
+
+ UNIT_ASSERT_VALUES_EQUAL(output, TString("[!a!foo {foo: bar}, !b!bar {something: other}]"));
+ free(output);
+}
+
+Y_UNIT_TEST(doc_build_with_tags) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ struct fy_token *fyt;
+ char *buf;
+ int rc;
+
+ /* build document */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* create a sequence and set it as root */
+ fyn = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+ fyn = NULL;
+
+ /* create a node, containing a new tag */
+ fyn = fy_node_build_from_string(fyd, "%TAG !e! tag:example.com,2000:app/\n---\n- foo\n- !e!foo bar\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ /* append it to the root of the document */
+ rc = fy_node_sequence_append(fy_document_root(fyd), fyn);
+ UNIT_ASSERT_EQUAL(rc, 0);
+ fyn = NULL;
+
+ /* there must be a new tag */
+ fyt = fy_document_tag_directive_lookup(fyd, "!e!");
+ UNIT_ASSERT_UNEQUAL(fyt, NULL);
+
+ /* try to build another, but with a different !e! prefix, it must fail */
+ fyn = fy_node_build_from_string(fyd, "%TAG !e! tag:example.com,2019:app/\n---\n- foo\n- !e!foo bar\n", FY_NT);
+ UNIT_ASSERT_EQUAL(fyn, NULL);
+
+ /* manually add a tag */
+ rc = fy_document_tag_directive_add(fyd, "!f!", "tag:example.com,2019:f/");
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* build a node with a tag that's already in the document */
+ fyn = fy_node_build_from_string(fyd, "!f!whiz frooz\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ /* append it to the root of the document */
+ rc = fy_node_sequence_append(fy_document_root(fyd), fyn);
+ UNIT_ASSERT_EQUAL(rc, 0);
+ fyn = NULL;
+
+ /* convert to string */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ free(buf);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(doc_attach_check) {
+ struct fy_document *fyd;
+ struct fy_node *fyn, *fyn_seq, *fyn_map;
+ struct fy_node *fyn_foo, *fyn_foo2, *fyn_bar, *fyn_baz;
+ struct fy_node_pair *fynp;
+ int rc;
+
+ /* build document */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* create a sequence */
+ fyn_seq = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_seq, NULL);
+
+ /* create a mapping */
+ fyn_map = fy_node_create_mapping(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_map, NULL);
+
+ /* create a simple scalar node foo */
+ fyn_foo = fy_node_build_from_string(fyd, "foo", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn_foo, NULL);
+
+ /* create another simple scalar node bar */
+ fyn_bar = fy_node_build_from_string(fyd, "bar", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn_bar, NULL);
+
+ /* create another simple scalar node baz */
+ fyn_baz = fy_node_build_from_string(fyd, "baz", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn_baz, NULL);
+
+ /* create a scalar node with the same content as foo */
+ fyn_foo2 = fy_node_build_from_string(fyd, "foo", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn_foo2, NULL);
+
+ /* set the root as the sequence */
+ rc = fy_document_set_root(fyd, fyn_seq);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* should fail since fyn_seq is now attached */
+ rc = fy_document_set_root(fyd, fyn_seq);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* freeing should fail, since it's attached too */
+ rc = fy_node_free(fyn_seq);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* append it to the sequence */
+ rc = fy_node_sequence_append(fyn_seq, fyn_foo);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* freeing should fail, since it's attached to the seq */
+ rc = fy_node_free(fyn_foo);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* trying to append it to the sequence again should fail */
+ rc = fy_node_sequence_append(fyn_seq, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* append the mapping to the sequence */
+ rc = fy_node_sequence_append(fyn_seq, fyn_map);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* this should fail, since foo is attached to the sequence */
+ rc = fy_node_mapping_append(fyn_map, fyn_foo, fyn_bar);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* this should be OK, since foo2 is not attached */
+ rc = fy_node_mapping_append(fyn_map, fyn_foo2, fyn_bar);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* remove foo from the sequence */
+ fyn = fy_node_sequence_remove(fyn_seq, fyn_foo);
+ UNIT_ASSERT_EQUAL(fyn, fyn_foo);
+
+ /* trying to append the same key should fail */
+ rc = fy_node_mapping_append(fyn_map, fyn_foo, NULL);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* append the baz: NULL mapping */
+ rc = fy_node_mapping_append(fyn_map, fyn_baz, NULL);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* get the baz: null node pair */
+ fynp = fy_node_mapping_lookup_pair(fyn_map, fyn_baz);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_EQUAL(fy_node_pair_key(fynp), fyn_baz);
+ UNIT_ASSERT_EQUAL(fy_node_pair_value(fynp), NULL);
+
+ /* trying to set the same key in the mapping should fail */
+ rc = fy_node_pair_set_key(fynp, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(rc, 0);
+
+ /* get the foo: bar node pair */
+ fynp = fy_node_mapping_lookup_pair(fyn_map, fyn_foo);
+ UNIT_ASSERT_UNEQUAL(fynp, NULL);
+ UNIT_ASSERT_EQUAL(fy_node_pair_key(fynp), fyn_foo2);
+ UNIT_ASSERT_EQUAL(fy_node_pair_value(fynp), fyn_bar);
+
+ /* we're setting the same key to the mapping, but that's OK
+ * since the key is replaced */
+ rc = fy_node_pair_set_key(fynp, fyn_foo);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* fyn_foo has been freed */
+ fyn_foo = NULL;
+
+ /* convert to string */
+ rc = fy_emit_document_to_fp(fyd, FYECF_MODE_FLOW_ONELINE, stderr);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(manual_scalar_esc) {
+ // FIXME removed \e because it works incorrectly in MS C
+ const std::span MANUAL_SCALAR_ESC = "\\\"\0\a\b\t\v\f\r\xc2\x85\xc2\xa0\xe2\x80\xa8\xe2\x80\xa9";
+ const TStringBuf MANUAL_SCALAR_ESC_TXT = "\"\\\\\\\"\\0\\a\\b\\t\\v\\f\\r\\N\\_\\L\\P\"";
+ const char *what = MANUAL_SCALAR_ESC.data();
+ size_t what_sz = MANUAL_SCALAR_ESC.size() - 1;
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+ const char *buf2;
+ size_t sz2;
+ int rc;
+
+ /* build document */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* create a manual scalar with all the escapes */
+ fyn = fy_node_create_scalar(fyd, what, what_sz);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+ fyn = NULL;
+
+ /* emit to a buffer */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* destroy the old document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ /* verify that the resulting document is in the escaped form */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString(MANUAL_SCALAR_ESC_TXT) + "\n");
+
+ /* now load the result back and verify that it contains exactly the same */
+ fyd = fy_document_build_from_string(NULL, buf, FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* get the scalar content */
+ buf2 = fy_node_get_scalar(fy_document_root(fyd), &sz2);
+ UNIT_ASSERT_UNEQUAL(buf2, NULL);
+
+ /* sizes must match */
+ UNIT_ASSERT_EQUAL(what_sz, sz2);
+
+ /* and the strings too */
+ rc = memcmp(what, buf2, what_sz);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* free the document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ free(buf);
+}
+
+Y_UNIT_TEST(manual_scalar_quoted) {
+ const TStringBuf MANUAL_SCALAR_QUOTED = "&foo";
+ const TStringBuf MANUAL_SCALAR_QUOTED_TXT = "\"&foo\"";
+ const char *what = MANUAL_SCALAR_QUOTED.data();
+ size_t what_sz = MANUAL_SCALAR_QUOTED.length();
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+ const char *buf2;
+ size_t sz2;
+ int rc;
+
+ /* build document */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* create a manual scalar with all the escapes */
+ fyn = fy_node_create_scalar(fyd, what, what_sz);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+ fyn = NULL;
+
+ /* emit to a buffer */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* destroy the old document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ /* verify that the resulting document is in the escaped form */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString(MANUAL_SCALAR_QUOTED_TXT) + "\n");
+
+ /* now load the result back and verify that it contains exactly the same */
+ fyd = fy_document_build_from_string(NULL, buf, FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* get the scalar content */
+ buf2 = fy_node_get_scalar(fy_document_root(fyd), &sz2);
+ UNIT_ASSERT_UNEQUAL(buf2, NULL);
+
+ /* sizes must match */
+ UNIT_ASSERT_EQUAL(what_sz, sz2);
+
+ /* and the strings too */
+ rc = memcmp(what, buf2, what_sz);
+ UNIT_ASSERT_EQUAL(rc, 0);
+
+ /* free the document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ free(buf);
+}
+
+Y_UNIT_TEST(manual_scalar_copy) {
+ const TStringBuf MANUAL_SCALAR_COPY = "foo";
+ const char *what = MANUAL_SCALAR_COPY.data();
+ size_t what_sz = MANUAL_SCALAR_COPY.length();
+ char *what_copy;
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+
+ /* build document */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ what_copy = (char*)malloc(what_sz);
+ UNIT_ASSERT_UNEQUAL(what_copy, NULL);
+ memcpy(what_copy, what, what_sz);
+
+ /* create a manual scalar with all the escapes */
+ fyn = fy_node_create_scalar_copy(fyd, what_copy, what_sz);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ /* free the data */
+ free(what_copy);
+
+ fy_document_set_root(fyd, fyn);
+ fyn = NULL;
+
+ /* emit to a buffer */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* verify that the resulting document is the one we used + '\n' */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString(MANUAL_SCALAR_COPY) + "\n");
+
+ /* destroy the old document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ free(buf);
+
+}
+
+Y_UNIT_TEST(manual_scalarf) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ char *buf;
+
+ /* build document */
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* create a manual scalar using the printf interface */
+ fyn = fy_node_create_scalarf(fyd, "foo%d", 13);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+ fyn = NULL;
+
+ /* emit to a buffer */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* verify that the resulting document is the one we used + '\n' */
+ UNIT_ASSERT_VALUES_EQUAL(buf, TString("foo13\n"));
+
+ /* destroy the old document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ free(buf);
+}
+
+Y_UNIT_TEST(manual_valid_anchor) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int ret;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ fyn = fy_node_create_scalar(fyd, "foo", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ ret = fy_node_sequence_append(fy_document_root(fyd), fyn);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ /* create a valid anchor */
+ ret = fy_node_set_anchor(fyn, "foo", FY_NT);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(manual_invalid_anchor) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int ret;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ fyn = fy_node_create_scalar(fyd, "foo", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ ret = fy_node_sequence_append(fy_document_root(fyd), fyn);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ /* create an invalid anchor */
+ ret = fy_node_set_anchor(fyn, "*foo", FY_NT);
+ UNIT_ASSERT_UNEQUAL(ret, 0);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(manual_anchor_removal) {
+ struct fy_document *fyd;
+ struct fy_node *fyn;
+ int ret;
+
+ fyd = fy_document_create(NULL);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn = fy_node_create_sequence(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ fy_document_set_root(fyd, fyn);
+
+ fyn = fy_node_create_scalar(fyd, "foo", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn, NULL);
+
+ ret = fy_node_sequence_append(fy_document_root(fyd), fyn);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ /* create a valid anchor */
+ ret = fy_node_set_anchor(fyn, "foo", FY_NT);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fprintf(stderr, "---\n# with anchor\n");
+ fy_emit_document_to_fp(fyd, FYECF_MODE_FLOW_ONELINE, stderr);
+
+ /* should fail (an anchor already exists) */
+ ret = fy_node_set_anchor(fyn, "bar", FY_NT);
+ UNIT_ASSERT_UNEQUAL(ret, 0);
+
+ /* should succeed */
+ ret = fy_node_remove_anchor(fyn);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ fprintf(stderr, "---\n# without anchor\n");
+ fy_emit_document_to_fp(fyd, FYECF_MODE_FLOW_ONELINE, stderr);
+
+ fy_document_destroy(fyd);
+}
+
+Y_UNIT_TEST(manual_block_flow_mix) {
+ struct fy_document *fyd;
+ struct fy_node *fyn_mapping, *fyn_key, *fyn_value;
+ char *buf;
+ int ret;
+
+ fyd = fy_document_build_from_string(NULL, "--- &root\n{\n}\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_mapping = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_mapping, NULL);
+
+ UNIT_ASSERT(fy_node_is_mapping(fyn_mapping) == true);
+
+ fyn_key = fy_node_create_scalar(fyd, "key", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn_key, NULL);
+
+ fyn_value = fy_node_build_from_string(fyd, "|\n literal\n", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyn_value, NULL);
+
+ ret = fy_node_mapping_append(fyn_mapping, fyn_key, fyn_value);
+ UNIT_ASSERT_EQUAL(ret, 0);
+
+ /* emit document to buffer */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+
+ /* destroy the first document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ /* read the emitted document back */
+ fyd = fy_document_build_from_string(NULL, buf, FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* compare with expected result */
+ UNIT_ASSERT_VALUES_EQUAL(fy_node_get_scalar0(fy_node_by_path(fy_document_root(fyd), "/key", FY_NT, FYNWF_DONT_FOLLOW)), "literal\n");
+
+ /* destroy the second document */
+ fy_document_destroy(fyd);
+ fyd = NULL;
+
+ free(buf);
+
+}
+
+/* FIXME
+ * This test is disabled because we can't make compatible
+ * alloca-based API on windows because original library
+ * uses gcc inline block extensions it will be uncommented
+ * when new API will be introduced
+ */
+#if false
+Y_UNIT_TEST(alloca_check) {
+ struct fy_document *fyd;
+ char *buf;
+ const char *abuf;
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "{ "
+ "foo: 10, bar : [ ten, 20 ], baz:{ frob: boo, deep: { deeper: yet } }, "
+ "}", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ /* fy_emit_document_to_string*() */
+ buf = fy_emit_document_to_string(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+ abuf = fy_emit_document_to_string_alloca(fyd, FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(abuf, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(buf, abuf);
+ free(buf);
+
+ /* fy_emit_node_to_string*() */
+ buf = fy_emit_node_to_string(fy_node_by_path(fy_document_root(fyd), "/foo", FY_NT, FYNWF_DONT_FOLLOW), FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+ abuf = fy_emit_node_to_string_alloca(fy_node_by_path(fy_document_root(fyd), "/foo", FY_NT, FYNWF_DONT_FOLLOW), FYECF_MODE_FLOW_ONELINE);
+ UNIT_ASSERT_UNEQUAL(abuf, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(buf, abuf);
+ free(buf);
+
+ /* path check eq */
+ buf = fy_node_get_path(fy_node_by_path(fy_document_root(fyd), "/foo", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_UNEQUAL(buf, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(buf, "/foo");
+ abuf = fy_node_get_path_alloca(fy_node_by_path(fy_document_root(fyd), "/foo", FY_NT, FYNWF_DONT_FOLLOW));
+ UNIT_ASSERT_UNEQUAL(abuf, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(abuf, "/foo");
+ UNIT_ASSERT_VALUES_EQUAL(buf, abuf);
+ free(buf);
+
+ /* check that a bad path is "" */
+ abuf = fy_node_get_path_alloca(NULL);
+ UNIT_ASSERT_UNEQUAL(abuf, NULL);
+ UNIT_ASSERT_VALUES_EQUAL(abuf, "");
+
+ fy_document_destroy(fyd);
+
+}
+#endif
+
+Y_UNIT_TEST(scanf_check) {
+ struct fy_document *fyd;
+ struct fy_node *fyn_root;
+ int ret, ival;
+ char sval[256];
+
+ /* build document */
+ fyd = fy_document_build_from_string(NULL, "{ "
+ "foo: 10, bar : 20, baz:{ frob: boo }, "
+ "frooz: [ 1, { key: value }, three ]"
+ "}", FY_NT);
+ UNIT_ASSERT_UNEQUAL(fyd, NULL);
+
+ fyn_root = fy_document_root(fyd);
+ UNIT_ASSERT_UNEQUAL(fyn_root, NULL);
+
+ /* check scanf accesses to scalars */
+ ret = fy_node_scanf(fyn_root, "/foo %d", &ival);
+ UNIT_ASSERT_EQUAL(ret, 1);
+ UNIT_ASSERT_EQUAL(ival, 10);
+
+ ret = fy_node_scanf(fyn_root, "/bar %d", &ival);
+ UNIT_ASSERT_EQUAL(ret, 1);
+ UNIT_ASSERT_EQUAL(ival, 20);
+
+ ret = fy_node_scanf(fyn_root, "/baz/frob %s", sval);
+ UNIT_ASSERT_EQUAL(ret, 1);
+ UNIT_ASSERT_VALUES_EQUAL(sval, "boo");
+
+ ret = fy_node_scanf(fyn_root, "/frooz/0 %d", &ival);
+ UNIT_ASSERT_EQUAL(ret, 1);
+ UNIT_ASSERT_EQUAL(ival, 1);
+
+ ret = fy_node_scanf(fyn_root, "/frooz/1/key %s", sval);
+ UNIT_ASSERT_EQUAL(ret, 1);
+ UNIT_ASSERT_VALUES_EQUAL(sval, "value");
+
+ ret = fy_node_scanf(fyn_root, "/frooz/2 %s", sval);
+ UNIT_ASSERT_EQUAL(ret, 1);
+ UNIT_ASSERT_VALUES_EQUAL(sval, "three");
+
+ fy_document_destroy(fyd);
+}
+
+}