blob: 7bde6c325c58f3c47eec5b99f91f50529b6f3731 [file] [log] [blame]
Michal Vasko294d4c62016-02-01 10:10:27 +01001/**
Michal Vasko7227f352016-02-01 12:11:40 +01002 * \file test_fd_comm.c
Michal Vasko294d4c62016-02-01 10:10:27 +01003 * \author Michal Vasko <mvasko@cesnet.cz>
Michal Vasko7227f352016-02-01 12:11:40 +01004 * \brief libnetconf2 tests - file descriptor basic RPC communication
Michal Vasko294d4c62016-02-01 10:10:27 +01005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vaskoad1cc6a2016-02-26 15:06:06 +010011 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010012 * https://opensource.org/licenses/BSD-3-Clause
Michal Vasko294d4c62016-02-01 10:10:27 +010013 */
14
15#include <errno.h>
16#include <fcntl.h>
17#include <pthread.h>
18#include <setjmp.h>
19#include <stdarg.h>
20#include <stddef.h>
21#include <stdint.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28
29#include <cmocka.h>
30#include <libyang/libyang.h>
31
32#include <session_client.h>
33#include <session_server.h>
34#include <session_p.h>
35#include <messages_p.h>
36#include "config.h"
37
38struct nc_session *server_session;
39struct nc_session *client_session;
Michal Vasko8c5518b2016-03-01 12:35:13 +010040struct ly_ctx *ctx;
Michal Vasko294d4c62016-02-01 10:10:27 +010041
42struct nc_server_reply *
43my_get_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
44{
45 assert_string_equal(rpc->schema->name, "get");
46 assert_ptr_equal(session, server_session);
47
48 return nc_server_reply_ok();
49}
50
51struct nc_server_reply *
52my_getconfig_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
53{
54 struct lyd_node *data;
Michal Vasko294d4c62016-02-01 10:10:27 +010055
56 assert_string_equal(rpc->schema->name, "get-config");
57 assert_ptr_equal(session, server_session);
58
Radek Krejci539efb62016-08-24 15:05:16 +020059 data = lyd_new_path(NULL, session->ctx, "/ietf-netconf:get-config/data", NULL, LYD_ANYDATA_CONSTSTRING,
60 LYD_PATH_OPT_OUTPUT);
Michal Vasko294d4c62016-02-01 10:10:27 +010061 assert_non_null(data);
62
Radek Krejci36dfdb32016-09-01 16:56:35 +020063 return nc_server_reply_data(data, NC_WD_EXPLICIT, NC_PARAMTYPE_FREE);
Michal Vasko294d4c62016-02-01 10:10:27 +010064}
65
66static int
67setup_sessions(void **state)
68{
69 (void)state;
Michal Vasko294d4c62016-02-01 10:10:27 +010070 int sock[2];
71
Michal Vasko294d4c62016-02-01 10:10:27 +010072 /* create communication channel */
73 socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
74
Michal Vasko294d4c62016-02-01 10:10:27 +010075 /* create server session */
76 server_session = calloc(1, sizeof *server_session);
77 server_session->status = NC_STATUS_RUNNING;
78 server_session->side = NC_SERVER;
79 server_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +010080 server_session->ti_type = NC_TI_FD;
81 server_session->ti_lock = malloc(sizeof *server_session->ti_lock);
82 pthread_mutex_init(server_session->ti_lock, NULL);
Michal Vaskoade892d2017-02-22 13:40:35 +010083 server_session->ti_cond = malloc(sizeof *server_session->ti_cond);
84 pthread_cond_init(server_session->ti_cond, NULL);
85 server_session->ti_inuse = malloc(sizeof *server_session->ti_inuse);
86 *server_session->ti_inuse = 0;
Michal Vasko294d4c62016-02-01 10:10:27 +010087 server_session->ti.fd.in = sock[0];
88 server_session->ti.fd.out = sock[0];
89 server_session->ctx = ctx;
90 server_session->flags = NC_SESSION_SHAREDCTX;
91
92 /* create client session */
93 client_session = calloc(1, sizeof *server_session);
94 client_session->status = NC_STATUS_RUNNING;
95 client_session->side = NC_CLIENT;
96 client_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +010097 client_session->ti_type = NC_TI_FD;
98 client_session->ti_lock = malloc(sizeof *client_session->ti_lock);
99 pthread_mutex_init(client_session->ti_lock, NULL);
Michal Vaskoade892d2017-02-22 13:40:35 +0100100 client_session->ti_cond = malloc(sizeof *client_session->ti_cond);
101 pthread_cond_init(client_session->ti_cond, NULL);
102 client_session->ti_inuse = malloc(sizeof *client_session->ti_inuse);
103 *client_session->ti_inuse = 0;
Michal Vasko294d4c62016-02-01 10:10:27 +0100104 client_session->ti.fd.in = sock[1];
105 client_session->ti.fd.out = sock[1];
106 client_session->ctx = ctx;
107 client_session->flags = NC_SESSION_SHAREDCTX;
Michal Vasko338f8472016-10-13 15:01:27 +0200108 client_session->opts.client.msgid = 50;
Michal Vasko294d4c62016-02-01 10:10:27 +0100109
110 return 0;
111}
112
113static int
114teardown_sessions(void **state)
115{
116 (void)state;
117
Michal Vasko294d4c62016-02-01 10:10:27 +0100118 close(server_session->ti.fd.in);
119 pthread_mutex_destroy(server_session->ti_lock);
Michal Vaskoade892d2017-02-22 13:40:35 +0100120 pthread_cond_destroy(server_session->ti_cond);
Michal Vasko294d4c62016-02-01 10:10:27 +0100121 free(server_session->ti_lock);
Michal Vaskoade892d2017-02-22 13:40:35 +0100122 free(server_session->ti_cond);
123 free((int *)server_session->ti_inuse);
Michal Vasko294d4c62016-02-01 10:10:27 +0100124 free(server_session);
125
126 close(client_session->ti.fd.in);
127 pthread_mutex_destroy(client_session->ti_lock);
Michal Vaskoade892d2017-02-22 13:40:35 +0100128 pthread_cond_destroy(client_session->ti_cond);
Michal Vasko294d4c62016-02-01 10:10:27 +0100129 free(client_session->ti_lock);
Michal Vaskoade892d2017-02-22 13:40:35 +0100130 free(client_session->ti_cond);
131 free((int *)client_session->ti_inuse);
Michal Vasko294d4c62016-02-01 10:10:27 +0100132 free(client_session);
133
134 return 0;
135}
136
137static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100138test_send_recv_ok(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100139{
Michal Vasko294d4c62016-02-01 10:10:27 +0100140 int ret;
141 uint64_t msgid;
142 NC_MSG_TYPE msgtype;
143 struct nc_rpc *rpc;
144 struct nc_reply *reply;
145 struct nc_pollsession *ps;
146
147 /* client RPC */
148 rpc = nc_rpc_get(NULL, 0, 0);
149 assert_non_null(rpc);
150
151 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
152 assert_int_equal(msgtype, NC_MSG_RPC);
153
154 /* server RPC, send reply */
155 ps = nc_ps_new();
156 assert_non_null(ps);
157 nc_ps_add_session(ps, server_session);
158
Michal Vasko71090fc2016-05-24 16:37:28 +0200159 ret = nc_ps_poll(ps, 0, NULL);
160 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100161
162 /* server finished */
163 nc_ps_free(ps);
164
165 /* client reply */
Michal Vaskoeb7080e2016-02-18 13:27:05 +0100166 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, 0, &reply);
Michal Vasko294d4c62016-02-01 10:10:27 +0100167 assert_int_equal(msgtype, NC_MSG_REPLY);
168
169 nc_rpc_free(rpc);
170 assert_int_equal(reply->type, NC_RPL_OK);
171 nc_reply_free(reply);
172}
173
174static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100175test_send_recv_ok_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100176{
177 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100178
179 server_session->version = NC_VERSION_10;
180 client_session->version = NC_VERSION_10;
181
182 test_send_recv_ok();
183}
184
185static void
186test_send_recv_ok_11(void **state)
187{
188 (void)state;
189
190 server_session->version = NC_VERSION_11;
191 client_session->version = NC_VERSION_11;
192
193 test_send_recv_ok();
194}
195
196static void
197test_send_recv_error(void)
198{
Michal Vasko294d4c62016-02-01 10:10:27 +0100199 int ret;
200 uint64_t msgid;
201 NC_MSG_TYPE msgtype;
202 struct nc_rpc *rpc;
203 struct nc_reply *reply;
204 struct nc_pollsession *ps;
205
206 /* client RPC */
207 rpc = nc_rpc_kill(1);
208 assert_non_null(rpc);
209
210 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
211 assert_int_equal(msgtype, NC_MSG_RPC);
212
213 /* server RPC, send reply */
214 ps = nc_ps_new();
215 assert_non_null(ps);
216 nc_ps_add_session(ps, server_session);
217
Michal Vasko71090fc2016-05-24 16:37:28 +0200218 ret = nc_ps_poll(ps, 0, NULL);
219 assert_int_equal(ret, NC_PSPOLL_RPC | NC_PSPOLL_REPLY_ERROR);
Michal Vasko294d4c62016-02-01 10:10:27 +0100220
221 /* server finished */
222 nc_ps_free(ps);
223
224 /* client reply */
Michal Vaskoeb7080e2016-02-18 13:27:05 +0100225 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, 0, &reply);
Michal Vasko294d4c62016-02-01 10:10:27 +0100226 assert_int_equal(msgtype, NC_MSG_REPLY);
227
228 nc_rpc_free(rpc);
229 assert_int_equal(reply->type, NC_RPL_ERROR);
230 assert_string_equal(((struct nc_reply_error *)reply)->err->tag, "operation-not-supported");
231 nc_reply_free(reply);
232}
233
234static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100235test_send_recv_error_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100236{
237 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100238
239 server_session->version = NC_VERSION_10;
240 client_session->version = NC_VERSION_10;
241
242 test_send_recv_error();
243}
244
245static void
246test_send_recv_error_11(void **state)
247{
248 (void)state;
249
250 server_session->version = NC_VERSION_11;
251 client_session->version = NC_VERSION_11;
252
253 test_send_recv_error();
254}
255
256static void
257test_send_recv_data(void)
258{
Michal Vasko294d4c62016-02-01 10:10:27 +0100259 int ret;
260 uint64_t msgid;
261 NC_MSG_TYPE msgtype;
262 struct nc_rpc *rpc;
263 struct nc_reply *reply;
264 struct nc_pollsession *ps;
265
266 /* client RPC */
267 rpc = nc_rpc_getconfig(NC_DATASTORE_RUNNING, NULL, 0, 0);
268 assert_non_null(rpc);
269
270 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
271 assert_int_equal(msgtype, NC_MSG_RPC);
272
273 /* server RPC, send reply */
274 ps = nc_ps_new();
275 assert_non_null(ps);
276 nc_ps_add_session(ps, server_session);
277
Michal Vasko71090fc2016-05-24 16:37:28 +0200278 ret = nc_ps_poll(ps, 0, NULL);
279 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100280
281 /* server finished */
282 nc_ps_free(ps);
283
284 /* client reply */
Radek Krejci8c8e1242016-09-07 16:43:54 +0200285 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, 0, &reply);
Michal Vasko294d4c62016-02-01 10:10:27 +0100286 assert_int_equal(msgtype, NC_MSG_REPLY);
287
288 nc_rpc_free(rpc);
289 assert_int_equal(reply->type, NC_RPL_DATA);
290 nc_reply_free(reply);
291}
292
Michal Vasko58d152f2016-02-01 11:44:49 +0100293static void
294test_send_recv_data_10(void **state)
295{
296 (void)state;
297
298 server_session->version = NC_VERSION_10;
299 client_session->version = NC_VERSION_10;
300
301 test_send_recv_data();
302}
303
304static void
305test_send_recv_data_11(void **state)
306{
307 (void)state;
308
309 server_session->version = NC_VERSION_11;
310 client_session->version = NC_VERSION_11;
311
312 test_send_recv_data();
313}
314
Michal Vasko294d4c62016-02-01 10:10:27 +0100315/* TODO
316static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100317test_send_recv_notif(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100318{
319
320}*/
321
322int
323main(void)
324{
Michal Vasko8c5518b2016-03-01 12:35:13 +0100325 int ret;
326 const struct lys_module *module;
Michal Vasko88639e92017-08-03 14:38:10 +0200327 const struct lys_node *node;
Michal Vasko8c5518b2016-03-01 12:35:13 +0100328
329 /* create ctx */
Radek Krejci3222b7d2017-09-21 16:04:30 +0200330 ctx = ly_ctx_new(TESTS_DIR"../schemas", 0);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100331 assert_non_null(ctx);
332
333 /* load modules */
334 module = ly_ctx_load_module(ctx, "ietf-netconf-acm", NULL);
335 assert_non_null(module);
336
337 module = ly_ctx_load_module(ctx, "ietf-netconf", NULL);
338 assert_non_null(module);
339
340 /* set RPC callbacks */
Michal Vasko88639e92017-08-03 14:38:10 +0200341 node = ly_ctx_get_node(module->ctx, NULL, "/ietf-netconf:get", 0);
342 assert_non_null(node);
343 lys_set_private(node, my_get_rpc_clb);
344
345 node = ly_ctx_get_node(module->ctx, NULL, "/ietf-netconf:get-config", 0);
346 assert_non_null(node);
347 lys_set_private(node, my_getconfig_rpc_clb);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100348
349 nc_server_init(ctx);
350
Michal Vasko294d4c62016-02-01 10:10:27 +0100351 const struct CMUnitTest comm[] = {
Michal Vasko58d152f2016-02-01 11:44:49 +0100352 cmocka_unit_test_setup_teardown(test_send_recv_ok_10, setup_sessions, teardown_sessions),
353 cmocka_unit_test_setup_teardown(test_send_recv_error_10, setup_sessions, teardown_sessions),
354 cmocka_unit_test_setup_teardown(test_send_recv_data_10, setup_sessions, teardown_sessions),
355 cmocka_unit_test_setup_teardown(test_send_recv_ok_11, setup_sessions, teardown_sessions),
356 cmocka_unit_test_setup_teardown(test_send_recv_error_11, setup_sessions, teardown_sessions),
357 cmocka_unit_test_setup_teardown(test_send_recv_data_11, setup_sessions, teardown_sessions)
Michal Vasko294d4c62016-02-01 10:10:27 +0100358 };
359
Michal Vasko8c5518b2016-03-01 12:35:13 +0100360 ret = cmocka_run_group_tests(comm, NULL, NULL);
361
362 nc_server_destroy();
363 ly_ctx_destroy(ctx, NULL);
364
365 return ret;
Michal Vasko294d4c62016-02-01 10:10:27 +0100366}