#include #include #include #include #include #include #include #include #include #include #include #include #include extern int __real_rte_eal_init(int argc, char **argv); int __wrap_rte_eal_init(int argc, char * argv[]) { int inject_eal_init_failed = mock_type(int); if (inject_eal_init_failed) { return -1; } return 0; } static int rte_exit_called = 0; int __wrap_rte_exit(int status) { rte_exit_called = 1; return 0; } static int call_real_rte_mp_request_sync = 1; extern int __real_rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply, const struct timespec *ts); int __wrap_rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply, const struct timespec *ts) { if (call_real_rte_mp_request_sync) { return __real_rte_mp_request_sync(req, reply, ts); } int mock_ret = mock_type(int); if (mock_ret != 0) { return mock_ret; } struct rte_mp_msg * mock_out_req = mock_ptr_type(struct rte_mp_msg *); if (strcasecmp(req->name, "instance_alive_register") == 0) { struct app_register_resp * mock_resp = rte_zmalloc(NULL, sizeof(struct app_register_resp), 0); mock_resp->errcode = mock_type(int); const char * mock_symbol = mock_ptr_type(const char *); const char * mock_strerr = mock_ptr_type(const char *); snprintf((char *)mock_resp->symbol, sizeof(mock_resp->symbol), "%s", mock_symbol); snprintf((char *)mock_resp->strerr, sizeof(mock_resp->strerr), "%s", mock_strerr); /* NOTE: mock_msg_resp must alloc by malloc(), and release by free() */ struct rte_mp_msg * mock_msg_resp = malloc(sizeof(struct rte_mp_msg)); memset(mock_msg_resp, 0, sizeof(struct rte_mp_msg)); mock_msg_resp->len_param = sizeof(uintptr_t); *(uintptr_t *)(&mock_msg_resp->param) = (uintptr_t)mock_resp; reply->msgs = mock_msg_resp; } else { assert(0); } if (mock_out_req != NULL) { /* copy the param */ memcpy(mock_out_req->param, req->param, req->len_param); mock_out_req->len_param = req->len_param; /* copy the name */ snprintf(mock_out_req->name, sizeof(mock_out_req->name), "%s", req->name); /* dup the fds */ for (unsigned int i = 0; i < req->num_fds; i++) { mock_out_req->fds[i] = dup(req->fds[i]); } mock_out_req->num_fds = req->num_fds; } return mock_ret; } const char * fake_mrmonit_daemon_text = "{\n" " \"general\": {\n" " \"unixtime\": 1718330269,\n" " \"g_cfgfile\": \"/opt/mrzcpd/etc/mrglobal.conf\",\n" " \"g_hwfile\": \"/var/run/mrzcpd/hwfile.json\"\n" " }\n" "}"; static void testcase_marsio_init_register_succ(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); unsigned int u32_disable = 0; marsio_option_set(instance, MARSIO_OPT_EXIT_WHEN_ERR, (void *)&u32_disable, sizeof(u32_disable)); /* create a service daemon monit file to simulate the service is running */ mkdir("/var/run/mrzcpd", 0755); FILE * fp = fopen("/var/run/mrzcpd/mrmonit.daemon", "w"); assert_non_null(fp); fprintf(fp, "%s", fake_mrmonit_daemon_text); fclose(fp); #if 0 will_return(__wrap_rte_eal_init, 0); #endif struct rte_mp_msg msg_req; will_return(__wrap_rte_mp_request_sync, 0); will_return(__wrap_rte_mp_request_sync, &msg_req); will_return(__wrap_rte_mp_request_sync, 0); will_return(__wrap_rte_mp_request_sync, "test_marsio_init"); will_return(__wrap_rte_mp_request_sync, "successful"); /* should success */ int ret = marsio_init(instance, "test_marsio_init"); assert_int_equal(ret, 0); /* there's only one fd transfer to service process */ assert_int_equal(msg_req.num_fds, 1); /* try to close the fd to simulate the service exit or crash */ close(msg_req.fds[0]); /* sleep 1s, and the exit should be called */ sleep(1); assert_int_equal(rte_exit_called, 1); rte_exit_called = 0; ret = marsio_destory(instance); assert_int_equal(ret, 0); } static void testcase_marsio_init_register_failed_by_errcode(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); unsigned int u32_disable = 0; marsio_option_set(instance, MARSIO_OPT_EXIT_WHEN_ERR, (void *)&u32_disable, sizeof(u32_disable)); /* create a service daemon monit file to simulate the service is running */ FILE * fp = fopen("/var/run/mrzcpd/mrmonit.daemon", "w"); assert_non_null(fp); fprintf(fp, "%s", fake_mrmonit_daemon_text); fclose(fp); #if 0 will_return(__wrap_rte_eal_init, 0); #endif struct rte_mp_msg msg_req; will_return(__wrap_rte_mp_request_sync, 0); will_return(__wrap_rte_mp_request_sync, &msg_req); will_return(__wrap_rte_mp_request_sync, 1); will_return(__wrap_rte_mp_request_sync, "test_mrapp"); will_return(__wrap_rte_mp_request_sync, "test_mrapp register failed"); /* should fail, as the mrapp register failed */ int ret = marsio_init(instance, "test_marsio_init"); assert_int_equal(ret, -1); ret = marsio_destory(instance); assert_int_equal(ret, 0); } static void testcase_marsio_int_register_failed_by_mp_sync_failed(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); unsigned int u32_disable = 0; marsio_option_set(instance, MARSIO_OPT_EXIT_WHEN_ERR, (void *)&u32_disable, sizeof(u32_disable)); /* create a service daemon monit file to simulate the service is running */ mkdir("/var/run/mrzcpd", 0755); /* create a service daemon monit file to simulate the service is running */ FILE * fp = fopen("/var/run/mrzcpd/mrmonit.daemon", "w"); assert_non_null(fp); fprintf(fp, "%s", fake_mrmonit_daemon_text); fclose(fp); will_return(__wrap_rte_eal_init, 0); /* inject the mrapp register failed, ret value and reply value */ will_return(__wrap_rte_mp_request_sync, -1); /* should fail, as the mrapp register failed */ int ret = marsio_init(instance, "test_marsio_init"); assert_int_equal(ret, -1); ret = marsio_destory(instance); assert_int_equal(ret, 0); } static void testcase_marsio_init_eal_failed(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); unsigned int u32_disable = 0; marsio_option_set(instance, MARSIO_OPT_EXIT_WHEN_ERR, (void *)&u32_disable, sizeof(u32_disable)); /* create a service daemon monit file to simulate the service is running */ FILE * fp = fopen("/var/run/mrzcpd/mrmonit.daemon", "w"); assert_non_null(fp); fprintf(fp, "%s", fake_mrmonit_daemon_text); fclose(fp); /* inject the eal init failed */ int inject_eal_init_failed = 1; will_return(__wrap_rte_eal_init, inject_eal_init_failed); /* should fail, as the eal init failed */ int ret = marsio_init(instance, "test_marsio_init"); assert_int_equal(ret, -1); ret = marsio_destory(instance); assert_int_equal(ret, 0); } static void testcase_marsio_init_no_service_running(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); unsigned int u32_disable = 0; marsio_option_set(instance, MARSIO_OPT_EXIT_WHEN_ERR, (void *)&u32_disable, sizeof(u32_disable)); /* erase the service daemon monit file */ remove("/var/run/mrzcpd/mrmonit.daemon"); /* should fail, as the service is not running */ int ret = marsio_init(instance, "test_marsio_init"); assert_int_equal(ret, -1); ret = marsio_destory(instance); assert_int_equal(ret, 0); } static void testcase_marsio_instance_set_thread_mask_in_cpuset(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); /* should accept */ cpu_set_t param_cpu_set = {}; CPU_SET(1, ¶m_cpu_set); int ret = marsio_option_set(instance, MARSIO_OPT_THREAD_MASK_IN_CPUSET, ¶m_cpu_set, sizeof(param_cpu_set)); assert_int_equal(ret, 0); /* size is not enough, input should be rejected */ unsigned int cpu_set_small = 0; ret = marsio_option_set(instance, MARSIO_OPT_THREAD_MASK_IN_CPUSET, &cpu_set_small, sizeof(cpu_set_small)); assert_int_equal(ret, -EINVAL); #if 0 cpu_set_t param_cpu_set_get; marsio_option_get(instance, MARSIO_OPT_THREAD_MASK_IN_CPUSET, ¶m_cpu_set_get, sizeof(param_cpu_set_get)); assert_true(CPU_EQUAL(¶m_cpu_set, ¶m_cpu_set_get)); #endif marsio_destory(instance); } static void testcase_marsio_instance_set_thread_num(void ** state) { struct mr_instance * instance = marsio_create(); assert_non_null(instance); /* should accept */ unsigned int param_thread_num = 4; int ret = marsio_option_set(instance, MARSIO_OPT_THREAD_NUM, ¶m_thread_num, sizeof(param_thread_num)); assert_int_equal(ret, 0); /* size is not enough, input should be rejected */ uint8_t param_thread_num_u8 = 8; ret = marsio_option_set(instance, MARSIO_OPT_THREAD_NUM, ¶m_thread_num_u8, sizeof(param_thread_num_u8)); assert_int_equal(ret, -EINVAL); /* size is larger than expected * FIXME: the input should be rejected */ uint64_t param_thread_num_u64 = 8; ret = marsio_option_set(instance, MARSIO_OPT_THREAD_NUM, ¶m_thread_num_u64, sizeof(param_thread_num_u64)); assert_int_equal(ret, 0); #if 0 unsigned int param_thread_num_get = 0; marsio_option_get(instance, MARSIO_OPT_THREAD_NUM, ¶m_thread_num_get, sizeof(param_thread_num)); assert_int_equal(param_thread_num_get, param_thread_num_u64); #endif marsio_destory(instance); } int main(int argc, char * argv[]) { /* generate the eal args */ static char * eal_args[] = { "unittest", "-c 0x1", "--no-huge", "--no-pci", }; /* run the eal with no huge pages */ int ret = __real_rte_eal_init(RTE_DIM(eal_args), eal_args); if (ret < 0) { rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); } call_real_rte_mp_request_sync = 0; const struct CMUnitTest testcases_instance[] = { cmocka_unit_test(testcase_marsio_instance_set_thread_num), cmocka_unit_test(testcase_marsio_instance_set_thread_mask_in_cpuset), cmocka_unit_test(testcase_marsio_init_no_service_running), cmocka_unit_test(testcase_marsio_init_eal_failed), cmocka_unit_test(testcase_marsio_int_register_failed_by_mp_sync_failed), cmocka_unit_test(testcase_marsio_init_register_failed_by_errcode), cmocka_unit_test(testcase_marsio_init_register_succ), }; cmocka_run_group_tests(testcases_instance, NULL, NULL); rte_eal_cleanup(); }