Mir

Merge lp:~afrantzis/mir/fix-or-workaround-1523621 into lp:mir

Proposed by Alexandros Frantzis
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 3769
Proposed branch: lp:~afrantzis/mir/fix-or-workaround-1523621
Merge into: lp:mir
Diff against target: 166 lines (+44/-33)
1 file modified
tests/acceptance-tests/test_nested_mir.cpp (+44/-33)
To merge this branch: bzr merge lp:~afrantzis/mir/fix-or-workaround-1523621
Reviewer Review Type Date Requested Status
Alan Griffiths Approve
Cemil Azizoglu (community) Approve
Mir CI Bot continuous-integration Approve
Review via email: mp+308388@code.launchpad.net

Commit message

tests: Ensure client surface is in a steady state in tests using a nested setup (LP: #1523621)

Description of the change

tests: Ensure client surface is in a steady state in tests using a nested setup

Due to the many layers of asynchronous processing when using a nested setup, it's difficult to guarantee that the client surface will be in a steady state (visible, focused, ready for input etc) when we need it to. We work around this issue by using an implicit test to check for a steady state: we start sending input events from the device, and wait until we start receiving them on the client side. We have already employed this tactic in test_nested_input.cpp.

Note: Very rarely the new code fails, i.e., we never get input events while waiting for the steady state. This is not related to the test itself, but indicates a race somewhere in our infrastructure. In my testing the failure rate is at least two orders of magnitude lower than the current state of the code, so I think it's worth it over what we have now.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3764
https://mir-jenkins.ubuntu.com/job/mir-ci/1974/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2522
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2585
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2577
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2577
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2577
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2551
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2551/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2551
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2551/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2551
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2551/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2551
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2551/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2551
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2551/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2551
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2551/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1974/rebuild

review: Approve (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3765
https://mir-jenkins.ubuntu.com/job/mir-ci/1975/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2524
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2587
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2579
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2579
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2579
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2553
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2553/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2553
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2553/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2553
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2553/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2553
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2553/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2553
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2553/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2553
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2553/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1975/rebuild

review: Approve (continuous-integration)
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Sounds like an improvement to me.

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

OK

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
2--- tests/acceptance-tests/test_nested_mir.cpp 2016-10-12 06:03:15 +0000
3+++ tests/acceptance-tests/test_nested_mir.cpp 2016-10-13 14:31:18 +0000
4@@ -54,6 +54,8 @@
5 #include "mir/test/doubles/nested_mock_egl.h"
6 #include "mir/test/fake_shared.h"
7
8+#include <linux/input.h>
9+#include <atomic>
10 #include <future>
11 #include <gtest/gtest.h>
12 #include <gmock/gmock.h>
13@@ -73,23 +75,6 @@
14
15 namespace
16 {
17-struct InputReadyServerStatusListener : mir::ServerStatusListener
18-{
19- std::shared_ptr<std::promise<void>> const input_ready;
20- InputReadyServerStatusListener(std::shared_ptr<std::promise<void>> const& promise)
21- : input_ready(promise)
22- {}
23-
24- void paused() override {}
25- void resumed() override {}
26- void started() override {}
27- void ready_for_user_input() override
28- {
29- input_ready->set_value();
30- }
31- void stop_receiving_input() override {}
32-};
33-
34 struct MockSessionMediatorReport : mf::SessionMediatorReport
35 {
36 MockSessionMediatorReport()
37@@ -426,21 +411,31 @@
38 { return std::make_shared<NiceMock<MockDisplayConfigurationPolicy>>(); });
39 }
40
41- void wait_until_ready()
42+ void wait_until_surface_ready(MirSurface* surface)
43 {
44- auto future_status = ready_for_input->get_future().wait_for(10s);
45-
46- if (future_status != std::future_status::ready)
47- BOOST_THROW_EXCEPTION(std::runtime_error("Nested Server never started"));
48+ mir_surface_set_event_handler(surface, wait_for_key_a_event, this);
49+
50+ auto const dummy_events_received = mt::spin_wait_for_condition_or_timeout(
51+ [this]
52+ {
53+ if (surface_ready) return true;
54+ fake_input_device->emit_event(
55+ mi::synthesis::a_key_down_event().of_scancode(KEY_A));
56+ fake_input_device->emit_event(
57+ mi::synthesis::a_key_up_event().of_scancode(KEY_A));
58+ return false;
59+ },
60+ std::chrono::seconds{5});
61+
62+ EXPECT_TRUE(dummy_events_received);
63+
64+ mir_surface_set_event_handler(surface, nullptr, nullptr);
65 }
66
67 protected:
68 NestedMirRunner(std::string const& connection_string, bool)
69 : mtf::HeadlessNestedServerRunner(connection_string)
70 {
71- server.override_the_server_status_listener([this]
72- { return std::make_shared<InputReadyServerStatusListener>(ready_for_input); });
73-
74 server.override_the_host_lifecycle_event_listener([this]
75 { return the_mock_host_lifecycle_event_listener(); });
76
77@@ -455,12 +450,27 @@
78 }
79
80 private:
81+ static void wait_for_key_a_event(MirSurface*, MirEvent const* ev, void* context)
82+ {
83+ auto const nmr = static_cast<NestedMirRunner*>(context);
84+ if (mir_event_get_type(ev) == mir_event_type_input)
85+ {
86+ auto const iev = mir_event_get_input_event(ev);
87+ if (mir_input_event_get_type(iev) == mir_input_event_type_key)
88+ {
89+ auto const kev = mir_input_event_get_keyboard_event(iev);
90+ if (mir_keyboard_event_scan_code(kev) == KEY_A)
91+ nmr->surface_ready = true;
92+ }
93+ }
94+ }
95+
96 mir::CachedPtr<MockHostLifecycleEventListener> mock_host_lifecycle_event_listener;
97 mir::CachedPtr<MockDisplayConfigurationPolicy> mock_display_configuration_policy_;
98- std::shared_ptr<std::promise<void>> ready_for_input = std::make_shared<std::promise<void>>();
99- mir::UniqueModulePtr<mtf::FakeInputDevice> fake_device{mtf::add_fake_input_device(mi::InputDeviceInfo{
100+ mir::UniqueModulePtr<mtf::FakeInputDevice> fake_input_device{mtf::add_fake_input_device(mi::InputDeviceInfo{
101 "test-devce", "test-device",
102 mi::DeviceCapability::pointer | mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric})};
103+ std::atomic<bool> surface_ready{false};
104 };
105
106 struct NestedServer : mtf::HeadlessInProcessServer
107@@ -948,12 +958,12 @@
108 NestedMirRunner nested_mir{new_connection()};
109
110 ClientWithAPaintedSurfaceAndABufferStream client(nested_mir);
111+ nested_mir.wait_until_surface_ready(client.surface);
112+
113 auto const mock_cursor = the_mock_cursor();
114
115 server.the_cursor_listener()->cursor_moved_to(489, 9);
116
117- nested_mir.wait_until_ready();
118-
119 // FIXME: In this test setup the software cursor will trigger scene_changed() on show(...).
120 // Thus a new frame will be composed. Then a "FramePostObserver" in basic_surface.cpp will
121 // react to the frame_posted callback by setting the cursor buffer again via show(..)
122@@ -993,12 +1003,12 @@
123 NestedMirRunner nested_mir{new_connection()};
124
125 ClientWithAPaintedSurface client(nested_mir);
126+ nested_mir.wait_until_surface_ready(client.surface);
127
128 server.the_cursor_listener()->cursor_moved_to(489, 9);
129
130- nested_mir.wait_until_ready();
131 // wait for the initial cursor show call..
132- condition.wait_for(long_timeout);
133+ EXPECT_TRUE(condition.wait_for(long_timeout));
134 condition.reset();
135
136 // FIXME: In this test setup the software cursor will trigger scene_changed() on show(...).
137@@ -1035,10 +1045,10 @@
138
139 ClientWithAPaintedSurfaceAndABufferStream client(nested_mir);
140 auto const mock_cursor = the_mock_cursor();
141+ nested_mir.wait_until_surface_ready(client.surface);
142
143 server.the_cursor_listener()->cursor_moved_to(489, 9);
144
145- nested_mir.wait_until_ready();
146 Mock::VerifyAndClearExpectations(mock_cursor.get());
147
148 // FIXME: In this test setup the software cursor will trigger scene_changed() on show(...).
149@@ -1076,6 +1086,7 @@
150 NestedMirRunner nested_mir{new_connection()};
151
152 ClientWithAPaintedSurfaceAndABufferStream client(nested_mir);
153+ nested_mir.wait_until_surface_ready(client.surface);
154 auto const mock_cursor = the_mock_cursor();
155
156 server.the_cursor_listener()->cursor_moved_to(489, 9);
157@@ -1516,8 +1527,8 @@
158 {
159 using namespace std::chrono_literals;
160 NestedMirRunner nested_mir{new_connection()};
161- nested_mir.wait_until_ready();
162 ClientWithAPaintedSurface client(
163 nested_mir, display_geometry.front().size, mir_pixel_format_xbgr_8888);
164+ nested_mir.wait_until_surface_ready(client.surface);
165 EXPECT_TRUE(nested_mir.passthrough_tracker->wait_for_passthrough_frames(1, 5s));
166 }

Subscribers

People subscribed via source and target branches