Mir

Merge lp:~alan-griffiths/mir/fix-1188451 into lp:~mir-team/mir/trunk

Proposed by Alan Griffiths
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 764
Proposed branch: lp:~alan-griffiths/mir/fix-1188451
Merge into: lp:~mir-team/mir/trunk
Diff against target: 547 lines (+237/-43)
14 files modified
include/server/mir/frontend/communicator_report.h (+51/-0)
include/server/mir/frontend/session_mediator.h (+2/-0)
include/test/mir_test/test_protobuf_server.h (+20/-12)
src/server/frontend/make_protobuf_socket_communicator.cpp (+3/-1)
src/server/frontend/protobuf_socket_communicator.cpp (+22/-3)
src/server/frontend/protobuf_socket_communicator.h (+5/-1)
src/server/frontend/session_mediator.cpp (+9/-0)
src/server/frontend/socket_session.cpp (+28/-10)
src/server/frontend/socket_session.h (+3/-5)
tests/integration-tests/client/test_client_render.cpp (+2/-0)
tests/mir_test_doubles/test_protobuf_socket_server.cpp (+24/-5)
tests/unit-tests/client/test_client_mir_surface.cpp (+1/-0)
tests/unit-tests/frontend/test_protobuf_communicator.cpp (+66/-6)
tests/unit-tests/frontend/test_protobuf_reports_errors.cpp (+1/-0)
To merge this branch: bzr merge lp:~alan-griffiths/mir/fix-1188451
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Abstain
Alexandros Frantzis (community) Approve
Review via email: mp+169786@code.launchpad.net

Commit message

frontend: detect and drop dead client sessions

Description of the change

frontend: detect and drop dead client sessions

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Regression: The Mir server now wakes up 10 times per second, even when all clients are idle. That's bad. The reason is:

32 + io_service.post([&]
33 + {
34 + do
35 + {
36 + std::this_thread::sleep_for(std::chrono::milliseconds(100));
37 + connected_sessions->discard_disconnected();
38 + }
39 + while (!io_service.stopped());
40 + });

That has to be re-thought because polling is not an option.

An example of a well-behaved almost-idling client to test is mir_demo_client_fingerpaint when you don't move the pointer. And you can install and run powertop (from a remote login) to watch wakeups.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

If we really do need to poll, then just make sure it's not on a timer or in a loop.

Try piggy-backing the polling on some other event, like "the screen is redrawing (for some other clients) but I haven't got any communication from this client for a while".

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

On 18/06/13 04:33, Daniel van Vugt wrote:
> Regression: The Mir server now wakes up 10 times per second, even when all clients are idle. That's bad.

Agreed. Unfortunately I've not come up with anything better than polling
yet (but we could tie it to another event that wakes the server).

--
Alan Griffiths +44 (0)798 9938 758
Octopull Ltd http://www.octopull.co.uk/

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good. It would nice to have a test for this.

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

> Looks good. It would nice to have a test for this.

Yes, I'm thinking of rolling that with the "TODO need a way to report errors" resolution.

Happy to to that here or on another MP (depending upon much folks want the bug fix landed).

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

It always happens at EOD! This no longer seems to be working. (Will try again in the morning.)

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Sorry to say it doesn't work.

Following the test case in bug 1188451, I still get moveable leaked surfaces on the screen after a client dies. And even when I start a new client the dead clients' surface remains there, frozen and moveable.

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

Having found the problem I can't see how it ever did anything that made me think it worked. (Wishes for a video of earlier testing session.)

Please try r759.

review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Since Eleni's extra error checking has landed...

/home/dan/bzr/mir/tmp.alan/src/server/frontend/session_mediator.cpp:64:39: error: declaration of ‘virtual mir::frontend::SessionMediator::~SessionMediator()’ has a different exception specifier
In file included from /home/dan/bzr/mir/tmp.alan/src/server/frontend/session_mediator.cpp:19:0:
/home/dan/bzr/mir/tmp.alan/include/server/mir/frontend/session_mediator.h:70:5: error: from previous declaration ‘virtual mir::frontend::SessionMediator::~SessionMediator() noexcept (true)’

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

