static void test_same(void **state) { struct state *st = (*state); const char *xml = "<nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\">" "<enable-nacm>true</enable-nacm>" "<read-default>permit</read-default>" "<write-default>deny</write-default>" "<exec-default>permit</exec-default>" "<enable-external-groups>true</enable-external-groups>" "</nacm><df xmlns=\"urn:libyang:tests:defaults\">" "<foo>42</foo><b1_1>42</b1_1>" "</df><hidden xmlns=\"urn:libyang:tests:defaults\">" "<foo>42</foo><baz>42</baz></hidden>"; struct lyd_difflist *diff; assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_END); lyd_free_diff(diff); }
static void test_move1(void **state) { struct state *st = (*state); const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">" "<llist>1</llist>" "<llist>2</llist>" "</df>"; const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\">" "<llist>2</llist>" "<llist>1</llist>" "</df>"; char *str; struct lyd_difflist *diff; assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_MOVEDAFTER1); assert_ptr_not_equal(diff->first[0], NULL); assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/llist[.='1']"); free(str); assert_ptr_not_equal(diff->second[0], NULL); assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/llist[.='2']"); free(str); assert_int_equal(diff->type[1], LYD_DIFF_END); lyd_free_diff(diff); }
static void test_parse_print_oookeys_xml(void **state) { struct state *st = (*state); const char *xmlin = "<cont1 xmlns=\"urn:all\">" "<leaf3>-1</leaf3>" "<list1><leaf18>aaa</leaf18></list1>" "<list1><leaf19>123</leaf19><leaf18>bbb</leaf18></list1>" "</cont1>"; const char *xmlout = "<cont1 xmlns=\"urn:all\">" "<leaf3>-1</leaf3>" "<list1><leaf18>aaa</leaf18></list1>" "<list1><leaf18>bbb</leaf18><leaf19>123</leaf19></list1>" "</cont1>"; st->dt = NULL; /* with strict parsing, it is error since the key is not encoded as the first child */ st->dt = lyd_parse_mem(st->ctx, xmlin, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_STRICT); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_vecode, LYVE_INORDER); assert_string_equal(ly_errmsg(), "Invalid position of the key \"leaf18\" in a list \"list1\"."); /* without strict, it produces only warning, but the data are correctly loaded */ st->dt = lyd_parse_mem(st->ctx, xmlin, LYD_XML, LYD_OPT_CONFIG); assert_ptr_not_equal(st->dt, NULL); assert_int_equal(lyd_print_mem(&st->str1, st->dt, LYD_XML, 0), 0); assert_string_equal(st->str1, xmlout); }
static void test_empty3(void **state) { struct state *st = (*state); const char *xml = "<df xmlns=\"urn:libyang:tests:defaults\"><foo>42</foo></df>"; struct lyd_difflist *diff; assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(NULL, NULL, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_END); lyd_free_diff(diff); assert_ptr_equal((diff = lyd_diff(NULL, st->first->child, 0)), NULL); assert_int_equal(ly_errno, LY_EINVAL); assert_ptr_not_equal((diff = lyd_diff(st->first->child, NULL, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_DELETED); assert_ptr_equal(diff->first[0], st->first->child); assert_ptr_equal(diff->second[0], NULL); assert_int_equal(diff->type[1], LYD_DIFF_END); lyd_free_diff(diff); }
static void test_empty2(void **state) { struct state *st = (*state); const char *xml = "<df xmlns=\"urn:libyang:tests:defaults\">" "<foo>42</foo><b1_1>42</b1_1>" "</df><hidden xmlns=\"urn:libyang:tests:defaults\">" "<foo>42</foo><baz>42</baz></hidden>"; struct lyd_difflist *diff; assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(st->first, NULL, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_DELETED); assert_ptr_equal(diff->first[0], st->first); assert_ptr_equal(diff->second[0], NULL); assert_int_equal(diff->type[1], LYD_DIFF_DELETED); assert_ptr_equal(diff->first[1], st->first->next); assert_ptr_equal(diff->second[1], NULL); assert_int_equal(diff->type[2], LYD_DIFF_END); lyd_free_diff(diff); }
static void test_status(void **state) { struct state *st = (*state); const char *xml_min = "<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">" "<module-set-id>5</module-set-id>" "</modules-state><nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\">" "<denied-operations>0</denied-operations>" "<denied-data-writes>0</denied-data-writes>" "<denied-notifications>0</denied-notifications>" "</nacm>"; const char *xml = "<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">" "<module-set-id>5</module-set-id>" "</modules-state><nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\">" "<denied-operations>0</denied-operations>" "<denied-data-writes>0</denied-data-writes>" "<denied-notifications>0</denied-notifications>" "</nacm><df xmlns=\"urn:libyang:tests:defaults\">" "<b1_status>42</b1_status>" "</df><hidden xmlns=\"urn:libyang:tests:defaults\">" "<papa>42</papa></hidden>"; assert_ptr_not_equal((st->dt = lyd_parse_mem(st->ctx, xml_min, LYD_XML, LYD_OPT_DATA | LYD_WD_EXPLICIT)), NULL); assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_DATA, st->ctx), 0); assert_ptr_not_equal(st->dt, NULL); assert_int_equal(lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS), 0); assert_ptr_not_equal(st->xml, NULL); assert_string_equal(st->xml, xml); }
static void test_diff2(void **state) { struct state *st = (*state); const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">" "<list><name>a</name><value>1</value></list>" "<list><name>b</name><value>2</value></list>" "</df>"; const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\">" "<list><name>b</name><value>-2</value></list>" "<list><name>c</name><value>3</value></list>" "</df>"; char *str; struct lyd_difflist *diff; assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_CHANGED); assert_ptr_not_equal(diff->first[0], NULL); assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/list[name=\'b\']/value"); free(str); assert_ptr_not_equal(diff->second[0], NULL); assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/list[name=\'b\']/value"); free(str); assert_int_equal(diff->type[1], LYD_DIFF_DELETED); assert_ptr_not_equal(diff->first[1], NULL); assert_string_equal((str = lyd_path(diff->first[1])), "/defaults:df/list[name=\'a\']"); free(str); assert_ptr_equal(diff->second[1], NULL); assert_int_equal(diff->type[2], LYD_DIFF_CREATED); assert_ptr_not_equal(diff->first[2], NULL); assert_string_equal((str = lyd_path(diff->first[2])), "/defaults:df"); free(str); assert_ptr_not_equal(diff->second[2], NULL); assert_string_equal((str = lyd_path(diff->second[2])), "/defaults:df/list[name=\'c\']"); free(str); assert_int_equal(diff->type[3], LYD_DIFF_END); lyd_free_diff(diff); }
static int setup_f(void **state) { struct state *st; const char *augschema = "ietf-ip"; const char *typeschema = "iana-if-type"; const char *ietfdir = TESTS_DIR"/schema/yin/ietf/"; const struct lys_module *mod; (*state) = st = calloc(1, sizeof *st); if (!st) { fprintf(stderr, "Memory allocation error.\n"); return -1; } /* libyang context */ st->ctx = ly_ctx_new(ietfdir); if (!st->ctx) { fprintf(stderr, "Failed to create context.\n"); goto error; } /* schema */ mod = ly_ctx_load_module(st->ctx, augschema, NULL); if (!mod) { fprintf(stderr, "Failed to load data module \"%s\".\n", augschema); goto error; } lys_features_enable(mod, "*"); mod = ly_ctx_get_module(st->ctx, "ietf-interfaces", NULL); if (!mod) { fprintf(stderr, "Failed to get data module \"ietf-interfaces\".\n"); goto error; } lys_features_enable(mod, "*"); mod = ly_ctx_load_module(st->ctx, typeschema, NULL); if (!mod) { fprintf(stderr, "Failed to load data module \"%s\".\n", typeschema); goto error; } /* data */ st->dt = lyd_parse_mem(st->ctx, data, LYD_XML, LYD_OPT_CONFIG); if (!st->dt) { fprintf(stderr, "Failed to build the data tree.\n"); goto error; } return 0; error: ly_ctx_destroy(st->ctx, NULL); free(st); (*state) = NULL; return -1; }
static void test_diff1(void **state) { struct state *st = (*state); const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">" "<foo>42</foo>" "</df><hidden xmlns=\"urn:libyang:tests:defaults\">" "<foo>42</foo><baz>42</baz></hidden>"; const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\">" "<foo>41</foo><b1_1>42</b1_1>" "</df>"; char *str; struct lyd_difflist *diff; assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_CHANGED); assert_ptr_not_equal(diff->first[0], NULL); assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/foo"); free(str); assert_ptr_not_equal(diff->second[0], NULL); assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/foo"); free(str); assert_int_equal(diff->type[1], LYD_DIFF_DELETED); assert_ptr_not_equal(diff->first[1], NULL); assert_string_equal((str = lyd_path(diff->first[1])), "/defaults:hidden"); free(str); assert_ptr_equal(diff->second[1], NULL); assert_int_equal(diff->type[2], LYD_DIFF_CREATED); assert_ptr_not_equal(diff->first[2], NULL); assert_string_equal((str = lyd_path(diff->first[2])), "/defaults:df"); free(str); assert_ptr_not_equal(diff->second[2], NULL); assert_string_equal((str = lyd_path(diff->second[2])), "/defaults:df/b1_1"); free(str); assert_int_equal(diff->type[3], LYD_DIFF_END); lyd_free_diff(diff); }
static void test_wd1(void **state) { struct state *st = (*state); const char *xml = "<df xmlns=\"urn:libyang:tests:defaults\">" "<foo>41</foo><dllist>4</dllist>" "</df>"; char *str; struct lyd_difflist *diff; st->first = NULL; lyd_validate(&st->first, LYD_OPT_CONFIG, st->ctx); assert_ptr_not_equal(st->first, NULL); assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_CONFIG)), NULL); assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, LYD_DIFFOPT_WITHDEFAULTS)), NULL); assert_ptr_not_equal(diff->type, NULL); assert_int_equal(diff->type[0], LYD_DIFF_CHANGED); assert_ptr_not_equal(diff->first[0], NULL); assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/foo"); assert_int_equal(((struct lyd_node_leaf_list*)diff->first[0])->value.int32, 42); free(str); assert_ptr_not_equal(diff->second[0], NULL); assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/foo"); assert_int_equal(((struct lyd_node_leaf_list*)diff->second[0])->value.int32, 41); free(str); assert_int_equal(diff->type[1], LYD_DIFF_DELETED); assert_ptr_not_equal(diff->first[1], NULL); assert_string_equal((str = lyd_path(diff->first[1])), "/defaults:df/dllist[.='1']"); free(str); assert_ptr_equal(diff->second[1], NULL); assert_int_equal(diff->type[2], LYD_DIFF_DELETED); assert_ptr_not_equal(diff->first[2], NULL); assert_string_equal((str = lyd_path(diff->first[2])), "/defaults:df/dllist[.='2']"); free(str); assert_ptr_equal(diff->second[2], NULL); assert_int_equal(diff->type[3], LYD_DIFF_DELETED); assert_ptr_not_equal(diff->first[3], NULL); assert_string_equal((str = lyd_path(diff->first[3])), "/defaults:df/dllist[.='3']"); free(str); assert_ptr_equal(diff->second[3], NULL); assert_int_equal(diff->type[4], LYD_DIFF_CREATED); assert_ptr_not_equal(diff->first[4], NULL); assert_string_equal((str = lyd_path(diff->first[4])), "/defaults:df"); free(str); assert_ptr_not_equal(diff->second[4], NULL); assert_string_equal((str = lyd_path(diff->second[4])), "/defaults:df/dllist[.='4']"); free(str); assert_int_equal(diff->type[5], LYD_DIFF_END); lyd_free_diff(diff); }
static void test_dup_to_ctx_leafrefs(void **state) { struct state *st = (*state); const struct lys_module *mod; const char *sch = "module x {" " namespace urn:x;" " prefix x;" " container x {" " leaf a { type string; }" " leaf b { type leafref { path ../a; } } } }"; const char *data = "<x xmlns=\"urn:x\"><b>hello</b><a>hello</a></x>"; char *printed = NULL; mod = lys_parse_mem(st->ctx1, sch, LYS_IN_YANG); assert_ptr_not_equal(mod, NULL); mod = lys_parse_mem(st->ctx2, sch, LYS_IN_YANG); assert_ptr_not_equal(mod, NULL); st->dt1 = lyd_parse_mem(st->ctx1, data, LYD_XML, LYD_OPT_CONFIG); assert_ptr_not_equal(st->dt1, NULL); st->dt2 = lyd_dup_to_ctx(st->dt1, 1, st->ctx2); assert_ptr_not_equal(st->dt2, NULL); /* the result is not valid - the leafref is not resolved */ assert_int_not_equal(((struct lyd_node_leaf_list *)st->dt2->child)->value_type, LY_TYPE_LEAFREF); assert_int_equal(lyd_validate(&st->dt2, LYD_OPT_CONFIG, st->ctx2), 0); assert_ptr_equal(((struct lyd_node_leaf_list *)st->dt2->child)->value_type, LY_TYPE_LEAFREF); /* the values are the same, but they are stored in different contexts */ assert_string_equal(((struct lyd_node_leaf_list *)st->dt1->child)->value_str, ((struct lyd_node_leaf_list *)st->dt2->child)->value_str); assert_ptr_not_equal(((struct lyd_node_leaf_list *)st->dt1->child)->value_str, ((struct lyd_node_leaf_list *)st->dt2->child)->value_str); /* check the value data */ assert_ptr_not_equal(((struct lyd_node_leaf_list *)st->dt1->child)->value.leafref, ((struct lyd_node_leaf_list *)st->dt2->child)->value.leafref); /* and the schema nodes are the same, but comes from a different contexts */ assert_int_equal(st->dt1->child->schema->nodetype, st->dt2->child->schema->nodetype); assert_string_equal(st->dt1->child->schema->name, st->dt2->child->schema->name); assert_string_equal(st->dt1->child->schema->module->name, st->dt2->child->schema->module->name); assert_ptr_equal(st->dt1->child->schema->module->ctx, st->ctx1); assert_ptr_equal(st->dt2->child->schema->module->ctx, st->ctx2); /* valgrind test - remove the first context and the access the duplicated data * supposed to be in the second context */ lyd_free(st->dt1); ly_ctx_destroy(st->ctx1, NULL); st->dt1 = NULL; st->ctx1 = NULL; lyd_print_mem(&printed, st->dt2, LYD_XML, 0); assert_string_equal(printed, data); free(printed); }
static void test_dup_to_ctx_bits(void **state) { struct state *st = (*state); const struct lys_module *mod; const char *sch = "module x {" " namespace urn:x;" " prefix x;" " typedef mybits { type bits {" " bit disable;" " bit enable; } }" " leaf x { type mybits; }}"; const char *data = "<x xmlns=\"urn:x\">enable</x>"; char *printed = NULL; mod = lys_parse_mem(st->ctx1, sch, LYS_IN_YANG); assert_ptr_not_equal(mod, NULL); mod = lys_parse_mem(st->ctx2, sch, LYS_IN_YANG); assert_ptr_not_equal(mod, NULL); st->dt1 = lyd_parse_mem(st->ctx1, data, LYD_XML, LYD_OPT_CONFIG); assert_ptr_not_equal(st->dt1, NULL); st->dt2 = lyd_dup_to_ctx(st->dt1, 1, st->ctx2); assert_ptr_not_equal(st->dt2, NULL); /* the values are the same, but they are stored in different contexts */ assert_string_equal(((struct lyd_node_leaf_list *)st->dt1)->value_str, ((struct lyd_node_leaf_list *)st->dt2)->value_str); assert_ptr_not_equal(((struct lyd_node_leaf_list *)st->dt1)->value_str, ((struct lyd_node_leaf_list *)st->dt2)->value_str); /* check the value data */ assert_ptr_not_equal(((struct lyd_node_leaf_list *)st->dt1)->value.bit, ((struct lyd_node_leaf_list *)st->dt2)->value.bit); assert_ptr_not_equal(((struct lyd_node_leaf_list *)st->dt1)->value.bit[1], ((struct lyd_node_leaf_list *)st->dt2)->value.bit[1]); /* first bit is not set, so the value pointer is NULL in both cases */ assert_ptr_equal(((struct lyd_node_leaf_list *)st->dt1)->value.bit[0], NULL); assert_ptr_equal(((struct lyd_node_leaf_list *)st->dt2)->value.bit[0], NULL); /* and the schema nodes are the same, but comes from a different contexts */ assert_int_equal(st->dt1->schema->nodetype, st->dt2->schema->nodetype); assert_string_equal(st->dt1->schema->name, st->dt2->schema->name); assert_string_equal(st->dt1->schema->module->name, st->dt2->schema->module->name); assert_ptr_equal(st->dt1->schema->module->ctx, st->ctx1); assert_ptr_equal(st->dt2->schema->module->ctx, st->ctx2); /* valgrind test - remove the first context and the access the duplicated data * supposed to be in the second context */ lyd_free(st->dt1); ly_ctx_destroy(st->ctx1, NULL); st->dt1 = NULL; st->ctx1 = NULL; lyd_print_mem(&printed, st->dt2, LYD_XML, 0); assert_string_equal(printed, data); free(printed); }
static void test_parse_print_oookeys_json(void **state) { struct state *st = (*state); const char *in = "{\"all:cont1\":{\"leaf3\":-1,\"list1\":[{\"leaf18\":\"a\"},{\"leaf19\":123,\"leaf18\":\"b\"}]}}"; const char *out = "{\"all:cont1\":{\"leaf3\":-1,\"list1\":[{\"leaf18\":\"a\"},{\"leaf18\":\"b\",\"leaf19\":123}]}}"; st->dt = NULL; /* in JSON, ordering does not matter, so it will succeed even with strict */ st->dt = lyd_parse_mem(st->ctx, in, LYD_JSON, LYD_OPT_CONFIG | LYD_OPT_STRICT); assert_ptr_not_equal(st->dt, NULL); assert_int_equal(lyd_print_mem(&st->str1, st->dt, LYD_JSON, 0), 0); assert_string_equal(st->str1, out); }
static void test_dup_to_ctx(void **state) { struct state *st = (*state); const struct lys_module *mod; const char *sch = "module x {" " namespace urn:x;" " prefix x;" " leaf x { type string; }}"; const char *data = "<x xmlns=\"urn:x\">hello</x>"; /* case 1 - schema is only in the first context, duplicating data into the second context is supposed to * fail because of missing schema */ mod = lys_parse_mem(st->ctx1, sch, LYS_IN_YANG); assert_ptr_not_equal(mod, NULL); st->dt1 = lyd_parse_mem(st->ctx1, data, LYD_XML, LYD_OPT_CONFIG); assert_ptr_not_equal(st->dt1, NULL); st->dt2 = lyd_dup_to_ctx(st->dt1, 1, st->ctx2); assert_ptr_equal(st->dt2, NULL); assert_int_equal(ly_errno, LY_EINVAL); assert_string_equal(ly_errmsg(st->ctx2), "Target context does not contain schema node for the data node being duplicated (x:x)."); /* case 2 - with the schema present in both contexts, duplication should succeed */ mod = lys_parse_mem(st->ctx2, sch, LYS_IN_YANG); assert_ptr_not_equal(mod, NULL); st->dt2 = lyd_dup_to_ctx(st->dt1, 1, st->ctx2); assert_ptr_not_equal(st->dt2, NULL); /* the values are the same, but they are stored in different contexts */ assert_string_equal(((struct lyd_node_leaf_list *)st->dt1)->value_str, ((struct lyd_node_leaf_list *)st->dt2)->value_str); assert_ptr_not_equal(((struct lyd_node_leaf_list *)st->dt1)->value_str, ((struct lyd_node_leaf_list *)st->dt2)->value_str); /* and the schema nodes are the same, but comes from a different contexts */ assert_int_equal(st->dt1->schema->nodetype, st->dt2->schema->nodetype); assert_string_equal(st->dt1->schema->name, st->dt2->schema->name); assert_string_equal(st->dt1->schema->module->name, st->dt2->schema->module->name); assert_ptr_equal(st->dt1->schema->module->ctx, st->ctx1); assert_ptr_equal(st->dt2->schema->module->ctx, st->ctx2); }
static void test_mandatory(void **state) { struct state *st = (*state); const char miss_leaf1[] = "<top xmlns=\"urn:libyang:tests:mandatory\"/>" "<topleaf xmlns=\"urn:libyang:tests:mandatory\"/>"; const char few_llist1[] = "<top xmlns=\"urn:libyang:tests:mandatory\"><leaf1>a</leaf1></top>"; const char many_llist1[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1>" "<llist1>1</llist1><llist1>2</llist1><llist1>3</llist1>" "<llist1>4</llist1><llist1>5</llist1><llist1>6</llist1>" "</top>"; const char miss_leaf2[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1><llist1>1</llist1><llist1>2</llist1>" "</top>"; const char miss_choice2[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1><llist1>1</llist1><llist1>2</llist1>" "<cont1><cont2><cont3><leaf2>5</leaf2></cont3></cont2></cont1>" "<leaf3>b</leaf3>" "</top>"; const char miss_leaf6[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1><llist1>1</llist1><llist1>2</llist1>" "<cont1><cont2><cont3><leaf2>5</leaf2></cont3></cont2></cont1>" "</top>"; const char miss_leaf7[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1><llist1>1</llist1><llist1>2</llist1>" "<cont1><cont2><cont3><leaf2>5</leaf2></cont3></cont2></cont1>" "<leaf3>c</leaf3><leaf5>d</leaf5><leaf6/>" "</top>"; const char miss_topleaf[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1><llist1>1</llist1><llist1>2</llist1>" "<cont1><cont2><cont3><leaf2>5</leaf2></cont3></cont2></cont1>" "<leaf3>c</leaf3><leaf5>d</leaf5><leaf6/><leaf7/>" "</top>"; const char valid[] = "<top xmlns=\"urn:libyang:tests:mandatory\">" "<leaf1>a</leaf1><llist1>1</llist1><llist1>2</llist1>" "<cont1><cont2><cont3><leaf2>5</leaf2></cont3></cont2></cont1>" "<leaf3>c</leaf3><leaf5>d</leaf5><leaf6/><leaf7/>" "</top><topleaf xmlns=\"urn:libyang:tests:mandatory\"/>"; st->dt = lyd_parse_mem(st->ctx, miss_leaf1, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_MISSELEM); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top"); st->dt = lyd_parse_mem(st->ctx, few_llist1, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_NOMIN); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top"); st->dt = lyd_parse_mem(st->ctx, many_llist1, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_NOMAX); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top/llist1[.='6']"); st->dt = lyd_parse_mem(st->ctx, miss_leaf2, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_MISSELEM); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top/cont1/cont2/cont3"); st->dt = lyd_parse_mem(st->ctx, miss_choice2, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_NOMANDCHOICE); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top"); st->dt = lyd_parse_mem(st->ctx, miss_leaf6, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_MISSELEM); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top"); st->dt = lyd_parse_mem(st->ctx, miss_leaf7, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_MISSELEM); assert_string_equal(ly_errpath(st->ctx), "/mandatory:top"); st->dt = lyd_parse_mem(st->ctx, miss_topleaf, LYD_XML, LYD_OPT_CONFIG); assert_ptr_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_MISSELEM); assert_string_equal(ly_errpath(st->ctx), "/"); st->dt = lyd_parse_mem(st->ctx, valid, LYD_XML, LYD_OPT_CONFIG); assert_ptr_not_equal(st->dt, NULL); assert_int_equal(ly_errno, LY_SUCCESS); }
static void test_status_yin(void **state) { struct state *st = (*state); const char *yin = "<module name=\"status\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">" "<namespace uri=\"urn:status\"/>" "<prefix value=\"st\"/>" "<grouping name=\"g\">" " <leaf name=\"gl1\">" " <type name=\"string\"/>" " <mandatory value=\"true\"/>" " </leaf>" " <leaf name=\"gl2\">" " <type name=\"string\"/>" " <status value=\"deprecated\"/>" " </leaf>" " <leaf name=\"gl3\">" " <type name=\"string\"/>" " <status value=\"obsolete\"/>" " </leaf>" "</grouping>" "<container name=\"a\">" " <status value=\"deprecated\"/>" " <leaf name=\"l\">" " <type name=\"string\"/>" " <mandatory value=\"true\"/>" " </leaf>" " <uses name=\"g\"/>" "</container>" "<container name=\"b\">" " <status value=\"deprecated\"/>" " <leaf name=\"l\">" " <status value=\"obsolete\"/>" " <mandatory value=\"true\"/>" " <type name=\"string\"/>" " </leaf>" "</container>" "<container name=\"c\">" " <status value=\"obsolete\"/>" " <leaf name=\"l\">" " <mandatory value=\"true\"/>" " <type name=\"string\"/>" " </leaf>" " <uses name=\"g\"/>" "</container>" "</module>"; const char *xml1 = "<a xmlns=\"urn:status\"><gl2>x</gl2><gl3>y</gl3></a>"; const char *xml2 = "<c xmlns=\"urn:status\"><gl2>x</gl2><gl3>y</gl3></c>"; const char *yin_fail1 = "<module name=\"status\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">" "<namespace uri=\"urn:status\"/>" "<prefix value=\"st\"/>" "<container name=\"c\">" " <status value=\"deprecated\"/>" " <leaf name=\"l\">" " <status value=\"current\"/>" " <type name=\"string\"/>" " </leaf>" "</container>" "</module>"; const char *yin_fail2 = "<module name=\"status\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">" "<namespace uri=\"urn:status\"/>" "<prefix value=\"st\"/>" "<container name=\"c\">" " <status value=\"obsolete\"/>" " <leaf name=\"l\">" " <status value=\"current\"/>" " <type name=\"string\"/>" " </leaf>" "</container>" "</module>"; const char *yin_fail3 = "<module name=\"status\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">" "<namespace uri=\"urn:status\"/>" "<prefix value=\"st\"/>" "<container name=\"c\">" " <status value=\"obsolete\"/>" " <leaf name=\"l\">" " <status value=\"deprecated\"/>" " <type name=\"string\"/>" " </leaf>" "</container>" "</module>"; /* deprecated nodes cannot be in obsolete data (obsolete is stronger) */ assert_ptr_equal(NULL, lys_parse_mem(st->ctx, yin_fail3, LYS_IN_YIN)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_INSTATUS); /* current nodes cannot be in obsolete data (obsolete is stronger) */ assert_ptr_equal(NULL, lys_parse_mem(st->ctx, yin_fail2, LYS_IN_YIN)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_INSTATUS); /* current nodes cannot be in deprecated data (deprecated is stronger) */ assert_ptr_equal(NULL, lys_parse_mem(st->ctx, yin_fail1, LYS_IN_YIN)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_INSTATUS); /* status is inherited so all the mandatory statements should be ignored and empty data tree is fine */ assert_ptr_not_equal(NULL, lys_parse_mem(st->ctx, yin, LYS_IN_YIN)); assert_int_equal(0, lyd_validate(&st->dt, LYD_OPT_CONFIG, st->ctx)); /* xml1 - deprecated is applied to gl1, so it is not mandatory, * gl2 is deprecated so it can appear in data, * but gl3 is obsolete (not changed) so it cannot appear */ assert_ptr_equal(NULL, lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_OBSOLETE)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_OBSDATA); assert_string_equal(ly_errpath(st->ctx), "/status:a/gl3"); /* xml2 - obsolete is applied to gl1, so it is not mandatory, * gl2 is obsolete so it cannot appear in data and here the error should raise, * gl3 is obsolete (not changed) so it cannot appear */ assert_ptr_equal(NULL, lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_OBSOLETE)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_OBSDATA); assert_string_equal(ly_errpath(st->ctx), "/status:c/gl2"); }
static void test_status_yang(void **state) { struct state *st = (*state); const char *yang = "module status {" " namespace urn:status;" " prefix st;" " grouping g {" " leaf gl1 {" " type string;" " mandatory true;" " }" " leaf gl2 {" " type string;" " status deprecated;" " }" " leaf gl3 {" " type string;" " status obsolete;" " }" " }" " container a {" " status deprecated;" " leaf l {" " type string;" " mandatory true;" " }" " uses g;" " }" " container b {" " status deprecated;" " leaf l {" " status obsolete;" " type string;" " mandatory true;" " }" " }" " container c {" " status obsolete;" " leaf l {" " type string;" " mandatory true;" " }" " uses g;" " }" "}"; const char *xml1 = "<a xmlns=\"urn:status\"><gl2>x</gl2><gl3>y</gl3></a>"; const char *xml2 = "<c xmlns=\"urn:status\"><gl2>x</gl2><gl3>y</gl3></c>"; const char *yang_fail1 = "module status {" " namespace urn:status;" " prefix st;" " container c {" " status deprecated;" " leaf l {" " status current;" " type string;" " }" " }" "}"; const char *yang_fail2 = "module status {" " namespace urn:status;" " prefix st;" " container c {" " status obsolete;" " leaf l {" " status current;" " type string;" " }" " }" "}"; const char *yang_fail3 = "module status {" " namespace urn:status;" " prefix st;" " container c {" " status obsolete;" " leaf l {" " status deprecated;" " type string;" " }" " }" "}"; /* deprecated nodes cannot be in obsolete data (obsolete is stronger) */ assert_ptr_equal(NULL, lys_parse_mem(st->ctx, yang_fail3, LYS_IN_YANG)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_INSTATUS); /* current nodes cannot be in obsolete data (obsolete is stronger) */ assert_ptr_equal(NULL, lys_parse_mem(st->ctx, yang_fail2, LYS_IN_YANG)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_INSTATUS); /* current nodes cannot be in deprecated data (deprecated is stronger) */ assert_ptr_equal(NULL, lys_parse_mem(st->ctx, yang_fail1, LYS_IN_YANG)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_INSTATUS); /* status is inherited so all the mandatory statements should be ignored and empty data tree is fine */ assert_ptr_not_equal(NULL, lys_parse_mem(st->ctx, yang, LYS_IN_YANG)); assert_int_equal(0, lyd_validate(&st->dt, LYD_OPT_CONFIG, st->ctx)); /* xml1 - deprecated is applied to gl1, so it is not mandatory, * gl2 is deprecated so it can appear in data, * but gl3 is obsolete (not changed) so it cannot appear */ assert_ptr_equal(NULL, lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_OBSOLETE)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_OBSDATA); assert_string_equal(ly_errpath(st->ctx), "/status:a/gl3"); /* xml2 - obsolete is applied to gl1, so it is not mandatory, * gl2 is obsolete so it cannot appear in data and here the error should raise, * gl3 is obsolete (not changed) so it cannot appear */ assert_ptr_equal(NULL, lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_OBSOLETE)); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode(st->ctx), LYVE_OBSDATA); assert_string_equal(ly_errpath(st->ctx), "/status:c/gl2"); }
/** * @brief Import content of the specified datastore for the given module from a file * referenced by the descriptor 'fd_in' */ static int srcfg_import_datastore(struct ly_ctx *ly_ctx, int fd_in, const char *module_name, srcfg_datastore_t datastore, LYD_FORMAT format, bool permanent) { int rc = SR_ERR_INTERNAL; unsigned i = 0; struct lyd_node *new_data_tree = NULL; struct lyd_node *current_data_tree = NULL; struct lyd_difflist *diff = NULL; char *first_xpath = NULL, *second_xpath = NULL; char *input_data = NULL; int ret = 0; struct stat info; CHECK_NULL_ARG2(ly_ctx, module_name); /* parse input data */ ret = fstat(fd_in, &info); CHECK_NOT_MINUS1_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup, "Unable to obtain input file info: %s.", sr_strerror_safe(errno)); ly_errno = LY_SUCCESS; if (S_ISREG(info.st_mode)) { /* load (using mmap) and parse the input data in one step */ new_data_tree = lyd_parse_fd(ly_ctx, fd_in, format, LYD_OPT_STRICT | LYD_OPT_CONFIG); } else { /* most likely STDIN */ /* load input data into the memory first */ ret = srcfg_read_file_content(fd_in, &input_data); CHECK_RC_MSG_GOTO(ret, cleanup, "Unable to read the input data."); /* parse the input data stored inside memory buffer */ new_data_tree = lyd_parse_mem(ly_ctx, input_data, format, LYD_OPT_STRICT | LYD_OPT_CONFIG); } if (NULL == new_data_tree && LY_SUCCESS != ly_errno) { SR_LOG_ERR("Unable to parse the input data: %s", ly_errmsg()); goto cleanup; } /* validate input data */ if (NULL != new_data_tree) { ret = lyd_validate(&new_data_tree, LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_WD_IMPL_TAG); CHECK_ZERO_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup, "Input data are not valid: %s", ly_errmsg()); } /* remove default nodes */ lyd_wd_cleanup(&new_data_tree, 0); /* get data tree of currently stored configuration */ rc = srcfg_get_module_data(ly_ctx, module_name, ¤t_data_tree); if (SR_ERR_OK != rc) { goto cleanup; } /* get the list of changes made by the user */ diff = lyd_diff(current_data_tree, new_data_tree, 0); if (NULL == diff) { SR_LOG_ERR("Unable to get the list of changes: %s", ly_errmsg()); goto cleanup; } /* iterate over the list of differences and for each issue corresponding Sysrepo command(s) */ while (diff->type && LYD_DIFF_END != diff->type[i]) { if (NULL != diff->first[i]) { first_xpath = lyd_path(diff->first[i]); if (NULL == first_xpath) { SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg()); goto cleanup; } } if (NULL != diff->second[i]) { second_xpath = lyd_path(diff->second[i]); if (NULL == second_xpath) { free(first_xpath); first_xpath = NULL; SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg()); goto cleanup; } } switch (diff->type[i]) { case LYD_DIFF_DELETED: SR_LOG_DBG("<LYD_DIFF_DELETED> node: %s", first_xpath); rc = srcfg_convert_lydiff_deleted(first_xpath); break; case LYD_DIFF_CHANGED: SR_LOG_DBG("<LYD_DIFF_CHANGED> orig: %s, new: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_changed(first_xpath, diff->second[i]); break; case LYD_DIFF_MOVEDAFTER1: SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER1> moved: %s, after: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_movedafter(first_xpath, second_xpath); break; case LYD_DIFF_CREATED: SR_LOG_DBG("<LYD_DIFF_CREATED> parent: %s, new node: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_created(diff->second[i]); break; case LYD_DIFF_MOVEDAFTER2: SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER2> after: %s, this new node was inserted: %s", first_xpath, second_xpath); rc = srcfg_convert_lydiff_movedafter(second_xpath, first_xpath); break; default: assert(0 && "not reachable"); } free(first_xpath); free(second_xpath); first_xpath = second_xpath = NULL; if (SR_ERR_OK != rc) { goto cleanup; } ++i; } if (0 == i) { SR_LOG_DBG_MSG("No changes were made."); } else { /* commit the changes */ rc = sr_commit(srcfg_session); if (SR_ERR_OK != rc) { SR_LOG_ERR("Error returned from sr_commit: %s.", sr_strerror(rc)); goto cleanup; } if (SRCFG_STORE_RUNNING == datastore && permanent) { /* copy running datastore data into the startup datastore */ rc = sr_copy_config(srcfg_session, module_name, SR_DS_RUNNING, SR_DS_STARTUP); if (SR_ERR_OK != rc) { SR_LOG_ERR("Error returned from sr_copy_config: %s.", sr_strerror(rc)); goto cleanup; } } } rc = SR_ERR_OK; cleanup: if (NULL != diff) { lyd_free_diff(diff); } if (NULL != current_data_tree) { lyd_free_withsiblings(current_data_tree); } if (NULL != new_data_tree) { lyd_free_withsiblings(new_data_tree); } if (input_data) { free(input_data); } return rc; }
static void test_parse_noncharacters_xml(void **state) { struct state *st; const char* mod = "module x {namespace urn:x; prefix x; leaf x { type string;}}"; const char* data = "<x xmlns=\"urn:x\">----------</x>"; assert_ptr_not_equal(((*state) = st = calloc(1, sizeof *st)), NULL); assert_ptr_not_equal((st->ctx = ly_ctx_new(NULL)), NULL); /* test detection of invalid characters according to RFC 7950, sec 9.4 */ assert_ptr_not_equal(lys_parse_mem(st->ctx, mod, LYS_IN_YANG), 0); assert_ptr_not_equal((st->str1 = strdup(data)), NULL); /* exclude surrogate blocks 0xD800-DFFF - trying 0xd800 */ st->str1[17] = 0xed; st->str1[18] = 0xa0; st->str1[19] = 0x80; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INCHAR); assert_string_equal(ly_errmsg(), "Invalid UTF-8 value 0x0000d800"); /* exclude noncharacters %xFDD0-FDEF - trying 0xfdd0 */ st->str1[17] = 0xef; st->str1[18] = 0xb7; st->str1[19] = 0x90; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INCHAR); assert_string_equal(ly_errmsg(), "Invalid UTF-8 value 0x0000fdd0"); /* exclude noncharacters %xFFFE-FFFF - trying 0xfffe */ st->str1[17] = 0xef; st->str1[18] = 0xbf; st->str1[19] = 0xbe; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INCHAR); assert_string_equal(ly_errmsg(), "Invalid UTF-8 value 0x0000fffe"); /* exclude c0 control characters except tab, carriage return and line feed */ st->str1[17] = 0x9; /* valid - horizontal tab */ st->str1[18] = 0xa; /* valid - new line */ st->str1[19] = 0xd; /* valid - carriage return */ st->str1[20] = 0x6; /* invalid - ack */ assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INCHAR); assert_string_equal(ly_errmsg(), "Invalid UTF-8 value 0x06"); /* exclude noncharacters %x?FFFE-?FFFF - trying 0x10ffff */ st->str1[17] = 0xf4; st->str1[18] = 0x8f; st->str1[19] = 0xbf; st->str1[20] = 0xbf; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INCHAR); assert_string_equal(ly_errmsg(), "Invalid UTF-8 value 0x0010ffff"); /* 0x6 */ st->str1[17] = '&'; st->str1[18] = '#'; st->str1[19] = 'x'; st->str1[20] = '6'; st->str1[21] = ';'; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INVAL); assert_string_equal(ly_errmsg(), "Invalid character reference value."); /* 0xdfff */ st->str1[17] = '&'; st->str1[18] = '#'; st->str1[19] = 'x'; st->str1[20] = 'd'; st->str1[21] = 'f'; st->str1[22] = 'f'; st->str1[23] = 'f'; st->str1[24] = ';'; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INVAL); assert_string_equal(ly_errmsg(), "Invalid character reference value."); /* 0xfdef */ st->str1[17] = '&'; st->str1[18] = '#'; st->str1[19] = 'x'; st->str1[20] = 'f'; st->str1[21] = 'd'; st->str1[22] = 'e'; st->str1[23] = 'f'; st->str1[24] = ';'; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INVAL); assert_string_equal(ly_errmsg(), "Invalid character reference value."); /* 0xffff */ st->str1[17] = '&'; st->str1[18] = '#'; st->str1[19] = 'x'; st->str1[20] = 'f'; st->str1[21] = 'f'; st->str1[22] = 'f'; st->str1[23] = 'f'; st->str1[24] = ';'; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INVAL); assert_string_equal(ly_errmsg(), "Invalid character reference value."); /* the same using character reference */ /* 0x10ffff */ st->str1[17] = '&'; st->str1[18] = '#'; st->str1[19] = 'x'; st->str1[20] = '1'; st->str1[21] = '0'; st->str1[22] = 'f'; st->str1[23] = 'f'; st->str1[24] = 'f'; st->str1[25] = 'f'; st->str1[26] = ';'; assert_ptr_equal(lyd_parse_mem(st->ctx, st->str1, LYD_XML, LYD_OPT_CONFIG), NULL); assert_int_equal(ly_errno, LY_EVALID); assert_int_equal(ly_vecode, LYVE_XML_INVAL); assert_string_equal(ly_errmsg(), "Invalid character reference value."); }