/** * \file test_io.c * \author Radek Krejci * \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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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); }