Mir

Merge lp:~alan-griffiths/mir/spike-nested-server-test-fixture into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 1739
Proposed branch: lp:~alan-griffiths/mir/spike-nested-server-test-fixture
Merge into: lp:mir
Diff against target: 447 lines (+128/-146)
6 files modified
include/server/mir/default_server_configuration.h (+5/-1)
src/server/default_server_configuration.cpp (+2/-0)
src/server/graphics/default_configuration.cpp (+14/-5)
src/server/graphics/nested/nested_display.cpp (+0/-4)
src/server/run_mir.cpp (+5/-2)
tests/acceptance-tests/test_nested_mir.cpp (+102/-134)
To merge this branch: bzr merge lp:~alan-griffiths/mir/spike-nested-server-test-fixture
Reviewer Review Type Date Requested Status
Alexandros Frantzis (community) Approve
Kevin DuBois (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Abstain
Review via email: mp+224637@code.launchpad.net

Commit message

tests: rework the "nested" tests so that they can actually be run

Description of the change

tests: rework the "nested" tests so that they can actually be run

We need a *lot* more testing around the nested use cases, but restoring the tests we have is a valid first step.

To post a comment you must log in.
Revision history for this message
Kevin DuBois (kdub) wrote :

commented out code:
232 +// EXPECT_CALL(*this, eglInitialize(_, _, _)).Times(1).WillRepeatedly(
233 +// DoAll(WithArgs<1, 2>(Invoke(this, &NestedMockEGL::egl_initialize)), Return(EGL_TRUE)));

looks good otherwise!

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

@https://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-mako/1884/console
> [ FAILED ] ServerShutdown/OnSignal.removes_endpoint_on_signal/0, where GetParam() = 3
> [ FAILED ] ServerShutdown/OnSignal.removes_endpoint_on_signal/1, where GetParam() = 6
> [ FAILED ] ServerShutdown/OnSignal.removes_endpoint_on_signal/2, where GetParam() = 8
> [ FAILED ] ServerShutdown/OnSignal.removes_endpoint_on_signal/3, where GetParam() = 11
> [ FAILED ] ServerShutdown/OnSignal.removes_endpoint_on_signal/4, where GetParam() = 7

More mako instability?

@https://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-utopic-amd64-ci/530/console
> Start 4: mir_acceptance_tests
> Build timed out (after 240 minutes). Marking the build as failed.

Weird, but we see this intermittently and it isn't obvious that the time went anywhere related.

We'll see what happens after I delete the comment Kevin spotted.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

If running all the acceptance tests (not just the groups that ctests runs) there's an interaction with ServerShutdown/OnSignal.removes_endpoint_on_signal/* (which now hangs/times out)

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> If running all the acceptance tests (not just the groups that ctests runs)
> there's an interaction with
> ServerShutdown/OnSignal.removes_endpoint_on_signal/* (which now hangs/times
> out)

Fixed the immediate problem, but there's still a potential issue with "emergency cleanup" of multiple in-process servers. Will tease out a test case for a future MP.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

"Build timed out (after 60 minutes). Marking the build as failed."

rebuilding

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

okay, lgtm

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

221 struct NestedServerConfiguration : FakeCommandLine, public mir::DefaultServerConfiguration
332 +struct NestedServer : mtf::InProcessServer, HostServerConfiguration

Not a blocker, but inheriting from FakeCommandLine (pre-existing) or from HostServerConfiguration is a convenience that makes little conceptual sense (vs composition), and may create some confusion.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/server/mir/default_server_configuration.h'
2--- include/server/mir/default_server_configuration.h 2014-06-23 17:40:57 +0000
3+++ include/server/mir/default_server_configuration.h 2014-06-27 14:49:35 +0000
4@@ -98,6 +98,7 @@
5 }
6 namespace graphics
7 {
8+class NativePlatform;
9 class Platform;
10 class Display;
11 class BufferInitializer;
12@@ -164,6 +165,7 @@
13 virtual std::shared_ptr<ServerStatusListener> the_server_status_listener();
14 virtual std::shared_ptr<DisplayChanger> the_display_changer();
15 virtual std::shared_ptr<graphics::Platform> the_graphics_platform();
16+ virtual std::shared_ptr<graphics::NativePlatform> the_graphics_native_platform();
17 virtual std::shared_ptr<input::InputConfiguration> the_input_configuration();
18 virtual std::shared_ptr<input::InputDispatcher> the_input_dispatcher();
19 virtual std::shared_ptr<input::InputSender> the_input_sender();
20@@ -331,6 +333,7 @@
21 CachedPtr<shell::InputTargeter> input_targeter;
22 CachedPtr<input::CursorListener> cursor_listener;
23 CachedPtr<graphics::Platform> graphics_platform;
24+ CachedPtr<graphics::NativePlatform> graphics_native_platform;
25 CachedPtr<graphics::BufferInitializer> buffer_initializer;
26 CachedPtr<graphics::GraphicBufferAllocator> buffer_allocator;
27 CachedPtr<graphics::Display> display;
28@@ -367,7 +370,8 @@
29 CachedPtr<compositor::CompositorReport> compositor_report;
30 CachedPtr<logging::Logger> logger;
31 CachedPtr<graphics::DisplayReport> display_report;
32- CachedPtr<time::Clock> clock;
33+ // static to workaround the singleton clock in AsioMainLoop when running multiple servers
34+ static CachedPtr<time::Clock> clock;
35 CachedPtr<MainLoop> main_loop;
36 CachedPtr<ServerStatusListener> server_status_listener;
37 CachedPtr<graphics::DisplayConfigurationPolicy> display_configuration_policy;
38
39=== modified file 'src/server/default_server_configuration.cpp'
40--- src/server/default_server_configuration.cpp 2014-06-17 22:07:15 +0000
41+++ src/server/default_server_configuration.cpp 2014-06-27 14:49:35 +0000
42@@ -147,6 +147,8 @@
43 });
44 }
45
46+mir::CachedPtr<mir::time::Clock> mir::DefaultServerConfiguration::clock;
47+
48 std::shared_ptr<mir::time::Clock> mir::DefaultServerConfiguration::the_clock()
49 {
50 return clock(
51
52=== modified file 'src/server/graphics/default_configuration.cpp'
53--- src/server/graphics/default_configuration.cpp 2014-06-24 21:44:55 +0000
54+++ src/server/graphics/default_configuration.cpp 2014-06-27 14:49:35 +0000
55@@ -70,22 +70,31 @@
56 return graphics_platform(
57 [this]()->std::shared_ptr<mg::Platform>
58 {
59- auto graphics_lib = mir::load_library(the_options()->get<std::string>(options::platform_graphics_lib));
60-
61 if (!the_options()->is_set(options::host_socket_opt))
62 {
63 // fallback to standalone if host socket is unset
64+ auto graphics_lib = mir::load_library(the_options()->get<std::string>(options::platform_graphics_lib));
65 auto create_platform = graphics_lib->load_function<mg::CreatePlatform>("create_platform");
66 return create_platform(the_options(), the_emergency_cleanup(), the_display_report());
67 }
68
69- auto create_native_platform = graphics_lib->load_function<mg::CreateNativePlatform>("create_native_platform");
70-
71 return std::make_shared<mir::graphics::nested::NestedPlatform>(
72 the_host_connection(),
73 the_input_dispatcher(),
74 the_display_report(),
75- create_native_platform(the_display_report()));
76+ the_graphics_native_platform());
77+ });
78+}
79+
80+std::shared_ptr<mg::NativePlatform> mir::DefaultServerConfiguration::the_graphics_native_platform()
81+{
82+ return graphics_native_platform(
83+ [this]()
84+ {
85+ auto graphics_lib = mir::load_library(the_options()->get<std::string>(options::platform_graphics_lib));
86+ auto create_native_platform = graphics_lib->load_function<mg::CreateNativePlatform>("create_native_platform");
87+
88+ return create_native_platform(the_display_report());
89 });
90 }
91
92
93=== modified file 'src/server/graphics/nested/nested_display.cpp'
94--- src/server/graphics/nested/nested_display.cpp 2014-06-02 17:07:02 +0000
95+++ src/server/graphics/nested/nested_display.cpp 2014-06-27 14:49:35 +0000
96@@ -215,10 +215,6 @@
97 });
98 });
99
100- if (result.empty())
101- BOOST_THROW_EXCEPTION(std::runtime_error("Nested Mir needs at least one output for display"));
102-
103-
104 {
105 std::unique_lock<std::mutex> lock(outputs_mutex);
106 outputs.swap(result);
107
108=== modified file 'src/server/run_mir.cpp'
109--- src/server/run_mir.cpp 2014-06-02 17:07:02 +0000
110+++ src/server/run_mir.cpp 2014-06-27 14:49:35 +0000
111@@ -24,6 +24,7 @@
112 #include "mir/raii.h"
113 #include "mir/emergency_cleanup.h"
114
115+#include <atomic>
116 #include <exception>
117 #include <mutex>
118 #include <csignal>
119@@ -82,9 +83,11 @@
120
121 weak_emergency_cleanup = config.the_emergency_cleanup();
122
123+ static std::atomic<unsigned int> concurrent_calls{0};
124+
125 auto const raii = raii::paired_calls(
126- [&]{ for (auto sig : intercepted) old_handler[sig] = signal(sig, fatal_signal_cleanup); },
127- [&]{ for (auto sig : intercepted) signal(sig, old_handler[sig]); });
128+ [&]{ if (!concurrent_calls++) for (auto sig : intercepted) old_handler[sig] = signal(sig, fatal_signal_cleanup); },
129+ [&]{ if (!--concurrent_calls) for (auto sig : intercepted) signal(sig, old_handler[sig]); });
130
131 init(server);
132 server.run();
133
134=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
135--- tests/acceptance-tests/test_nested_mir.cpp 2014-06-11 16:11:32 +0000
136+++ tests/acceptance-tests/test_nested_mir.cpp 2014-06-27 14:49:35 +0000
137@@ -1,5 +1,5 @@
138 /*
139- * Copyright © 2013 Canonical Ltd.
140+ * Copyright © 2013-2014 Canonical Ltd.
141 *
142 * This program is free software: you can redistribute it and/or modify it
143 * under the terms of the GNU General Public License version 3,
144@@ -17,23 +17,21 @@
145 */
146
147 #include "mir/frontend/session_mediator_report.h"
148+#include "mir/graphics/native_platform.h"
149 #include "mir/display_server.h"
150 #include "mir/run_mir.h"
151
152-#include "mir_test_framework/display_server_test_fixture.h"
153-#include "mir_test_doubles/mock_gl.h"
154+#include "mir_test_framework/in_process_server.h"
155+#include "mir_test_framework/stubbed_server_configuration.h"
156+
157 #include "mir_test_doubles/mock_egl.h"
158
159-#ifndef ANDROID
160-#include "mir_test_doubles/mock_gbm.h"
161-#endif
162-
163+#include <gtest/gtest.h>
164 #include <gmock/gmock.h>
165-#include <gtest/gtest.h>
166
167 namespace mf = mir::frontend;
168+namespace mg = mir::graphics;
169 namespace mtf = mir_test_framework;
170-
171 using namespace testing;
172
173 namespace
174@@ -67,7 +65,7 @@
175 void session_error(const std::string&, const char*, const std::string&) override {};
176 };
177
178-struct HostServerConfiguration : public mtf::TestingServerConfiguration
179+struct HostServerConfiguration : mtf::StubbedServerConfiguration
180 {
181 virtual std::shared_ptr<mf::SessionMediatorReport> the_session_mediator_report()
182 {
183@@ -97,13 +95,61 @@
184 }
185 };
186
187+struct NativePlatformAdapter : mg::NativePlatform
188+{
189+ NativePlatformAdapter(std::shared_ptr<mg::Platform> const& adaptee) :
190+ adaptee(adaptee) {}
191+
192+ void initialize(std::shared_ptr<mg::NestedContext> const& /*nested_context*/) override {}
193+
194+ std::shared_ptr<mg::GraphicBufferAllocator> create_buffer_allocator(
195+ std::shared_ptr<mg::BufferInitializer> const& buffer_initializer) override
196+ {
197+ return adaptee->create_buffer_allocator(buffer_initializer);
198+ }
199+
200+ std::shared_ptr<mg::PlatformIPCPackage> get_ipc_package() override
201+ {
202+ return adaptee->get_ipc_package();
203+ }
204+
205+ std::shared_ptr<mg::InternalClient> create_internal_client() override
206+ {
207+ return adaptee->create_internal_client();
208+ }
209+
210+ void fill_buffer_package(
211+ mg::BufferIPCPacker* packer,
212+ mg::Buffer const* buffer,
213+ mg::BufferIpcMsgType msg_type) const override
214+ {
215+ return adaptee->fill_buffer_package(packer, buffer, msg_type);
216+ }
217+
218+ std::shared_ptr<mg::Platform> const adaptee;
219+};
220+
221 struct NestedServerConfiguration : FakeCommandLine, public mir::DefaultServerConfiguration
222 {
223- NestedServerConfiguration(std::string const& host_socket) :
224+ NestedServerConfiguration(
225+ std::string const& host_socket,
226+ std::shared_ptr<mg::Platform> const& graphics_platform) :
227 FakeCommandLine(host_socket),
228- DefaultServerConfiguration(FakeCommandLine::argc, FakeCommandLine::argv)
229- {
230- }
231+ DefaultServerConfiguration(FakeCommandLine::argc, FakeCommandLine::argv),
232+ graphics_platform(graphics_platform)
233+ {
234+ }
235+
236+ std::shared_ptr<mg::NativePlatform> the_graphics_native_platform() override
237+ {
238+ return graphics_native_platform(
239+ [this]() -> std::shared_ptr<mg::NativePlatform>
240+ {
241+ return std::make_shared<NativePlatformAdapter>(graphics_platform);
242+ });
243+ }
244+
245+ std::shared_ptr<mg::Platform> const graphics_platform;
246 };
247
248 struct NestedMockEGL : mir::test::doubles::MockEGL
249@@ -113,13 +159,6 @@
250 {
251 InSequence init_before_terminate;
252 EXPECT_CALL(*this, eglGetDisplay(_)).Times(1);
253-
254- EXPECT_CALL(*this, eglInitialize(_, _, _)).Times(1).WillRepeatedly(
255- DoAll(WithArgs<1, 2>(Invoke(this, &NestedMockEGL::egl_initialize)), Return(EGL_TRUE)));
256-
257- EXPECT_CALL(*this, eglChooseConfig(_, _, _, _, _)).Times(AnyNumber()).WillRepeatedly(
258- DoAll(WithArgs<2, 4>(Invoke(this, &NestedMockEGL::egl_choose_config)), Return(EGL_TRUE)));
259-
260 EXPECT_CALL(*this, eglTerminate(_)).Times(1);
261 }
262
263@@ -127,6 +166,18 @@
264 EXPECT_CALL(*this, eglMakeCurrent(_, _, _, _)).Times(AnyNumber());
265 EXPECT_CALL(*this, eglDestroySurface(_, _)).Times(AnyNumber());
266
267+ EXPECT_CALL(*this, eglQueryString(_, _)).Times(AnyNumber());
268+ ON_CALL(*this, eglQueryString(_,EGL_EXTENSIONS))
269+ .WillByDefault(Return("EGL_KHR_image "
270+ "EGL_KHR_image_base "
271+ "EGL_MESA_drm_image"));
272+
273+ EXPECT_CALL(*this, eglChooseConfig(_, _, _, _, _)).Times(AnyNumber()).WillRepeatedly(
274+ DoAll(WithArgs<2, 4>(Invoke(this, &NestedMockEGL::egl_choose_config)), Return(EGL_TRUE)));
275+
276+ EXPECT_CALL(*this, eglGetCurrentContext()).Times(AnyNumber());
277+ EXPECT_CALL(*this, eglCreatePbufferSurface(_, _, _)).Times(AnyNumber());
278+
279 EXPECT_CALL(*this, eglGetProcAddress(StrEq("eglCreateImageKHR"))).Times(AnyNumber());
280 EXPECT_CALL(*this, eglGetProcAddress(StrEq("eglDestroyImageKHR"))).Times(AnyNumber());
281 EXPECT_CALL(*this, eglGetProcAddress(StrEq("glEGLImageTargetTexture2DOES"))).Times(AnyNumber());
282@@ -147,117 +198,39 @@
283 }
284 };
285
286-struct NestedMockPlatform
287-#ifndef ANDROID
288- : mir::test::doubles::MockGBM
289-#endif
290-{
291- NestedMockPlatform()
292- {
293-#ifndef ANDROID
294- InSequence gbm_device_lifecycle;
295- EXPECT_CALL(*this, gbm_create_device(_)).Times(1);
296- EXPECT_CALL(*this, gbm_device_destroy(_)).Times(1);
297-#endif
298- }
299-};
300-
301-struct NestedMockGL : NiceMock<mir::test::doubles::MockGL>
302-{
303- NestedMockGL() {}
304-};
305-
306-template<class NestedServerConfiguration>
307-struct ClientConfig : mtf::TestingClientConfiguration
308-{
309- ClientConfig(std::string const& host_socket) : host_socket(host_socket) {}
310-
311- std::string const host_socket;
312-
313- void exec() override
314- {
315- try
316- {
317- NestedMockPlatform mock_gbm;
318- NestedMockEGL mock_egl;
319- NestedMockGL mock_gl;
320- NestedServerConfiguration nested_config(host_socket);
321-
322- mir::run_mir(nested_config, [](mir::DisplayServer& server){server.stop();});
323-
324- // TODO - remove FAIL() as we should exit (NB we need logic to cause exit).
325- FAIL();
326- }
327- catch (std::exception const& x)
328- {
329- // TODO - this is only temporary until NestedPlatform is implemented.
330- EXPECT_THAT(x.what(), HasSubstr("Platform::create_buffer_allocator is not implemented yet!"));
331- }
332+struct NestedServer : mtf::InProcessServer, HostServerConfiguration
333+{
334+ NestedMockEGL mock_egl;
335+
336+ virtual mir::DefaultServerConfiguration& server_config()
337+ {
338+ return *this;
339 }
340 };
341 }
342
343-using TestNestedMir = mtf::BespokeDisplayServerTestFixture;
344-
345-// TODO resolve problems running "nested" tests on android and running nested on MESA
346-#ifdef ANDROID
347-#define DISABLED_ON_ANDROID_AND_MESA(name) DISABLED_##name
348-#else
349-#define DISABLED_ON_ANDROID_AND_MESA(name) DISABLED_##name
350-#endif
351-
352-TEST_F(TestNestedMir, DISABLED_ON_ANDROID_AND_MESA(nested_platform_connects_and_disconnects))
353+TEST_F(NestedServer, nested_platform_connects_and_disconnects)
354 {
355- struct MyHostServerConfiguration : HostServerConfiguration
356- {
357- void exec() override
358- {
359- InSequence seq;
360- EXPECT_CALL(*mock_session_mediator_report, session_connect_called(_)).Times(1);
361- EXPECT_CALL(*mock_session_mediator_report, session_disconnect_called(_)).Times(1);
362- }
363- };
364-
365- MyHostServerConfiguration host_config;
366- ClientConfig<NestedServerConfiguration> client_config(host_config.the_socket_file());
367-
368-
369- launch_server_process(host_config);
370- launch_client_process(client_config);
371+ std::string const connection_string{new_connection()};
372+ NestedServerConfiguration nested_config{connection_string, the_graphics_platform()};
373+
374+ InSequence seq;
375+ EXPECT_CALL(*mock_session_mediator_report, session_connect_called(_)).Times(1);
376+ EXPECT_CALL(*mock_session_mediator_report, session_disconnect_called(_)).Times(1);
377+
378+ mir::run_mir(nested_config, [](mir::DisplayServer& server){server.stop();});
379 }
380
381 //////////////////////////////////////////////////////////////////
382-// TODO the following tests were used in investigating lifetime issues.
383-// TODO they may not have much long term value, but decide that later
384-
385-TEST(DisplayLeak, on_exit_display_objects_should_be_destroyed)
386-{
387- struct MyServerConfiguration : mtf::TestingServerConfiguration
388- {
389- std::shared_ptr<mir::graphics::Display> the_display() override
390- {
391- auto const& temp = mtf::TestingServerConfiguration::the_display();
392- my_display = temp;
393- return temp;
394- }
395-
396- std::weak_ptr<mir::graphics::Display> my_display;
397- };
398-
399- MyServerConfiguration host_config;
400-
401- mir::run_mir(host_config, [](mir::DisplayServer& server){server.stop();});
402-
403- EXPECT_FALSE(host_config.my_display.lock()) << "after run_mir() exits the display should be released";
404-}
405-
406-TEST_F(TestNestedMir, DISABLED_ON_ANDROID_AND_MESA(on_exit_display_objects_should_be_destroyed))
407-{
408- struct MyNestedServerConfiguration : NestedServerConfiguration
409- {
410- // TODO clang says "error: inheriting constructors are not supported"
411- // using NestedServerConfiguration::NestedServerConfiguration;
412- MyNestedServerConfiguration(std::string const& host_socket) : NestedServerConfiguration(host_socket) {}
413+// TODO the following test was used in investigating lifetime issues.
414+// TODO it may not have much long term value, but decide that later.
415+TEST_F(NestedServer, on_exit_display_objects_should_be_destroyed)
416+{
417+ std::string const connection_string{new_connection()};
418+
419+ struct MyServerConfiguration : NestedServerConfiguration
420+ {
421+ using NestedServerConfiguration::NestedServerConfiguration;
422
423 std::shared_ptr<mir::graphics::Display> the_display() override
424 {
425@@ -266,17 +239,12 @@
426 return temp;
427 }
428
429- ~MyNestedServerConfiguration()
430- {
431- EXPECT_FALSE(my_display.lock()) << "after run_mir() exits the display should be released";
432- }
433-
434 std::weak_ptr<mir::graphics::Display> my_display;
435 };
436
437- HostServerConfiguration host_config;
438- ClientConfig<MyNestedServerConfiguration> client_config(host_config.the_socket_file());
439-
440- launch_server_process(host_config);
441- launch_client_process(client_config);
442+ MyServerConfiguration config{connection_string, the_graphics_platform()};
443+
444+ mir::run_mir(config, [](mir::DisplayServer& server){server.stop();});
445+
446+ EXPECT_FALSE(config.my_display.lock()) << "after run_mir() exits the display should be released";
447 }

Subscribers

People subscribed via source and target branches