blob: f5448d338098010aef6b83d01e48598a05ab5160 [file] [log] [blame]
/**
* \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);
}