blob: c2eb74682335998c38b038af538ef9671cccbf26 [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 Vasko58791da2024-02-26 13:52:59 +010064 lyd_new_path(NULL, session->ctx, "/ietf-netconf:get-config/data", NULL, LYD_NEW_VAL_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;
Michal Vaskocf898172024-01-15 15:04:28 +010095 struct timespec ts;
Michal Vasko131120a2018-05-29 15:44:02 +020096
97 sess = calloc(1, sizeof *sess);
98 if (!sess) {
99 return NULL;
100 }
101
102 sess->side = side;
103
104 if (side == NC_SERVER) {
Michal Vaskocf898172024-01-15 15:04:28 +0100105 pthread_mutex_init(&sess->opts.server.ntf_status_lock, NULL);
Michal Vaskoacf98472021-02-04 15:33:57 +0100106 pthread_mutex_init(&sess->opts.server.rpc_lock, NULL);
107 pthread_cond_init(&sess->opts.server.rpc_cond, NULL);
108 sess->opts.server.rpc_inuse = 0;
Michal Vaskocf898172024-01-15 15:04:28 +0100109
110 nc_timeouttime_get(&ts, 0);
111 sess->opts.server.last_rpc = ts.tv_sec;
Michal Vasko131120a2018-05-29 15:44:02 +0200112 }
113
114 sess->io_lock = malloc(sizeof *sess->io_lock);
115 if (!sess->io_lock) {
116 goto error;
117 }
118 pthread_mutex_init(sess->io_lock, NULL);
119
120 return sess;
121
122error:
Michal Vasko131120a2018-05-29 15:44:02 +0200123 free(sess);
124 return NULL;
125}
126
Michal Vasko294d4c62016-02-01 10:10:27 +0100127static int
128setup_sessions(void **state)
129{
130 (void)state;
Michal Vasko294d4c62016-02-01 10:10:27 +0100131 int sock[2];
132
Michal Vasko294d4c62016-02-01 10:10:27 +0100133 /* create communication channel */
134 socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
135
Michal Vasko294d4c62016-02-01 10:10:27 +0100136 /* create server session */
Michal Vasko131120a2018-05-29 15:44:02 +0200137 server_session = test_new_session(NC_SERVER);
Michal Vasko294d4c62016-02-01 10:10:27 +0100138 server_session->status = NC_STATUS_RUNNING;
Michal Vasko294d4c62016-02-01 10:10:27 +0100139 server_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +0100140 server_session->ti_type = NC_TI_FD;
Michal Vasko294d4c62016-02-01 10:10:27 +0100141 server_session->ti.fd.in = sock[0];
142 server_session->ti.fd.out = sock[0];
143 server_session->ctx = ctx;
144 server_session->flags = NC_SESSION_SHAREDCTX;
145
146 /* create client session */
Michal Vasko131120a2018-05-29 15:44:02 +0200147 client_session = test_new_session(NC_CLIENT);
Michal Vasko294d4c62016-02-01 10:10:27 +0100148 client_session->status = NC_STATUS_RUNNING;
Michal Vasko294d4c62016-02-01 10:10:27 +0100149 client_session->id = 1;
Michal Vasko294d4c62016-02-01 10:10:27 +0100150 client_session->ti_type = NC_TI_FD;
Michal Vasko294d4c62016-02-01 10:10:27 +0100151 client_session->ti.fd.in = sock[1];
152 client_session->ti.fd.out = sock[1];
153 client_session->ctx = ctx;
154 client_session->flags = NC_SESSION_SHAREDCTX;
Michal Vasko338f8472016-10-13 15:01:27 +0200155 client_session->opts.client.msgid = 50;
Michal Vasko294d4c62016-02-01 10:10:27 +0100156
157 return 0;
158}
159
160static int
161teardown_sessions(void **state)
162{
163 (void)state;
164
Michal Vasko294d4c62016-02-01 10:10:27 +0100165 close(server_session->ti.fd.in);
Michal Vasko77367452021-02-16 16:32:18 +0100166 server_session->ti.fd.in = -1;
Michal Vasko131120a2018-05-29 15:44:02 +0200167 nc_session_free(server_session, NULL);
Michal Vasko294d4c62016-02-01 10:10:27 +0100168
169 close(client_session->ti.fd.in);
Michal Vasko77367452021-02-16 16:32:18 +0100170 client_session->ti.fd.in = -1;
Michal Vasko131120a2018-05-29 15:44:02 +0200171 nc_session_free(client_session, NULL);
Michal Vasko294d4c62016-02-01 10:10:27 +0100172
173 return 0;
174}
175
176static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100177test_send_recv_ok(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100178{
Michal Vasko294d4c62016-02-01 10:10:27 +0100179 int ret;
180 uint64_t msgid;
181 NC_MSG_TYPE msgtype;
182 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100183 struct lyd_node *envp, *op;
Michal Vasko294d4c62016-02-01 10:10:27 +0100184 struct nc_pollsession *ps;
185
186 /* client RPC */
187 rpc = nc_rpc_get(NULL, 0, 0);
188 assert_non_null(rpc);
189
190 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
191 assert_int_equal(msgtype, NC_MSG_RPC);
192
193 /* server RPC, send reply */
194 ps = nc_ps_new();
195 assert_non_null(ps);
196 nc_ps_add_session(ps, server_session);
197
Michal Vasko71090fc2016-05-24 16:37:28 +0200198 ret = nc_ps_poll(ps, 0, NULL);
199 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100200
201 /* server finished */
202 nc_ps_free(ps);
203
204 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100205 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100206 assert_int_equal(msgtype, NC_MSG_REPLY);
207
208 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100209 assert_null(op);
210 assert_string_equal(LYD_NAME(lyd_child(envp)), "ok");
211 lyd_free_tree(envp);
Michal Vasko294d4c62016-02-01 10:10:27 +0100212}
213
214static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100215test_send_recv_ok_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100216{
217 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100218
219 server_session->version = NC_VERSION_10;
220 client_session->version = NC_VERSION_10;
221
222 test_send_recv_ok();
223}
224
225static void
226test_send_recv_ok_11(void **state)
227{
228 (void)state;
229
230 server_session->version = NC_VERSION_11;
231 client_session->version = NC_VERSION_11;
232
233 test_send_recv_ok();
234}
235
236static void
237test_send_recv_error(void)
238{
Michal Vasko294d4c62016-02-01 10:10:27 +0100239 int ret;
240 uint64_t msgid;
241 NC_MSG_TYPE msgtype;
242 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100243 struct lyd_node *envp, *op, *node;
Michal Vasko294d4c62016-02-01 10:10:27 +0100244 struct nc_pollsession *ps;
245
246 /* client RPC */
247 rpc = nc_rpc_kill(1);
248 assert_non_null(rpc);
249
250 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
251 assert_int_equal(msgtype, NC_MSG_RPC);
252
253 /* server RPC, send reply */
254 ps = nc_ps_new();
255 assert_non_null(ps);
256 nc_ps_add_session(ps, server_session);
257
Michal Vasko71090fc2016-05-24 16:37:28 +0200258 ret = nc_ps_poll(ps, 0, NULL);
259 assert_int_equal(ret, NC_PSPOLL_RPC | NC_PSPOLL_REPLY_ERROR);
Michal Vasko294d4c62016-02-01 10:10:27 +0100260
261 /* server finished */
262 nc_ps_free(ps);
263
264 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100265 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100266 assert_int_equal(msgtype, NC_MSG_REPLY);
267
268 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100269 assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
270 lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
271 assert_non_null(node);
272 assert_string_equal(((struct lyd_node_opaq *)node)->value, "operation-not-supported");
273 lyd_free_tree(envp);
274 assert_null(op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100275}
276
277static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100278test_send_recv_error_10(void **state)
Michal Vasko294d4c62016-02-01 10:10:27 +0100279{
280 (void)state;
Michal Vasko58d152f2016-02-01 11:44:49 +0100281
282 server_session->version = NC_VERSION_10;
283 client_session->version = NC_VERSION_10;
284
285 test_send_recv_error();
286}
287
288static void
289test_send_recv_error_11(void **state)
290{
291 (void)state;
292
293 server_session->version = NC_VERSION_11;
294 client_session->version = NC_VERSION_11;
295
296 test_send_recv_error();
297}
298
299static void
300test_send_recv_data(void)
301{
Michal Vasko294d4c62016-02-01 10:10:27 +0100302 int ret;
303 uint64_t msgid;
304 NC_MSG_TYPE msgtype;
305 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100306 struct lyd_node *envp, *op;
Michal Vasko294d4c62016-02-01 10:10:27 +0100307 struct nc_pollsession *ps;
308
309 /* client RPC */
310 rpc = nc_rpc_getconfig(NC_DATASTORE_RUNNING, NULL, 0, 0);
311 assert_non_null(rpc);
312
313 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
314 assert_int_equal(msgtype, NC_MSG_RPC);
315
316 /* server RPC, send reply */
317 ps = nc_ps_new();
318 assert_non_null(ps);
319 nc_ps_add_session(ps, server_session);
320
Michal Vasko71090fc2016-05-24 16:37:28 +0200321 ret = nc_ps_poll(ps, 0, NULL);
322 assert_int_equal(ret, NC_PSPOLL_RPC);
Michal Vasko294d4c62016-02-01 10:10:27 +0100323
324 /* server finished */
325 nc_ps_free(ps);
326
327 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100328 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100329 assert_int_equal(msgtype, NC_MSG_REPLY);
330
331 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100332 assert_non_null(envp);
333 lyd_free_tree(envp);
334 assert_non_null(op);
335 lyd_free_tree(op);
Michal Vasko294d4c62016-02-01 10:10:27 +0100336}
337
Michal Vasko58d152f2016-02-01 11:44:49 +0100338static void
339test_send_recv_data_10(void **state)
340{
341 (void)state;
342
343 server_session->version = NC_VERSION_10;
344 client_session->version = NC_VERSION_10;
345
346 test_send_recv_data();
347}
348
349static void
350test_send_recv_data_11(void **state)
351{
352 (void)state;
353
354 server_session->version = NC_VERSION_11;
355 client_session->version = NC_VERSION_11;
356
357 test_send_recv_data();
358}
359
Michal Vasko131120a2018-05-29 15:44:02 +0200360static void *
361server_send_notif_thread(void *arg)
362{
363 NC_MSG_TYPE msg_type;
364 struct lyd_node *notif_tree;
365 struct nc_server_notif *notif;
Michal Vasko49eb3f42021-05-19 10:20:57 +0200366 struct timespec ts;
Michal Vasko131120a2018-05-29 15:44:02 +0200367 char *buf;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200368
Michal Vasko131120a2018-05-29 15:44:02 +0200369 (void)arg;
370
371 /* wait for the RPC callback to be called */
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100372 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200373 while (glob_state != 1) {
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100374 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200375 usleep(1000);
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100376 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200377 }
378
379 /* create notif */
Michal Vasko77367452021-02-16 16:32:18 +0100380 lyd_new_path(NULL, ctx, "/nc-notifications:notificationComplete", NULL, 0, &notif_tree);
Michal Vasko131120a2018-05-29 15:44:02 +0200381 assert_non_null(notif_tree);
Michal Vasko49eb3f42021-05-19 10:20:57 +0200382 clock_gettime(CLOCK_REALTIME, &ts);
Michal Vaskod7fb6df2021-05-19 11:27:35 +0200383 ly_time_ts2str(&ts, &buf);
384 notif = nc_server_notif_new(notif_tree, buf, NC_PARAMTYPE_FREE);
Michal Vasko131120a2018-05-29 15:44:02 +0200385 assert_non_null(notif);
386
387 /* send notif */
Michal Vasko71dbd772021-03-23 14:08:37 +0100388 nc_session_inc_notif_status(server_session);
Michal Vasko131120a2018-05-29 15:44:02 +0200389 msg_type = nc_server_notif_send(server_session, notif, 100);
390 nc_server_notif_free(notif);
391 assert_int_equal(msg_type, NC_MSG_NOTIF);
392
393 /* update state */
394 glob_state = 2;
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200395 pthread_barrier_wait(&barrier);
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100396 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200397
398 return NULL;
399}
400
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200401static void *
402thread_recv_notif(void *arg)
403{
404 struct nc_session *session = (struct nc_session *)arg;
405 struct lyd_node *envp;
406 struct lyd_node *op;
407 NC_MSG_TYPE msgtype;
408
409 pthread_barrier_wait(&barrier);
410 msgtype = nc_recv_notif(session, 1000, &envp, &op);
411 assert_int_equal(msgtype, NC_MSG_NOTIF);
412 assert_string_equal(op->schema->name, "notificationComplete");
413
414 lyd_free_tree(envp);
415 lyd_free_tree(op);
416
417 pthread_mutex_lock(&state_lock);
418 glob_state = 3;
419 pthread_mutex_unlock(&state_lock);
420
421 return (void *)0;
422}
423
Michal Vasko294d4c62016-02-01 10:10:27 +0100424static void
Michal Vasko58d152f2016-02-01 11:44:49 +0100425test_send_recv_notif(void)
Michal Vasko294d4c62016-02-01 10:10:27 +0100426{
Michal Vasko131120a2018-05-29 15:44:02 +0200427 int ret;
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200428 pthread_t tid[2];
Michal Vasko131120a2018-05-29 15:44:02 +0200429 uint64_t msgid;
430 NC_MSG_TYPE msgtype;
431 struct nc_rpc *rpc;
Michal Vasko77367452021-02-16 16:32:18 +0100432 struct lyd_node *envp, *op;
Michal Vasko131120a2018-05-29 15:44:02 +0200433 struct nc_pollsession *ps;
Michal Vasko294d4c62016-02-01 10:10:27 +0100434
Michal Vasko131120a2018-05-29 15:44:02 +0200435 /* client RPC */
436 rpc = nc_rpc_commit(0, 0, NULL, NULL, 0);
437 assert_non_null(rpc);
438
439 msgtype = nc_send_rpc(client_session, rpc, 0, &msgid);
440 assert_int_equal(msgtype, NC_MSG_RPC);
441
442 /* client subscription */
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200443 pthread_create(&tid[0], NULL, thread_recv_notif, client_session);
Michal Vasko131120a2018-05-29 15:44:02 +0200444
445 /* create server */
446 ps = nc_ps_new();
447 assert_non_null(ps);
448 nc_ps_add_session(ps, server_session);
449
450 /* server will send a notification */
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100451 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200452 glob_state = 0;
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100453 pthread_mutex_unlock(&state_lock);
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200454 ret = pthread_create(&tid[1], NULL, server_send_notif_thread, NULL);
Michal Vasko131120a2018-05-29 15:44:02 +0200455 assert_int_equal(ret, 0);
456
457 /* server blocked on RPC */
458 ret = nc_ps_poll(ps, 0, NULL);
459 assert_int_equal(ret, NC_PSPOLL_RPC);
460
461 /* RPC, notification finished fine */
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100462 pthread_mutex_lock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200463 assert_int_equal(glob_state, 3);
Michal Vaskobbaa9b22019-03-14 12:35:43 +0100464 pthread_mutex_unlock(&state_lock);
Michal Vasko131120a2018-05-29 15:44:02 +0200465
466 /* server finished */
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200467 ret = 0;
468 ret |= pthread_join(tid[0], NULL);
469 ret |= pthread_join(tid[1], NULL);
Michal Vasko131120a2018-05-29 15:44:02 +0200470 assert_int_equal(ret, 0);
471 nc_ps_free(ps);
472
473 /* client reply */
Michal Vasko77367452021-02-16 16:32:18 +0100474 msgtype = nc_recv_reply(client_session, rpc, msgid, 0, &envp, &op);
Michal Vasko131120a2018-05-29 15:44:02 +0200475 assert_int_equal(msgtype, NC_MSG_REPLY);
Michal Vasko131120a2018-05-29 15:44:02 +0200476 nc_rpc_free(rpc);
Michal Vasko77367452021-02-16 16:32:18 +0100477
478 assert_string_equal(LYD_NAME(lyd_child(envp)), "ok");
479 lyd_free_tree(envp);
480 assert_null(op);
Michal Vasko131120a2018-05-29 15:44:02 +0200481}
482
483static void
484test_send_recv_notif_10(void **state)
485{
486 (void)state;
487
488 server_session->version = NC_VERSION_10;
489 client_session->version = NC_VERSION_10;
490
491 test_send_recv_notif();
492}
493
494static void
495test_send_recv_notif_11(void **state)
496{
497 (void)state;
498
499 server_session->version = NC_VERSION_11;
500 client_session->version = NC_VERSION_11;
501
502 test_send_recv_notif();
503}
Michal Vasko294d4c62016-02-01 10:10:27 +0100504
Michal Vasko77e83572022-07-21 15:31:15 +0200505static void
506test_send_recv_malformed_10(void **state)
507{
508 int ret;
509 struct nc_pollsession *ps;
510 struct nc_rpc *rpc;
511 struct lyd_node *envp, *op, *node;
512 NC_MSG_TYPE msgtype;
513 const char *msg;
514
515 (void)state;
516
517 server_session->version = NC_VERSION_10;
518 client_session->version = NC_VERSION_10;
519
520 /* write malformed message */
521 msg =
522 "<nc:rpc xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
523 " <nc:commit/>"
524 "</nc:rpc>"
525 "]]>]]>";
526 assert_int_equal(write(client_session->ti.fd.out, msg, strlen(msg)), strlen(msg));
527 rpc = nc_rpc_commit(0, 0, NULL, NULL, 0);
528 assert_non_null(rpc);
529
530 /* server RPC, send reply */
531 ps = nc_ps_new();
532 assert_non_null(ps);
533 nc_ps_add_session(ps, server_session);
534
535 ret = nc_ps_poll(ps, 0, NULL);
Michal Vaskof8fba542023-10-23 12:03:50 +0200536 assert_int_equal(ret, NC_PSPOLL_BAD_RPC | NC_PSPOLL_REPLY_ERROR);
Michal Vasko77e83572022-07-21 15:31:15 +0200537
538 /* server finished */
539 nc_ps_free(ps);
540
541 /* client reply */
542 msgtype = nc_recv_reply(client_session, rpc, 0, 0, &envp, &op);
543 assert_int_equal(msgtype, NC_MSG_REPLY_ERR_MSGID);
544
545 nc_rpc_free(rpc);
546 assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
547 lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
548 assert_non_null(node);
549 assert_string_equal(((struct lyd_node_opaq *)node)->value, "missing-attribute");
550 lyd_free_tree(envp);
551 assert_null(op);
552}
553
Michal Vasko294d4c62016-02-01 10:10:27 +0100554int
555main(void)
556{
Michal Vasko8c5518b2016-03-01 12:35:13 +0100557 int ret;
558 const struct lys_module *module;
Michal Vasko77367452021-02-16 16:32:18 +0100559 struct lysc_node *node;
560 const char *nc_features[] = {"candidate", NULL};
Michal Vasko8c5518b2016-03-01 12:35:13 +0100561
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200562 pthread_barrier_init(&barrier, NULL, 2);
563
Michal Vasko8c5518b2016-03-01 12:35:13 +0100564 /* create ctx */
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200565 ly_ctx_new(TESTS_DIR "/data/modules", 0, &ctx);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100566 assert_non_null(ctx);
567
568 /* load modules */
Michal Vasko77367452021-02-16 16:32:18 +0100569 module = ly_ctx_load_module(ctx, "ietf-netconf-acm", NULL, NULL);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100570 assert_non_null(module);
571
Michal Vasko77367452021-02-16 16:32:18 +0100572 module = ly_ctx_load_module(ctx, "ietf-netconf", NULL, nc_features);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100573 assert_non_null(module);
Michal Vasko131120a2018-05-29 15:44:02 +0200574
Michal Vasko77367452021-02-16 16:32:18 +0100575 module = ly_ctx_load_module(ctx, "nc-notifications", NULL, NULL);
Michal Vasko131120a2018-05-29 15:44:02 +0200576 assert_non_null(module);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100577
578 /* set RPC callbacks */
Michal Vasko77367452021-02-16 16:32:18 +0100579 node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:get", 0);
Michal Vasko88639e92017-08-03 14:38:10 +0200580 assert_non_null(node);
Michal Vasko77367452021-02-16 16:32:18 +0100581 node->priv = my_get_rpc_clb;
Michal Vasko88639e92017-08-03 14:38:10 +0200582
Michal Vasko77367452021-02-16 16:32:18 +0100583 node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:get-config", 0);
Michal Vasko88639e92017-08-03 14:38:10 +0200584 assert_non_null(node);
Michal Vasko77367452021-02-16 16:32:18 +0100585 node->priv = my_getconfig_rpc_clb;
Michal Vasko8c5518b2016-03-01 12:35:13 +0100586
Michal Vasko77367452021-02-16 16:32:18 +0100587 node = (struct lysc_node *)lys_find_path(module->ctx, NULL, "/ietf-netconf:commit", 0);
Michal Vasko131120a2018-05-29 15:44:02 +0200588 assert_non_null(node);
Michal Vasko77367452021-02-16 16:32:18 +0100589 node->priv = my_commit_rpc_clb;
Michal Vasko131120a2018-05-29 15:44:02 +0200590
Michal Vasko93224072021-11-09 12:14:28 +0100591 nc_server_init();
Michal Vasko8c5518b2016-03-01 12:35:13 +0100592
Michal Vasko294d4c62016-02-01 10:10:27 +0100593 const struct CMUnitTest comm[] = {
Michal Vasko58d152f2016-02-01 11:44:49 +0100594 cmocka_unit_test_setup_teardown(test_send_recv_ok_10, setup_sessions, teardown_sessions),
595 cmocka_unit_test_setup_teardown(test_send_recv_error_10, setup_sessions, teardown_sessions),
596 cmocka_unit_test_setup_teardown(test_send_recv_data_10, setup_sessions, teardown_sessions),
Michal Vasko131120a2018-05-29 15:44:02 +0200597 cmocka_unit_test_setup_teardown(test_send_recv_notif_10, setup_sessions, teardown_sessions),
Michal Vasko77e83572022-07-21 15:31:15 +0200598 cmocka_unit_test_setup_teardown(test_send_recv_malformed_10, setup_sessions, teardown_sessions),
Michal Vasko58d152f2016-02-01 11:44:49 +0100599 cmocka_unit_test_setup_teardown(test_send_recv_ok_11, setup_sessions, teardown_sessions),
600 cmocka_unit_test_setup_teardown(test_send_recv_error_11, setup_sessions, teardown_sessions),
Michal Vasko131120a2018-05-29 15:44:02 +0200601 cmocka_unit_test_setup_teardown(test_send_recv_data_11, setup_sessions, teardown_sessions),
602 cmocka_unit_test_setup_teardown(test_send_recv_notif_11, setup_sessions, teardown_sessions),
Michal Vasko294d4c62016-02-01 10:10:27 +0100603 };
604
Michal Vasko8c5518b2016-03-01 12:35:13 +0100605 ret = cmocka_run_group_tests(comm, NULL, NULL);
606
607 nc_server_destroy();
Michal Vasko1dcb7642021-04-14 15:28:23 +0200608 ly_ctx_destroy(ctx);
tadeas-vintrlik2e803db2021-08-25 12:12:07 +0200609 pthread_barrier_destroy(&barrier);
Michal Vasko8c5518b2016-03-01 12:35:13 +0100610
611 return ret;
Michal Vasko294d4c62016-02-01 10:10:27 +0100612}