#include <stic.h> #include <stddef.h> /* NULL */ #include <stdlib.h> /* free() malloc() */ #include <string.h> /* memset() strcmp() strdup() */ #include <test-utils.h> #include "../../src/utils/str.h" #include "../../src/utils/string_array.h" #include "../../src/background.h" #include "../../src/ipc.h" static void test_ipc_args(char *args[]); static void test_ipc_args2(char *args[]); static void recursive_ipc_args(char *args[]); static char * test_ipc_eval(const char expr[]); static char * test_ipc_eval_error(const char expr[]); static void other_instance(bg_op_t *bg_op, void *arg); static int enabled_and_not_in_wine(void); static int enabled_and_not_windows(void); static const char NAME[] = "vifm-test"; static int nmessages; static char *message; static int nmessages2; static char *message2; static ipc_t *recursive_ipc; TEARDOWN() { nmessages = 0; nmessages2 = 0; update_string(&message, NULL); update_string(&message2, NULL); } TEST(destroy_null, IF(ipc_enabled)) { ipc_free(NULL); } TEST(create_and_destroy, IF(ipc_enabled)) { ipc_t *const ipc = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); assert_non_null(ipc); ipc_free(ipc); } TEST(name_can_be_null, IF(ipc_enabled)) { ipc_t *const ipc = ipc_init(NULL, &test_ipc_args, &test_ipc_eval); assert_non_null(ipc); ipc_free(ipc); } TEST(name_is_taken_into_account, IF(ipc_enabled)) { ipc_t *const ipc = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); assert_string_starts_with(NAME, ipc_get_name(ipc)); ipc_free(ipc); } TEST(names_do_not_repeat, IF(enabled_and_not_in_wine)) { ipc_t *const ipc1 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); ipc_t *const ipc2 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); assert_true(strcmp(ipc_get_name(ipc1), ipc_get_name(ipc2)) != 0); ipc_free(ipc1); ipc_free(ipc2); } TEST(instance_is_listed_when_it_exists, IF(enabled_and_not_in_wine)) { int len; ipc_t *const ipc = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); char **const list = ipc_list(&len); assert_true(is_in_string_array(list, len, ipc_get_name(ipc))); free_string_array(list, len); ipc_free(ipc); } TEST(instance_is_not_listed_after_it_is_freed, IF(ipc_enabled)) { int len; char **list; ipc_t *const ipc = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); char *const name = strdup(ipc_get_name(ipc)); ipc_free(ipc); list = ipc_list(&len); assert_false(is_in_string_array(list, len, name)); free_string_array(list, len); free(name); } TEST(message_is_delivered, IF(enabled_and_not_in_wine)) { char msg[] = "test message"; char *data[] = { msg, NULL }; ipc_t *const ipc1 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); ipc_t *const ipc2 = ipc_init(NAME, &test_ipc_args2, &test_ipc_eval); assert_success(ipc_send(ipc1, ipc_get_name(ipc2), data)); assert_false(ipc_check(ipc1)); assert_true(ipc_check(ipc2)); assert_false(ipc_check(ipc2)); ipc_free(ipc1); ipc_free(ipc2); assert_int_equal(0, nmessages); assert_string_equal(NULL, message); assert_int_equal(2, nmessages2); assert_string_equal(msg, message2); } TEST(large_message_is_delivered, IF(enabled_and_not_in_wine)) { enum { LEN = 64*1024 }; char *msg = malloc(LEN + 1); memset(msg, 'x', LEN - 1); msg[LEN - 1] = '\0'; char *data[] = { msg, NULL }; ipc_t *const ipc1 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); ipc_t *const ipc2 = ipc_init(NAME, &test_ipc_args2, &test_ipc_eval); assert_success(bg_execute("", "", 0, 1, &other_instance, ipc2)); assert_success(ipc_send(ipc1, ipc_get_name(ipc2), data)); assert_false(ipc_check(ipc1)); wait_for_bg(); ipc_free(ipc1); ipc_free(ipc2); assert_int_equal(0, nmessages); assert_string_equal(NULL, message); assert_int_equal(2, nmessages2); assert_string_equal(msg, message2); free(msg); } TEST(expr_is_evaluated, IF(enabled_and_not_in_wine)) { const char expr[] = "good expression"; char *result; ipc_t *const ipc1 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); ipc_t *const ipc2 = ipc_init(NAME, &test_ipc_args2, &test_ipc_eval); assert_success(bg_execute("", "", 0, 1, &other_instance, ipc2)); result = ipc_eval(ipc1, ipc_get_name(ipc2), expr); assert_false(ipc_check(ipc1)); wait_for_bg(); ipc_free(ipc1); ipc_free(ipc2); assert_int_equal(0, nmessages); assert_string_equal(NULL, message); assert_int_equal(0, nmessages2); assert_string_equal(NULL, message2); assert_string_equal("good result", result); free(result); } TEST(eval_error_is_handled, IF(enabled_and_not_in_wine)) { const char expr[] = "bad expression"; char *result; ipc_t *const ipc1 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); ipc_t *const ipc2 = ipc_init(NAME, &test_ipc_args2, &test_ipc_eval_error); assert_success(bg_execute("", "", 0, 1, &other_instance, ipc2)); result = ipc_eval(ipc1, ipc_get_name(ipc2), expr); assert_false(ipc_check(ipc1)); wait_for_bg(); ipc_free(ipc1); ipc_free(ipc2); assert_int_equal(0, nmessages); assert_string_equal(NULL, message); assert_int_equal(0, nmessages2); assert_string_equal(NULL, message2); assert_string_equal(NULL, result); free(result); } TEST(checking_ipc_from_ipc_handler_is_noop, IF(enabled_and_not_windows)) { char msg[] = "test message"; char *data[] = { msg, NULL }; ipc_t *const ipc1 = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); ipc_t *const ipc2 = ipc_init(NAME, &recursive_ipc_args, &test_ipc_eval); recursive_ipc = ipc2; assert_success(ipc_send(ipc1, ipc_get_name(ipc2), data)); assert_success(ipc_send(ipc1, ipc_get_name(ipc2), data)); assert_true(ipc_check(ipc2)); assert_true(ipc_check(ipc2)); ipc_free(ipc1); ipc_free(ipc2); } TEST(no_send_to_self, IF(enabled_and_not_in_wine)) { char msg[] = "test message"; char *data[] = { msg, NULL }; ipc_t *ipc = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); assert_failure(ipc_send(ipc, ipc_get_name(ipc), data)); assert_false(ipc_check(ipc)); ipc_free(ipc); assert_int_equal(0, nmessages); assert_string_equal(NULL, message); } TEST(no_eval_to_self, IF(enabled_and_not_in_wine)) { const char expr[] = "good expression"; ipc_t *ipc = ipc_init(NAME, &test_ipc_args, &test_ipc_eval); assert_string_equal(NULL, ipc_eval(ipc, ipc_get_name(ipc), expr)); assert_false(ipc_check(ipc)); ipc_free(ipc); assert_int_equal(0, nmessages); assert_string_equal(NULL, message); } static void test_ipc_args(char *args[]) { nmessages += count_strings(args); update_string(&message, args[1]); } static void test_ipc_args2(char *args[]) { nmessages2 += count_strings(args); update_string(&message2, args[1]); } static void recursive_ipc_args(char *args[]) { assert_false(ipc_check(recursive_ipc)); } static char * test_ipc_eval(const char expr[]) { if(strcmp("good expression", expr) == 0) { return strdup("good result"); } return NULL; } static char * test_ipc_eval_error(const char expr[]) { return NULL; } static void other_instance(bg_op_t *bg_op, void *arg) { ipc_t *const ipc = arg; while(!ipc_check(ipc)) { /* Do nothing. */ } } static int enabled_and_not_in_wine(void) { #ifndef _WIN32 return ipc_enabled(); #else /* Apparently, WINE doesn't implement some things related to named pipes. */ return (ipc_enabled() && not_wine()); #endif } static int enabled_and_not_windows(void) { #ifndef _WIN32 return ipc_enabled(); #else return 0; #endif } /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 filetype=c : */