diff options
Diffstat (limited to 'src/irmd/reg/tests')
| -rw-r--r-- | src/irmd/reg/tests/CMakeLists.txt | 29 | ||||
| -rw-r--r-- | src/irmd/reg/tests/flow_test.c | 294 | ||||
| -rw-r--r-- | src/irmd/reg/tests/ipcp_test.c | 89 | ||||
| -rw-r--r-- | src/irmd/reg/tests/name_test.c | 283 | ||||
| -rw-r--r-- | src/irmd/reg/tests/proc_test.c | 107 | ||||
| -rw-r--r-- | src/irmd/reg/tests/prog_test.c | 105 | ||||
| -rw-r--r-- | src/irmd/reg/tests/reg_test.c | 1583 | 
7 files changed, 2490 insertions, 0 deletions
diff --git a/src/irmd/reg/tests/CMakeLists.txt b/src/irmd/reg/tests/CMakeLists.txt new file mode 100644 index 00000000..bc1354ed --- /dev/null +++ b/src/irmd/reg/tests/CMakeLists.txt @@ -0,0 +1,29 @@ +get_filename_component(tmp ".." ABSOLUTE) +get_filename_component(src_folder "${tmp}" NAME) + +create_test_sourcelist(${src_folder}_tests test_suite.c +  # Add new tests here +  flow_test.c +  ipcp_test.c +  name_test.c +  proc_test.c +  prog_test.c +  reg_test.c +) + +add_executable(${src_folder}_test EXCLUDE_FROM_ALL ${${src_folder}_tests}) +target_link_libraries(${src_folder}_test ouroboros-common) + +if (CMAKE_BUILD_TYPE MATCHES "Debug*") +  add_compile_flags(${src_folder}_test -DCONFIG_OUROBOROS_DEBUG) +endif () + +add_dependencies(check ${src_folder}_test) + +set(tests_to_run ${${src_folder}_tests}) +remove(tests_to_run test_suite.c) + +foreach(test ${tests_to_run}) +  get_filename_component(test_name ${test} NAME_WE) +  add_test(irmd/reg/${test_name} ${C_TEST_PATH}/${src_folder}_test ${test_name}) +endforeach(test) diff --git a/src/irmd/reg/tests/flow_test.c b/src/irmd/reg/tests/flow_test.c new file mode 100644 index 00000000..efdf21d2 --- /dev/null +++ b/src/irmd/reg/tests/flow_test.c @@ -0,0 +1,294 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * The IPC Resource Manager - Registry - Flows - Unit Tests + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include "../flow.c" + +#include <ouroboros/test.h> + +#include <string.h> + +#define TEST_DATA "testpiggybackdata" + +static int test_reg_flow_create(void) +{ +        struct reg_flow * f; + +        struct flow_info info = { +                .id    = 1, +                .n_pid = 1, +                .qs    = qos_raw, +                .state = FLOW_INIT +        }; + +        TEST_START(); + +        f = reg_flow_create(&info); +        if (f == NULL) { +                printf("Failed to create flow.\n"); +                goto fail; +        } + +        reg_flow_destroy(f); + +        TEST_SUCCESS(); + +        return 0; + fail: +        TEST_FAIL(); +        return -1; +} + +static int test_reg_flow_create_no_id(void) { +        struct flow_info info = { +                .id    = 0, +                .n_pid = 1, +                .qs    = qos_raw, +                .state = FLOW_INIT +        }; + +        reg_flow_create(&info); /* assert fail */ + +        return 0; +} + +static int test_reg_flow_create_no_pid(void) { +        struct flow_info info = { +                .id    = 1, +                .n_pid = 0, +                .qs    = qos_raw, +                .state = FLOW_INIT +        }; + +        reg_flow_create(&info); /* assert fail */ + +        return 0; +} + +static int test_reg_flow_create_has_n_1_pid(void) { +        struct flow_info info = { +                .id      = 1, +                .n_pid   = 0, +                .n_1_pid = 1, +                .qs      = qos_raw, +                .state   = FLOW_INIT +        }; + +        reg_flow_create(&info); /* assert fail */ + +        return 0; +} + +static int test_reg_flow_create_wrong_state(void) { +        struct flow_info info = { +                .id      = 1, +                .n_pid   = 0, +                .n_1_pid = 1, +                .qs      = qos_raw, +                .state   = FLOW_ALLOC_PENDING +        }; + +        reg_flow_create(&info); /* assert fail */ + +        return 0; +} + +static int test_reg_flow_create_has_mpl(void) { +        struct flow_info info = { +                .id      = 1, +                .n_pid   = 1, +                .n_1_pid = 0, +                .mpl     = 10, +                .qs      = qos_raw, +                .state   = FLOW_ALLOC_PENDING +        }; + +        reg_flow_create(&info); /* assert fail */ + +        return 0; +} + +static int test_reg_flow_update(void) +{ +        struct reg_flow * f; + +        struct flow_info info = { +                .id    = 1, +                .n_pid = 1, +                .qs    = qos_raw, +                .state = FLOW_INIT +        }; + +        struct flow_info upd = { +                .id    = 1, +                .n_pid = 1, +                .qs    = qos_data, +                .state = FLOW_DEALLOCATED +        }; + +        TEST_START(); + +        f = reg_flow_create(&info); +        if (f == NULL) { +                printf("Failed to create flow.\n"); +                goto fail; +        } + +        reg_flow_update(f, &upd); + +        if (memcmp(&f->info, &upd, sizeof(upd)) != 0) { +                printf("Flow info not updated.\n"); +                goto fail; +        } + +        reg_flow_destroy(f); + +        TEST_SUCCESS(); + +        return 0; + fail: +        TEST_FAIL(); +        return -1; +} + +static int test_reg_flow_update_wrong_id(void) +{ +        struct reg_flow * f; + +        struct flow_info info = { +                .id    = 1, +                .n_pid = 1, +                .qs    = qos_raw, +                .state = FLOW_INIT +        }; + +        struct flow_info upd = { +                .id    = 2, +                .n_pid = 1, +                .qs    = qos_data, +                .state = FLOW_DEALLOCATED +        }; + +        TEST_START(); + +        f = reg_flow_create(&info); +        if (f == NULL) { +                printf("Failed to create flow.\n"); +                goto fail; +        } + +        reg_flow_update(f, &upd); /* assert fail */ + +        TEST_SUCCESS(); + +        return 0; + fail: +        TEST_FAIL(); +        return -1; +} + +static int test_reg_flow_assert_fails(void) +{ +        int ret = 0; + +        ret |= test_assert_fail(test_reg_flow_create_no_id); + +        ret |= test_assert_fail(test_reg_flow_create_no_pid); + +        ret |= test_assert_fail(test_reg_flow_create_has_n_1_pid); + +        ret |= test_assert_fail(test_reg_flow_create_wrong_state); + +        ret |= test_assert_fail(test_reg_flow_create_has_mpl); + +        ret |= test_assert_fail(test_reg_flow_update_wrong_id); + +        return ret; +} + +static int test_flow_data(void) +{ +        struct reg_flow * f; + +        struct flow_info info = { +                .id    = 1, +                .n_pid = 1, +                .qs    = qos_raw, +                .state = FLOW_INIT +        }; + +        char * data; +        buffer_t buf; +        buffer_t rcv = {NULL, 0}; + +        TEST_START(); + +        data = strdup(TEST_DATA); +        if (data == NULL) { +                printf("Failed to strdup data.\n"); +                goto fail; +        } + +        buf.data = (uint8_t *) data; +        buf.len  = strlen(data); + +        f = reg_flow_create(&info); +        if (f == NULL) { +                printf("Failed to create flow.\n"); +                goto fail; +        } + +        reg_flow_set_data(f, &buf); + +        reg_flow_get_data(f, &rcv); + +        freebuf(buf); +        clrbuf(rcv); + +        reg_flow_destroy(f); + +        TEST_SUCCESS(); + +        return 0; + fail: +        free(data); +        TEST_FAIL(); +        return -1; +} + +int flow_test(int     argc, +              char ** argv) +{ +        int ret = 0; + +        (void) argc; +        (void) argv; + +        ret |= test_reg_flow_create(); + +        ret |= test_reg_flow_update(); + +        ret |= test_reg_flow_assert_fails(); + +        ret |= test_flow_data(); + +        return ret; +}
\ No newline at end of file diff --git a/src/irmd/reg/tests/ipcp_test.c b/src/irmd/reg/tests/ipcp_test.c new file mode 100644 index 00000000..4e0a764b --- /dev/null +++ b/src/irmd/reg/tests/ipcp_test.c @@ -0,0 +1,89 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * The IPC Resource Manager - Registry - IPCPs - Unit Tests + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include <ouroboros/test.h> + +#include "../ipcp.c" + +#define TEST_PID 65535 + +static int test_reg_ipcp_create(void) +{ +        struct reg_ipcp *  ipcp; +        struct ipcp_info   info = { +                .pid   = TEST_PID, +                .state = IPCP_BOOT +        }; +        struct layer_info layer = { +                .name = "testlayer", +                .dir_hash_algo = DIR_HASH_SHA3_224 +        }; + +        TEST_START(); + +        ipcp = reg_ipcp_create(&info); +        if (ipcp == NULL) { +                printf("Failed to create ipcp.\n"); +                goto fail; +        } + +        if (strcmp(ipcp->layer.name, "Not enrolled.") != 0) { +                printf("Layer name was not set.\n"); +                goto fail; +        } + +        ipcp->info.state = IPCP_OPERATIONAL; + +        reg_ipcp_set_layer(ipcp, &layer); + +        if (strcmp(ipcp->layer.name, layer.name) != 0) { +                printf("Layer name was not set.\n"); +                goto fail; +        } + +        if (ipcp->info.state != IPCP_OPERATIONAL) { +                printf("IPCP state was not set.\n"); +                goto fail; +        } + +        reg_ipcp_destroy(ipcp); + +        TEST_SUCCESS(); + +        return 0; + fail: +        TEST_FAIL(); +        return -1; +} + +int ipcp_test(int     argc, +              char ** argv) +{ +        int res = 0; + +        (void) argc; +        (void) argv; + +        res |= test_reg_ipcp_create(); + +        return res; +}
\ No newline at end of file diff --git a/src/irmd/reg/tests/name_test.c b/src/irmd/reg/tests/name_test.c new file mode 100644 index 00000000..e2ceb0fc --- /dev/null +++ b/src/irmd/reg/tests/name_test.c @@ -0,0 +1,283 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * The IPC Resource Manager - Registry - Names - Unit Tests + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include "../name.c" + +#define TEST_PID  65534 +#define TEST_PROG "/usr/bin/testprog" +#define TEST_NAME "testservicename" + +static int test_reg_name_create(void) +{ +        struct reg_name * n; +        struct name_info  info = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR, +        }; + +        n = reg_name_create(&info); +        if (n == NULL) { +                printf("Failed to create name %s.\n", info.name); +                goto fail; +        } + +        reg_name_destroy(n); + +        return 0; + fail: +        return -1; +} + +static int test_reg_name_add_proc(void) +{ +        struct reg_name * n; +        struct name_info  info = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR, +        }; + +        n = reg_name_create(&info); +        if (n == NULL) { +                printf("Failed to create name %s.\n", info.name); +                goto fail; +        } + +        if (reg_name_add_proc(n, TEST_PID) < 0) { +                printf("Failed to add proc.\n"); +                goto fail; +        } + +        if (n->n_procs != 1) { +                printf("n_procs not updated.\n"); +                goto fail; +        } + +        if (!reg_name_has_proc(n, TEST_PID)) { +                printf("Proc not found.\n"); +                goto fail; +        } + +        reg_name_del_proc(n, TEST_PID); + +        if (n->n_procs != 0) { +                printf("n_procs not updated.\n"); +                goto fail; +        } + +        reg_name_destroy(n); + +        return 0; + fail: +        return -1; +} + +static int test_reg_name_add_prog(void) +{ +        struct reg_name * n; +        struct name_info  info = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR, +        }; + +        char * exec[] = { TEST_PROG, "--argswitch", "argvalue", NULL}; + +        n = reg_name_create(&info); +        if (n == NULL) { +                printf("Failed to create name %s.\n", info.name); +                goto fail; +        } + +        if (reg_name_add_prog(n, exec) < 0) { +                printf("Failed to add prog.\n"); +                goto fail; +        } + +        if (n->n_progs != 1) { +                printf("n_progs not updated.\n"); +                goto fail; +        } + +        if (!reg_name_has_prog(n, TEST_PROG)) { +                printf("Prog not found.\n"); +                goto fail; +        } + +        reg_name_del_prog(n, TEST_PROG); + +        if (n->n_progs != 0) { +                printf("n_progs not updated.\n"); +                goto fail; +        } + +        reg_name_destroy(n); + +        return 0; + fail: +        return -1; +} + +static int test_reg_name_add_active(enum pol_balance lb) +{ +        struct reg_name * n; +        pid_t             pid; +        struct name_info  info = { +                .name   = TEST_NAME, +                .pol_lb = lb, +        }; + +        n = reg_name_create(&info); +        if (n == NULL) { +                printf("Failed to create name %s.\n", info.name); +                goto fail; +        } + +        if (reg_name_get_active(n) != -1) { +                printf("Got active from empty actives.\n"); +                goto fail; +        } + +        if (reg_name_add_proc(n, TEST_PID) < 0) { +                printf("Failed to add proc 0.\n"); +                goto fail; +        } + +        if (reg_name_add_proc(n, TEST_PID + 1) < 0) { +                printf("Failed to add proc 1.\n"); +                goto fail; +        } + +        if (reg_name_add_proc(n, TEST_PID + 2) < 0) { +                printf("Failed to add proc 2.\n"); +                goto fail; +        } + +        if (reg_name_add_active(n, TEST_PID) < 0) { +                printf("Failed to add active.\n"); +                goto fail; +        } + +        if (n->n_active != 1) { +                printf("n_active not updated.\n"); +                goto fail; +        } + +        if (reg_name_get_active(n) != TEST_PID) { +                printf("Failed to get active.\n"); +                goto fail; +        } + +        if (reg_name_get_active(n) != TEST_PID) { +                printf("Failed to get active.\n"); +                goto fail; +        } + +        if (reg_name_add_active(n, TEST_PID + 1) < 0) { +                printf("Failed to add active 3.\n"); +                goto fail; +        } + +        if (reg_name_add_active(n, TEST_PID + 1) < 0) { +                printf("Failed to add active 3.\n"); +                goto fail; +        } + + +        if (reg_name_add_active(n, TEST_PID + 2) < 0) { +                printf("Failed to add active 4.\n"); +                goto fail; +        } + +        if (n->n_procs != 3) { +                printf("n_procs not updated.\n"); +                goto fail; +        } + +        if (n->n_active != 4) { +                printf("n_active not updated.\n"); +                goto fail; +        } + +        pid = info.pol_lb == LB_RR ? TEST_PID : TEST_PID + 2; + +        if (reg_name_get_active(n) != pid) { +                printf("Got wrong active pid 1.\n"); +                goto fail; +        } + +        reg_name_del_active(n, pid); + +        if (reg_name_add_active(n, pid) < 0) { +                printf("Failed to add active 4.\n"); +                goto fail; +        } + +        pid = info.pol_lb == LB_RR ? TEST_PID + 1 : TEST_PID + 2; + +        if (reg_name_get_active(n) != pid) { +                printf("Got wrong active pid 2 %d.\n", pid); +                goto fail; +        } + +        reg_name_del_proc(n, TEST_PID + 2); + +        reg_name_del_proc(n, TEST_PID + 1); + +        reg_name_del_proc(n, TEST_PID); + +        if (n->n_procs != 0) { +                printf("n_procs not updated.\n"); +                goto fail; +        } + +        if (n->n_active != 0) { +                printf("n_active not updated.\n"); +                goto fail; +        } + +        reg_name_destroy(n); + +        return 0; + fail: +        return -1; +} + + +int name_test(int     argc, +              char ** argv) +{ +        int res = 0; + +        (void) argc; +        (void) argv; + +        res |= test_reg_name_create(); + +        res |= test_reg_name_add_proc(); + +        res |= test_reg_name_add_prog(); + +        res |= test_reg_name_add_active(LB_RR); + +        res |= test_reg_name_add_active(LB_SPILL); + +        return res; +}
\ No newline at end of file diff --git a/src/irmd/reg/tests/proc_test.c b/src/irmd/reg/tests/proc_test.c new file mode 100644 index 00000000..5c9dd865 --- /dev/null +++ b/src/irmd/reg/tests/proc_test.c @@ -0,0 +1,107 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * The IPC Resource Manager - Registry - Processes - Unit Tests + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include "../proc.c" + +#define TEST_PID  65534 +#define TEST_PROG "usr/bin/testprog" + +static int test_reg_proc_create(void) +{ +        struct reg_proc * proc; +        struct proc_info  info = { +                .pid =  TEST_PID, +                .prog = TEST_PROG +        }; + +        proc = reg_proc_create(&info); +        if (proc == NULL) { +                printf("Failed to create proc.\n"); +                goto fail; +        } + +        reg_proc_destroy(proc); + +        return 0; + fail: +        return -1; +} + +static int test_reg_proc_add_name(void) +{ +        struct reg_proc * proc; +        struct proc_info  info = { +                .pid  = TEST_PID, +                .prog = TEST_PROG +        }; + +        char * name = "testname"; + +        proc = reg_proc_create(&info); +        if (proc == NULL) { +                printf("Failed to create proc.\n"); +                goto fail; +        } + +        if (reg_proc_add_name(proc, name) < 0) { +                printf("Failed to add name."); +                goto fail; +        } + +        if (proc->n_names != 1) { +                printf("n_names not updated.\n"); +                goto fail; +        } + +        if (!reg_proc_has_name(proc, name)) { +                printf("Name not found.\n"); +                goto fail; +        } + +        reg_proc_del_name(proc, name); + +        if (proc->n_names != 0) { +                printf("n_names not updated.\n"); +                goto fail; +        } + +        reg_proc_destroy(proc); + +        return 0; + fail: +        return -1; +} + +int proc_test(int     argc, +              char ** argv) +{ +        int res = 0; + +        (void) argc; +        (void) argv; + +        res |= test_reg_proc_create(); + +        res |= test_reg_proc_add_name(); + +        return res; +} diff --git a/src/irmd/reg/tests/prog_test.c b/src/irmd/reg/tests/prog_test.c new file mode 100644 index 00000000..2565204b --- /dev/null +++ b/src/irmd/reg/tests/prog_test.c @@ -0,0 +1,105 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * The IPC Resource Manager - Registry - Programs - Unit Tests + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include "../prog.c" + +#define TEST_PROG "usr/bin/testprog" + + +static int test_reg_prog_create(void) +{ +        struct reg_prog * prog; +        struct prog_info  info = { +                .name = TEST_PROG +        }; + +        prog = reg_prog_create(&info); +        if (prog == NULL) { +                printf("Failed to create prog.\n"); +                goto fail; +        } + +        reg_prog_destroy(prog); + +        return 0; + fail: +        return -1; +} + +static int test_reg_prog_add_name(void) +{ +        struct reg_prog * prog; +        struct prog_info  info = { +                .name = TEST_PROG +        }; + +        char * name = "testname"; + +        prog = reg_prog_create(&info); +        if (prog == NULL) { +                printf("Failed to create prog.\n"); +                goto fail; +        } + +        if (reg_prog_add_name(prog, name) < 0) { +                printf("Failed to add name."); +                goto fail; +        } + +        if (prog->n_names != 1) { +                printf("n_names not updated.\n"); +                goto fail; +        } + +        if (!reg_prog_has_name(prog, name)) { +                printf("Name not found.\n"); +                goto fail; +        } + +        reg_prog_del_name(prog, name); + +        if (prog->n_names != 0) { +                printf("n_names not updated.\n"); +                goto fail; +        } + +        reg_prog_destroy(prog); + +        return 0; + fail: +        return -1; +} + +int prog_test(int     argc, +              char ** argv) +{ +        int ret = 0; + +        (void) argc; +        (void) argv; + +        ret |= test_reg_prog_create(); + +        ret |= test_reg_prog_add_name(); + +        return ret; +}
\ No newline at end of file diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c new file mode 100644 index 00000000..35290caf --- /dev/null +++ b/src/irmd/reg/tests/reg_test.c @@ -0,0 +1,1583 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2024 + * + * The IPC Resource Manager - Registry - Unit Tests + * + *    Dimitri Staessens <dimitri@ouroboros.rocks> + *    Sander Vrijders   <sander@ouroboros.rocks> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + + +#include "../reg.c" + +#include <ouroboros/test.h> + +#define TEST_PID      3666 +#define TEST_N_1_PID  3999 +#define TEST_FAKE_ID  9128349 +#define TEST_MPL      5 +#define TEST_PROG     "reg_test" /* own binary for binary check */ +#define TEST_IPCP     "testipcp" +#define TEST_NAME     "testname" +#define TEST_DATA     "testpbufdata" +#define TEST_DATA2    "testpbufdata2" +#define TEST_LAYER    "testlayer" +#define REG_TEST_FAIL() \ +        do { TEST_FAIL(); memset(®, 0, sizeof(reg)); } while(0) + +static int test_reg_init(void) +{ +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_create_flow(void) +{ +        struct flow_info info = { +                .n_pid = TEST_PID, +                .qs    = qos_raw, +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_flow(&info) < 0) { +                printf("Failed to create flow.\n"); +                goto fail; +        } + +        if (info.id == 0) { +                printf("Failed to update id.'n"); +                goto fail; +        } + +        if (reg.n_flows != 1) { +                printf("n_flows was not updated.\n"); +                goto fail; +        } + +        if (!reg_has_flow(info.id)) { +                printf("Failed to find flow.\n"); +                goto fail; +        } + +        if (reg_destroy_flow(info.id) < 0) { +                printf("Failed to destroy flow.\n"); +                goto fail; +        } + +        if (reg.n_flows != 0) { +                printf("n_flows was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_allocate_flow_timeout(void) +{ +        struct timespec abstime; +        struct timespec timeo = TIMESPEC_INIT_MS(1); +        buffer_t        pbuf; +        buffer_t        rbuf = {NULL, 0}; + +        struct flow_info info = { +                .n_pid = TEST_PID, +                .qs    = qos_raw +        }; + +        TEST_START(); + +        pbuf.data = (uint8_t *) strdup(TEST_DATA);; +        if (pbuf.data == NULL) { +                printf("Failed to strdup data.\n"); +                goto fail; +        } + +        pbuf.len  = strlen((char *) pbuf.data) + 1; + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); + +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_flow(&info) < 0) { +                printf("Failed to add flow.\n"); +                goto fail; +        } + +        if (reg_prepare_flow_accept(&info, &pbuf) < 0) { +                printf("Failed to prepare flow for accept.\n"); +                goto fail; +        } + +        if (reg_wait_flow_accepted(&info, &rbuf, &abstime) != -ETIMEDOUT) { +                printf("Wait allocated did not timeout.\n"); +                goto fail; +        } + +        if (info.state != FLOW_DEALLOCATED) { +                printf("Flow did not timeout in deallocated state.\n"); +                goto fail; +        } + +        if (pbuf.data == NULL) { +                printf("Flow data was updated on timeout."); +                goto fail; +        } + +        freebuf(pbuf); +        reg_destroy_flow(info.id); + +        if (reg.n_flows != 0) { +                printf("Flow did not destroy.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static void * test_flow_respond_alloc(void * o) +{ +        struct flow_info * info = (struct flow_info *) o; +        buffer_t           pbuf = {NULL, 0}; + +        if (info->state == FLOW_ALLOCATED) { +                pbuf.data = (uint8_t *) strdup(TEST_DATA2); +                if (pbuf.data == NULL) { +                        printf("Failed to strdup data2.\n"); +                        goto fail; +                } +                pbuf.len  = strlen((char *) pbuf.data) + 1; +        } + +        reg_respond_alloc(info, &pbuf); + +        return (void *) 0; + fail: +        return (void *) -1; +} + +static void * test_flow_respond_accept(void * o) +{ +        struct flow_info * info = (struct flow_info *) o; +        buffer_t           pbuf; + +        pbuf.data = (uint8_t *) strdup(TEST_DATA2); +        if (pbuf.data == NULL) { +                printf("Failed to strdup data2.\n"); +                goto fail; +        } +        pbuf.len  = strlen((char *) pbuf.data) + 1; + +        reg_respond_accept(info, &pbuf); + +        if (info->qs.cypher_s == 0) { +                freebuf(pbuf); +        } else if (strcmp((char *) pbuf.data, TEST_DATA) != 0) { +                printf("Data was not passed correctly.\n"); +                goto fail; +        } + +        return (void *) 0; + fail: +        return (void *) -1; +} + +static int test_reg_accept_flow_success(void) +{ +        pthread_t       thr; +        struct timespec abstime; +        struct timespec timeo = TIMESPEC_INIT_S(1); +        buffer_t        pbuf = {(uint8_t *) TEST_DATA, strlen(TEST_DATA)}; +        buffer_t        rbuf  = {NULL, 0}; + +        struct flow_info info = { +                .n_pid = TEST_PID, +                .qs    = qos_raw +        }; + +        struct flow_info n_1_info = { +                .n_1_pid = TEST_N_1_PID, +                .qs      = qos_data_crypt, +                .state   = FLOW_ALLOCATED /* RESPONSE SUCCESS */ +        }; + +        TEST_START(); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); + +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_flow(&info) < 0) { +                printf("Failed to add flow.\n"); +                goto fail; +        } + +        if (reg_prepare_flow_accept(&info, &pbuf) < 0) { +                printf("Failed to prepare flow for accept.\n"); +                goto fail; +        } + +        n_1_info.id  = info.id; +        n_1_info.mpl = 1; + +        pthread_create(&thr, NULL, test_flow_respond_accept, &n_1_info); + +        if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0 ) { +                printf("Flow allocation failed.\n"); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        if (info.state != FLOW_ALLOCATED) { +                printf("Flow succeeded but not in allocated state.\n"); +                goto fail; +        } + +        if (rbuf.data == NULL) { +                printf("rbuf data not returned.\n"); +                goto fail; +        } + +        if (strcmp((char *) rbuf.data, TEST_DATA2) != 0) { +                printf("Data2 was not passed correctly.\n"); +                goto fail; +        } + +        freebuf(rbuf); + +        reg_dealloc_flow(&info); + +        if (info.state != FLOW_DEALLOC_PENDING) { +                printf("Flow dealloc requested but not in pending state.\n"); +                goto fail; +        } + +        reg_dealloc_flow_resp(&info); + +        if (info.state != FLOW_DEALLOCATED) { +                printf("Flow deallocated but not in deallocated state.\n"); +                goto fail; +        } + +        reg_destroy_flow(n_1_info.id); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_accept_flow_success_no_crypt(void) +{ +        pthread_t       thr; +        struct timespec abstime; +        struct timespec timeo = TIMESPEC_INIT_S(1); +        buffer_t        pbuf = {(uint8_t *) TEST_DATA, strlen(TEST_DATA)}; +        buffer_t        rbuf  = {NULL, 0}; + +        struct flow_info info = { +                .n_pid = TEST_PID, +                .qs    = qos_raw +        }; + +        struct flow_info n_1_info = { +                .n_1_pid = TEST_N_1_PID, +                .qs      = qos_data, +                .state   = FLOW_ALLOCATED /* RESPONSE SUCCESS */ +        }; + +        TEST_START(); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); + +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_flow(&info) < 0) { +                printf("Failed to add flow.\n"); +                goto fail; +        } + +        if (reg_prepare_flow_accept(&info, &pbuf) < 0) { +                printf("Failed to prepare flow for accept.\n"); +                goto fail; +        } + +        n_1_info.id  = info.id; +        n_1_info.mpl = 1; + +        pthread_create(&thr, NULL, test_flow_respond_accept, &n_1_info); + +        if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0 ) { +                printf("Flow allocation failed.\n"); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        if (info.state != FLOW_ALLOCATED) { +                printf("Flow succeeded but not in allocated state.\n"); +                goto fail; +        } + +        if (rbuf.data == NULL) { +                printf("rbuf data was not returned.\n"); +                goto fail; +        } + +        if (strcmp((char *) rbuf.data, TEST_DATA) != 0) { +                printf("Data was updated.\n"); +                goto fail; +        } + +        n_1_info.state = FLOW_DEALLOCATED; + +        reg_dealloc_flow(&info); + +        if (info.state != FLOW_DEALLOC_PENDING) { +                printf("Flow dealloc requested but not in pending state.\n"); +                goto fail; +        } + +        reg_dealloc_flow_resp(&info); + +        if (info.state != FLOW_DEALLOCATED) { +                printf("Flow deallocated but not in deallocated state.\n"); +                goto fail; +        } + +        reg_destroy_flow(n_1_info.id); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + + +static int test_reg_allocate_flow_fail(void) +{ +        buffer_t        buf   = {NULL, 0}; +        pthread_t       thr; +        struct timespec abstime; +        struct timespec timeo = TIMESPEC_INIT_S(1); + +        struct flow_info info = { +                .n_pid = TEST_PID, +                .qs    = qos_raw +        }; + +        struct flow_info n_1_info = { +                .n_1_pid = TEST_N_1_PID, +                .qs      = qos_data, +                .state = FLOW_DEALLOCATED /* RESPONSE FAIL */ +        }; + +        TEST_START(); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); + +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_flow(&info) < 0) { +                printf("Failed to add flow.\n"); +                goto fail; +        } + +        info.n_1_pid = TEST_N_1_PID; + +        if (reg_prepare_flow_alloc(&info) < 0) { +                printf("Failed to prepare flow for alloc.\n"); +                goto fail; +        } + +        n_1_info.id  = info.id; + +        pthread_create(&thr, NULL, test_flow_respond_alloc, &n_1_info); + +        if (reg_wait_flow_allocated(&info, &buf, &abstime) == 0 ) { +                printf("Flow allocation succeeded.\n"); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        if (info.state != FLOW_DEALLOCATED) { +                printf("Flow failed but not in deallocated state.\n"); +                goto fail; +        } + +        reg_destroy_flow(n_1_info.id); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_flow(void) { +        int ret = 0; + +        ret |= test_reg_create_flow(); + +        ret |= test_reg_allocate_flow_timeout(); + +        ret |= test_reg_accept_flow_success(); + +        ret |= test_reg_accept_flow_success_no_crypt(); + +        ret |= test_reg_allocate_flow_fail(); + +        return ret; +} + +static int test_reg_create_ipcp(void) +{ +        struct ipcp_info info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_BOOT /* set by spawn_ipcp */ +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_ipcp(&info) < 0) { +                printf("Failed to create ipcp.\n"); +                goto fail; +        } + +        if (reg.n_ipcps != 1) { +                printf("n_ipcps was not updated.\n"); +                goto fail; +        } + +        if (!reg_has_ipcp(info.pid)) { +                printf("Failed to find ipcp.\n"); +                goto fail; +        } + +        if (reg_destroy_ipcp(info.pid) < 0) { +                printf("Failed to destroy ipcp.\n"); +                goto fail; +        } + +        if (reg.n_ipcps != 0) { +                printf("n_ipcps was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_set_layer(void) +{ +        struct reg_ipcp * ipcp; +        struct ipcp_info info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_BOOT /* set by spawn_ipcp */ +        }; +        struct layer_info layer = { +                .name = TEST_LAYER, +        }; + +        struct ipcp_info  get_info = { +                .pid = TEST_PID +        }; +        struct layer_info get_layer; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_ipcp(&info) < 0) { +                printf("Failed to create ipcp.\n"); +                goto fail; +        } + +        ipcp = __reg_get_ipcp(info.pid); +        ipcp->info.state = IPCP_OPERATIONAL; +        info.state = IPCP_ENROLLED; + +        reg_set_layer_for_ipcp(&info, &layer); + +        reg_get_ipcp(&get_info, &get_layer); + +        if (memcmp(&get_info, &info, sizeof(ipcp)) != 0) { +                printf("Failed to set ipcp info.\n"); +                goto fail; +        } + +        if (memcmp(&get_layer, &layer, sizeof(layer)) != 0) { +                printf("Failed to set layer info.\n"); +                goto fail; +        } + +        if (reg_destroy_ipcp(info.pid) < 0) { +                printf("Failed to destroy ipcp.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_ipcp(void) +{ +        int ret = 0; + +        ret |= test_reg_create_ipcp(); + +        ret |= test_set_layer(); + +        return ret; +} + +static int test_reg_create_name(void) +{ +        struct name_info info = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_name(&info) < 0) { +                printf("Failed to create name.\n"); +                goto fail; +        } + +        if (reg.n_names != 1) { +                printf("n_names was not updated.\n"); +                goto fail; +        } + +        if (!reg_has_name(info.name)) { +                printf("Failed to find name.\n"); +                goto fail; +        } + +        if (reg_destroy_name(info.name) < 0) { +                printf("Failed to destroy name.\n"); +                goto fail; +        } + +        if (reg.n_names != 0) { +                printf("n_names was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_name(void) +{ +        int ret = 0; + +        ret |= test_reg_create_name(); + +        return ret; +} + +static int test_reg_create_proc(void) +{ +        struct proc_info info = { +                .pid =  TEST_PID, +                .prog = TEST_PROG +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_proc(&info) < 0) { +                printf("Failed to create process.\n"); +                goto fail; +        } + +        if (reg.n_procs != 1) { +                printf("n_procs was not updated.\n"); +                goto fail; +        } + +        if (!reg_has_proc(info.pid)) { +                printf("Failed to find process.\n"); +                goto fail; +        } + +        if (reg_destroy_proc(info.pid) < 0) { +                printf("Failed to destroy process.\n"); +                goto fail; +        } + +        if (reg.n_procs != 0) { +                printf("n_procs was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_proc(void) +{ +        int ret = 0; + +        ret |= test_reg_create_proc(); + +        return ret; +} + +static int test_reg_spawned(void) +{ +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_spawned(TEST_PID) < 0) { +                printf("Failed to create process.\n"); +                goto fail; +        } + +        if (reg.n_spawned != 1) { +                printf("n_spawned was not updated.\n"); +                goto fail; +        } + +        if (!reg_has_spawned(TEST_PID)) { +                printf("Failed to find spawned.\n"); +                goto fail; +        } + +        if (reg_destroy_spawned(TEST_PID) < 0) { +                printf("Failed to destroy spawned.\n"); +                goto fail; +        } + +        if (reg.n_spawned != 0) { +                printf("n_spawned was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_create_prog(void) +{ +        struct prog_info info = { +                .name = TEST_PROG +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_prog(&info) < 0) { +                printf("Failed to create program.\n"); +                goto fail; +        } + +        if (reg.n_progs != 1) { +                printf("n_progs was not updated.\n"); +                goto fail; +        } + +        if (!reg_has_prog(info.name)) { +                printf("Failed to find program.\n"); +                goto fail; +        } + +        if (reg_destroy_prog(info.name) < 0) { +                printf("Failed to destroy program.\n"); +                goto fail; +        } + +        if (reg.n_progs != 0) { +                printf("n_progs was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_reg_prog(void) +{ +        int ret = 0; + +        ret |= test_reg_create_prog(); + +        return ret; +} + +static int test_bind_proc(void) +{ +        struct proc_info pinfo = { +                .pid =  TEST_PID, +                .prog = TEST_PROG +        }; + +        struct name_info ninfo = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR +        }; + +        TEST_START(); + +        if (reg_init()) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_name(&ninfo) < 0) { +                printf("Failed to create name.\n"); +                goto fail; +        } + +        if (reg_create_proc(&pinfo) < 0) { +                printf("Failed to create proc.\n"); +                goto fail; +        } + +        if (reg_bind_proc(TEST_NAME, TEST_PID) < 0) { +                printf("Failed to bind proc.\n"); +                goto fail; +        } + +        if (reg_unbind_proc(TEST_NAME, TEST_PID) < 0) { +                printf("Failed to unbind proc.\n"); +                goto fail; +        } + +        reg_destroy_proc(TEST_PID); + +        if (reg_name_has_proc( __reg_get_name(TEST_NAME), TEST_PID)) { +                printf("Proc still in name after destroy.\n"); +                goto fail; +        } + +        reg_destroy_name(TEST_NAME); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; +fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_bind_prog(void) +{ +        struct prog_info pinfo = { +                .name = TEST_PROG +        }; + +        struct name_info ninfo = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR +        }; + +        char * exec[] = { TEST_PROG, "--argswitch", "argvalue", NULL}; + +        TEST_START(); + +        if (reg_init()) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_name(&ninfo) < 0) { +                printf("Failed to create name.\n"); +                goto fail; +        } + +        if (reg_create_prog(&pinfo) < 0) { +                printf("Failed to create prog.\n"); +                goto fail; +        } + +        if (reg_bind_prog(TEST_NAME, exec, BIND_AUTO) < 0) { +                printf("Failed to bind prog.\n"); +                goto fail; +        } + +        if (!reg_name_has_prog( __reg_get_name(TEST_NAME), TEST_PROG)) { +                printf("Prog not found in name.\n"); +                goto fail; +        } + +        if (!reg_prog_has_name( __reg_get_prog(TEST_PROG), TEST_NAME)) { +                printf("Name not found in prog.\n"); +                goto fail; +        } + +        if (reg_unbind_prog(TEST_NAME, TEST_PROG) < 0) { +                printf("Failed to unbind prog.\n"); +                goto fail; +        } + +        if (reg_name_has_prog( __reg_get_name(TEST_NAME), TEST_PROG)) { +                printf("Prog still in name after unbind.\n"); +                goto fail; +        } + +        if (reg_prog_has_name( __reg_get_prog(TEST_PROG), TEST_NAME)) { +                printf("Name still in prog after unbind.\n"); +                goto fail; +        } + +        if (reg_bind_prog(TEST_NAME, exec, 0) < 0) { +                printf("Failed to bind prog.\n"); +                goto fail; +        } + +        if (reg_name_has_prog( __reg_get_name(TEST_NAME), TEST_PROG)) { +                printf("Non-auto prog found in name.\n"); +                goto fail; +        } + +        if (reg_unbind_prog(TEST_NAME, TEST_PROG) < 0) { +                printf("Failed to unbind prog.\n"); +                goto fail; +        } + +        reg_destroy_prog(TEST_PROG); + +        reg_destroy_name(TEST_NAME); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; +fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_inherit_prog(void) +{ +        struct name_info nameinfo = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR +        }; + +        struct prog_info proginfo = { +                .name = TEST_PROG +        }; + +        struct proc_info procinfo = { +                .pid  = TEST_PID, +                .prog = TEST_PROG +        }; + +        char * exec[] = { TEST_PROG, NULL}; + +        TEST_START(); + +        if (reg_init()) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_name(&nameinfo) < 0) { +                printf("Failed to create name.\n"); +                goto fail; +        } + +        if (reg_create_prog(&proginfo) < 0) { +                printf("Failed to create prog.\n"); +                goto fail; +        } + +        if (reg_bind_prog(TEST_NAME, exec, 0) < 0) { +                printf("Failed to bind prog.\n"); +                goto fail; +        } + +        if (reg_create_proc(&procinfo) < 0) { +                printf("Failed to create proc.\n"); +                goto fail; +        } + +        if (!reg_name_has_proc(__reg_get_name(TEST_NAME), TEST_PID)) { +                printf("Failed to update name from prog.\n"); +                goto fail; +        } + +        if (!reg_proc_has_name(__reg_get_proc(TEST_PID), TEST_NAME)) { +                printf("Failed to update proc from prog.\n"); +                goto fail; +        } + +        reg_destroy_proc(TEST_PID); + +        reg_destroy_prog(TEST_PROG); + +        reg_destroy_name(TEST_NAME); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; +fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_wait_accepting_timeout(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_MS(1); +        int              flow_id; +        uint8_t          hash[64]; +        struct name_info ninfo = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR +        }; + +        TEST_START(); + +        if (reg_init()) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_name(&ninfo) < 0) { +                printf("Failed to create name.\n"); +                goto fail; +        } + +        str_hash(HASH_SHA3_256, hash, ninfo.name); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        flow_id = reg_wait_flow_accepting(HASH_SHA3_256, hash, &abstime); +        if (flow_id != -ETIMEDOUT) { +                printf("Wait accept did not time out: %d.\n", flow_id); +                goto fail; +        } + +        reg_destroy_name(TEST_NAME); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_wait_accepting_fail_name(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_S(1); +        int              flow_id; +        uint8_t          hash[64]; + +        TEST_START(); + +        if (reg_init()) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); +        str_hash(HASH_SHA3_256, hash, "C0FF33"); + +        flow_id = reg_wait_flow_accepting(HASH_SHA3_256, hash, &abstime); +        if (flow_id != -ENAME) { +                printf("Wait accept did not fail on name: %d.\n", flow_id); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static void * test_call_flow_accept(void * o) +{ +        struct timespec abstime; +        struct timespec timeo = TIMESPEC_INIT_MS(1); +        buffer_t        pbuf = {NULL, 0}; + +        struct proc_info pinfo = { +                .pid =  TEST_PID, +                .prog = TEST_PROG +        }; + +        struct flow_info info = { +                .n_pid = pinfo.pid, +                .qs    = qos_raw, +        }; + +        if (reg_create_proc(&pinfo) < 0) { +                printf("Failed to create proc.\n"); +                goto fail; +        } + +        if (reg_bind_proc((char *) o, TEST_PID) < 0) { +                printf("Failed to bind proc.\n"); +                goto fail; +        } + +        if (reg_create_flow(&info) < 0) { +                printf("Failed to create flow.\n"); +                goto fail; +        } + +        info.state = FLOW_ACCEPT_PENDING; + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        reg_prepare_flow_accept(&info, &pbuf); + +        if (reg_wait_flow_accepted(&info, &pbuf, &abstime) != -ETIMEDOUT) { +                printf("Wait allocated did not timeout.\n"); +                goto fail; +        } + +        reg_destroy_flow(info.id); +        reg_destroy_proc(pinfo.pid); + +        return (void *) 0; + fail: +        return (void *) -1; +} + +static int test_wait_accepting_success(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_S(1); +        int              flow_id; +        pthread_t        thr; +        uint8_t          hash[64]; +        struct name_info ninfo = { +                .name   = TEST_NAME, +                .pol_lb = LB_RR +        }; + +        TEST_START(); + +        if (reg_init()) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_name(&ninfo) < 0) { +                printf("Failed to create name.\n"); +                goto fail; +        } + +        pthread_create(&thr, NULL, test_call_flow_accept, ninfo.name); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        str_hash(HASH_SHA3_256, hash, ninfo.name); + +        flow_id = reg_wait_flow_accepting(HASH_SHA3_256, hash, &abstime); +        if (flow_id < 0) { +                printf("Wait accept did not return a flow id: %d.", flow_id); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        reg_destroy_name(TEST_NAME); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_wait_accepting(void) +{ +        int ret = 0; + +        ret |= test_wait_accepting_timeout(); + +        ret |= test_wait_accepting_fail_name(); + +        ret |= test_wait_accepting_success(); + +        return ret; +} + +static int test_wait_ipcp_boot_timeout(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_MS(1); +        struct ipcp_info info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_BOOT  /* set by spawn_ipcp */ +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_ipcp(&info) < 0) { +                printf("Failed to create ipcp.\n"); +                goto fail; +        } + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_wait_ipcp_boot(&info, &abstime) != -ETIMEDOUT) { +                printf("Wait boot did not timeout.\n"); +                goto fail; +        } + +        if (reg_destroy_ipcp(info.pid) < 0) { +                printf("Failed to destroy ipcp.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static void * test_ipcp_respond(void * o) +{ +        (void) o; + +        reg_respond_ipcp((struct ipcp_info *) o); + +        return (void *) 0; +} + +static int test_wait_ipcp_boot_fail(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_S(1); +        pthread_t        thr; +        struct ipcp_info info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_BOOT /* set by spawn_ipcp */ +        }; +        struct ipcp_info resp_info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_NULL +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_ipcp(&info) < 0) { +                printf("Failed to create ipcp.\n"); +                goto fail; +        } + +        pthread_create(&thr, NULL, test_ipcp_respond, &resp_info); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        info.state = IPCP_BOOT; + +        if (reg_wait_ipcp_boot(&info, &abstime) == 0) { +                printf("IPCP boot reported success.\n"); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        if (reg_destroy_ipcp(info.pid) < 0) { +                printf("Failed to destroy ipcp.\n"); +                goto fail; +        } + +        if (reg.n_ipcps != 0) { +                printf("n_ipcps was not updated.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_wait_ipcp_boot_success(void) +{ +        pthread_t        thr; +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_S(1); +        struct ipcp_info info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_BOOT /* set by spawn_ipcp */ +        }; +        struct ipcp_info resp_info = { +                .name  = TEST_IPCP, +                .pid   = TEST_PID, +                .state = IPCP_OPERATIONAL +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        if (reg_create_ipcp(&info) < 0) { +                printf("Failed to create ipcp.\n"); +                goto fail; +        } + +        pthread_create(&thr, NULL, test_ipcp_respond, &resp_info); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        info.state = IPCP_BOOT; + +        if (reg_wait_ipcp_boot(&info, &abstime) < 0) { +                printf("IPCP boot failed.\n"); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        if (info.state != IPCP_OPERATIONAL) { +                printf("IPCP boot succeeded in non-operational state.\n"); +                goto fail; +        } + +        if (reg_destroy_ipcp(info.pid) < 0) { +                printf("Failed to destroy ipcp.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_wait_ipcp_boot(void) +{ +        int ret = 0; + +        ret |= test_wait_ipcp_boot_timeout(); + +        ret |= test_wait_ipcp_boot_fail(); + +        ret |= test_wait_ipcp_boot_success(); + +        return ret; +} + +static int test_wait_proc_timeout(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_MS(1); + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_wait_proc(TEST_PID, &abstime) != -ETIMEDOUT) { +                printf("Wait proc did not timeout.\n"); +                goto fail; +        } + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static void * test_proc(void * o) +{ +        (void) o; + +        reg_create_proc((struct proc_info *) o); + +        return (void *) 0; +} + +static int test_wait_proc_success(void) +{ +        struct timespec  abstime; +        struct timespec  timeo = TIMESPEC_INIT_S(1); +        pthread_t        thr; +        struct proc_info info = { +                .pid  = TEST_PID, +                .prog = TEST_PROG +        }; + +        TEST_START(); + +        if (reg_init() < 0) { +                printf("Failed to init registry.\n"); +                goto fail; +        } + +        pthread_create(&thr, NULL, test_proc, &info); + +        clock_gettime(PTHREAD_COND_CLOCK, &abstime); +        ts_add(&abstime, &timeo, &abstime); + +        if (reg_wait_proc(info.pid, &abstime) < 0) { +                printf("Waiting for proc failed.\n"); +                goto fail; +        } + +        pthread_join(thr, NULL); + +        reg_destroy_proc(info.pid); + +        reg_fini(); + +        TEST_SUCCESS(); + +        return 0; + fail: +        REG_TEST_FAIL(); +        return -1; +} + +static int test_wait_proc(void) +{ +        int ret = 0; + +        ret |= test_wait_proc_timeout(); + +        ret |= test_wait_proc_success(); + +        return ret; +} + + +int reg_test(int     argc, +             char ** argv) +{ +        int ret = 0; + +        (void) argc; +        (void) argv; + +        ret |= test_reg_init(); + +        ret |= test_reg_flow(); + +        ret |= test_reg_ipcp(); + +        ret |= test_reg_name(); + +        ret |= test_reg_proc(); + +        ret |= test_reg_prog(); + +        ret |= test_reg_spawned(); + +        ret |= test_bind_proc(); + +        ret |= test_bind_prog(); + +        ret |= test_inherit_prog(); + +        ret |= test_wait_accepting(); + +        ret |= test_wait_ipcp_boot(); + +        ret |= test_wait_proc(); + +        return ret; +}
\ No newline at end of file  | 
