diff --git a/CMakeLists.txt b/CMakeLists.txt index a98463bf..38077131 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,23 +125,29 @@ if(NOT SERVER_DIR) endif() endif() -include(ExternalProject) -set(UDP_NOTIF_BIN ${CMAKE_CURRENT_BINARY_DIR}/lib) -set(UDP_NOTIF_STATIC_LIB ${UDP_NOTIF_BIN}/lib/libunyte-udp-notif.a) -set(UDP_NOTIF_INCLUDES ${UDP_NOTIF_BIN}/include) - -ExternalProject_Add(udp-notif-c-collector - PREFIX ${UDP_NOTIF_BIN} - GIT_REPOSITORY https://github.com/network-analytics/udp-notif-c-collector - GIT_TAG main - BUILD_IN_SOURCE 1 - UPDATE_DISCONNECTED true - PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/patches/0001-feat-add-local-address-to-sender.patch - CONFIGURE_COMMAND ./bootstrap && ./configure --prefix=${UDP_NOTIF_BIN} - BUILD_COMMAND make - INSTALL_COMMAND make install - BUILD_BYPRODUCTS ${UDP_NOTIF_STATIC_LIB} -) +if (NOT UDP_NOTIF_STATIC_LIB) + include(ExternalProject) + set(UDP_NOTIF_BIN ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + set(UDP_NOTIF_STATIC_LIB ${UDP_NOTIF_BIN}/${CMAKE_INSTALL_LIBDIR}/libunyte-udp-notif.a) + set(UDP_NOTIF_INCLUDES ${UDP_NOTIF_BIN}/${CMAKE_INSTALL_INCLUDEDIR}) + + ExternalProject_Add(udp-notif-c-collector + PREFIX ${UDP_NOTIF_BIN} + GIT_REPOSITORY https://github.com/network-analytics/udp-notif-c-collector + GIT_TAG main + BUILD_IN_SOURCE 1 + UPDATE_DISCONNECTED true + PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/patches/0001-feat-add-local-address-to-sender.patch + CONFIGURE_COMMAND ./bootstrap && ./configure --prefix=${UDP_NOTIF_BIN} + BUILD_COMMAND make + INSTALL_COMMAND make install + BUILD_BYPRODUCTS ${UDP_NOTIF_STATIC_LIB} + ) +else() + if (NOT UDP_NOTIF_INCLUDES) + message(FATAL_ERROR "Missing UDP_NOTIF_INCLUDES") + endif() +endif() # # sources @@ -267,7 +273,9 @@ use_compat() # netopeer2-server add_library(serverobj OBJECT ${SERVER_SRC}) -add_dependencies(serverobj udp-notif-c-collector) +if(UDP_NOTIF_BIN) + add_dependencies(serverobj udp-notif-c-collector) +endif() add_executable(netopeer2-server $ src/main.c ${compatsrc}) # @@ -286,7 +294,9 @@ set_target_properties(netopeer2-server PROPERTIES IMPORTED_LOCATION ${UDP_NOTIF_ set_target_properties(netopeer2-server PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${UDP_NOTIF_INCLUDES}) target_link_libraries(netopeer2-server ${UDP_NOTIF_STATIC_LIB}) include_directories(${UDP_NOTIF_INCLUDES}) -add_dependencies(netopeer2-server udp-notif-c-collector) +if(UDP_NOTIF_BIN) + add_dependencies(netopeer2-server udp-notif-c-collector) +endif() # libssh (was already found, if exists) if(LIBSSH_FOUND AND LIBNETCONF2_ENABLED_SSH) diff --git a/src/main.c b/src/main.c index c5db4a5b..91fb4d6b 100644 --- a/src/main.c +++ b/src/main.c @@ -860,15 +860,24 @@ server_data_subscribe(void) SR_CONFIG_SUBSCR(mod_name, "/ietf-subscribed-notifications:subscriptions/receiver-instances/receiver-instance", np2srv_config_receivers_cb); - SR_CONFIG_SUBSCR(mod_name, "/ietf-subscribed-notifications:subscriptions/subscription", - np2srv_config_subscriptions_cb); + rc = sr_module_change_subscribe(np2srv.sr_sess, mod_name, "/ietf-subscribed-notifications:subscriptions/subscription", + np2srv_config_subscriptions_cb, NULL, 0, SR_SUBSCR_ENABLED, &np2srv.sr_data_sub); + if (rc != SR_ERR_OK) { + ERR("Subscribing for \"%s\" data changes failed (%s).", mod_name, sr_strerror(rc)); + goto error; + } SR_CONFIG_SUBSCR(mod_name, "/ietf-subscribed-notifications:subscriptions/subscription/receivers/receiver", np2srv_config_subscriptions_receivers_cb); /* operational data */ SR_OPER_SUBSCR(mod_name, "/ietf-subscribed-notifications:streams", np2srv_oper_sub_ntf_streams_cb); - SR_OPER_SUBSCR(mod_name, "/ietf-subscribed-notifications:subscriptions", np2srv_oper_sub_ntf_subscriptions_cb); + rc = sr_oper_get_subscribe(np2srv.sr_sess, mod_name, "/ietf-subscribed-notifications:subscriptions", + np2srv_oper_sub_ntf_subscriptions_cb, NULL, SR_SUBSCR_OPER_MERGE, &np2srv.sr_data_sub); + if (rc != SR_ERR_OK) { + ERR("Subscribing for providing \"%s\" state data failed (%s).", mod_name, sr_strerror(rc)); + goto error; + } /* * ietf-netconf-server diff --git a/src/netconf_subscribed_notifications.c b/src/netconf_subscribed_notifications.c index bcb5cda3..dd20bdfa 100644 --- a/src/netconf_subscribed_notifications.c +++ b/src/netconf_subscribed_notifications.c @@ -19,6 +19,7 @@ #include "netconf_subscribed_notifications.h" #include +#include #include #include #include @@ -152,49 +153,42 @@ sub_ntf_find_next(struct np2srv_sub_ntf *last, int (*sub_ntf_match_cb)(struct np return NULL; } -int -csn_send_notif(struct csn_receiver_info *recv_info, uint32_t nc_sub_id, - struct timespec timestamp, struct lyd_node **ly_ntf, int use_ntf) +/** + * @brief Build a notification. + * + * @param[in] timestamp any timestamp, mainly the current time. + * @param[in] ly_ntf the notification content to add to the message. + * @return a pointer to a new unyte message on success, NULL on failure. + */ +static unyte_message_t * +csn_build_notification(struct timespec timestamp, struct lyd_node **ly_ntf) { - char *string_notification = NULL; unyte_message_t *message = NULL; static uint32_t message_id = 0; char *string_to_send = NULL; - struct np2srv_sub_ntf *sub; char *eventtime = NULL; - int rc = SR_ERR_OK; - uint32_t r; + int rc = 0; - /* find the subscription structure */ ly_time_ts2str(×tamp, &eventtime); + message = (unyte_message_t *)malloc(sizeof *message); + if (!message) { + EMEM; + goto cleanup; + } + lyd_print_mem(&string_to_send, *ly_ntf, LYD_XML, LYD_PRINT_WD_ALL | LY_PRINT_SHRINK); - if (asprintf(&string_notification, + if ((rc = asprintf((char **)&message->buffer, "" "%s" "%s" "", - eventtime, string_to_send) < 0) { - EINT; - rc = SR_ERR_NO_MEMORY; - goto cleanup; - } - - sub = sub_ntf_find(nc_sub_id, 0, 0, 0); - if (!sub) { - EINT; - rc = SR_ERR_INTERNAL; + eventtime, string_to_send)) < 0) { + EMEM; goto cleanup; } - message = (unyte_message_t *)malloc(sizeof *message); - if (!message) { - EINT; - rc = SR_ERR_NO_MEMORY; - goto cleanup; - } + message->buffer_len = rc; - message->buffer = string_notification; - message->buffer_len = strlen(string_notification); /* UDP-notif */ message->version = 0; message->space = 0; @@ -209,19 +203,52 @@ csn_send_notif(struct csn_receiver_info *recv_info, uint32_t nc_sub_id, message->options = NULL; message->options_len = 0; +cleanup: + if (rc < 0) { + free(message); + message = NULL; + } + + free(eventtime); + free(string_to_send); + return message; +} + +int +csn_send_notif(struct csn_receiver_info *recv_info, uint32_t nc_sub_id, + struct timespec timestamp, struct lyd_node **ly_ntf, int use_ntf) +{ + unyte_message_t *message = NULL; + struct np2srv_sub_ntf *sub; + int rc = SR_ERR_OK; + uint32_t r; + + sub = sub_ntf_find(nc_sub_id, 0, 0, 0); + if (!sub) { + EINT; + rc = SR_ERR_INTERNAL; + goto cleanup; + } + + message = csn_build_notification(timestamp, ly_ntf); + if (!message) { + EMEM; + rc = SR_ERR_NO_MEMORY; + goto cleanup; + } + /* search transport */ for (r = 0; r < recv_info->count; r++) { unyte_send(recv_info->receivers[r].udp.sender, message); + ATOMIC_INC_RELAXED(sub->sent_count); } - free(string_notification); - - ATOMIC_INC_RELAXED(sub->sent_count); - cleanup: - free(message); - free(eventtime); - free(string_to_send); + if (message) { + free(message->buffer); + free(message); + } + if (use_ntf) { lyd_free_tree(*ly_ntf); *ly_ntf = NULL; @@ -229,6 +256,60 @@ csn_send_notif(struct csn_receiver_info *recv_info, uint32_t nc_sub_id, return rc; } +/** + * @brief Send a notification to a receiver. + * + * @param[in] receiver the receiver to send the notif. + * @param[in] nc_sub_id the configured subscription id. + * @param[in] type may be started or terminated. + * @return Sysrepo error value. + */ +static int +csn_send_notif_one(struct csn_receiver *receiver, uint32_t nc_sub_id, const char *type) +{ + unyte_message_t *message = NULL; + const struct ly_ctx *ly_ctx; + struct np2srv_sub_ntf *sub; + struct lyd_node *ly_ntf; + char notif_string[128]; + int rc = SR_ERR_OK; + char buf[11]; + + ly_ctx = sr_acquire_context(np2srv.sr_conn); + sr_release_context(np2srv.sr_conn); + + sprintf(buf, "%" PRIu32, nc_sub_id); + sprintf(notif_string, "/ietf-subscribed-notifications:subscription-%s/id", type); + lyd_new_path(NULL, ly_ctx, notif_string, buf, 0, &ly_ntf); + + sub = sub_ntf_find(nc_sub_id, 0, 0, 0); + if (!sub) { + EINT; + rc = SR_ERR_INTERNAL; + goto cleanup; + } + + message = csn_build_notification(np_gettimespec(1), &ly_ntf); + if (!message) { + EMEM; + rc = SR_ERR_NO_MEMORY; + goto cleanup; + } + + unyte_send(receiver->udp.sender, message); + + ATOMIC_INC_RELAXED(sub->sent_count); + +cleanup: + if (message) { + free(message->buffer); + free(message); + } + + lyd_free_tree(ly_ntf); + return rc; +} + int sub_ntf_send_notif(struct nc_session *ncs, uint32_t nc_sub_id, struct timespec timestamp, struct lyd_node **ly_ntf, int use_ntf) @@ -297,7 +378,7 @@ sub_ntf_add(const struct np2srv_sub_ntf *sub) } /** - * @brief add receiver config to the list of receivers + * @brief Add receiver config to the list of receivers. * * @param[in] recv_config receiver config to add to the list. * @return 0 on success. @@ -401,9 +482,18 @@ np2srv_sub_ntf_destroy(void) INFO_UNLOCK; } +/** + * @brief Establish a new subscription either configured or not. + * + * @param[in] session sysrepo session. + * @param[in] input the data containing the subscription info. + * @param[out] output to return to the netconf subscriber. + * @param[in] ncs the NETCONF session to use. + * @return Sysrepo error value. + */ static int -np2srv_establish_sub_cb(sr_session_ctx_t *session, const struct lyd_node *input, - struct lyd_node *output, struct nc_session *ncs) +np2srv_establish_sub(sr_session_ctx_t *session, const struct lyd_node *input, struct lyd_node *output, + struct nc_session *ncs) { struct lyd_node *node; struct np2srv_sub_ntf sub = {0}, *sub_p; @@ -461,7 +551,7 @@ np2srv_establish_sub_cb(sr_session_ctx_t *session, const struct lyd_node *input, if (lyd_find_path(input, "id", 0, &node)) { ERR("id not found."); - rc = SR_ERR_INTERNAL; + rc = SR_ERR_INVAL_ARG; goto error; } @@ -558,7 +648,14 @@ np2srv_establish_sub_cb(sr_session_ctx_t *session, const struct lyd_node *input, return rc; } -struct csn_receiver * +/** + * @brief Return the receiver info found with its name. + * + * @param[in] recv_info the receiver info of a subscription. + * @param[in] name the name of the receiver. + * @return the found receiver info or NULL. + */ +static struct csn_receiver * csn_receiver_get_by_name(struct csn_receiver_info *recv_info, const char *name) { uint32_t r; @@ -572,9 +669,161 @@ csn_receiver_get_by_name(struct csn_receiver_info *recv_info, const char *name) return NULL; } -int -csn_config_sub_receivers_prepare(const struct lyd_node *node_receiver, +/** + * @brief Destroy content of receiver in a subscription + * + * @param[in] receiver in the subscription in the receiver_info. + * @param[in] keep_ref 0: only the udp connection is destroyed, for restart, 1: everything is deleted. + */ +static void +csn_receiver_destroy(struct csn_receiver *receiver, int keep_ref) +{ + if (!receiver) { + return; + } + + if (!keep_ref) { + free(receiver->name); + receiver->name = NULL; + + free(receiver->instance_ref); + receiver->instance_ref = NULL; + } + + free_sender_socket(receiver->udp.sender); + receiver->udp.sender = NULL; + + free(receiver->udp.options.address); + receiver->udp.options.address = NULL; + + free(receiver->udp.options.port); + receiver->udp.options.port = NULL; + + free(receiver->udp.options.interface); + receiver->udp.options.interface = NULL; + + free(receiver->udp.options.local_address); + receiver->udp.options.local_address = NULL; +} + +/** + * @brief Start a receiver to send udp notification + * + * @param[in,out] receiver the receiver to configure and start. + * @param[in] recv_config the configuration of this receiver. + * @param[in] recv_info, the receiver info structure in the subscription. + * @return 0 on success, -1 on error. + */ +static int +csn_receiver_start(struct csn_receiver *receiver, struct csn_receiver_config *recv_config, struct csn_receiver_info *recv_info) +{ + receiver->state = CSN_RECEIVER_STATE_CONNECTING; + receiver->reset_time = np_gettimespec(1); + + receiver->udp.options.default_mtu = 1500; + receiver->udp.options.address = strdup(recv_config->udp.address); + if (!receiver->udp.options.address) { + EMEM; + goto error; + } + + receiver->udp.options.port = strdup(recv_config->udp.port); + if (!receiver->udp.options.port) { + EMEM; + goto error; + } + + if (recv_info->local_address) { + receiver->udp.options.local_address = strdup(recv_info->local_address); + if (!receiver->udp.options.local_address) { + EMEM; + goto error; + } + } + + if (recv_info->interface) { + receiver->udp.options.interface = strdup(recv_info->interface); + if (!receiver->udp.options.interface) { + EMEM; + goto error; + } + } + + receiver->udp.sender = unyte_start_sender(&receiver->udp.options); + if (!receiver->udp.sender) { + ERR("Cannot create udp sender: (%s).", strerror(errno)); + goto error; + } + + receiver->state = CSN_RECEIVER_STATE_ACTIVE; + + return 0; + +error: + free(receiver->udp.options.address); + free(receiver->udp.options.port); + free(receiver->udp.options.interface); + free(receiver->udp.options.local_address); + return -1; +} + +/** + * @brief add a receiver in the receiver_info list + * + * @param[in] receiver in the subscription in the receiver_info. + * @param[in] receiver_info in the subscription. + * @return 0 on success, -1 on error. + */ +static int +csn_receiver_add(struct csn_receiver_info *recv_info, struct csn_receiver *receiver) +{ + void *mem; + + mem = realloc(recv_info->receivers, (recv_info->count + 1) * sizeof *receiver); + if (!mem) { + return -1; + } + + recv_info->receivers = mem; + + recv_info->receivers[recv_info->count] = *receiver; + ++recv_info->count; + + return 0; +} + +/** + * @brief Look for a receiver config according to its name. + * + * @param[in] name the name of the receiver config. + * @return the found receiver config or NULL. + */ +static struct csn_receiver_config * +csn_receiver_config_get_by_name(const char *name) +{ + uint32_t r; + + for (r = 0; r < info.recv_cfg_count; r++) { + if (!strcmp(name, info.recv_configs[r].instance_name)) { + return &info.recv_configs[r]; + } + } + + return NULL; +} + +/** + * @brief Add a receiver to a subscription. + * + * @param[in] node_receiver the configuration of the receiver. + * @param[in] recv_info the receivers info of this subscription. + * @param[in] nc_sub_id the subscription id of this configured subscription. + * @return Sysrepo error value. + */ +static int +csn_add_sub_receivers_prepare(const struct lyd_node *node_receiver, + struct csn_receiver_info *recv_info, uint32_t nc_sub_id) { struct csn_receiver_config *recv_config = NULL; struct csn_receiver *receiver_search = NULL; @@ -584,61 +833,77 @@ csn_config_sub_receivers_prepare(const struct lyd_node *node_receiver, int rc = SR_ERR_OK; if (lyd_find_path(node_receiver, "name", 0, &node_receiver_name)) { - ERR("Missing receiver name"); + ERR("Missing receiver name."); + rc = SR_ERR_INVAL_ARG; goto cleanup; } if (lyd_find_path(node_receiver, "ietf-subscribed-notif-receivers:receiver-instance-ref", 0, &node_receiver_ref)) { - ERR("Missing receiver instance ref"); + ERR("Missing receiver instance ref."); + rc = SR_ERR_INVAL_ARG; goto cleanup; } receiver_search = csn_receiver_get_by_name(recv_info, lyd_get_value(node_receiver_name)); if (receiver_search) { - WRN("Receiver already existing"); + WRN("Receiver already existing."); goto cleanup; } receiver.name = strdup(lyd_get_value(node_receiver_name)); if (!receiver.name) { + EMEM; rc = SR_ERR_NO_MEMORY; - csn_receiver_destroy(&receiver, 0); goto cleanup; } receiver.instance_ref = strdup(lyd_get_value(node_receiver_ref)); if (!receiver.instance_ref) { + EMEM; rc = SR_ERR_NO_MEMORY; - csn_receiver_destroy(&receiver, 0); goto cleanup; } recv_config = csn_receiver_config_get_by_name(lyd_get_value(node_receiver_ref)); if (!recv_config) { - EINT; - csn_receiver_destroy(&receiver, 0); + ERR("Cannot get receiver config."); + rc = SR_ERR_NOT_FOUND; goto cleanup; } rc = csn_receiver_start(&receiver, recv_config, recv_info); if (rc) { - ERR("Cannot init receiver"); - csn_receiver_destroy(&receiver, 0); + ERR("Cannot init receiver."); + rc = SR_ERR_INTERNAL; goto cleanup; } + if (csn_send_notif_one(&receiver, nc_sub_id, "started")) { + WRN("Could not send notification ."); + } + rc = csn_receiver_add(recv_info, &receiver); if (rc) { + EMEM; rc = SR_ERR_NO_MEMORY; - ERR("Cannot add receiver"); - csn_receiver_destroy(&receiver, 0); goto cleanup; } + cleanup: + if (rc) { + csn_receiver_destroy(&receiver, 0); + } + return rc; } -int +/** + * @brief Modify a receiver of a subscription. + * + * @param[in] node_receiver the configuration of the receiver. + * @return Sysrepo error value. + */ +static int csn_modify_sub_receiver(const struct lyd_node *node_receiver) { const struct lyd_node *input = lyd_parent(lyd_parent(node_receiver)); @@ -653,7 +918,7 @@ csn_modify_sub_receiver(const struct lyd_node *node_receiver) if (lyd_find_path(input, "id", 0, &node)) { ERR("id not found."); - rc = SR_ERR_INTERNAL; + rc = SR_ERR_INVAL_ARG; goto cleanup; } @@ -678,47 +943,66 @@ csn_modify_sub_receiver(const struct lyd_node *node_receiver) } if (lyd_find_path(node_receiver, "ietf-subscribed-notif-receivers:receiver-instance-ref", 0, &node_receiver_ref)) { - ERR("Missing receiver instance ref"); + ERR("Missing receiver instance ref."); + rc = SR_ERR_INVAL_ARG; goto cleanup; } if (lyd_find_path(node_receiver, "name", 0, &node)) { - rc = SR_ERR_LY; - ERR("Could not find receiver name"); + ERR("Could not find receiver name."); + rc = SR_ERR_INVAL_ARG; goto cleanup; } receiver = csn_receiver_get_by_name(recv_info, lyd_get_value(node)); if (!receiver) { + ERR("Receiver not found."); rc = SR_ERR_INVAL_ARG; - ERR("Receiver not found"); goto cleanup; } recv_config = csn_receiver_config_get_by_name(lyd_get_value(node_receiver_ref)); if (!recv_config) { - EINT; + ERR("Cannot get receiver config."); + rc = SR_ERR_NOT_FOUND; goto cleanup; } if (strcmp(lyd_get_value(node_receiver_ref), receiver->instance_ref)) { + free(receiver->instance_ref); receiver->instance_ref = strdup(lyd_get_value(node_receiver_ref)); + if (csn_send_notif_one(receiver, nc_sub_id, "terminated")) { + WRN("Could not send notification ."); + } + csn_receiver_destroy(receiver, 1); + rc = csn_receiver_start(receiver, recv_config, recv_info); if (rc) { - ERR("Cannot init receiver"); + ERR("Cannot init receiver."); + rc = SR_ERR_INTERNAL; goto cleanup; } + + if (csn_send_notif_one(receiver, nc_sub_id, "started")) { + WRN("Could not send notification ."); + } } cleanup: return rc; } -int -csn_config_sub_receiver(const struct lyd_node *node_receiver) +/** + * @brief add a receiver of a subscription. + * + * @param[in] node_receiver the configuration of the receiver. + * @return Sysrepo error value. + */ +static int +csn_add_sub_receiver(const struct lyd_node *node_receiver) { const struct lyd_node *input = lyd_parent(lyd_parent(node_receiver)); struct csn_receiver_info *recv_info = NULL; @@ -729,7 +1013,7 @@ csn_config_sub_receiver(const struct lyd_node *node_receiver) if (lyd_find_path(input, "id", 0, &node)) { ERR("id not found."); - rc = SR_ERR_INTERNAL; + rc = SR_ERR_INVAL_ARG; goto error; } @@ -737,69 +1021,51 @@ csn_config_sub_receiver(const struct lyd_node *node_receiver) sub = sub_ntf_find(nc_sub_id, 0, 0, 0); if (!sub) { ERR("no such subscription."); - rc = SR_ERR_INTERNAL; - goto error; - } - - if (sub->type == SUB_TYPE_CFG_SUB) { - recv_info = sub_ntf_receivers_info_get(sub->data); - } else if (sub->type == SUB_TYPE_CFG_YANG_PUSH) { - recv_info = yang_push_receivers_info_get(sub->data); - } - - if (!recv_info) { - ERR("no receivers info."); - rc = SR_ERR_INTERNAL; + rc = SR_ERR_INVAL_ARG; goto error; } - rc = csn_config_sub_receivers_prepare(node_receiver, recv_info); - -error: - return rc; -} - -void -csn_receiver_destroy(struct csn_receiver *receiver, int keep_ref) -{ - if (!receiver) { - return; - } - - if (!keep_ref) { - free(receiver->name); - receiver->name = NULL; - - free(receiver->instance_ref); - receiver->instance_ref = NULL; - } - - free_sender_socket(receiver->udp.sender); - receiver->udp.sender = NULL; - - free(receiver->udp.options.address); - receiver->udp.options.address = NULL; + if (sub->type == SUB_TYPE_CFG_SUB) { + recv_info = sub_ntf_receivers_info_get(sub->data); + } else if (sub->type == SUB_TYPE_CFG_YANG_PUSH) { + recv_info = yang_push_receivers_info_get(sub->data); + } - free(receiver->udp.options.port); - receiver->udp.options.port = NULL; + if (!recv_info) { + ERR("no receivers info."); + rc = SR_ERR_INTERNAL; + goto error; + } - free(receiver->udp.options.interface); - receiver->udp.options.interface = NULL; + rc = csn_add_sub_receivers_prepare(node_receiver, recv_info, nc_sub_id); - free(receiver->udp.options.local_address); - receiver->udp.options.local_address = NULL; +error: + return rc; } -int -csn_receiver_remove_by_name(struct csn_receiver_info *recv_info, const char *name) +/** + * @brief Remove a receiver from a subscription using its name. + * + * @param[in] recv_info the receivers in the subscription. + * @param[in] name the name of the receiver. + * @param[in] nc_sub_id the configured subscription id. + * @return Sysrepo error value. + */ +static int +csn_receiver_remove_by_name(struct csn_receiver_info *recv_info, const char *name, uint32_t nc_sub_id) { uint32_t r; for (r = 0; r < recv_info->count; r++) { + if (strcmp(name, recv_info->receivers[r].name)) { continue; } + if (csn_send_notif_one(&recv_info->receivers[r], nc_sub_id, "terminated")) { + WRN("Could not send notification ."); + } + csn_receiver_destroy(&recv_info->receivers[r], 0); recv_info->count--; @@ -815,7 +1081,13 @@ csn_receiver_remove_by_name(struct csn_receiver_info *recv_info, const char *nam return SR_ERR_INTERNAL; } -int +/** + * @brief Remove a receiver from a subscription. + * + * @param[in] node_receiver the information regarding the receiver. + * @return Sysrepo error value. + */ +static int csn_delete_sub_receiver(const struct lyd_node *node_receiver) { const struct lyd_node *input = lyd_parent(lyd_parent(node_receiver)); @@ -828,15 +1100,15 @@ csn_delete_sub_receiver(const struct lyd_node *node_receiver) if (lyd_find_path(input, "id", 0, &node)) { ERR("id not found."); - rc = SR_ERR_INTERNAL; + rc = SR_ERR_INVAL_ARG; goto error; } nc_sub_id = ((struct lyd_node_term *)node)->value.uint32; if (lyd_find_path(node_receiver, "name", 0, &node)) { - rc = SR_ERR_LY; - ERR("Could not find receiver name"); + ERR("Could not find receiver name."); + rc = SR_ERR_INVAL_ARG; goto error; } @@ -861,7 +1133,7 @@ csn_delete_sub_receiver(const struct lyd_node *node_receiver) goto error; } - rc = csn_receiver_remove_by_name(recv_info, receiver_name); + rc = csn_receiver_remove_by_name(recv_info, receiver_name, nc_sub_id); error: return rc; @@ -882,39 +1154,55 @@ np2srv_rpc_establish_sub_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), /* find this NETCONF session */ if ((rc = np_find_user_sess(session, __func__, &ncs, NULL))) { - goto error; + return rc; } - return np2srv_establish_sub_cb(session, input, output, ncs); - -error: - - return rc; + return np2srv_establish_sub(session, input, output, ncs); } -static struct lyd_node * +/** + * @brief Helpers to get the actual configured subscription config. + * + * @param[in] session sysrepo session. + * @param[in] nc_sub_id the configured subscription id. + * @return tree of the subscription config on success, NULL on error. + */ +static sr_data_t * get_sr_config_sub_ntf(sr_session_ctx_t *session, uint32_t nc_sub_id) { sr_data_t *data_node; char *xpath; - asprintf(&xpath, "/ietf-subscribed-notifications:subscriptions/subscription[id=%" PRIu32 "]", nc_sub_id); + if (asprintf(&xpath, "/ietf-subscribed-notifications:subscriptions/subscription[id=%" PRIu32 "]", nc_sub_id) == -1) { + EMEM; + return NULL; + } + sr_get_subtree(session, xpath, 0, &data_node); free(xpath); - if (data_node) { - return data_node->tree; - } - - return NULL; + return data_node; } -int -csn_config_sub(sr_session_ctx_t *session, const struct lyd_node *input) +/** + * @brief Establish a new confgured subscription + * + * @param[in] session sysrepo session. + * @param[in] input the data containing the subscription info. + * @return Sysrepo error value. + */ +static int +csn_add_sub(sr_session_ctx_t *session, const struct lyd_node *input) { - return np2srv_establish_sub_cb(session, input, NULL, NULL); + return np2srv_establish_sub(session, input, NULL, NULL); } +/** + * @brief Delete a receiver config from the list. + * + * @param[in] name of the receiver config to remove. + * @return 0 on success, -1 on error. + */ static int csn_receiver_config_remove_by_name(const char *name) { @@ -944,6 +1232,12 @@ csn_receiver_config_remove_by_name(const char *name) return -1; } +/** + * @brief Delete a receiver config from the list. + * + * @param[in] input the information regarding the receiver. + * @return 0 on success, -1 on error. + */ static int csn_receiver_config_delete(const struct lyd_node *input) { @@ -951,20 +1245,26 @@ csn_receiver_config_delete(const struct lyd_node *input) int rc = SR_ERR_OK; if (lyd_find_path(input, "name", 0, &name_node)) { - ERR("Missing receiver name\n"); - return -1; + ERR("Missing receiver name."); + return SR_ERR_INVAL_ARG; } /* remove from receivers */ rc = csn_receiver_config_remove_by_name(lyd_get_value(name_node)); if (rc) { - ERR("Cannot remove receiver\n"); - return -1; + ERR("Cannot remove receiver."); + return SR_ERR_INTERNAL; } - return 0; + return rc; } +/** + * @brief restart a receiver of all the subscriptions using it. + * + * @param[in] recv_config the information regarding the receiver. + * @return Sysrepo error value. + */ static int csn_receivers_restart(struct csn_receiver_config *recv_config) { @@ -989,17 +1289,26 @@ csn_receivers_restart(struct csn_receiver_config *recv_config) /* restart receivers of this subscription if they match the name */ for (r = 0; r < recv_info->count; r++) { struct csn_receiver *receiver = &recv_info->receivers[r]; + if (strcmp(receiver->instance_ref, recv_config->instance_name)) { continue; } + if (csn_send_notif_one(receiver, info.subs[s].nc_sub_id, "terminated")) { + WRN("Could not send notification ."); + } + csn_receiver_destroy(receiver, 1); rc = csn_receiver_start(receiver, recv_config, recv_info); if (rc) { - ERR("Cannot init receiver"); + ERR("Cannot init receiver."); + rc = SR_ERR_INTERNAL; goto cleanup; } + if (csn_send_notif_one(receiver, info.subs[s].nc_sub_id, "started")) { + WRN("Could not send notification ."); + } } } @@ -1007,6 +1316,12 @@ csn_receivers_restart(struct csn_receiver_config *recv_config) return rc; } +/** + * @brief Modify a receiver configuration. + * + * @param[in] input the information regarding the receiver. + * @return Sysrepo error value. + */ static int csn_receiver_config_modify(const struct lyd_node *input) { @@ -1018,22 +1333,22 @@ csn_receiver_config_modify(const struct lyd_node *input) int rc = SR_ERR_OK; if (lyd_find_path(input, "name", 0, &name_node)) { - ERR("Missing receiver name\n"); - rc = SR_ERR_NOT_FOUND; + ERR("Missing receiver name."); + rc = SR_ERR_INVAL_ARG; goto error; } /* get from receivers */ recv_config = csn_receiver_config_get_by_name(lyd_get_value(name_node)); - if (rc) { - ERR("Cannot get receiver config.\n"); + if (!recv_config) { + ERR("Cannot get receiver config."); rc = SR_ERR_NOT_FOUND; goto error; } if (lyd_find_path(input, "ietf-udp-notif-transport:udp-notif-receiver", 0, &receiver_node)) { ERR("Missing mandatory \"udp-notif-receiver\" leave."); - rc = SR_ERR_LY; + rc = SR_ERR_INVAL_ARG; goto error; } @@ -1041,7 +1356,7 @@ csn_receiver_config_modify(const struct lyd_node *input) free(recv_config->udp.address); recv_config->udp.address = strdup(lyd_get_value(remote_address_node)); if (!recv_config->udp.address) { - ERR("Cannot allocate remote address.\n"); + EMEM; rc = SR_ERR_NO_MEMORY; goto error; } @@ -1051,7 +1366,7 @@ csn_receiver_config_modify(const struct lyd_node *input) free(recv_config->udp.port); recv_config->udp.port = strdup(lyd_get_value(remote_port_node)); if (!recv_config->udp.port) { - ERR("Cannot allocate remote port.\n"); + EMEM; rc = SR_ERR_NO_MEMORY; goto error; } @@ -1059,7 +1374,7 @@ csn_receiver_config_modify(const struct lyd_node *input) rc = csn_receivers_restart(recv_config); if (rc) { - ERR("Cannot init receivers"); + ERR("Cannot init receivers."); goto error; } @@ -1095,74 +1410,12 @@ csn_receiver_info_destroy(struct csn_receiver_info *recv_info) recv_info->count = 0; } -struct csn_receiver_config * -csn_receiver_config_get_by_name(const char *name) -{ - uint32_t r; - - for (r = 0; r < info.recv_cfg_count; r++) { - if (!strcmp(name, info.recv_configs[r].instance_name)) { - return &info.recv_configs[r]; - } - } - - return NULL; -} - -int -csn_receiver_start(struct csn_receiver *receiver, struct csn_receiver_config *recv_config, - struct csn_receiver_info *recv_info) -{ - receiver->state = CSN_RECEIVER_STATE_CONNECTING; - receiver->reset_time = np_gettimespec(1); - - receiver->udp.options.default_mtu = 1500; - receiver->udp.options.address = strdup(recv_config->udp.address); - if (!receiver->udp.options.address) { - EMEM; - goto error; - } - - receiver->udp.options.port = strdup(recv_config->udp.port); - if (!receiver->udp.options.port) { - EMEM; - goto error; - } - - if (recv_info->local_address) { - receiver->udp.options.local_address = strdup(recv_info->local_address); - if (!receiver->udp.options.local_address) { - EMEM; - goto error; - } - } - - if (recv_info->interface) { - receiver->udp.options.interface = strdup(recv_info->interface); - if (!receiver->udp.options.interface) { - EMEM; - goto error; - } - } - - receiver->udp.sender = unyte_start_sender(&receiver->udp.options); - if (!receiver->udp.sender) { - ERR("Cannot create udp sender\n"); - goto error; - } - - receiver->state = CSN_RECEIVER_STATE_ACTIVE; - - return 0; - -error: - free(receiver->udp.options.address); - free(receiver->udp.options.port); - free(receiver->udp.options.interface); - free(receiver->udp.options.local_address); - return -1; -} - +/** + * @brief reset a receiver. + * + * @param[in] receiver the receiver to restart. + * @return 0 on success, -1 on failure. + */ static int csn_receiver_reset(struct csn_receiver *receiver) { @@ -1172,7 +1425,7 @@ csn_receiver_reset(struct csn_receiver *receiver) receiver->udp.sender = unyte_start_sender(&receiver->udp.options); if (!receiver->udp.sender) { - ERR("Cannot create udp sender\n"); + ERR("Cannot create udp sender: (%s).", strerror(errno)); goto error; } @@ -1184,24 +1437,12 @@ csn_receiver_reset(struct csn_receiver *receiver) return -1; } -int -csn_receiver_add(struct csn_receiver_info *recv_info, struct csn_receiver *receiver) -{ - void *mem; - - mem = realloc(recv_info->receivers, (recv_info->count + 1) * sizeof *receiver); - if (!mem) { - return -1; - } - - recv_info->receivers = mem; - - recv_info->receivers[recv_info->count] = *receiver; - ++recv_info->count; - - return 0; -} - +/** + * @brief Create a receiver configuration. + * + * @param[in] input the information regarding the receiver config. + * @return Sysrepo error value. + */ static int csn_receiver_config_start(const struct lyd_node *input) { @@ -1213,50 +1454,58 @@ csn_receiver_config_start(const struct lyd_node *input) int rc = SR_ERR_OK; if (lyd_find_path(input, "name", 0, &name_node)) { - ERR("Missing receiver name\n"); + ERR("Missing receiver name."); + rc = SR_ERR_INVAL_ARG; goto error; } recv_config.instance_name = strdup(lyd_get_value(name_node)); if (!recv_config.instance_name) { - ERR("Cannot allocate instance_name\n"); + EMEM; + rc = SR_ERR_NO_MEMORY; goto error; } /* detect type */ if (lyd_find_path(input, "ietf-udp-notif-transport:udp-notif-receiver", 0, &receiver_node)) { ERR("Missing mandatory \"udp-notif-receiver\" leave."); + rc = SR_ERR_INVAL_ARG; goto error; } recv_config.type = CSN_TRANSPORT_UDP; if (lyd_find_path(receiver_node, "remote-address", 0, &remote_address_node)) { - ERR("Missing receiver remote address\n"); + ERR("Missing receiver remote address."); + rc = SR_ERR_INVAL_ARG; goto error; } recv_config.udp.address = strdup(lyd_get_value(remote_address_node)); if (!recv_config.udp.address) { - ERR("Cannot allocate remote address\n"); + EMEM; + rc = SR_ERR_NO_MEMORY; goto error; } if (lyd_find_path(receiver_node, "remote-port", 0, &remote_port_node)) { - ERR("Missing receiver remote port\n"); + ERR("Missing receiver remote port."); + rc = SR_ERR_INVAL_ARG; goto error; } recv_config.udp.port = strdup(lyd_get_value(remote_port_node)); if (!recv_config.udp.port) { - ERR("Cannot allocate remote port\n"); + EMEM; + rc = SR_ERR_NO_MEMORY; goto error; } /* add into receivers, is not accessible before */ rc = csn_receiver_config_add(&recv_config); if (rc) { - ERR("Cannot add receiver\n"); + EMEM; + rc = SR_ERR_NO_MEMORY; goto error; } @@ -1626,7 +1875,14 @@ np2srv_rpc_delete_sub_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), con return rc; } -int +/** + * @brief Delete a configured subscription. + * + * @param[in] session sysrepo session. + * @param[in] input the information regarding the subscription. + * @return Sysrepo error value. + */ +static int csn_delete_sub(sr_session_ctx_t *session, const struct lyd_node *input) { struct np2srv_sub_ntf *sub; @@ -1636,20 +1892,24 @@ csn_delete_sub(sr_session_ctx_t *session, const struct lyd_node *input) uint32_t nc_sub_id; /* id */ - lyd_find_path(input, "id", 0, &node); + if (lyd_find_path(input, "id", 0, &node)) { + ERR("Could not find subscription id."); + return SR_ERR_INVAL_ARG; + } + nc_sub_id = ((struct lyd_node_term *)node)->value.uint32; /* WRITE LOCK */ sub = sub_ntf_find(nc_sub_id, 0, 1, 0); if (!sub) { if (asprintf(&message, "Subscription with ID %" PRIu32 " for the current receiver does not exist.", nc_sub_id) == -1) { - rc = SR_ERR_NO_MEMORY; EMEM; + rc = SR_ERR_NO_MEMORY; return rc; } np_err_ntf_sub_no_such_sub(session, message); - ERR("np_err_ntf_sub_no_such_sub"); + ERR("No such subscription."); rc = SR_ERR_INVAL_ARG; return rc; @@ -1658,7 +1918,7 @@ csn_delete_sub(sr_session_ctx_t *session, const struct lyd_node *input) /* terminate the subscription */ rc = sub_ntf_terminate_sub(sub, NULL); if (rc != SR_ERR_OK) { - ERR("sub_ntf_terminate_sub"); + ERR("Error on subscription termination."); goto cleanup_unlock; } @@ -1834,7 +2094,10 @@ np2srv_config_receivers_cb(sr_session_ctx_t *session, while ((r = sr_get_change_tree_next(session, iter, &op, &node, NULL, NULL, NULL)) == SR_ERR_OK) { if (op == SR_OP_MODIFIED) { - csn_receiver_config_modify(lyd_parent(lyd_parent(node))); + rc = csn_receiver_config_modify(lyd_parent(lyd_parent(node))); + if (rc != SR_ERR_OK) { + goto cleanup; + } } } @@ -1853,16 +2116,20 @@ np2srv_config_receivers_cb(sr_session_ctx_t *session, } int -np2srv_config_subscriptions_cb(sr_session_ctx_t *session, - uint32_t UNUSED(sub_id), const char *UNUSED(module_name), const char *UNUSED(path), - sr_event_t UNUSED(event), uint32_t UNUSED(request_id), void *UNUSED(private_data)) +np2srv_config_subscriptions_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const char *UNUSED(module_name), + const char *UNUSED(path), sr_event_t event, uint32_t UNUSED(request_id), void *UNUSED(private_data)) { sr_change_iter_t *iter = NULL; const struct lyd_node *node; uint32_t last_nc_sub_id = 0; + sr_data_t *data_node = NULL; int r, rc = SR_ERR_OK; sr_change_oper_t op; + if (event != SR_EV_CHANGE) { + return SR_ERR_OK; + } + /* subscribed-notifications */ rc = sr_get_changes_iter(session, "/ietf-subscribed-notifications:subscriptions/subscription", &iter); if (rc != SR_ERR_OK) { @@ -1871,9 +2138,8 @@ np2srv_config_subscriptions_cb(sr_session_ctx_t *session, } while ((r = sr_get_change_tree_next(session, iter, &op, &node, NULL, NULL, NULL)) == SR_ERR_OK) { - if (op == SR_OP_CREATED) { - rc = csn_config_sub(session, node); + rc = csn_add_sub(session, node); if (rc != SR_ERR_OK) { goto cleanup; } @@ -1884,7 +2150,6 @@ np2srv_config_subscriptions_cb(sr_session_ctx_t *session, } } } - if (r != SR_ERR_NOT_FOUND) { rc = r; ERR("Getting next change failed (%s).", sr_strerror(rc)); @@ -1921,29 +2186,35 @@ np2srv_config_subscriptions_cb(sr_session_ctx_t *session, } /* restart subscription with actual config */ - config = get_sr_config_sub_ntf(session, nc_sub_id); - if (!config) { - VRB("Could not find sub config %lu", nc_sub_id); + data_node = get_sr_config_sub_ntf(session, nc_sub_id); + if (!data_node || !data_node->tree) { + ERR("Could not find sub config %" PRIu32 ".", nc_sub_id); rc = SR_ERR_INTERNAL; goto cleanup; } + config = data_node->tree; + /* delete and create the subscriptions */ - rc = csn_delete_sub(session, lyd_parent(node)); - if (rc != SR_ERR_OK) { - VRB("Could not delete subscription"); + if ((rc = csn_delete_sub(session, lyd_parent(node)))) { + goto cleanup; + } + if ((rc = csn_add_sub(session, config))) { goto cleanup; } - - csn_config_sub(session, config); if (!lyd_find_path(config, "receivers", 0, &node_receivers)) { LY_LIST_FOR(lyd_child(node_receivers), node_receiver) { - csn_config_sub_receiver(node_receiver); + rc = csn_add_sub_receiver(node_receiver); + if (rc != SR_ERR_OK) { + goto cleanup; + } } } /* save id of modified subscription */ last_nc_sub_id = nc_sub_id; + sr_release_data(data_node); + data_node = NULL; } if (r != SR_ERR_NOT_FOUND) { @@ -1953,7 +2224,7 @@ np2srv_config_subscriptions_cb(sr_session_ctx_t *session, } cleanup: - + sr_release_data(data_node); sr_free_change_iter(iter); return rc; } @@ -1976,9 +2247,15 @@ np2srv_config_subscriptions_receivers_cb(sr_session_ctx_t *session, while ((r = sr_get_change_tree_next(session, iter, &op, &node, NULL, NULL, NULL)) == SR_ERR_OK) { if (op == SR_OP_CREATED) { - csn_config_sub_receiver(node); + rc = csn_add_sub_receiver(node); + if (rc) { + goto cleanup; + } } else if (op == SR_OP_DELETED) { - csn_delete_sub_receiver(node); + rc = csn_delete_sub_receiver(node); + if (rc) { + goto cleanup; + } } } @@ -1998,7 +2275,10 @@ np2srv_config_subscriptions_receivers_cb(sr_session_ctx_t *session, while ((r = sr_get_change_tree_next(session, iter, &op, &node, NULL, NULL, NULL)) == SR_ERR_OK) { if (op == SR_OP_MODIFIED) { - csn_modify_sub_receiver(lyd_parent(node)); + rc = csn_modify_sub_receiver(lyd_parent(node)); + if (rc) { + goto cleanup; + } } } @@ -2092,7 +2372,7 @@ np2srv_oper_sub_ntf_streams_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id int np2srv_oper_sub_ntf_subscriptions_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const char *UNUSED(module_name), - const char *UNUSED(path), const char *request_xpath, uint32_t UNUSED(request_id), + const char *UNUSED(path), const char *UNUSED(request_xpath), uint32_t UNUSED(request_id), struct lyd_node **parent, void *UNUSED(private_data)) { const struct ly_ctx *ly_ctx; @@ -2104,11 +2384,6 @@ np2srv_oper_sub_ntf_subscriptions_cb(sr_session_ctx_t *session, uint32_t UNUSED( char *name = NULL; uint32_t id; - if (strstr(request_xpath,"subscriptions/subscription[") - && strstr(request_xpath,"/receivers/receiver[")) { - return np2srv_oper_sub_ntf_receivers_cb(session, 0, NULL, NULL, request_xpath, 0, parent, NULL); - } - /* context is locked while the callback is executing */ ly_ctx = sr_session_acquire_context(session); sr_session_release_context(session); @@ -2274,8 +2549,8 @@ np2srv_rpc_reset_receiver_cb(sr_session_ctx_t *UNUSED(session), uint32_t UNUSED( INFO_WLOCK; if (lyd_find_path(lyd_parent(input), "name", 0, &node)) { - rc = SR_ERR_LY; - ERR("Could not find receiver name"); + ERR("Could not find receiver name."); + rc = SR_ERR_INVAL_ARG; goto cleanup; } @@ -2284,17 +2559,17 @@ np2srv_rpc_reset_receiver_cb(sr_session_ctx_t *UNUSED(session), uint32_t UNUSED( input = lyd_parent(lyd_parent(lyd_parent(input))); if (lyd_find_path(input, "id", 0, &node)) { - rc = SR_ERR_LY; - ERR("Could not find subscription id"); + ERR("Could not find subscription id."); + rc = SR_ERR_INVAL_ARG; goto cleanup; } - nc_sub_id = strtoul(lyd_get_value(node), NULL, 10); + nc_sub_id = ((struct lyd_node_term *)node)->value.uint32; sub = sub_ntf_find(nc_sub_id, 0, 0, 0); if (!sub) { + ERR("Subscription not found."); rc = SR_ERR_INVAL_ARG; - ERR("Subscription not found"); goto cleanup; } @@ -2306,34 +2581,42 @@ np2srv_rpc_reset_receiver_cb(sr_session_ctx_t *UNUSED(session), uint32_t UNUSED( recv_info = yang_push_receivers_info_get(sub->data); break; default: - ERR("Bad subscription type"); + ERR("Bad subscription type."); break; } if (!recv_info) { + ERR("Receiver info not found."); rc = SR_ERR_INVAL_ARG; - ERR("Receiver info not found"); goto cleanup; } receiver = csn_receiver_get_by_name(recv_info, receiver_name); if (!receiver) { + ERR("Receiver not found."); rc = SR_ERR_INVAL_ARG; - ERR("Receiver not found"); goto cleanup; } + if (csn_send_notif_one(receiver, nc_sub_id, "terminated")) { + WRN("Could not send notification ."); + } + if (csn_receiver_reset(receiver)) { + ERR("Receiver could not be reset."); rc = SR_ERR_INVAL_ARG; - ERR("Receiver could not be reset"); goto cleanup; } + if (csn_send_notif_one(receiver, nc_sub_id, "started")) { + WRN("Could not send notification ."); + } + if (output) { ly_time_ts2str(&receiver->reset_time, &time_str); if (lyd_new_term(output, NULL, "time", time_str, 1, NULL)) { + ERR("Could not add time."); rc = SR_ERR_LY; - ERR("Could not add time"); goto cleanup; } } @@ -2346,28 +2629,3 @@ np2srv_rpc_reset_receiver_cb(sr_session_ctx_t *UNUSED(session), uint32_t UNUSED( return rc; } -int -np2srv_oper_sub_ntf_receivers_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const char *UNUSED(module_name), - const char *UNUSED(path), const char *request_xpath, uint32_t UNUSED(request_id), - struct lyd_node **parent, void *UNUSED(private_data)) -{ - const struct ly_ctx *ly_ctx; - struct lyd_node *root; - int r; - - /* context is locked while the callback is executing */ - ly_ctx = sr_session_acquire_context(session); - sr_session_release_context(session); - - if (lyd_new_path(NULL, ly_ctx, request_xpath, NULL, 0, &root)) { - r = SR_ERR_LY; - } - - if (r) { - lyd_free_tree(root); - } else { - *parent = root; - } - - return SR_ERR_OK; -} diff --git a/src/netconf_subscribed_notifications.h b/src/netconf_subscribed_notifications.h index 06f0f4e6..3c299c3f 100644 --- a/src/netconf_subscribed_notifications.h +++ b/src/netconf_subscribed_notifications.h @@ -212,7 +212,7 @@ int np2srv_rpc_reset_receiver_cb(sr_session_ctx_t *session, uint32_t sub_id, con */ /** - * @brief Send a notification. + * @brief Send a notification to all receivers of this subscription. * * @param[in] receivers reference to receivers to use. * @param[in] receivers_count the number of receivers. @@ -232,38 +232,4 @@ int csn_send_notif(struct csn_receiver_info *recv_info, uint32_t nc_sub_id, */ void csn_receiver_info_destroy(struct csn_receiver_info *recv_info); -/** - * @brief Destroy content of receiver in a subscription - * - * @param[in] receiver in the subscription in the receiver_info. - */ -void csn_receiver_destroy(struct csn_receiver *receiver, int keep_ref); - -/** - * @brief start a receiver - * - * @param[in] receiver in the subscription in the receiver_info. - * @param[in] receiver_config is the global receiver config - * @param[in] receiver_info in the subscription. - * @return Sysrepo error value. - */ -int csn_receiver_start(struct csn_receiver *receiver, struct csn_receiver_config *recv_config, - struct csn_receiver_info *recv_info); -/** - * @brief add a receiver in the receiver_info list - * - * @param[in] receiver in the subscription in the receiver_info. - * @param[in] receiver_info in the subscription. - * @return Sysrepo error value. - */ -int csn_receiver_add(struct csn_receiver_info *recv_info, struct csn_receiver *receiver); - -/** - * @brief get a receiver configration from the list - * - * @param[in] name of a receiver configuration. - * @return a config containing receiver connection parameters - */ -struct csn_receiver_config *csn_receiver_config_get_by_name(const char *name); - #endif /* NP2SRV_NETCONF_SUBSCRIBED_NOTIFICATIONS_H_ */ diff --git a/src/subscribed_notifications.c b/src/subscribed_notifications.c index 3f5b6171..f71bd232 100644 --- a/src/subscribed_notifications.c +++ b/src/subscribed_notifications.c @@ -193,6 +193,7 @@ np2srv_rpc_establish_sub_ntf_cb(sr_session_ctx_t *UNUSED(session), uint32_t sub_ * @param[in] ev_sess Event session for reporting errors. * @param[out] sub_ids Generated sysrepo subscription IDs, the first one is used as sub-ntf subscription ID. * @param[out] sub_id_count Number of @p sub_ids. + * @param[in] sr_sub_ctx is the sysrepo context. * @return Sysrepo error value. */ static int diff --git a/src/yang_push.c b/src/yang_push.c index 04d16b98..426794ff 100644 --- a/src/yang_push.c +++ b/src/yang_push.c @@ -562,6 +562,7 @@ np2srv_change_yang_push_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), c * @param[in] ev_sess Event sysrepo session for errors. * @param[in,out] sub_ids Array of SR sub IDs to add to. * @param[in,out] sub_id_count Number of items in @p sub_ids. + * @param[in] sr_sub_ctx is the sysrepo context. * @return Sysrepo error value. */ static int @@ -669,6 +670,7 @@ yang_push_sr_subscribe_filter_collect_mods(const struct ly_ctx *ly_ctx, const ch * @param[in] ev_sess Event session for reporting errors. * @param[out] sub_ids Generated sysrepo subscription IDs, the first one is used as sub-ntf subscription ID. * @param[out] sub_id_count Number of @p sub_ids. + * @param[in] sr_sub_ctx is the sysrepo context. * @return Sysrepo error value. */ static int @@ -879,17 +881,18 @@ yang_push_notif_update_send(struct nc_session *ncs, sr_session_ctx_t *sr_sess, s const struct ly_ctx *ly_ctx; sr_data_t *data = NULL; char buf[11]; - int rc = SR_ERR_OK; + int rc = SR_ERR_OK, r; /* switch to the datastore */ sr_session_switch_ds(sr_sess, yp_data->datastore); /* get the data from sysrepo */ - rc = sr_get_data(sr_sess, yp_data->xpath ? yp_data->xpath : "/*", 0, np2srv.sr_timeout, 0, &data); - if (rc != SR_ERR_OK) { - if (ncs) { - goto cleanup; - } + r = sr_get_data(sr_sess, yp_data->xpath ? yp_data->xpath : "/*", 0, np2srv.sr_timeout, 0, &data); + if (r == SR_ERR_NOT_FOUND) { + WRN("XPath \"%s\" does not match any schema or data nodes."); + } else if (r) { + rc = r; + goto cleanup; } /* context lock is already held by data */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 68eb1e9d..e1e4a23f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -37,7 +37,7 @@ set(test_sources "np_test.c") # list of all the tests set(tests test_rpc test_edit test_filter test_subscribe_filter test_subscribe_param test_parallel_sessions - test_candidate test_with_defaults test_nacm test_sub_ntf test_sub_ntf_advanced test_sub_ntf_filter test_error) + test_candidate test_with_defaults test_nacm test_sub_ntf test_sub_ntf_advanced test_configured_subscriptions test_sub_ntf_filter test_error) if(CMAKE_C_FLAGS MATCHES "-fsanitize=thread") message(WARNING "Features which use SIGEV_THREAD are known to be broken under TSAN, disabling tests for YANG-push and confirmed commit") diff --git a/tests/np_test.c b/tests/np_test.c index d8086e96..6530aa17 100644 --- a/tests/np_test.c +++ b/tests/np_test.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include +#include #include #include @@ -40,6 +42,51 @@ uint8_t debug = 0; /* Global variable to indicate if debugging */ +int +np_is_string_equal(const char *str1, const char *str2) +{ + uint32_t i, line, line_idx; + + if (!str1 && !str2) { + return 1; + } else if (!str1 && str2) { + print_error("[ ERROR ] --- First string NULL, second non-NULL\n"); + return 0; + } else if (str1 && !str2) { + print_error("[ ERROR ] --- First string non-NULL, second NULL\n"); + return 0; + } + + line = 1; + for (i = 0, line_idx = 0; str1[i] && str2[i]; ++i, ++line_idx) { + if (str1[i] != str2[i]) { + break; + } else if (str1[i] == '\n') { + ++line; + line_idx = 0; + } + } + + if (str1[i] != str2[i]) { + print_error("[ ERROR ] --- Diff at index %u, line %u:%u \"%.20s\" != \"%.20s\"\n", i, line, line_idx, + str1 + i, str2 + i); + return 0; + } + + return 1; +} + +char * +np_strstr(const char *haystack, const char *needle) +{ + char *where = strstr(haystack, needle); + if (!where) { + print_error("[ ERROR ] --- '%s' does not contain '%s'\n", haystack, needle); + } + + return where; +} + void parse_arg(int argc, char **argv) { diff --git a/tests/np_test.h b/tests/np_test.h index 35354022..761af17f 100644 --- a/tests/np_test.h +++ b/tests/np_test.h @@ -261,6 +261,16 @@ ASSERT_OK_REPLY(st); \ FREE_TEST_VARS(st); \ +#define np_assert_string_equal(str1, str2) \ + if (!np_is_string_equal(str1, str2)) { \ + fail(); \ + } + +#define np_assert_strstr(haystack, needle) \ + if (!np_strstr(haystack, needle)) { \ + fail(); \ + } + /* test state structure */ struct np_test { pid_t server_pid; @@ -284,6 +294,10 @@ struct np_test { uint32_t ntf_id; }; +int np_is_string_equal(const char *str1, const char *str2); + +char *np_strstr(const char *haystack, const char *needle); + void np_glob_setup_test_name(char *buf); int np_glob_setup_env(const char *test_name); diff --git a/tests/test_configured_subscriptions.c b/tests/test_configured_subscriptions.c new file mode 100644 index 00000000..6899f262 --- /dev/null +++ b/tests/test_configured_subscriptions.c @@ -0,0 +1,3397 @@ +/** + * @file test_configured_subscriptions.c + * @author Jeremie Leska + * @brief tests for configured subscriptions. + * + * @copyright + * Copyright 2023 6WIND S.A. + * + * This source code is licensed under BSD 3-Clause License (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "np_test.h" +#include "np_test_config.h" + +#define MAX_MSG_SIZE 8192 +#define MAX_NB_MSG 10 + +struct test_collector_t { + int nb_expected; + char xml_data[MAX_NB_MSG][MAX_MSG_SIZE]; + pthread_t th_read; + int sockfd; + char buffer[65535]; + struct sockaddr_storage msg_name; + struct mmsghdr message; + struct iovec iovec; +} tc_12345, tc_12346, tc_12347; + +pthread_barrier_t barrier_read; + +static void +collector_stop(struct test_collector_t *tc) +{ + if (!tc) { + return; + } + + close(tc->sockfd); +} + +static int +udp_create_socket(char *address, char *port, uint64_t buffer_size) +{ + struct addrinfo *addr_info; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; + + // Using getaddrinfo to support both IPv4 and IPv6 + int rc = getaddrinfo(address, port, &hints, &addr_info); + + if (rc != 0) { + printf("getaddrinfo error: %s\n", gai_strerror(rc)); + exit(EXIT_FAILURE); + } + + fprintf(stderr, "Address type: %s | %d\n", (addr_info->ai_family == AF_INET) ? "IPv4" : "IPv6", ntohs(((struct sockaddr_in *)addr_info->ai_addr)->sin_port)); + + // create socket on UDP protocol + int sockfd = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol); + + // handle error + if (sockfd < 0) { + perror("Cannot create socket"); + exit(EXIT_FAILURE); + } + + // Use SO_REUSEPORT to be able to launch multiple collector on the same address + int optval = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int)) < 0) { + perror("Cannot set SO_REUSEPORT option on socket"); + exit(EXIT_FAILURE); + } + + uint64_t receive_buf_size = buffer_size; + if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &receive_buf_size, sizeof(receive_buf_size)) < 0) { + perror("Cannot set buffer size"); + exit(EXIT_FAILURE); + } + + if (bind(sockfd, addr_info->ai_addr, (int)addr_info->ai_addrlen) == -1) { + perror("Bind failed"); + close(sockfd); + exit(EXIT_FAILURE); + } + + // free addr_info after usage + freeaddrinfo(addr_info); + + struct sockaddr_storage sin; + socklen_t len = sizeof(sin); + if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1) { + perror("getsockname"); + exit(EXIT_FAILURE); + } + + optval = 1; + // get ip header IPv4 + if (setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &optval, sizeof(int)) < 0) { + perror("Cannot set IP_PKTINFO option on socket"); + exit(EXIT_FAILURE); + } + + // get ip header IPv6 + if ((((struct sockaddr *)&sin)->sa_family == AF_INET6) && (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval, sizeof(int)) < 0)) { + perror("Cannot set IPV6_RECVPKTINFO option on socket"); + exit(EXIT_FAILURE); + } + + return sockfd; +} + +static int +collector_msg_get(struct test_collector_t *tc, char *xml_data) +{ + tc->message.msg_hdr.msg_iov = &tc->iovec; + tc->message.msg_hdr.msg_iovlen = 1; + + tc->message.msg_hdr.msg_control = NULL; + tc->message.msg_hdr.msg_controllen = 0; + + tc->message.msg_hdr.msg_iov->iov_base = tc->buffer; + tc->message.msg_hdr.msg_iov->iov_len = 65535; + + tc->message.msg_hdr.msg_name = &tc->msg_name; + tc->message.msg_hdr.msg_namelen = sizeof(struct sockaddr_storage); + + if (recvmmsg(tc->sockfd, &tc->message, 1, 0, NULL) == -1) { + perror("recvmmsg failed"); + close(tc->sockfd); + return -1; + } + + memcpy(xml_data, tc->message.msg_hdr.msg_iov->iov_base + 12, tc->message.msg_len - 12); + xml_data[tc->message.msg_len - 12] = '\0'; + + return 0; +} + +static int +collector_get(struct test_collector_t *tc) +{ + int c = 0; + + /* check if notification was sent */ + while (c < tc->nb_expected) { + if (collector_msg_get(tc, tc->xml_data[c])) { + return -1; + } + c++; + } + + pthread_barrier_wait(&barrier_read); + + return 0; +} + +static int +collector_start(struct test_collector_t *tc, char *port) +{ + tc->sockfd = udp_create_socket("127.0.0.1", port, 20971520); + if (tc->sockfd < 0) { + fprintf(stderr, "cannot create socket %s\n", port); + return -1; + } + + return 0; +} + +static void +test_collector_display_received_data() +{ +#ifdef DEBUG_TEST_CONFIGURED_SUBSCRIPTIONS + fprintf(stderr, "tc_12345\n"); + for (int c = 0; c < MAX_NB_MSG; c++) { + if (tc_12345.xml_data[c][0]) { + fprintf(stderr, "%s\n", tc_12345.xml_data[c]); + } + } + + fprintf(stderr, "tc_12346\n"); + for (int c = 0; c < MAX_NB_MSG; c++) { + if (tc_12346.xml_data[c][0]) { + fprintf(stderr, "%s\n", tc_12346.xml_data[c]); + } + } + + fprintf(stderr, "tc_12347\n"); + for (int c = 0; c < MAX_NB_MSG; c++) { + if (tc_12347.xml_data[c][0]) { + fprintf(stderr, "%s\n", tc_12347.xml_data[c]); + } + } +#endif +} + +void * +test_collector_read(void *tc) +{ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + collector_get((struct test_collector_t *)tc); + pthread_exit(NULL); +} + +static int +test_collectors_start() +{ + int ret; + ret = collector_start(&tc_12345, "12345"); + if (ret) { + fprintf(stderr, "cannot init collector\n"); + return -1; + } + + ret = collector_start(&tc_12346, "12346"); + if (ret) { + fprintf(stderr, "cannot init collector\n"); + goto stop; + } + + ret = collector_start(&tc_12347, "12347"); + if (ret) { + fprintf(stderr, "cannot init collector\n"); + goto stop; + } + + pthread_barrier_init(&barrier_read, NULL, 4); + + return 0; + +stop: + collector_stop(&tc_12345); + collector_stop(&tc_12346); + collector_stop(&tc_12347); + + return -1; +} + +static void +test_collectors_stop() +{ + collector_stop(&tc_12345); + collector_stop(&tc_12346); + collector_stop(&tc_12347); + + pthread_barrier_destroy(&barrier_read); +} + +static void +test_collector_start_read_threads() +{ + unsigned int b = 0; + pthread_attr_t attr; + + for (b = 0; b < MAX_NB_MSG; b++) { + memset(tc_12345.xml_data[b], 0, MAX_MSG_SIZE); + memset(tc_12346.xml_data[b], 0, MAX_MSG_SIZE); + memset(tc_12347.xml_data[b], 0, MAX_MSG_SIZE); + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, 1); + pthread_create(&tc_12345.th_read, &attr, test_collector_read, (void *)&tc_12345); + pthread_create(&tc_12346.th_read, &attr, test_collector_read, (void *)&tc_12346); + pthread_create(&tc_12347.th_read, &attr, test_collector_read, (void *)&tc_12347); +} + +static void +test_collector_stop_read_threads() +{ + pthread_barrier_wait(&barrier_read); + pthread_join(tc_12345.th_read, NULL); + pthread_join(tc_12346.th_read, NULL); + pthread_join(tc_12346.th_read, NULL); + +} + +static void +delete_subscription_config(void **state) +{ + struct np_test *st = *state; + const char *config; + + test_collector_start_read_threads(); + + /* remove subscriptions */ + config = + "\n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + /* remove receivers */ + config = + "\n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); +} + +static int +local_setup(void **state) +{ + struct np_test *st; + char test_name[256]; + const char *modules[] = {NP_TEST_MODULE_DIR "/notif1.yang", NP_TEST_MODULE_DIR "/notif2.yang", NULL}; + int rc; + + /* get test name */ + np_glob_setup_test_name(test_name); + + /* setup environment */ + rc = np_glob_setup_env(test_name); + assert_int_equal(rc, 0); + + /* setup netopeer2 server */ + rc = np_glob_setup_np2(state, test_name, modules); + assert_int_equal(rc, 0); + st = *state; + + /* second session */ + assert_int_equal(sr_session_start(st->conn, SR_DS_OPERATIONAL, &st->sr_sess2), SR_ERR_OK); + + /* enable replay support */ + assert_int_equal(SR_ERR_OK, sr_set_module_replay_support(st->conn, "notif1", 1)); + + /* setup NACM */ + rc = setup_nacm(state); + assert_int_equal(rc, 0); + + rc = test_collectors_start(); + assert_int_equal(rc, 0); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); + + return 0; +} + +static int +teardown_common(void **state) +{ + struct np_test *st = *state; + char *cmd; + int ret; + + /* Remove the notifications */ + if (asprintf(&cmd, "rm -rf %s/%s/data/notif/notif1.notif*", NP_SR_REPOS_DIR, st->test_name) == -1) { + return 1; + } + + ret = system(cmd); + free(cmd); + + if (ret == -1) { + return 1; + } else if (!WIFEXITED(ret) || WEXITSTATUS(ret)) { + return 1; + } + + /* reestablish NETCONF connection */ + nc_session_free(st->nc_sess, NULL); + st->nc_sess = nc_connect_unix(st->socket_path, NULL); + assert_non_null(st->nc_sess); + + return 0; +} + +static int +local_teardown(void **state) +{ + struct np_test *st = *state; + const char *modules[] = {"notif1", "notif2", NULL}; + + if (!st) { + return 0; + } + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); + + /* disable replay support */ + assert_int_equal(SR_ERR_OK, sr_set_module_replay_support(st->conn, "notif1", 0)); + + /* close the session */ + assert_int_equal(sr_session_stop(st->sr_sess2), SR_ERR_OK); + + /* Remove the notifications */ + teardown_common(state); + + test_collectors_stop(); + + /* close netopeer2 server */ + return np_glob_teardown(state, modules); +} + +static void +test_configured_subscriptions_receivers(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + np_assert_string_equal(st->str, EMPTY_GETCONFIG); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + np_assert_string_equal(st->str, EMPTY_GET); + FREE_TEST_VARS(st); + + config = + "\n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + /* Check if merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions/receiver-instances"); + expected = + "\n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_receivers_modif(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + config = + "\n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + /* merge without 3rd receiver and modify 2nd receiver port */ + config = + "\n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions/receiver-instances"); + expected = + "\n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + /* Check state merged successfully */ + GET_FILTER(st, "/subscriptions/receiver-instances"); + expected = + "\n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_add(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + config = + "\n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 3; + + test_collector_start_read_threads(); + + /* add 3 subscriptions, first subscription has 2 receivers */ + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + + np_assert_strstr(tc_12345.xml_data[0], "1"); + + assert_non_null(tc_12347.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[0], ""); + + np_assert_strstr(tc_12347.xml_data[0], "1"); + + assert_non_null(tc_12345.xml_data[1][0] == '\0'); + assert_non_null(tc_12347.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[1], ""); + + np_assert_strstr(tc_12347.xml_data[1], "3"); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 2\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 3; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_reset(void **state) +{ + struct np_test *st = *state; + const char *config; + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 3; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 2; + + test_collector_start_read_threads(); + + /* reset a receiver in a subscription */ + config = + "\n" + " \n" + " \n" + " 3\n" + " \n" + " \n" + " name2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + st->rpc = nc_rpc_act_generic_xml(config, NC_PARAMTYPE_CONST); + st->msgtype = nc_send_rpc(st->nc_sess, st->rpc, 1000, &st->msgid); + assert_int_equal(NC_MSG_RPC, st->msgtype); + st->msgtype = nc_recv_reply(st->nc_sess, st->rpc, st->msgid, 1000, &st->envp, &st->op); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12347.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[0], ""); + np_assert_strstr(tc_12347.xml_data[0], "3"); + + assert_non_null(tc_12347.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[1], ""); + + np_assert_strstr(tc_12347.xml_data[1], "3"); + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 3; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_modif(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 3; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 3; + + test_collector_start_read_threads(); + + /* replace port of receiver 2 , should restart the 3 subscriptions because they use receiver2 */ + config = + "\n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12347.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[0], ""); + + np_assert_strstr(tc_12347.xml_data[0], "1"); + + assert_non_null(tc_12347.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[1], ""); + + np_assert_strstr(tc_12347.xml_data[1], "3"); + + assert_non_null(tc_12347.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12347.xml_data[2], ""); + + np_assert_strstr(tc_12347.xml_data[2], "4"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + + np_assert_strstr(tc_12346.xml_data[0], "1"); + + assert_non_null(tc_12346.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[1], ""); + + np_assert_strstr(tc_12346.xml_data[1], "3"); + + assert_non_null(tc_12346.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[2], ""); + + np_assert_strstr(tc_12346.xml_data[2], "4"); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 4\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 3\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 3\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_modif2(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 1; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + /* change source address of subscription 1 also change the name of receiver used use receiver2 instead of receiver1 */ + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name1\n" + " receiver2\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.2\n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + + np_assert_strstr(tc_12345.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + + np_assert_strstr(tc_12346.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[1], ""); + np_assert_strstr(tc_12346.xml_data[1], "1"); + + assert_non_null(tc_12346.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[2], ""); + np_assert_strstr(tc_12346.xml_data[2], "1"); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.2\n" + " \n" + " \n" + " name1\n" + " receiver2\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.2\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver2\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 2\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 4; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_modif3(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 4; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.2\n" + " \n" + " \n" + " name1\n" + " receiver2\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + /* change source address of subscription 1 also change the name of receiver used use again receiver1 */ + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + np_assert_strstr(tc_12345.xml_data[0], "1"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + np_assert_strstr(tc_12346.xml_data[0], "1no-such-subscription"); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 3\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_yang_push(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 4; + tc_12346.nb_expected = 2; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + np_assert_strstr(tc_12345.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + np_assert_strstr(tc_12346.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[1], ""); + np_assert_strstr(tc_12346.xml_data[1], "1"); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " 0\n" + " true\n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 3\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " 0\n" + " true\n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_yang_push_modif(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + char *pos; + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " 0\n" + " true\n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 4; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + /* modify from on_change to periodic */ + config = + "\n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " \n" + " 1000\n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + np_assert_strstr(tc_12345.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12345.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[1], ""); + np_assert_strstr(tc_12345.xml_data[1], "1no-such-subscription"); + + assert_non_null(tc_12345.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[2], ""); + np_assert_strstr(tc_12345.xml_data[2], "1"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + np_assert_strstr(tc_12346.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[1], ""); + np_assert_strstr(tc_12346.xml_data[1], "1"); + + assert_non_null(tc_12346.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[2], ""); + + pos = strstr(tc_12346.xml_data[2], "1"); + + /* at least one push update event should be received */ + assert_non_null(pos); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " 1000\n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 6\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " 1000\n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 4; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); + + /* in case there are more yang push update notif */ + usleep(200000); +} + +static void +test_configured_subscriptions_back(void **state) +{ + struct np_test *st = *state; + const char *expected; + const char *config; + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " ds:operational\n" + " /state/vrf/interface/physical/enabled\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " 1000\n" + " false\n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 4; + tc_12346.nb_expected = 2; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + /* switch back to stream NETCONF for sub 1 */ + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + np_assert_strstr(tc_12345.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12345.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[1], ""); + np_assert_strstr(tc_12345.xml_data[1], "1no-such-subscription"); + + assert_non_null(tc_12345.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[2], ""); + np_assert_strstr(tc_12345.xml_data[2], "1"); + + assert_non_null(tc_12345.xml_data[3][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[3], ""); + np_assert_strstr(tc_12345.xml_data[3], "1"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + np_assert_strstr(tc_12346.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[1], ""); + np_assert_strstr(tc_12346.xml_data[1], "1"); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + expected = + "\n" + " \n" + " \n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " CONFIG notif 1\n" + " 3\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 3\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " valid\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " CONFIG notif 4\n" + " 1\n" + " 0\n" + " active\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + np_assert_string_equal(st->str, expected); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); +} + +static void +test_configured_subscriptions_remove(void **state) +{ + struct np_test *st = *state; + const char *config; + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + config = + "\n" + " \n" + " 1\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name1\n" + " receiver1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " name3\n" + " receiver1\n" + " \n" + " \n" + " \n" + " \n" + " 3\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name2\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " 4\n" + " notif1\n" + " encode-xml\n" + " send notifications\n" + " 127.0.0.1\n" + " \n" + " \n" + " name4\n" + " receiver2\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12346\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + tc_12345.nb_expected = 2; + tc_12346.nb_expected = 3; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + /* end : remove subscriptions */ + config = + "\n" + " \n" + " '/ietf-subscribed-notifications:subscriptions/subscription[id=1]'\n" + " \n" + " \n" + " '/ietf-subscribed-notifications:subscriptions/subscription[id=3]'\n" + " \n" + " \n" + " '/ietf-subscribed-notifications:subscriptions/subscription[id=4]'\n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + assert_non_null(tc_12345.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12345.xml_data[0], ""); + np_assert_strstr(tc_12345.xml_data[0], "1no-such-subscription"); + + np_assert_strstr(tc_12345.xml_data[1], ""); + np_assert_strstr(tc_12345.xml_data[1], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[0][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[0], ""); + np_assert_strstr(tc_12346.xml_data[0], "1no-such-subscription"); + + assert_non_null(tc_12346.xml_data[1][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[1], ""); + np_assert_strstr(tc_12346.xml_data[1], "3no-such-subscription"); + + assert_non_null(tc_12346.xml_data[2][0] != '\0'); + np_assert_strstr(tc_12346.xml_data[2], ""); + np_assert_strstr(tc_12346.xml_data[2], "4no-such-subscription"); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); + assert_non_null(tc_12345.xml_data[0][0] == '\0'); + assert_non_null(tc_12346.xml_data[0][0] == '\0'); + assert_non_null(tc_12346.xml_data[0][0] == '\0'); +} + +static void +test_configured_subscriptions_remove_receivers(void **state) +{ + struct np_test *st = *state; + const char *config; + + config = + "\n" + " \n" + " \n" + " receiver1\n" + " \n" + " 127.0.0.1\n" + " 12345\n" + " \n" + " \n" + " \n" + " receiver2\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + " receiver3\n" + " \n" + " 127.0.0.1\n" + " 12347\n" + " \n" + " \n" + " \n" + "\n"; + + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + test_collector_start_read_threads(); + + /* end : remove receivers */ + config = + "\n" + " \n" + " \n" + "\n"; + SEND_EDIT_RPC(st, config); + ASSERT_OK_REPLY(st); + FREE_TEST_VARS(st); + + test_collector_stop_read_threads(); + test_collector_display_received_data(); + + /* Check config merged successfully */ + GET_CONFIG_FILTER(st, "/subscriptions"); + np_assert_string_equal(st->str, EMPTY_GETCONFIG); + FREE_TEST_VARS(st); + + GET_FILTER(st, "/subscriptions"); + np_assert_string_equal(st->str, EMPTY_GET); + FREE_TEST_VARS(st); + + tc_12345.nb_expected = 0; + tc_12346.nb_expected = 0; + tc_12347.nb_expected = 0; + + delete_subscription_config(state); + + assert_non_null(tc_12345.xml_data[0][0] == '\0'); + assert_non_null(tc_12346.xml_data[0][0] == '\0'); + assert_non_null(tc_12346.xml_data[0][0] == '\0'); +} + +int +main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_teardown(test_configured_subscriptions_receivers, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_receivers_modif, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_add, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_reset, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_modif, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_modif2, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_modif3, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_yang_push, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_yang_push_modif, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_back, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_remove, teardown_common), + cmocka_unit_test_teardown(test_configured_subscriptions_remove_receivers, teardown_common) + }; + + nc_verbosity(NC_VERB_WARNING); + sr_log_stderr(SR_LL_WRN); + parse_arg(argc, argv); + return cmocka_run_group_tests(tests, local_setup, local_teardown); +} diff --git a/tests/test_sub_ntf_advanced.c b/tests/test_sub_ntf_advanced.c index e235bb0d..6a5ea059 100644 --- a/tests/test_sub_ntf_advanced.c +++ b/tests/test_sub_ntf_advanced.c @@ -139,7 +139,7 @@ test_filter_pass(void **state) /* Send the notification */ assert_int_equal(sr_notif_send_tree(st->sr_sess, st->node, 1000, 1), SR_ERR_OK); RECV_NOTIF(st); - assert_string_equal(data, st->str); + np_assert_string_equal(data, st->str); FREE_TEST_VARS(st); } @@ -187,7 +187,7 @@ test_modifysub_filter(void **state) NOTIF_PARSE(st, data); assert_int_equal(sr_notif_send_tree(st->sr_sess, st->node, 1000, 1), SR_ERR_OK); RECV_NOTIF(st); - assert_string_equal(data, st->str); + np_assert_string_equal(data, st->str); FREE_TEST_VARS(st); /* Modify the filter so that notifications do no pass */ @@ -204,7 +204,7 @@ test_modifysub_filter(void **state) " \n" "\n"; assert_int_not_equal(-1, asprintf(&ntf, template, st->ntf_id)); - assert_string_equal(st->str, ntf); + np_assert_string_equal(st->str, ntf); free(ntf); FREE_TEST_VARS(st); st->rpc = nc_rpc_modifysub(st->ntf_id, NULL, NULL, NC_PARAMTYPE_CONST); @@ -258,7 +258,7 @@ test_modifysub_stop_time(void **state) " no-such-subscription\n" "\n"; assert_int_not_equal(-1, asprintf(&ntf, template, st->ntf_id)); - assert_string_equal(st->str, ntf); + np_assert_string_equal(st->str, ntf); free(ntf); FREE_TEST_VARS(st); @@ -282,9 +282,9 @@ test_modifysub_fail_no_such_sub(void **state) SEND_RPC_MODSUB(st, 1, "", NULL); ASSERT_ERROR_REPLY(st); /* Check if correct error-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); /* Check if correct error-app-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), "ietf-subscribed-notifications:no-such-subscription"); FREE_TEST_VARS(st); } @@ -309,7 +309,7 @@ test_deletesub(void **state) " no-such-subscription\n" "\n"; assert_int_not_equal(-1, asprintf(&ntf, template, st->ntf_id)); - assert_string_equal(st->str, ntf); + np_assert_string_equal(st->str, ntf); free(ntf); FREE_TEST_VARS(st); st->rpc = nc_rpc_deletesub(st->ntf_id); @@ -335,9 +335,9 @@ test_deletesub_fail(void **state) SEND_RPC_DELSUB(st, 1); ASSERT_ERROR_REPLY(st); /* Check if correct error-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); /* Check if correct error-app-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), "ietf-subscribed-notifications:no-such-subscription"); FREE_TEST_VARS(st); } @@ -363,7 +363,7 @@ test_deletesub_fail_diff_sess(void **state) assert_int_equal(sr_notif_send_tree(st->sr_sess, st->node, 1000, 1), SR_ERR_OK); FREE_TEST_VARS(st); RECV_NOTIF(st); - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); /* Create a new session */ @@ -378,11 +378,11 @@ test_deletesub_fail_diff_sess(void **state) st->msgtype = nc_recv_reply(tmp, st->rpc, st->msgid, 2000, &st->envp, &st->op); assert_int_equal(st->msgtype, NC_MSG_REPLY); assert_null(st->op); - assert_string_equal(LYD_NAME(lyd_child(st->envp)), "rpc-error"); + np_assert_string_equal(LYD_NAME(lyd_child(st->envp)), "rpc-error"); /* Check if correct error-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); /* Check if correct error-app-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), "ietf-subscribed-notifications:no-such-subscription"); FREE_TEST_VARS(st); @@ -421,7 +421,7 @@ test_ds_subscriptions(void **state) GET_FILTER(st, "/subscriptions"); assert_int_not_equal(-1, asprintf(&expected, template, st->ntf_id, nc_session_get_id(st->nc_sess))); - assert_string_equal(st->str, expected); + np_assert_string_equal(st->str, expected); free(expected); FREE_TEST_VARS(st); } @@ -469,7 +469,7 @@ test_ds_subscriptions_sent_event(void **state) GET_FILTER(st, "/subscriptions"); assert_int_not_equal(-1, asprintf(&expected, template, st->ntf_id, nc_session_get_id(st->nc_sess))); - assert_string_equal(st->str, expected); + np_assert_string_equal(st->str, expected); free(expected); FREE_TEST_VARS(st); } @@ -524,7 +524,7 @@ test_ds_subscriptions_excluded_event(void **state) GET_FILTER(st, "/subscriptions"); assert_int_not_equal(-1, asprintf(&expected, template, st->ntf_id, nc_session_get_id(st->nc_sess))); - assert_string_equal(st->str, expected); + np_assert_string_equal(st->str, expected); free(expected); FREE_TEST_VARS(st); } @@ -579,7 +579,7 @@ test_multiple_subscriptions(void **state) GET_FILTER(st, "/subscriptions"); nc_sess_id = nc_session_get_id(st->nc_sess); assert_int_not_equal(-1, asprintf(&expected, template, tmp_id, nc_sess_id, st->ntf_id, nc_sess_id)); - assert_string_equal(st->str, expected); + np_assert_string_equal(st->str, expected); free(expected); FREE_TEST_VARS(st); } @@ -658,7 +658,7 @@ test_multiple_subscriptions_notif(void **state) nc_sess_id = nc_session_get_id(st->nc_sess); assert_int_not_equal(-1, asprintf(&expected, template, tmp_ids[0], nc_sess_id, tmp_ids[1], nc_sess_id, tmp_ids[2], nc_sess_id)); - assert_string_equal(st->str, expected); + np_assert_string_equal(st->str, expected); free(expected); FREE_TEST_VARS(st); } @@ -701,7 +701,7 @@ test_multiple_subscriptions_notif_interlaced(void **state) assert_int_equal(sr_notif_send_tree(st->sr_sess, st->node, 1000, 1), SR_ERR_OK); FREE_TEST_VARS(st); RECV_NOTIF(st); - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); /* Send another notification to the first session */ @@ -718,7 +718,7 @@ test_multiple_subscriptions_notif_interlaced(void **state) /* Receive the notification sent before establishing another subscription and check it */ RECV_NOTIF(st); - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); /* Check for establishing the sub */ @@ -755,7 +755,7 @@ test_multiple_subscriptions_notif_interlaced(void **state) "\n" " Test\n" "\n"; - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); /* Receive the notification from second sub */ @@ -769,7 +769,7 @@ test_multiple_subscriptions_notif_interlaced(void **state) " \n" " \n" "\n"; - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); } @@ -811,7 +811,7 @@ test_killsub_fail_nacm(void **state) /* Should fail on NACM */ SEND_RPC_KILLSUB(st, 1); ASSERT_ERROR_REPLY(st); - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "access-denied"); + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "access-denied"); FREE_TEST_VARS(st); } @@ -848,9 +848,9 @@ test_killsub_fail_no_such_sub(void **state) /* Should fail on no such sub */ ASSERT_ERROR_REPLY(st); /* Check if correct error-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next), "invalid-value"); /* Check if correct error-app-tag */ - assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), + np_assert_string_equal(lyd_get_value(lyd_child(lyd_child(st->envp))->next->next->next), "ietf-subscribed-notifications:no-such-subscription"); FREE_TEST_VARS(st); } @@ -876,7 +876,7 @@ test_killsub_same_sess(void **state) assert_int_equal(sr_notif_send_tree(st->sr_sess, st->node, 1000, 1), SR_ERR_OK); FREE_TEST_VARS(st); RECV_NOTIF(st); - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); /* Kill it */ @@ -889,7 +889,7 @@ test_killsub_same_sess(void **state) " no-such-subscription\n" "\n"; assert_int_not_equal(-1, asprintf(&ntf, template, st->ntf_id)); - assert_string_equal(st->str, ntf); + np_assert_string_equal(st->str, ntf); free(ntf); FREE_TEST_VARS(st); st->rpc = nc_rpc_killsub(st->ntf_id); @@ -930,7 +930,7 @@ test_killsub_diff_sess(void **state) assert_int_equal(sr_notif_send_tree(st->sr_sess, st->node, 1000, 1), SR_ERR_OK); FREE_TEST_VARS(st); RECV_NOTIF(st); - assert_string_equal(st->str, data); + np_assert_string_equal(st->str, data); FREE_TEST_VARS(st); /* Create a new session */ @@ -949,7 +949,7 @@ test_killsub_diff_sess(void **state) " no-such-subscription\n" "\n"; assert_int_not_equal(-1, asprintf(&ntf, template, st->ntf_id)); - assert_string_equal(st->str, ntf); + np_assert_string_equal(st->str, ntf); free(ntf); FREE_TEST_VARS(st); st->rpc = nc_rpc_killsub(st->ntf_id); @@ -957,7 +957,7 @@ test_killsub_diff_sess(void **state) st->msgtype = nc_recv_reply(tmp, st->rpc, st->msgid, 2000, &st->envp, &st->op); assert_int_equal(st->msgtype, NC_MSG_REPLY); assert_null(st->op); - assert_string_equal(LYD_NAME(lyd_child(st->envp)), "ok"); + np_assert_string_equal(LYD_NAME(lyd_child(st->envp)), "ok"); FREE_TEST_VARS(st); /* Send notification, should NOT arrive */ @@ -975,1766 +975,6 @@ test_killsub_diff_sess(void **state) nc_session_free(tmp, NULL); } -static void -test_configured_subscriptions(void **state) -{ - struct np_test *st = *state; - const char *expected; - - /* end : remove subscriptions */ - const char *config = - "\n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* end : remove receivers */ - config = - "\n" - " \n" - " \n" - "\n"; - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - assert_string_equal(st->str, EMPTY_GETCONFIG); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - assert_string_equal(st->str, EMPTY_GET); - FREE_TEST_VARS(st); - - config = - "\n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check if merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions/receiver-instances"); - expected = - "\n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* merge without 3rd receiver and modify 2nd receiver port */ - config = - "\n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions/receiver-instances"); - expected = - "\n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* Check state merged successfully */ - GET_FILTER(st, "/subscriptions/receiver-instances"); - expected = - "\n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* add 3 subscriptions, first subscription has 2 receivers */ - config = - "\n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - /* comment for now */ - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* reset a receiver in a subscription */ - config = - "\n" - " \n" - " \n" - " 3\n" - " \n" - " \n" - " name2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - st->rpc = nc_rpc_act_generic_xml(config, NC_PARAMTYPE_CONST); - st->msgtype = nc_send_rpc(st->nc_sess, st->rpc, 1000, &st->msgid); - assert_int_equal(NC_MSG_RPC, st->msgtype); - st->msgtype = nc_recv_reply(st->nc_sess, st->rpc, st->msgid, 1000, &st->envp, &st->op); - FREE_TEST_VARS(st); - - /* replace port of receiver 2 , should restart the 3 subscriptions because they use receiver2 */ - config = - "\n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* change source address of subscription 1 also change the name of receiver used use receiver2 instead of receiver1 */ - config = - "\n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name1\n" - " receiver2\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.2\n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.2\n" - " \n" - " \n" - " name1\n" - " receiver2\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.2\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver2\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - /* comment for now */ - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* change source address of subscription 1 also change the name of receiver used use receiver2 instead of receiver1 */ - config = - "\n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - /* comment for now */ - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - config = - "\n" - " \n" - " 1\n" - " ds:operational\n" - " /state/vrf/interface/physical/enabled\n" - " \n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " ds:operational\n" - " /state/vrf/interface/physical/enabled\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " \n" - " 0\n" - " true\n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " ds:operational\n" - " /state/vrf/interface/physical/enabled\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " 0\n" - " true\n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - /* comment for now */ - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* modify from on_change to periodic */ - config = - "\n" - " \n" - " 1\n" - " ds:operational\n" - " /state/vrf/interface/physical/enabled\n" - " \n" - " 3000\n" - " \n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " ds:operational\n" - " /state/vrf/interface/physical/enabled\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " \n" - " 3000\n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " ds:operational\n" - " /state/vrf/interface/physical/enabled\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " 3000\n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - /* comment for now */ - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* switch back to stream NETCONF for sub 1 */ - config = - "\n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - expected = - "\n" - " \n" - " \n" - " \n" - " 1\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name1\n" - " receiver1\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " name3\n" - " receiver1\n" - " \n" - " \n" - " CONFIG notif 1\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 3\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name2\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 3\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " 4\n" - " notif1\n" - " encode-xml\n" - " send notifications\n" - " 127.0.0.1\n" - " valid\n" - " \n" - " \n" - " name4\n" - " receiver2\n" - " \n" - " \n" - " CONFIG notif 4\n" - " 0\n" - " 0\n" - " active\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " receiver1\n" - " \n" - " 127.0.0.1\n" - " 12345\n" - " \n" - " \n" - " \n" - " receiver2\n" - " \n" - " 127.0.0.1\n" - " 12346\n" - " \n" - " \n" - " \n" - " receiver3\n" - " \n" - " 127.0.0.1\n" - " 12347\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; - - assert_string_equal(st->str, expected); - FREE_TEST_VARS(st); - - /* end : remove subscriptions */ - config = - "\n" - " \n" - " '/ietf-subscribed-notifications:subscriptions/subscription[id=1]'\n" - " \n" - " \n" - " '/ietf-subscribed-notifications:subscriptions/subscription[id=3]'\n" - " \n" - " \n" - " '/ietf-subscribed-notifications:subscriptions/subscription[id=4]'\n" - " \n" - "\n"; - - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* end : remove receivers */ - config = - "\n" - " \n" - " \n" - "\n"; - SEND_EDIT_RPC(st, config); - ASSERT_OK_REPLY(st); - FREE_TEST_VARS(st); - - /* Check config merged successfully */ - GET_CONFIG_FILTER(st, "/subscriptions"); - assert_string_equal(st->str, EMPTY_GETCONFIG); - FREE_TEST_VARS(st); - - GET_FILTER(st, "/subscriptions"); - assert_string_equal(st->str, EMPTY_GET); - FREE_TEST_VARS(st); -} - int main(int argc, char **argv) { @@ -2756,8 +996,7 @@ main(int argc, char **argv) cmocka_unit_test_teardown(test_killsub_fail_nacm, teardown_nacm), cmocka_unit_test_setup_teardown(test_killsub_fail_no_such_sub, setup_test_killsub, teardown_nacm), cmocka_unit_test_setup_teardown(test_killsub_same_sess, setup_test_killsub, teardown_nacm), - cmocka_unit_test_setup_teardown(test_killsub_diff_sess, setup_test_killsub, teardown_nacm), - cmocka_unit_test_teardown(test_configured_subscriptions, teardown_common) + cmocka_unit_test_setup_teardown(test_killsub_diff_sess, setup_test_killsub, teardown_nacm) }; nc_verbosity(NC_VERB_WARNING);