~hikiko/mir/mir.unity8-desktop-session

« back to all changes in this revision

Viewing changes to tests/acceptance-tests/test_client_screencast.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Daniel van Vugt, Ubuntu daily release
  • Date: 2014-02-04 14:49:07 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20140204144907-2lcyf87mba5rdca6
Tags: 0.1.4+14.04.20140204-0ubuntu1
[ Daniel van Vugt ]
* New upstream release 0.1.4 (https://launchpad.net/mir/+milestone/0.1.4)
  - Fixed snapshotting and flicker problems for Unity8 on various Nexus
    devices.
  - Enhanced reporting of performance information:
    . Report input latency in InputReport/InputReceiverReport.
    . Added a CompositorReport for logging compositor performance and state.
  - Added a new package "mir-utils" containing new tools:
    . mirping: Displays round-trip times between client and server
    . mirout: Displays the monitor layout/configuration details
  - Added GL texture caching to improve performance when multiple surfaces
    are visible.
  - Added opacity controls to mir_demo_server_shell
  - Mir server ABI bumped to 13. Client ABI bumped to 5.
  - Removed lots of Android headers, replaced by build-dep: android-headers
  - Added support for translucent nested servers.
  - tests: Fix unitialized values and incorrect fd closing loops
  - Fix unitialized values and incorrect fd closing loops.
  - client: Add basic MirScreencast C API.
  - config: start moving default values for config options from all the
    call sites to the setup
  - tests: Provide a helper for running clients with a stub ClientPlatform.
  - android: split out HWC layers into their own file and add a
    mga::CompositionLayer type that depends on the interface mg::Renderable.
  - client: Add basic MirOutputCapture class.
  - client: Don't create mesa ClientBuffer objects from invalid
    MirBufferPackages.
  - Optimize surface resizing to avoid doing anything if the dimensions
    are unchanged.
  - SwitchingBundle - add operator<< for debugging.
  - support hwcomposer 1.2 for android 4.4 on nexus 4 (which needs hwc1.2
    support). This patch adds hwc1.2 device construction, as well as progs
    the 'skip' layer in HWC to the buffer properties of the framebuffer.
  - demo-shell: Add simple keyboard controls to rotate outputs; Ctrl +
    Alt + <arrow-key>. Fixes: https://bugs.launchpad.net/bugs/1203215.
  - frontend: exposing internals of the RPC mechanism to enable custom
    function calls to be added.
  - Make udev wrapper into a top-level citizen
  - compositor: ignore double requests to start or stop the
    MultiThreadedCompositor.
  - Add DisplayBuffer::orientation(), to tell the Renderer if we need it
    to do screen rotation in GL (for platforms which don't implement 
    rotation natively) Fixes: https://bugs.launchpad.net/bugs/1203215.
  - graphics: add an post_update function that takes a list of renderables
    to the display buffer. This will let the display buffer take advantage
    of full-surface overlays on android.
  - android-input: Improve debug output
  - the stock qcom 8960 hwcomposer chokes on getDisplayAttributes if the
    submitted arrays are not at least size 6. patched the qcom android 4.2
    hwcomposer driver on the ubuntu touch images to work properly, but
    causes us problems with in-the wild drivers, and the new 4.4 drivers.
    Make sure we always submit a larger-than-needed array to this function.
  - frontend: refactoring to make it easier to expose the underlying RPC
    transport on the server side.
  - Don't assume pressure value is zero if not yet known
  - build: Expose options to allow building but not running tests by default.
  - Translucent Server which prefers a transparent pixel format
  - frontend: refactor ProtobufMessageProcessor to separate out generic
    response sending logic from specific message handling.
  - client: expose the part of the client RPC infrastructure needed for
    downstream to prototype their own message sending.
  - Bugs fixed:
    . unity8 display flickers and stops responding on Nexus 7 (grouper)
      (LP: #1238695)
    . Mir gets textures/buffers confused when running both scroll and flicker
      demos (LP: #1263592)
    . Some snapshots on Nexus10 upside-down (LP: #1263741)
    . mir_unit_tests is crashing with SIGSEGV in libhybris gl functions
      (LP: #1264968)
    . Some snapshots on Nexus10 have swapped red/blue channels (LP: #1265787)
    . Bypass causes some non-bypassed surfaces (on top) to be invisible
      (LP: #1266385)
    . helgrind: Possible data race - MirConnection::mutex not used
      consistently (LP: #1243575)
    . helgrind: Lock order violated (potential deadlock) in
      ConnectionSurfaceMap (LP: #1243576)
    . helgrind: Possible data race - inconsistent locking in PendingCallCache
      (LP: #1243578)
    . helgrind: Lock order violated in
      mir::client::ConnectionSurfaceMap::erase(int) (LP: #1243584)
    . [enhancement] Allow a Mir nested server to have a transparent
      background (LP: #1256702)
    . Compiling without tests fails (-DMIR_ENABLE_TESTS=NO) (LP: #1263724)
    . examples, doc: Make it clear and consistent how to use
      a non-root client with a root compositor endpoint. 
      (LP: #1272143)
    . Avoid linking to umockdev on platforms (android) which don't yet
      use it. This allows mir_unit_tests to run on touch images again
      (LP: #1271434)
    . Workaround for N4 nested server issue. This change removes
      mir_pixel_format_bgr_888 - HAL_PIXEL_FORMAT_RGB_888 from the
      list of supported pixel formats on android. (LP: #1272041)
    . Don't ask glUniformMatrix4fv to transpose your matrix. That option
      was officially deprecated between OpenGL and OpenGL|ES. And some
      drivers like the Nexus 10 don't implement it, resulting in incorrect
      transformations and even nothing on screen! (LP: #1271853)
    . Fixes: bug 1272143 (LP: #1272143)
    . fix integration test failure on the galaxy nexus that was due to
      creating two surfaces and registering the same buffer twice. Fixes:
      (LP: #1272597)
    . Implement screen rotation in GLRenderer, for platforms
      which can't do it natively in DisplayBuffer.
      (LP: #1203215)
    . Add an "orientation" field to output structures in preparation for
      screen rotation. It's not yet functionally wired to anything.
      (LP: #1203215)
    . Only use SwitchingBundle::last_consumed after it has been
      set. Otherwise SwitchingBundle::compositor_acquire could follow a bogus
      code path. (LP:#1270964)
    . tests: Override configuration to avoid creating an (unused)
      filesystem endpoint for connections when using InProcessServer. 
      (LP: #1271604)
    . frontend: ensure that BasicConnector threads don't exit
      immediately. (LP: #1271655)

[ Ubuntu daily release ]
* New rebuild forced

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2014 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3,
 
6
 * as 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: Alexandros Frantzis <alexandros.frantzis@canonical.com>
 
17
 */
 
18
 
 
19
#include "mir_toolkit/mir_screencast.h"
 
20
#include "mir_toolkit/mir_client_library.h"
 
21
 
 
22
#include "mir_test_framework/stubbed_server_configuration.h"
 
23
#include "mir_test_framework/in_process_server.h"
 
24
#include "mir_test_framework/using_stub_client_platform.h"
 
25
#include "src/server/frontend/protobuf_ipc_factory.h"
 
26
#include "mir_protobuf.pb.h"
 
27
 
 
28
#include "mir_test_doubles/null_display_changer.h"
 
29
#include "mir_test_doubles/stub_display_configuration.h"
 
30
#include "mir_test/fake_shared.h"
 
31
 
 
32
#include <gtest/gtest.h>
 
33
#include <gmock/gmock.h>
 
34
 
 
35
namespace mtf = mir_test_framework;
 
36
namespace mtd = mir::test::doubles;
 
37
namespace mg = mir::graphics;
 
38
namespace mf = mir::frontend;
 
39
namespace mt = mir::test;
 
40
 
 
41
namespace
 
42
{
 
43
 
 
44
ACTION(RunClosure)
 
45
{
 
46
    arg3->Run();
 
47
}
 
48
 
 
49
MATCHER_P(WithOutputId, value, "")
 
50
{
 
51
    return arg->output_id() == value;
 
52
}
 
53
 
 
54
MATCHER_P(WithScreencastId, value, "")
 
55
{
 
56
    return arg->value() == value;
 
57
}
 
58
 
 
59
ACTION_P(SetCreateScreencastId, screencast_id)
 
60
{
 
61
    arg2->mutable_screencast_id()->set_value(screencast_id);
 
62
}
 
63
 
 
64
ACTION(FillCreateScreencastBuffer)
 
65
{
 
66
    int fds[2]{-1,-1};
 
67
    if (pipe(fds))
 
68
        FAIL() << "Failed to create FillCreateScreencastBuffer fds";
 
69
    close(fds[1]);
 
70
    arg2->mutable_buffer()->add_fd(fds[0]);
 
71
}
 
72
 
 
73
/*
 
74
 * This setup is used temporarily to test MirScreencast, until
 
75
 * we have the server-side implementation of the feature in place.
 
76
 */
 
77
struct MockScreencastServer : mir::protobuf::DisplayServer
 
78
{
 
79
    MockScreencastServer(
 
80
        std::shared_ptr<mir::protobuf::DisplayServer> const& ds)
 
81
        : wrapped_display_server{ds}
 
82
    {
 
83
        using namespace testing;
 
84
        ON_CALL(*this, create_screencast(_,_,_,_))
 
85
            .WillByDefault(DoAll(FillCreateScreencastBuffer(),RunClosure()));
 
86
        ON_CALL(*this, release_screencast(_,_,_,_))
 
87
            .WillByDefault(RunClosure());
 
88
    }
 
89
 
 
90
    void connect(
 
91
        ::google::protobuf::RpcController* rpc,
 
92
        const ::mir::protobuf::ConnectParameters* request,
 
93
        ::mir::protobuf::Connection* response,
 
94
        ::google::protobuf::Closure* done) override
 
95
    {
 
96
        wrapped_display_server->connect(rpc, request, response, done);
 
97
    }
 
98
 
 
99
    void disconnect(
 
100
        google::protobuf::RpcController* rpc,
 
101
        const mir::protobuf::Void* request,
 
102
        mir::protobuf::Void* response,
 
103
        google::protobuf::Closure* done) override
 
104
    {
 
105
        wrapped_display_server->disconnect(rpc, request, response, done);
 
106
    }
 
107
 
 
108
    MOCK_METHOD4(create_screencast,
 
109
                 void(google::protobuf::RpcController*,
 
110
                      const mir::protobuf::ScreencastParameters*,
 
111
                      mir::protobuf::Screencast*,
 
112
                      google::protobuf::Closure*));
 
113
 
 
114
    MOCK_METHOD4(release_screencast,
 
115
                 void(google::protobuf::RpcController*,
 
116
                      const mir::protobuf::ScreencastId*,
 
117
                      mir::protobuf::Void*,
 
118
                      google::protobuf::Closure*));
 
119
 
 
120
    std::shared_ptr<mir::protobuf::DisplayServer> const wrapped_display_server;
 
121
};
 
122
 
 
123
std::shared_ptr<MockScreencastServer> global_mock_screencast_server;
 
124
 
 
125
class WrappingIpcFactory : public mf::ProtobufIpcFactory
 
126
{
 
127
public:
 
128
    WrappingIpcFactory(
 
129
        std::shared_ptr<mf::ProtobufIpcFactory> const& ipc_factory)
 
130
        : wrapped_ipc_factory{ipc_factory}
 
131
    {
 
132
    }
 
133
 
 
134
    std::shared_ptr<mir::protobuf::DisplayServer> make_ipc_server(
 
135
        std::shared_ptr<mf::EventSink> const& sink, bool auth) override
 
136
    {
 
137
        auto ipc_server = wrapped_ipc_factory->make_ipc_server(sink, auth);
 
138
        global_mock_screencast_server =
 
139
            std::make_shared<testing::NiceMock<MockScreencastServer>>(ipc_server);
 
140
        return global_mock_screencast_server;
 
141
    }
 
142
 
 
143
    std::shared_ptr<mf::ResourceCache> resource_cache() override
 
144
    {
 
145
        return wrapped_ipc_factory->resource_cache();
 
146
    }
 
147
 
 
148
private:
 
149
    std::shared_ptr<mf::ProtobufIpcFactory> const wrapped_ipc_factory;
 
150
};
 
151
 
 
152
class StubChanger : public mtd::NullDisplayChanger
 
153
{
 
154
public:
 
155
    StubChanger()
 
156
        : stub_display_config{{{connected, !used}, {connected, used}}}
 
157
    {
 
158
    }
 
159
 
 
160
    std::shared_ptr<mg::DisplayConfiguration> active_configuration() override
 
161
    {
 
162
        return mt::fake_shared(stub_display_config);
 
163
    }
 
164
 
 
165
    mtd::StubDisplayConfig stub_display_config;
 
166
 
 
167
private:
 
168
    static bool const connected;
 
169
    static bool const used;
 
170
};
 
171
 
 
172
bool const StubChanger::connected{true};
 
173
bool const StubChanger::used{true};
 
174
 
 
175
struct StubServerConfig : mir_test_framework::StubbedServerConfiguration
 
176
{
 
177
    std::shared_ptr<mf::DisplayChanger> the_frontend_display_changer() override
 
178
    {
 
179
        return mt::fake_shared(stub_changer);
 
180
    }
 
181
 
 
182
    std::shared_ptr<mf::ProtobufIpcFactory> the_ipc_factory(
 
183
        std::shared_ptr<mf::Shell> const& shell,
 
184
        std::shared_ptr<mg::GraphicBufferAllocator> const& alloc) override
 
185
    {
 
186
        auto factory = mtf::StubbedServerConfiguration::the_ipc_factory(shell, alloc);
 
187
        return std::make_shared<WrappingIpcFactory>(factory);
 
188
    }
 
189
 
 
190
    StubChanger stub_changer;
 
191
};
 
192
 
 
193
class MirScreencastTest : public mir_test_framework::InProcessServer
 
194
{
 
195
public:
 
196
    ~MirScreencastTest()
 
197
    {
 
198
        global_mock_screencast_server.reset();
 
199
    }
 
200
 
 
201
    mir::DefaultServerConfiguration& server_config() override { return server_config_; }
 
202
 
 
203
    StubServerConfig server_config_;
 
204
    mtf::UsingStubClientPlatform using_stub_client_platform;
 
205
};
 
206
 
 
207
}
 
208
 
 
209
TEST_F(MirScreencastTest, creation_with_invalid_connection_fails)
 
210
{
 
211
    using namespace testing;
 
212
 
 
213
    uint32_t const output_id{2};
 
214
    MirScreencastParameters params{output_id, 0, 0, mir_pixel_format_invalid};
 
215
 
 
216
    auto screencast = mir_connection_create_screencast_sync(nullptr, &params);
 
217
    ASSERT_EQ(nullptr, screencast);
 
218
}
 
219
 
 
220
TEST_F(MirScreencastTest, creation_with_invalid_output_fails)
 
221
{
 
222
    using namespace testing;
 
223
 
 
224
    auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
 
225
    ASSERT_TRUE(mir_connection_is_valid(connection));
 
226
 
 
227
    uint32_t const invalid_output_id{33};
 
228
    MirScreencastParameters params{invalid_output_id, 0, 0, mir_pixel_format_invalid};
 
229
 
 
230
    EXPECT_CALL(*global_mock_screencast_server,
 
231
                create_screencast(_,_,_,_))
 
232
        .Times(0);
 
233
 
 
234
    auto screencast =
 
235
        mir_connection_create_screencast_sync(connection, &params);
 
236
    ASSERT_EQ(nullptr, screencast);
 
237
 
 
238
    mir_connection_release(connection);
 
239
}
 
240
 
 
241
TEST_F(MirScreencastTest, create_and_release_contact_server)
 
242
{
 
243
    using namespace testing;
 
244
 
 
245
    auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
 
246
    ASSERT_TRUE(mir_connection_is_valid(connection));
 
247
 
 
248
    uint32_t const screencast_id{99};
 
249
    uint32_t const output_id{2};
 
250
    MirScreencastParameters params{output_id, 0, 0, mir_pixel_format_invalid};
 
251
 
 
252
    InSequence seq;
 
253
 
 
254
    EXPECT_CALL(*global_mock_screencast_server,
 
255
                create_screencast(_,WithOutputId(output_id),_,_))
 
256
        .WillOnce(DoAll(SetCreateScreencastId(screencast_id),
 
257
                        FillCreateScreencastBuffer(),
 
258
                        RunClosure()));
 
259
 
 
260
    EXPECT_CALL(*global_mock_screencast_server,
 
261
                release_screencast(_,WithScreencastId(screencast_id),_,_))
 
262
        .WillOnce(RunClosure());
 
263
 
 
264
    auto screencast = mir_connection_create_screencast_sync(connection, &params);
 
265
    ASSERT_NE(nullptr, screencast);
 
266
    mir_screencast_release_sync(screencast);
 
267
 
 
268
    mir_connection_release(connection);
 
269
}
 
270
 
 
271
TEST_F(MirScreencastTest, gets_valid_egl_native_window)
 
272
{
 
273
    using namespace testing;
 
274
 
 
275
    auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
 
276
    ASSERT_TRUE(mir_connection_is_valid(connection));
 
277
 
 
278
    uint32_t const output_id{2};
 
279
    MirScreencastParameters params{output_id, 0, 0, mir_pixel_format_invalid};
 
280
 
 
281
    auto screencast = mir_connection_create_screencast_sync(connection, &params);
 
282
    ASSERT_NE(nullptr, screencast);
 
283
 
 
284
    auto egl_native_window = mir_screencast_egl_native_window(screencast);
 
285
    EXPECT_NE(MirEGLNativeWindowType(), egl_native_window);
 
286
 
 
287
    mir_screencast_release_sync(screencast);
 
288
 
 
289
    mir_connection_release(connection);
 
290
}