blob: cd279e29f2c1daa2388896fcbbc4c29058410d65 [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
Michal Vaskoba9f3582023-02-22 10:26:32 +010015#define _GNU_SOURCE
16
Michal Vasko294d4c62016-02-01 10:10:27 +010017#include <errno.h>
18#include <fcntl.h>
19#include <pthread.h>
20#include <setjmp.h>
21#include <stdarg.h>
22#include <stddef.h>
23#include <stdint.h>
24#include <stdlib.h>
Michal Vasko294d4c62016-02-01 10:10:27 +010025#include <string.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020026#include <sys/socket.h>
Michal Vasko294d4c62016-02-01 10:10:27 +010027#include <sys/stat.h>
28#include <sys/types.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020029#include <unistd.h>
Michal Vasko294d4c62016-02-01 10:10:27 +010030
31#include <cmocka.h>
32#include <libyang/libyang.h>
33
Michal Vasko294d4c62016-02-01 10:10:27 +010034#include <messages_p.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020035#include <session_client.h>
36#include <session_p.h>
37#include <session_server.h>
Jan Kundrátcf15d6c2017-10-26 18:07:56 +020038#include "tests/config.h"
Michal Vasko294d4c62016-02-01 10:10:27 +010039
40struct nc_session *server_session;
41struct nc_session *client_session;
Michal Vasko8c5518b2016-03-01 12:35:13 +010042struct ly_ctx *ctx;
Michal Vaskobbaa9b22019-03-14 12:35:43 +010043pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER;
tadeas-vintrlik2e803db2021-08-25 12:12:07 +020044pthread_barrier_t barrier;
Michal Vaskobbaa9b22019-03-14 12:35:43 +010045int glob_state;
Michal Vasko294d4c62016-02-01 10:10:27 +010046
47struct nc_server_reply *
48my_get_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
49{
50 assert_string_equal(rpc->schema->name, "get");
51 assert_ptr_equal(session, server_session);
52
53 return nc_server_reply_ok();
54}
55
56struct nc_server_reply *
57my_getconfig_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
58{
59 struct lyd_node *data;
Michal Vasko294d4c62016-02-01 10:10:27 +010060
61 assert_string_equal(rpc->schema->name, "get-config");
62 assert_ptr_equal(session, server_session);
63
Michal Vasko77367452021-02-16 16:32:18 +010064 lyd_new_path(NULL, session->ctx, "/ietf-netconf:get-config/data", NULL, LYD_NEW_PATH_OUTPUT, &data);
Michal Vasko294d4c62016-02-01 10:10:27 +010065 assert_non_null(data);
66
Radek Krejci36dfdb32016-09-01 16:56:35 +020067 return nc_server_reply_data(data, NC_WD_EXPLICIT, NC_PARAMTYPE_FREE);
Michal Vasko294d4c62016-02-01 10:10:27 +010068}
69
Michal Vasko131120a2018-05-29 15:44:02 +020070struct nc_server_reply *
71my_commit_rpc_clb(struct lyd_node *rpc, struct nc_session *session)
72{
73 assert_string_equal(rpc->schema->name, "commit");
74 assert_ptr_equal(session, server_session);
75
76 /* update state */
Michal Vaskobbaa9b22019-03-14 12:35:43 +010077 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +020078 glob_state = 1;
79
80 /* wait until the client receives the notification */
81 while (glob_state != 3) {
Michal Vaskobbaa9b22019-03-14 12:35:43 +010082 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +020083 usleep(100000);
Michal Vaskobbaa9b22019-03-14 12:35:43 +010084 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +020085 }
Michal Vaskobbaa9b22019-03-14 12:35:43 +010086 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +020087
88 return nc_server_reply_ok();
89}
90
91static struct nc_session *
92test_new_session(NC_SIDE side)
93{
94 struct nc_session *sess;
95
96 sess = calloc(1, sizeof *sess);
97 if (!sess) {
98 return NULL;
99 }
100
101 sess->side = side;
102
103 if (side == NC_SERVER) {
Michal Vaskoacf98472021-02-04 15:33:57 +0100104 pthread_mutex_init(&sess->opts.server.rpc_lock, NULL);
105 pthread_cond_init(&sess->opts.server.rpc_cond, NULL);
106 sess->opts.server.rpc_inuse = 0;
Michal Vasko131120a2018-05-29 15:44:02 +0200107 }
108
109 sess->io_lock = malloc(sizeof *sess->io_lock);
110 if (!sess->io_lock) {
111 goto error;
112 }
113 pthread_mutex_init(sess->io_lock, NULL);
114
115 return sess;
116
117error:
Michal Vasko131120a2018-05-29 15:44:02 +0200118 free(sess);
119 return NULL;
120}
121
Michal Vasko294d4c62016-02-01 10:10:27 +0100122static int
123setup_sessions(void **state)
124{
125 (void)state;
Michal Vasko294d4c62016-02-01 10:10:27 +0100126 int sock[2];
127
Michal Vasko294d4c62016-02-01 10:10:27 +0100128 /* create communication channel */
129 socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
130
Michal Vasko294d4c62016-02-01 10:10:27 +0100131 /* create server session */
Michal Vasko131120a2018-05-29 15:44:02 +0200132 server_session = test_new_session(NC_SERVER);
Michal Vasko294d4c62016-02-01 10:10:27 +0100133 server_session->status = NC_STATUS_RUNNING;
Michal Vasko294d4c62016-02-01 10:10:27 +0100134 server_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +0100135 server_session->ti_type = NC_TI_FD;
Michal Vasko294d4c62016-02-01 10:10:27 +0100136 server_session->ti.fd.in = sock[0];
137 server_session->ti.fd.out = sock[0];
138 server_session->ctx = ctx;
139 server_session->flags = NC_SESSION_SHAREDCTX;
140
141 /* create client session */
Michal Vasko131120a2018-05-29 15:44:02 +0200142 client_session = test_new_session(NC_CLIENT);
Michal Vasko294d4c62016-02-01 10:10:27 +0100143 client_session->status = NC_STATUS_RUNNING;
Michal Vasko294d4c62016-02-01 10:10:27 +0100144 client_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +0100145 client_session->ti_type = NC_TI_FD;
Michal Vasko294d4c62016-02-01 10:10:27 +0100146 client_session->ti.fd.in = sock[1];
147 client_session->ti.fd.out = sock[1];
148 client_session->ctx = ctx;
149 client_session->flags = NC_SESSION_SHAREDCTX;
Michal Vasko338f8472016-10-13 15:01:27 +0200150 client_session->opts.client.msgid = 50;
Michal Vasko294d4c62016-02-01 10:10:27 +0100151
152 return 0;
153}
154
155static int
156teardown_sessions(void **state)
157{
158 (void)state;
159
Michal Vasko294d4c62016-02-01 10:10:27 +0100160 close(server_session->ti.fd.in);
Michal Vasko77367452021-02-16 16:32:18 +0100161 server_session->ti.fd.in = -1;
Michal Vasko131120a2018-05-29 15:44:02 +0200162 nc_session_free(server_session, NULL);
Michal Vasko294d4c62016-02-01 10:10:27 +0100163
164 close(client_session->ti.fd.in);
Michal Vasko77367452021-02-16 16:32:18 +0100165 client_session->ti.fd.in = -1;
Michal Vasko131120a2018-05-29 15:44:02 +0200166 nc_session_free(client_session, NULL);
Michal Vasko294d4c62016-02-01 10:10:27 +0100167
168 return 0;
169}
170
171static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100172test_send_recv_ok(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100173{
Michal Vasko294d4c62016-02-01 10:10:27 +0100174 int ret;
175 uint64_t msgid;
176 NC_MSG_TYPE msgtype;
177 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100178 struct lyd_node *envp, *op;
Michal Vasko294d4c62016-02-01 10:10:27 +0100179 struct nc_pollsession *ps;
180
181 /* client RPC */
182 rpc = nc_rpc_get(NULL, 0, 0);
183 assert_non_null(rpc);
184
185 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
186 assert_int_equal(msgtype, NC_MSG_RPC);
187
188 /* server RPC, send reply */
189 ps = nc_ps_new();
190 assert_non_null(ps);
191 nc_ps_add_session(ps, server_session);
192
Michal Vasko71090fc2016-05-24 16:37:28 +0200193 ret = nc_ps_poll(ps, 0, NULL);
194 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100195
196 /* server finished */
197 nc_ps_free(ps);
198
199 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100200 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100201 assert_int_equal(msgtype, NC_MSG_REPLY);
202
203 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100204 assert_null(op);
205 assert_string_equal(LYD_NAME(lyd_child(envp)), "ok");
206 lyd_free_tree(envp);
Michal Vasko294d4c62016-02-01 10:10:27 +0100207}
208
209static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100210test_send_recv_ok_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100211{
212 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100213
214 server_session->version = NC_VERSION_10;
215 client_session->version = NC_VERSION_10;
216
217 test_send_recv_ok();
218}
219
220static void
221test_send_recv_ok_11(void **state)
222{
223 (void)state;
224
225 server_session->version = NC_VERSION_11;
226 client_session->version = NC_VERSION_11;
227
228 test_send_recv_ok();
229}
230
231static void
232test_send_recv_error(void)
233{
Michal Vasko294d4c62016-02-01 10:10:27 +0100234 int ret;
235 uint64_t msgid;
236 NC_MSG_TYPE msgtype;
237 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100238 struct lyd_node *envp, *op, *node;
Michal Vasko294d4c62016-02-01 10:10:27 +0100239 struct nc_pollsession *ps;
240
241 /* client RPC */
242 rpc = nc_rpc_kill(1);
243 assert_non_null(rpc);
244
245 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
246 assert_int_equal(msgtype, NC_MSG_RPC);
247
248 /* server RPC, send reply */
249 ps = nc_ps_new();
250 assert_non_null(ps);
251 nc_ps_add_session(ps, server_session);
252
Michal Vasko71090fc2016-05-24 16:37:28 +0200253 ret = nc_ps_poll(ps, 0, NULL);
254 assert_int_equal(ret, NC_PSPOLL_RPC | NC_PSPOLL_REPLY_ERROR);
Michal Vasko294d4c62016-02-01 10:10:27 +0100255
256 /* server finished */
257 nc_ps_free(ps);
258
259 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100260 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100261 assert_int_equal(msgtype, NC_MSG_REPLY);
262
263 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100264 assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
265 lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
266 assert_non_null(node);
267 assert_string_equal(((struct lyd_node_opaq *)node)->value, "operation-not-supported");
268 lyd_free_tree(envp);
269 assert_null(op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100270}
271
272static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100273test_send_recv_error_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100274{
275 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100276
277 server_session->version = NC_VERSION_10;
278 client_session->version = NC_VERSION_10;
279
280 test_send_recv_error();
281}
282
283static void
284test_send_recv_error_11(void **state)
285{
286 (void)state;
287
288 server_session->version = NC_VERSION_11;
289 client_session->version = NC_VERSION_11;
290
291 test_send_recv_error();
292}
293
294static void
295test_send_recv_data(void)
296{
Michal Vasko294d4c62016-02-01 10:10:27 +0100297 int ret;
298 uint64_t msgid;
299 NC_MSG_TYPE msgtype;
300 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100301 struct lyd_node *envp, *op;
Michal Vasko294d4c62016-02-01 10:10:27 +0100302 struct nc_pollsession *ps;
303
304 /* client RPC */
305 rpc = nc_rpc_getconfig(NC_DATASTORE_RUNNING, NULL, 0, 0);
306 assert_non_null(rpc);
307
308 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
309 assert_int_equal(msgtype, NC_MSG_RPC);
310
311 /* server RPC, send reply */
312 ps = nc_ps_new();
313 assert_non_null(ps);
314 nc_ps_add_session(ps, server_session);
315
Michal Vasko71090fc2016-05-24 16:37:28 +0200316 ret = nc_ps_poll(ps, 0, NULL);
317 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100318
319 /* server finished */
320 nc_ps_free(ps);
321
322 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100323 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100324 assert_int_equal(msgtype, NC_MSG_REPLY);
325
326 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100327 assert_non_null(envp);
328 lyd_free_tree(envp);
329 assert_non_null(op);
330 lyd_free_tree(op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100331}
332
Michal Vasko58d152f2016-02-01 11:44:49 +0100333static void
334test_send_recv_data_10(void **state)
335{
336 (void)state;
337
338 server_session->version = NC_VERSION_10;
339 client_session->version = NC_VERSION_10;
340
341 test_send_recv_data();
342}
343
344static void
345test_send_recv_data_11(void **state)
346{
347 (void)state;
348
349 server_session->version = NC_VERSION_11;
350 client_session->version = NC_VERSION_11;
351
352 test_send_recv_data();
353}
354
Michal Vasko131120a2018-05-29 15:44:02 +0200355static void *
356server_send_notif_thread(void *arg)
357{
358 NC_MSG_TYPE msg_type;
359 struct lyd_node *notif_tree;
360 struct nc_server_notif *notif;
Michal Vasko49eb3f42021-05-19 10:20:57 +0200361 struct timespec ts;
Michal Vasko131120a2018-05-29 15:44:02 +0200362 char *buf;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200363
Michal Vasko131120a2018-05-29 15:44:02 +0200364 (void)arg;
365
366 /* wait for the RPC callback to be called */
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100367 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200368 while (glob_state != 1) {
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100369 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200370 usleep(1000);
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100371 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200372 }
373
374 /* create notif */
Michal Vasko77367452021-02-16 16:32:18 +0100375 lyd_new_path(NULL, ctx, "/nc-notifications:notificationComplete", NULL, 0, &notif_tree);
Michal Vasko131120a2018-05-29 15:44:02 +0200376 assert_non_null(notif_tree);
Michal Vasko49eb3f42021-05-19 10:20:57 +0200377 clock_gettime(CLOCK_REALTIME, &ts);
Michal Vaskod7fb6df2021-05-19 11:27:35 +0200378 ly_time_ts2str(&ts, &buf);
379 notif = nc_server_notif_new(notif_tree, buf, NC_PARAMTYPE_FREE);
Michal Vasko131120a2018-05-29 15:44:02 +0200380 assert_non_null(notif);
381
382 /* send notif */
Michal Vasko71dbd772021-03-23 14:08:37 +0100383 nc_session_inc_notif_status(server_session);
Michal Vasko131120a2018-05-29 15:44:02 +0200384 msg_type = nc_server_notif_send(server_session, notif, 100);
385 nc_server_notif_free(notif);
386 assert_int_equal(msg_type, NC_MSG_NOTIF);
387
388 /* update state */
389 glob_state = 2;
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200390 pthread_barrier_wait(&barrier);
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100391 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200392
393 return NULL;
394}
395
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200396static void *
397thread_recv_notif(void *arg)
398{
399 struct nc_session *session = (struct nc_session *)arg;
400 struct lyd_node *envp;
401 struct lyd_node *op;
402 NC_MSG_TYPE msgtype;
403
404 pthread_barrier_wait(&barrier);
405 msgtype = nc_recv_notif(session, 1000, &envp, &op);
406 assert_int_equal(msgtype, NC_MSG_NOTIF);
407 assert_string_equal(op->schema->name, "notificationComplete");
408
409 lyd_free_tree(envp);
410 lyd_free_tree(op);
411
412 pthread_mutex_lock(&state_lock);
413 glob_state = 3;
414 pthread_mutex_unlock(&state_lock);
415
416 return (void *)0;
417}
418
Michal Vasko294d4c62016-02-01 10:10:27 +0100419static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100420test_send_recv_notif(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100421{
Michal Vasko131120a2018-05-29 15:44:02 +0200422 int ret;
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200423 pthread_t tid[2];
Michal Vasko131120a2018-05-29 15:44:02 +0200424 uint64_t msgid;
425 NC_MSG_TYPE msgtype;
426 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100427 struct lyd_node *envp, *op;
Michal Vasko131120a2018-05-29 15:44:02 +0200428 struct nc_pollsession *ps;
Michal Vasko294d4c62016-02-01 10:10:27 +0100429
Michal Vasko131120a2018-05-29 15:44:02 +0200430 /* client RPC */
431 rpc = nc_rpc_commit(0, 0, NULL, NULL, 0);
432 assert_non_null(rpc);
433
434 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
435 assert_int_equal(msgtype, NC_MSG_RPC);
436
437 /* client subscription */
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200438 pthread_create(&tid[0], NULL, thread_recv_notif, client_session);
Michal Vasko131120a2018-05-29 15:44:02 +0200439
440 /* create server */
441 ps = nc_ps_new();
442 assert_non_null(ps);
443 nc_ps_add_session(ps, server_session);
444
445 /* server will send a notification */
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100446 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200447 glob_state = 0;
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100448 pthread_mutex_unlock(&state_lock);
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200449 ret = pthread_create(&tid[1], NULL, server_send_notif_thread, NULL);
Michal Vasko131120a2018-05-29 15:44:02 +0200450 assert_int_equal(ret, 0);
451
452 /* server blocked on RPC */
453 ret = nc_ps_poll(ps, 0, NULL);
454 assert_int_equal(ret, NC_PSPOLL_RPC);
455
456 /* RPC, notification finished fine */
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100457 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200458 assert_int_equal(glob_state, 3);
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100459 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200460
461 /* server finished */
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200462 ret = 0;
463 ret |= pthread_join(tid[0], NULL);
464 ret |= pthread_join(tid[1], NULL);
Michal Vasko131120a2018-05-29 15:44:02 +0200465 assert_int_equal(ret, 0);
466 nc_ps_free(ps);
467
468 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100469 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko131120a2018-05-29 15:44:02 +0200470 assert_int_equal(msgtype, NC_MSG_REPLY);
Michal Vasko131120a2018-05-29 15:44:02 +0200471 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100472
473 assert_string_equal(LYD_NAME(lyd_child(envp)), "ok");
474 lyd_free_tree(envp);
475 assert_null(op);
Michal Vasko131120a2018-05-29 15:44:02 +0200476}
477
478static void
479test_send_recv_notif_10(void **state)
480{
481 (void)state;
482
483 server_session->version = NC_VERSION_10;
484 client_session->version = NC_VERSION_10;
485
486 test_send_recv_notif();
487}
488
489static void
490test_send_recv_notif_11(void **state)
491{
492 (void)state;
493
494 server_session->version = NC_VERSION_11;
495 client_session->version = NC_VERSION_11;
496
497 test_send_recv_notif();
498}
Michal Vasko294d4c62016-02-01 10:10:27 +0100499
Michal Vasko77e83572022-07-21 15:31:15 +0200500static void
501test_send_recv_malformed_10(void **state)
502{
503 int ret;
504 struct nc_pollsession *ps;
505 struct nc_rpc *rpc;
506 struct lyd_node *envp, *op, *node;
507 NC_MSG_TYPE msgtype;
508 const char *msg;
509
510 (void)state;
511
512 server_session->version = NC_VERSION_10;
513 client_session->version = NC_VERSION_10;
514
515 /* write malformed message */
516 msg =
517 "<nc:rpc xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
518 " <nc:commit/>"
519 "</nc:rpc>"
520 "]]>]]>";
521 assert_int_equal(write(client_session->ti.fd.out, msg, strlen(msg)), strlen(msg));
522 rpc = nc_rpc_commit(0, 0, NULL, NULL, 0);
523 assert_non_null(rpc);
524
525 /* server RPC, send reply */
526 ps = nc_ps_new();
527 assert_non_null(ps);
528 nc_ps_add_session(ps, server_session);
529
530 ret = nc_ps_poll(ps, 0, NULL);
Michal Vaskof8fba542023-10-23 12:03:50 +0200531 assert_int_equal(ret, NC_PSPOLL_BAD_RPC | NC_PSPOLL_REPLY_ERROR);
Michal Vasko77e83572022-07-21 15:31:15 +0200532
533 /* server finished */
534 nc_ps_free(ps);
535
536 /* client reply */
537 msgtype = nc_recv_reply(client_session, rpc, 0, 0, &envp, &op);
538 assert_int_equal(msgtype, NC_MSG_REPLY_ERR_MSGID);
539
540 nc_rpc_free(rpc);
541 assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
542 lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
543 assert_non_null(node);
544 assert_string_equal(((struct lyd_node_opaq *)node)->value, "missing-attribute");
545 lyd_free_tree(envp);
546 assert_null(op);
547}
548
Michal Vasko294d4c62016-02-01 10:10:27 +0100549int
550main(void)
551{
Michal Vasko8c5518b2016-03-01 12:35:13 +0100552 int ret;
553 const struct lys_module *module;
Michal Vasko77367452021-02-16 16:32:18 +0100554 struct lysc_node *node;
555 const char *nc_features[] = {"candidate", NULL};
Michal Vasko8c5518b2016-03-01 12:35:13 +0100556
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200557 pthread_barrier_init(&barrier, NULL, 2);
558
Michal Vasko8c5518b2016-03-01 12:35:13 +0100559 /* create ctx */
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200560 ly_ctx_new(TESTS_DIR "/data/modules", 0, &ctx);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100561 assert_non_null(ctx);
562
563 /* load modules */
Michal Vasko77367452021-02-16 16:32:18 +0100564 module = ly_ctx_load_module(ctx, "ietf-netconf-acm", NULL, NULL);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100565 assert_non_null(module);
566
Michal Vasko77367452021-02-16 16:32:18 +0100567 module = ly_ctx_load_module(ctx, "ietf-netconf", NULL, nc_features);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100568 assert_non_null(module);
Michal Vasko131120a2018-05-29 15:44:02 +0200569
Michal Vasko77367452021-02-16 16:32:18 +0100570 module = ly_ctx_load_module(ctx, "nc-notifications", NULL, NULL);
Michal Vasko131120a2018-05-29 15:44:02 +0200571 assert_non_null(module);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100572
573 /* set RPC callbacks */
Michal Vasko77367452021-02-16 16:32:18 +0100574 node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:get", 0);
Michal Vasko88639e92017-08-03 14:38:10 +0200575 assert_non_null(node);
Michal Vasko77367452021-02-16 16:32:18 +0100576 node->priv = my_get_rpc_clb;
Michal Vasko88639e92017-08-03 14:38:10 +0200577
Michal Vasko77367452021-02-16 16:32:18 +0100578 node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:get-config", 0);
Michal Vasko88639e92017-08-03 14:38:10 +0200579 assert_non_null(node);
Michal Vasko77367452021-02-16 16:32:18 +0100580 node->priv = my_getconfig_rpc_clb;
Michal Vasko8c5518b2016-03-01 12:35:13 +0100581
Michal Vasko77367452021-02-16 16:32:18 +0100582 node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:commit", 0);
Michal Vasko131120a2018-05-29 15:44:02 +0200583 assert_non_null(node);
Michal Vasko77367452021-02-16 16:32:18 +0100584 node->priv = my_commit_rpc_clb;
Michal Vasko131120a2018-05-29 15:44:02 +0200585
Michal Vasko93224072021-11-09 12:14:28 +0100586 nc_server_init();
Michal Vasko8c5518b2016-03-01 12:35:13 +0100587
Michal Vasko294d4c62016-02-01 10:10:27 +0100588 const struct CMUnitTest comm[] = {
Michal Vasko58d152f2016-02-01 11:44:49 +0100589 cmocka_unit_test_setup_teardown(test_send_recv_ok_10, setup_sessions, teardown_sessions),
590 cmocka_unit_test_setup_teardown(test_send_recv_error_10, setup_sessions, teardown_sessions),
591 cmocka_unit_test_setup_teardown(test_send_recv_data_10, setup_sessions, teardown_sessions),
Michal Vasko131120a2018-05-29 15:44:02 +0200592 cmocka_unit_test_setup_teardown(test_send_recv_notif_10, setup_sessions, teardown_sessions),
Michal Vasko77e83572022-07-21 15:31:15 +0200593 cmocka_unit_test_setup_teardown(test_send_recv_malformed_10, setup_sessions, teardown_sessions),
Michal Vasko58d152f2016-02-01 11:44:49 +0100594 cmocka_unit_test_setup_teardown(test_send_recv_ok_11, setup_sessions, teardown_sessions),
595 cmocka_unit_test_setup_teardown(test_send_recv_error_11, setup_sessions, teardown_sessions),
Michal Vasko131120a2018-05-29 15:44:02 +0200596 cmocka_unit_test_setup_teardown(test_send_recv_data_11, setup_sessions, teardown_sessions),
597 cmocka_unit_test_setup_teardown(test_send_recv_notif_11, setup_sessions, teardown_sessions),
Michal Vasko294d4c62016-02-01 10:10:27 +0100598 };
599
Michal Vasko8c5518b2016-03-01 12:35:13 +0100600 ret = cmocka_run_group_tests(comm, NULL, NULL);
601
602 nc_server_destroy();
Michal Vasko1dcb7642021-04-14 15:28:23 +0200603 ly_ctx_destroy(ctx);
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200604 pthread_barrier_destroy(&barrier);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100605
606 return ret;
Michal Vasko294d4c62016-02-01 10:10:27 +0100607}