Mir

Merge lp:~afrantzis/mir/client-lifecycle-terminate-properly into lp:mir

Proposed by Alexandros Frantzis
Status: Work in progress
Proposed branch: lp:~afrantzis/mir/client-lifecycle-terminate-properly
Merge into: lp:mir
Diff against target: 653 lines (+169/-111)
16 files modified
include/test/mir_test_framework/basic_client_server_fixture.h (+2/-0)
include/test/mir_test_framework/display_server_test_fixture.h (+2/-0)
include/test/mir_test_framework/testing_process_manager.h (+3/-2)
src/client/mir_connection.cpp (+6/-1)
tests/acceptance-tests/test_client_input.cpp (+2/-0)
tests/acceptance-tests/test_client_screencast.cpp (+7/-43)
tests/acceptance-tests/test_client_surface_swap_buffers.cpp (+3/-15)
tests/acceptance-tests/test_prompt_session_client_api.cpp (+2/-0)
tests/acceptance-tests/test_server_disconnect.cpp (+60/-0)
tests/acceptance-tests/test_server_shutdown.cpp (+2/-0)
tests/acceptance-tests/test_stale_frames.cpp (+0/-2)
tests/integration-tests/shell/test_session_lifecycle_event.cpp (+37/-48)
tests/mir_test_framework/display_server_test_fixture.cpp (+5/-0)
tests/mir_test_framework/testing_process_manager.cpp (+22/-0)
tests/mir_test_framework/using_stub_client_platform.cpp (+5/-0)
tests/unit-tests/client/test_client_mir_surface.cpp (+11/-0)
To merge this branch: bzr merge lp:~afrantzis/mir/client-lifecycle-terminate-properly
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Mir development team Pending
Review via email: mp+229234@code.launchpad.net

Commit message

client: Fix SIGTERM dispatch in our default lifecycle event handler

Our default lifecycle event handler used to call raise() to send a TERM signal to the app when a connection break was detected. However, in a multi-threaded program raise() sends the signal to the current thread only. If the signal is blocked in that thread, then the signal is lost.

Depending on thread in which we detected that the connection was lost, the TERM signal would be dispatched (e.g. in the context of a driver callback asking for the next buffer) or not (e.g. in the context of our main RPC threads which block all signals). This MP fixes the issue by explicitly sending the signal to the process instead of the current thread. This ensures that it will be dispatched to some thread that doesn't block it.

Description of the change

client: Fix SIGTERM dispatch in our default lifecycle event handler

Our default lifecycle event handler used to call raise() to send a TERM signal to the app when a connection break was detected. However, in a multi-threaded program raise() sends the signal to the current thread only. If the signal is blocked in that thread, then the signal is lost.

Depending on thread in which we detected that the connection was lost, the TERM signal would be dispatched (e.g. in the context of a driver callback asking for the next buffer) or not (e.g. in the context of our main RPC threads which block all signals). This MP fixes the issue by explicitly sending the signal to the process instead of the current thread. This ensures that it will be dispatched to some thread that doesn't block it.

It turns out that we send a lifecycle connection lost event to ourselves when we release a client connection. With the signal dispatch issue fixed, this always leads to a SIGTERM being sent to the process when we call mir_connection_release() (with the default handler). This breaks most of the tests, since clients are expected to exit properly, not be terminated by a signal.

I assumed that sending a lifecycle event on release is a behavior we want, i.e. it's not accidental. If it's indeed accidental, we can remove it, along with the workaround in this MP.

The workaround proposed in this MP is for our stub client platform (used in almost all the tests that use full clients) to clear any lifecycle handlers just prior to disconnecting. This has the benefit that the default handler is active for the lifetime of the client and can therefore catch premature disconnections. It's not ideal, but it's reasonable for now (IMO).

As part of the workaround I refactored some of the test code to use newer infrastructure (like BasicClientServerFixture). However these refactorings are beneficial on their own and can remain even if we decide not to use the proposed workaround.

Finally, this change fixes some instances of the "client spinning when the server dies" issue, which is especially pronounced if we apply https://code.launchpad.net/~afrantzis/mir/fix-1347053/+merge/229221, since we won't abort() in driver code any more.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

1811. By Alexandros Frantzis

