Skip to content

Commit d169f3f

Browse files
committed
test_ch UPDATE add ch thread del while sess
1 parent 7a3b975 commit d169f3f

1 file changed

Lines changed: 182 additions & 4 deletions

File tree

tests/test_ch.c

Lines changed: 182 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@
2929

3030
struct test_ch_data {
3131
struct lyd_node *tree;
32+
pthread_barrier_t *barrier2;
3233
};
3334

3435
char buffer[512];
3536
char expected[512];
3637

37-
int TEST_PORT = 10050, TEST_PORT_2 = 10051;
38-
const char *TEST_PORT_STR = "10050", *TEST_PORT_2_STR = "10051";
38+
int TEST_PORT = 10050, TEST_PORT_2 = 10051, TEST_PORT_3 = 10052, TEST_PORT_4 = 10053;
39+
const char *TEST_PORT_STR = "10050", *TEST_PORT_2_STR = "10051", *TEST_PORT_3_STR = "10052", *TEST_PORT_4_STR = "10053";
3940

4041
static void
4142
test_msg_callback(const struct nc_session *session, NC_VERB_LEVEL level, const char *msg)
@@ -169,6 +170,10 @@ test_nc_ch_free_test_data(void *test_data)
169170

170171
test_ch_data = test_data;
171172
lyd_free_tree(test_ch_data->tree);
173+
if (test_ch_data->barrier2) {
174+
pthread_barrier_destroy(test_ch_data->barrier2);
175+
free(test_ch_data->barrier2);
176+
}
172177
free(test_ch_data);
173178
}
174179

@@ -382,16 +387,189 @@ setup_tls(void **state)
382387
return 0;
383388
}
384389

