2
* Copyright © 2014 Canonical Ltd.
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.
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.
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/>.
16
* Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
19
#include "mir_protobuf.pb.h"
20
#include "src/client/default_connection_configuration.h"
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"
27
#include <gtest/gtest.h>
31
#include <condition_variable>
32
#include <boost/throw_exception.hpp>
34
namespace mcl = mir::client;
35
namespace mt = mir::test;
45
std::unique_lock<std::mutex> lock{mutex};
50
void wait_until_ready()
52
std::unique_lock<std::mutex> lock{mutex};
53
if (!cv.wait_for(lock, std::chrono::seconds{10}, [this] { return ready; }))
55
BOOST_THROW_EXCEPTION(std::runtime_error("WaitObject timed out"));
61
std::condition_variable cv;
65
struct StubScreencastServerTool : mt::StubServerTool
67
void create_screencast(
68
google::protobuf::RpcController*,
69
const mir::protobuf::ScreencastParameters*,
70
mir::protobuf::Screencast* response,
71
google::protobuf::Closure* done) override
73
response->mutable_buffer()->add_fd(pipe.read_fd());
77
void screencast_buffer(
78
::google::protobuf::RpcController*,
79
::mir::protobuf::ScreencastId const*,
80
::mir::protobuf::Buffer* response,
81
::google::protobuf::Closure* done) override
83
response->add_fd(pipe.read_fd());
90
struct MirScreencastTest : public testing::Test
93
: server_tool{std::make_shared<StubScreencastServerTool>()}
95
std::remove(test_socket);
97
std::make_shared<mt::TestProtobufServer>(test_socket, server_tool);
98
test_server->comm->start();
101
mcl::DefaultConnectionConfiguration{test_socket}.the_rpc_channel();
103
std::make_shared<mir::protobuf::DisplayServer::Stub>(rpc_channel.get());
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;
115
TEST_F(MirScreencastTest, gets_buffer_fd_when_creating_screencast)
117
std::vector<char> const cookie{'2','3','l','$'};
119
ASSERT_EQ(static_cast<ssize_t>(cookie.size()),
120
write(server_tool->pipe.write_fd(), cookie.data(), cookie.size()));
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;
130
protobuf_server->create_screencast(
132
&protobuf_parameters,
133
&protobuf_screencast,
134
google::protobuf::NewCallback(&wait_rpc, &WaitObject::notify_ready));
136
wait_rpc.wait_until_ready();
138
ASSERT_EQ(1, protobuf_screencast.buffer().fd_size());
139
auto const read_fd = protobuf_screencast.buffer().fd(0);
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());
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);
155
TEST_F(MirScreencastTest, gets_buffer_fd_when_getting_screencast_buffer)
157
std::vector<char> const cookie{'X','%','q','S'};
159
ASSERT_EQ(static_cast<ssize_t>(cookie.size()),
160
write(server_tool->pipe.write_fd(), cookie.data(), cookie.size()));
162
mir::protobuf::ScreencastId protobuf_screencast_id;
163
protobuf_screencast_id.set_value(0);
164
mir::protobuf::Buffer protobuf_buffer;
168
protobuf_server->screencast_buffer(
170
&protobuf_screencast_id,
172
google::protobuf::NewCallback(&wait_rpc, &WaitObject::notify_ready));
174
wait_rpc.wait_until_ready();
176
ASSERT_EQ(1, protobuf_buffer.fd_size());
177
auto const read_fd = protobuf_buffer.fd(0);
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());
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);