~ubuntu-branches/ubuntu/utopic/mir/utopic-proposed

« back to all changes in this revision

Viewing changes to tests/integration-tests/client/test_screencast.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Kevin Gunn
  • Date: 2014-02-12 18:29:29 UTC
  • mfrom: (1.1.56)
  • Revision ID: package-import@ubuntu.com-20140212182929-ru6hzd1hqdf98tub
Tags: 0.1.5+14.04.20140212-0ubuntu1
[ Kevin Gunn ]
* Cherry-picked from future release 0.1.6:
  - frontend, shell: provide the client process ID in the shell::Session
    interface (LP: #1276704)
* New upstream release 0.1.5 (https://launchpad.net/mir/+milestone/0.1.5)
  - mirclient ABI bumped to 7
  - mirserver ABI bumped to 15
  - Refactoring to support client-controled RPC.
  - Add an translucent server example (use sparingly, this will kill
    performance!)
  - Add workaround for Qualcomm Snapdragon 8960 driver bug.
  - android-input: Improve debug output
  - Screen rotation support half done (rotation of the screen works but input
    rotation not implemented yet).
  - Add groundwork for overlay support to take better advantage of mobile
    hardware features and optimize composition in future.
  - Add support for HWC 1.2 (Android 4.4)
  - Add groundwork for screencasting (screen recording).
  - Optimized surface resizing, significantly reducing event flooding for
    some input configurations like touch.
  - Bugs fixed:
    . Surfaces no longer visible at all on Nexus 10 (LP: #1271853)
    . mir nested server failure: what(): error binding buffer to texture
      (LP: #1272041)
    . Unity does not process events from evdev device created before unity is
      restarted (autopilot tests) (LP: #1238417)
    . mir_unit_tests can't run on touch images any more (missing
      libumockdev.so.0) (LP: #1271434)
    . chmod 777 /tmp/mir_socket is no longer sufficient for non-root clients
      to connect to a root server (LP: #1272143)
    . Nexus7(2013) flo framerate maxes out at 30fps (LP: #1274189)
    . libmirserver user is unable to #include
       <mir/frontend/template_protobuf_message_processor.h> (LP: #1276162)
    . libmirclient user cannot "#include <mir/client/private.h>"
      (LP: #1276565)
    . AndroidInternalClient.internal_client_creation_and_use hangs on Nexus
      10 (LP: #1270685)
    . Tests that use the InProcessServer bind the default socket file
      (LP: #1271604)
    . BasicConnector threads exit immediately (LP: #1271655)
    . Integration tests TestClientIPCRender.test_accelerated_render fails on
      Galaxy Nexus and Nexus4 (LP: #1272597)
    . Android backend unit-tests FTBS on amd64 (LP: #1276621)
    . Erroneous use of last_consumed in SwitchingBundle::compositor_acquire
      (LP: #1270964)

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
 
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: Alexandros Frantzis <alexandros.frantzis@canonical.com>
 
17
 */
 
18
 
 
19
#include "mir_protobuf.pb.h"
 
20
#include "src/client/default_connection_configuration.h"
 
21
 
 
22
#include "mir/frontend/connector.h"
 
23
#include "mir_test/test_protobuf_server.h"
 
24
#include "mir_test/stub_server_tool.h"
 
25
#include "mir_test/pipe.h"
 
26
 
 
27
#include <gtest/gtest.h>
 
28
 
 
29
#include <thread>
 
30
#include <mutex>
 
31
#include <condition_variable>
 
32
#include <boost/throw_exception.hpp>
 
33
 
 
34
namespace mcl = mir::client;
 
35
namespace mt = mir::test;
 
36
 
 
37
namespace
 
38
{
 
39
 
 
40
class WaitObject
 
41
{
 
42
public:
 
43
    void notify_ready()
 
44
    {
 
45
        std::unique_lock<std::mutex> lock{mutex};
 
46
        ready = true;
 
47
        cv.notify_all();
 
48
    }
 
49
 
 
50
    void wait_until_ready()
 
51
    {
 
52
        std::unique_lock<std::mutex> lock{mutex};
 
53
        if (!cv.wait_for(lock, std::chrono::seconds{10}, [this] { return ready; }))
 
54
        {
 
55
            BOOST_THROW_EXCEPTION(std::runtime_error("WaitObject timed out"));
 
56
        }
 
57
    }
 
58
 
 
59
private:
 
60
    std::mutex mutex;
 
61
    std::condition_variable cv;
 
62
    bool ready = false;
 
63
};
 
64
 
 
65
struct StubScreencastServerTool : mt::StubServerTool
 
66
{
 
67
    void create_screencast(
 
68
        google::protobuf::RpcController*,
 
69
        const mir::protobuf::ScreencastParameters*,
 
70
        mir::protobuf::Screencast* response,
 
71
        google::protobuf::Closure* done) override
 
72
    {
 
73
        response->mutable_buffer()->add_fd(pipe.read_fd());
 
74
        done->Run();
 
75
    }
 
76
 
 
77
    void screencast_buffer(
 
78
        ::google::protobuf::RpcController*,
 
79
        ::mir::protobuf::ScreencastId const*,
 
80
        ::mir::protobuf::Buffer* response,
 
81
        ::google::protobuf::Closure* done) override
 
82
    {
 
83
        response->add_fd(pipe.read_fd());
 
84
        done->Run();
 
85
    }
 
86
 
 
87
    mt::Pipe pipe;
 
88
};
 
89
 
 
90
struct MirScreencastTest : public testing::Test
 
91
{
 
92
    MirScreencastTest()
 
93
        : server_tool{std::make_shared<StubScreencastServerTool>()}
 
94
    {
 
95
        std::remove(test_socket);
 
96
        test_server =
 
97
            std::make_shared<mt::TestProtobufServer>(test_socket, server_tool);
 
98
        test_server->comm->start();
 
99
 
 
100
        rpc_channel =
 
101
            mcl::DefaultConnectionConfiguration{test_socket}.the_rpc_channel();
 
102
        protobuf_server =
 
103
            std::make_shared<mir::protobuf::DisplayServer::Stub>(rpc_channel.get());
 
104
    }
 
105
 
 
106
    char const* const test_socket = "./test_socket_screencast";
 
107
    std::shared_ptr<StubScreencastServerTool> const server_tool;
 
108
    std::shared_ptr<mt::TestProtobufServer> test_server;
 
109
    std::shared_ptr<google::protobuf::RpcChannel> rpc_channel;
 
110
    std::shared_ptr<mir::protobuf::DisplayServer> protobuf_server;
 
111
};
 
112
 
 
113
}
 
114
 
 
115
TEST_F(MirScreencastTest, gets_buffer_fd_when_creating_screencast)
 
116
{
 
117
    std::vector<char> const cookie{'2','3','l','$'};
 
118
 
 
119
    ASSERT_EQ(static_cast<ssize_t>(cookie.size()),
 
120
              write(server_tool->pipe.write_fd(), cookie.data(), cookie.size()));
 
121
 
 
122
    mir::protobuf::ScreencastParameters protobuf_parameters;
 
123
    protobuf_parameters.set_output_id(0);
 
124
    protobuf_parameters.set_width(0);
 
125
    protobuf_parameters.set_height(0);
 
126
    mir::protobuf::Screencast protobuf_screencast;
 
127
 
 
128
    WaitObject wait_rpc;
 
129
 
 
130
    protobuf_server->create_screencast(
 
131
        nullptr,
 
132
        &protobuf_parameters,
 
133
        &protobuf_screencast,
 
134
        google::protobuf::NewCallback(&wait_rpc, &WaitObject::notify_ready));
 
135
 
 
136
    wait_rpc.wait_until_ready();
 
137
 
 
138
    ASSERT_EQ(1, protobuf_screencast.buffer().fd_size());
 
139
    auto const read_fd = protobuf_screencast.buffer().fd(0);
 
140
 
 
141
    // The received FD should be different from the original pipe fd,
 
142
    // since we are sending it over our IPC mechanism, which for
 
143
    // the purposes of this test, lives in the same process.
 
144
    // TODO: Don't depend on IPC implementation details
 
145
    EXPECT_NE(read_fd, server_tool->pipe.read_fd());
 
146
 
 
147
    std::vector<char> received(cookie.size(), '\0');
 
148
    EXPECT_EQ(static_cast<ssize_t>(cookie.size()),
 
149
              read(read_fd, received.data(), received.size()));
 
150
    EXPECT_EQ(cookie, received);
 
151
 
 
152
    close(read_fd);
 
153
}
 
154
 
 
155
TEST_F(MirScreencastTest, gets_buffer_fd_when_getting_screencast_buffer)
 
156
{
 
157
    std::vector<char> const cookie{'X','%','q','S'};
 
158
 
 
159
    ASSERT_EQ(static_cast<ssize_t>(cookie.size()),
 
160
              write(server_tool->pipe.write_fd(), cookie.data(), cookie.size()));
 
161
 
 
162
    mir::protobuf::ScreencastId protobuf_screencast_id;
 
163
    protobuf_screencast_id.set_value(0);
 
164
    mir::protobuf::Buffer protobuf_buffer;
 
165
 
 
166
    WaitObject wait_rpc;
 
167
 
 
168
    protobuf_server->screencast_buffer(
 
169
        nullptr,
 
170
        &protobuf_screencast_id,
 
171
        &protobuf_buffer,
 
172
        google::protobuf::NewCallback(&wait_rpc, &WaitObject::notify_ready));
 
173
 
 
174
    wait_rpc.wait_until_ready();
 
175
 
 
176
    ASSERT_EQ(1, protobuf_buffer.fd_size());
 
177
    auto const read_fd = protobuf_buffer.fd(0);
 
178
 
 
179
    // The received FD should be different from the original pipe fd,
 
180
    // since we are sending it over our IPC mechanism, which, for
 
181
    // the purposes of this test, lives in the same process.
 
182
    // TODO: Don't depend on IPC implementation details
 
183
    EXPECT_NE(read_fd, server_tool->pipe.read_fd());
 
184
 
 
185
    std::vector<char> received(cookie.size(), '\0');
 
186
    EXPECT_EQ(static_cast<ssize_t>(cookie.size()),
 
187
              read(read_fd, received.data(), received.size()));
 
188
    EXPECT_EQ(cookie, received);
 
189
 
 
190
    close(read_fd);
 
191
}