390+
/*
391+
* Test: Delete CH client while session is established
392+
* Verifies that deleting a CH client from config properly signals the thread to stop,
393+
* even when the session is in RUNNING state.
394+
*/
395+
static int
396+
session_established_flag = 0;
397+
398+
static int
399+
ch_new_session_set_flag_cb(const char *client_name, struct nc_session *new_session, void *user_data)
400+
{
401+
int ret = 0;
402+
struct nc_pollsession *ps = (struct nc_pollsession *)user_data;
403+
404+
(void) client_name;
405+
406+
ret = nc_ps_add_session(ps, new_session);
407+
assert_int_equal(ret, 0);
408+
409+
session_established_flag = 1;
410+
return 0;
411+
}
412+
413+
static void *
414+
server_thread_delete_while_session(void *arg)
415+
{
416+
int ret;
417+
struct nc_pollsession *ps;
418+
struct ln2_test_ctx *test_ctx = arg;
419+
struct test_ch_data *test_data = test_ctx->test_data;
420+
421+
nc_set_print_clb_session(test_msg_callback);
422+
buffer[0] = '\0';
423+
strcpy(expected, "thread exit");
424+
425+
ps = nc_ps_new();
426+
assert_non_null(ps);
427+
428+
pthread_barrier_wait(&test_ctx->barrier);
429+
430+
ret = nc_connect_ch_client_dispatch("ch_delete_test", ch_session_acquire_ctx_cb,
431+
ch_session_release_ctx_cb, test_ctx, ch_new_session_set_flag_cb, ps);
432+
assert_int_equal(ret, 0);
433+
434+
while (!session_established_flag) {
435+
usleep(10000);
436+
}
437+
438+
do {
439+
ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
440+
if (ret & (NC_PSPOLL_TIMEOUT | NC_PSPOLL_NOSESSIONS)) {
441+
usleep(500);
442+
}
443+
} while (ret & NC_PSPOLL_RPC);
444+
445+
ret = nc_server_config_setup_data(test_data->tree);
446+
assert_int_equal(ret, 0);
447+
448+
do {
449+
usleep(5000);
450+
} while (!strlen(buffer));
451+
452+
assert_true(strlen(buffer) > 0);
453+
454+
pthread_barrier_wait(test_data->barrier2);
455+
456+
nc_ps_clear(ps, 1, NULL);
457+
nc_ps_free(ps);
458+
459+
return NULL;
460+
}
461+
462+
static void *
463+
client_thread_delete_while_session(void *arg)
464+
{
465+
int ret;
466+
struct nc_session *session = NULL;
467+
struct ln2_test_ctx *test_ctx = arg;
468+
struct test_ch_data *test_data = test_ctx->test_data;
469+
470+
nc_client_ssh_ch_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
471+
ret = nc_client_set_schema_searchpath(MODULES_DIR);
472+
assert_int_equal(ret, 0);
473+
ret = nc_client_ssh_ch_set_username("test_ch_delete");
474+
assert_int_equal(ret, 0);
475+
ret = nc_client_ssh_ch_add_keypair(TESTS_DIR "/data/id_ed25519.pub", TESTS_DIR "/data/id_ed25519");
476+
assert_int_equal(ret, 0);
477+
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", TEST_PORT_3);
478+
assert_int_equal(ret, 0);
479+
480+
pthread_barrier_wait(&test_ctx->barrier);
481+
482+
ret = nc_accept_callhome(NC_ACCEPT_TIMEOUT, NULL, &session);
483+
assert_int_equal(ret, 1);
484+
485+
/* wait until the server deletes the client */
486+
pthread_barrier_wait(test_data->barrier2);
487+
488+
ret = nc_client_ssh_ch_del_bind("127.0.0.1", TEST_PORT_3);
489+
assert_int_equal(ret, 0);
490+
491+
nc_session_free(session, NULL);
492+
return NULL;
493+
}
494+
495+
static int
496+
setup_delete_while_session(void **state)
497+
{
498+
int ret;
499+
struct lyd_node *tree = NULL;
500+
struct ln2_test_ctx *test_ctx;
501+
struct test_ch_data *test_data;
502+
503+
ret = ln2_glob_test_setup(&test_ctx);
504+
assert_int_equal(ret, 0);
505+
506+
test_data = calloc(1, sizeof *test_data);
507+
assert_non_null(test_data);
508+
test_data->barrier2 = calloc(1, sizeof(pthread_barrier_t));
509+
assert_non_null(test_data->barrier2);
510+
pthread_barrier_init(test_data->barrier2, NULL, 2);
511+
512+
test_ctx->test_data = test_data;
513+
test_ctx->free_test_data = test_nc_ch_free_test_data;
514+
*state = test_ctx;
515+
516+
session_established_flag = 0;
517+
518+
ret = nc_server_config_add_ch_address_port(test_ctx->ctx, "ch_delete_test", "endpt", NC_TI_SSH,
519+
"127.0.0.1", TEST_PORT_3_STR, &tree);
520+
assert_int_equal(ret, 0);
521+
522+
ret = nc_server_config_add_ch_persistent(test_ctx->ctx, "ch_delete_test", &tree);
523+
assert_int_equal(ret, 0);
524+
525+
ret = nc_server_config_add_ch_ssh_hostkey(test_ctx->ctx, "ch_delete_test", "endpt", "hostkey",
526+
TESTS_DIR "/data/key_ecdsa", NULL, &tree);
527+
assert_int_equal(ret, 0);
528+
529+
ret = nc_server_config_add_ch_ssh_user_pubkey(test_ctx->ctx, "ch_delete_test", "endpt", "test_ch_delete",
530+
"pubkey", TESTS_DIR "/data/id_ed25519.pub", &tree);
531+
assert_int_equal(ret, 0);
532+
533+
ret = nc_server_config_setup_data(tree);
534+
assert_int_equal(ret, 0);
535+
536+
ret = nc_server_config_del_ch_client("ch_delete_test", &tree);
537+
assert_int_equal(ret, 0);
538+
539+
test_data->tree = tree;
540+
return 0;
541+
}
542+
543+
static void
544+
test_nc_ch_delete_client_while_session(void **state)
545+
{
546+
int ret, i;
547+
pthread_t tids[2];
548+
549+
assert_non_null(state);
550+
551+
ret = pthread_create(&tids[0], NULL, client_thread_delete_while_session, *state);
552+
assert_int_equal(ret, 0);
553+
554+
ret = pthread_create(&tids[1], NULL, server_thread_delete_while_session, *state);
555+
assert_int_equal(ret, 0);
556+
557+
for (i = 0; i < 2; i++) {
558+
pthread_join(tids[i], NULL);
559+
}
560+
}
561+
385562
int
386563
main(void)
387564
{
388565
const struct CMUnitTest tests[] = {
389566
cmocka_unit_test_setup_teardown(test_nc_ch_ssh, setup_ssh, ln2_glob_test_teardown),
390567
cmocka_unit_test_setup_teardown(test_nc_ch_tls, setup_tls, ln2_glob_test_teardown),
568+
cmocka_unit_test_setup_teardown(test_nc_ch_delete_client_while_session, setup_delete_while_session, ln2_glob_test_teardown),
391569
};
392570

393-
/* try to get ports from the environment, otherwise use the default */
394-
if (ln2_glob_test_get_ports(2, &TEST_PORT, &TEST_PORT_STR, &TEST_PORT_2, &TEST_PORT_2_STR)) {
571+
if (ln2_glob_test_get_ports(4, &TEST_PORT, &TEST_PORT_STR, &TEST_PORT_2, &TEST_PORT_2_STR,
572+
&TEST_PORT_3, &TEST_PORT_3_STR, &TEST_PORT_4, &TEST_PORT_4_STR)) {
395573
return 1;
396574
}
397575

0 commit comments

Comments
 (0)