> Since Eleni's extra error checking has landed...
>
> /home/dan/bzr/mir/tmp.alan/src/server/frontend/session_mediator.cpp:64:39:
> error: declaration of ‘virtual
> mir::frontend::SessionMediator::~SessionMediator()’ has a different exception
> specifier
> In file included from
> /home/dan/bzr/mir/tmp.alan/src/server/frontend/session_mediator.cpp:19:0:
> /home/dan/bzr/mir/tmp.alan/include/server/mir/frontend/session_mediator.h:70:5
> : error: from previous declaration ‘virtual
> mir::frontend::SessionMediator::~SessionMediator() noexcept (true)’

Weird, that's true (and fixed), but I didn't get a diagnostic. (g++ (Ubuntu 4.8.1-3ubuntu2) 4.8.1)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

And again:

/home/dan/bzr/mir/tmp.alan/tests/unit-tests/frontend/test_protobuf_communicator.cpp:47:7: error: looser throw specifier for ‘virtual {anonymous}::MockCommunicatorReport::~MockCommunicatorReport()’
In file included from /home/dan/bzr/mir/tmp.alan/tests/unit-tests/frontend/test_protobuf_communicator.cpp:21:0:
/home/dan/bzr/mir/tmp.alan/include/server/mir/frontend/communicator_report.h:36:13: error: overriding ‘virtual mir::frontend::CommunicatorReport::~CommunicatorReport() noexcept (true)’

Try merging in lp:mir to get the new error checking flag that just landed.

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

> Try merging in lp:mir to get the new error checking flag that just landed.

That was merged in 758 (but that flag has nothing to do with this error).

What compiler are you using?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> > Try merging in lp:mir to get the new error checking flag that just landed.
>
> That was merged in 758 (but that flag has nothing to do with this error).
>
> What compiler are you using?

Nevermind, clang reports these

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Verified the bug is fixed.

1. Needs fixing: Unused protocol changes:
src/shared/protobuf/mir_protobuf_wire.proto

2. Query: void mf::ProtobufSocketCommunicator::start()
I find the structure of this loop a bit confusing. Can it be simplified?

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

> Verified the bug is fixed.
>
> 1. Needs fixing: Unused protocol changes:
> src/shared/protobuf/mir_protobuf_wire.proto

OK, that's an unrelated change.

> 2. Query: void mf::ProtobufSocketCommunicator::start()
> I find the structure of this loop a bit confusing. Can it be simplified?

