#include #include #include #include #include #include #include #include #include #include #include #include "safe-kill.h" #define BUF_MAX 1024 int __real_kill(pid_t pid, int sig); FILE *__real_fopen(const char *pathname, const char *mode); int __wrap_kill(pid_t pid, int sig) { bool fake = mock_type(bool); if (!fake) return __real_kill(pid, sig); check_expected(pid); check_expected(sig); return 0; } FILE *__wrap_fopen(const char *pathname, const char *mode) { char buf[BUF_MAX]; int fake_type = mock_type(int); if (fake_type == 0) { /* don't mock */ return __real_fopen(pathname, mode); } else if (fake_type == 1) { /* return prepared file */ check_expected_ptr(pathname); check_expected_ptr(mode); int coredump_state = mock_type(int); snprintf(buf, sizeof buf, "../../tests/test-safe-kill-%d.txt", coredump_state); return __real_fopen(buf, mode); } else { /* file not found */ errno = ENOENT; return NULL; } } FILE *__wrap_fopen64(const char *pathname, const char *mode) { return __wrap_fopen(pathname, mode); } static void is_process_coredumping_positive(void **state) { /* CoreDumping = 0 */ will_return(__wrap_fopen, 1); will_return(__wrap_fopen, 0); expect_string(__wrap_fopen, pathname, "/proc/1/status"); expect_string(__wrap_fopen, mode, "r"); assert(is_process_coredumping(1) == false); /* CoreDumping = 1 */ will_return(__wrap_fopen, 1); will_return(__wrap_fopen, 1); expect_string(__wrap_fopen, pathname, "/proc/1/status"); expect_string(__wrap_fopen, mode, "r"); assert(is_process_coredumping(1) == true); /* no CoreDumping entry (i.e. unsupported by kernel) */ will_return(__wrap_fopen, 1); will_return(__wrap_fopen, 3); expect_string(__wrap_fopen, pathname, "/proc/1/status"); expect_string(__wrap_fopen, mode, "r"); assert(is_process_coredumping(1) == false); } static void is_process_coredumping_negative(void **state) { /* file not found (fopen returns NULL) */ will_return(__wrap_fopen, 2); assert(is_process_coredumping(1) == false); will_return(__wrap_fopen, 1); will_return(__wrap_fopen, 2); expect_string(__wrap_fopen, pathname, "/proc/123/status"); expect_string(__wrap_fopen, mode, "r"); /* wrong CoreDumping key value */ assert(is_process_coredumping(123) == false); } static void safe_kill_positive(void **state) { /* SIGKILL shouldn't be delivered if the process is coredumping */ will_return(__wrap_fopen, 1); will_return(__wrap_fopen, 1); expect_string(__wrap_fopen, pathname, "/proc/3/status"); expect_string(__wrap_fopen, mode, "r"); assert(safe_kill(3, SIGKILL, SAFE_KILL_BY_UNKNOWN_REASON) == 0); } static void safe_kill_negative(void **state) { /* SIGUSR1 should be delivered always */ will_return(__wrap_kill, true); expect_value(__wrap_kill, pid, 1); expect_value(__wrap_kill, sig, SIGUSR1); assert(safe_kill(1, SIGUSR1, SAFE_KILL_BY_UNKNOWN_REASON) == 0); /* SIGKILL should be delivered if the process is not coredumping */ will_return(__wrap_fopen, 1); will_return(__wrap_fopen, 0); expect_string(__wrap_fopen, pathname, "/proc/2/status"); expect_string(__wrap_fopen, mode, "r"); will_return(__wrap_kill, true); expect_value(__wrap_kill, pid, 2); expect_value(__wrap_kill, sig, SIGKILL); assert(safe_kill(2, SIGKILL, SAFE_KILL_BY_UNKNOWN_REASON) == 0); } int main(int argc, char* argv[]) { int r; const struct CMUnitTest positive_tests[] = { cmocka_unit_test(is_process_coredumping_positive), cmocka_unit_test(safe_kill_positive), }; const struct CMUnitTest negative_tests[] = { cmocka_unit_test(is_process_coredumping_negative), cmocka_unit_test(safe_kill_negative), }; r = cmocka_run_group_tests(positive_tests, NULL, NULL); if (r != 0) return r; r = cmocka_run_group_tests(negative_tests, NULL, NULL); if (r != 0) return r; return r; }