client: Fix SIGTERM dispatch in our default lifecycle event handler

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/test/mir_test_framework/basic_client_server_fixture.h'
--- include/test/mir_test_framework/basic_client_server_fixture.h 2014-05-20 10:31:58 +0000
+++ include/test/mir_test_framework/basic_client_server_fixture.h 2014-08-01 13:50:17 +0000
@@ -22,6 +22,7 @@
22#include "mir_toolkit/mir_client_library.h"22#include "mir_toolkit/mir_client_library.h"
2323
24#include "mir_test_framework/in_process_server.h"24#include "mir_test_framework/in_process_server.h"
25#include "mir_test_framework/using_stub_client_platform.h"
2526
26namespace mir_test_framework27namespace mir_test_framework
27{28{
@@ -31,6 +32,7 @@
31struct BasicClientServerFixture : InProcessServer32struct BasicClientServerFixture : InProcessServer
32{33{
33 TestServerConfiguration server_configuration;34 TestServerConfiguration server_configuration;
35 UsingStubClientPlatform using_stub_client_platform;
3436
35 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }37 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }
3638
3739
=== modified file 'include/test/mir_test_framework/display_server_test_fixture.h'
--- include/test/mir_test_framework/display_server_test_fixture.h 2014-04-10 22:23:27 +0000
+++ include/test/mir_test_framework/display_server_test_fixture.h 2014-08-01 13:50:17 +0000
@@ -26,6 +26,7 @@
2626
27#include <memory>27#include <memory>
28#include <functional>28#include <functional>
29#include <vector>
2930
30namespace mir_test_framework31namespace mir_test_framework
31{32{
@@ -65,6 +66,7 @@
6566
66 bool shutdown_server_process();67 bool shutdown_server_process();
67 Result wait_for_shutdown_server_process();68 Result wait_for_shutdown_server_process();
69 std::vector<Result> wait_for_shutdown_client_processes();
68 bool kill_server_process();70 bool kill_server_process();
69 void kill_client_processes();71 void kill_client_processes();
70 void terminate_client_processes();72 void terminate_client_processes();
7173
=== modified file 'include/test/mir_test_framework/testing_process_manager.h'
--- include/test/mir_test_framework/testing_process_manager.h 2014-04-10 22:23:27 +0000
+++ include/test/mir_test_framework/testing_process_manager.h 2014-08-01 13:50:17 +0000
@@ -27,7 +27,7 @@
27#include "mir_test_framework/testing_client_configuration.h"27#include "mir_test_framework/testing_client_configuration.h"
2828
29#include <memory>29#include <memory>
30#include <list>30#include <vector>
31#include <functional>31#include <functional>
3232
33namespace mir33namespace mir
@@ -60,13 +60,14 @@
60 Result shutdown_server_process();60 Result shutdown_server_process();
61 Result kill_server_process();61 Result kill_server_process();
62 Result wait_for_shutdown_server_process();62 Result wait_for_shutdown_server_process();
63 std::vector<Result> wait_for_shutdown_client_processes();
63 void kill_client_processes();64 void kill_client_processes();
64 void terminate_client_processes();65 void terminate_client_processes();
65 void run_in_test_process(std::function<void()> const& run_code);66 void run_in_test_process(std::function<void()> const& run_code);
6667
67private:68private:
68 std::shared_ptr<Process> server_process;69 std::shared_ptr<Process> server_process;
69 std::list<std::shared_ptr<Process>> clients;70 std::vector<std::shared_ptr<Process>> clients;
7071
71 bool is_test_process;72 bool is_test_process;
72 bool server_process_was_started;73 bool server_process_was_started;
7374
=== modified file 'src/client/mir_connection.cpp'
--- src/client/mir_connection.cpp 2014-07-17 11:05:42 +0000
+++ src/client/mir_connection.cpp 2014-08-01 13:50:17 +0000
@@ -241,7 +241,12 @@
241{241{
242 if (transition == mir_lifecycle_connection_lost)242 if (transition == mir_lifecycle_connection_lost)
243 {243 {
244 raise(SIGTERM);244 /*
245 * We need to use kill() instead of raise() to ensure the signal
246 * is dispatched to the process even if it's blocked in the current
247 * thread.
248 */
249 kill(getpid(), SIGTERM);
245 }250 }
246}251}
247}252}
248253
=== modified file 'tests/acceptance-tests/test_client_input.cpp'
--- tests/acceptance-tests/test_client_input.cpp 2014-06-26 16:03:00 +0000
+++ tests/acceptance-tests/test_client_input.cpp 2014-08-01 13:50:17 +0000
@@ -32,6 +32,7 @@
32#include "mir_test_framework/input_testing_server_configuration.h"32#include "mir_test_framework/input_testing_server_configuration.h"
33#include "mir_test_framework/input_testing_client_configuration.h"33#include "mir_test_framework/input_testing_client_configuration.h"
34#include "mir_test_framework/declarative_placement_strategy.h"34#include "mir_test_framework/declarative_placement_strategy.h"
35#include "mir_test_framework/using_stub_client_platform.h"
3536
36#include <gtest/gtest.h>37#include <gtest/gtest.h>
37#include <gmock/gmock.h>38#include <gmock/gmock.h>
@@ -120,6 +121,7 @@
120 mt::Barrier fence{2};121 mt::Barrier fence{2};
121 mt::WaitCondition second_client_done;122 mt::WaitCondition second_client_done;
122 ServerConfiguration server_configuration{fence};123 ServerConfiguration server_configuration{fence};
124 mtf::UsingStubClientPlatform using_stub_client_platform;
123125
124 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }126 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }
125127
126128
=== modified file 'tests/acceptance-tests/test_client_screencast.cpp'
--- tests/acceptance-tests/test_client_screencast.cpp 2014-06-02 17:07:02 +0000
+++ tests/acceptance-tests/test_client_screencast.cpp 2014-08-01 13:50:17 +0000
@@ -22,8 +22,7 @@
22#include "mir_toolkit/mir_client_library.h"22#include "mir_toolkit/mir_client_library.h"
2323
24#include "mir_test_framework/stubbed_server_configuration.h"24#include "mir_test_framework/stubbed_server_configuration.h"
25#include "mir_test_framework/in_process_server.h"25#include "mir_test_framework/basic_client_server_fixture.h"
26#include "mir_test_framework/using_stub_client_platform.h"
2726
28#include "mir_test_doubles/null_display_changer.h"27#include "mir_test_doubles/null_display_changer.h"
29#include "mir_test_doubles/stub_display_configuration.h"28#include "mir_test_doubles/stub_display_configuration.h"
@@ -84,15 +83,10 @@
84 mtd::MockScreencast mock_screencast;83 mtd::MockScreencast mock_screencast;
85};84};
8685
87class MirScreencastTest : public mir_test_framework::InProcessServer86struct MirScreencastTest : mtf::BasicClientServerFixture<StubServerConfig>
88{87{
89public:88 mtd::MockScreencast& mock_screencast() { return server_configuration.mock_screencast; }
90 mir::DefaultServerConfiguration& server_config() override { return server_config_; }89
91
92 mtd::MockScreencast& mock_screencast() { return server_config_.mock_screencast; }
93
94 StubServerConfig server_config_;
95 mtf::UsingStubClientPlatform using_stub_client_platform;
96 MirScreencastParameters default_screencast_params {90 MirScreencastParameters default_screencast_params {
97 {0, 0, 1, 1}, 1, 1, mir_pixel_format_abgr_8888};91 {0, 0, 1, 1}, 1, 1, mir_pixel_format_abgr_8888};
98};92};
@@ -111,9 +105,6 @@
111{105{
112 using namespace testing;106 using namespace testing;
113107
114 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
115 ASSERT_TRUE(mir_connection_is_valid(connection));
116
117 mf::ScreencastSessionId const screencast_session_id{99};108 mf::ScreencastSessionId const screencast_session_id{99};
118109
119 InSequence seq;110 InSequence seq;
@@ -130,17 +121,12 @@
130 auto screencast = mir_connection_create_screencast_sync(connection, &default_screencast_params);121 auto screencast = mir_connection_create_screencast_sync(connection, &default_screencast_params);
131 ASSERT_NE(nullptr, screencast);122 ASSERT_NE(nullptr, screencast);
132 mir_screencast_release_sync(screencast);123 mir_screencast_release_sync(screencast);
133
134 mir_connection_release(connection);
135}124}
136125
137TEST_F(MirScreencastTest, contacts_server_screencast_with_provided_params)126TEST_F(MirScreencastTest, contacts_server_screencast_with_provided_params)
138{127{
139 using namespace testing;128 using namespace testing;
140129
141 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
142 ASSERT_TRUE(mir_connection_is_valid(connection));
143
144 mf::ScreencastSessionId const screencast_session_id{99};130 mf::ScreencastSessionId const screencast_session_id{99};
145131
146 geom::Size const size{default_screencast_params.width, default_screencast_params.height};132 geom::Size const size{default_screencast_params.width, default_screencast_params.height};
@@ -164,17 +150,12 @@
164 ASSERT_NE(nullptr, screencast);150 ASSERT_NE(nullptr, screencast);
165151
166 mir_screencast_release_sync(screencast);152 mir_screencast_release_sync(screencast);
167
168 mir_connection_release(connection);
169}153}
170154
171TEST_F(MirScreencastTest, creation_with_invalid_params_fails)155TEST_F(MirScreencastTest, creation_with_invalid_params_fails)
172{156{
173 using namespace testing;157 using namespace testing;
174158
175 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
176 ASSERT_TRUE(mir_connection_is_valid(connection));
177
178 MirScreencastParameters params = default_screencast_params;159 MirScreencastParameters params = default_screencast_params;
179 params.width = params.height = 0;160 params.width = params.height = 0;
180 auto screencast = mir_connection_create_screencast_sync(connection, &params);161 auto screencast = mir_connection_create_screencast_sync(connection, &params);
@@ -190,17 +171,12 @@
190171
191 screencast = mir_connection_create_screencast_sync(connection, &params);172 screencast = mir_connection_create_screencast_sync(connection, &params);
192 ASSERT_EQ(nullptr, screencast);173 ASSERT_EQ(nullptr, screencast);
193
194 mir_connection_release(connection);
195}174}
196175
197TEST_F(MirScreencastTest, gets_valid_egl_native_window)176TEST_F(MirScreencastTest, gets_valid_egl_native_window)
198{177{
199 using namespace testing;178 using namespace testing;
200179
201 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
202 ASSERT_TRUE(mir_connection_is_valid(connection));
203
204 mf::ScreencastSessionId const screencast_session_id{99};180 mf::ScreencastSessionId const screencast_session_id{99};
205181
206 InSequence seq;182 InSequence seq;
@@ -217,24 +193,17 @@
217 EXPECT_NE(MirEGLNativeWindowType(), egl_native_window);193 EXPECT_NE(MirEGLNativeWindowType(), egl_native_window);
218194
219 mir_screencast_release_sync(screencast);195 mir_screencast_release_sync(screencast);
220
221 mir_connection_release(connection);
222}196}
223197
224TEST_F(MirScreencastTest, fails_on_client_when_server_request_fails)198TEST_F(MirScreencastTest, fails_on_client_when_server_request_fails)
225{199{
226 using namespace testing;200 using namespace testing;
227201
228 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
229 ASSERT_TRUE(mir_connection_is_valid(connection));
230
231 EXPECT_CALL(mock_screencast(), create_session(_, _, _))202 EXPECT_CALL(mock_screencast(), create_session(_, _, _))
232 .WillOnce(Throw(std::runtime_error("")));203 .WillOnce(Throw(std::runtime_error("")));
233204
234 auto screencast = mir_connection_create_screencast_sync(connection, &default_screencast_params);205 auto screencast = mir_connection_create_screencast_sync(connection, &default_screencast_params);
235 ASSERT_EQ(nullptr, screencast);206 ASSERT_EQ(nullptr, screencast);
236
237 mir_connection_release(connection);
238}207}
239208
240namespace209namespace
@@ -255,15 +224,10 @@
255 MockSessionAuthorizer mock_authorizer;224 MockSessionAuthorizer mock_authorizer;
256};225};
257226
258class UnauthorizedMirScreencastTest : public mir_test_framework::InProcessServer227struct UnauthorizedMirScreencastTest : mtf::BasicClientServerFixture<MockAuthorizerServerConfig>
259{228{
260public:229 MockSessionAuthorizer& mock_authorizer() { return server_configuration.mock_authorizer; }
261 mir::DefaultServerConfiguration& server_config() override { return server_config_; }230
262
263 MockSessionAuthorizer& mock_authorizer() { return server_config_.mock_authorizer; }
264
265 MockAuthorizerServerConfig server_config_;
266 mtf::UsingStubClientPlatform using_stub_client_platform;
267 MirScreencastParameters default_screencast_params {231 MirScreencastParameters default_screencast_params {
268 {0, 0, 1, 1}, 1, 1, mir_pixel_format_abgr_8888};232 {0, 0, 1, 1}, 1, 1, mir_pixel_format_abgr_8888};
269};233};
270234
=== modified file 'tests/acceptance-tests/test_client_surface_swap_buffers.cpp'
--- tests/acceptance-tests/test_client_surface_swap_buffers.cpp 2014-06-09 17:16:32 +0000
+++ tests/acceptance-tests/test_client_surface_swap_buffers.cpp 2014-08-01 13:50:17 +0000
@@ -19,8 +19,7 @@
19#include "mir_toolkit/mir_client_library.h"19#include "mir_toolkit/mir_client_library.h"
2020
21#include "mir_test_framework/stubbed_server_configuration.h"21#include "mir_test_framework/stubbed_server_configuration.h"
22#include "mir_test_framework/in_process_server.h"22#include "mir_test_framework/basic_client_server_fixture.h"
23#include "mir_test_framework/using_stub_client_platform.h"
24#include "mir_test_doubles/null_display_buffer_compositor_factory.h"23#include "mir_test_doubles/null_display_buffer_compositor_factory.h"
25#include "mir_test/signal.h"24#include "mir_test/signal.h"
2625
@@ -43,30 +42,20 @@
43 }42 }
44};43};
4544
46class MirSurfaceSwapBuffersTest : public mir_test_framework::InProcessServer
47{
48public:
49 mir::DefaultServerConfiguration& server_config() override { return server_config_; }
50
51 StubServerConfig server_config_;
52 mtf::UsingStubClientPlatform using_stub_client_platform;
53};
54
55void swap_buffers_callback(MirSurface*, void* ctx)45void swap_buffers_callback(MirSurface*, void* ctx)
56{46{
57 auto buffers_swapped = static_cast<mt::Signal*>(ctx);47 auto buffers_swapped = static_cast<mt::Signal*>(ctx);
58 buffers_swapped->raise();48 buffers_swapped->raise();
59}49}
6050
51using MirSurfaceSwapBuffersTest = mtf::BasicClientServerFixture<StubServerConfig>;
52
61}53}
6254
63TEST_F(MirSurfaceSwapBuffersTest, swap_buffers_does_not_block_when_surface_is_not_composited)55TEST_F(MirSurfaceSwapBuffersTest, swap_buffers_does_not_block_when_surface_is_not_composited)
64{56{
65 using namespace testing;57 using namespace testing;
6658
67 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
68 ASSERT_TRUE(mir_connection_is_valid(connection));
69
70 MirSurfaceParameters request_params =59 MirSurfaceParameters request_params =
71 {60 {
72 __PRETTY_FUNCTION__,61 __PRETTY_FUNCTION__,
@@ -93,5 +82,4 @@
93 }82 }
9483
95 mir_surface_release_sync(surface);84 mir_surface_release_sync(surface);
96 mir_connection_release(connection);
97}85}
9886
=== modified file 'tests/acceptance-tests/test_prompt_session_client_api.cpp'
--- tests/acceptance-tests/test_prompt_session_client_api.cpp 2014-07-21 03:35:31 +0000
+++ tests/acceptance-tests/test_prompt_session_client_api.cpp 2014-08-01 13:50:17 +0000
@@ -27,6 +27,7 @@
27#include "mir_test_doubles/stub_session_authorizer.h"27#include "mir_test_doubles/stub_session_authorizer.h"
28#include "mir_test_framework/stubbed_server_configuration.h"28#include "mir_test_framework/stubbed_server_configuration.h"
29#include "mir_test_framework/in_process_server.h"29#include "mir_test_framework/in_process_server.h"
30#include "mir_test_framework/using_stub_client_platform.h"
30#include "mir_test/popen.h"31#include "mir_test/popen.h"
3132
32#include <gtest/gtest.h>33#include <gtest/gtest.h>
@@ -140,6 +141,7 @@
140 std::shared_ptr<mf::Session> application_session;141 std::shared_ptr<mf::Session> application_session;
141142
142 std::shared_ptr<ms::PromptSession> server_prompt_session;143 std::shared_ptr<ms::PromptSession> server_prompt_session;
144 mtf::UsingStubClientPlatform using_stub_client_platform;
143145
144 void SetUp() override146 void SetUp() override
145 {147 {
146148
=== modified file 'tests/acceptance-tests/test_server_disconnect.cpp'
--- tests/acceptance-tests/test_server_disconnect.cpp 2014-03-26 05:48:59 +0000
+++ tests/acceptance-tests/test_server_disconnect.cpp 2014-08-01 13:50:17 +0000
@@ -130,6 +130,40 @@
130 mt::CrossProcessAction configure_display;130 mt::CrossProcessAction configure_display;
131 mt::CrossProcessAction disconnect;131 mt::CrossProcessAction disconnect;
132};132};
133
134/*
135 * This client will self-terminate on server connection break (through the default
136 * lifecycle handler).
137 */
138struct TerminatingTestingClientConfiguration : mtf::TestingClientConfiguration
139{
140 void exec() override
141 {
142 MirConnection* connection{nullptr};
143
144 connect.exec([&] {
145 connection = mir_connect_sync(mtf::test_socket_file().c_str() , __PRETTY_FUNCTION__);
146 EXPECT_TRUE(mir_connection_is_valid(connection));
147 });
148
149 create_surface_sync.wait_for_signal_ready_for();
150
151 MirSurfaceParameters const parameters =
152 {
153 __PRETTY_FUNCTION__,
154 1, 1,
155 mir_pixel_format_abgr_8888,
156 mir_buffer_usage_hardware,
157 mir_display_output_id_invalid
158 };
159 mir_connection_create_surface_sync(connection, &parameters);
160
161 mir_connection_release(connection);
162 }
163
164 mt::CrossProcessAction connect;
165 mtf::CrossProcessSync create_surface_sync;
166};
133}167}
134168
135TEST_F(ServerDisconnect, client_detects_server_shutdown)169TEST_F(ServerDisconnect, client_detects_server_shutdown)
@@ -168,3 +202,29 @@
168 client_config.disconnect();202 client_config.disconnect();
169 });203 });
170}204}
205
206TEST_F(ServerDisconnect, causes_client_to_terminate_by_default)
207{
208 TestingServerConfiguration server_config;
209 launch_server_process(server_config);
210
211 TerminatingTestingClientConfiguration client_config;
212 launch_client_process(client_config);
213
214 run_in_test_process([this, &client_config]
215 {
216 client_config.connect();
217 shutdown_server_process();
218
219 /*
220 * While trying to create a surface the connection break will be detected
221 * and the client should self-terminate.
222 */
223 client_config.create_surface_sync.signal_ready();
224
225 auto client_results = wait_for_shutdown_client_processes();
226 ASSERT_EQ(1, client_results.size());
227 EXPECT_EQ(mtf::TerminationReason::child_terminated_by_signal,
228 client_results[0].reason);
229 });
230}
171231
=== modified file 'tests/acceptance-tests/test_server_shutdown.cpp'
--- tests/acceptance-tests/test_server_shutdown.cpp 2014-07-21 03:35:31 +0000
+++ tests/acceptance-tests/test_server_shutdown.cpp 2014-08-01 13:50:17 +0000
@@ -327,6 +327,8 @@
327327
328 /* Notify the clients that we are done (we only need to set the flag once) */328 /* Notify the clients that we are done (we only need to set the flag once) */
329 server_done.set();329 server_done.set();
330
331 wait_for_shutdown_client_processes();
330 });332 });
331333
332 /*334 /*
333335
=== modified file 'tests/acceptance-tests/test_stale_frames.cpp'
--- tests/acceptance-tests/test_stale_frames.cpp 2014-07-25 10:02:18 +0000
+++ tests/acceptance-tests/test_stale_frames.cpp 2014-08-01 13:50:17 +0000
@@ -25,7 +25,6 @@
25#include "mir/graphics/buffer.h"25#include "mir/graphics/buffer.h"
26#include "mir/graphics/buffer_id.h"26#include "mir/graphics/buffer_id.h"
2727
28#include "mir_test_framework/using_stub_client_platform.h"
29#include "mir_test_framework/stubbed_server_configuration.h"28#include "mir_test_framework/stubbed_server_configuration.h"
30#include "mir_test_framework/basic_client_server_fixture.h"29#include "mir_test_framework/basic_client_server_fixture.h"
31#include "mir_test_doubles/stub_renderer.h"30#include "mir_test_doubles/stub_renderer.h"
@@ -180,7 +179,6 @@
180 }179 }
181180
182 MirSurface* surface;181 MirSurface* surface;
183 mtf::UsingStubClientPlatform using_stub_client_platform;
184};182};
185183
186}184}
187185
=== modified file 'tests/integration-tests/shell/test_session_lifecycle_event.cpp'
--- tests/integration-tests/shell/test_session_lifecycle_event.cpp 2014-07-21 03:35:31 +0000
+++ tests/integration-tests/shell/test_session_lifecycle_event.cpp 2014-08-01 13:50:17 +0000
@@ -19,82 +19,71 @@
19#include "mir/scene/null_session_listener.h"19#include "mir/scene/null_session_listener.h"
20#include "src/server/scene/application_session.h"20#include "src/server/scene/application_session.h"
2121
22#include "mir_test_framework/display_server_test_fixture.h"22#include "mir_test_framework/stubbed_server_configuration.h"
23#include "mir_test_framework/basic_client_server_fixture.h"
24#include "mir_test_framework/in_process_server.h"
2325
24#include "mir_toolkit/mir_client_library.h"26#include "mir_toolkit/mir_client_library.h"
2527
26#include <gtest/gtest.h>28#include <gtest/gtest.h>
27#include <gmock/gmock.h>29#include <gmock/gmock.h>
2830
29#include <thread>
30#include <unistd.h>
31#include <fcntl.h>
32
33namespace ms = mir::scene;31namespace ms = mir::scene;
34namespace msh = mir::shell;
35namespace mtf = mir_test_framework;32namespace mtf = mir_test_framework;
3633
37namespace34namespace
38{35{
39char const* const mir_test_socket = mtf::test_socket_file().c_str();
4036
41struct MockStateHandler37struct MockStateHandler
42{38{
43 MOCK_METHOD1(state_changed, void (MirLifecycleState));39 MOCK_METHOD1(state_changed, void (MirLifecycleState));
44};40};
4541
42void lifecycle_callback(MirConnection* /*connection*/, MirLifecycleState state, void* context)
43{
44 auto handler = static_cast<MockStateHandler*>(context);
45 handler->state_changed(state);
46}
47
46class StubSessionListener : public ms::NullSessionListener48class StubSessionListener : public ms::NullSessionListener
47{49{
48 void stopping(std::shared_ptr<ms::Session> const& session)50 void stopping(std::shared_ptr<ms::Session> const& session)
49 {51 {
50 std::shared_ptr<ms::ApplicationSession> app_session(52 auto const app_session = std::static_pointer_cast<ms::ApplicationSession>(session);
51 std::static_pointer_cast<ms::ApplicationSession>(session)
52 );
5353
54 app_session->set_lifecycle_state(mir_lifecycle_state_will_suspend);54 app_session->set_lifecycle_state(mir_lifecycle_state_will_suspend);
55 }55 }
56};56};
5757
58using LifecycleEventTest = BespokeDisplayServerTestFixture;58struct StubServerConfig : mtf::StubbedServerConfiguration
59{
60 std::shared_ptr<ms::SessionListener> the_session_listener() override
61 {
62 return std::make_shared<StubSessionListener>();
63 }
64};
65
66struct LifecycleEventTest : mtf::InProcessServer
67{
68 StubServerConfig server_configuration;
69
70 mir::DefaultServerConfiguration& server_config() override
71 { return server_configuration; }
72};
73
74}
75
59TEST_F(LifecycleEventTest, lifecycle_event_test)76TEST_F(LifecycleEventTest, lifecycle_event_test)
60{77{
61 using namespace ::testing;78 using namespace ::testing;
6279
63 struct ServerConfig : TestingServerConfiguration80 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
64 {81
65 std::shared_ptr<ms::SessionListener> the_session_listener() override82 auto const handler = std::make_shared<MockStateHandler>();
66 {83 mir_connection_set_lifecycle_event_callback(connection, lifecycle_callback, handler.get());
67 return std::make_shared<StubSessionListener>();84
68 }85 EXPECT_CALL(*handler, state_changed(Eq(mir_lifecycle_state_will_suspend))).Times(1);
69 } server_config;86 EXPECT_CALL(*handler, state_changed(Eq(mir_lifecycle_connection_lost))).Times(AtMost(1));
7087
71 launch_server_process(server_config);88 mir_connection_release(connection);
72
73 struct ClientConfig : TestingClientConfiguration
74 {
75 static void lifecycle_callback(MirConnection* /*connection*/, MirLifecycleState state, void* context)
76 {
77 auto config = static_cast<ClientConfig*>(context);
78 config->handler->state_changed(state);
79 }
80
81 void exec()
82 {
83 handler = std::make_shared<MockStateHandler>();
84
85 MirConnection* connection = mir_connect_sync(mir_test_socket, "testapp");
86 mir_connection_set_lifecycle_event_callback(connection, lifecycle_callback, this);
87
88 EXPECT_CALL(*handler, state_changed(Eq(mir_lifecycle_state_will_suspend))).Times(1);
89 EXPECT_CALL(*handler, state_changed(Eq(mir_lifecycle_connection_lost))).Times(AtMost(1));
90 mir_connection_release(connection);
91
92 handler.reset();
93 }
94
95 std::shared_ptr<MockStateHandler> handler;
96 } client_config;
97
98 launch_client_process(client_config);
99}
100}89}
10190
=== modified file 'tests/mir_test_framework/display_server_test_fixture.cpp'
--- tests/mir_test_framework/display_server_test_fixture.cpp 2014-04-10 22:23:27 +0000
+++ tests/mir_test_framework/display_server_test_fixture.cpp 2014-08-01 13:50:17 +0000
@@ -87,6 +87,11 @@
87 return process_manager.wait_for_shutdown_server_process();87 return process_manager.wait_for_shutdown_server_process();
88}88}
8989
90std::vector<mtf::Result> BespokeDisplayServerTestFixture::wait_for_shutdown_client_processes()
91{
92 return process_manager.wait_for_shutdown_client_processes();
93}
94
90void BespokeDisplayServerTestFixture::terminate_client_processes()95void BespokeDisplayServerTestFixture::terminate_client_processes()
91{96{
92 process_manager.terminate_client_processes();97 process_manager.terminate_client_processes();
9398
=== modified file 'tests/mir_test_framework/testing_process_manager.cpp'
--- tests/mir_test_framework/testing_process_manager.cpp 2014-04-10 22:23:27 +0000
+++ tests/mir_test_framework/testing_process_manager.cpp 2014-08-01 13:50:17 +0000
@@ -203,6 +203,28 @@
203 return result;203 return result;
204}204}
205205
206std::vector<mtf::Result> mtf::TestingProcessManager::wait_for_shutdown_client_processes()
207{
208 std::vector<Result> results;
209
210 if (!clients.empty())
211 {
212 for (auto client : clients)
213 results.push_back(client->wait_for_termination());
214
215 clients.clear();
216 }
217 else
218 {
219 Result result;
220 result.reason = TerminationReason::child_terminated_normally;
221 result.exit_code = EXIT_SUCCESS;
222 results.push_back(result);
223 }
224
225 return results;
226}
227
206void mtf::TestingProcessManager::terminate_client_processes()228void mtf::TestingProcessManager::terminate_client_processes()
207{229{
208 if (is_test_process)230 if (is_test_process)
209231
=== modified file 'tests/mir_test_framework/using_stub_client_platform.cpp'
--- tests/mir_test_framework/using_stub_client_platform.cpp 2014-07-29 10:25:43 +0000
+++ tests/mir_test_framework/using_stub_client_platform.cpp 2014-08-01 13:50:17 +0000
@@ -27,6 +27,10 @@
27namespace27namespace
28{28{
2929
30void null_lifecycle_callback(MirConnection*, MirLifecycleState, void*)
31{
32}
33
30MirWaitHandle* mir_connect_override(34MirWaitHandle* mir_connect_override(
31 char const *socket_file,35 char const *socket_file,
32 char const *app_name,36 char const *app_name,
@@ -42,6 +46,7 @@
42{46{
43 try47 try
44 {48 {
49 mir_connection_set_lifecycle_event_callback(connection, null_lifecycle_callback, nullptr);
45 auto wait_handle = connection->disconnect();50 auto wait_handle = connection->disconnect();
46 mir_wait_for(wait_handle);51 mir_wait_for(wait_handle);
47 }52 }
4853
=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
--- tests/unit-tests/client/test_client_mir_surface.cpp 2014-07-21 03:35:31 +0000
+++ tests/unit-tests/client/test_client_mir_surface.cpp 2014-08-01 13:50:17 +0000
@@ -392,6 +392,10 @@
392{392{
393}393}
394394
395void null_lifecycle_callback(MirConnection*, MirLifecycleState, void*)
396{
397}
398
395MATCHER_P(BufferPackageMatches, package, "")399MATCHER_P(BufferPackageMatches, package, "")
396{400{
397 // Can't simply use memcmp() on the whole struct because age is not sent over the wire401 // Can't simply use memcmp() on the whole struct because age is not sent over the wire
@@ -415,6 +419,13 @@
415 connect_to_test_server();419 connect_to_test_server();
416 }420 }
417421
422 ~MirClientSurfaceTest()
423 {
424 // Clear the lifecycle callback in order not to get SIGTERM by the default
425 // lifecycle handler during connection teardown
426 connection->register_lifecycle_event_callback(null_lifecycle_callback, nullptr);
427 }
428
418 void start_test_server()429 void start_test_server()
419 {430 {
420 // In case an earlier test left a stray file431 // In case an earlier test left a stray file

Subscribers

People subscribed via source and target branches