Would using "break" in place of "return" help? (I don't feel that introducing a goto or a loop variable simplifies in this case.)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Approved based on reviewing the diff for r767. I'm assuming it still works well.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'include/server/mir/frontend/communicator_report.h'
2--- include/server/mir/frontend/communicator_report.h 1970-01-01 00:00:00 +0000
3+++ include/server/mir/frontend/communicator_report.h 2013-06-21 08:43:41 +0000
4@@ -0,0 +1,51 @@
5+/*
6+ * Copyright © 2013 Canonical Ltd.
7+ *
8+ * This program is free software: you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License version 3,
10+ * as published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Alan Griffiths <alan@octopull.co.uk
21+ */
22+
23+#ifndef MIR_FRONTEND_COMMUNICATOR_REPORT_H_
24+#define MIR_FRONTEND_COMMUNICATOR_REPORT_H_
25+
26+#include <stdexcept>
27+
28+namespace mir
29+{
30+namespace frontend
31+{
32+
33+class CommunicatorReport
34+{
35+public:
36+
37+ virtual void error(std::exception const& error) = 0;
38+
39+protected:
40+ virtual ~CommunicatorReport() = default;
41+ CommunicatorReport() = default;
42+ CommunicatorReport(const CommunicatorReport&) = delete;
43+ CommunicatorReport& operator=(const CommunicatorReport&) = delete;
44+};
45+
46+class NullCommunicatorReport : public CommunicatorReport
47+{
48+public:
49+
50+ void error(std::exception const& error);
51+};
52+}
53+}
54+
55+#endif // MIR_FRONTEND_COMMUNICATOR_REPORT_H_
56
57=== modified file 'include/server/mir/frontend/session_mediator.h'
58--- include/server/mir/frontend/session_mediator.h 2013-05-30 03:50:54 +0000
59+++ include/server/mir/frontend/session_mediator.h 2013-06-21 08:43:41 +0000
60@@ -67,6 +67,8 @@
61 std::shared_ptr<events::EventSink> const& event_sink,
62 std::shared_ptr<ResourceCache> const& resource_cache);
63
64+ ~SessionMediator() noexcept;
65+
66 /* Platform independent requests */
67 void connect(::google::protobuf::RpcController* controller,
68 const ::mir::protobuf::ConnectParameters* request,
69
70=== modified file 'include/test/mir_test/test_protobuf_server.h'
71--- include/test/mir_test/test_protobuf_server.h 2013-04-24 05:22:20 +0000
72+++ include/test/mir_test/test_protobuf_server.h 2013-06-21 08:43:41 +0000
73@@ -19,29 +19,37 @@
74 #ifndef MIR_TEST_TEST_PROTOBUF_SERVER_H_
75 #define MIR_TEST_TEST_PROTOBUF_SERVER_H_
76
77-#include "mir_test/stub_server_tool.h"
78-#include "mir_test_doubles/stub_ipc_factory.h"
79-#include "mir/frontend/communicator.h"
80+#include <memory>
81
82 namespace mir
83 {
84+namespace frontend
85+{
86+class Communicator;
87+class CommunicatorReport;
88+}
89+
90+namespace protobuf
91+{
92+class DisplayServer;
93+}
94+
95 namespace test
96 {
97-
98 struct TestProtobufServer
99 {
100- TestProtobufServer(std::string socket_name,
101- const std::shared_ptr<protobuf::DisplayServer>& tool);
102+ TestProtobufServer(
103+ std::string const& socket_name,
104+ std::shared_ptr<protobuf::DisplayServer> const& tool);
105
106- std::shared_ptr<frontend::Communicator> make_communicator(
107- const std::string& socket_name,
108- std::shared_ptr<frontend::ProtobufIpcFactory> const& factory);
109+ TestProtobufServer(
110+ std::string const& socket_name,
111+ std::shared_ptr<protobuf::DisplayServer> const& tool,
112+ std::shared_ptr<frontend::CommunicatorReport> const& report);
113
114 // "Server" side
115- std::shared_ptr<doubles::StubIpcFactory> factory;
116- std::shared_ptr<frontend::Communicator> comm;
117+ std::shared_ptr<frontend::Communicator> const comm;
118 };
119-
120 }
121 }
122 #endif /* MIR_TEST_TEST_PROTOBUF_SERVER_H_ */
123
124=== modified file 'src/server/frontend/make_protobuf_socket_communicator.cpp'
125--- src/server/frontend/make_protobuf_socket_communicator.cpp 2013-04-25 09:48:54 +0000
126+++ src/server/frontend/make_protobuf_socket_communicator.cpp 2013-06-21 08:43:41 +0000
127@@ -22,6 +22,7 @@
128 #include "mir/shell/session_container.h"
129 #include "mir/shell/session.h"
130 #include "protobuf_socket_communicator.h"
131+#include "mir/frontend/communicator_report.h"
132
133 namespace mf = mir::frontend;
134 namespace mg = mir::graphics;
135@@ -46,7 +47,8 @@
136 {
137 session->force_requests_to_complete();
138 });
139- });
140+ },
141+ std::make_shared<mf::NullCommunicatorReport>());
142 });
143 }
144
145
146=== modified file 'src/server/frontend/protobuf_socket_communicator.cpp'
147--- src/server/frontend/protobuf_socket_communicator.cpp 2013-04-25 09:48:54 +0000
148+++ src/server/frontend/protobuf_socket_communicator.cpp 2013-06-21 08:43:41 +0000
149@@ -20,6 +20,7 @@
150 #include "protobuf_message_processor.h"
151 #include "socket_session.h"
152
153+#include "mir/frontend/communicator_report.h"
154 #include "mir/frontend/protobuf_ipc_factory.h"
155 #include "mir/protobuf/google_protobuf_guard.h"
156 #include "event_pipe.h"
157@@ -36,14 +37,16 @@
158 std::string const& socket_file,
159 std::shared_ptr<ProtobufIpcFactory> const& ipc_factory,
160 int threads,
161- std::function<void()> const& force_requests_to_complete)
162+ std::function<void()> const& force_requests_to_complete,
163+ std::shared_ptr<CommunicatorReport> const& report)
164 : socket_file((std::remove(socket_file.c_str()), socket_file)),
165 acceptor(io_service, socket_file),
166 io_service_threads(threads),
167 ipc_factory(ipc_factory),
168 next_session_id(0),
169 connected_sessions(std::make_shared<mfd::ConnectedSessions<mfd::SocketSession>>()),
170- force_requests_to_complete(force_requests_to_complete)
171+ force_requests_to_complete(force_requests_to_complete),
172+ report(report)
173 {
174 start_accept();
175 }
176@@ -85,7 +88,19 @@
177
178 void mf::ProtobufSocketCommunicator::start()
179 {
180- auto run_io_service = boost::bind(&ba::io_service::run, &io_service);
181+ auto run_io_service = [&]
182+ {
183+ while (true)
184+ try
185+ {
186+ io_service.run();
187+ return;
188+ }
189+ catch (std::exception const& e)
190+ {
191+ report->error(e);
192+ }
193+ };
194
195 for (auto& thread : io_service_threads)
196 {
197@@ -138,3 +153,7 @@
198 }
199 start_accept();
200 }
201+
202+void mf::NullCommunicatorReport::error(std::exception const& /*error*/)
203+{
204+}
205
206=== modified file 'src/server/frontend/protobuf_socket_communicator.h'
207--- src/server/frontend/protobuf_socket_communicator.h 2013-04-25 09:48:54 +0000
208+++ src/server/frontend/protobuf_socket_communicator.h 2013-06-21 08:43:41 +0000
209@@ -52,6 +52,8 @@
210 struct SocketSession;
211 }
212
213+class CommunicatorReport;
214+
215 class ProtobufSocketCommunicator : public Communicator
216 {
217 public:
218@@ -61,7 +63,8 @@
219 const std::string& socket_file,
220 std::shared_ptr<ProtobufIpcFactory> const& ipc_factory,
221 int threads,
222- std::function<void()> const& force_requests_to_complete);
223+ std::function<void()> const& force_requests_to_complete,
224+ std::shared_ptr<CommunicatorReport> const& report);
225 ~ProtobufSocketCommunicator();
226 void start();
227 void stop();
228@@ -79,6 +82,7 @@
229 std::atomic<int> next_session_id;
230 std::shared_ptr<detail::ConnectedSessions<detail::SocketSession>> const connected_sessions;
231 std::function<void()> const force_requests_to_complete;
232+ std::shared_ptr<CommunicatorReport> const report;
233 };
234
235 }
236
237=== modified file 'src/server/frontend/session_mediator.cpp'
238--- src/server/frontend/session_mediator.cpp 2013-06-12 15:36:31 +0000
239+++ src/server/frontend/session_mediator.cpp 2013-06-21 08:43:41 +0000
240@@ -61,6 +61,15 @@
241 {
242 }
243
244+mf::SessionMediator::~SessionMediator() noexcept
245+{
246+ if (session)
247+ {
248+ report->session_error(session->name(), __PRETTY_FUNCTION__, "connection dropped without disconnect");
249+ shell->close_session(session);
250+ }
251+}
252+
253 void mf::SessionMediator::connect(
254 ::google::protobuf::RpcController*,
255 const ::mir::protobuf::ConnectParameters* request,
256
257=== modified file 'src/server/frontend/socket_session.cpp'
258--- src/server/frontend/socket_session.cpp 2013-05-27 09:39:39 +0000
259+++ src/server/frontend/socket_session.cpp 2013-06-21 08:43:41 +0000
260@@ -27,6 +27,21 @@
261
262 namespace mfd = mir::frontend::detail;
263
264+mfd::SocketSession::SocketSession(
265+ boost::asio::io_service& io_service,
266+ int id_,
267+ std::shared_ptr<ConnectedSessions<SocketSession>> const& connected_sessions) :
268+ socket(io_service),
269+ id_(id_),
270+ connected_sessions(connected_sessions),
271+ processor(std::make_shared<NullMessageProcessor>())
272+{
273+}
274+
275+mfd::SocketSession::~SocketSession() noexcept
276+{
277+}
278+
279 void mfd::SocketSession::send(std::string const& body)
280 {
281 const size_t size = body.size();
282@@ -62,19 +77,22 @@
283 this, ba::placeholders::error));
284 }
285
286-void mfd::SocketSession::on_read_size(const boost::system::error_code& ec)
287+void mfd::SocketSession::on_read_size(const boost::system::error_code& error)
288 {
289- if (!ec)
290+ if (error)
291 {
292- size_t const body_size = (message_header_bytes[0] << 8) + message_header_bytes[1];
293- // Read newline delimited messages for now
294- ba::async_read(
295- socket,
296- message,
297- ba::transfer_exactly(body_size),
298- boost::bind(&mfd::SocketSession::on_new_message,
299- this, ba::placeholders::error));
300+ connected_sessions->remove(id());
301+ BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
302 }
303+
304+ size_t const body_size = (message_header_bytes[0] << 8) + message_header_bytes[1];
305+ // Read newline delimited messages for now
306+ ba::async_read(
307+ socket,
308+ message,
309+ ba::transfer_exactly(body_size),
310+ boost::bind(&mfd::SocketSession::on_new_message,
311+ this, ba::placeholders::error));
312 }
313
314 void mfd::SocketSession::on_new_message(const boost::system::error_code& error)
315
316=== modified file 'src/server/frontend/socket_session.h'
317--- src/server/frontend/socket_session.h 2013-05-27 09:39:39 +0000
318+++ src/server/frontend/socket_session.h 2013-06-21 08:43:41 +0000
319@@ -37,11 +37,9 @@
320 SocketSession(
321 boost::asio::io_service& io_service,
322 int id_,
323- std::shared_ptr<ConnectedSessions<SocketSession>> const& connected_sessions) :
324- socket(io_service),
325- id_(id_),
326- connected_sessions(connected_sessions),
327- processor(std::make_shared<NullMessageProcessor>()) {}
328+ std::shared_ptr<ConnectedSessions<SocketSession>> const& connected_sessions);
329+
330+ ~SocketSession() noexcept;
331
332 int id() const { return id_; }
333
334
335=== modified file 'tests/integration-tests/client/test_client_render.cpp'
336--- tests/integration-tests/client/test_client_render.cpp 2013-06-06 08:36:17 +0000
337+++ tests/integration-tests/client/test_client_render.cpp 2013-06-21 08:43:41 +0000
338@@ -27,6 +27,8 @@
339 #include "mir_test/stub_server_tool.h"
340 #include "mir_test/test_protobuf_server.h"
341
342+#include "mir/frontend/communicator.h"
343+
344 #include <gmock/gmock.h>
345 #include <thread>
346 #include <hardware/gralloc.h>
347
348=== modified file 'tests/mir_test_doubles/test_protobuf_socket_server.cpp'
349--- tests/mir_test_doubles/test_protobuf_socket_server.cpp 2013-04-25 09:48:54 +0000
350+++ tests/mir_test_doubles/test_protobuf_socket_server.cpp 2013-06-21 08:43:41 +0000
351@@ -17,22 +17,41 @@
352 */
353
354 #include "mir_test/test_protobuf_server.h"
355+#include "mir_test_doubles/stub_ipc_factory.h"
356+#include "mir/frontend/communicator_report.h"
357 #include "src/server/frontend/protobuf_socket_communicator.h"
358
359 namespace mt = mir::test;
360 namespace mtd = mir::test::doubles;
361 namespace mf = mir::frontend;
362
363+namespace
364+{
365+std::shared_ptr<mf::Communicator> make_communicator(
366+ std::string const& socket_name,
367+ std::shared_ptr<mf::ProtobufIpcFactory> const& factory,
368+ std::shared_ptr<mf::CommunicatorReport> const& report)
369+{
370+ return std::make_shared<mf::ProtobufSocketCommunicator>(
371+ socket_name,
372+ factory,
373+ 10,
374+ []{},
375+ report);
376+}
377+}
378
379 mt::TestProtobufServer::TestProtobufServer(
380- std::string socket_name,
381+ std::string const& socket_name,
382 const std::shared_ptr<protobuf::DisplayServer>& tool) :
383- factory(std::make_shared<mtd::StubIpcFactory>(*tool)),
384- comm(make_communicator(socket_name, factory))
385+ TestProtobufServer(socket_name, tool, std::make_shared<mf::NullCommunicatorReport>())
386 {
387 }
388
389-std::shared_ptr<mf::Communicator> mt::TestProtobufServer::make_communicator(const std::string& socket_name, std::shared_ptr<frontend::ProtobufIpcFactory> const& factory)
390+mt::TestProtobufServer::TestProtobufServer(
391+ std::string const& socket_name,
392+ const std::shared_ptr<protobuf::DisplayServer>& tool,
393+ std::shared_ptr<frontend::CommunicatorReport> const& report) :
394+ comm(make_communicator(socket_name, std::make_shared<mtd::StubIpcFactory>(*tool), report))
395 {
396- return std::make_shared<mf::ProtobufSocketCommunicator>(socket_name, factory, 10, []{});
397 }
398
399=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
400--- tests/unit-tests/client/test_client_mir_surface.cpp 2013-06-03 08:14:01 +0000
401+++ tests/unit-tests/client/test_client_mir_surface.cpp 2013-06-21 08:43:41 +0000
402@@ -30,6 +30,7 @@
403 #include "src/client/rpc/mir_basic_rpc_channel.h"
404
405 #include "mir/frontend/resource_cache.h"
406+#include "mir/frontend/communicator.h"
407 #include "mir/input/input_platform.h"
408 #include "mir/input/input_receiver_thread.h"
409
410
411=== modified file 'tests/unit-tests/frontend/test_protobuf_communicator.cpp'
412--- tests/unit-tests/frontend/test_protobuf_communicator.cpp 2013-05-30 03:50:54 +0000
413+++ tests/unit-tests/frontend/test_protobuf_communicator.cpp 2013-06-21 08:43:41 +0000
414@@ -18,6 +18,7 @@
415 */
416
417 #include "mir/frontend/communicator.h"
418+#include "mir/frontend/communicator_report.h"
419 #include "mir/frontend/resource_cache.h"
420 #include "src/server/frontend/protobuf_socket_communicator.h"
421
422@@ -41,24 +42,43 @@
423 namespace mt = mir::test;
424 namespace mtd = mir::test::doubles;
425
426+namespace
427+{
428+class MockCommunicatorReport : public mf::CommunicatorReport
429+{
430+public:
431+
432+ ~MockCommunicatorReport() noexcept {}
433+
434+ MOCK_METHOD1(error, void (std::exception const& error));
435+};
436+}
437+
438 struct ProtobufCommunicator : public ::testing::Test
439 {
440 static void SetUpTestCase()
441 {
442+ communicator_report = std::make_shared<MockCommunicatorReport>();
443 stub_server_tool = std::make_shared<mt::StubServerTool>();
444- stub_server = std::make_shared<mt::TestProtobufServer>("./test_socket", stub_server_tool);
445+ stub_server = std::make_shared<mt::TestProtobufServer>(
446+ "./test_socket",
447+ stub_server_tool,
448+ communicator_report);
449+ }
450
451+ void SetUp()
452+ {
453+ using namespace testing;
454+ EXPECT_CALL(*communicator_report, error(_)).Times(AnyNumber());
455 stub_server->comm->start();
456- }
457-
458- void SetUp()
459- {
460 client = std::make_shared<mt::TestProtobufClient>("./test_socket", 100);
461 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);
462 }
463
464 void TearDown()
465 {
466+ stub_server->comm->stop();
467+ testing::Mock::VerifyAndClearExpectations(communicator_report.get());
468 client.reset();
469 }
470
471@@ -66,15 +86,18 @@
472 {
473 stub_server.reset();
474 stub_server_tool.reset();
475+ communicator_report.reset();
476 }
477
478 std::shared_ptr<mt::TestProtobufClient> client;
479+ static std::shared_ptr<MockCommunicatorReport> communicator_report;
480 static std::shared_ptr<mt::StubServerTool> stub_server_tool;
481 private:
482 static std::shared_ptr<mt::TestProtobufServer> stub_server;
483 };
484
485 std::shared_ptr<mt::StubServerTool> ProtobufCommunicator::stub_server_tool;
486+std::shared_ptr<MockCommunicatorReport> ProtobufCommunicator::communicator_report;
487 std::shared_ptr<mt::TestProtobufServer> ProtobufCommunicator::stub_server;
488
489 TEST_F(ProtobufCommunicator, create_surface_results_in_a_callback)
490@@ -297,7 +320,44 @@
491 auto comms = std::make_shared<mf::ProtobufSocketCommunicator>(
492 "./test_socket1", ipc_factory, 10,
493 std::bind(&MockForceRequests::force_requests_to_complete,
494- &mock_force_requests));
495+ &mock_force_requests),
496+ std::make_shared<mf::NullCommunicatorReport>());
497 comms->start();
498 comms->stop();
499 }
500+
501+TEST_F(ProtobufCommunicator,
502+ disorderly_disconnection_handled)
503+{
504+ using namespace testing;
505+
506+ EXPECT_CALL(*client, create_surface_done()).Times(AnyNumber());
507+ client->display_server.create_surface(
508+ 0,
509+ &client->surface_parameters,
510+ &client->surface,
511+ google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
512+
513+ client->wait_for_create_surface();
514+
515+ std::mutex m;
516+ std::condition_variable cv;
517+ bool done = false;
518+
519+ ON_CALL(*communicator_report, error(_)).WillByDefault(Invoke([&] (std::exception const&)
520+ {
521+ std::unique_lock<std::mutex> lock(m);
522+
523+ done = true;
524+ cv.notify_all();
525+ }));
526+
527+ EXPECT_CALL(*communicator_report, error(_)).Times(1);
528+
529+ client.reset();
530+
531+ std::unique_lock<std::mutex> lock(m);
532+
533+ auto const deadline = std::chrono::system_clock::now() + std::chrono::seconds(1);
534+ while (!done && cv.wait_until(lock, deadline) != std::cv_status::timeout);
535+}
536
537=== modified file 'tests/unit-tests/frontend/test_protobuf_reports_errors.cpp'
538--- tests/unit-tests/frontend/test_protobuf_reports_errors.cpp 2013-01-21 12:05:00 +0000
539+++ tests/unit-tests/frontend/test_protobuf_reports_errors.cpp 2013-06-21 08:43:41 +0000
540@@ -20,6 +20,7 @@
541 #include "mir/frontend/communicator.h"
542 #include "mir/frontend/resource_cache.h"
543
544+#include "mir_test/stub_server_tool.h"
545 #include "mir_test/test_protobuf_server.h"
546 #include "mir_test_doubles/stub_ipc_factory.h"
547 #include "mir_test/test_protobuf_client.h"

Subscribers

People subscribed via source and target branches