TEST_F(ServerStartup, after_server_sigkilled_can_start_new_instance) { ASSERT_FALSE(mtf::detect_server(mtf::test_socket_file(), std::chrono::milliseconds(0))); run_in_server([]{}); if (is_test_process()) { /* Under valgrind, raise(SIGKILL) results in a memcheck orphan process * we kill the server process from the test process instead */ EXPECT_TRUE(sigkill_server_process()); run_in_server([]{}); } run_in_client([] { EXPECT_TRUE(mtf::detect_server(mtf::test_socket_file(), std::chrono::milliseconds(100))); }); }
int find_test_symbol(Context * ctx, const char * name, void ** addr, int * sym_class) { /* This code allows to run TCF diagnostic tests when symbols info is not available */ if (is_test_process(ctx) && strncmp(name, "tcf_test_", 9) == 0) { *addr = NULL; if (strcmp(name, "tcf_test_array") == 0) { *sym_class = SYM_CLASS_REFERENCE; *addr = &tcf_test_array; } else if (strcmp(name, "tcf_test_char") == 0) { *sym_class = SYM_CLASS_REFERENCE; *addr = &tcf_test_char; } else { *sym_class = SYM_CLASS_FUNCTION; if (strcmp(name, "tcf_test_func0") == 0) *addr = (void *)&tcf_test_func0; else if (strcmp(name, "tcf_test_func1") == 0) *addr = (void *)&tcf_test_func1; else if (strcmp(name, "tcf_test_func2") == 0) *addr = (void *)&tcf_test_func2; else if (strcmp(name, "tcf_test_func3") == 0) *addr = (void *)&tcf_test_func3; } if (*addr != NULL) return 0; } errno = ERR_SYM_NOT_FOUND; return -1; }
TEST_F(UnresponsiveClient, does_not_hang_server) { mt::CrossProcessAction server_send_events; mt::CrossProcessAction client_connect; mt::CrossProcessAction client_release; mt::CrossProcessAction server_finish; SessionListener sessions; init_server([&] { server.override_the_session_listener([&] { return mt::fake_shared(sessions); }); }); run_in_server([&] { mt::AutoJoinThread t{ [&] { server_send_events.exec([&] { for (int i = 0; i < 1000; ++i) { sessions.for_each( [i] (std::shared_ptr<ms::Session> const& session) { session->default_surface()->resize({i + 1, i + 1}); }); } }); }}; server_finish.exec([]{}); }); auto const client_code = [&] { MirConnection* connection = nullptr; MirSurface* surface = nullptr; client_connect.exec([&] { connection = mir_connect_sync(mir_test_socket, __PRETTY_FUNCTION__); surface = mtf::make_any_surface(connection); }); client_release.exec([&] { // We would normally explicitly release the surface at this // point. However, because we have been filling the server // send socket buffer, releasing the surface may cause the // server to try to write to a full socket buffer when // responding, leading the server to believe that the client // is blocked, and causing a premature client disconnection. mir_connection_release(connection); }); }; auto client_process = new_client_process(client_code); if (is_test_process()) { client_connect(); kill(client_pid(), SIGSTOP); try { server_send_events(std::chrono::seconds{10}); } catch(...) { ADD_FAILURE() << "Server blocked while sending events"; } kill(client_pid(), SIGCONT); client_release(); server_finish(); auto const result = client_process->wait_for_termination(); EXPECT_THAT(result.exit_code, testing::Eq(EXIT_SUCCESS)); } }