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_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_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_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_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 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); }
/** * @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; }