Adding upstream version 2.0.24.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e508fcfeb9
commit
afb0a8fea7
118 changed files with 45084 additions and 0 deletions
78
tests/CMakeLists.txt
Normal file
78
tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,78 @@
|
|||
# headers test for including compat.h
|
||||
add_test(NAME headers
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/compat/check_includes.sh ${CMAKE_SOURCE_DIR}/src/)
|
||||
|
||||
# format
|
||||
if (${SOURCE_FORMAT_ENABLED})
|
||||
add_test(NAME format WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND make format-check)
|
||||
endif()
|
||||
|
||||
# list of all the tests in each directory
|
||||
set(tests test_io test_fd_comm test_init_destroy_client test_init_destroy_server test_client_thread test_thread_messages)
|
||||
set(client_tests test_client test_client_messages)
|
||||
|
||||
# add -Wl,--wrap flags
|
||||
set(test test_client_ssh)
|
||||
set(${test}_mock_funcs connect ssh_connect ssh_userauth_none ssh_userauth_kbdint ssh_is_connected
|
||||
ssh_channel_open_session ssh_channel_request_subsystem ssh_channel_is_close ssh_channel_write
|
||||
ssh_channel_poll_timeout ssh_userauth_password nc_handshake_io nc_ctx_check_and_fill
|
||||
ssh_userauth_try_publickey ssh_userauth_publickey nc_sock_listen_inet nc_sock_accept_binds nc_accept_callhome_ssh_sock)
|
||||
set(${test}_wrap_link_flags "-Wl")
|
||||
foreach(mock_func IN LISTS ${test}_mock_funcs)
|
||||
set(${test}_wrap_link_flags "${${test}_wrap_link_flags},--wrap=${mock_func}")
|
||||
endforeach()
|
||||
|
||||
set(test test_client_tls)
|
||||
set(${test}_mock_funcs connect SSL_connect nc_send_hello_io nc_handshake_io nc_ctx_check_and_fill)
|
||||
set(${test}_wrap_link_flags "-Wl")
|
||||
foreach(mock_func IN LISTS ${test}_mock_funcs)
|
||||
set(${test}_wrap_link_flags "${${test}_wrap_link_flags},--wrap=${mock_func}")
|
||||
endforeach()
|
||||
|
||||
#append tests depending on SSH/TLS
|
||||
if(ENABLE_SSH OR ENABLE_TLS)
|
||||
list(APPEND tests test_server_thread)
|
||||
if(ENABLE_SSH)
|
||||
list(APPEND client_tests test_client_ssh)
|
||||
endif()
|
||||
|
||||
if(ENABLE_TLS)
|
||||
list(APPEND client_tests test_client_tls)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(src IN LISTS libsrc)
|
||||
list(APPEND test_srcs "../${src}")
|
||||
endforeach()
|
||||
add_library(testobj OBJECT ${test_srcs})
|
||||
|
||||
foreach(test_name IN LISTS tests)
|
||||
add_executable(${test_name} $<TARGET_OBJECTS:testobj> ${test_name}.c)
|
||||
target_link_libraries(${test_name} ${CMOCKA_LIBRARIES} ${LIBYANG_LIBRARIES} netconf2)
|
||||
target_include_directories(${test_name} PRIVATE ${CMOCKA_INCLUDE_DIR})
|
||||
set_target_properties(${test_name} PROPERTIES LINK_FLAGS "${${test_name}_wrap_link_flags}")
|
||||
add_test(NAME ${test_name} COMMAND $<TARGET_FILE:${test_name}>)
|
||||
endforeach()
|
||||
|
||||
foreach(test_name IN LISTS client_tests)
|
||||
add_executable(${test_name} $<TARGET_OBJECTS:testobj> ./client/${test_name}.c)
|
||||
target_link_libraries(${test_name} ${CMOCKA_LIBRARIES} ${LIBYANG_LIBRARIES} netconf2)
|
||||
target_include_directories(${test_name} PRIVATE ${CMOCKA_INCLUDE_DIR})
|
||||
set_target_properties(${test_name} PROPERTIES LINK_FLAGS "${${test_name}_wrap_link_flags}")
|
||||
add_test(NAME ${test_name} COMMAND $<TARGET_FILE:${test_name}>)
|
||||
endforeach()
|
||||
|
||||
if(ENABLE_VALGRIND_TESTS)
|
||||
foreach(test_name IN LISTS tests)
|
||||
add_test(${test_name}_valgrind valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1
|
||||
--suppressions=${PROJECT_SOURCE_DIR}/tests/ld.supp ${CMAKE_BINARY_DIR}/tests/${test_name})
|
||||
endforeach()
|
||||
|
||||
foreach(test_name IN LISTS client_tests)
|
||||
add_test(${test_name}_valgrind valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1
|
||||
--suppressions=${PROJECT_SOURCE_DIR}/tests/ld.supp ${CMAKE_BINARY_DIR}/tests/${test_name})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src ${PROJECT_BINARY_DIR})
|
||||
configure_file("${PROJECT_SOURCE_DIR}/tests/config.h.in" "${PROJECT_BINARY_DIR}/tests/config.h" ESCAPE_QUOTES @ONLY)
|
125
tests/client/test_client.c
Normal file
125
tests/client/test_client.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <libyang/libyang.h>
|
||||
#include <log.h>
|
||||
#include <session_client.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
static int
|
||||
setup_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
nc_verbosity(NC_VERB_VERBOSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_setting_schema_searchpath(void **state)
|
||||
{
|
||||
(void)state;
|
||||
const char *path;
|
||||
int ret;
|
||||
|
||||
/* initiate client */
|
||||
nc_client_init();
|
||||
|
||||
path = nc_client_get_schema_searchpath();
|
||||
assert_null(path);
|
||||
|
||||
ret = nc_client_set_schema_searchpath("path");
|
||||
assert_int_equal(ret, 0);
|
||||
path = nc_client_get_schema_searchpath();
|
||||
assert_string_equal(path, "path");
|
||||
|
||||
ret = nc_client_set_schema_searchpath("path1");
|
||||
assert_int_equal(ret, 0);
|
||||
path = nc_client_get_schema_searchpath();
|
||||
assert_string_equal(path, "path1");
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
test_clb(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev, void *user_data,
|
||||
LYS_INFORMAT *format, const char **model_data, void (**free_module_data)(void *model_data, void *user_data))
|
||||
{
|
||||
(void)mod_name;
|
||||
(void)mod_rev;
|
||||
(void)submod_name;
|
||||
(void)sub_rev;
|
||||
(void)user_data;
|
||||
(void)format;
|
||||
(void)model_data;
|
||||
(void)free_module_data;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
test_clb1(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev, void *user_data,
|
||||
LYS_INFORMAT *format, const char **model_data, void (**free_module_data)(void *model_data, void *user_data))
|
||||
{
|
||||
(void)mod_name;
|
||||
(void)mod_rev;
|
||||
(void)submod_name;
|
||||
(void)sub_rev;
|
||||
(void)user_data;
|
||||
(void)format;
|
||||
(void)model_data;
|
||||
(void)free_module_data;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_setting_schema_callback(void **state)
|
||||
{
|
||||
(void)state;
|
||||
ly_module_imp_clb ret_f;
|
||||
char *data_ret;
|
||||
int ret;
|
||||
|
||||
ret_f = nc_client_get_schema_callback((void **)&data_ret);
|
||||
assert_null(ret_f);
|
||||
assert_null(data_ret);
|
||||
|
||||
ret = nc_client_set_schema_callback(test_clb, "DATA");
|
||||
assert_int_equal(ret, 0);
|
||||
ret_f = nc_client_get_schema_callback((void **)&data_ret);
|
||||
assert_ptr_equal(test_clb, ret_f);
|
||||
assert_string_equal("DATA", data_ret);
|
||||
|
||||
ret = nc_client_set_schema_callback(test_clb1, "DATA1");
|
||||
assert_int_equal(ret, 0);
|
||||
ret_f = nc_client_get_schema_callback((void **)&data_ret);
|
||||
assert_ptr_equal(test_clb1, ret_f);
|
||||
assert_string_equal("DATA1", data_ret);
|
||||
|
||||
/* destroy client */
|
||||
nc_client_destroy();
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_setting_schema_searchpath, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_setting_schema_callback, setup_f, teardown_f),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
709
tests/client/test_client_messages.c
Normal file
709
tests/client/test_client_messages.c
Normal file
|
@ -0,0 +1,709 @@
|
|||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <config.h>
|
||||
#include <libyang/libyang.h>
|
||||
#include <log.h>
|
||||
#include <messages_p.h>
|
||||
#include <session_client.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
static int
|
||||
setup_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
nc_verbosity(NC_VERB_VERBOSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_act_generic_xml(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
struct nc_rpc_act_generic *generic_rpc = NULL;
|
||||
|
||||
/* create generic rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_act_generic_xml("xml", NC_PARAMTYPE_CONST);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_ACT_GENERIC);
|
||||
generic_rpc = (struct nc_rpc_act_generic *)rpc;
|
||||
assert_int_equal(generic_rpc->type, NC_RPC_ACT_GENERIC);
|
||||
assert_int_equal(generic_rpc->has_data, 0);
|
||||
assert_string_equal(generic_rpc->content.xml_str, "xml");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create generic rpc with NC_PARAMTYPE_FREE */
|
||||
char *str = strdup("str");
|
||||
|
||||
rpc = nc_rpc_act_generic_xml(str, NC_PARAMTYPE_FREE);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_ACT_GENERIC);
|
||||
generic_rpc = (struct nc_rpc_act_generic *)rpc;
|
||||
assert_int_equal(generic_rpc->type, NC_RPC_ACT_GENERIC);
|
||||
assert_int_equal(generic_rpc->has_data, 0);
|
||||
assert_string_equal(generic_rpc->content.xml_str, str);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create generic rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_act_generic_xml("xml", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_ACT_GENERIC);
|
||||
generic_rpc = (struct nc_rpc_act_generic *)rpc;
|
||||
assert_int_equal(generic_rpc->type, NC_RPC_ACT_GENERIC);
|
||||
assert_int_equal(generic_rpc->has_data, 0);
|
||||
assert_string_equal(generic_rpc->content.xml_str, "xml");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_act_generic(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
struct nc_rpc_act_generic *generic_rpc = NULL;
|
||||
struct lyd_node node;
|
||||
|
||||
node.next = NULL;
|
||||
node.prev = &node;
|
||||
|
||||
rpc = nc_rpc_act_generic(&node, NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_ACT_GENERIC);
|
||||
generic_rpc = (struct nc_rpc_act_generic *)rpc;
|
||||
assert_int_equal(generic_rpc->type, NC_RPC_ACT_GENERIC);
|
||||
assert_int_equal(generic_rpc->has_data, 1);
|
||||
assert_ptr_equal(generic_rpc->content.data, &node);
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of getconfig rpc are set correctly */
|
||||
void
|
||||
check_getconfig(struct nc_rpc *rpc, enum NC_DATASTORE_TYPE source, char *filter, NC_WD_MODE wd_mode)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_GETCONFIG);
|
||||
struct nc_rpc_getconfig *getconfig_rpc = (struct nc_rpc_getconfig *)rpc;
|
||||
|
||||
assert_int_equal(getconfig_rpc->type, NC_RPC_GETCONFIG);
|
||||
assert_int_equal(getconfig_rpc->source, source);
|
||||
assert_string_equal(getconfig_rpc->filter, filter);
|
||||
assert_int_equal(getconfig_rpc->wd_mode, wd_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_getconfig(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create getconfig rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_getconfig(NC_DATASTORE_CANDIDATE, "filter-string", NC_WD_UNKNOWN, NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_getconfig(rpc, NC_DATASTORE_CANDIDATE, "filter-string", NC_WD_UNKNOWN);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create getconfig rpc with NC_PARAMTYPE_FREE */
|
||||
char *filter = strdup("string");
|
||||
|
||||
rpc = nc_rpc_getconfig(NC_DATASTORE_CONFIG, filter, NC_WD_EXPLICIT, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_getconfig(rpc, NC_DATASTORE_CONFIG, filter, NC_WD_EXPLICIT);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create getconfig rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_getconfig(NC_DATASTORE_RUNNING, "filter", NC_WD_ALL, NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_getconfig(rpc, NC_DATASTORE_RUNNING, "filter", NC_WD_ALL);
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of edit rpc are set correctly */
|
||||
void
|
||||
check_edit(struct nc_rpc *rpc, NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
|
||||
NC_RPC_EDIT_ERROPT error_opt, const char *edit_content)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_EDIT);
|
||||
struct nc_rpc_edit *edit_rpc = (struct nc_rpc_edit *)rpc;
|
||||
|
||||
assert_int_equal(edit_rpc->type, NC_RPC_EDIT);
|
||||
assert_int_equal(edit_rpc->target, target);
|
||||
assert_int_equal(edit_rpc->default_op, default_op);
|
||||
assert_int_equal(edit_rpc->test_opt, test_opt);
|
||||
assert_int_equal(edit_rpc->error_opt, error_opt);
|
||||
assert_string_equal(edit_rpc->edit_cont, edit_content);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_edit(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create edit rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_edit(NC_DATASTORE_RUNNING, NC_RPC_EDIT_DFLTOP_REPLACE, NC_RPC_EDIT_TESTOPT_TESTSET,
|
||||
NC_RPC_EDIT_ERROPT_STOP, "url", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_edit(rpc, NC_DATASTORE_RUNNING, NC_RPC_EDIT_DFLTOP_REPLACE,
|
||||
NC_RPC_EDIT_TESTOPT_TESTSET, NC_RPC_EDIT_ERROPT_STOP, "url");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create edit rpc with NC_PARAMTYPE_FREE */
|
||||
char *str = strdup("string");
|
||||
|
||||
rpc = nc_rpc_edit(NC_DATASTORE_CANDIDATE, NC_RPC_EDIT_DFLTOP_MERGE, NC_RPC_EDIT_TESTOPT_SET,
|
||||
NC_RPC_EDIT_ERROPT_ROLLBACK, str, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_edit(rpc, NC_DATASTORE_CANDIDATE, NC_RPC_EDIT_DFLTOP_MERGE,
|
||||
NC_RPC_EDIT_TESTOPT_SET, NC_RPC_EDIT_ERROPT_ROLLBACK, str);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create edit rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_edit(NC_DATASTORE_CONFIG, NC_RPC_EDIT_DFLTOP_NONE, NC_RPC_EDIT_TESTOPT_TEST,
|
||||
NC_RPC_EDIT_ERROPT_CONTINUE, "url1", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_edit(rpc, NC_DATASTORE_CONFIG, NC_RPC_EDIT_DFLTOP_NONE,
|
||||
NC_RPC_EDIT_TESTOPT_TEST, NC_RPC_EDIT_ERROPT_CONTINUE, "url1");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of copy rpc are set correctly */
|
||||
void
|
||||
check_copy(struct nc_rpc *rpc, NC_DATASTORE target, const char *url_trg, NC_DATASTORE source,
|
||||
const char *url_or_config_src, NC_WD_MODE wd_mode)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_COPY);
|
||||
struct nc_rpc_copy *copy_rpc = (struct nc_rpc_copy *)rpc;
|
||||
|
||||
assert_int_equal(copy_rpc->type, NC_RPC_COPY);
|
||||
assert_int_equal(copy_rpc->target, target);
|
||||
assert_string_equal(copy_rpc->url_trg, url_trg);
|
||||
assert_int_equal(copy_rpc->source, source);
|
||||
assert_string_equal(copy_rpc->url_config_src, url_or_config_src);
|
||||
assert_int_equal(copy_rpc->wd_mode, wd_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_copy(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create copy rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_copy(NC_DATASTORE_RUNNING, "target-url", NC_DATASTORE_RUNNING, "src-url",
|
||||
NC_WD_ALL, NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_copy(rpc, NC_DATASTORE_RUNNING, "target-url", NC_DATASTORE_RUNNING, "src-url", NC_WD_ALL);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create copy rpc with NC_PARAMTYPE_FREE */
|
||||
char *target = strdup("target");
|
||||
char *src = strdup("src");
|
||||
|
||||
rpc = nc_rpc_copy(NC_DATASTORE_STARTUP, target, NC_DATASTORE_RUNNING, src,
|
||||
NC_WD_ALL_TAG, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_copy(rpc, NC_DATASTORE_STARTUP, target, NC_DATASTORE_RUNNING, src, NC_WD_ALL_TAG);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create copy rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_copy(NC_DATASTORE_STARTUP, "url", NC_DATASTORE_CANDIDATE, "url",
|
||||
NC_WD_TRIM, NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_copy(rpc, NC_DATASTORE_STARTUP, "url", NC_DATASTORE_CANDIDATE, "url", NC_WD_TRIM);
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of delete rpc are set correctly */
|
||||
void
|
||||
check_delete(struct nc_rpc *rpc, NC_DATASTORE target, const char *url)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_DELETE);
|
||||
struct nc_rpc_delete *delete_rpc = (struct nc_rpc_delete *)rpc;
|
||||
|
||||
assert_int_equal(delete_rpc->type, NC_RPC_DELETE);
|
||||
assert_int_equal(delete_rpc->target, target);
|
||||
assert_string_equal(delete_rpc->url, url);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_delete(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create delete rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_delete(NC_DATASTORE_RUNNING, "target-url", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_delete(rpc, NC_DATASTORE_RUNNING, "target-url");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create delete rpc with NC_PARAMTYPE_FREE */
|
||||
char *url = strdup("url");
|
||||
|
||||
rpc = nc_rpc_delete(NC_DATASTORE_CANDIDATE, url, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_delete(rpc, NC_DATASTORE_CANDIDATE, url);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create delete rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_delete(NC_DATASTORE_CONFIG, "target", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_delete(rpc, NC_DATASTORE_CONFIG, "target");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_lock(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
struct nc_rpc_lock *lock_rpc = NULL;
|
||||
|
||||
rpc = nc_rpc_lock(NC_DATASTORE_RUNNING);
|
||||
assert_non_null(rpc);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_LOCK);
|
||||
|
||||
lock_rpc = (struct nc_rpc_lock *)rpc;
|
||||
assert_int_equal(lock_rpc->type, NC_RPC_LOCK);
|
||||
assert_int_equal(lock_rpc->target, NC_DATASTORE_RUNNING);
|
||||
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_unlock(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
struct nc_rpc_lock *unlock_rpc = NULL;
|
||||
|
||||
rpc = nc_rpc_unlock(NC_DATASTORE_RUNNING);
|
||||
assert_non_null(rpc);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_UNLOCK);
|
||||
|
||||
unlock_rpc = (struct nc_rpc_lock *)rpc;
|
||||
assert_int_equal(unlock_rpc->type, NC_RPC_UNLOCK);
|
||||
assert_int_equal(unlock_rpc->target, NC_DATASTORE_RUNNING);
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of get rpc are set correctly */
|
||||
void
|
||||
check_get_rpc(struct nc_rpc *rpc, const char *filter, NC_WD_MODE wd_mode)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_GET);
|
||||
struct nc_rpc_get *get_rpc = (struct nc_rpc_get *)rpc;
|
||||
|
||||
assert_int_equal(get_rpc->type, NC_RPC_GET);
|
||||
assert_string_equal(get_rpc->filter, filter);
|
||||
assert_int_equal(get_rpc->wd_mode, wd_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_get(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create get rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_get("filter", NC_WD_ALL, NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_get_rpc(rpc, "filter", NC_WD_ALL);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create get rpc with NC_PARAMTYPE_FREE */
|
||||
char *str = strdup("string");
|
||||
|
||||
rpc = nc_rpc_get(str, NC_WD_EXPLICIT, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_get_rpc(rpc, str, NC_WD_EXPLICIT);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create get rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_get("filter-string", NC_WD_UNKNOWN, NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_get_rpc(rpc, "filter-string", NC_WD_UNKNOWN);
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_kill(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
struct nc_rpc_kill *kill_rpc = NULL;
|
||||
|
||||
rpc = nc_rpc_kill(10);
|
||||
assert_non_null(rpc);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_KILL);
|
||||
|
||||
kill_rpc = (struct nc_rpc_kill *)rpc;
|
||||
assert_int_equal(kill_rpc->type, NC_RPC_KILL);
|
||||
assert_int_equal(kill_rpc->sid, 10);
|
||||
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of commit rpc are set correctly */
|
||||
void
|
||||
check_commit_rpc(struct nc_rpc *rpc, int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_COMMIT);
|
||||
struct nc_rpc_commit *commit_rpc = (struct nc_rpc_commit *)rpc;
|
||||
|
||||
assert_int_equal(commit_rpc->type, NC_RPC_COMMIT);
|
||||
assert_int_equal(commit_rpc->confirmed, confirmed);
|
||||
assert_int_equal(commit_rpc->confirm_timeout, confirm_timeout);
|
||||
assert_string_equal(commit_rpc->persist, persist);
|
||||
assert_string_equal(commit_rpc->persist_id, persist_id);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_commit(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create commit rpc with NC_PARAMTYPE_CONST*/
|
||||
rpc = nc_rpc_commit(1, 100, "persist", "persist-id", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_commit_rpc(rpc, 1, 100, "persist", "persist-id");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create commit rpc with NC_PARAMTYPE_FREE*/
|
||||
char *str1 = strdup("str1");
|
||||
char *str2 = strdup("str2");
|
||||
|
||||
rpc = nc_rpc_commit(2, 5, str1, str2, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_commit_rpc(rpc, 2, 5, str1, str2);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create commit rpc with NC_PARAMTYPE_DUP_AND_FREE*/
|
||||
rpc = nc_rpc_commit(10, 200, "persistent", "persistent-id", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_commit_rpc(rpc, 10, 200, "persistent", "persistent-id");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_discard(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
rpc = nc_rpc_discard();
|
||||
assert_non_null(rpc);
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_DISCARD);
|
||||
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of cancel rpc are set correctly */
|
||||
void
|
||||
check_cancel_rpc(struct nc_rpc *rpc, const char *persist_id)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_CANCEL);
|
||||
struct nc_rpc_cancel *cancel_rpc = (struct nc_rpc_cancel *)rpc;
|
||||
|
||||
assert_int_equal(cancel_rpc->type, NC_RPC_CANCEL);
|
||||
assert_string_equal(cancel_rpc->persist_id, persist_id);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_cancel(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create cancel rpc with NC_PARAMTYPE_CONST*/
|
||||
rpc = nc_rpc_cancel("persist-id", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_cancel_rpc(rpc, "persist-id");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create cancel rpc with NC_PARAMTYPE_FREE*/
|
||||
char *str = strdup("string");
|
||||
|
||||
rpc = nc_rpc_cancel(str, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_cancel_rpc(rpc, str);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create cancel rpc with NC_PARAMTYPE_DUP_AND_FREE*/
|
||||
rpc = nc_rpc_cancel("id", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_cancel_rpc(rpc, "id");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of validate rpc are set correctly */
|
||||
void
|
||||
check_validate_rpc(struct nc_rpc *rpc, NC_DATASTORE source, const char *url_or_config)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_VALIDATE);
|
||||
struct nc_rpc_validate *validate_rpc = (struct nc_rpc_validate *)rpc;
|
||||
|
||||
assert_int_equal(validate_rpc->type, NC_RPC_VALIDATE);
|
||||
assert_int_equal(validate_rpc->source, source);
|
||||
assert_string_equal(validate_rpc->url_config_src, url_or_config);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_validate(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create validate rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_validate(NC_DATASTORE_RUNNING, "url", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_validate_rpc(rpc, NC_DATASTORE_RUNNING, "url");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create validate rpc with NC_PARAMTYPE_FREE */
|
||||
char *str = strdup("string");
|
||||
|
||||
rpc = nc_rpc_validate(NC_DATASTORE_CANDIDATE, str, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_validate_rpc(rpc, NC_DATASTORE_CANDIDATE, str);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create validate rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_validate(NC_DATASTORE_CONFIG, "url1", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_validate_rpc(rpc, NC_DATASTORE_CONFIG, "url1");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of getschema rpc are set correctly */
|
||||
void
|
||||
check_getschema_rpc(struct nc_rpc *rpc, const char *identifier, const char *version, const char *format)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_GETSCHEMA);
|
||||
struct nc_rpc_getschema *getchema_rpc = (struct nc_rpc_getschema *)rpc;
|
||||
|
||||
assert_int_equal(getchema_rpc->type, NC_RPC_GETSCHEMA);
|
||||
assert_string_equal(getchema_rpc->identifier, identifier);
|
||||
assert_string_equal(getchema_rpc->version, version);
|
||||
assert_string_equal(getchema_rpc->format, format);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_getschema(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create getchema with NC_PARAMTYPE_CONST*/
|
||||
rpc = nc_rpc_getschema("id", "version", "format", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_getschema_rpc(rpc, "id", "version", "format");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create getchema with NC_PARAMTYPE_FREE*/
|
||||
char *str1 = strdup("str1");
|
||||
char *str2 = strdup("str2");
|
||||
char *str3 = strdup("str3");
|
||||
|
||||
rpc = nc_rpc_getschema(str1, str2, str3, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_getschema_rpc(rpc, str1, str2, str3);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create getchema with NC_PARAMTYPE_DUP_AND_FREE*/
|
||||
rpc = nc_rpc_getschema("id1", "version1", "format1", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_getschema_rpc(rpc, "id1", "version1", "format1");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of subscribe rpc are set correctly */
|
||||
void
|
||||
check_subscribe_rpc(struct nc_rpc *rpc, const char *stream_name, const char *filter,
|
||||
const char *start_time, const char *stop_time)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_SUBSCRIBE);
|
||||
struct nc_rpc_subscribe *subscribe_rpc = (struct nc_rpc_subscribe *)rpc;
|
||||
|
||||
assert_int_equal(subscribe_rpc->type, NC_RPC_SUBSCRIBE);
|
||||
assert_string_equal(subscribe_rpc->stream, stream_name);
|
||||
assert_string_equal(subscribe_rpc->filter, filter);
|
||||
assert_string_equal(subscribe_rpc->start, start_time);
|
||||
assert_string_equal(subscribe_rpc->stop, stop_time);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_subscribe(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create subscribe rpc with NC_PARAMTYPE_CONST*/
|
||||
rpc = nc_rpc_subscribe("stream-name", "filter", "start-time", "stop-time", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_subscribe_rpc(rpc, "stream-name", "filter", "start-time", "stop-time");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create subscribe rpc with NC_PARAMTYPE_FREE*/
|
||||
char *str1 = strdup("str1");
|
||||
char *str2 = strdup("str2");
|
||||
char *str3 = strdup("str3");
|
||||
char *str4 = strdup("str4");
|
||||
|
||||
rpc = nc_rpc_subscribe(str1, str2, str3, str4, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_subscribe_rpc(rpc, str1, str2, str3, str4);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create subscribe rpc with NC_PARAMTYPE_DUP_AND_FREE*/
|
||||
rpc = nc_rpc_subscribe("name", "filter-str", "start", "stop", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_subscribe_rpc(rpc, "name", "filter-str", "start", "stop");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of getdata rpc are set correctly */
|
||||
void
|
||||
check_getdata(struct nc_rpc *rpc, char *datastore, const char *filter, const char *config_filter,
|
||||
char **origin_filter, int origin_filter_count, int negated_origin_filter, uint16_t max_depth,
|
||||
int with_origin, NC_WD_MODE wd_mode)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_GETDATA);
|
||||
struct nc_rpc_getdata *rpc_getdata = (struct nc_rpc_getdata *)rpc;
|
||||
|
||||
assert_int_equal(rpc_getdata->type, NC_RPC_GETDATA);
|
||||
assert_string_equal(rpc_getdata->datastore, datastore);
|
||||
assert_string_equal(rpc_getdata->filter, filter);
|
||||
assert_string_equal(rpc_getdata->config_filter, config_filter);
|
||||
assert_string_equal(*rpc_getdata->origin_filter, *origin_filter);
|
||||
assert_int_equal(rpc_getdata->origin_filter_count, origin_filter_count);
|
||||
assert_int_equal(rpc_getdata->negated_origin_filter, negated_origin_filter);
|
||||
assert_int_equal(rpc_getdata->max_depth, max_depth);
|
||||
assert_int_equal(rpc_getdata->with_origin, with_origin);
|
||||
assert_int_equal(rpc_getdata->wd_mode, wd_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_getdata(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create getdata rpc with NC_PARAMTYPE_CONST */
|
||||
char *origin_filters = "origin_filter";
|
||||
|
||||
rpc = nc_rpc_getdata("candidate", "filter", "true", &origin_filters, 1, 1, 3, 1, NC_WD_UNKNOWN, NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_getdata(rpc, "candidate", "filter", "true", &origin_filters, 1, 1, 3, 1, NC_WD_UNKNOWN);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create getdata rpc with NC_PARAMTYPE_FREE */
|
||||
char *datastore = strdup("running");
|
||||
char *filter = strdup("filter");
|
||||
char *config_filter = strdup("true");
|
||||
char buf[20] = {0};
|
||||
char **origin_filter;
|
||||
int origin_filter_count = 2;
|
||||
|
||||
origin_filter = calloc(origin_filter_count, sizeof *origin_filter);
|
||||
assert_non_null(origin_filter);
|
||||
for (int i = 0; i < origin_filter_count; i++) {
|
||||
snprintf(buf, sizeof(buf) - 1, "origin_filter%d", i + 1);
|
||||
origin_filter[i] = strdup(buf);
|
||||
}
|
||||
|
||||
rpc = nc_rpc_getdata(datastore, filter, config_filter, origin_filter, origin_filter_count, 2, 3, 1, NC_WD_EXPLICIT, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_getdata(rpc, datastore, filter, config_filter, origin_filter, origin_filter_count, 2, 3, 1, NC_WD_EXPLICIT);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create getdata rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
char *origin_filter1 = "origin_filter1";
|
||||
|
||||
rpc = nc_rpc_getdata("startup", "filter1", "false", &origin_filter1, 1, 0, 3, 1, NC_WD_ALL, NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_getdata(rpc, "startup", "filter1", "false", &origin_filter1, 1, 0, 3, 1, NC_WD_ALL);
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
/* function to check if values of editdata rpc are set correctly */
|
||||
void
|
||||
check_editdata(struct nc_rpc *rpc, char *datastore, NC_RPC_EDIT_DFLTOP default_op, const char *edit_content)
|
||||
{
|
||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_EDITDATA);
|
||||
struct nc_rpc_editdata *rpc_editdata = (struct nc_rpc_editdata *)rpc;
|
||||
|
||||
assert_int_equal(rpc_editdata->type, NC_RPC_EDITDATA);
|
||||
assert_string_equal(rpc_editdata->datastore, datastore);
|
||||
assert_int_equal(rpc_editdata->default_op, default_op);
|
||||
assert_string_equal(rpc_editdata->edit_cont, edit_content);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_rpc_editdata(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_rpc *rpc = NULL;
|
||||
|
||||
/* create editdata rpc with NC_PARAMTYPE_CONST */
|
||||
rpc = nc_rpc_editdata("candidate", NC_RPC_EDIT_DFLTOP_UNKNOWN, "edit", NC_PARAMTYPE_CONST);
|
||||
assert_non_null(rpc);
|
||||
check_editdata(rpc, "candidate", NC_RPC_EDIT_DFLTOP_UNKNOWN, "edit");
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create editdata rpc with NC_PARAMTYPE_FREE */
|
||||
char *datastore = strdup("running");
|
||||
char *edit_cont = strdup("edit_data");
|
||||
|
||||
rpc = nc_rpc_editdata(datastore, NC_RPC_EDIT_DFLTOP_MERGE, edit_cont, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_editdata(rpc, datastore, NC_RPC_EDIT_DFLTOP_MERGE, edit_cont);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
/* create editdata rpc with NC_PARAMTYPE_DUP_AND_FREE */
|
||||
rpc = nc_rpc_editdata("startup", NC_RPC_EDIT_DFLTOP_REPLACE, "edit_cont", NC_PARAMTYPE_DUP_AND_FREE);
|
||||
assert_non_null(rpc);
|
||||
check_editdata(rpc, "startup", NC_RPC_EDIT_DFLTOP_REPLACE, "edit_cont");
|
||||
nc_rpc_free(rpc);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_act_generic_xml, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_act_generic, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_getconfig, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_edit, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_copy, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_delete, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_lock, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_unlock, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_get, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_kill, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_commit, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_discard, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_cancel, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_validate, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_getschema, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_subscribe, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_getdata, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_rpc_editdata, setup_f, teardown_f),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
813
tests/client/test_client_ssh.c
Normal file
813
tests/client/test_client_ssh.c
Normal file
|
@ -0,0 +1,813 @@
|
|||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <config.h>
|
||||
#include <libyang/libyang.h>
|
||||
#include <log.h>
|
||||
#include <session_client.h>
|
||||
#include <session_client_ch.h>
|
||||
#include <session_p.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
|
||||
static int
|
||||
ssh_hostkey_check_clb(const char *hostname, ssh_session session, void *priv)
|
||||
{
|
||||
(void)hostname;
|
||||
(void)session;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
|
||||
nc_verbosity(NC_VERB_VERBOSE);
|
||||
|
||||
ret = nc_client_ssh_set_username("username");
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_ssh_ch_set_username("ch_username");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_ssh_set_auth_hostkey_check_clb(ssh_hostkey_check_clb, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
(void)sockfd;
|
||||
(void)addr;
|
||||
(void)addrlen;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_connect(ssh_session session)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
/* set support of all authentication methods by fake server */
|
||||
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_userauth_none(ssh_session session, const char *username)
|
||||
{
|
||||
(void)session;
|
||||
(void)username;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods)
|
||||
{
|
||||
(void)session;
|
||||
(void)user;
|
||||
(void)submethods;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_is_connected(ssh_session session)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_channel_open_session(ssh_channel channel)
|
||||
{
|
||||
(void)channel;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem)
|
||||
{
|
||||
(void)channel;
|
||||
(void)subsystem;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_channel_is_closed(ssh_channel channel)
|
||||
{
|
||||
(void)channel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_channel_write(ssh_channel channel, const void *data, uint32_t len)
|
||||
{
|
||||
(void)channel;
|
||||
(void)data;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
|
||||
{
|
||||
(void)channel;
|
||||
(void)timeout;
|
||||
(void)is_stderr;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_userauth_password(ssh_session session, const char *username, const char *password)
|
||||
{
|
||||
(void)session;
|
||||
check_expected(password);
|
||||
check_expected(username);
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_nc_handshake_io(struct nc_session *session)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_nc_ctx_check_and_fill(struct nc_session *session)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey)
|
||||
{
|
||||
(void)session;
|
||||
(void)username;
|
||||
(void)pubkey;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey)
|
||||
{
|
||||
(void)session;
|
||||
(void)username;
|
||||
(void)privkey;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka)
|
||||
{
|
||||
(void)address;
|
||||
(void)port;
|
||||
(void)ka;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_nc_sock_accept_binds(struct nc_bind *binds, uint16_t bind_count, int timeout, char **host, uint16_t *port, uint16_t *idx)
|
||||
{
|
||||
(void)binds;
|
||||
(void)bind_count;
|
||||
(void)timeout;
|
||||
(void)host;
|
||||
(void)port;
|
||||
|
||||
*idx = 0;
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK struct nc_session *
|
||||
__wrap_nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly_ctx *ctx, int timeout)
|
||||
{
|
||||
(void)sock;
|
||||
(void)host;
|
||||
(void)port;
|
||||
(void)ctx;
|
||||
(void)timeout;
|
||||
|
||||
return mock_ptr_type(struct nc_session *);
|
||||
}
|
||||
|
||||
static int
|
||||
test_hostkey_clb(const char *hostname, ssh_session session, void *priv)
|
||||
{
|
||||
(void)hostname;
|
||||
(void)session;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_setting_auth_hostkey_check_clb(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int (*ret_f)(const char *hostname, ssh_session session, void *priv);
|
||||
char *priv_data_ret;
|
||||
|
||||
/* ssh_hostkey_check_clb is set in setup_f */
|
||||
nc_client_ssh_get_auth_hostkey_check_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(ret_f, ssh_hostkey_check_clb);
|
||||
assert_null(priv_data_ret);
|
||||
|
||||
/* set different callback and private data */
|
||||
nc_client_ssh_set_auth_hostkey_check_clb(test_hostkey_clb, "DATA");
|
||||
nc_client_ssh_get_auth_hostkey_check_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(ret_f, test_hostkey_clb);
|
||||
assert_string_equal(priv_data_ret, "DATA");
|
||||
}
|
||||
|
||||
char *
|
||||
test_pwd_clb1(const char *username, const char *hostname, void *priv)
|
||||
{
|
||||
char *pass, *pass_to_return;
|
||||
|
||||
check_expected(username);
|
||||
check_expected(hostname);
|
||||
check_expected(priv);
|
||||
|
||||
pass = (char *)mock();
|
||||
pass_to_return = malloc(sizeof *pass * (strlen(pass) + 1));
|
||||
strcpy(pass_to_return, pass);
|
||||
|
||||
return pass_to_return;
|
||||
}
|
||||
|
||||
char *
|
||||
test_pwd_clb2(const char *username, const char *hostname, void *priv)
|
||||
{
|
||||
(void)username;
|
||||
(void)hostname;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_setting_auth_password_clb(void **state)
|
||||
{
|
||||
(void)state;
|
||||
char *(*ret_f)(const char *username, const char *hostname, void *priv);
|
||||
char *priv_data_ret;
|
||||
|
||||
/* set callback */
|
||||
nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "DATA");
|
||||
nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(test_pwd_clb1, ret_f);
|
||||
assert_string_equal("DATA", priv_data_ret);
|
||||
|
||||
/* set different callback */
|
||||
nc_client_ssh_set_auth_password_clb(test_pwd_clb2, "NEW DATA");
|
||||
nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(test_pwd_clb2, ret_f);
|
||||
assert_string_equal("NEW DATA", priv_data_ret);
|
||||
}
|
||||
|
||||
char *
|
||||
test_inter_clb1(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
|
||||
{
|
||||
(void)auth_name;
|
||||
(void)instruction;
|
||||
(void)prompt;
|
||||
(void)echo;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
test_inter_clb2(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
|
||||
{
|
||||
(void)auth_name;
|
||||
(void)instruction;
|
||||
(void)prompt;
|
||||
(void)echo;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_setting_auth_interactive_clb(void **state)
|
||||
{
|
||||
(void)state;
|
||||
char *(*ret_f)(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv);
|
||||
char *priv_data_ret;
|
||||
|
||||
/* set callback */
|
||||
nc_client_ssh_set_auth_interactive_clb(test_inter_clb1, "DATA");
|
||||
nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(test_inter_clb1, ret_f);
|
||||
assert_string_equal("DATA", priv_data_ret);
|
||||
|
||||
/* set diferent callback */
|
||||
nc_client_ssh_set_auth_interactive_clb(test_inter_clb2, "NEW DATA");
|
||||
nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(test_inter_clb2, ret_f);
|
||||
assert_string_equal("NEW DATA", priv_data_ret);
|
||||
}
|
||||
|
||||
char *
|
||||
test_passphrase_clb1(const char *privkey_path, void *priv)
|
||||
{
|
||||
(void)privkey_path;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
test_passphrase_clb2(const char *privkey_path, void *priv)
|
||||
{
|
||||
(void)privkey_path;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_setting_auth_privkey_passphrase_clb(void **state)
|
||||
{
|
||||
(void)state;
|
||||
char *(*ret_f)(const char *privkey_path, void *priv);
|
||||
char *priv_data_ret;
|
||||
|
||||
/* set first callback */
|
||||
nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb1, "DATA");
|
||||
nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(ret_f, test_passphrase_clb1);
|
||||
assert_string_equal("DATA", priv_data_ret);
|
||||
|
||||
/* set different callback */
|
||||
nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb2, "NEW DATA");
|
||||
nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
|
||||
assert_ptr_equal(ret_f, test_passphrase_clb2);
|
||||
assert_string_equal("NEW DATA", priv_data_ret);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_adding_keypair(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
const char *pubkey1, *pubkey2;
|
||||
|
||||
/* at the beginning keypair count should be 0 */
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* add first key pair */
|
||||
ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_dsa.pub", TESTS_DIR "/data/key_dsa");
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 1);
|
||||
|
||||
/* add second keypair */
|
||||
ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 2);
|
||||
ret = nc_client_ssh_get_keypair(1, &pubkey1, &pubkey2);
|
||||
assert_int_equal(ret, 0);
|
||||
assert_string_equal(pubkey1, "key_pub");
|
||||
assert_string_equal(pubkey2, "key_priv");
|
||||
|
||||
/* delete first keypair */
|
||||
ret = nc_client_ssh_del_keypair(0);
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 1);
|
||||
/* try to get deleted keypair */
|
||||
ret = nc_client_ssh_get_keypair(5, &pubkey1, &pubkey2);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* try to add keypair that is already set */
|
||||
ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
|
||||
assert_int_equal(ret, -1);
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 1);
|
||||
|
||||
/* try to delete keypair with id that is not used */
|
||||
ret = nc_client_ssh_del_keypair(42);
|
||||
assert_int_equal(ret, -1);
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 1);
|
||||
|
||||
/* remove remaining keypairs */
|
||||
ret = nc_client_ssh_del_keypair(0);
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_ssh_get_keypair_count();
|
||||
assert_int_equal(ret, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_setting_auth_pref(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
|
||||
/* initiate client, must be called in first test */
|
||||
nc_client_init();
|
||||
|
||||
/* check default prefference settings according to documentation */
|
||||
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
|
||||
assert_int_equal(ret, 3);
|
||||
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
|
||||
assert_int_equal(ret, 2);
|
||||
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
|
||||
assert_int_equal(ret, 1);
|
||||
|
||||
/* try to set prefetence of non existing method */
|
||||
nc_client_ssh_set_auth_pref(42, 22);
|
||||
|
||||
/* try to get preference of non existing method */
|
||||
ret = nc_client_ssh_get_auth_pref(42);
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* change values of all methods and check if they actually changed */
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 9);
|
||||
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
|
||||
assert_int_equal(ret, 9);
|
||||
|
||||
/* negative value should be set as -1 */
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -5);
|
||||
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 11);
|
||||
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
|
||||
assert_int_equal(ret, 11);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_setting_username(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
const char *username_ret;
|
||||
|
||||
username_ret = nc_client_ssh_get_username();
|
||||
/* username is set to "username" in setup_f */
|
||||
assert_string_equal(username_ret, "username");
|
||||
|
||||
/* set new username and check if it changes */
|
||||
ret = nc_client_ssh_set_username("new_username");
|
||||
assert_int_equal(ret, 0);
|
||||
username_ret = nc_client_ssh_get_username();
|
||||
assert_string_equal(username_ret, "new_username");
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_ssh_interactive_succesfull(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session;
|
||||
|
||||
/* set authentication method to use interactive authentication */
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
|
||||
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 20);
|
||||
|
||||
/* prepare return values for functions used by nc_connect_ssh */
|
||||
will_return(__wrap_connect, 0);
|
||||
will_return(__wrap_ssh_connect, 0);
|
||||
will_return(__wrap_ssh_userauth_none, 1);
|
||||
|
||||
will_return(__wrap_ssh_userauth_kbdint, 0);
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
|
||||
will_return(__wrap_ssh_channel_open_session, 0);
|
||||
will_return(__wrap_ssh_channel_request_subsystem, 0);
|
||||
|
||||
will_return(__wrap_nc_handshake_io, 3);
|
||||
will_return(__wrap_nc_ctx_check_and_fill, 0);
|
||||
|
||||
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
|
||||
assert_non_null(session);
|
||||
|
||||
will_return(__wrap_ssh_channel_poll_timeout, 0);
|
||||
nc_session_free(session, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_ssh_password_succesfull(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session;
|
||||
|
||||
/* set authentication method to use password authentication */
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
|
||||
|
||||
/* set authentication callback */
|
||||
nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "private_data");
|
||||
will_return(test_pwd_clb1, "secret password");
|
||||
/* set values that are expected as parameters for authentication callback */
|
||||
expect_string(test_pwd_clb1, username, "username");
|
||||
expect_string(test_pwd_clb1, hostname, "127.0.0.1");
|
||||
expect_string(test_pwd_clb1, priv, "private_data");
|
||||
|
||||
/* fake succesfull connection */
|
||||
will_return(__wrap_connect, 0);
|
||||
will_return(__wrap_ssh_connect, 0);
|
||||
/* do not authenticate using no authentication method */
|
||||
will_return(__wrap_ssh_userauth_none, 1);
|
||||
|
||||
/* succesfully authenticate via password authentication */
|
||||
expect_string(__wrap_ssh_userauth_password, password, "secret password");
|
||||
expect_string(__wrap_ssh_userauth_password, username, "username");
|
||||
will_return(__wrap_ssh_userauth_password, 0);
|
||||
|
||||
/* fake ssh functions that are used to open netconf channel */
|
||||
will_return(__wrap_ssh_channel_open_session, 0);
|
||||
will_return(__wrap_ssh_channel_request_subsystem, 0);
|
||||
|
||||
/* fake that connection is still alive*/
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
|
||||
/* fake ssh function for recieving hello message */
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
|
||||
will_return(__wrap_nc_handshake_io, 3);
|
||||
will_return(__wrap_nc_ctx_check_and_fill, 0);
|
||||
|
||||
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
|
||||
assert_non_null(session);
|
||||
|
||||
/* disconnect */
|
||||
will_return(__wrap_ssh_channel_poll_timeout, 0);
|
||||
nc_session_free(session, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_ssh_pubkey_succesfull(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session;
|
||||
int ret = 0;
|
||||
|
||||
/* set authentication method to use password authentication */
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
|
||||
|
||||
/* add keypair for authentication */
|
||||
ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_dsa.pub", TESTS_DIR "/data/key_dsa");
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* fake succesfull connection */
|
||||
will_return(__wrap_connect, 0);
|
||||
will_return(__wrap_ssh_connect, 0);
|
||||
/* do not authenticate using no authentication method */
|
||||
will_return(__wrap_ssh_userauth_none, 1);
|
||||
will_return(__wrap_ssh_userauth_try_publickey, 0);
|
||||
will_return(__wrap_ssh_userauth_publickey, 0);
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
will_return(__wrap_ssh_channel_open_session, 0);
|
||||
will_return(__wrap_ssh_channel_request_subsystem, 0);
|
||||
|
||||
/* fake ssh function for recieving hello message */
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
|
||||
will_return(__wrap_nc_handshake_io, 3);
|
||||
will_return(__wrap_nc_ctx_check_and_fill, 0);
|
||||
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
|
||||
assert_non_null(session);
|
||||
|
||||
/* disconnect */
|
||||
will_return(__wrap_ssh_channel_poll_timeout, 0);
|
||||
nc_session_free(session, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_connection_failed(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session;
|
||||
|
||||
errno = ECONNREFUSED;
|
||||
will_return(__wrap_connect, -1);
|
||||
will_return(__wrap_ssh_is_connected, 0);
|
||||
|
||||
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
|
||||
assert_null(session);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_ssh_bad_hello(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session;
|
||||
|
||||
/* set authentication method to use interactive authentication */
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
|
||||
|
||||
nc_client_ssh_set_auth_password_clb(test_pwd_clb2, NULL);
|
||||
|
||||
will_return(__wrap_connect, 0);
|
||||
will_return(__wrap_ssh_connect, 0);
|
||||
will_return(__wrap_ssh_userauth_none, 1);
|
||||
|
||||
will_return(__wrap_ssh_userauth_kbdint, 0);
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
will_return(__wrap_ssh_is_connected, 1);
|
||||
|
||||
will_return(__wrap_ssh_channel_open_session, 0);
|
||||
will_return(__wrap_ssh_channel_request_subsystem, 0);
|
||||
will_return(__wrap_nc_handshake_io, 4);
|
||||
|
||||
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
|
||||
assert_null(session);
|
||||
|
||||
/* destroy client, must be called in last test */
|
||||
nc_client_destroy();
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_ch_setting_username(void **state)
|
||||
{
|
||||
(void)state;
|
||||
const char *username_ret;
|
||||
int ret;
|
||||
|
||||
/* username is set to "ch_username" in setup_f */
|
||||
username_ret = nc_client_ssh_ch_get_username();
|
||||
assert_string_equal(username_ret, "ch_username");
|
||||
/* set new username and check if it changes */
|
||||
ret = nc_client_ssh_ch_set_username("new_ch_username");
|
||||
assert_int_equal(ret, 0);
|
||||
username_ret = nc_client_ssh_ch_get_username();
|
||||
assert_string_equal(username_ret, "new_ch_username");
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_ch_add_bind_listen(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
|
||||
/* invalid parameters, address NULL or port 0 */
|
||||
ret = nc_client_ssh_ch_add_bind_listen(NULL, 4334);
|
||||
assert_int_equal(ret, -1);
|
||||
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 0);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* failed to create an ssh listening socket */
|
||||
will_return(__wrap_nc_sock_listen_inet, -1);
|
||||
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* fake a successful CH ssh listening socket */
|
||||
will_return(__wrap_nc_sock_listen_inet, 1);
|
||||
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* remove ssh listening client binds */
|
||||
ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_accept_callhome(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session = NULL;
|
||||
int timeout = 10;
|
||||
int ret;
|
||||
|
||||
/* invalid parameter session */
|
||||
ret = nc_accept_callhome(timeout, NULL, NULL);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* no client bind */
|
||||
ret = nc_accept_callhome(timeout, NULL, &session);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* successfully add a client Call Home bind */
|
||||
will_return(__wrap_nc_sock_listen_inet, 1);
|
||||
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* failed to accept a client bind */
|
||||
will_return(__wrap_nc_sock_accept_binds, -1);
|
||||
ret = nc_accept_callhome(timeout, NULL, &session);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* failed to accept a server Call Home connection */
|
||||
will_return(__wrap_nc_accept_callhome_ssh_sock, NULL);
|
||||
will_return(__wrap_nc_sock_accept_binds, 2);
|
||||
ret = nc_accept_callhome(timeout, NULL, &session);
|
||||
assert_int_equal(ret, -1);
|
||||
|
||||
/* create session structure to fake a successful server call home connection */
|
||||
session = nc_new_session(NC_CLIENT, 0);
|
||||
assert_non_null(session);
|
||||
will_return(__wrap_nc_sock_accept_binds, 2);
|
||||
will_return(__wrap_nc_accept_callhome_ssh_sock, session);
|
||||
ret = nc_accept_callhome(timeout, NULL, &session);
|
||||
assert_int_equal(ret, 1);
|
||||
|
||||
/* remove ssh listening client binds */
|
||||
ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* free session */
|
||||
nc_session_free(session, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_ssh_callhome_successful(void **state)
|
||||
{
|
||||
(void)state;
|
||||
struct nc_session *session = NULL;
|
||||
int timeout = 10;
|
||||
int ret;
|
||||
|
||||
/* create session structure */
|
||||
session = nc_new_session(NC_CLIENT, 0);
|
||||
assert_non_null(session);
|
||||
|
||||
/* prepare to fake return values for functions used by nc_accept_callhome */
|
||||
will_return(__wrap_nc_sock_listen_inet, 1);
|
||||
will_return(__wrap_nc_sock_accept_binds, 2);
|
||||
will_return(__wrap_nc_accept_callhome_ssh_sock, session);
|
||||
|
||||
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_accept_callhome(timeout, NULL, &session);
|
||||
assert_int_equal(ret, 1);
|
||||
|
||||
/* remove ssh listening client binds */
|
||||
ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* free session */
|
||||
nc_session_free(session, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_pref, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_hostkey_check_clb, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_password_clb, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_interactive_clb, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_privkey_passphrase_clb, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_adding_keypair, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_username, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_interactive_succesfull, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_password_succesfull, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_pubkey_succesfull, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_connection_failed, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_bad_hello, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_setting_username, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_add_bind_listen, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_accept_callhome, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_ssh_callhome_successful, setup_f, teardown_f),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
200
tests/client/test_client_tls.c
Normal file
200
tests/client/test_client_tls.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <config.h>
|
||||
#include <libyang/libyang.h>
|
||||
#include <log.h>
|
||||
#include <session_client.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
static int
|
||||
setup_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
nc_verbosity(NC_VERB_VERBOSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_f(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
(void)sockfd;
|
||||
(void)addr;
|
||||
(void)addrlen;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_SSL_connect(SSL *ssl)
|
||||
{
|
||||
(void)ssl;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_nc_handshake_io(struct nc_session *session)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
MOCK int
|
||||
__wrap_nc_ctx_check_and_fill(struct nc_session *session)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
return (int)mock();
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_tls_setting_cert_key_paths(void **state)
|
||||
{
|
||||
(void)state;
|
||||
const char *cert, *key;
|
||||
int ret;
|
||||
|
||||
nc_client_init();
|
||||
|
||||
/* no certificats are set, nc_client_tls_get_cert_key_paths should output NULL */
|
||||
nc_client_tls_get_cert_key_paths(&cert, &key);
|
||||
assert_null(cert);
|
||||
assert_null(key);
|
||||
|
||||
/* set certificate path */
|
||||
ret = nc_client_tls_set_cert_key_paths("cert_path", "key_path");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_tls_get_cert_key_paths(&cert, &key);
|
||||
assert_string_equal(cert, "cert_path");
|
||||
assert_string_equal(key, "key_path");
|
||||
|
||||
/* override certificate path */
|
||||
ret = nc_client_tls_set_cert_key_paths("cert_path1", "key_path1");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_tls_get_cert_key_paths(&cert, &key);
|
||||
assert_string_equal(cert, "cert_path1");
|
||||
assert_string_equal(key, "key_path1");
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_tls_setting_trusted_ca_paths(void **state)
|
||||
{
|
||||
(void)state;
|
||||
const char *file, *dir;
|
||||
int ret;
|
||||
|
||||
ret = nc_client_tls_set_trusted_ca_paths("ca_file", "ca_dir");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_tls_get_trusted_ca_paths(&file, &dir);
|
||||
assert_string_equal("ca_file", file);
|
||||
assert_string_equal("ca_dir", dir);
|
||||
|
||||
ret = nc_client_tls_set_trusted_ca_paths("ca_file1", "ca_dir1");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_tls_get_trusted_ca_paths(&file, &dir);
|
||||
assert_string_equal("ca_file1", file);
|
||||
assert_string_equal("ca_dir1", dir);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_tls_succesfull(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
struct nc_session *session;
|
||||
|
||||
ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
will_return(__wrap_connect, 0);
|
||||
will_return(__wrap_SSL_connect, 1);
|
||||
|
||||
/* fake succesfull handshake */
|
||||
will_return(__wrap_nc_handshake_io, 3);
|
||||
will_return(__wrap_nc_ctx_check_and_fill, 0);
|
||||
session = nc_connect_tls("0.0.0.0", 6001, NULL);
|
||||
assert_non_null(session);
|
||||
|
||||
nc_session_free(session, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_client_tls_setting_crl_paths(void **state)
|
||||
{
|
||||
(void)state;
|
||||
const char *file, *dir;
|
||||
int ret;
|
||||
|
||||
nc_client_tls_get_crl_paths(&file, &dir);
|
||||
assert_null(file);
|
||||
assert_null(dir);
|
||||
|
||||
ret = nc_client_tls_set_crl_paths("file", "dir");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_tls_get_crl_paths(&file, &dir);
|
||||
assert_string_equal(file, "file");
|
||||
assert_string_equal(dir, "dir");
|
||||
|
||||
ret = nc_client_tls_set_crl_paths("file1", "dir1");
|
||||
assert_int_equal(ret, 0);
|
||||
nc_client_tls_get_crl_paths(&file, &dir);
|
||||
assert_string_equal(file, "file1");
|
||||
assert_string_equal(dir, "dir1");
|
||||
|
||||
/* destroy client */
|
||||
nc_client_destroy();
|
||||
}
|
||||
|
||||
static void
|
||||
test_nc_connect_tls_handshake_failed(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int ret;
|
||||
struct nc_session *session;
|
||||
|
||||
ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
|
||||
assert_int_equal(ret, 0);
|
||||
ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
will_return(__wrap_connect, 0);
|
||||
will_return(__wrap_SSL_connect, 1);
|
||||
|
||||
/* fake failed handshake */
|
||||
will_return(__wrap_nc_handshake_io, 0);
|
||||
session = nc_connect_tls("0.0.0.0", 6001, NULL);
|
||||
assert_null(session);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_tls_setting_cert_key_paths, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_tls_handshake_failed, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_connect_tls_succesfull, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_tls_setting_trusted_ca_paths, setup_f, teardown_f),
|
||||
cmocka_unit_test_setup_teardown(test_nc_client_tls_setting_crl_paths, setup_f, teardown_f),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
24
tests/config.h.in
Normal file
24
tests/config.h.in
Normal file
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @file config.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief cmocka tests configuration header.
|
||||
*
|
||||
* Copyright (c) 2015 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||
#else
|
||||
# define UNUSED(x) UNUSED_ ## x
|
||||
#endif
|
||||
|
||||
#define TESTS_DIR "@CMAKE_SOURCE_DIR@/tests"
|
||||
|
||||
@SSH_MACRO@
|
||||
@TLS_MACRO@
|
1
tests/data/042686bb.0
Symbolic link
1
tests/data/042686bb.0
Symbolic link
|
@ -0,0 +1 @@
|
|||
serverca.pem
|
1
tests/data/5412ca73.0
Symbolic link
1
tests/data/5412ca73.0
Symbolic link
|
@ -0,0 +1 @@
|
|||
server.crt
|
1
tests/data/62436b04.0
Symbolic link
1
tests/data/62436b04.0
Symbolic link
|
@ -0,0 +1 @@
|
|||
client.crt
|
25
tests/data/client.crt
Normal file
25
tests/data/client.crt
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEQDCCAygCCQCV65JgDvfWkDANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJD
|
||||
WjETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwG
|
||||
Q0VTTkVUMQwwCgYDVQQLDANUTUMxETAPBgNVBAMMCHNlcnZlcmNhMB4XDTE4MTEw
|
||||
NTA3MzAzOVoXDTI4MTEwMjA3MzAzOVowYTELMAkGA1UEBhMCQ1oxEzARBgNVBAgM
|
||||
ClNvbWUtU3RhdGUxDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEMMAoG
|
||||
A1UECwwDVE1DMQ8wDQYDVQQDDAZjbGllbnQwggIiMA0GCSqGSIb3DQEBAQUAA4IC
|
||||
DwAwggIKAoICAQC+kqPqDL9GbWmqVQhp4qla4vYo4kFuh2HG48b7RLp/4l/guik4
|
||||
Hvq2aDVFD9sBcs3FeQbjoLH1Q4doUr8jG6VwJsfovE5SD3T8dVLs2dtpW0OyXTcc
|
||||
b0I9lOVDMz6f6IUBe/m5vk8XNbdUII0NJ8y1dQ51VH3e784Bzu7PSdaMaFac4fkw
|
||||
8kJA9LxkWkv2FDFC7IBcVjRgtb/15EwODH849O6+VPEgX5gdozNj5bL45rKDBvvx
|
||||
0KjD7dFBGAIHbSjmjp7HHadfYKqvtQnMb83fRcK6wohxNP3vy13wBTtSOlvOg16G
|
||||
b+2ZB0Or7wgOw19ZvEIcNgswPwhHfZQNcYMNVLCu02BSzwdY00IEqNM0J5B/W//K
|
||||
JF3uFF/ZqP7D2wO7w8j5UL2lpuxF7YrGecNT1Kr7ggHdkzcLlekkNu7wNWKAZlJ6
|
||||
+Kbun8PqZbamGXLG2Ur1aZDkyKyD9nyMzsRneAlxO+HbQhLojimUbsMm+wgL89zc
|
||||
hLYkL/DSmsJlryA4qhvzHaaONBw4DV5UhSbLDpZtXVfrn+MAm8hLpqf+gUCThsFN
|
||||
8kDp9h9Tg9v01ai9jGb941HkFtGYUWHS5drSz3ZLnSI6i1/wKdbs9ns9YqDMqq2c
|
||||
305v5h7taMN0b40KuGSIME4K4cOsdfCprFYGZQgKjaadQwrsm4k1Jl7kMwIDAQAB
|
||||
MA0GCSqGSIb3DQEBCwUAA4IBAQAtwH2u1o16jkABlqEGDIvAJSMwBmZzNTNHgOXt
|
||||
WDlkzWGsj+L1wc/DNjDRBkE31h4h7ASthhqi1nzzHYQ1hhPVhUUqI532AS/V7EPs
|
||||
Bg3f+BI8gxqQ31TUBEQ4Ll6FtW36nqpJOe6Uui2rH2FonuUg2Av5BvDRil42Tu7f
|
||||
YW4WpSU3e00HiGJ0J0t+QjoKRnnoLJJqlmzk8Y4aIlQim7Azvrlo1WEtOhI3L9UE
|
||||
1GEqxLjRB45P36FSe1wfkgt7xmD0Xjy33Wh6Ae2Fvx7OfJ0K1zy0LHr4rDDJ3tLT
|
||||
qjPqHIFhaa73jGXwXk8sZnbAk542Oa6C6AjzNFyqV7T5Q5lg
|
||||
-----END CERTIFICATE-----
|
51
tests/data/client.key
Normal file
51
tests/data/client.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
12
tests/data/key_dsa
Normal file
12
tests/data/key_dsa
Normal file
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBugIBAAKBgQC5UysgLVJXTBaY4hPuLBBmxsOkC9VzFKbH581ufLqKxBZlQhcn
|
||||
OZ4DaQWXUvMXOmDTnG+ROpjbXBMxaYRmCwrUL9Gz0JeTYuqE413D1XYpQYZH5oJH
|
||||
7SyIe4R+mlCdORekeSKdY2oJ9dREVVe0WXiAzrBV+Eg5Ve3uWQkYw3HAMwIVAMOo
|
||||
rc88si96YqcYSPf//761FJtVAoGANwUJNODSvguHU6x55+UTGHLyWnbIqd/nbUn1
|
||||
cnCRa4xeHSHq0rBayoHh3hJiqqpcdRpb0lVoYNe51HmFJHJUGLHtYcxgnqdvIF5K
|
||||
QiP5h1ESxYqb4v4AXHl5+CVyC0Yp/hkowqaNfVqyOgol/IhNlJknZDCMxWUD9NUJ
|
||||
iiV5oc0CgYACU3qrETmgEHbwx5kCKN1/Ly4pWzS5rNg764aYsU0wE714TfYs5nOf
|
||||
yEvQYkfBDb+rEpGyKot6ZvDsHvL0WVVVx7mIDSKnzHAYwYGl1wKNHlLenOMZIDRT
|
||||
43AKfTz03wRkCrzBl2fAmLLq7wFaXcDDxaBg4zN2CDbuHjmJgRuwzAIUBRb7QH4c
|
||||
p2gVuWcmRuuI9Qexmzc=
|
||||
-----END DSA PRIVATE KEY-----
|
1
tests/data/key_dsa.pub
Normal file
1
tests/data/key_dsa.pub
Normal file
|
@ -0,0 +1 @@
|
|||
ssh-dss AAAAB3NzaC1kc3MAAACBALlTKyAtUldMFpjiE+4sEGbGw6QL1XMUpsfnzW58uorEFmVCFyc5ngNpBZdS8xc6YNOcb5E6mNtcEzFphGYLCtQv0bPQl5Ni6oTjXcPVdilBhkfmgkftLIh7hH6aUJ05F6R5Ip1jagn11ERVV7RZeIDOsFX4SDlV7e5ZCRjDccAzAAAAFQDDqK3PPLIvemKnGEj3//++tRSbVQAAAIA3BQk04NK+C4dTrHnn5RMYcvJadsip3+dtSfVycJFrjF4dIerSsFrKgeHeEmKqqlx1GlvSVWhg17nUeYUkclQYse1hzGCep28gXkpCI/mHURLFipvi/gBceXn4JXILRin+GSjCpo19WrI6CiX8iE2UmSdkMIzFZQP01QmKJXmhzQAAAIACU3qrETmgEHbwx5kCKN1/Ly4pWzS5rNg764aYsU0wE714TfYs5nOfyEvQYkfBDb+rEpGyKot6ZvDsHvL0WVVVx7mIDSKnzHAYwYGl1wKNHlLenOMZIDRT43AKfTz03wRkCrzBl2fAmLLq7wFaXcDDxaBg4zN2CDbuHjmJgRuwzA== vasko@pcvasko
|
5
tests/data/key_ecdsa
Normal file
5
tests/data/key_ecdsa
Normal file
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEICQ2fr9Jt2xluom0YQQ7HseE8YTo5reZRVcQENKUWOrooAoGCCqGSM49
|
||||
AwEHoUQDQgAENEgHZ41JFZT4c1ZFQYqvvqCEIuDxFoyVQKmz2UGOdzqCBomXZD5M
|
||||
4ufyx7bAB0reVgEzPd1ypH5KVTt4HzAkBw==
|
||||
-----END EC PRIVATE KEY-----
|
1
tests/data/key_ecdsa.pub
Normal file
1
tests/data/key_ecdsa.pub
Normal file
|
@ -0,0 +1 @@
|
|||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDRIB2eNSRWU+HNWRUGKr76ghCLg8RaMlUCps9lBjnc6ggaJl2Q+TOLn8se2wAdK3lYBMz3dcqR+SlU7eB8wJAc= vasko@pcvasko
|
27
tests/data/key_rsa
Normal file
27
tests/data/key_rsa
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAz2r1QC4jO0MEyFAJ3TvBPRjpEg0Fo7hMJM2yd5DgT2u5JKu9
|
||||
VDmRXnnA4xW/XoqZJY3xcrPyWBxkGmFRfP7L09CleYex5brUXResr6khG46W0zkW
|
||||
9u6XR194hRMgwsAiKKvbzHl/sMl57Xsp9NRqSC9IoNFgJ75Kl/0j47qZV+WSLVEq
|
||||
9DIVzO3zUl+dAQ+hvCDtP3Y1HHTFHI04xr+90sQfWcy78Z4V7lCW8xCSSS4+qmo8
|
||||
hCFWiUmu97wN9yQg/Ks2q67LiE6I1SzwxZnh8EgKAeXT/OsqKenusqbl8yscXn+s
|
||||
jV3BPKE4/FBWASF7ICD9pwb1pONRGitFZN2BZQIDAQABAoIBAQC1jeTQYdI67EXC
|
||||
ZLTNrqFNroFMaJOYJBiaWmat2+VL/3nWzHDzyVQiQyaAXyfcRCsbQSyn/zTQxUEm
|
||||
Cis+4vRdGpPNVeZ0tN1wAuoH9F3jdiM1DhK44E0Qj1O5/+08Ktt7iDrjtzH699A+
|
||||
/ADUqh3Bw4mqIrss7pbyhQSmME5LLTbaWikZ8LgtUiF9f5JWzsqjPb6Yd8JEg0O+
|
||||
5lDngLfgEYevKCJxxBMtQQQ6gZCjQQWmir+/0NBezSHsoltPlw1m8Vs8Y5zz684y
|
||||
v33J/qxDM7+rbGbte2fSQ06OuK7abCZMyfXyWdp4cQpG1JZRxGp4Y8vQKvsU5ZOQ
|
||||
UT/v7ur9AoGBAO+Li/vUzU3GlL7mxBlPTg5LavItWq6C7Rnwftjql7yPxrQ/+m5R
|
||||
Za0YujnqvZq5SpdpljCZbF9KYrFr92wgFqlt5uYptI4eD0/6xALEUcJJIlllTjiK
|
||||
tJmuyFkkD45WEn1IlDGAURQiDn6aqd40odlPsv4L5EdnQEQQz6Kfv6JLAoGBAN2q
|
||||
chHTKv1PBXfqRm0ABYSPyFhki2RqI4DWsbwykFXn3qP7tDDnmR/VMsAbApgTVW77
|
||||
LGffJ7DZXsqgzujwcqvLBKf8Wl5MRJg2jTe0GkKEBYqhGWNzBhuIwnIcKu/6HsEd
|
||||
FfCD93hwUPaVTBE+2ckXQVb9RSUCpGarXKk9cZ0PAoGBAJ/Hku29OdwA80KKpo7D
|
||||
SStbvtAe1HfGuOQueE2z3NZXiJC+hAqFnK5i6gSrwSCtK0XnldiA3bqJ4V66x2SF
|
||||
2tfUiMlJVDffcRNGDuxRir9vDMxYOF6alnBUFyruVLn6S4bpnH+QOYSWWtizzU58
|
||||
CODsulWeFPxTsJg2Jmkw6SAVAoGANWBGqX4k2uw9T9vM65BWw83vm0FSw3I/bFXG
|
||||
ZJ/0W4tC9E+22xPZrm2jE9ktLbtyFhBLaBO3NgGRrs88I6FKq41uaJj+lbhdyB1S
|
||||
sfgfXqb1wqT6PRVEgjrTP7ECsdiTsUK0tr7AR3McO9RFhd2Ribec1zqTfM7/EW3w
|
||||
GRyfkAcCgYAtw6KO+5fXHE79v9pUdZAJ4PAc/KdHjv0zE9s5snwUrh7TO5fIB62d
|
||||
i6nPBWLwD5InDZ9sNgxzTBt+0o2N6PsvKQFtfEBemKimmZShMytFkx9/KTRNR9se
|
||||
2qcBMiJsdAaz6hHUliYVWV3Ui+Uy+vYh5reuEhcvEjEzT6ySaCrZfg==
|
||||
-----END RSA PRIVATE KEY-----
|
1
tests/data/key_rsa.pub
Normal file
1
tests/data/key_rsa.pub
Normal file
|
@ -0,0 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDPavVALiM7QwTIUAndO8E9GOkSDQWjuEwkzbJ3kOBPa7kkq71UOZFeecDjFb9eipkljfFys/JYHGQaYVF8/svT0KV5h7HlutRdF6yvqSEbjpbTORb27pdHX3iFEyDCwCIoq9vMeX+wyXnteyn01GpIL0ig0WAnvkqX/SPjuplX5ZItUSr0MhXM7fNSX50BD6G8IO0/djUcdMUcjTjGv73SxB9ZzLvxnhXuUJbzEJJJLj6qajyEIVaJSa73vA33JCD8qzarrsuITojVLPDFmeHwSAoB5dP86yop6e6ypuXzKxxef6yNXcE8oTj8UFYBIXsgIP2nBvWk41EaK0Vk3YFl vasko@pcvasko
|
464
tests/data/modules/ietf-netconf-acm.yin
Normal file
464
tests/data/modules/ietf-netconf-acm.yin
Normal file
|
@ -0,0 +1,464 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module name="ietf-netconf-acm"
|
||||
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
|
||||
xmlns:nacm="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
|
||||
xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types">
|
||||
<namespace uri="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"/>
|
||||
<prefix value="nacm"/>
|
||||
<import module="ietf-yang-types">
|
||||
<prefix value="yang"/>
|
||||
</import>
|
||||
<organization>
|
||||
<text>IETF NETCONF (Network Configuration) Working Group</text>
|
||||
</organization>
|
||||
<contact>
|
||||
<text>WG Web: <https://datatracker.ietf.org/wg/netconf/>
|
||||
WG List: <mailto:netconf@ietf.org>
|
||||
|
||||
Author: Andy Bierman
|
||||
<mailto:andy@yumaworks.com>
|
||||
|
||||
Author: Martin Bjorklund
|
||||
<mailto:mbj@tail-f.com></text>
|
||||
</contact>
|
||||
<description>
|
||||
<text>Network Configuration Access Control Model.
|
||||
|
||||
Copyright (c) 2012 - 2018 IETF Trust and the persons
|
||||
identified as authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD
|
||||
License set forth in Section 4.c of the IETF Trust's
|
||||
Legal Provisions Relating to IETF Documents
|
||||
(https://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 8341; see
|
||||
the RFC itself for full legal notices.</text>
|
||||
</description>
|
||||
<revision date="2018-02-14">
|
||||
<description>
|
||||
<text>Added support for YANG 1.1 actions and notifications tied to
|
||||
data nodes. Clarified how NACM extensions can be used by
|
||||
other data models.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 8341: Network Configuration Access Control Model</text>
|
||||
</reference>
|
||||
</revision>
|
||||
<revision date="2012-02-22">
|
||||
<description>
|
||||
<text>Initial version.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6536: Network Configuration Protocol (NETCONF)
|
||||
Access Control Model</text>
|
||||
</reference>
|
||||
</revision>
|
||||
<extension name="default-deny-write">
|
||||
<description>
|
||||
<text>Used to indicate that the data model node
|
||||
represents a sensitive security system parameter.
|
||||
|
||||
If present, the NETCONF server will only allow the designated
|
||||
'recovery session' to have write access to the node. An
|
||||
explicit access control rule is required for all other users.
|
||||
|
||||
If the NACM module is used, then it must be enabled (i.e.,
|
||||
/nacm/enable-nacm object equals 'true'), or this extension
|
||||
is ignored.
|
||||
|
||||
The 'default-deny-write' extension MAY appear within a data
|
||||
definition statement. It is ignored otherwise.</text>
|
||||
</description>
|
||||
</extension>
|
||||
<extension name="default-deny-all">
|
||||
<description>
|
||||
<text>Used to indicate that the data model node
|
||||
controls a very sensitive security system parameter.
|
||||
|
||||
If present, the NETCONF server will only allow the designated
|
||||
'recovery session' to have read, write, or execute access to
|
||||
the node. An explicit access control rule is required for all
|
||||
other users.
|
||||
|
||||
If the NACM module is used, then it must be enabled (i.e.,
|
||||
/nacm/enable-nacm object equals 'true'), or this extension
|
||||
is ignored.
|
||||
|
||||
The 'default-deny-all' extension MAY appear within a data
|
||||
definition statement, 'rpc' statement, or 'notification'
|
||||
statement. It is ignored otherwise.</text>
|
||||
</description>
|
||||
</extension>
|
||||
<typedef name="user-name-type">
|
||||
<type name="string">
|
||||
<length value="1..max"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>General-purpose username string.</text>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="matchall-string-type">
|
||||
<type name="string">
|
||||
<pattern value="\*"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>The string containing a single asterisk '*' is used
|
||||
to conceptually represent all possible values
|
||||
for the particular leaf using this data type.</text>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="access-operations-type">
|
||||
<type name="bits">
|
||||
<bit name="create">
|
||||
<description>
|
||||
<text>Any protocol operation that creates a
|
||||
new data node.</text>
|
||||
</description>
|
||||
</bit>
|
||||
<bit name="read">
|
||||
<description>
|
||||
<text>Any protocol operation or notification that
|
||||
returns the value of a data node.</text>
|
||||
</description>
|
||||
</bit>
|
||||
<bit name="update">
|
||||
<description>
|
||||
<text>Any protocol operation that alters an existing
|
||||
data node.</text>
|
||||
</description>
|
||||
</bit>
|
||||
<bit name="delete">
|
||||
<description>
|
||||
<text>Any protocol operation that removes a data node.</text>
|
||||
</description>
|
||||
</bit>
|
||||
<bit name="exec">
|
||||
<description>
|
||||
<text>Execution access to the specified protocol operation.</text>
|
||||
</description>
|
||||
</bit>
|
||||
</type>
|
||||
<description>
|
||||
<text>Access operation.</text>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="group-name-type">
|
||||
<type name="string">
|
||||
<length value="1..max"/>
|
||||
<pattern value="[^\*].*"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>Name of administrative group to which
|
||||
users can be assigned.</text>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="action-type">
|
||||
<type name="enumeration">
|
||||
<enum name="permit">
|
||||
<description>
|
||||
<text>Requested action is permitted.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="deny">
|
||||
<description>
|
||||
<text>Requested action is denied.</text>
|
||||
</description>
|
||||
</enum>
|
||||
</type>
|
||||
<description>
|
||||
<text>Action taken by the server when a particular
|
||||
rule matches.</text>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="node-instance-identifier">
|
||||
<type name="yang:xpath1.0"/>
|
||||
<description>
|
||||
<text>Path expression used to represent a special
|
||||
data node, action, or notification instance-identifier
|
||||
string.
|
||||
|
||||
A node-instance-identifier value is an
|
||||
unrestricted YANG instance-identifier expression.
|
||||
All the same rules as an instance-identifier apply,
|
||||
except that predicates for keys are optional. If a key
|
||||
predicate is missing, then the node-instance-identifier
|
||||
represents all possible server instances for that key.
|
||||
|
||||
This XML Path Language (XPath) expression is evaluated in the
|
||||
following context:
|
||||
|
||||
o The set of namespace declarations are those in scope on
|
||||
the leaf element where this type is used.
|
||||
|
||||
o The set of variable bindings contains one variable,
|
||||
'USER', which contains the name of the user of the
|
||||
current session.
|
||||
|
||||
o The function library is the core function library, but
|
||||
note that due to the syntax restrictions of an
|
||||
instance-identifier, no functions are allowed.
|
||||
|
||||
o The context node is the root node in the data tree.
|
||||
|
||||
The accessible tree includes actions and notifications tied
|
||||
to data nodes.</text>
|
||||
</description>
|
||||
</typedef>
|
||||
<container name="nacm">
|
||||
<nacm:default-deny-all/>
|
||||
<description>
|
||||
<text>Parameters for NETCONF access control model.</text>
|
||||
</description>
|
||||
<leaf name="enable-nacm">
|
||||
<type name="boolean"/>
|
||||
<default value="true"/>
|
||||
<description>
|
||||
<text>Enables or disables all NETCONF access control
|
||||
enforcement. If 'true', then enforcement
|
||||
is enabled. If 'false', then enforcement
|
||||
is disabled.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="read-default">
|
||||
<type name="action-type"/>
|
||||
<default value="permit"/>
|
||||
<description>
|
||||
<text>Controls whether read access is granted if
|
||||
no appropriate rule is found for a
|
||||
particular read request.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="write-default">
|
||||
<type name="action-type"/>
|
||||
<default value="deny"/>
|
||||
<description>
|
||||
<text>Controls whether create, update, or delete access
|
||||
is granted if no appropriate rule is found for a
|
||||
particular write request.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="exec-default">
|
||||
<type name="action-type"/>
|
||||
<default value="permit"/>
|
||||
<description>
|
||||
<text>Controls whether exec access is granted if no appropriate
|
||||
rule is found for a particular protocol operation request.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="enable-external-groups">
|
||||
<type name="boolean"/>
|
||||
<default value="true"/>
|
||||
<description>
|
||||
<text>Controls whether the server uses the groups reported by the
|
||||
NETCONF transport layer when it assigns the user to a set of
|
||||
NACM groups. If this leaf has the value 'false', any group
|
||||
names reported by the transport layer are ignored by the
|
||||
server.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="denied-operations">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<config value="false"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Number of times since the server last restarted that a
|
||||
protocol operation request was denied.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="denied-data-writes">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<config value="false"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Number of times since the server last restarted that a
|
||||
protocol operation request to alter
|
||||
a configuration datastore was denied.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="denied-notifications">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<config value="false"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Number of times since the server last restarted that
|
||||
a notification was dropped for a subscription because
|
||||
access to the event type was denied.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<container name="groups">
|
||||
<description>
|
||||
<text>NETCONF access control groups.</text>
|
||||
</description>
|
||||
<list name="group">
|
||||
<key value="name"/>
|
||||
<description>
|
||||
<text>One NACM group entry. This list will only contain
|
||||
configured entries, not any entries learned from
|
||||
any transport protocols.</text>
|
||||
</description>
|
||||
<leaf name="name">
|
||||
<type name="group-name-type"/>
|
||||
<description>
|
||||
<text>Group name associated with this entry.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf-list name="user-name">
|
||||
<type name="user-name-type"/>
|
||||
<description>
|
||||
<text>Each entry identifies the username of
|
||||
a member of the group associated with
|
||||
this entry.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
</list>
|
||||
</container>
|
||||
<list name="rule-list">
|
||||
<key value="name"/>
|
||||
<ordered-by value="user"/>
|
||||
<description>
|
||||
<text>An ordered collection of access control rules.</text>
|
||||
</description>
|
||||
<leaf name="name">
|
||||
<type name="string">
|
||||
<length value="1..max"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>Arbitrary name assigned to the rule-list.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf-list name="group">
|
||||
<type name="union">
|
||||
<type name="matchall-string-type"/>
|
||||
<type name="group-name-type"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>List of administrative groups that will be
|
||||
assigned the associated access rights
|
||||
defined by the 'rule' list.
|
||||
|
||||
The string '*' indicates that all groups apply to the
|
||||
entry.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
<list name="rule">
|
||||
<key value="name"/>
|
||||
<ordered-by value="user"/>
|
||||
<description>
|
||||
<text>One access control rule.
|
||||
|
||||
Rules are processed in user-defined order until a match is
|
||||
found. A rule matches if 'module-name', 'rule-type', and
|
||||
'access-operations' match the request. If a rule
|
||||
matches, the 'action' leaf determines whether or not
|
||||
access is granted.</text>
|
||||
</description>
|
||||
<leaf name="name">
|
||||
<type name="string">
|
||||
<length value="1..max"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>Arbitrary name assigned to the rule.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="module-name">
|
||||
<type name="union">
|
||||
<type name="matchall-string-type"/>
|
||||
<type name="string"/>
|
||||
</type>
|
||||
<default value="*"/>
|
||||
<description>
|
||||
<text>Name of the module associated with this rule.
|
||||
|
||||
This leaf matches if it has the value '*' or if the
|
||||
object being accessed is defined in the module with the
|
||||
specified module name.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<choice name="rule-type">
|
||||
<description>
|
||||
<text>This choice matches if all leafs present in the rule
|
||||
match the request. If no leafs are present, the
|
||||
choice matches all requests.</text>
|
||||
</description>
|
||||
<case name="protocol-operation">
|
||||
<leaf name="rpc-name">
|
||||
<type name="union">
|
||||
<type name="matchall-string-type"/>
|
||||
<type name="string"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>This leaf matches if it has the value '*' or if
|
||||
its value equals the requested protocol operation
|
||||
name.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</case>
|
||||
<case name="notification">
|
||||
<leaf name="notification-name">
|
||||
<type name="union">
|
||||
<type name="matchall-string-type"/>
|
||||
<type name="string"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>This leaf matches if it has the value '*' or if its
|
||||
value equals the requested notification name.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</case>
|
||||
<case name="data-node">
|
||||
<leaf name="path">
|
||||
<type name="node-instance-identifier"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Data node instance-identifier associated with the
|
||||
data node, action, or notification controlled by
|
||||
this rule.
|
||||
|
||||
Configuration data or state data
|
||||
instance-identifiers start with a top-level
|
||||
data node. A complete instance-identifier is
|
||||
required for this type of path value.
|
||||
|
||||
The special value '/' refers to all possible
|
||||
datastore contents.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</case>
|
||||
</choice>
|
||||
<leaf name="access-operations">
|
||||
<type name="union">
|
||||
<type name="matchall-string-type"/>
|
||||
<type name="access-operations-type"/>
|
||||
</type>
|
||||
<default value="*"/>
|
||||
<description>
|
||||
<text>Access operations associated with this rule.
|
||||
|
||||
This leaf matches if it has the value '*' or if the
|
||||
bit corresponding to the requested operation is set.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="action">
|
||||
<type name="action-type"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>The access control action associated with the
|
||||
rule. If a rule has been determined to match a
|
||||
particular request, then this object is used
|
||||
to determine whether to permit or deny the
|
||||
request.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="comment">
|
||||
<type name="string"/>
|
||||
<description>
|
||||
<text>A textual description of the access rule.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</list>
|
||||
</list>
|
||||
</container>
|
||||
</module>
|
600
tests/data/modules/ietf-netconf-monitoring.yin
Normal file
600
tests/data/modules/ietf-netconf-monitoring.yin
Normal file
|
@ -0,0 +1,600 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module name="ietf-netconf-monitoring"
|
||||
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
|
||||
xmlns:ncm="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"
|
||||
xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types"
|
||||
xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types">
|
||||
<namespace uri="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"/>
|
||||
<prefix value="ncm"/>
|
||||
<import module="ietf-yang-types">
|
||||
<prefix value="yang"/>
|
||||
</import>
|
||||
<import module="ietf-inet-types">
|
||||
<prefix value="inet"/>
|
||||
</import>
|
||||
<organization>
|
||||
<text>IETF NETCONF (Network Configuration) Working Group</text>
|
||||
</organization>
|
||||
<contact>
|
||||
<text>WG Web: <http://tools.ietf.org/wg/netconf/>
|
||||
WG List: <mailto:netconf@ietf.org>
|
||||
|
||||
WG Chair: Mehmet Ersue
|
||||
<mailto:mehmet.ersue@nsn.com>
|
||||
|
||||
WG Chair: Bert Wijnen
|
||||
<mailto:bertietf@bwijnen.net>
|
||||
|
||||
Editor: Mark Scott
|
||||
<mailto:mark.scott@ericsson.com>
|
||||
|
||||
Editor: Martin Bjorklund
|
||||
<mailto:mbj@tail-f.com></text>
|
||||
</contact>
|
||||
<description>
|
||||
<text>NETCONF Monitoring Module.
|
||||
All elements in this module are read-only.
|
||||
|
||||
Copyright (c) 2010 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD
|
||||
License set forth in Section 4.c of the IETF Trust's
|
||||
Legal Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 6022; see
|
||||
the RFC itself for full legal notices.</text>
|
||||
</description>
|
||||
<revision date="2010-10-04">
|
||||
<description>
|
||||
<text>Initial revision.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6022: YANG Module for NETCONF Monitoring</text>
|
||||
</reference>
|
||||
</revision>
|
||||
<typedef name="netconf-datastore-type">
|
||||
<type name="enumeration">
|
||||
<enum name="running"/>
|
||||
<enum name="candidate"/>
|
||||
<enum name="startup"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>Enumeration of possible NETCONF datastore types.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4741: NETCONF Configuration Protocol</text>
|
||||
</reference>
|
||||
</typedef>
|
||||
<identity name="transport">
|
||||
<description>
|
||||
<text>Base identity for NETCONF transport types.</text>
|
||||
</description>
|
||||
</identity>
|
||||
<identity name="netconf-ssh">
|
||||
<base name="transport"/>
|
||||
<description>
|
||||
<text>NETCONF over Secure Shell (SSH).</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4742: Using the NETCONF Configuration Protocol
|
||||
over Secure SHell (SSH)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="netconf-soap-over-beep">
|
||||
<base name="transport"/>
|
||||
<description>
|
||||
<text>NETCONF over Simple Object Access Protocol (SOAP) over
|
||||
Blocks Extensible Exchange Protocol (BEEP).</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4743: Using NETCONF over the Simple Object
|
||||
Access Protocol (SOAP)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="netconf-soap-over-https">
|
||||
<base name="transport"/>
|
||||
<description>
|
||||
<text>NETCONF over Simple Object Access Protocol (SOAP)
|
||||
over Hypertext Transfer Protocol Secure (HTTPS).</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4743: Using NETCONF over the Simple Object
|
||||
Access Protocol (SOAP)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="netconf-beep">
|
||||
<base name="transport"/>
|
||||
<description>
|
||||
<text>NETCONF over Blocks Extensible Exchange Protocol (BEEP).</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4744: Using the NETCONF Protocol over the
|
||||
Blocks Extensible Exchange Protocol (BEEP)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="netconf-tls">
|
||||
<base name="transport"/>
|
||||
<description>
|
||||
<text>NETCONF over Transport Layer Security (TLS).</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 5539: NETCONF over Transport Layer Security (TLS)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="schema-format">
|
||||
<description>
|
||||
<text>Base identity for data model schema languages.</text>
|
||||
</description>
|
||||
</identity>
|
||||
<identity name="xsd">
|
||||
<base name="schema-format"/>
|
||||
<description>
|
||||
<text>W3C XML Schema Definition.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>W3C REC REC-xmlschema-1-20041028:
|
||||
XML Schema Part 1: Structures</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="yang">
|
||||
<base name="schema-format"/>
|
||||
<description>
|
||||
<text>The YANG data modeling language for NETCONF.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6020: YANG - A Data Modeling Language for the
|
||||
Network Configuration Protocol (NETCONF)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="yin">
|
||||
<base name="schema-format"/>
|
||||
<description>
|
||||
<text>The YIN syntax for YANG.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6020: YANG - A Data Modeling Language for the
|
||||
Network Configuration Protocol (NETCONF)</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="rng">
|
||||
<base name="schema-format"/>
|
||||
<description>
|
||||
<text>Regular Language for XML Next Generation (RELAX NG).</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>ISO/IEC 19757-2:2008: RELAX NG</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<identity name="rnc">
|
||||
<base name="schema-format"/>
|
||||
<description>
|
||||
<text>Relax NG Compact Syntax</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>ISO/IEC 19757-2:2008: RELAX NG</text>
|
||||
</reference>
|
||||
</identity>
|
||||
<grouping name="common-counters">
|
||||
<description>
|
||||
<text>Counters that exist both per session, and also globally,
|
||||
accumulated from all sessions.</text>
|
||||
</description>
|
||||
<leaf name="in-rpcs">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of correct <rpc> messages received.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="in-bad-rpcs">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of messages received when an <rpc> message was expected,
|
||||
that were not correct <rpc> messages. This includes XML parse
|
||||
errors and errors on the rpc layer.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="out-rpc-errors">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of <rpc-reply> messages sent that contained an
|
||||
<rpc-error> element.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="out-notifications">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of <notification> messages sent.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</grouping>
|
||||
<container name="netconf-state">
|
||||
<config value="false"/>
|
||||
<description>
|
||||
<text>The netconf-state container is the root of the monitoring
|
||||
data model.</text>
|
||||
</description>
|
||||
<container name="capabilities">
|
||||
<description>
|
||||
<text>Contains the list of NETCONF capabilities supported by the
|
||||
server.</text>
|
||||
</description>
|
||||
<leaf-list name="capability">
|
||||
<type name="inet:uri"/>
|
||||
<description>
|
||||
<text>List of NETCONF capabilities supported by the server.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
</container>
|
||||
<container name="datastores">
|
||||
<description>
|
||||
<text>Contains the list of NETCONF configuration datastores.</text>
|
||||
</description>
|
||||
<list name="datastore">
|
||||
<key value="name"/>
|
||||
<description>
|
||||
<text>List of NETCONF configuration datastores supported by
|
||||
the NETCONF server and related information.</text>
|
||||
</description>
|
||||
<leaf name="name">
|
||||
<type name="netconf-datastore-type"/>
|
||||
<description>
|
||||
<text>Name of the datastore associated with this list entry.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<container name="locks">
|
||||
<presence value="This container is present only if the datastore is locked."/>
|
||||
<description>
|
||||
<text>The NETCONF <lock> and <partial-lock> operations allow
|
||||
a client to lock specific resources in a datastore. The
|
||||
NETCONF server will prevent changes to the locked
|
||||
resources by all sessions except the one that acquired
|
||||
the lock(s).
|
||||
|
||||
Monitoring information is provided for each datastore
|
||||
entry including details such as the session that acquired
|
||||
the lock, the type of lock (global or partial) and the
|
||||
list of locked resources. Multiple locks per datastore
|
||||
are supported.</text>
|
||||
</description>
|
||||
<grouping name="lock-info">
|
||||
<description>
|
||||
<text>Lock related parameters, common to both global and
|
||||
partial locks.</text>
|
||||
</description>
|
||||
<leaf name="locked-by-session">
|
||||
<type name="uint32"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>The session ID of the session that has locked
|
||||
this resource. Both a global lock and a partial
|
||||
lock MUST contain the NETCONF session-id.
|
||||
|
||||
If the lock is held by a session that is not managed
|
||||
by the NETCONF server (e.g., a CLI session), a session
|
||||
id of 0 (zero) is reported.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4741: NETCONF Configuration Protocol</text>
|
||||
</reference>
|
||||
</leaf>
|
||||
<leaf name="locked-time">
|
||||
<type name="yang:date-and-time"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>The date and time of when the resource was
|
||||
locked.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</grouping>
|
||||
<choice name="lock-type">
|
||||
<description>
|
||||
<text>Indicates if a global lock or a set of partial locks
|
||||
are set.</text>
|
||||
</description>
|
||||
<container name="global-lock">
|
||||
<description>
|
||||
<text>Present if the global lock is set.</text>
|
||||
</description>
|
||||
<uses name="lock-info"/>
|
||||
</container>
|
||||
<list name="partial-lock">
|
||||
<key value="lock-id"/>
|
||||
<description>
|
||||
<text>List of partial locks.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 5717: Partial Lock Remote Procedure Call (RPC) for
|
||||
NETCONF</text>
|
||||
</reference>
|
||||
<leaf name="lock-id">
|
||||
<type name="uint32"/>
|
||||
<description>
|
||||
<text>This is the lock id returned in the <partial-lock>
|
||||
response.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<uses name="lock-info"/>
|
||||
<leaf-list name="select">
|
||||
<type name="yang:xpath1.0"/>
|
||||
<min-elements value="1"/>
|
||||
<description>
|
||||
<text>The xpath expression that was used to request
|
||||
the lock. The select expression indicates the
|
||||
original intended scope of the lock.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
<leaf-list name="locked-node">
|
||||
<type name="instance-identifier"/>
|
||||
<description>
|
||||
<text>The list of instance-identifiers (i.e., the
|
||||
locked nodes).
|
||||
|
||||
The scope of the partial lock is defined by the list
|
||||
of locked nodes.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
</list>
|
||||
</choice>
|
||||
</container>
|
||||
</list>
|
||||
</container>
|
||||
<container name="schemas">
|
||||
<description>
|
||||
<text>Contains the list of data model schemas supported by the
|
||||
server.</text>
|
||||
</description>
|
||||
<list name="schema">
|
||||
<key value="identifier version format"/>
|
||||
<description>
|
||||
<text>List of data model schemas supported by the server.</text>
|
||||
</description>
|
||||
<leaf name="identifier">
|
||||
<type name="string"/>
|
||||
<description>
|
||||
<text>Identifier to uniquely reference the schema. The
|
||||
identifier is used in the <get-schema> operation and may
|
||||
be used for other purposes such as file retrieval.
|
||||
|
||||
For modeling languages that support or require a data
|
||||
model name (e.g., YANG module name) the identifier MUST
|
||||
match that name. For YANG data models, the identifier is
|
||||
the name of the module or submodule. In other cases, an
|
||||
identifier such as a filename MAY be used instead.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="version">
|
||||
<type name="string"/>
|
||||
<description>
|
||||
<text>Version of the schema supported. Multiple versions MAY be
|
||||
supported simultaneously by a NETCONF server. Each
|
||||
version MUST be reported individually in the schema list,
|
||||
i.e., with same identifier, possibly different location,
|
||||
but different version.
|
||||
|
||||
For YANG data models, version is the value of the most
|
||||
recent YANG 'revision' statement in the module or
|
||||
submodule, or the empty string if no 'revision' statement
|
||||
is present.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="format">
|
||||
<type name="identityref">
|
||||
<base name="schema-format"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>The data modeling language the schema is written
|
||||
in (currently xsd, yang, yin, rng, or rnc).
|
||||
For YANG data models, 'yang' format MUST be supported and
|
||||
'yin' format MAY also be provided.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="namespace">
|
||||
<type name="inet:uri"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>The XML namespace defined by the data model.
|
||||
|
||||
For YANG data models, this is the module's namespace.
|
||||
If the list entry describes a submodule, this field
|
||||
contains the namespace of the module to which the
|
||||
submodule belongs.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf-list name="location">
|
||||
<type name="union">
|
||||
<type name="enumeration">
|
||||
<enum name="NETCONF"/>
|
||||
</type>
|
||||
<type name="inet:uri"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>One or more locations from which the schema can be
|
||||
retrieved. This list SHOULD contain at least one
|
||||
entry per schema.
|
||||
|
||||
A schema entry may be located on a remote file system
|
||||
(e.g., reference to file system for ftp retrieval) or
|
||||
retrieved directly from a server supporting the
|
||||
<get-schema> operation (denoted by the value 'NETCONF').</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
</list>
|
||||
</container>
|
||||
<container name="sessions">
|
||||
<description>
|
||||
<text>The sessions container includes session-specific data for
|
||||
NETCONF management sessions. The session list MUST include
|
||||
all currently active NETCONF sessions.</text>
|
||||
</description>
|
||||
<list name="session">
|
||||
<key value="session-id"/>
|
||||
<description>
|
||||
<text>All NETCONF sessions managed by the NETCONF server
|
||||
MUST be reported in this list.</text>
|
||||
</description>
|
||||
<leaf name="session-id">
|
||||
<type name="uint32">
|
||||
<range value="1..max"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>Unique identifier for the session. This value is the
|
||||
NETCONF session identifier, as defined in RFC 4741.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 4741: NETCONF Configuration Protocol</text>
|
||||
</reference>
|
||||
</leaf>
|
||||
<leaf name="transport">
|
||||
<type name="identityref">
|
||||
<base name="transport"/>
|
||||
</type>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Identifies the transport for each session, e.g.,
|
||||
'netconf-ssh', 'netconf-soap', etc.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="username">
|
||||
<type name="string"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>The username is the client identity that was authenticated
|
||||
by the NETCONF transport protocol. The algorithm used to
|
||||
derive the username is NETCONF transport protocol specific
|
||||
and in addition specific to the authentication mechanism
|
||||
used by the NETCONF transport protocol.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="source-host">
|
||||
<type name="inet:host"/>
|
||||
<description>
|
||||
<text>Host identifier of the NETCONF client. The value
|
||||
returned is implementation specific (e.g., hostname,
|
||||
IPv4 address, IPv6 address)</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="login-time">
|
||||
<type name="yang:date-and-time"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Time at the server at which the session was established.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<uses name="common-counters">
|
||||
<description>
|
||||
<text>Per-session counters. Zero based with following reset
|
||||
behaviour:
|
||||
- at start of a session
|
||||
- when max value is reached</text>
|
||||
</description>
|
||||
</uses>
|
||||
</list>
|
||||
</container>
|
||||
<container name="statistics">
|
||||
<description>
|
||||
<text>Statistical data pertaining to the NETCONF server.</text>
|
||||
</description>
|
||||
<leaf name="netconf-start-time">
|
||||
<type name="yang:date-and-time"/>
|
||||
<description>
|
||||
<text>Date and time at which the management subsystem was
|
||||
started.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="in-bad-hellos">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of sessions silently dropped because an
|
||||
invalid <hello> message was received. This includes <hello>
|
||||
messages with a 'session-id' attribute, bad namespace, and
|
||||
bad capability declarations.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="in-sessions">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of sessions started. This counter is incremented
|
||||
when a <hello> message with a <session-id> is sent.
|
||||
|
||||
'in-sessions' - 'in-bad-hellos' =
|
||||
'number of correctly started netconf sessions'</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="dropped-sessions">
|
||||
<type name="yang:zero-based-counter32"/>
|
||||
<description>
|
||||
<text>Number of sessions that were abnormally terminated, e.g.,
|
||||
due to idle timeout or transport close. This counter is not
|
||||
incremented when a session is properly closed by a
|
||||
<close-session> operation, or killed by a <kill-session>
|
||||
operation.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<uses name="common-counters">
|
||||
<description>
|
||||
<text>Global counters, accumulated from all sessions.
|
||||
Zero based with following reset behaviour:
|
||||
- re-initialization of NETCONF server
|
||||
- when max value is reached</text>
|
||||
</description>
|
||||
</uses>
|
||||
</container>
|
||||
</container>
|
||||
<rpc name="get-schema">
|
||||
<description>
|
||||
<text>This operation is used to retrieve a schema from the
|
||||
NETCONF server.
|
||||
|
||||
Positive Response:
|
||||
The NETCONF server returns the requested schema.
|
||||
|
||||
Negative Response:
|
||||
If requested schema does not exist, the <error-tag> is
|
||||
'invalid-value'.
|
||||
|
||||
If more than one schema matches the requested parameters, the
|
||||
<error-tag> is 'operation-failed', and <error-app-tag> is
|
||||
'data-not-unique'.</text>
|
||||
</description>
|
||||
<input>
|
||||
<leaf name="identifier">
|
||||
<type name="string"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Identifier for the schema list entry.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="version">
|
||||
<type name="string"/>
|
||||
<description>
|
||||
<text>Version of the schema requested. If this parameter is not
|
||||
present, and more than one version of the schema exists on
|
||||
the server, a 'data-not-unique' error is returned, as
|
||||
described above.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="format">
|
||||
<type name="identityref">
|
||||
<base name="schema-format"/>
|
||||
</type>
|
||||
<description>
|
||||
<text>The data modeling language of the schema. If this
|
||||
parameter is not present, and more than one formats of
|
||||
the schema exists on the server, a 'data-not-unique' error
|
||||
is returned, as described above.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</input>
|
||||
<output>
|
||||
<anyxml name="data">
|
||||
<description>
|
||||
<text>Contains the schema content.</text>
|
||||
</description>
|
||||
</anyxml>
|
||||
</output>
|
||||
</rpc>
|
||||
</module>
|
353
tests/data/modules/ietf-netconf-notifications.yin
Normal file
353
tests/data/modules/ietf-netconf-notifications.yin
Normal file
|
@ -0,0 +1,353 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module name="ietf-netconf-notifications"
|
||||
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
|
||||
xmlns:ncn="urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"
|
||||
xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types"
|
||||
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
|
||||
<namespace uri="urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"/>
|
||||
<prefix value="ncn"/>
|
||||
<import module="ietf-inet-types">
|
||||
<prefix value="inet"/>
|
||||
</import>
|
||||
<import module="ietf-netconf">
|
||||
<prefix value="nc"/>
|
||||
</import>
|
||||
<organization>
|
||||
<text>IETF NETCONF (Network Configuration Protocol) Working Group</text>
|
||||
</organization>
|
||||
<contact>
|
||||
<text>WG Web: <http://tools.ietf.org/wg/netconf/>
|
||||
WG List: <mailto:netconf@ietf.org>
|
||||
|
||||
WG Chair: Bert Wijnen
|
||||
<mailto:bertietf@bwijnen.net>
|
||||
|
||||
WG Chair: Mehmet Ersue
|
||||
<mailto:mehmet.ersue@nsn.com>
|
||||
|
||||
Editor: Andy Bierman
|
||||
<mailto:andy@netconfcentral.org></text>
|
||||
</contact>
|
||||
<description>
|
||||
<text>This module defines a YANG data model for use with the
|
||||
NETCONF protocol that allows the NETCONF client to
|
||||
receive common NETCONF base event notifications.
|
||||
|
||||
Copyright (c) 2012 IETF Trust and the persons identified as
|
||||
the document authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD License
|
||||
|
||||
|
||||
|
||||
set forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 6470; see
|
||||
the RFC itself for full legal notices.</text>
|
||||
</description>
|
||||
<revision date="2012-02-06">
|
||||
<description>
|
||||
<text>Initial version.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6470: NETCONF Base Notifications</text>
|
||||
</reference>
|
||||
</revision>
|
||||
<grouping name="common-session-parms">
|
||||
<description>
|
||||
<text>Common session parameters to identify a
|
||||
management session.</text>
|
||||
</description>
|
||||
<leaf name="username">
|
||||
<type name="string"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Name of the user for the session.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="session-id">
|
||||
<type name="nc:session-id-or-zero-type"/>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Identifier of the session.
|
||||
A NETCONF session MUST be identified by a non-zero value.
|
||||
A non-NETCONF session MAY be identified by the value zero.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="source-host">
|
||||
<type name="inet:ip-address"/>
|
||||
<description>
|
||||
<text>Address of the remote host for the session.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</grouping>
|
||||
<grouping name="changed-by-parms">
|
||||
<description>
|
||||
<text>Common parameters to identify the source
|
||||
of a change event, such as a configuration
|
||||
or capability change.</text>
|
||||
</description>
|
||||
<container name="changed-by">
|
||||
<description>
|
||||
<text>Indicates the source of the change.
|
||||
If caused by internal action, then the
|
||||
empty leaf 'server' will be present.
|
||||
If caused by a management session, then
|
||||
the name, remote host address, and session ID
|
||||
of the session that made the change will be reported.</text>
|
||||
</description>
|
||||
<choice name="server-or-user">
|
||||
<mandatory value="true"/>
|
||||
<leaf name="server">
|
||||
<type name="empty"/>
|
||||
<description>
|
||||
<text>If present, the change was caused
|
||||
by the server.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<case name="by-user">
|
||||
<uses name="common-session-parms"/>
|
||||
</case>
|
||||
</choice>
|
||||
</container>
|
||||
</grouping>
|
||||
<notification name="netconf-config-change">
|
||||
<description>
|
||||
<text>Generated when the NETCONF server detects that the
|
||||
<running> or <startup> configuration datastore
|
||||
has been changed by a management session.
|
||||
The notification summarizes the edits that
|
||||
have been detected.
|
||||
|
||||
The server MAY choose to also generate this
|
||||
notification while loading a datastore during the
|
||||
boot process for the device.</text>
|
||||
</description>
|
||||
<uses name="changed-by-parms"/>
|
||||
<leaf name="datastore">
|
||||
<type name="enumeration">
|
||||
<enum name="running">
|
||||
<description>
|
||||
<text>The <running> datastore has changed.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="startup">
|
||||
<description>
|
||||
<text>The <startup> datastore has changed</text>
|
||||
</description>
|
||||
</enum>
|
||||
</type>
|
||||
<default value="running"/>
|
||||
<description>
|
||||
<text>Indicates which configuration datastore has changed.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<list name="edit">
|
||||
<description>
|
||||
<text>An edit record SHOULD be present for each distinct
|
||||
edit operation that the server has detected on
|
||||
the target datastore. This list MAY be omitted
|
||||
if the detailed edit operations are not known.
|
||||
The server MAY report entries in this list for
|
||||
changes not made by a NETCONF session (e.g., CLI).</text>
|
||||
</description>
|
||||
<leaf name="target">
|
||||
<type name="instance-identifier"/>
|
||||
<description>
|
||||
<text>Topmost node associated with the configuration change.
|
||||
A server SHOULD set this object to the node within
|
||||
the datastore that is being altered. A server MAY
|
||||
set this object to one of the ancestors of the actual
|
||||
node that was changed, or omit this object, if the
|
||||
exact node is not known.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="operation">
|
||||
<type name="nc:edit-operation-type"/>
|
||||
<description>
|
||||
<text>Type of edit operation performed.
|
||||
A server MUST set this object to the NETCONF edit
|
||||
operation performed on the target datastore.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</list>
|
||||
</notification>
|
||||
<notification name="netconf-capability-change">
|
||||
<description>
|
||||
<text>Generated when the NETCONF server detects that
|
||||
the server capabilities have changed.
|
||||
Indicates which capabilities have been added, deleted,
|
||||
and/or modified. The manner in which a server
|
||||
capability is changed is outside the scope of this
|
||||
document.</text>
|
||||
</description>
|
||||
<uses name="changed-by-parms"/>
|
||||
<leaf-list name="added-capability">
|
||||
<type name="inet:uri"/>
|
||||
<description>
|
||||
<text>List of capabilities that have just been added.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
<leaf-list name="deleted-capability">
|
||||
<type name="inet:uri"/>
|
||||
<description>
|
||||
<text>List of capabilities that have just been deleted.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
<leaf-list name="modified-capability">
|
||||
<type name="inet:uri"/>
|
||||
<description>
|
||||
<text>List of capabilities that have just been modified.
|
||||
A capability is considered to be modified if the
|
||||
base URI for the capability has not changed, but
|
||||
one or more of the parameters encoded at the end of
|
||||
the capability URI have changed.
|
||||
The new modified value of the complete URI is returned.</text>
|
||||
</description>
|
||||
</leaf-list>
|
||||
</notification>
|
||||
<notification name="netconf-session-start">
|
||||
<description>
|
||||
<text>Generated when a NETCONF server detects that a
|
||||
NETCONF session has started. A server MAY generate
|
||||
this event for non-NETCONF management sessions.
|
||||
Indicates the identity of the user that started
|
||||
the session.</text>
|
||||
</description>
|
||||
<uses name="common-session-parms"/>
|
||||
</notification>
|
||||
<notification name="netconf-session-end">
|
||||
<description>
|
||||
<text>Generated when a NETCONF server detects that a
|
||||
NETCONF session has terminated.
|
||||
A server MAY optionally generate this event for
|
||||
non-NETCONF management sessions. Indicates the
|
||||
identity of the user that owned the session,
|
||||
and why the session was terminated.</text>
|
||||
</description>
|
||||
<uses name="common-session-parms"/>
|
||||
<leaf name="killed-by">
|
||||
<when condition="../termination-reason = 'killed'"/>
|
||||
<type name="nc:session-id-type"/>
|
||||
<description>
|
||||
<text>The ID of the session that directly caused this session
|
||||
to be abnormally terminated. If this session was abnormally
|
||||
terminated by a non-NETCONF session unknown to the server,
|
||||
then this leaf will not be present.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="termination-reason">
|
||||
<type name="enumeration">
|
||||
<enum name="closed">
|
||||
<description>
|
||||
<text>The session was terminated by the client in normal
|
||||
fashion, e.g., by the NETCONF <close-session>
|
||||
protocol operation.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="killed">
|
||||
<description>
|
||||
<text>The session was terminated in abnormal
|
||||
fashion, e.g., by the NETCONF <kill-session>
|
||||
protocol operation.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="dropped">
|
||||
<description>
|
||||
<text>The session was terminated because the transport layer
|
||||
connection was unexpectedly closed.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="timeout">
|
||||
<description>
|
||||
<text>The session was terminated because of inactivity,
|
||||
e.g., waiting for the <hello> message or <rpc>
|
||||
messages.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="bad-hello">
|
||||
<description>
|
||||
<text>The client's <hello> message was invalid.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="other">
|
||||
<description>
|
||||
<text>The session was terminated for some other reason.</text>
|
||||
</description>
|
||||
</enum>
|
||||
</type>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Reason the session was terminated.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</notification>
|
||||
<notification name="netconf-confirmed-commit">
|
||||
<description>
|
||||
<text>Generated when a NETCONF server detects that a
|
||||
confirmed-commit event has occurred. Indicates the event
|
||||
and the current state of the confirmed-commit procedure
|
||||
in progress.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6241, Section 8.4</text>
|
||||
</reference>
|
||||
<uses name="common-session-parms">
|
||||
<when condition="confirm-event != 'timeout'"/>
|
||||
</uses>
|
||||
<leaf name="confirm-event">
|
||||
<type name="enumeration">
|
||||
<enum name="start">
|
||||
<description>
|
||||
<text>The confirmed-commit procedure has started.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="cancel">
|
||||
<description>
|
||||
<text>The confirmed-commit procedure has been canceled,
|
||||
e.g., due to the session being terminated, or an
|
||||
explicit <cancel-commit> operation.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="timeout">
|
||||
<description>
|
||||
<text>The confirmed-commit procedure has been canceled
|
||||
due to the confirm-timeout interval expiring.
|
||||
The common session parameters will not be present
|
||||
in this sub-mode.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="extend">
|
||||
<description>
|
||||
<text>The confirmed-commit timeout has been extended,
|
||||
e.g., by a new <confirmed-commit> operation.</text>
|
||||
</description>
|
||||
</enum>
|
||||
<enum name="complete">
|
||||
<description>
|
||||
<text>The confirmed-commit procedure has been completed.</text>
|
||||
</description>
|
||||
</enum>
|
||||
</type>
|
||||
<mandatory value="true"/>
|
||||
<description>
|
||||
<text>Indicates the event that caused the notification.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
<leaf name="timeout">
|
||||
<when condition="../confirm-event = 'start' or ../confirm-event = 'extend'"/>
|
||||
<type name="uint32"/>
|
||||
<units name="seconds"/>
|
||||
<description>
|
||||
<text>The configured timeout value if the event type
|
||||
is 'start' or 'extend'. This value represents
|
||||
the approximate number of seconds from the event
|
||||
time when the 'timeout' event might occur.</text>
|
||||
</description>
|
||||
</leaf>
|
||||
</notification>
|
||||
</module>
|
149
tests/data/modules/ietf-netconf-with-defaults.yin
Normal file
149
tests/data/modules/ietf-netconf-with-defaults.yin
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module name="ietf-netconf-with-defaults"
|
||||
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
|
||||
xmlns:ncwd="urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults"
|
||||
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
|
||||
<namespace uri="urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults"/>
|
||||
<prefix value="ncwd"/>
|
||||
<import module="ietf-netconf">
|
||||
<prefix value="nc"/>
|
||||
</import>
|
||||
<organization>
|
||||
<text>IETF NETCONF (Network Configuration Protocol) Working Group</text>
|
||||
</organization>
|
||||
<contact>
|
||||
<text>WG Web: <http://tools.ietf.org/wg/netconf/>
|
||||
|
||||
WG List: <netconf@ietf.org>
|
||||
|
||||
WG Chair: Bert Wijnen
|
||||
<bertietf@bwijnen.net>
|
||||
|
||||
WG Chair: Mehmet Ersue
|
||||
<mehmet.ersue@nsn.com>
|
||||
|
||||
Editor: Andy Bierman
|
||||
<andy.bierman@brocade.com>
|
||||
|
||||
Editor: Balazs Lengyel
|
||||
<balazs.lengyel@ericsson.com></text>
|
||||
</contact>
|
||||
<description>
|
||||
<text>This module defines an extension to the NETCONF protocol
|
||||
that allows the NETCONF client to control how default
|
||||
values are handled by the server in particular NETCONF
|
||||
operations.
|
||||
|
||||
Copyright (c) 2011 IETF Trust and the persons identified as
|
||||
the document authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD License
|
||||
set forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 6243; see
|
||||
the RFC itself for full legal notices.</text>
|
||||
</description>
|
||||
<revision date="2011-06-01">
|
||||
<description>
|
||||
<text>Initial version.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243: With-defaults Capability for NETCONF</text>
|
||||
</reference>
|
||||
</revision>
|
||||
<typedef name="with-defaults-mode">
|
||||
<description>
|
||||
<text>Possible modes to report default data.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 3.</text>
|
||||
</reference>
|
||||
<type name="enumeration">
|
||||
<enum name="report-all">
|
||||
<description>
|
||||
<text>All default data is reported.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 3.1</text>
|
||||
</reference>
|
||||
</enum>
|
||||
<enum name="report-all-tagged">
|
||||
<description>
|
||||
<text>All default data is reported.
|
||||
Any nodes considered to be default data
|
||||
will contain a 'default' XML attribute,
|
||||
set to 'true' or '1'.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 3.4</text>
|
||||
</reference>
|
||||
</enum>
|
||||
<enum name="trim">
|
||||
<description>
|
||||
<text>Values are not reported if they contain the default.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 3.2</text>
|
||||
</reference>
|
||||
</enum>
|
||||
<enum name="explicit">
|
||||
<description>
|
||||
<text>Report values that contain the definition of
|
||||
explicitly set data.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 3.3</text>
|
||||
</reference>
|
||||
</enum>
|
||||
</type>
|
||||
</typedef>
|
||||
<grouping name="with-defaults-parameters">
|
||||
<description>
|
||||
<text>Contains the <with-defaults> parameter for control
|
||||
of defaults in NETCONF retrieval operations.</text>
|
||||
</description>
|
||||
<leaf name="with-defaults">
|
||||
<description>
|
||||
<text>The explicit defaults processing mode requested.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 4.5.1</text>
|
||||
</reference>
|
||||
<type name="with-defaults-mode"/>
|
||||
</leaf>
|
||||
</grouping>
|
||||
<augment target-node="/nc:get-config/nc:input">
|
||||
<description>
|
||||
<text>Adds the <with-defaults> parameter to the
|
||||
input of the NETCONF <get-config> operation.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 4.5.1</text>
|
||||
</reference>
|
||||
<uses name="with-defaults-parameters"/>
|
||||
</augment>
|
||||
<augment target-node="/nc:get/nc:input">
|
||||
<description>
|
||||
<text>Adds the <with-defaults> parameter to
|
||||
the input of the NETCONF <get> operation.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 4.5.1</text>
|
||||
</reference>
|
||||
<uses name="with-defaults-parameters"/>
|
||||
</augment>
|
||||
<augment target-node="/nc:copy-config/nc:input">
|
||||
<description>
|
||||
<text>Adds the <with-defaults> parameter to
|
||||
the input of the NETCONF <copy-config> operation.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 6243; Section 4.5.1</text>
|
||||
</reference>
|
||||
<uses name="with-defaults-parameters"/>
|
||||
</augment>
|
||||
</module>
|
1032
tests/data/modules/ietf-netconf.yin
Normal file
1032
tests/data/modules/ietf-netconf.yin
Normal file
File diff suppressed because it is too large
Load diff
16
tests/data/modules/module-a-dv.yang
Normal file
16
tests/data/modules/module-a-dv.yang
Normal file
|
@ -0,0 +1,16 @@
|
|||
module module-a-dv {
|
||||
|
||||
namespace "urn:jmu:params:xml:ns:yang:module-a-dv";
|
||||
prefix dv;
|
||||
|
||||
import module-a {
|
||||
prefix a;
|
||||
}
|
||||
|
||||
description
|
||||
"Contains some deviations to module-a";
|
||||
|
||||
deviation "/a:top/a:hidden" {
|
||||
deviate not-supported;
|
||||
}
|
||||
}
|
21
tests/data/modules/module-a-dv2.yang
Normal file
21
tests/data/modules/module-a-dv2.yang
Normal file
|
@ -0,0 +1,21 @@
|
|||
module module-a-dv2 {
|
||||
|
||||
namespace "urn:jmu:params:xml:ns:yang:module-a-dv2";
|
||||
prefix dv2;
|
||||
|
||||
import module-a {
|
||||
prefix a;
|
||||
}
|
||||
|
||||
description
|
||||
"Contains some deviations to module-a";
|
||||
|
||||
deviation "/a:top/a:type" {
|
||||
deviate add {
|
||||
default "admin";
|
||||
must "count(.) = 1";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
23
tests/data/modules/module-a.yang
Normal file
23
tests/data/modules/module-a.yang
Normal file
|
@ -0,0 +1,23 @@
|
|||
module module-a {
|
||||
|
||||
namespace "urn:jmu:params:xml:ns:yang:module-a";
|
||||
prefix a;
|
||||
|
||||
description "This is a simple user module";
|
||||
|
||||
container top {
|
||||
|
||||
leaf name {
|
||||
type string;
|
||||
}
|
||||
|
||||
leaf type {
|
||||
type string;
|
||||
}
|
||||
|
||||
leaf hidden {
|
||||
type boolean;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
102
tests/data/modules/nc-notifications.yin
Normal file
102
tests/data/modules/nc-notifications.yin
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module name="nc-notifications"
|
||||
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
|
||||
xmlns:manageEvent="urn:ietf:params:xml:ns:netmod:notification"
|
||||
xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types"
|
||||
xmlns:ncEvent="urn:ietf:params:xml:ns:netconf:notification:1.0">
|
||||
<namespace uri="urn:ietf:params:xml:ns:netmod:notification"/>
|
||||
<prefix value="manageEvent"/>
|
||||
<import module="ietf-yang-types">
|
||||
<prefix value="yang"/>
|
||||
</import>
|
||||
<import module="notifications">
|
||||
<prefix value="ncEvent"/>
|
||||
</import>
|
||||
<organization>
|
||||
<text>IETF NETCONF WG</text>
|
||||
</organization>
|
||||
<contact>
|
||||
<text>netconf@ietf.org</text>
|
||||
</contact>
|
||||
<description>
|
||||
<text>Conversion of the 'manageEvent' XSD in the NETCONF
|
||||
Notifications RFC.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 5277</text>
|
||||
</reference>
|
||||
<revision date="2008-07-14">
|
||||
<description>
|
||||
<text>RFC 5277 version.</text>
|
||||
</description>
|
||||
</revision>
|
||||
<container name="netconf">
|
||||
<description>
|
||||
<text>Top-level element in the notification namespace</text>
|
||||
</description>
|
||||
<config value="false"/>
|
||||
<container name="streams">
|
||||
<description>
|
||||
<text>The list of event streams supported by the system. When
|
||||
a query is issued, the returned set of streams is
|
||||
determined based on user privileges.</text>
|
||||
</description>
|
||||
<list name="stream">
|
||||
<description>
|
||||
<text>Stream name, description and other information.</text>
|
||||
</description>
|
||||
<key value="name"/>
|
||||
<min-elements value="1"/>
|
||||
<leaf name="name">
|
||||
<description>
|
||||
<text>The name of the event stream. If this is the default
|
||||
NETCONF stream, this must have the value 'NETCONF'.</text>
|
||||
</description>
|
||||
<type name="ncEvent:streamNameType"/>
|
||||
</leaf>
|
||||
<leaf name="description">
|
||||
<description>
|
||||
<text>A description of the event stream, including such
|
||||
information as the type of events that are sent over
|
||||
this stream.</text>
|
||||
</description>
|
||||
<type name="string"/>
|
||||
<mandatory value="true"/>
|
||||
</leaf>
|
||||
<leaf name="replaySupport">
|
||||
<description>
|
||||
<text>A description of the event stream, including such
|
||||
information as the type of events that are sent over
|
||||
this stream.</text>
|
||||
</description>
|
||||
<type name="boolean"/>
|
||||
<mandatory value="true"/>
|
||||
</leaf>
|
||||
<leaf name="replayLogCreationTime">
|
||||
<description>
|
||||
<text>The timestamp of the creation of the log used to support
|
||||
the replay function on this stream. Note that this might
|
||||
be earlier then the earliest available notification in
|
||||
the log. This object is updated if the log resets for
|
||||
some reason. This object MUST be present if replay is
|
||||
supported.</text>
|
||||
</description>
|
||||
<type name="yang:date-and-time"/>
|
||||
</leaf>
|
||||
</list>
|
||||
</container>
|
||||
</container>
|
||||
<notification name="replayComplete">
|
||||
<description>
|
||||
<text>This notification is sent to signal the end of a replay
|
||||
portion of a subscription.</text>
|
||||
</description>
|
||||
</notification>
|
||||
<notification name="notificationComplete">
|
||||
<description>
|
||||
<text>This notification is sent to signal the end of a notification
|
||||
subscription. It is sent in the case that stopTime was
|
||||
specified during the creation of the subscription..</text>
|
||||
</description>
|
||||
</notification>
|
||||
</module>
|
10
tests/data/modules/notif1.yang
Normal file
10
tests/data/modules/notif1.yang
Normal file
|
@ -0,0 +1,10 @@
|
|||
module notif1 {
|
||||
namespace "n1";
|
||||
prefix "n1";
|
||||
|
||||
notification n1 {
|
||||
leaf first {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
96
tests/data/modules/notifications.yin
Normal file
96
tests/data/modules/notifications.yin
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module name="notifications"
|
||||
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
|
||||
xmlns:ncEvent="urn:ietf:params:xml:ns:netconf:notification:1.0"
|
||||
xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types">
|
||||
<namespace uri="urn:ietf:params:xml:ns:netconf:notification:1.0"/>
|
||||
<prefix value="ncEvent"/>
|
||||
<import module="ietf-yang-types">
|
||||
<prefix value="yang"/>
|
||||
</import>
|
||||
<organization>
|
||||
<text>IETF NETCONF WG</text>
|
||||
</organization>
|
||||
<contact>
|
||||
<text>netconf@ops.ietf.org</text>
|
||||
</contact>
|
||||
<description>
|
||||
<text>Conversion of the 'ncEvent' XSD in the
|
||||
NETCONF Notifications RFC.</text>
|
||||
</description>
|
||||
<reference>
|
||||
<text>RFC 5277.</text>
|
||||
</reference>
|
||||
<revision date="2008-07-14">
|
||||
<description>
|
||||
<text>RFC 5277 version.</text>
|
||||
</description>
|
||||
</revision>
|
||||
<typedef name="streamNameType">
|
||||
<description>
|
||||
<text>The name of an event stream.</text>
|
||||
</description>
|
||||
<type name="string"/>
|
||||
</typedef>
|
||||
<rpc name="create-subscription">
|
||||
<description>
|
||||
<text>The command to create a notification subscription. It
|
||||
takes as argument the name of the notification stream
|
||||
and filter. Both of those options limit the content of
|
||||
the subscription. In addition, there are two time-related
|
||||
parameters, startTime and stopTime, which can be used to
|
||||
select the time interval of interest to the notification
|
||||
replay feature.</text>
|
||||
</description>
|
||||
<input>
|
||||
<leaf name="stream">
|
||||
<description>
|
||||
<text>An optional parameter that indicates which stream of events
|
||||
is of interest. If not present, then events in the default
|
||||
NETCONF stream will be sent.</text>
|
||||
</description>
|
||||
<type name="streamNameType"/>
|
||||
<default value="NETCONF"/>
|
||||
</leaf>
|
||||
<anyxml name="filter">
|
||||
<description>
|
||||
<text>An optional parameter that indicates which subset of all
|
||||
possible events is of interest. The format of this
|
||||
parameter is the same as that of the filter parameter
|
||||
in the NETCONF protocol operations. If not present,
|
||||
all events not precluded by other parameters will
|
||||
be sent.</text>
|
||||
</description>
|
||||
</anyxml>
|
||||
<leaf name="startTime">
|
||||
<description>
|
||||
<text>A parameter used to trigger the replay feature and
|
||||
indicates that the replay should start at the time
|
||||
specified. If start time is not present, this is not a
|
||||
replay subscription.</text>
|
||||
</description>
|
||||
<type name="yang:date-and-time"/>
|
||||
</leaf>
|
||||
<leaf name="stopTime">
|
||||
<description>
|
||||
<text>An optional parameter used with the optional replay
|
||||
feature to indicate the newest notifications of
|
||||
interest. If stop time is not present, the notifications
|
||||
will continue until the subscription is terminated.
|
||||
Must be used with startTime.</text>
|
||||
</description>
|
||||
<type name="yang:date-and-time"/>
|
||||
</leaf>
|
||||
</input>
|
||||
</rpc>
|
||||
<container name="notification">
|
||||
<description>
|
||||
<text>internal struct to start a notification</text>
|
||||
</description>
|
||||
<config value="false"/>
|
||||
<leaf name="eventTime">
|
||||
<mandatory value="true"/>
|
||||
<type name="yang:date-and-time"/>
|
||||
</leaf>
|
||||
</container>
|
||||
</module>
|
9
tests/data/nc10/rpc-lock
Normal file
9
tests/data/nc10/rpc-lock
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
|
||||
<lock>
|
||||
<target>
|
||||
<running/>
|
||||
</target>
|
||||
</lock>
|
||||
</rpc>
|
||||
]]>]]>
|
7
tests/data/nc11/rpc-lock
Normal file
7
tests/data/nc11/rpc-lock
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
#11
|
||||
<rpc xmlns=
|
||||
#103
|
||||
"urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1"><lock><target><running/></target></lock></rpc>
|
||||
##
|
||||
|
26
tests/data/server.crt
Normal file
26
tests/data/server.crt
Normal file
|
@ -0,0 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIETjCCAzYCFEO1ljvG2ET9vb1itRsNMb8xN0R3MA0GCSqGSIb3DQEBCwUAMGMx
|
||||
CzAJBgNVBAYTAkNaMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQHDARCcm5v
|
||||
MQ8wDQYDVQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzERMA8GA1UEAwwIc2VydmVy
|
||||
Y2EwHhcNMjEwOTAzMTExNjMyWhcNMzEwOTAxMTExNjMyWjBkMQswCQYDVQQGEwJD
|
||||
WjETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwG
|
||||
Q0VTTkVUMQwwCgYDVQQLDANUTUMxEjAQBgNVBAMMCTEyNy4wLjAuMTCCAiIwDQYJ
|
||||
KoZIhvcNAQEBBQADggIPADCCAgoCggIBAOqI7Y3w5r8kD9WZCMAaa/e3ig7nm76a
|
||||
IJUR0Xb1bk6X/4FNVQKwEJsBodOYupZvE5FZdZ6DJSMSyQ3FrJWnlZ+isr7F9B4b
|
||||
ELV8Kj6sJGuVAr+mpcH/4rwL3DaXF9Y9Lf7iBgiOHUoip80Asn9BU4q80JI6w2VH
|
||||
d5ng4TUE67gmpRleIHzViKt3taBrsAJ9bS5bvaE6xOB8zKYGzRFOsDZrEqqcBsVI
|
||||
WC6EmjO29HS5qj/mXM0ktFGnNDxTZHoRkNgmCE/NH+fNKOFxraCwlFBpKemAky+G
|
||||
dgngRGiQAVowyAx/nSmCFAalKc+E4ddoFwD/oft6iOvvXqaXh6368wEQ7Hy48FDc
|
||||
UCbHtUEgK4wMrX9BSrRh6zkXO1tE4ghb0dM2qFDS0ypO3p04kUPa31mTgLuOH1Lz
|
||||
wmlwxOs113mlYKCgqOFR5YaN+nq1HI5RATPo5NvCMpG2RrQW+ooCr2GtbT0oHmJv
|
||||
8yaBVY0HJ69eLnIv37dfjWvoTiBKBBIisXAD5Nm9rwSjZUSFu1iyd7u2YrkBCUzZ
|
||||
uvt3BOPpX8GgQgagU6BPnac76FF6DMhRUXlBXdTuWsbuH14LdNIzGjkMZhNL/Tpk
|
||||
f6S/z1iH5VReGc+clTjWGg1XO5fr3mNKBGa7hDydIZRIMbgsy63DIY7n5dqhNkO3
|
||||
0CGmr/9TagVZAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEjP2Zed4zY/nProMy67
|
||||
JyI3vV2fDYpYUkPD7ofSjFHjQc3ooXfBCF6Ho0dCdBTpof6kGIjfDmhcKoVcPqr8
|
||||
A/EA1pEGOB0RZkCjrwEnbAVdIb/5QP6nLtm7M5md3dEF+rttfBwisH6CV4XbXXZc
|
||||
t/cNP+MPK2sXevCK2w8Xbt9nHeI/MXZoUW3WNGFwlRNlmQxCIoI0hnge9Gyb0WcT
|
||||
ciHvhm8WtUQI1Ff3DLDgcQZQ1oOhci+ocBJVhC9l9lDCOpu93coyM7PD4CbVTFxf
|
||||
nPnOy81525W6ya0nmZOKafG20bdc+T1LqMXM+uR5hBHsg9K6UbREHEoP3pLYW7zg
|
||||
0Aw=
|
||||
-----END CERTIFICATE-----
|
51
tests/data/server.key
Normal file
51
tests/data/server.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIJKAIBAAKCAgEA6ojtjfDmvyQP1ZkIwBpr97eKDuebvpoglRHRdvVuTpf/gU1V
|
||||
ArAQmwGh05i6lm8TkVl1noMlIxLJDcWslaeVn6KyvsX0HhsQtXwqPqwka5UCv6al
|
||||
wf/ivAvcNpcX1j0t/uIGCI4dSiKnzQCyf0FTirzQkjrDZUd3meDhNQTruCalGV4g
|
||||
fNWIq3e1oGuwAn1tLlu9oTrE4HzMpgbNEU6wNmsSqpwGxUhYLoSaM7b0dLmqP+Zc
|
||||
zSS0Uac0PFNkehGQ2CYIT80f580o4XGtoLCUUGkp6YCTL4Z2CeBEaJABWjDIDH+d
|
||||
KYIUBqUpz4Th12gXAP+h+3qI6+9eppeHrfrzARDsfLjwUNxQJse1QSArjAytf0FK
|
||||
tGHrORc7W0TiCFvR0zaoUNLTKk7enTiRQ9rfWZOAu44fUvPCaXDE6zXXeaVgoKCo
|
||||
4VHlho36erUcjlEBM+jk28IykbZGtBb6igKvYa1tPSgeYm/zJoFVjQcnr14uci/f
|
||||
t1+Na+hOIEoEEiKxcAPk2b2vBKNlRIW7WLJ3u7ZiuQEJTNm6+3cE4+lfwaBCBqBT
|
||||
oE+dpzvoUXoMyFFReUFd1O5axu4fXgt00jMaOQxmE0v9OmR/pL/PWIflVF4Zz5yV
|
||||
ONYaDVc7l+veY0oEZruEPJ0hlEgxuCzLrcMhjufl2qE2Q7fQIaav/1NqBVkCAwEA
|
||||
AQKCAgAeRZw75Oszoqj0jfMmMILdD3Cfad+dY3FvLESYESeyt0XAX8XoOed6ymQj
|
||||
1qPGxQGGkkBvPEgv1b3jrC8Rhfb3Ct39Z7mRpTar5iHhwwBUboBTUmQ0vR173iAH
|
||||
X8sw2Oa17mCO/CDlr8Fu4Xcom7r3vlVBepo72VSjpPYMjN0MANjwhEi3NCyWzTXB
|
||||
RgUK3TuZbzfzto0w2Irlpx0S7dAqxfk70jXBgwv2vSDWKfg1lL1X0BkMVX98xpMk
|
||||
cjMW2muSqp4KBtTma4GqT6z0f7Y1Bs3lGLZmvPlBXxQVVvkFtiQsENCtSd/h17Gk
|
||||
2mb4EbReaaBzwCYqJdRWtlpJ54kzy8U00co+Yn//ZS7sbbIDkqHPnXkpdIr+0rED
|
||||
MlOw2Y3vRZCxqZFqfWCW0uzhwKqk2VoYqtDL+ORKG/aG/KTBQ4Y71Uh+7aabPwj5
|
||||
R+NaVMjbqmrVeH70eKjoNVgcNYY1C9rGVF1d+LQEm7UsqS0DPp4wN9QKLAqIfuar
|
||||
AhQBhZy1R7Sj1r5macD9DsGxsurM4mHZV0LNmYLZiFHjTUb6iRSPD5RBFW80vcNt
|
||||
xZ0cxmkLtxrj/DVyExV11Cl0SbZLLa9mScYvxdl/qZutXt3PQyab0NiYxGzCD2Rn
|
||||
LkCyxkh1vuHHjhvIWYfbd2VgZB/qGr+o9T07FGfMCu23//fugQKCAQEA9UH38glH
|
||||
/rAjZ431sv6ryUEFY8I2FyLTijtvoj9CNGcQn8vJQAHvUPfMdyqDoum6wgcTmG+U
|
||||
XA6mZzpGQCiY8JW5CoItgXRoYgNzpvVVe2aLf51QGtNLLEFpNDMpCtI+I+COpAmG
|
||||
vWAukku0pZfRjm9eb1ydvTpHlFC9+VhVUsLzw3VtSC5PVW6r65mZcYcB6SFVPap+
|
||||
31ENP/9jOMFoymh57lSMZJMxTEA5b0l2miFb9Rp906Zqiud5zv2jIqF6gL70giW3
|
||||
ovVxR7LGKKTKIa9pxawHwB6Ithygs7YoJkjF2dm8pZTMZKsQN92K70XGj07SmYRL
|
||||
ZpkVD7i+cqbbKQKCAQEA9M6580Rcw6W0twfcy0/iB4U5ZS52EcCjW8vHlL+MpUo7
|
||||
YvXadSgV1ZaM28zW/ZGk3wE0zy1YT5s30SQkm0NiWN3t/J0l19ccAOxlPWfjhF7v
|
||||
IQZr7XMo5HeaK0Ak5+68J6bx6KgcXmlJOup7INaE8DyGXB6vd4K6957IXyqs3/bf
|
||||
JAUmz49hnveCfLFdTVVT/Uq4IoPKfQSbSZc0BvPBsnBCF164l4jllGBaWS302dhg
|
||||
W4cgxzG0SZGgNwow4AhB+ygiiS8yvOa7UcHfUObVrzWeeq9mYSQ1PkvUTjkWR2/Y
|
||||
8xy7WP0TRBdJOVSs90H51lerEDGNQWvQvI97S9ZOsQKCAQB59u9lpuXtqwxAQCFy
|
||||
fSFSuQoEHR2nDcOjF4GhbtHum15yCPaw5QVs/33nuPWze4ZLXReKk9p0mTh5V0p+
|
||||
N3IvGlXl+uzEVu5d55eI7LIw5sLymHmwjWjxvimiMtrzLbCHSPHGc5JU9NLUH9/b
|
||||
BY/JxGpy+NzcsHHOOQTwTdRIjviIOAo7fgQn2RyX0k+zXE8/7zqjqvji9zyemdNu
|
||||
8we4uJICSntyvJwkbj/hrufTKEnBrwXpzfVn1EsH+6w32ZPBGLUhT75txJ8r56SR
|
||||
q7l1XPU9vxovmT+lSMFF/Y0j1MbHWnds5H1shoFPNtYTvWBL/gfPHjIc+H23zsiu
|
||||
3XlZAoIBAC2xB/Pnpoi9vOUMiqFH36AXtYa1DURy+AqCFlYlClMvb7YgvQ1w1eJv
|
||||
nwrHSLk7HdKhnwGsLPduuRRH8q0n/osnoOutSQroE0n41UyIv2ZNccRwNmSzQcai
|
||||
rBu2dSz02hlsh2otNl5IuGpOqXyPjXBpW4qGD6n2tH7THALnLC0BHtTSQVQsJsRM
|
||||
3gX39LoiWvLDp2qJvplm6rTpi8Rgap6rZSqHe1yNKIxxD2vlr/WY9SMgLXYASO4S
|
||||
SBz9wfGOmQIPk6KXNJkdV4kC7nNjIi75iwLLCgjHgUiHTrDq5sWekpeNnUoWsinb
|
||||
Tsdsjnv3zHG9GyiClyLGxMbs4M5eyYECggEBAKuC8ZMpdIrjk6tERYB6g0LnQ7mW
|
||||
8XYbDFAmLYMLs9yfG2jcjVbsW9Kugsr+3poUUv/q+hNO3jfY4HazhZDa0MalgNPo
|
||||
Swr/VNRnkck40x2ovFb989J7yl++zTrnIrax9XRH1V0cNu+Kj7OMwZ2RRfbNv5JB
|
||||
dOZPvkfqyIKFmbQgYbtD66rHuzNOfJpzqr/WVLO57/zzW8245NKG2B6B0oXkei/K
|
||||
qDY0DAbHR3i3EOj1NPtVI1FC/xX8R9BREaid458bqoHJKuInrGcBjaUI9Cvymv8T
|
||||
bstUgD6NPbJR4Sm6vrLeUqzjWZP3t1+Z6DjXmnpR2vvhMU/FWb//21p/88o=
|
||||
-----END RSA PRIVATE KEY-----
|
27
tests/data/serverca.key
Normal file
27
tests/data/serverca.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpgIBAAKCAQEAyMrKraqraFGklO2itRIEWxfuzWo1IwxZ22aJmeXDLeomt689
|
||||
3NXelMLaC3swQ+hu49JjiIY81DXvbVgmIgLm7cAz5tHTHuJbfdI4Q6gyic4aOpy2
|
||||
s3s1/vYz+1TvEUFCiPXEsJrH72he/z9nBxL8vY6Eg8U8EG8NvKp9zyCKA7vmNSgQ
|
||||
OtuyF18fesYHAnvQjNXO5q6diPXdHOr2bjTRUvARGbWlv4Rvf81RwUkRsWoF/0pg
|
||||
lV/TxnW2MoHnn3apxb/kmH92CQ+GWKxq5SkhvbkYePlA87kgKnDtXl4wEXIhYwM5
|
||||
1kafRhhlAKN+qYeV9teBqGpjsZRYesrh3mXHlQIDAQABAoIBAQC0eeI2usKaX1fJ
|
||||
LNckXW9g2WAhbicYu49ArydbFrOaX24xh+fYyLrph0IpM66sOw0A5SflnJKsQ1ZT
|
||||
N/n+dBFQ/YMpIsvaZKbLrto3pcTXLFNS/20QYdyksHMEotDG95twM0d5XYX74BoS
|
||||
3tAiAaT+VE0zi2Jzev4j6DJwq9ShiPclZFcpAbyVqi77ruJLID0j+lxLEOsTpN9h
|
||||
Y/36CMwfAVe8OwiBl8vOAjEf3ssNz0iesEIB/Rx0rmg0dNquuYvJmF7pJNdQNq7Q
|
||||
5fOM5Ww0iwqb8lzIU9fkMwFhljcxtc51nrr6mg8kKT1A0cDu4dJuYa6Od+IkW0nP
|
||||
ozE7JDo5AoGBAPgfEwtsr/w5OFDtwiO+9wRxug+M6zuczeYIvK/FtDSghnZv18MK
|
||||
HZJx6omApdgqF10ya5VuZg6VGBCO7DF20wORWriI7zPXIY0QBIw5zzEnMpw/wW6J
|
||||
GSQ3KBBgVJKiSsv0pmf7h+pt2Tz/leh4bIgV7gryYyy2x+M0S5qk30EjAoGBAM8q
|
||||
/PdTwpE8AKEr5LgQvSUpSXKl2tLewyK6XL7FMNIQxe8frlIeF+jgPsNFlWaVl+e6
|
||||
qDksEqlltn2rmBRYVsSWFytpOHyVAfFtoJw1Qpa7bx3cYqA+jgIw3Lrva3AdircW
|
||||
DG9sLjk4V3y5FJogXuNbeYj/exUq4CTzRwMoXIvnAoGBAOyHWvVaIA3WUkw7ywWe
|
||||
hwZSj+dBFAHZAiMXEyCQ3LAKkwQWrF1+qCAxvj5kSDTgMzOh3BMwkdO256DpTln9
|
||||
Bz1wdEZUK4uEurQpn9w5Q718u29eC7yerzvp5KRv4E+ErL7vMy8PBktBeoT+tN5O
|
||||
5k94cFs5I7e9aqG5+ZSrNTR3AoGBAIln7djtiUNjFNfRkSY0k/+t3rVYJEdw0OSb
|
||||
zyAJElSCI4Zy8OAubZVcBsTlxi4AUny0ZRdmkAojGGNKCNiVrxc8pal5ZKnc+yjy
|
||||
mXCCMuRe9VhM8G1wkCgL2Jt0aUI3leXRjfXpPs9c+0oSSAPiLI2IAphHO4/SnFBl
|
||||
u1fw0VFJAoGBAK+yZBxqo3nJqYhhPyvNUyEkDZJnuhcc7mQJsPd4AbgmeN/3izbI
|
||||
2Rvn1wzkqz5LoCvAWAg51gWJBO99XvuT/J0ob4w494NtUYJdSq8Bg7dkebhdaAXl
|
||||
lBXCI5kOmboHCaTsbJlXglxv7p6zkctU844p2Ki8XlkAbQTL+uQgZ6fE
|
||||
-----END RSA PRIVATE KEY-----
|
22
tests/data/serverca.pem
Normal file
22
tests/data/serverca.pem
Normal file
|
@ -0,0 +1,22 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDnDCCAoSgAwIBAgIJAIjf7UNx4uabMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
|
||||
BAYTAkNaMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQHDARCcm5vMQ8wDQYD
|
||||
VQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzERMA8GA1UEAwwIc2VydmVyY2EwHhcN
|
||||
MTgxMTA1MDcyNjM5WhcNMjgxMTAyMDcyNjM5WjBjMQswCQYDVQQGEwJDWjETMBEG
|
||||
A1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwGQ0VTTkVU
|
||||
MQwwCgYDVQQLDANUTUMxETAPBgNVBAMMCHNlcnZlcmNhMIIBIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAQ8AMIIBCgKCAQEAyMrKraqraFGklO2itRIEWxfuzWo1IwxZ22aJmeXD
|
||||
Leomt6893NXelMLaC3swQ+hu49JjiIY81DXvbVgmIgLm7cAz5tHTHuJbfdI4Q6gy
|
||||
ic4aOpy2s3s1/vYz+1TvEUFCiPXEsJrH72he/z9nBxL8vY6Eg8U8EG8NvKp9zyCK
|
||||
A7vmNSgQOtuyF18fesYHAnvQjNXO5q6diPXdHOr2bjTRUvARGbWlv4Rvf81RwUkR
|
||||
sWoF/0pglV/TxnW2MoHnn3apxb/kmH92CQ+GWKxq5SkhvbkYePlA87kgKnDtXl4w
|
||||
EXIhYwM51kafRhhlAKN+qYeV9teBqGpjsZRYesrh3mXHlQIDAQABo1MwUTAdBgNV
|
||||
HQ4EFgQU60nJ4q3ItcfaOOBjJSqadAPiMg8wHwYDVR0jBBgwFoAU60nJ4q3Itcfa
|
||||
OOBjJSqadAPiMg8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
xIqIQ5SCXnKslZfrXiAEbB5dglxVOSa8me5a/70uHK/27JZ6veeIgRqZ4VgPHnBC
|
||||
a3m6EHr+mnTjjqSUcGIUiKV3g2Dumw8paqZC+Qv+Ib/NKquS1lO2Ry1wHBtXzn5K
|
||||
KHHyM1bWMDaDszirw2+pp22VdRrPZNA9NWXheEDYOLyQekyL2CfidhxhaXvUZyWg
|
||||
alLyF2XRZ5/jAT+NjfWw39EmWPUGk13Jm83OaFc1VdrXNCiD0sGCQ+BTCllDinQv
|
||||
R08yzd4fzA3YXthvX1dBu1SvqQAGOS7gssRCyv9uWI6MXta25X91eY1ZMz1euJ04
|
||||
mB8EdyYiZc0kzrb9dv5d0g==
|
||||
-----END CERTIFICATE-----
|
10
tests/ld.supp
Normal file
10
tests/ld.supp
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
ld
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
fun:calloc
|
||||
fun:_dlerror_run
|
||||
fun:dlopen@@GLIBC_2.2.5
|
||||
fun:lyext_load_plugins
|
||||
fun:ly_ctx_new
|
||||
}
|
77
tests/test_client_thread.c
Normal file
77
tests/test_client_thread.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* \file test_client_thread.c
|
||||
* \author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* \brief libnetconf2 tests - threads functions in client
|
||||
*
|
||||
* Copyright (c) 2017 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <session_client.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
#define nc_assert(cond) if (!(cond)) { fprintf(stderr, "assert failed (%s:%d)\n", __FILE__, __LINE__); exit(1); }
|
||||
|
||||
static void *
|
||||
thread(void *arg)
|
||||
{
|
||||
/* default search path is NULL */
|
||||
nc_assert(nc_client_get_schema_searchpath() == NULL);
|
||||
|
||||
/* use the context shared from the main thread */
|
||||
nc_client_set_thread_context(arg);
|
||||
|
||||
/* check that we have now the search path set in main thread */
|
||||
nc_assert(strcmp(nc_client_get_schema_searchpath(), "/tmp") == 0);
|
||||
/* and change it to check it later in main thread */
|
||||
nc_assert(nc_client_set_schema_searchpath("/etc") == 0)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
void *arg;
|
||||
pthread_t t;
|
||||
int r;
|
||||
|
||||
nc_client_init();
|
||||
|
||||
/*
|
||||
* TEST sharing the thread context
|
||||
*/
|
||||
nc_assert(nc_client_set_schema_searchpath("/tmp") == 0)
|
||||
|
||||
/* get the context for sharing */
|
||||
arg = nc_client_get_thread_context();
|
||||
|
||||
/* create new thread and provide the context */
|
||||
r = pthread_create(&t, NULL, &thread, arg);
|
||||
nc_assert(r == 0);
|
||||
|
||||
pthread_join(t, NULL);
|
||||
|
||||
/* check the changed search path value from the thread */
|
||||
nc_assert(strcmp(nc_client_get_schema_searchpath(), "/etc") == 0);
|
||||
|
||||
/* cleanup */
|
||||
nc_client_destroy();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
555
tests/test_fd_comm.c
Normal file
555
tests/test_fd_comm.c
Normal file
|
@ -0,0 +1,555 @@
|
|||
/**
|
||||
* \file test_fd_comm.c
|
||||
* \author Michal Vasko <mvasko@cesnet.cz>
|
||||
* \brief libnetconf2 tests - file descriptor basic RPC communication
|
||||
*
|
||||
* Copyright (c) 2015 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <messages_p.h>
|
||||
#include <session_client.h>
|
||||
#include <session_p.h>
|
||||
#include <session_server.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
struct nc_session *server_session;
|
||||
struct nc_session *client_session;
|
||||
struct ly_ctx *ctx;
|
||||
pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_barrier_t barrier;
|
||||
int glob_state;
|
||||
|
||||
struct nc_server_reply *
|
||||
my_get_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
||||
{
|
||||
assert_string_equal(rpc->schema->name, "get");
|
||||
assert_ptr_equal(session, server_session);
|
||||
|
||||
return nc_server_reply_ok();
|
||||
}
|
||||
|
||||
struct nc_server_reply *
|
||||
my_getconfig_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
||||
{
|
||||
struct lyd_node *data;
|
||||
|
||||
assert_string_equal(rpc->schema->name, "get-config");
|
||||
assert_ptr_equal(session, server_session);
|
||||
|
||||
lyd_new_path(NULL, session->ctx, "/ietf-netconf:get-config/data", NULL, LYD_NEW_PATH_OUTPUT, &data);
|
||||
assert_non_null(data);
|
||||
|
||||
return nc_server_reply_data(data, NC_WD_EXPLICIT, NC_PARAMTYPE_FREE);
|
||||
}
|
||||
|
||||
struct nc_server_reply *
|
||||
my_commit_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
||||
{
|
||||
assert_string_equal(rpc->schema->name, "commit");
|
||||
assert_ptr_equal(session, server_session);
|
||||
|
||||
/* update state */
|
||||
pthread_mutex_lock(&state_lock);
|
||||
glob_state = 1;
|
||||
|
||||
/* wait until the client receives the notification */
|
||||
while (glob_state != 3) {
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
usleep(100000);
|
||||
pthread_mutex_lock(&state_lock);
|
||||
}
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
|
||||
return nc_server_reply_ok();
|
||||
}
|
||||
|
||||
static struct nc_session *
|
||||
test_new_session(NC_SIDE side)
|
||||
{
|
||||
struct nc_session *sess;
|
||||
|
||||
sess = calloc(1, sizeof *sess);
|
||||
if (!sess) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sess->side = side;
|
||||
|
||||
if (side == NC_SERVER) {
|
||||
pthread_mutex_init(&sess->opts.server.rpc_lock, NULL);
|
||||
pthread_cond_init(&sess->opts.server.rpc_cond, NULL);
|
||||
sess->opts.server.rpc_inuse = 0;
|
||||
}
|
||||
|
||||
sess->io_lock = malloc(sizeof *sess->io_lock);
|
||||
if (!sess->io_lock) {
|
||||
goto error;
|
||||
}
|
||||
pthread_mutex_init(sess->io_lock, NULL);
|
||||
|
||||
return sess;
|
||||
|
||||
error:
|
||||
free(sess);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_sessions(void **state)
|
||||
{
|
||||
(void)state;
|
||||
int sock[2];
|
||||
|
||||
/* create communication channel */
|
||||
socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
|
||||
|
||||
/* create server session */
|
||||
server_session = test_new_session(NC_SERVER);
|
||||
server_session->status = NC_STATUS_RUNNING;
|
||||
server_session->id = 1;
|
||||
server_session->ti_type = NC_TI_FD;
|
||||
server_session->ti.fd.in = sock[0];
|
||||
server_session->ti.fd.out = sock[0];
|
||||
server_session->ctx = ctx;
|
||||
server_session->flags = NC_SESSION_SHAREDCTX;
|
||||
|
||||
/* create client session */
|
||||
client_session = test_new_session(NC_CLIENT);
|
||||
client_session->status = NC_STATUS_RUNNING;
|
||||
client_session->id = 1;
|
||||
client_session->ti_type = NC_TI_FD;
|
||||
client_session->ti.fd.in = sock[1];
|
||||
client_session->ti.fd.out = sock[1];
|
||||
client_session->ctx = ctx;
|
||||
client_session->flags = NC_SESSION_SHAREDCTX;
|
||||
client_session->opts.client.msgid = 50;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_sessions(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
close(server_session->ti.fd.in);
|
||||
server_session->ti.fd.in = -1;
|
||||
nc_session_free(server_session, NULL);
|
||||
|
||||
close(client_session->ti.fd.in);
|
||||
client_session->ti.fd.in = -1;
|
||||
nc_session_free(client_session, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_ok(void)
|
||||
{
|
||||
int ret;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE msgtype;
|
||||
struct nc_rpc *rpc;
|
||||
struct lyd_node *envp, *op;
|
||||
struct nc_pollsession *ps;
|
||||
|
||||
/* client RPC */
|
||||
rpc = nc_rpc_get(NULL, 0, 0);
|
||||
assert_non_null(rpc);
|
||||
|
||||
msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
|
||||
assert_int_equal(msgtype, NC_MSG_RPC);
|
||||
|
||||
/* server RPC, send reply */
|
||||
ps = nc_ps_new();
|
||||
assert_non_null(ps);
|
||||
nc_ps_add_session(ps, server_session);
|
||||
|
||||
ret = nc_ps_poll(ps, 0, NULL);
|
||||
assert_int_equal(ret, NC_PSPOLL_RPC);
|
||||
|
||||
/* server finished */
|
||||
nc_ps_free(ps);
|
||||
|
||||
/* client reply */
|
||||
msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
|
||||
assert_int_equal(msgtype, NC_MSG_REPLY);
|
||||
|
||||
nc_rpc_free(rpc);
|
||||
assert_null(op);
|
||||
assert_string_equal(LYD_NAME(lyd_child(envp)), "ok");
|
||||
lyd_free_tree(envp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_ok_10(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_10;
|
||||
client_session->version = NC_VERSION_10;
|
||||
|
||||
test_send_recv_ok();
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_ok_11(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_11;
|
||||
client_session->version = NC_VERSION_11;
|
||||
|
||||
test_send_recv_ok();
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_error(void)
|
||||
{
|
||||
int ret;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE msgtype;
|
||||
struct nc_rpc *rpc;
|
||||
struct lyd_node *envp, *op, *node;
|
||||
struct nc_pollsession *ps;
|
||||
|
||||
/* client RPC */
|
||||
rpc = nc_rpc_kill(1);
|
||||
assert_non_null(rpc);
|
||||
|
||||
msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
|
||||
assert_int_equal(msgtype, NC_MSG_RPC);
|
||||
|
||||
/* server RPC, send reply */
|
||||
ps = nc_ps_new();
|
||||
assert_non_null(ps);
|
||||
nc_ps_add_session(ps, server_session);
|
||||
|
||||
ret = nc_ps_poll(ps, 0, NULL);
|
||||
assert_int_equal(ret, NC_PSPOLL_RPC | NC_PSPOLL_REPLY_ERROR);
|
||||
|
||||
/* server finished */
|
||||
nc_ps_free(ps);
|
||||
|
||||
/* client reply */
|
||||
msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
|
||||
assert_int_equal(msgtype, NC_MSG_REPLY);
|
||||
|
||||
nc_rpc_free(rpc);
|
||||
assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
|
||||
lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
|
||||
assert_non_null(node);
|
||||
assert_string_equal(((struct lyd_node_opaq *)node)->value, "operation-not-supported");
|
||||
lyd_free_tree(envp);
|
||||
assert_null(op);
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_error_10(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_10;
|
||||
client_session->version = NC_VERSION_10;
|
||||
|
||||
test_send_recv_error();
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_error_11(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_11;
|
||||
client_session->version = NC_VERSION_11;
|
||||
|
||||
test_send_recv_error();
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_data(void)
|
||||
{
|
||||
int ret;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE msgtype;
|
||||
struct nc_rpc *rpc;
|
||||
struct lyd_node *envp, *op;
|
||||
struct nc_pollsession *ps;
|
||||
|
||||
/* client RPC */
|
||||
rpc = nc_rpc_getconfig(NC_DATASTORE_RUNNING, NULL, 0, 0);
|
||||
assert_non_null(rpc);
|
||||
|
||||
msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
|
||||
assert_int_equal(msgtype, NC_MSG_RPC);
|
||||
|
||||
/* server RPC, send reply */
|
||||
ps = nc_ps_new();
|
||||
assert_non_null(ps);
|
||||
nc_ps_add_session(ps, server_session);
|
||||
|
||||
ret = nc_ps_poll(ps, 0, NULL);
|
||||
assert_int_equal(ret, NC_PSPOLL_RPC);
|
||||
|
||||
/* server finished */
|
||||
nc_ps_free(ps);
|
||||
|
||||
/* client reply */
|
||||
msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
|
||||
assert_int_equal(msgtype, NC_MSG_REPLY);
|
||||
|
||||
nc_rpc_free(rpc);
|
||||
assert_non_null(envp);
|
||||
lyd_free_tree(envp);
|
||||
assert_non_null(op);
|
||||
lyd_free_tree(op);
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_data_10(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_10;
|
||||
client_session->version = NC_VERSION_10;
|
||||
|
||||
test_send_recv_data();
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_data_11(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_11;
|
||||
client_session->version = NC_VERSION_11;
|
||||
|
||||
test_send_recv_data();
|
||||
}
|
||||
|
||||
static void *
|
||||
server_send_notif_thread(void *arg)
|
||||
{
|
||||
NC_MSG_TYPE msg_type;
|
||||
struct lyd_node *notif_tree;
|
||||
struct nc_server_notif *notif;
|
||||
struct timespec ts;
|
||||
char *buf;
|
||||
|
||||
(void)arg;
|
||||
|
||||
/* wait for the RPC callback to be called */
|
||||
pthread_mutex_lock(&state_lock);
|
||||
while (glob_state != 1) {
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
usleep(1000);
|
||||
pthread_mutex_lock(&state_lock);
|
||||
}
|
||||
|
||||
/* create notif */
|
||||
lyd_new_path(NULL, ctx, "/nc-notifications:notificationComplete", NULL, 0, ¬if_tree);
|
||||
assert_non_null(notif_tree);
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ly_time_ts2str(&ts, &buf);
|
||||
notif = nc_server_notif_new(notif_tree, buf, NC_PARAMTYPE_FREE);
|
||||
assert_non_null(notif);
|
||||
|
||||
/* send notif */
|
||||
nc_session_inc_notif_status(server_session);
|
||||
msg_type = nc_server_notif_send(server_session, notif, 100);
|
||||
nc_server_notif_free(notif);
|
||||
assert_int_equal(msg_type, NC_MSG_NOTIF);
|
||||
|
||||
/* update state */
|
||||
glob_state = 2;
|
||||
pthread_barrier_wait(&barrier);
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
thread_recv_notif(void *arg)
|
||||
{
|
||||
struct nc_session *session = (struct nc_session *)arg;
|
||||
struct lyd_node *envp;
|
||||
struct lyd_node *op;
|
||||
NC_MSG_TYPE msgtype;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
msgtype = nc_recv_notif(session, 1000, &envp, &op);
|
||||
assert_int_equal(msgtype, NC_MSG_NOTIF);
|
||||
assert_string_equal(op->schema->name, "notificationComplete");
|
||||
|
||||
lyd_free_tree(envp);
|
||||
lyd_free_tree(op);
|
||||
|
||||
pthread_mutex_lock(&state_lock);
|
||||
glob_state = 3;
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_notif(void)
|
||||
{
|
||||
int ret;
|
||||
pthread_t tid[2];
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE msgtype;
|
||||
struct nc_rpc *rpc;
|
||||
struct lyd_node *envp, *op;
|
||||
struct nc_pollsession *ps;
|
||||
|
||||
/* client RPC */
|
||||
rpc = nc_rpc_commit(0, 0, NULL, NULL, 0);
|
||||
assert_non_null(rpc);
|
||||
|
||||
msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
|
||||
assert_int_equal(msgtype, NC_MSG_RPC);
|
||||
|
||||
/* client subscription */
|
||||
pthread_create(&tid[0], NULL, thread_recv_notif, client_session);
|
||||
|
||||
/* create server */
|
||||
ps = nc_ps_new();
|
||||
assert_non_null(ps);
|
||||
nc_ps_add_session(ps, server_session);
|
||||
|
||||
/* server will send a notification */
|
||||
pthread_mutex_lock(&state_lock);
|
||||
glob_state = 0;
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
ret = pthread_create(&tid[1], NULL, server_send_notif_thread, NULL);
|
||||
assert_int_equal(ret, 0);
|
||||
|
||||
/* server blocked on RPC */
|
||||
ret = nc_ps_poll(ps, 0, NULL);
|
||||
assert_int_equal(ret, NC_PSPOLL_RPC);
|
||||
|
||||
/* RPC, notification finished fine */
|
||||
pthread_mutex_lock(&state_lock);
|
||||
assert_int_equal(glob_state, 3);
|
||||
pthread_mutex_unlock(&state_lock);
|
||||
|
||||
/* server finished */
|
||||
ret = 0;
|
||||
ret |= pthread_join(tid[0], NULL);
|
||||
ret |= pthread_join(tid[1], NULL);
|
||||
assert_int_equal(ret, 0);
|
||||
nc_ps_free(ps);
|
||||
|
||||
/* client reply */
|
||||
msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
|
||||
assert_int_equal(msgtype, NC_MSG_REPLY);
|
||||
nc_rpc_free(rpc);
|
||||
|
||||
assert_string_equal(LYD_NAME(lyd_child(envp)), "ok");
|
||||
lyd_free_tree(envp);
|
||||
assert_null(op);
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_notif_10(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_10;
|
||||
client_session->version = NC_VERSION_10;
|
||||
|
||||
test_send_recv_notif();
|
||||
}
|
||||
|
||||
static void
|
||||
test_send_recv_notif_11(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
server_session->version = NC_VERSION_11;
|
||||
client_session->version = NC_VERSION_11;
|
||||
|
||||
test_send_recv_notif();
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int ret;
|
||||
const struct lys_module *module;
|
||||
struct lysc_node *node;
|
||||
const char *nc_features[] = {"candidate", NULL};
|
||||
|
||||
pthread_barrier_init(&barrier, NULL, 2);
|
||||
|
||||
/* create ctx */
|
||||
ly_ctx_new(TESTS_DIR "/data/modules", 0, &ctx);
|
||||
assert_non_null(ctx);
|
||||
|
||||
/* load modules */
|
||||
module = ly_ctx_load_module(ctx, "ietf-netconf-acm", NULL, NULL);
|
||||
assert_non_null(module);
|
||||
|
||||
module = ly_ctx_load_module(ctx, "ietf-netconf", NULL, nc_features);
|
||||
assert_non_null(module);
|
||||
|
||||
module = ly_ctx_load_module(ctx, "nc-notifications", NULL, NULL);
|
||||
assert_non_null(module);
|
||||
|
||||
/* set RPC callbacks */
|
||||
node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:get", 0);
|
||||
assert_non_null(node);
|
||||
node->priv = my_get_rpc_clb;
|
||||
|
||||
node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:get-config", 0);
|
||||
assert_non_null(node);
|
||||
node->priv = my_getconfig_rpc_clb;
|
||||
|
||||
node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:commit", 0);
|
||||
assert_non_null(node);
|
||||
node->priv = my_commit_rpc_clb;
|
||||
|
||||
nc_server_init(ctx);
|
||||
|
||||
const struct CMUnitTest comm[] = {
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_ok_10, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_error_10, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_data_10, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_notif_10, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_ok_11, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_error_11, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_data_11, setup_sessions, teardown_sessions),
|
||||
cmocka_unit_test_setup_teardown(test_send_recv_notif_11, setup_sessions, teardown_sessions),
|
||||
};
|
||||
|
||||
ret = cmocka_run_group_tests(comm, NULL, NULL);
|
||||
|
||||
nc_server_destroy();
|
||||
ly_ctx_destroy(ctx);
|
||||
pthread_barrier_destroy(&barrier);
|
||||
|
||||
return ret;
|
||||
}
|
69
tests/test_init_destroy_client.c
Normal file
69
tests/test_init_destroy_client.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* \file test_init_destroy_client.c
|
||||
* \author Michal Vasko <mvasko@cesnet.cz>
|
||||
* \brief libnetconf2 tests - init/destroy client
|
||||
*
|
||||
* Copyright (c) 2015 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <session_client.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
static int
|
||||
setup_client(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
nc_client_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_client(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
nc_client_destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dummy(void **state)
|
||||
{
|
||||
(void)state;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest init_destroy[] = {
|
||||
cmocka_unit_test_setup_teardown(test_dummy, setup_client, teardown_client)
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(init_destroy, NULL, NULL);
|
||||
}
|
75
tests/test_init_destroy_server.c
Normal file
75
tests/test_init_destroy_server.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* \file test_init_destroy_server.c
|
||||
* \author Michal Vasko <mvasko@cesnet.cz>
|
||||
* \brief libnetconf2 tests - init/destroy server
|
||||
*
|
||||
* Copyright (c) 2015 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <session_server.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
struct ly_ctx *ctx;
|
||||
|
||||
static int
|
||||
setup_server(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
ly_ctx_new(NULL, 0, &ctx);
|
||||
assert_non_null(ctx);
|
||||
|
||||
nc_server_init(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_server(void **state)
|
||||
{
|
||||
(void)state;
|
||||
|
||||
nc_server_destroy();
|
||||
ly_ctx_destroy(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dummy(void **state)
|
||||
{
|
||||
(void)state;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest init_destroy[] = {
|
||||
cmocka_unit_test_setup_teardown(test_dummy, setup_server, teardown_server)
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(init_destroy, NULL, NULL);
|
||||
}
|
186
tests/test_io.c
Normal file
186
tests/test_io.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* \file test_io.c
|
||||
* \author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* \brief libnetconf2 tests - input/output functions
|
||||
*
|
||||
* Copyright (c) 2015 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <messages_p.h>
|
||||
#include <session_client.h>
|
||||
#include <session_p.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
struct wr {
|
||||
struct nc_session *session;
|
||||
struct nc_rpc *rpc;
|
||||
};
|
||||
|
||||
static int
|
||||
setup_write(void **state)
|
||||
{
|
||||
(void) state; /* unused */
|
||||
int fd, pipes[2];
|
||||
struct wr *w;
|
||||
|
||||
w = malloc(sizeof *w);
|
||||
w->session = calloc(1, sizeof *w->session);
|
||||
ly_ctx_new(TESTS_DIR "/data/modules", 0, &w->session->ctx);
|
||||
|
||||
/* ietf-netconf */
|
||||
fd = open(TESTS_DIR "/data/modules/ietf-netconf.yin", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
free(w);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lys_parse_fd(w->session->ctx, fd, LYS_IN_YIN, NULL);
|
||||
close(fd);
|
||||
|
||||
assert_return_code(pipe(pipes), errno);
|
||||
|
||||
w->session->status = NC_STATUS_RUNNING;
|
||||
w->session->version = NC_VERSION_10;
|
||||
w->session->opts.client.msgid = 999;
|
||||
w->session->ti_type = NC_TI_FD;
|
||||
w->session->io_lock = malloc(sizeof *w->session->io_lock);
|
||||
pthread_mutex_init(w->session->io_lock, NULL);
|
||||
w->session->ti.fd.in = pipes[0];
|
||||
w->session->ti.fd.out = pipes[1];
|
||||
|
||||
/* get rpc to write */
|
||||
w->rpc = nc_rpc_lock(NC_DATASTORE_RUNNING);
|
||||
assert_non_null(w->rpc);
|
||||
|
||||
*state = w;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_write(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
|
||||
nc_rpc_free(w->rpc);
|
||||
close(w->session->ti.fd.in);
|
||||
w->session->ti.fd.in = -1;
|
||||
close(w->session->ti.fd.out);
|
||||
w->session->ti.fd.out = -1;
|
||||
nc_session_free(w->session, NULL);
|
||||
free(w);
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_rpc(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE type;
|
||||
|
||||
w->session->side = NC_CLIENT;
|
||||
|
||||
do {
|
||||
type = nc_send_rpc(w->session, w->rpc, 1000, &msgid);
|
||||
} while (type == NC_MSG_WOULDBLOCK);
|
||||
|
||||
assert_int_equal(type, NC_MSG_RPC);
|
||||
|
||||
assert_int_equal(write(w->session->ti.fd.out, "\n", 1), 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_rpc_10(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
|
||||
w->session->version = NC_VERSION_10;
|
||||
|
||||
return test_write_rpc(state);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_rpc_11(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
|
||||
w->session->version = NC_VERSION_11;
|
||||
|
||||
return test_write_rpc(state);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_rpc_bad(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE type;
|
||||
|
||||
w->session->side = NC_SERVER;
|
||||
pthread_mutex_init(&w->session->opts.server.rpc_lock, NULL);
|
||||
pthread_cond_init(&w->session->opts.server.rpc_cond, NULL);
|
||||
w->session->opts.server.rpc_inuse = 0;
|
||||
|
||||
do {
|
||||
type = nc_send_rpc(w->session, w->rpc, 1000, &msgid);
|
||||
} while (type == NC_MSG_WOULDBLOCK);
|
||||
|
||||
assert_int_equal(type, NC_MSG_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_rpc_10_bad(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
|
||||
w->session->version = NC_VERSION_10;
|
||||
|
||||
return test_write_rpc_bad(state);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_rpc_11_bad(void **state)
|
||||
{
|
||||
struct wr *w = (struct wr *)*state;
|
||||
|
||||
w->session->version = NC_VERSION_11;
|
||||
|
||||
return test_write_rpc_bad(state);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest io[] = {
|
||||
cmocka_unit_test_setup_teardown(test_write_rpc_10, setup_write, teardown_write),
|
||||
cmocka_unit_test_setup_teardown(test_write_rpc_10_bad, setup_write, teardown_write),
|
||||
cmocka_unit_test_setup_teardown(test_write_rpc_11, setup_write, teardown_write),
|
||||
cmocka_unit_test_setup_teardown(test_write_rpc_11_bad, setup_write, teardown_write)
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(io, NULL, NULL);
|
||||
}
|
765
tests/test_server_thread.c
Normal file
765
tests/test_server_thread.c
Normal file
|
@ -0,0 +1,765 @@
|
|||
/**
|
||||
* \file test_server_thread.c
|
||||
* \author Michal Vasko <mvasko@cesnet.cz>
|
||||
* \brief libnetconf2 tests - thread-safety of all server functions
|
||||
*
|
||||
* Copyright (c) 2017 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <log.h>
|
||||
#include <session_client.h>
|
||||
#include <session_server.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
/* millisec */
|
||||
#define NC_ACCEPT_TIMEOUT 5000
|
||||
/* millisec */
|
||||
#define NC_PS_POLL_TIMEOUT 5000
|
||||
/* sec */
|
||||
#define CLIENT_SSH_AUTH_TIMEOUT 10
|
||||
|
||||
#define nc_assert(cond) if (!(cond)) { fprintf(stderr, "assert failed (%s:%d)\n", __FILE__, __LINE__); exit(1); }
|
||||
|
||||
#if _POSIX_BARRIERS >= 200112L
|
||||
pthread_barrier_t barrier;
|
||||
|
||||
#if defined (NC_ENABLED_SSH) || defined (NC_ENABLED_TLS)
|
||||
|
||||
static void *
|
||||
server_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
NC_MSG_TYPE msgtype;
|
||||
int ret;
|
||||
struct nc_pollsession *ps;
|
||||
struct nc_session *session;
|
||||
|
||||
ps = nc_ps_new();
|
||||
nc_assert(ps);
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
#if defined (NC_ENABLED_SSH) && defined (NC_ENABLED_TLS)
|
||||
msgtype = nc_accept(NC_ACCEPT_TIMEOUT, &session);
|
||||
nc_assert(msgtype == NC_MSG_HELLO);
|
||||
|
||||
nc_ps_add_session(ps, session);
|
||||
ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
|
||||
nc_assert(ret & NC_PSPOLL_RPC);
|
||||
nc_ps_clear(ps, 0, NULL);
|
||||
#endif
|
||||
|
||||
msgtype = nc_accept(NC_ACCEPT_TIMEOUT, &session);
|
||||
nc_assert(msgtype == NC_MSG_HELLO);
|
||||
|
||||
nc_ps_add_session(ps, session);
|
||||
ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
|
||||
nc_assert(ret & NC_PSPOLL_RPC);
|
||||
nc_ps_clear(ps, 0, NULL);
|
||||
|
||||
nc_ps_free(ps);
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* NC_ENABLED_SSH || NC_ENABLED_TLS */
|
||||
|
||||
#ifdef NC_ENABLED_SSH
|
||||
|
||||
static int
|
||||
clb_hostkeys(const char *name, void *UNUSED(user_data), char **privkey_path, char **UNUSED(privkey_data),
|
||||
NC_SSH_KEY_TYPE *UNUSED(privkey_type))
|
||||
{
|
||||
if (!strcmp(name, "key_rsa")) {
|
||||
*privkey_path = strdup(TESTS_DIR "/data/key_rsa");
|
||||
return 0;
|
||||
} else if (!strcmp(name, "key_dsa")) {
|
||||
*privkey_path = strdup(TESTS_DIR "/data/key_dsa");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
add_endpt_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
ret = nc_server_add_endpt("tertiary", NC_TI_LIBSSH);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
del_endpt_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_del_endpt("secondary", 0);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_endpt_set_hostkey_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_ssh_endpt_add_hostkey("main_ssh", "key_dsa", -1);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_endpt_set_auth_methods_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_ssh_endpt_set_auth_methods("main_ssh", NC_SSH_AUTH_PUBLICKEY | NC_SSH_AUTH_PASSWORD | NC_SSH_AUTH_INTERACTIVE);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_endpt_set_auth_attempts_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_ssh_endpt_set_auth_attempts("main_ssh", 2);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_endpt_set_auth_timeout_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_ssh_endpt_set_auth_timeout("main_ssh", 5);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_endpt_add_authkey_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_ssh_add_authkey_path(TESTS_DIR "/data/key_rsa.pub", "test3");
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_endpt_del_authkey_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_ssh_del_authkey(TESTS_DIR "/data/key_dsa.pub", NULL, 0, "test2");
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_hostkey_check_clb(const char *hostname, ssh_session session, void *priv)
|
||||
{
|
||||
(void)hostname;
|
||||
(void)session;
|
||||
(void)priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
ssh_client_thread(void *arg)
|
||||
{
|
||||
int ret, read_pipe = *(int *)arg;
|
||||
char buf[9];
|
||||
struct nc_session *session;
|
||||
|
||||
fprintf(stdout, "SSH client start.\n");
|
||||
|
||||
ret = read(read_pipe, buf, 9);
|
||||
nc_assert(ret == 9);
|
||||
nc_assert(!strncmp(buf, "ssh_ready", 9));
|
||||
|
||||
/* skip the knownhost check */
|
||||
nc_client_ssh_set_auth_hostkey_check_clb(ssh_hostkey_check_clb, NULL);
|
||||
|
||||
ret = nc_client_ssh_set_username("test");
|
||||
nc_assert(!ret);
|
||||
|
||||
ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_ecdsa.pub", TESTS_DIR "/data/key_ecdsa");
|
||||
nc_assert(!ret);
|
||||
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
|
||||
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
|
||||
|
||||
session = nc_connect_ssh("127.0.0.1", 6001, NULL);
|
||||
nc_assert(session);
|
||||
|
||||
nc_session_free(session, NULL);
|
||||
|
||||
fprintf(stdout, "SSH client finished.\n");
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* NC_ENABLED_SSH */
|
||||
|
||||
#ifdef NC_ENABLED_TLS
|
||||
|
||||
static int
|
||||
clb_server_cert(const char *name, void *UNUSED(user_data), char **cert_path, char **cert_data, char **privkey_path,
|
||||
char **privkey_data, NC_SSH_KEY_TYPE *privkey_type)
|
||||
{
|
||||
if (!strcmp(name, "server_cert1")) {
|
||||
*cert_data = strdup("MIIEQDCCAygCCQCV65JgDvfWkTANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJD\n"
|
||||
"WjETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwG\n"
|
||||
"Q0VTTkVUMQwwCgYDVQQLDANUTUMxETAPBgNVBAMMCHNlcnZlcmNhMB4XDTE4MTEw\n"
|
||||
"NTA3MzExMFoXDTI4MTEwMjA3MzExMFowYTELMAkGA1UEBhMCQ1oxEzARBgNVBAgM\n"
|
||||
"ClNvbWUtU3RhdGUxDTALBgNVBAcMBEJybm8xDzANBgNVBAoMBkNFU05FVDEMMAoG\n"
|
||||
"A1UECwwDVE1DMQ8wDQYDVQQDDAZzZXJ2ZXIwggIiMA0GCSqGSIb3DQEBAQUAA4IC\n"
|
||||
"DwAwggIKAoICAQDqiO2N8Oa/JA/VmQjAGmv3t4oO55u+miCVEdF29W5Ol/+BTVUC\n"
|
||||
"sBCbAaHTmLqWbxORWXWegyUjEskNxayVp5WforK+xfQeGxC1fCo+rCRrlQK/pqXB\n"
|
||||
"/+K8C9w2lxfWPS3+4gYIjh1KIqfNALJ/QVOKvNCSOsNlR3eZ4OE1BOu4JqUZXiB8\n"
|
||||
"1Yird7Wga7ACfW0uW72hOsTgfMymBs0RTrA2axKqnAbFSFguhJoztvR0uao/5lzN\n"
|
||||
"JLRRpzQ8U2R6EZDYJghPzR/nzSjhca2gsJRQaSnpgJMvhnYJ4ERokAFaMMgMf50p\n"
|
||||
"ghQGpSnPhOHXaBcA/6H7eojr716ml4et+vMBEOx8uPBQ3FAmx7VBICuMDK1/QUq0\n"
|
||||
"Yes5FztbROIIW9HTNqhQ0tMqTt6dOJFD2t9Zk4C7jh9S88JpcMTrNdd5pWCgoKjh\n"
|
||||
"UeWGjfp6tRyOUQEz6OTbwjKRtka0FvqKAq9hrW09KB5ib/MmgVWNByevXi5yL9+3\n"
|
||||
"X41r6E4gSgQSIrFwA+TZva8Eo2VEhbtYsne7tmK5AQlM2br7dwTj6V/BoEIGoFOg\n"
|
||||
"T52nO+hRegzIUVF5QV3U7lrG7h9eC3TSMxo5DGYTS/06ZH+kv89Yh+VUXhnPnJU4\n"
|
||||
"1hoNVzuX695jSgRmu4Q8nSGUSDG4LMutwyGO5+XaoTZDt9Ahpq//U2oFWQIDAQAB\n"
|
||||
"MA0GCSqGSIb3DQEBCwUAA4IBAQAXWHf/MG8RPCyA0rC3RwxmM70ndyKPIJoL4ggU\n"
|
||||
"VgkN66BdpsE4UlWdlp0XL3aauMPxzLn9rq1yRtoHWT4/ucL9iEa6B295JBNjkgW+\n"
|
||||
"ct9/y8060P9BUhY1DTv5DLzitsA4bjRaraIevjATDPfsbHFx9DTNrS5pXHIFbRcz\n"
|
||||
"y3WniYXTKhpfM6m+1X8ogImE968DG8RqAW5YZZtrZW0VF/dhlQp20jEX/8Rv33Bp\n"
|
||||
"RhNEIhPnYAquKCesMMclUtPW+5n2z8rgj5t/ETv4wc5QegpyPfdHNq09bGKB10Sy\n"
|
||||
"sGvC6hP9GKU3R2Jhxih/t88O3WoisFQ8+Tf9s2LuSxUV0bzp");
|
||||
*privkey_data = strdup("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");
|
||||
*privkey_type = NC_SSH_KEY_RSA;
|
||||
return 0;
|
||||
} else if (!strcmp(name, "main_cert")) {
|
||||
*cert_path = strdup(TESTS_DIR "/data/server.crt");
|
||||
*privkey_path = strdup(TESTS_DIR "/data/server.key");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
clb_trusted_cert_lists(const char *name, void *UNUSED(user_data), char ***cert_paths, int *cert_path_count,
|
||||
char ***cert_data, int *cert_data_count)
|
||||
{
|
||||
if (!strcmp(name, "trusted_cert_list1")) {
|
||||
*cert_data = malloc(sizeof **cert_data);
|
||||
(*cert_data)[0] = strdup("MIIDnDCCAoSgAwIBAgIJAIjf7UNx4uabMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV\n"
|
||||
"BAYTAkNaMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQHDARCcm5vMQ8wDQYD\n"
|
||||
"VQQKDAZDRVNORVQxDDAKBgNVBAsMA1RNQzERMA8GA1UEAwwIc2VydmVyY2EwHhcN\n"
|
||||
"MTgxMTA1MDcyNjM5WhcNMjgxMTAyMDcyNjM5WjBjMQswCQYDVQQGEwJDWjETMBEG\n"
|
||||
"A1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwEQnJubzEPMA0GA1UECgwGQ0VTTkVU\n"
|
||||
"MQwwCgYDVQQLDANUTUMxETAPBgNVBAMMCHNlcnZlcmNhMIIBIjANBgkqhkiG9w0B\n"
|
||||
"AQEFAAOCAQ8AMIIBCgKCAQEAyMrKraqraFGklO2itRIEWxfuzWo1IwxZ22aJmeXD\n"
|
||||
"Leomt6893NXelMLaC3swQ+hu49JjiIY81DXvbVgmIgLm7cAz5tHTHuJbfdI4Q6gy\n"
|
||||
"ic4aOpy2s3s1/vYz+1TvEUFCiPXEsJrH72he/z9nBxL8vY6Eg8U8EG8NvKp9zyCK\n"
|
||||
"A7vmNSgQOtuyF18fesYHAnvQjNXO5q6diPXdHOr2bjTRUvARGbWlv4Rvf81RwUkR\n"
|
||||
"sWoF/0pglV/TxnW2MoHnn3apxb/kmH92CQ+GWKxq5SkhvbkYePlA87kgKnDtXl4w\n"
|
||||
"EXIhYwM51kafRhhlAKN+qYeV9teBqGpjsZRYesrh3mXHlQIDAQABo1MwUTAdBgNV\n"
|
||||
"HQ4EFgQU60nJ4q3ItcfaOOBjJSqadAPiMg8wHwYDVR0jBBgwFoAU60nJ4q3Itcfa\n"
|
||||
"OOBjJSqadAPiMg8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA\n"
|
||||
"xIqIQ5SCXnKslZfrXiAEbB5dglxVOSa8me5a/70uHK/27JZ6veeIgRqZ4VgPHnBC\n"
|
||||
"a3m6EHr+mnTjjqSUcGIUiKV3g2Dumw8paqZC+Qv+Ib/NKquS1lO2Ry1wHBtXzn5K\n"
|
||||
"KHHyM1bWMDaDszirw2+pp22VdRrPZNA9NWXheEDYOLyQekyL2CfidhxhaXvUZyWg\n"
|
||||
"alLyF2XRZ5/jAT+NjfWw39EmWPUGk13Jm83OaFc1VdrXNCiD0sGCQ+BTCllDinQv\n"
|
||||
"R08yzd4fzA3YXthvX1dBu1SvqQAGOS7gssRCyv9uWI6MXta25X91eY1ZMz1euJ04\n"
|
||||
"mB8EdyYiZc0kzrb9dv5d0g==");
|
||||
*cert_data_count = 1;
|
||||
return 0;
|
||||
} else if (!strcmp(name, "client_cert_list")) {
|
||||
*cert_paths = malloc(sizeof **cert_paths);
|
||||
(*cert_paths)[0] = strdup(TESTS_DIR "/data/client.crt");
|
||||
*cert_path_count = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
endpt_set_address_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_endpt_set_address("quaternary", "0.0.0.0");
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
endpt_set_port_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_endpt_set_port("quaternary", 6003);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_set_server_cert_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_tls_endpt_set_server_cert("quaternary", "server_cert1");
|
||||
nc_assert(!ret);
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_add_trusted_cert_list_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_tls_endpt_add_trusted_cert_list("quaternary", "trusted_cert_list1");
|
||||
nc_assert(!ret);
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_set_trusted_ca_paths_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_tls_endpt_set_trusted_ca_paths("quaternary", TESTS_DIR "/data/serverca.pem", "data");
|
||||
nc_assert(!ret);
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_del_trusted_cert_list_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
nc_server_tls_endpt_del_trusted_cert_list("quaternary", "trusted_cert_list1");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_set_crl_paths_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_tls_endpt_set_crl_paths("quaternary", NULL, "data");
|
||||
nc_assert(!ret);
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_clear_crls_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
nc_server_tls_endpt_clear_crls("quaternary");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_add_ctn_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_tls_endpt_add_ctn("main_tls", 2, "02:F0:F1:F2:F3:F4:F5:F6:F7:F8:F9:10:11:12:EE:FF:A0:A1:A2:A3",
|
||||
NC_TLS_CTN_SAN_IP_ADDRESS, NULL);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_endpt_del_ctn_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ret;
|
||||
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
ret = nc_server_tls_endpt_del_ctn("main_tls", -1, NULL, NC_TLS_CTN_SAN_ANY, NULL);
|
||||
nc_assert(!ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
tls_client_thread(void *arg)
|
||||
{
|
||||
int ret, read_pipe = *(int *)arg;
|
||||
char buf[9];
|
||||
struct nc_session *session;
|
||||
|
||||
fprintf(stdout, "TLS client start.\n");
|
||||
|
||||
ret = read(read_pipe, buf, 9);
|
||||
nc_assert(ret == 9);
|
||||
nc_assert(!strncmp(buf, "tls_ready", 9));
|
||||
|
||||
ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
|
||||
nc_assert(!ret);
|
||||
ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
|
||||
nc_assert(!ret);
|
||||
|
||||
session = nc_connect_tls("127.0.0.1", 6501, NULL);
|
||||
nc_assert(session);
|
||||
|
||||
/* verify some capabilities */
|
||||
nc_assert(nc_session_cpblt(session, "urn:jmu:params:xml:ns:yang:module-a?module=module-a&deviations=module-a-dv,module-a-dv2"));
|
||||
|
||||
nc_session_free(session, NULL);
|
||||
|
||||
fprintf(stdout, "TLS client finished.\n");
|
||||
|
||||
nc_thread_destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* NC_ENABLED_TLS */
|
||||
|
||||
static void *(*thread_funcs[])(void *) = {
|
||||
#if defined (NC_ENABLED_SSH) || defined (NC_ENABLED_TLS)
|
||||
server_thread,
|
||||
#endif
|
||||
#ifdef NC_ENABLED_SSH
|
||||
add_endpt_thread,
|
||||
del_endpt_thread,
|
||||
ssh_endpt_set_hostkey_thread,
|
||||
ssh_endpt_set_auth_methods_thread,
|
||||
ssh_endpt_set_auth_attempts_thread,
|
||||
ssh_endpt_set_auth_timeout_thread,
|
||||
ssh_endpt_add_authkey_thread,
|
||||
ssh_endpt_del_authkey_thread,
|
||||
#endif
|
||||
#ifdef NC_ENABLED_TLS
|
||||
endpt_set_address_thread,
|
||||
endpt_set_port_thread,
|
||||
tls_endpt_set_server_cert_thread,
|
||||
tls_endpt_add_trusted_cert_list_thread,
|
||||
tls_endpt_set_trusted_ca_paths_thread,
|
||||
tls_endpt_del_trusted_cert_list_thread,
|
||||
tls_endpt_set_crl_paths_thread,
|
||||
tls_endpt_clear_crls_thread,
|
||||
tls_endpt_add_ctn_thread,
|
||||
tls_endpt_del_ctn_thread,
|
||||
#endif
|
||||
};
|
||||
|
||||
const int thread_count = sizeof thread_funcs / sizeof *thread_funcs;
|
||||
|
||||
#if defined (NC_ENABLED_SSH) && defined (NC_ENABLED_TLS)
|
||||
const int client_count = 2;
|
||||
pid_t pids[2];
|
||||
int pipes[4];
|
||||
#else
|
||||
const int client_count = 1;
|
||||
pid_t pids[1];
|
||||
int pipes[2];
|
||||
#endif
|
||||
|
||||
static void
|
||||
client_fork(void)
|
||||
{
|
||||
int ret, clients = 0;
|
||||
|
||||
#ifdef NC_ENABLED_SSH
|
||||
nc_assert(pipe(pipes + clients * 2) == 0);
|
||||
|
||||
if (!(pids[clients] = fork())) {
|
||||
nc_client_init();
|
||||
|
||||
ret = nc_client_set_schema_searchpath(TESTS_DIR "/data/modules");
|
||||
nc_assert(!ret);
|
||||
|
||||
/* close write */
|
||||
close(pipes[clients * 2 + 1]);
|
||||
ssh_client_thread(&pipes[clients * 2]);
|
||||
close(pipes[clients * 2]);
|
||||
nc_client_destroy();
|
||||
exit(0);
|
||||
}
|
||||
/* close read */
|
||||
close(pipes[clients * 2]);
|
||||
|
||||
++clients;
|
||||
#endif
|
||||
|
||||
#ifdef NC_ENABLED_TLS
|
||||
nc_assert(pipe(pipes + clients * 2) == 0);
|
||||
|
||||
if (!(pids[clients] = fork())) {
|
||||
nc_client_init();
|
||||
|
||||
ret = nc_client_set_schema_searchpath(TESTS_DIR "/data/modules");
|
||||
nc_assert(!ret);
|
||||
|
||||
/* close write */
|
||||
close(pipes[clients * 2 + 1]);
|
||||
tls_client_thread(&pipes[clients * 2]);
|
||||
close(pipes[clients * 2]);
|
||||
nc_client_destroy();
|
||||
exit(0);
|
||||
}
|
||||
/* close read */
|
||||
close(pipes[clients * 2]);
|
||||
|
||||
++clients;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
#if _POSIX_BARRIERS >= 200112L
|
||||
struct ly_ctx *ctx;
|
||||
int ret, i, clients = 0;
|
||||
pthread_t tids[thread_count];
|
||||
|
||||
nc_verbosity(NC_VERB_VERBOSE);
|
||||
|
||||
client_fork();
|
||||
|
||||
ly_ctx_new(TESTS_DIR "/data/modules", 0, &ctx);
|
||||
nc_assert(ctx);
|
||||
ly_ctx_load_module(ctx, "ietf-netconf", NULL, NULL);
|
||||
|
||||
/* load some application models with deviations */
|
||||
nc_assert(ly_ctx_load_module(ctx, "module-a", NULL, NULL));
|
||||
nc_assert(ly_ctx_load_module(ctx, "module-a-dv", NULL, NULL));
|
||||
nc_assert(ly_ctx_load_module(ctx, "module-a-dv2", NULL, NULL));
|
||||
|
||||
nc_server_init(ctx);
|
||||
|
||||
pthread_barrier_init(&barrier, NULL, thread_count);
|
||||
|
||||
#ifdef NC_ENABLED_SSH
|
||||
/* set callback */
|
||||
nc_server_ssh_set_hostkey_clb(clb_hostkeys, NULL, NULL);
|
||||
|
||||
/* do first, so that client can connect on SSH */
|
||||
ret = nc_server_add_endpt("main_ssh", NC_TI_LIBSSH);
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_endpt_set_address("main_ssh", "0.0.0.0");
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_endpt_set_port("main_ssh", 6001);
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_ssh_add_authkey_path(TESTS_DIR "/data/key_ecdsa.pub", "test");
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_ssh_endpt_add_hostkey("main_ssh", "key_rsa", -1);
|
||||
nc_assert(!ret);
|
||||
|
||||
/* client ready */
|
||||
ret = write(pipes[clients * 2 + 1], "ssh_ready", 9);
|
||||
nc_assert(ret == 9);
|
||||
++clients;
|
||||
|
||||
/* for ssh_endpt_del_authkey */
|
||||
ret = nc_server_ssh_add_authkey_path(TESTS_DIR "/data/key_dsa.pub", "test2");
|
||||
nc_assert(!ret);
|
||||
|
||||
ret = nc_server_add_endpt("secondary", NC_TI_LIBSSH);
|
||||
nc_assert(!ret);
|
||||
#endif
|
||||
|
||||
#ifdef NC_ENABLED_TLS
|
||||
/* set callbacks */
|
||||
nc_server_tls_set_server_cert_clb(clb_server_cert, NULL, NULL);
|
||||
nc_server_tls_set_trusted_cert_list_clb(clb_trusted_cert_lists, NULL, NULL);
|
||||
|
||||
/* do first, so that client can connect on TLS */
|
||||
ret = nc_server_add_endpt("main_tls", NC_TI_OPENSSL);
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_endpt_set_address("main_tls", "0.0.0.0");
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_endpt_set_port("main_tls", 6501);
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_tls_endpt_set_server_cert("main_tls", "main_cert");
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_tls_endpt_add_trusted_cert_list("main_tls", "client_cert_list");
|
||||
nc_assert(!ret);
|
||||
ret = nc_server_tls_endpt_add_ctn("main_tls", 0, "02:B3:9F:26:65:76:6B:CC:FC:86:8E:D4:1A:81:64:0F:92:EB:18:AE:FF", NC_TLS_CTN_SPECIFIED, "test");
|
||||
nc_assert(!ret);
|
||||
|
||||
/* client ready */
|
||||
ret = write(pipes[clients * 2 + 1], "tls_ready", 9);
|
||||
nc_assert(ret == 9);
|
||||
++clients;
|
||||
|
||||
/* for tls_endpt_del_ctn */
|
||||
ret = nc_server_tls_endpt_add_ctn("main_tls", 1, "02:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:A0:A1:A2:A3", NC_TLS_CTN_SAN_ANY, NULL);
|
||||
nc_assert(!ret);
|
||||
|
||||
ret = nc_server_add_endpt("quaternary", NC_TI_OPENSSL);
|
||||
nc_assert(!ret);
|
||||
#endif
|
||||
|
||||
/* threads'n'stuff */
|
||||
ret = 0;
|
||||
for (i = 0; i < thread_count; ++i) {
|
||||
ret += pthread_create(&tids[i], NULL, thread_funcs[i], NULL);
|
||||
}
|
||||
nc_assert(!ret);
|
||||
|
||||
/* cleanup */
|
||||
for (i = 0; i < thread_count; ++i) {
|
||||
pthread_join(tids[i], NULL);
|
||||
}
|
||||
for (i = 0; i < client_count; ++i) {
|
||||
waitpid(pids[i], NULL, 0);
|
||||
close(pipes[i * 2 + 1]);
|
||||
}
|
||||
|
||||
pthread_barrier_destroy(&barrier);
|
||||
|
||||
nc_server_destroy();
|
||||
ly_ctx_destroy(ctx);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
15
tests/test_server_thread.supp
Normal file
15
tests/test_server_thread.supp
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
<custom_func_global_variables_check>
|
||||
Helgrind:Race
|
||||
fun:CRYPTO_malloc
|
||||
}
|
||||
{
|
||||
<global_variable_always_set_with_default_method_when_getting>
|
||||
Helgrind:Race
|
||||
fun:DSA_get_default_method
|
||||
}
|
||||
{
|
||||
<helgrind_ignores_rwlocks>
|
||||
Helgrind:Race
|
||||
fun:nc_server_endpt_set_address_port
|
||||
}
|
189
tests/test_thread_messages.c
Normal file
189
tests/test_thread_messages.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
* \file test_thread_messages
|
||||
* \author Tadeas Vintrlik <xvint04@stud.fit.vutbr.cz>
|
||||
* \brief libnetconf2 tests - thread-safety for receiving messages
|
||||
*
|
||||
* Copyright 2021 Deutsche Telekom AG.
|
||||
* Copyright 2021 CESNET, z.s.p.o.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
#include <log.h>
|
||||
#include <messages_p.h>
|
||||
#include <messages_server.h>
|
||||
#include <session_client.h>
|
||||
#include <session_server.h>
|
||||
#include "tests/config.h"
|
||||
|
||||
/* millisec */
|
||||
#define NC_ACCEPT_TIMEOUT 5000
|
||||
/* millisec */
|
||||
#define NC_PS_POLL_TIMEOUT 5000
|
||||
/* sec */
|
||||
#define CLIENT_SSH_AUTH_TIMEOUT 10
|
||||
|
||||
#define nc_assert(cond) if (!(cond)) { fprintf(stderr, "assert failed (%s:%d)\n", __FILE__, __LINE__); exit(1); }
|
||||
|
||||
#if _POSIX_BARRIERS >= 200112L
|
||||
pthread_barrier_t barrier;
|
||||
pthread_barrier_t barrier_msg;
|
||||
#endif
|
||||
|
||||
typedef struct arg {
|
||||
int in;
|
||||
int out;
|
||||
struct ly_ctx *ctx;
|
||||
} arg_t;
|
||||
|
||||
struct nc_server_reply *
|
||||
rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
||||
{
|
||||
(void)rpc; (void)session;
|
||||
return nc_server_reply_ok();
|
||||
}
|
||||
|
||||
static void *
|
||||
server_thread(void *arg)
|
||||
{
|
||||
struct nc_session *sess;
|
||||
struct nc_server_notif *notif;
|
||||
struct lyd_node *ntf;
|
||||
struct ly_in *in;
|
||||
struct nc_pollsession *ps;
|
||||
arg_t args = *(arg_t *)arg;
|
||||
char *eventtime;
|
||||
struct timespec ts;
|
||||
const char *data;
|
||||
int poll;
|
||||
|
||||
nc_assert(!nc_server_init(args.ctx));
|
||||
nc_assert(nc_accept_inout(args.in, args.out, "test", &sess) == NC_MSG_HELLO);
|
||||
nc_session_inc_notif_status(sess);
|
||||
data =
|
||||
"<n1 xmlns=\"n1\">\n"
|
||||
" <first>Test</first>\n"
|
||||
"</n1>\n";
|
||||
|
||||
nc_assert(ly_in_new_memory(data, &in) == LY_SUCCESS);
|
||||
nc_assert(lyd_parse_op(args.ctx, NULL, in, LYD_XML, LYD_TYPE_NOTIF_YANG, &ntf, NULL) == LY_SUCCESS);
|
||||
ly_in_free(in, 0);
|
||||
|
||||
nc_assert(clock_gettime(CLOCK_REALTIME, &ts) != -1);
|
||||
nc_assert(ly_time_ts2str(&ts, &eventtime) == LY_SUCCESS);
|
||||
notif = nc_server_notif_new(ntf, eventtime, NC_PARAMTYPE_FREE);
|
||||
|
||||
ps = nc_ps_new();
|
||||
nc_assert(ps);
|
||||
nc_ps_add_session(ps, sess);
|
||||
poll = nc_ps_poll(ps, 1000, &sess);
|
||||
nc_server_notif_send(sess, notif, 1000);
|
||||
nc_assert(poll == NC_PSPOLL_RPC);
|
||||
nc_ps_clear(ps, 1, NULL);
|
||||
nc_ps_free(ps);
|
||||
|
||||
/* Waiting for end of test */
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
nc_server_notif_free(notif);
|
||||
return arg;
|
||||
}
|
||||
|
||||
static void *
|
||||
notif_thread(void *arg)
|
||||
{
|
||||
struct nc_session *sess = (struct nc_session *)arg;
|
||||
struct lyd_node *envp;
|
||||
struct lyd_node *op;
|
||||
NC_MSG_TYPE msgtype;
|
||||
|
||||
/* Sync threads for receiving message to increase chance of datarace */
|
||||
pthread_barrier_wait(&barrier_msg);
|
||||
do {
|
||||
msgtype = nc_recv_notif(sess, 1000, &envp, &op);
|
||||
} while (msgtype == NC_MSG_REPLY);
|
||||
nc_assert(msgtype == NC_MSG_NOTIF);
|
||||
lyd_free_tree(envp);
|
||||
lyd_free_tree(op);
|
||||
return arg;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int pipes[4];
|
||||
struct nc_session *sess;
|
||||
struct lyd_node *op, *envp;
|
||||
struct ly_ctx *ctx;
|
||||
struct nc_rpc *rpc;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE msgtype;
|
||||
const char *features[] = {"startup", NULL};
|
||||
arg_t thread_arg;
|
||||
pthread_t t[2];
|
||||
|
||||
pthread_barrier_init(&barrier, NULL, 2);
|
||||
pthread_barrier_init(&barrier_msg, NULL, 2);
|
||||
|
||||
/* Create a two pipes */
|
||||
nc_assert(pipe(pipes) != -1);
|
||||
nc_assert(pipe(pipes + 2) != -1);
|
||||
thread_arg.in = pipes[0];
|
||||
thread_arg.out = pipes[3];
|
||||
|
||||
/* Create context */
|
||||
nc_assert(ly_ctx_new(TESTS_DIR "/data/modules", 0, &ctx) == LY_SUCCESS);
|
||||
nc_assert(ly_ctx_load_module(ctx, "ietf-netconf", NULL, features));
|
||||
nc_assert(ly_ctx_load_module(ctx, "notif1", NULL, NULL));
|
||||
thread_arg.ctx = ctx;
|
||||
nc_set_global_rpc_clb(rpc_clb);
|
||||
|
||||
/* Start server thread */
|
||||
pthread_create(&t[0], NULL, server_thread, &thread_arg);
|
||||
nc_client_init();
|
||||
|
||||
/* Listen for notifications */
|
||||
sess = nc_connect_inout(pipes[2], pipes[1], ctx);
|
||||
nc_assert(sess);
|
||||
pthread_create(&t[1], NULL, notif_thread, sess);
|
||||
|
||||
/* Send rpc */
|
||||
rpc = nc_rpc_delete(NC_DATASTORE_STARTUP, NULL, NC_PARAMTYPE_CONST);
|
||||
nc_assert(nc_send_rpc(sess, rpc, 1000, &msgid) == NC_MSG_RPC);
|
||||
|
||||
/* Sync threads for receiving message to increase chance of datarace */
|
||||
pthread_barrier_wait(&barrier_msg);
|
||||
do {
|
||||
msgtype = nc_recv_reply(sess, rpc, msgid, 1000, &envp, &op);
|
||||
} while (msgtype == NC_MSG_NOTIF);
|
||||
nc_assert(msgtype == NC_MSG_REPLY);
|
||||
nc_rpc_free(rpc);
|
||||
lyd_free_tree(envp);
|
||||
|
||||
/* Waiting of end of test */
|
||||
pthread_barrier_wait(&barrier);
|
||||
pthread_join(t[0], NULL);
|
||||
pthread_join(t[1], NULL);
|
||||
|
||||
/* Cleanup */
|
||||
nc_session_free(sess, NULL);
|
||||
ly_ctx_destroy(ctx);
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
close(pipes[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue