~ubuntu-branches/ubuntu/vivid/mir/vivid

« back to all changes in this revision

Viewing changes to tests/unit-tests/scene/test_mediating_display_changer.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Daniel van Vugt, Ubuntu daily release
  • Date: 2014-06-03 21:41:02 UTC
  • mfrom: (1.1.62)
  • Revision ID: package-import@ubuntu.com-20140603214102-jh0yoq6xy4x0rwn1
Tags: 0.2.0+14.10.20140603.3-0ubuntu1
[ Daniel van Vugt ]
* New upstream release 0.2.0 (https://launchpad.net/mir/+milestone/0.2.0)
  - mirclient ABI unchanged, still at 7. Clients do not need rebuilding.
  - mirserver ABI bumped to 20. Shells need rebuilding.
    . Cursor::set_image() parameters changed.
    . Display::the_cursor() renamed to Display::create_hardware_cursor()
    . Platform::create_display() requires a new parameter; gl_program_factory
    . Renderable::buffer() no longer accepts any parameter at all. Multi-
      monitor frame sync is guaranteed in other ways now.
    . Scene::generate_renderable_list() renamed to renderable_list_for(id)
      where id is an opaque compositor ID of your choosing.
    . Scene::set_change_callback() replaced by the more generic:
      add_observer() and remove_observer() functions.
    . Added default implementation for SceneObserver.  
    . SessionCreator renamed to ConnectionCreator.
    . ConnectedSessions renamed to Connections.
    . ProtobufSessionCreator renamed to ProtobufConnectionCreator.
    . SessionAuthorizer: pid_t parameters replaced by SessionCredentials.
    . Massive architectural changes to Input-everything.
    . Surface no longer implements Renderable, but emits one via
      compositor_snapshot().
    . Pass the full renderable list to Renderer::render().
    . Graceful handling of exceptions thrown from server threads.
    . Clarify size position interfaces in the Surface classes.
    . Plumbing for trusted sessions.
    . Allow posting and managing custom main-loop actions.
    . Timer extension.
    . Identify client process when client connects to Mir not when socket
      connects.
    . Use the ServerActionQueue for display config.
    . Recomposition signal moved to the MultiThreadedCompositor.
    . Make timer service replaceable.
    . Clarify assumptions about how many buffers a client can fill without
      blocking.
    . Introduce EmergencyCleanup interface.
  - Demo shell enhancements:
    . You can now change graphics modes on the fly using Ctrl+Alt+(-/=).
      To reset to the preferred mode use Ctrl+Alt+0.
    . The above mode changing as well as existing screen rotation keys
      (Ctrl+Alt+arrows) are now per-display; only applied to the monitor
      the mouse pointer is on.
    . New shell controls documented.
  - A new testing category, performance test, was introduced. It currently
    runs glmark2-es2 and compares the result to a minimum threshold. 
  - MIR_VERSION_MINOR is tied to MIRSERVER_ABI in the sense that a change
    in the former now requires dependent projects that a rebuild is 
    necessary.
  - SwitchingBundle was replaced by BufferQueue.
  - Expand credentials to include uid/gid for session authorizer.
  - Bypass control is now Mesa-specific and tied to the command line options.
    So the environment variable MIR_BYPASS has changed to MIR_SERVER_BYPASS.
  - mirscreencast screenshots now produce images with correct color instead
    of transparency.
  - Ongoing architectural changes in the compositor/renderer logic to
    prepare for overlay support, and to reduce locking overhead.
  - Made InputDispatcher replaceable.
  - Progress made on new cursor interfaces with the end goal of client and
    toolkit control of the mouse cursor appearance. More work required.
  - Updated cross-compile docs and scripts to support the latest utopic
    devel images.
  - Replaced uses of android::sp with std::shared_ptr.
  - Client cursor API infrastructure.
  - Enabled eglSwapInternal(0).
  - Make texture caching algorithm reuseable.
  - Add a DPI surface attribute.
  - Exclude arm64 from build.
  - Bugs fixed:
    . Mir doesn't install cleanly if docs are not built. (LP: #1304271)
    . Unity-system-compositor crashed [what(): Failed to set DRM crtc].
      (LP: #1294510)
    . [regression] unity8 fails to load libmirplatformgraphics
      (undefined symbol: _ZN3mir8graphics9GLProgramD1Ev). (LP: #1317200)
    . [regression] unity8 rendering artifacts. (LP: #1317260)
    . [regression] [BufferQueue] 
      BufferQueueTest.compositor_never_owns_client_buffers occasionally
      crashes with: what(): unexpected release: buffer was not given to
      compositor. (LP: #1317801)
    . Hardcoded size for serialization buffers is neither reliable nor
      secure. (LP: #1320187)
    . [regression] [BufferQueue] mir does not composite last client given
      buffer. (LP: #1321861)
    . [regression] stale frame on seen on greeter when screen is unblanked
      and toolkit/apps are laggy/throttled. (LP: #1321886)
    . [regression] [BufferQueue] current_buffer_users vector memory usage
      grows unbounded. (LP: #1317808)
    . Intermittent test failures in 
      CustomInputDispatcherFixture.custom_input_dispatcher_receives_input.
      (LP: #1318587)
    . [regression] [BufferQueue] Race condition in 
      BufferQueue::compositor_acquire could underflow shared_ptr refcount and
      delete prematurely, crash. (LP: #1318632)
    . Overflow in 
      mir::client::rpc::MirSocketRpcChannel::receive_file_descriptors as
      reported by address sanitizer. (LP: #1320821)
    . [regression] [input] Scroll events are now always zero: 
      event.motion.pointer_coordinates[0].vscroll. (LP: #1321077)
    . CI failures in CustomInputDispatcherFixture
      .custom_input_dispatcher_gets_started_and_stopped. (LP: #1321215)
    . [regression] Mir cursor vanishes after switching VTs. (LP: #1323225)
    . Server library links against libmirserverlttng. (LP: #1323317)
    . [DRM/GBM] Killing (or crashing) Mir often leaves the screen blank and
      difficult to recover. (LP: #1189770)
    . Frame rates of GL clients are limited to 60Hz on Android, even with
      swapinterval=0. (LP: #1206400)
    . mir_surface_is_valid(NULL) crashes instead of returning false.
      (LP: #1248474)
    . Mirscreencast outputs translucency instead of shadows, producing
      incorrect images. (LP: #1301210)
    . [regression] tests/unit-tests/shell/test_mediating_display_changer.cpp
      is not compiled and executed. (LP: #1312832)
    . Android platform does not reset the compositionType to HWC_FRAMEBUFFER
      before prepare() on every frame. (LP: #1314399)
    . The client process is identified when the socket connects, not when the
      client connects to Mir. (LP: #1314574)
    . [regression] Clients can't acquire multiple buffers any more.
      (LP: #1315302)
    . [regression] Enabling SwitchingBundleTest 
      DISABLED_synchronous_clients_only_get_two_real_buffers now crashes with
      no usable stack trace. It used to only fail. (LP: #1315312)
    . [regression] [BufferQueue] double-buffered client freezes as no buffer
      is returned on compositor_release. (LP: #1319765)
    . Uninitialized mem in OutputBuilder.hwc_version_11_success.
      (LP: #1312867)
    . [enhancement] In the tests make it possible to get a
      DefaultConfiguration initialized from the command line (LP: #1316987)
    . ci train blocked due to missing arm64 libandroid-properties-dev.
      (LP: #1323504)
[ Ubuntu daily release ]
* New rebuild forced

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2013 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
 
17
 */
 
18
 
 
19
#include "src/server/scene/mediating_display_changer.h"
 
20
#include "src/server/scene/session_container.h"
 
21
#include "mir/graphics/display_configuration_policy.h"
 
22
#include "src/server/scene/broadcasting_session_event_sink.h"
 
23
#include "mir/server_action_queue.h"
 
24
 
 
25
#include "mir_test_doubles/mock_display.h"
 
26
#include "mir_test_doubles/mock_compositor.h"
 
27
#include "mir_test_doubles/null_display_configuration.h"
 
28
#include "mir_test_doubles/stub_display_configuration.h"
 
29
#include "mir_test_doubles/mock_scene_session.h"
 
30
#include "mir_test_doubles/stub_scene_session.h"
 
31
#include "mir_test/fake_shared.h"
 
32
#include "mir_test/display_config_matchers.h"
 
33
 
 
34
#include <mutex>
 
35
 
 
36
#include <gmock/gmock.h>
 
37
#include <gtest/gtest.h>
 
38
 
 
39
namespace mt = mir::test;
 
40
namespace mtd = mir::test::doubles;
 
41
namespace mf = mir::frontend;
 
42
namespace ms = mir::scene;
 
43
namespace mg = mir::graphics;
 
44
 
 
45
namespace
 
46
{
 
47
 
 
48
class MockDisplayConfigurationPolicy : public mg::DisplayConfigurationPolicy
 
49
{
 
50
public:
 
51
    ~MockDisplayConfigurationPolicy() noexcept {}
 
52
    MOCK_METHOD1(apply_to, void(mg::DisplayConfiguration&));
 
53
};
 
54
 
 
55
class StubSessionContainer : public ms::SessionContainer
 
56
{
 
57
public:
 
58
    void insert_session(std::shared_ptr<ms::Session> const& session)
 
59
    {
 
60
        sessions.push_back(session);
 
61
    }
 
62
 
 
63
    void remove_session(std::shared_ptr<ms::Session> const&)
 
64
    {
 
65
    }
 
66
 
 
67
    void for_each(std::function<void(std::shared_ptr<ms::Session> const&)> f) const
 
68
    {
 
69
        for (auto const& session : sessions)
 
70
            f(session);
 
71
    }
 
72
 
 
73
    std::shared_ptr<ms::Session> successor_of(std::shared_ptr<ms::Session> const&) const
 
74
    {
 
75
        return {};
 
76
    }
 
77
 
 
78
private:
 
79
    std::vector<std::shared_ptr<ms::Session>> sessions;
 
80
};
 
81
 
 
82
struct MockDisplay : public mtd::MockDisplay
 
83
{
 
84
    std::unique_ptr<mg::DisplayConfiguration> configuration() const override
 
85
    {
 
86
        conf_ptr = new mtd::StubDisplayConfig{};
 
87
        return std::unique_ptr<mg::DisplayConfiguration>(conf_ptr);
 
88
    }
 
89
 
 
90
    mutable mg::DisplayConfiguration* conf_ptr;
 
91
};
 
92
 
 
93
struct StubServerActionQueue : mir::ServerActionQueue
 
94
{
 
95
    void flush()
 
96
    {
 
97
        std::lock_guard<std::mutex> lock{mutex};
 
98
        for (auto const& action : actions)
 
99
            action();
 
100
        actions.clear();
 
101
    }
 
102
 
 
103
    void enqueue(void const* /*owner*/, mir::ServerAction const& action) override
 
104
    {
 
105
        std::lock_guard<std::mutex> lock{mutex};
 
106
        actions.push_back(action);
 
107
    }
 
108
 
 
109
    void pause_processing_for(void const* /*owner*/) override {}
 
110
    void resume_processing_for(void const* /*owner*/) override {}
 
111
 
 
112
    std::vector<mir::ServerAction> actions;
 
113
    std::mutex mutex;
 
114
};
 
115
 
 
116
struct MockServerActionQueue : mir::ServerActionQueue
 
117
{
 
118
    MOCK_METHOD2(enqueue, void(void const*, mir::ServerAction const&));
 
119
    MOCK_METHOD1(pause_processing_for, void(void const*));
 
120
    MOCK_METHOD1(resume_processing_for, void(void const*));
 
121
};
 
122
 
 
123
struct MediatingDisplayChangerTest : public ::testing::Test
 
124
{
 
125
    MediatingDisplayChangerTest()
 
126
    {
 
127
        using namespace testing;
 
128
 
 
129
        changer = std::make_shared<ms::MediatingDisplayChanger>(
 
130
                      mt::fake_shared(mock_display),
 
131
                      mt::fake_shared(mock_compositor),
 
132
                      mt::fake_shared(mock_conf_policy),
 
133
                      mt::fake_shared(stub_session_container),
 
134
                      mt::fake_shared(session_event_sink),
 
135
                      mt::fake_shared(server_action_queue));
 
136
    }
 
137
 
 
138
    testing::NiceMock<MockDisplay> mock_display;
 
139
    testing::NiceMock<mtd::MockCompositor> mock_compositor;
 
140
    testing::NiceMock<MockDisplayConfigurationPolicy> mock_conf_policy;
 
141
    StubSessionContainer stub_session_container;
 
142
    ms::BroadcastingSessionEventSink session_event_sink;
 
143
    mtd::StubDisplayConfig base_config;
 
144
    StubServerActionQueue server_action_queue;
 
145
    std::shared_ptr<ms::MediatingDisplayChanger> changer;
 
146
};
 
147
 
 
148
}
 
149
 
 
150
TEST_F(MediatingDisplayChangerTest, returns_active_configuration_from_display)
 
151
{
 
152
    using namespace testing;
 
153
 
 
154
    auto returned_conf = changer->active_configuration();
 
155
    EXPECT_EQ(mock_display.conf_ptr, returned_conf.get());
 
156
}
 
157
 
 
158
TEST_F(MediatingDisplayChangerTest, pauses_system_when_applying_new_configuration_for_focused_session)
 
159
{
 
160
    using namespace testing;
 
161
    mtd::NullDisplayConfiguration conf;
 
162
    auto session = std::make_shared<mtd::StubSceneSession>();
 
163
 
 
164
    InSequence s;
 
165
    EXPECT_CALL(mock_compositor, stop());
 
166
 
 
167
    EXPECT_CALL(mock_display, configure(Ref(conf)));
 
168
 
 
169
    EXPECT_CALL(mock_compositor, start());
 
170
 
 
171
    session_event_sink.handle_focus_change(session);
 
172
    changer->configure(session,
 
173
                       mt::fake_shared(conf));
 
174
 
 
175
    server_action_queue.flush();
 
176
}
 
177
 
 
178
TEST_F(MediatingDisplayChangerTest, doesnt_apply_config_for_unfocused_session)
 
179
{
 
180
    using namespace testing;
 
181
    mtd::NullDisplayConfiguration conf;
 
182
 
 
183
    EXPECT_CALL(mock_compositor, stop()).Times(0);
 
184
    EXPECT_CALL(mock_display, configure(Ref(conf))).Times(0);
 
185
    EXPECT_CALL(mock_compositor, start()).Times(0);
 
186
 
 
187
    changer->configure(std::make_shared<mtd::StubSceneSession>(),
 
188
                       mt::fake_shared(conf));
 
189
 
 
190
    server_action_queue.flush();
 
191
}
 
192
 
 
193
TEST_F(MediatingDisplayChangerTest, handles_hardware_change_properly_when_pausing_system)
 
194
{
 
195
    using namespace testing;
 
196
    mtd::NullDisplayConfiguration conf;
 
197
 
 
198
    InSequence s;
 
199
    EXPECT_CALL(mock_conf_policy, apply_to(Ref(conf)));
 
200
 
 
201
    EXPECT_CALL(mock_compositor, stop());
 
202
    EXPECT_CALL(mock_display, configure(Ref(conf)));
 
203
    EXPECT_CALL(mock_compositor, start());
 
204
 
 
205
    changer->configure_for_hardware_change(mt::fake_shared(conf),
 
206
                                           mir::DisplayChanger::PauseResumeSystem);
 
207
 
 
208
    server_action_queue.flush();
 
209
}
 
210
 
 
211
TEST_F(MediatingDisplayChangerTest, handles_hardware_change_properly_when_retaining_system_state)
 
212
{
 
213
    using namespace testing;
 
214
    mtd::NullDisplayConfiguration conf;
 
215
 
 
216
    EXPECT_CALL(mock_compositor, stop()).Times(0);
 
217
    EXPECT_CALL(mock_compositor, start()).Times(0);
 
218
 
 
219
    InSequence s;
 
220
    EXPECT_CALL(mock_conf_policy, apply_to(Ref(conf)));
 
221
    EXPECT_CALL(mock_display, configure(Ref(conf)));
 
222
 
 
223
    changer->configure_for_hardware_change(mt::fake_shared(conf),
 
224
                                           mir::DisplayChanger::RetainSystemState);
 
225
 
 
226
    server_action_queue.flush();
 
227
}
 
228
 
 
229
TEST_F(MediatingDisplayChangerTest, hardware_change_doesnt_apply_base_config_if_per_session_config_is_active)
 
230
{
 
231
    using namespace testing;
 
232
 
 
233
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
234
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
235
 
 
236
    stub_session_container.insert_session(session1);
 
237
    changer->configure(session1, conf);
 
238
 
 
239
    session_event_sink.handle_focus_change(session1);
 
240
 
 
241
    server_action_queue.flush();
 
242
    Mock::VerifyAndClearExpectations(&mock_compositor);
 
243
    Mock::VerifyAndClearExpectations(&mock_display);
 
244
 
 
245
    InSequence s;
 
246
    EXPECT_CALL(mock_compositor, stop()).Times(0);
 
247
    EXPECT_CALL(mock_display, configure(_)).Times(0);
 
248
    EXPECT_CALL(mock_compositor, start()).Times(0);
 
249
 
 
250
    changer->configure_for_hardware_change(conf,
 
251
                                           mir::DisplayChanger::PauseResumeSystem);
 
252
 
 
253
    server_action_queue.flush();
 
254
}
 
255
 
 
256
TEST_F(MediatingDisplayChangerTest, notifies_all_sessions_on_hardware_config_change)
 
257
{
 
258
    using namespace testing;
 
259
    mtd::NullDisplayConfiguration conf;
 
260
    mtd::MockSceneSession mock_session1;
 
261
    mtd::MockSceneSession mock_session2;
 
262
 
 
263
    stub_session_container.insert_session(mt::fake_shared(mock_session1));
 
264
    stub_session_container.insert_session(mt::fake_shared(mock_session2));
 
265
 
 
266
    EXPECT_CALL(mock_session1, send_display_config(_));
 
267
    EXPECT_CALL(mock_session2, send_display_config(_));
 
268
 
 
269
    changer->configure_for_hardware_change(mt::fake_shared(conf),
 
270
                                           mir::DisplayChanger::PauseResumeSystem);
 
271
 
 
272
    server_action_queue.flush();
 
273
}
 
274
 
 
275
TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_attached_config_applies_config)
 
276
{
 
277
    using namespace testing;
 
278
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
279
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
280
 
 
281
    stub_session_container.insert_session(session1);
 
282
    changer->configure(session1, conf);
 
283
 
 
284
    InSequence s;
 
285
    EXPECT_CALL(mock_compositor, stop());
 
286
    EXPECT_CALL(mock_display, configure(Ref(*conf)));
 
287
    EXPECT_CALL(mock_compositor, start());
 
288
 
 
289
    session_event_sink.handle_focus_change(session1);
 
290
 
 
291
    server_action_queue.flush();
 
292
}
 
293
 
 
294
TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config)
 
295
{
 
296
    using namespace testing;
 
297
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
298
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
299
    auto session2 = std::make_shared<mtd::StubSceneSession>();
 
300
 
 
301
    stub_session_container.insert_session(session1);
 
302
    changer->configure(session1, conf);
 
303
 
 
304
    session_event_sink.handle_focus_change(session1);
 
305
 
 
306
    server_action_queue.flush();
 
307
    Mock::VerifyAndClearExpectations(&mock_compositor);
 
308
    Mock::VerifyAndClearExpectations(&mock_display);
 
309
 
 
310
    InSequence s;
 
311
    EXPECT_CALL(mock_compositor, stop());
 
312
    EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(base_config))));
 
313
    EXPECT_CALL(mock_compositor, start());
 
314
 
 
315
    session_event_sink.handle_focus_change(session2);
 
316
 
 
317
    server_action_queue.flush();
 
318
}
 
319
 
 
320
TEST_F(MediatingDisplayChangerTest, losing_focus_applies_base_config)
 
321
{
 
322
    using namespace testing;
 
323
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
324
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
325
 
 
326
    stub_session_container.insert_session(session1);
 
327
    changer->configure(session1, conf);
 
328
 
 
329
    session_event_sink.handle_focus_change(session1);
 
330
 
 
331
    server_action_queue.flush();
 
332
    Mock::VerifyAndClearExpectations(&mock_compositor);
 
333
    Mock::VerifyAndClearExpectations(&mock_display);
 
334
 
 
335
    InSequence s;
 
336
    EXPECT_CALL(mock_compositor, stop());
 
337
    EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(base_config))));
 
338
    EXPECT_CALL(mock_compositor, start());
 
339
 
 
340
    session_event_sink.handle_no_focus();
 
341
 
 
342
    server_action_queue.flush();
 
343
}
 
344
 
 
345
TEST_F(MediatingDisplayChangerTest, base_config_is_not_applied_if_already_active)
 
346
{
 
347
    using namespace testing;
 
348
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
349
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
350
    auto session2 = std::make_shared<mtd::StubSceneSession>();
 
351
 
 
352
    EXPECT_CALL(mock_compositor, stop()).Times(0);
 
353
    EXPECT_CALL(mock_display, configure(_)).Times(0);
 
354
    EXPECT_CALL(mock_compositor, start()).Times(0);
 
355
 
 
356
    stub_session_container.insert_session(session1);
 
357
    stub_session_container.insert_session(session2);
 
358
 
 
359
    session_event_sink.handle_focus_change(session1);
 
360
    session_event_sink.handle_focus_change(session2);
 
361
    session_event_sink.handle_no_focus();
 
362
 
 
363
    server_action_queue.flush();
 
364
}
 
365
 
 
366
TEST_F(MediatingDisplayChangerTest, hardware_change_invalidates_session_configs)
 
367
{
 
368
    using namespace testing;
 
369
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
370
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
371
 
 
372
    stub_session_container.insert_session(session1);
 
373
    changer->configure(session1, conf);
 
374
 
 
375
    changer->configure_for_hardware_change(conf,
 
376
                                           mir::DisplayChanger::PauseResumeSystem);
 
377
 
 
378
    server_action_queue.flush();
 
379
    Mock::VerifyAndClearExpectations(&mock_compositor);
 
380
    Mock::VerifyAndClearExpectations(&mock_display);
 
381
 
 
382
    /*
 
383
     * Session1 had a config, but it should have been invalidated by the hardware
 
384
     * change, so expect no reconfiguration.
 
385
     */
 
386
    EXPECT_CALL(mock_compositor, stop()).Times(0);
 
387
    EXPECT_CALL(mock_display, configure(_)).Times(0);
 
388
    EXPECT_CALL(mock_compositor, start()).Times(0);
 
389
 
 
390
    session_event_sink.handle_focus_change(session1);
 
391
 
 
392
    server_action_queue.flush();
 
393
}
 
394
 
 
395
TEST_F(MediatingDisplayChangerTest, session_stopping_invalidates_session_config)
 
396
{
 
397
    using namespace testing;
 
398
    auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
399
    auto session1 = std::make_shared<mtd::StubSceneSession>();
 
400
 
 
401
    stub_session_container.insert_session(session1);
 
402
    changer->configure(session1, conf);
 
403
 
 
404
    session_event_sink.handle_session_stopping(session1);
 
405
 
 
406
    server_action_queue.flush();
 
407
    Mock::VerifyAndClearExpectations(&mock_compositor);
 
408
    Mock::VerifyAndClearExpectations(&mock_display);
 
409
 
 
410
    /*
 
411
     * Session1 had a config, but it should have been invalidated by the
 
412
     * session stopping event, so expect no reconfiguration.
 
413
     */
 
414
    EXPECT_CALL(mock_compositor, stop()).Times(0);
 
415
    EXPECT_CALL(mock_display, configure(_)).Times(0);
 
416
    EXPECT_CALL(mock_compositor, start()).Times(0);
 
417
 
 
418
    session_event_sink.handle_focus_change(session1);
 
419
 
 
420
    server_action_queue.flush();
 
421
}
 
422
 
 
423
TEST_F(MediatingDisplayChangerTest, uses_server_action_queue_for_configuration_actions)
 
424
{
 
425
    using namespace testing;
 
426
 
 
427
    auto const conf = std::make_shared<mtd::NullDisplayConfiguration>();
 
428
    auto const session1 = std::make_shared<mtd::StubSceneSession>();
 
429
    auto const session2 = std::make_shared<mtd::StubSceneSession>();
 
430
    MockServerActionQueue mock_server_action_queue;
 
431
 
 
432
    stub_session_container.insert_session(session1);
 
433
    stub_session_container.insert_session(session2);
 
434
 
 
435
    ms::MediatingDisplayChanger display_changer(
 
436
      mt::fake_shared(mock_display),
 
437
      mt::fake_shared(mock_compositor),
 
438
      mt::fake_shared(mock_conf_policy),
 
439
      mt::fake_shared(stub_session_container),
 
440
      mt::fake_shared(session_event_sink),
 
441
      mt::fake_shared(mock_server_action_queue));
 
442
 
 
443
    void const* owner{nullptr};
 
444
 
 
445
    EXPECT_CALL(mock_server_action_queue, enqueue(_, _))
 
446
        .WillOnce(SaveArg<0>(&owner));
 
447
    display_changer.configure(session1, conf);
 
448
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
449
 
 
450
    EXPECT_CALL(mock_server_action_queue, enqueue(owner, _));
 
451
    display_changer.configure_for_hardware_change(
 
452
        conf,
 
453
        mir::DisplayChanger::PauseResumeSystem);
 
454
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
455
 
 
456
    EXPECT_CALL(mock_server_action_queue, enqueue(owner, _));
 
457
    session_event_sink.handle_focus_change(session1);
 
458
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
459
 
 
460
    EXPECT_CALL(mock_server_action_queue, enqueue(owner, _));
 
461
    session_event_sink.handle_focus_change(session2);
 
462
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
463
 
 
464
    EXPECT_CALL(mock_server_action_queue, enqueue(owner, _));
 
465
    session_event_sink.handle_no_focus();
 
466
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
467
 
 
468
    EXPECT_CALL(mock_server_action_queue, pause_processing_for(owner));
 
469
    display_changer.pause_display_config_processing();
 
470
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
471
 
 
472
    EXPECT_CALL(mock_server_action_queue, resume_processing_for(owner));
 
473
    display_changer.resume_display_config_processing();
 
474
    Mock::VerifyAndClearExpectations(&mock_server_action_queue);
 
475
}