Mir

Merge lp:~alan-griffiths/mir/fix-1236698 into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 1126
Proposed branch: lp:~alan-griffiths/mir/fix-1236698
Merge into: lp:mir
Diff against target: 128 lines (+44/-13)
2 files modified
src/client/mir_connection.cpp (+0/-1)
tests/unit-tests/frontend/test_published_socket_connector.cpp (+44/-12)
To merge this branch: bzr merge lp:~alan-griffiths/mir/fix-1236698
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+190400@code.launchpad.net

Commit message

client, tests: deal correctly with a race condition during double
disconnection test (LP: #1236698)

Description of the change

client, tests: deal correctly with a race condition during double disconnection test

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Sorry, the SetUpTestCase, SetUp and TearDown changes are not essential to the fix (but are useful tidy-up).

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 :

Seems to do the trick.

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

I'm going to rush this one through, because the spurious CI failures are holding up other MPs.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/client/mir_connection.cpp'
2--- src/client/mir_connection.cpp 2013-10-07 09:27:32 +0000
3+++ src/client/mir_connection.cpp 2013-10-10 15:41:01 +0000
4@@ -288,7 +288,6 @@
5 catch (std::exception const& x)
6 {
7 set_error_message(std::string("disconnect: ") + x.what());
8- disconnect_wait_handle.result_received();
9 }
10
11 return &disconnect_wait_handle;
12
13=== modified file 'tests/unit-tests/frontend/test_published_socket_connector.cpp'
14--- tests/unit-tests/frontend/test_published_socket_connector.cpp 2013-10-07 09:27:32 +0000
15+++ tests/unit-tests/frontend/test_published_socket_connector.cpp 2013-10-10 15:41:01 +0000
16@@ -49,6 +49,18 @@
17 class MockConnectorReport : public mf::ConnectorReport
18 {
19 public:
20+ MockConnectorReport()
21+ {
22+ using namespace testing;
23+ EXPECT_CALL(*this, thread_start()).Times(AnyNumber());
24+ EXPECT_CALL(*this, thread_end()).Times(AnyNumber());
25+ EXPECT_CALL(*this, starting_threads(_)).Times(AnyNumber());
26+ EXPECT_CALL(*this, stopping_threads(_)).Times(AnyNumber());
27+ EXPECT_CALL(*this, creating_session_for(_)).Times(AnyNumber());
28+ EXPECT_CALL(*this, creating_socket_pair(_, _)).Times(AnyNumber());
29+ EXPECT_CALL(*this, listening_on(_)).Times(AnyNumber());
30+ EXPECT_CALL(*this, error(_)).Times(AnyNumber());
31+ }
32
33 ~MockConnectorReport() noexcept {}
34
35@@ -68,8 +80,10 @@
36
37 struct PublishedSocketConnector : public ::testing::Test
38 {
39+ static const char* const test_socket;
40 static void SetUpTestCase()
41 {
42+ remove(test_socket);
43 }
44
45 void SetUp()
46@@ -77,23 +91,20 @@
47 communicator_report = std::make_shared<MockConnectorReport>();
48 stub_server_tool = std::make_shared<mt::StubServerTool>();
49 stub_server = std::make_shared<mt::TestProtobufServer>(
50- "./test_socket",
51+ test_socket,
52 stub_server_tool,
53 communicator_report);
54
55- using namespace testing;
56- EXPECT_CALL(*communicator_report, error(_)).Times(AnyNumber());
57 stub_server->comm->start();
58- client = std::make_shared<mt::TestProtobufClient>("./test_socket", 100);
59+ client = std::make_shared<mt::TestProtobufClient>(test_socket, 100);
60 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);
61 }
62
63 void TearDown()
64 {
65+ client.reset();
66+
67 stub_server->comm->stop();
68- testing::Mock::VerifyAndClearExpectations(communicator_report.get());
69- client.reset();
70-
71 stub_server.reset();
72 stub_server_tool.reset();
73 communicator_report.reset();
74@@ -109,6 +120,7 @@
75 static std::shared_ptr<mt::TestProtobufServer> stub_server;
76 };
77
78+const char* const PublishedSocketConnector::test_socket = "./test_socket";
79 std::shared_ptr<mt::StubServerTool> PublishedSocketConnector::stub_server_tool;
80 std::shared_ptr<MockConnectorReport> PublishedSocketConnector::communicator_report;
81 std::shared_ptr<mt::TestProtobufServer> PublishedSocketConnector::stub_server;
82@@ -196,7 +208,7 @@
83
84 }
85
86-TEST_F(PublishedSocketConnector, double_disconnection_attempt_throws_exception)
87+TEST_F(PublishedSocketConnector, double_disconnection_does_not_break)
88 {
89 using namespace testing;
90
91@@ -220,13 +232,33 @@
92
93 Mock::VerifyAndClearExpectations(client.get());
94
95- EXPECT_CALL(*client->rpc_report, invocation_failed(InvocationMethodEq("disconnect"),_));
96+ // There is a race between the server closing the socket and
97+ // the client sending the second "disconnect".
98+ // Usually[*] the server wins and the "disconnect" fails resulting
99+ // in an invocation_failed() report and an exception.
100+ // Occasionally, the client wins and the message is sent to dying socket.
101+ // [*] ON my desktop under valgrind "Usually" is ~49 times out of 50
102+
103+ EXPECT_CALL(*client->rpc_report, invocation_failed(InvocationMethodEq("disconnect"),_)).Times(AtMost(1));
104 EXPECT_CALL(*client, disconnect_done()).Times(1);
105
106- EXPECT_THROW({
107- client->display_server.disconnect(0, &client->ignored, &client->ignored, google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
108+ try
109+ {
110+ client->display_server.disconnect(
111+ 0,
112+ &client->ignored,
113+ &client->ignored,
114+ google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
115+
116+ // the write beat the socket closing
117+ }
118+ catch (std::runtime_error const& x)
119+ {
120+ // the socket closing beat the write
121+ EXPECT_THAT(x.what(), HasSubstr("Failed to send message to server:"));
122+ }
123+
124 client->wait_for_disconnect_done();
125- }, std::runtime_error);
126 }
127
128 TEST_F(PublishedSocketConnector, getting_and_advancing_buffers)

Subscribers

People subscribed via source and target branches