blob: e4ff738e4e1e44901f4f03cee79c1f481247384b [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);
83 server_session->ti.fd.in = sock[0];
84 server_session->ti.fd.out = sock[0];
85 server_session->ctx = ctx;
86 server_session->flags = NC_SESSION_SHAREDCTX;
87
88 /* create client session */
89 client_session = calloc(1, sizeof *server_session);
90 client_session->status = NC_STATUS_RUNNING;
91 client_session->side = NC_CLIENT;
92 client_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +010093 client_session->ti_type = NC_TI_FD;
94 client_session->ti_lock = malloc(sizeof *client_session->ti_lock);
95 pthread_mutex_init(client_session->ti_lock, NULL);
96 client_session->ti.fd.in = sock[1];
97 client_session->ti.fd.out = sock[1];
98 client_session->ctx = ctx;
99 client_session->flags = NC_SESSION_SHAREDCTX;
Michal Vasko338f8472016-10-13 15:01:27 +0200100 client_session->opts.client.msgid = 50;
Michal Vasko294d4c62016-02-01 10:10:27 +0100101
102 return 0;
103}
104
105static int
106teardown_sessions(void **state)
107{
108 (void)state;
109
Michal Vasko294d4c62016-02-01 10:10:27 +0100110 close(server_session->ti.fd.in);
111 pthread_mutex_destroy(server_session->ti_lock);
112 free(server_session->ti_lock);
113 free(server_session);
114
115 close(client_session->ti.fd.in);
116 pthread_mutex_destroy(client_session->ti_lock);
117 free(client_session->ti_lock);
118 free(client_session);
119
120 return 0;
121}
122
123static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100124test_send_recv_ok(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100125{
Michal Vasko294d4c62016-02-01 10:10:27 +0100126 int ret;
127 uint64_t msgid;
128 NC_MSG_TYPE msgtype;
129 struct nc_rpc *rpc;
130 struct nc_reply *reply;
131 struct nc_pollsession *ps;
132
133 /* client RPC */
134 rpc = nc_rpc_get(NULL, 0, 0);
135 assert_non_null(rpc);
136
137 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
138 assert_int_equal(msgtype, NC_MSG_RPC);
139
140 /* server RPC, send reply */
141 ps = nc_ps_new();
142 assert_non_null(ps);
143 nc_ps_add_session(ps, server_session);
144
Michal Vasko71090fc2016-05-24 16:37:28 +0200145 ret = nc_ps_poll(ps, 0, NULL);
146 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100147
148 /* server finished */
149 nc_ps_free(ps);
150
151 /* client reply */
Michal Vaskoeb7080e2016-02-18 13:27:05 +0100152 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, 0, &reply);
Michal Vasko294d4c62016-02-01 10:10:27 +0100153 assert_int_equal(msgtype, NC_MSG_REPLY);
154
155 nc_rpc_free(rpc);
156 assert_int_equal(reply->type, NC_RPL_OK);
157 nc_reply_free(reply);
158}
159
160static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100161test_send_recv_ok_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100162{
163 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100164
165 server_session->version = NC_VERSION_10;
166 client_session->version = NC_VERSION_10;
167
168 test_send_recv_ok();
169}
170
171static void
172test_send_recv_ok_11(void **state)
173{
174 (void)state;
175
176 server_session->version = NC_VERSION_11;
177 client_session->version = NC_VERSION_11;
178
179 test_send_recv_ok();
180}
181
182static void
183test_send_recv_error(void)
184{
Michal Vasko294d4c62016-02-01 10:10:27 +0100185 int ret;
186 uint64_t msgid;
187 NC_MSG_TYPE msgtype;
188 struct nc_rpc *rpc;
189 struct nc_reply *reply;
190 struct nc_pollsession *ps;
191
192 /* client RPC */
193 rpc = nc_rpc_kill(1);
194 assert_non_null(rpc);
195
196 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
197 assert_int_equal(msgtype, NC_MSG_RPC);
198
199 /* server RPC, send reply */
200 ps = nc_ps_new();
201 assert_non_null(ps);
202 nc_ps_add_session(ps, server_session);
203
Michal Vasko71090fc2016-05-24 16:37:28 +0200204 ret = nc_ps_poll(ps, 0, NULL);
205 assert_int_equal(ret, NC_PSPOLL_RPC | NC_PSPOLL_REPLY_ERROR);
Michal Vasko294d4c62016-02-01 10:10:27 +0100206
207 /* server finished */
208 nc_ps_free(ps);
209
210 /* client reply */
Michal Vaskoeb7080e2016-02-18 13:27:05 +0100211 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, 0, &reply);
Michal Vasko294d4c62016-02-01 10:10:27 +0100212 assert_int_equal(msgtype, NC_MSG_REPLY);
213
214 nc_rpc_free(rpc);
215 assert_int_equal(reply->type, NC_RPL_ERROR);
216 assert_string_equal(((struct nc_reply_error *)reply)->err->tag, "operation-not-supported");
217 nc_reply_free(reply);
218}
219
220static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100221test_send_recv_error_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100222{
223 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100224
225 server_session->version = NC_VERSION_10;
226 client_session->version = NC_VERSION_10;
227
228 test_send_recv_error();
229}
230
231static void
232test_send_recv_error_11(void **state)
233{
234 (void)state;
235
236 server_session->version = NC_VERSION_11;
237 client_session->version = NC_VERSION_11;
238
239 test_send_recv_error();
240}
241
242static void
243test_send_recv_data(void)
244{
Michal Vasko294d4c62016-02-01 10:10:27 +0100245 int ret;
246 uint64_t msgid;
247 NC_MSG_TYPE msgtype;
248 struct nc_rpc *rpc;
249 struct nc_reply *reply;
250 struct nc_pollsession *ps;
251
252 /* client RPC */
253 rpc = nc_rpc_getconfig(NC_DATASTORE_RUNNING, NULL, 0, 0);
254 assert_non_null(rpc);
255
256 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
257 assert_int_equal(msgtype, NC_MSG_RPC);
258
259 /* server RPC, send reply */
260 ps = nc_ps_new();
261 assert_non_null(ps);
262 nc_ps_add_session(ps, server_session);
263
Michal Vasko71090fc2016-05-24 16:37:28 +0200264 ret = nc_ps_poll(ps, 0, NULL);
265 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100266
267 /* server finished */
268 nc_ps_free(ps);
269
270 /* client reply */
Radek Krejci8c8e1242016-09-07 16:43:54 +0200271 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, 0, &reply);
Michal Vasko294d4c62016-02-01 10:10:27 +0100272 assert_int_equal(msgtype, NC_MSG_REPLY);
273
274 nc_rpc_free(rpc);
275 assert_int_equal(reply->type, NC_RPL_DATA);
276 nc_reply_free(reply);
277}
278
Michal Vasko58d152f2016-02-01 11:44:49 +0100279static void
280test_send_recv_data_10(void **state)
281{
282 (void)state;
283
284 server_session->version = NC_VERSION_10;
285 client_session->version = NC_VERSION_10;
286
287 test_send_recv_data();
288}
289
290static void
291test_send_recv_data_11(void **state)
292{
293 (void)state;
294
295 server_session->version = NC_VERSION_11;
296 client_session->version = NC_VERSION_11;
297
298 test_send_recv_data();
299}
300
Michal Vasko294d4c62016-02-01 10:10:27 +0100301/* TODO
302static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100303test_send_recv_notif(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100304{
305
306}*/
307
308int
309main(void)
310{
Michal Vasko8c5518b2016-03-01 12:35:13 +0100311 int ret;
312 const struct lys_module *module;
313 const struct lys_node *node;
314
315 /* create ctx */
316 ctx = ly_ctx_new(TESTS_DIR"../schemas");
317 assert_non_null(ctx);
318
319 /* load modules */
320 module = ly_ctx_load_module(ctx, "ietf-netconf-acm", NULL);
321 assert_non_null(module);
322
323 module = ly_ctx_load_module(ctx, "ietf-netconf", NULL);
324 assert_non_null(module);
325
326 /* set RPC callbacks */
Michal Vasko303245c2016-03-24 15:20:03 +0100327 node = ly_ctx_get_node(module->ctx, NULL, "/ietf-netconf:get");
Michal Vasko8c5518b2016-03-01 12:35:13 +0100328 assert_non_null(node);
329 lys_set_private(node, my_get_rpc_clb);
330
Michal Vasko303245c2016-03-24 15:20:03 +0100331 node = ly_ctx_get_node(module->ctx, NULL, "/ietf-netconf:get-config");
Michal Vasko8c5518b2016-03-01 12:35:13 +0100332 assert_non_null(node);
333 lys_set_private(node, my_getconfig_rpc_clb);
334
335 nc_server_init(ctx);
336
Michal Vasko294d4c62016-02-01 10:10:27 +0100337 const struct CMUnitTest comm[] = {
Michal Vasko58d152f2016-02-01 11:44:49 +0100338 cmocka_unit_test_setup_teardown(test_send_recv_ok_10, setup_sessions, teardown_sessions),
339 cmocka_unit_test_setup_teardown(test_send_recv_error_10, setup_sessions, teardown_sessions),
340 cmocka_unit_test_setup_teardown(test_send_recv_data_10, setup_sessions, teardown_sessions),
341 cmocka_unit_test_setup_teardown(test_send_recv_ok_11, setup_sessions, teardown_sessions),
342 cmocka_unit_test_setup_teardown(test_send_recv_error_11, setup_sessions, teardown_sessions),
343 cmocka_unit_test_setup_teardown(test_send_recv_data_11, setup_sessions, teardown_sessions)
Michal Vasko294d4c62016-02-01 10:10:27 +0100344 };
345
Michal Vasko8c5518b2016-03-01 12:35:13 +0100346 ret = cmocka_run_group_tests(comm, NULL, NULL);
347
348 nc_server_destroy();
349 ly_ctx_destroy(ctx, NULL);
350
351 return ret;
Michal Vasko294d4c62016-02-01 10:10:27 +0100352}