Mir

Merge lp:~albaguirre/mir/fix-tsan-findings into lp:mir

Proposed by Alberto Aguirre
Status: Merged
Approved by: Alberto Aguirre
Approved revision: no longer in the source branch.
Merged at revision: 3199
Proposed branch: lp:~albaguirre/mir/fix-tsan-findings
Merge into: lp:mir
Diff against target: 1121 lines (+232/-340)
16 files modified
cmake/MirCommon.cmake (+3/-1)
src/server/compositor/buffer_stream_surfaces.cpp (+10/-7)
src/server/compositor/multi_threaded_compositor.cpp (+16/-11)
src/server/scene/surface_stack.cpp (+2/-1)
src/server/scene/surface_stack.h (+4/-3)
tests/acceptance-tests/test_unresponsive_client.cpp (+12/-3)
tests/include/mir/test/stub_server_tool.h (+24/-7)
tests/include/mir/test/test_protobuf_client.h (+26/-50)
tests/include/mir_test_framework/stub_input_platform.h (+2/-0)
tests/mir_test_doubles/test_protobuf_client.cpp (+86/-133)
tests/mir_test_framework/stub_input_platform.cpp (+4/-0)
tests/unit-tests/client/test_client_mir_surface.cpp (+5/-1)
tests/unit-tests/frontend/test_protobuf_reports_errors.cpp (+1/-1)
tests/unit-tests/frontend/test_protobuf_surface_apis.cpp (+3/-7)
tests/unit-tests/frontend/test_published_socket_connector.cpp (+32/-114)
tests/unit-tests/thread/test_basic_thread_pool.cpp (+2/-1)
To merge this branch: bzr merge lp:~albaguirre/mir/fix-tsan-findings
Reviewer Review Type Date Requested Status
Alan Griffiths Approve
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Abstain
Review via email: mp+279816@code.launchpad.net

Commit message

Fix TSan findings

Description of the change

Fix TSan findings

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

Umm unsure if I introduced an issue or uncovered one...I'll check tomorrow.

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

Changes look sensible, but from multiple motivations which makes reviewing harder.

Triggering a rebuild to get another datapoint

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

^-- the xenial-amd64 failure also happens with lp:mir, it's lp:1523965

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 :

Sounds good.

Hopefully we'll reach a point where we're clean enough to automate this in CI...

review: Approve
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

We had a CI job that ran Thread Sanitizer with a clang build. I believe it got axed after the GCC5/clang fiasco.

So now with Jenkass we should setup a GCC TSan job.

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 :

Failed due to lots of FD leaks. Is that right?

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

I'd really like to approve a lot of these changes as they are obviously correct.

But the rework of CompositingFunctor::operator() isn't...

~~~~

+ //Appease TSan, avoid destructor and this thread accessing the same shared_ptr instance
+ auto disp_listener = std::move(display_listener);

As display_listener is const, isn't this simpler as:

    auto const disp_listener = display_listener;

Or even better, just make it a value capture in the lines below? Vis:

        auto display_registration = mir::raii::paired_calls(
            [display_listener=display_listener, &group=group]{group.for_each_display_buffer([&](mg::DisplayBuffer& buffer)
                { display_listener->add_display(buffer.view_area()); });},
            [display_listener=display_listener, &group=group]{group.for_each_display_buffer([&](mg::DisplayBuffer& buffer)
                { display_listener->remove_display(buffer.view_area()); });});

~~~~

- auto on_startup_failure = on_unwind(
- [this]
- {
- if (started_future.wait_for(0s) != std::future_status::ready)
- started.set_exception(std::current_exception());
- });
-
...
     catch(...)
     {
+ try
+ {
+ //Move the promise so that the promise destructor occurs here rather than in the thread
+ //destroying CompositingFunctor, mostly to appease TSan
+ auto promise = std::move(started);
+ promise.set_exception(std::current_exception());
+ }
+ catch(...)
+ {
+ }

So we no longer use "on_unwind()" because the destructor of the moved promise will throw after we set_exception()? And then we eat the exception anyway? That seems an overly complex mechanism to destroy CompositingFunctor::promise.

review: Needs Fixing
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

>As display_listener is const, isn't this simpler as:

> auto const disp_listener = display_listener;

The MP code I propose avoids an unnecessary ref count increase, but sure I can make that change.

>Or even better, just make it a value capture in the lines below? Vis:

You cannot capture a member variable directly; you can only through access through "this" (or by creating a local reference that the lambda can then capture).

> So we no longer use "on_unwind()" because the destructor of the moved promise
> will throw after we set_exception()? And then we eat the exception anyway?
> That seems an overly complex mechanism to destroy CompositingFunctor::promise.

No. I didn't see a need for unwind helper since we already have a catch block.

The main motivation is not removing the unwind helper, it's removing the query of std::future since it's not threadsafe (std::future sate would be accessed by two threads). Rather than synchronizing that access, I avoid querying the std::future at all. Since I won't check its status, then set_exception may throw if it already has a value and so we eat the exception.

The move of the std::promise is also to avoid two threads access std::promise state, the thread calling the destructor and the thread accessing the promise (the compositing thread).

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

> >As display_listener is const, isn't this simpler as:
>
> > auto const disp_listener = display_listener;
>
> The MP code I propose avoids an unnecessary ref count increase, but sure I can
> make that change.

Don't we get a single ref count increment in both cases? The proposed version can't move from a const display_listener so an unnamed temporary is created for the move.

> >Or even better, just make it a value capture in the lines below? Vis:
>
> You cannot capture a member variable directly; you can only through access
> through "this" (or by creating a local reference that the lambda can then
> capture).

I gave the syntax I was thinking of. Admittedly, that does create two copies of display_listener.

~~~~

> > So we no longer use "on_unwind()" because the destructor of the moved
> promise
> > will throw after we set_exception()? And then we eat the exception anyway?
> > That seems an overly complex mechanism to destroy
> CompositingFunctor::promise.
>
> No. I didn't see a need for unwind helper since we already have a catch block.
>
> The main motivation is not removing the unwind helper, it's removing the query
> of std::future since it's not threadsafe (std::future sate would be accessed
> by two threads). Rather than synchronizing that access, I avoid querying the
> std::future at all. Since I won't check its status, then set_exception may
> throw if it already has a value and so we eat the exception.
>
> The move of the std::promise is also to avoid two threads access std::promise
> state, the thread calling the destructor and the thread accessing the promise
> (the compositing thread).

I need to think about this - it sounds like the wrong synchronization objects are being used.

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3189
http://jenkins.qa.ubuntu.com/job/mir-ci/5845/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5307
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4213
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5256
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/155/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/173
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/173/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/173
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/173/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5256
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5256/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/7776
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26032
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/153
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/153/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/12/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26039

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ci/5845/rebuild

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

OK, I still think the logic around started/started_future is expressed poorly, but that's pre-existing and not worth blocking on.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cmake/MirCommon.cmake'
--- cmake/MirCommon.cmake 2015-12-14 06:21:46 +0000
+++ cmake/MirCommon.cmake 2015-12-14 15:38:49 +0000
@@ -74,7 +74,9 @@
74 endif()74 endif()
75 endif()75 endif()
76 # Space after ${TSAN_EXTRA_OPTIONS} works around bug in TSAN env. variable parsing 76 # Space after ${TSAN_EXTRA_OPTIONS} works around bug in TSAN env. variable parsing
77 list(APPEND test_env "TSAN_OPTIONS=\"suppressions=${CMAKE_SOURCE_DIR}/tools/tsan-suppressions second_deadlock_stack=1 halt_on_error=1 history_size=7 ${TSAN_EXTRA_OPTIONS} \"")77 list(APPEND test_env "TSAN_OPTIONS=\"suppressions=${CMAKE_SOURCE_DIR}/tools/tsan-suppressions second_deadlock_stack=1 halt_on_error=1 history_size=7 die_after_fork=0 ${TSAN_EXTRA_OPTIONS} \"")
78 # TSan does not support starting threads after fork
79 set(test_exclusion_filter "ThreadedDispatcherSignalTest.keeps_dispatching_after_signal_interruption")
78 endif()80 endif()
7981
80 if(SYSTEM_SUPPORTS_O_TMPFILE EQUAL 1)82 if(SYSTEM_SUPPORTS_O_TMPFILE EQUAL 1)
8183
=== modified file 'src/server/compositor/buffer_stream_surfaces.cpp'
--- src/server/compositor/buffer_stream_surfaces.cpp 2015-11-21 00:23:00 +0000
+++ src/server/compositor/buffer_stream_surfaces.cpp 2015-12-14 15:38:49 +0000
@@ -59,20 +59,20 @@
59{59{
60 buffer_bundle->client_release(buf);60 buffer_bundle->client_release(buf);
61 {61 {
62 std::unique_lock<std::mutex> lk(mutex);62 std::lock_guard<decltype(mutex)> lk(mutex);
63 first_frame_posted = true;63 first_frame_posted = true;
64 }64 }
65}65}
6666
67geom::Size mc::BufferStreamSurfaces::stream_size()67geom::Size mc::BufferStreamSurfaces::stream_size()
68{68{
69 std::unique_lock<std::mutex> lk(mutex);69 std::lock_guard<decltype(mutex)> lk(mutex);
70 return logical_size;70 return logical_size;
71}71}
7272
73void mc::BufferStreamSurfaces::resize(geom::Size const& size)73void mc::BufferStreamSurfaces::resize(geom::Size const& size)
74{74{
75 std::unique_lock<std::mutex> lk(mutex);75 std::lock_guard<decltype(mutex)> lk(mutex);
76 logical_size = size;76 logical_size = size;
77 buffer_bundle->resize(logical_size * scale);77 buffer_bundle->resize(logical_size * scale);
78}78}
@@ -117,14 +117,17 @@
117117
118bool mc::BufferStreamSurfaces::has_submitted_buffer() const118bool mc::BufferStreamSurfaces::has_submitted_buffer() const
119{119{
120 std::unique_lock<std::mutex> lk(mutex);120 std::lock_guard<decltype(mutex)> lk(mutex);
121 return first_frame_posted;121 return first_frame_posted;
122}122}
123123
124void mc::BufferStreamSurfaces::with_most_recent_buffer_do(std::function<void(graphics::Buffer&)> const& exec)124void mc::BufferStreamSurfaces::with_most_recent_buffer_do(std::function<void(graphics::Buffer&)> const& exec)
125{125{
126 if (!first_frame_posted)126 {
127 BOOST_THROW_EXCEPTION(std::runtime_error("No frame posted yet"));127 std::lock_guard<decltype(mutex)> lk(mutex);
128 if (!first_frame_posted)
129 BOOST_THROW_EXCEPTION(std::runtime_error("No frame posted yet"));
130 }
128 exec(*std::make_shared<mc::TemporarySnapshotBuffer>(buffer_bundle));131 exec(*std::make_shared<mc::TemporarySnapshotBuffer>(buffer_bundle));
129}132}
130133
@@ -164,7 +167,7 @@
164 if (new_scale <= 0.0f)167 if (new_scale <= 0.0f)
165 BOOST_THROW_EXCEPTION(std::logic_error("invalid scale (must be greater than zero)"));168 BOOST_THROW_EXCEPTION(std::logic_error("invalid scale (must be greater than zero)"));
166169
167 std::unique_lock<std::mutex> lk(mutex);170 std::lock_guard<decltype(mutex)> lk(mutex);
168 scale = new_scale;171 scale = new_scale;
169 buffer_bundle->resize(logical_size * scale);172 buffer_bundle->resize(logical_size * scale);
170}173}
171174
=== modified file 'src/server/compositor/multi_threaded_compositor.cpp'
--- src/server/compositor/multi_threaded_compositor.cpp 2015-09-22 14:53:26 +0000
+++ src/server/compositor/multi_threaded_compositor.cpp 2015-12-14 15:38:49 +0000
@@ -73,13 +73,6 @@
73 void operator()() noexcept // noexcept is important! (LP: #1237332)73 void operator()() noexcept // noexcept is important! (LP: #1237332)
74 try74 try
75 {75 {
76 auto on_startup_failure = on_unwind(
77 [this]
78 {
79 if (started_future.wait_for(0s) != std::future_status::ready)
80 started.set_exception(std::current_exception());
81 });
82
83 mir::set_thread_name("Mir/Comp");76 mir::set_thread_name("Mir/Comp");
8477
85 std::vector<std::tuple<mg::DisplayBuffer*, std::unique_ptr<mc::DisplayBufferCompositor>>> compositors;78 std::vector<std::tuple<mg::DisplayBuffer*, std::unique_ptr<mc::DisplayBufferCompositor>>> compositors;
@@ -96,11 +89,13 @@
96 CompositorReport::SubCompositorId{comp_id});89 CompositorReport::SubCompositorId{comp_id});
97 });90 });
9891
92 //Appease TSan, avoid destructor and this thread accessing the same shared_ptr instance
93 auto const disp_listener = display_listener;
99 auto display_registration = mir::raii::paired_calls(94 auto display_registration = mir::raii::paired_calls(
100 [this]{group.for_each_display_buffer([this](mg::DisplayBuffer& buffer)95 [this, &disp_listener]{group.for_each_display_buffer([&disp_listener](mg::DisplayBuffer& buffer)
101 { display_listener->add_display(buffer.view_area()); });},96 { disp_listener->add_display(buffer.view_area()); });},
102 [this]{group.for_each_display_buffer([this](mg::DisplayBuffer& buffer)97 [this, &disp_listener]{group.for_each_display_buffer([&disp_listener](mg::DisplayBuffer& buffer)
103 { display_listener->remove_display(buffer.view_area()); });});98 { disp_listener->remove_display(buffer.view_area()); });});
10499
105 auto compositor_registration = mir::raii::paired_calls(100 auto compositor_registration = mir::raii::paired_calls(
106 [this,&compositors]101 [this,&compositors]
@@ -179,6 +174,16 @@
179 }174 }
180 catch(...)175 catch(...)
181 {176 {
177 try
178 {
179 //Move the promise so that the promise destructor occurs here rather than in the thread
180 //destroying CompositingFunctor, mostly to appease TSan
181 auto promise = std::move(started);
182 promise.set_exception(std::current_exception());
183 }
184 catch(...)
185 {
186 }
182 mir::terminate_with_current_exception();187 mir::terminate_with_current_exception();
183 }188 }
184189
185190
=== modified file 'src/server/scene/surface_stack.cpp'
--- src/server/scene/surface_stack.cpp 2015-12-03 23:57:09 +0000
+++ src/server/scene/surface_stack.cpp 2015-12-14 15:38:49 +0000
@@ -121,7 +121,8 @@
121121
122ms::SurfaceStack::SurfaceStack(122ms::SurfaceStack::SurfaceStack(
123 std::shared_ptr<SceneReport> const& report) :123 std::shared_ptr<SceneReport> const& report) :
124 report{report}124 report{report},
125 scene_changed{false}
125{126{
126}127}
127128
128129
=== modified file 'src/server/scene/surface_stack.h'
--- src/server/scene/surface_stack.h 2015-12-03 10:28:45 +0000
+++ src/server/scene/surface_stack.h 2015-12-14 15:38:49 +0000
@@ -28,11 +28,12 @@
2828
29#include "mir/basic_observers.h"29#include "mir/basic_observers.h"
3030
31#include <atomic>
32#include <map>
31#include <memory>33#include <memory>
32#include <vector>
33#include <mutex>34#include <mutex>
34#include <map>
35#include <set>35#include <set>
36#include <vector>
3637
37namespace mir38namespace mir
38{39{
@@ -119,7 +120,7 @@
119 std::vector<std::shared_ptr<graphics::Renderable>> overlays;120 std::vector<std::shared_ptr<graphics::Renderable>> overlays;
120121
121 Observers observers;122 Observers observers;
122 bool scene_changed = false;123 std::atomic<bool> scene_changed;
123};124};
124125
125}126}
126127
=== modified file 'tests/acceptance-tests/test_unresponsive_client.cpp'
--- tests/acceptance-tests/test_unresponsive_client.cpp 2015-07-28 09:09:00 +0000
+++ tests/acceptance-tests/test_unresponsive_client.cpp 2015-12-14 15:38:49 +0000
@@ -32,8 +32,9 @@
32#include <gtest/gtest.h>32#include <gtest/gtest.h>
33#include <gmock/gmock.h>33#include <gmock/gmock.h>
3434
35#include <future>
36#include <mutex>
35#include <string>37#include <string>
36#include <future>
3738
38namespace ms = mir::scene;39namespace ms = mir::scene;
39namespace mt = mir::test;40namespace mt = mir::test;
@@ -45,19 +46,27 @@
45{46{
46struct SessionListener : ms::NullSessionListener47struct SessionListener : ms::NullSessionListener
47{48{
49 ~SessionListener()
50 {
51 std::lock_guard<decltype(guard)> lk{guard};
52 sessions.clear();
53 }
54
48 void starting(std::shared_ptr<ms::Session> const& session) override55 void starting(std::shared_ptr<ms::Session> const& session) override
49 { sessions.insert(session); }56 { std::lock_guard<decltype(guard)> lk{guard}; sessions.insert(session); }
5057
51 void stopping(std::shared_ptr<ms::Session> const& session) override58 void stopping(std::shared_ptr<ms::Session> const& session) override
52 { sessions.erase(session); }59 { std::lock_guard<decltype(guard)> lk{guard}; sessions.erase(session); }
5360
54 void for_each(std::function<void(std::shared_ptr<ms::Session> const&)> f) const61 void for_each(std::function<void(std::shared_ptr<ms::Session> const&)> f) const
55 {62 {
63 std::lock_guard<decltype(guard)> lk{guard};
56 for (auto& session : sessions)64 for (auto& session : sessions)
57 f(session);65 f(session);
58 }66 }
5967
60private:68private:
69 std::mutex mutable guard;
61 std::set<std::shared_ptr<ms::Session>> sessions;70 std::set<std::shared_ptr<ms::Session>> sessions;
62};71};
63}72}
6473
=== modified file 'tests/include/mir/test/stub_server_tool.h'
--- tests/include/mir/test/stub_server_tool.h 2015-09-18 14:44:59 +0000
+++ tests/include/mir/test/stub_server_tool.h 2015-12-14 15:38:49 +0000
@@ -44,8 +44,8 @@
44 response->set_pixel_format(request->pixel_format());44 response->set_pixel_format(request->pixel_format());
45 response->mutable_buffer()->set_buffer_id(22);45 response->mutable_buffer()->set_buffer_id(22);
4646
47 std::unique_lock<std::mutex> lock(guard);47 std::lock_guard<std::mutex> lock(guard);
48 surface_name = request->surface_name();48 surf_name = request->surface_name();
49 wait_condition.notify_one();49 wait_condition.notify_one();
5050
51 done->Run();51 done->Run();
@@ -58,7 +58,8 @@
58 {58 {
59 response->set_buffer_id(22);59 response->set_buffer_id(22);
6060
61 std::unique_lock<std::mutex> lock(guard);61 std::lock_guard<std::mutex> lock(guard);
62 //FIXME: huh? What's the condition here?
62 wait_condition.notify_one();63 wait_condition.notify_one();
63 done->Run();64 done->Run();
64 }65 }
@@ -78,7 +79,10 @@
78 mir::protobuf::Connection* connect_msg,79 mir::protobuf::Connection* connect_msg,
79 google::protobuf::Closure* done) override80 google::protobuf::Closure* done) override
80 {81 {
81 app_name = request->application_name();82 {
83 std::lock_guard<std::mutex> lock(guard);
84 app_name = request->application_name();
85 }
82 // If you check out MirConnection::connected either the platform and display_configuration86 // If you check out MirConnection::connected either the platform and display_configuration
83 // have to be set or the error has to be set, otherwise we die and fail to callback.87 // have to be set or the error has to be set, otherwise we die and fail to callback.
84 //88 //
@@ -95,7 +99,8 @@
95 mir::protobuf::Void* /*response*/,99 mir::protobuf::Void* /*response*/,
96 google::protobuf::Closure* done) override100 google::protobuf::Closure* done) override
97 {101 {
98 std::unique_lock<std::mutex> lock(guard);102 std::lock_guard<std::mutex> lock(guard);
103 //FIXME: huh? What's the condition here?
99 wait_condition.notify_one();104 wait_condition.notify_one();
100 done->Run();105 done->Run();
101 }106 }
@@ -108,8 +113,20 @@
108 done->Run();113 done->Run();
109 }114 }
110115
111 std::mutex guard;116 std::string application_name() const
112 std::string surface_name;117 {
118 std::lock_guard<std::mutex> lock(guard);
119 return app_name;
120 }
121
122 std::string surface_name() const
123 {
124 std::lock_guard<std::mutex> lock(guard);
125 return surf_name;
126 }
127
128 std::mutex mutable guard;
129 std::string surf_name;
113 std::condition_variable wait_condition;130 std::condition_variable wait_condition;
114 std::string app_name;131 std::string app_name;
115};132};
116133
=== modified file 'tests/include/mir/test/test_protobuf_client.h'
--- tests/include/mir/test/test_protobuf_client.h 2015-09-18 14:44:59 +0000
+++ tests/include/mir/test/test_protobuf_client.h 2015-12-14 15:38:49 +0000
@@ -26,8 +26,10 @@
2626
27#include <gmock/gmock.h>27#include <gmock/gmock.h>
2828
29#include <memory>29#include <condition_variable>
30#include <atomic>30#include <functional>
31#include <mutex>
32#include <string>
3133
32namespace mir34namespace mir
33{35{
@@ -63,69 +65,43 @@
63 MOCK_METHOD0(connect_done, void());65 MOCK_METHOD0(connect_done, void());
64 MOCK_METHOD0(create_surface_done, void());66 MOCK_METHOD0(create_surface_done, void());
65 MOCK_METHOD0(next_buffer_done, void());67 MOCK_METHOD0(next_buffer_done, void());
66 MOCK_METHOD0(exchange_buffer_done, void());
67 MOCK_METHOD0(release_surface_done, void());
68 MOCK_METHOD0(disconnect_done, void());68 MOCK_METHOD0(disconnect_done, void());
69 MOCK_METHOD0(display_configure_done, void());69 MOCK_METHOD0(display_configure_done, void());
70 MOCK_METHOD0(prompt_session_start_done, void());
71 MOCK_METHOD0(prompt_session_stop_done, void());
7270
73 void on_connect_done();71 void on_connect_done();
74
75 void on_create_surface_done();72 void on_create_surface_done();
76
77 void on_next_buffer_done();73 void on_next_buffer_done();
78
79 void on_exchange_buffer_done();
80
81 void on_release_surface_done();
82
83 void on_disconnect_done();74 void on_disconnect_done();
84
85 void on_configure_display_done();75 void on_configure_display_done();
8676
77 void connect();
78 void disconnect();
79 void create_surface();
80 void next_buffer();
81 void configure_display();
82
87 void wait_for_connect_done();83 void wait_for_connect_done();
88
89 void wait_for_create_surface();84 void wait_for_create_surface();
90
91 void wait_for_next_buffer();85 void wait_for_next_buffer();
92
93 void wait_for_exchange_buffer();
94
95 void wait_for_release_surface();
96
97 void wait_for_disconnect_done();86 void wait_for_disconnect_done();
9887 void wait_for_configure_display_done();
99 void wait_for_surface_count(int count);88 void wait_for_surface_count(int count);
10089
101 void wait_for_disconnect_count(int count);90 void wait_for(std::function<bool()> const& predicate, std::string const& error_message);
10291 void signal_condition(bool& condition);
103 void tfd_done();92 void reset_condition(bool& condition);
10493
105 void wait_for_tfd_done();94 int const maxwait;
10695 bool connect_done_called;
107 void wait_for_configure_display_done();96 bool create_surface_called;
10897 bool next_buffer_called;
109 void wait_for_prompt_session_start_done();98 bool exchange_buffer_called;
11099 bool disconnect_done_called;
111 void wait_for_prompt_session_stop_done();100 bool configure_display_done_called;
112101 int create_surface_done_count;
113 const int maxwait;102
114 std::atomic<bool> connect_done_called;103 std::mutex mutable guard;
115 std::atomic<bool> create_surface_called;104 std::condition_variable cv;
116 std::atomic<bool> next_buffer_called;
117 std::atomic<bool> exchange_buffer_called;
118 std::atomic<bool> release_surface_called;
119 std::atomic<bool> disconnect_done_called;
120 std::atomic<bool> configure_display_done_called;
121 std::atomic<bool> tfd_done_called;
122
123 WaitCondition wc_prompt_session_start;
124 WaitCondition wc_prompt_session_stop;
125
126 std::atomic<int> connect_done_count;
127 std::atomic<int> create_surface_done_count;
128 std::atomic<int> disconnect_done_count;
129};105};
130}106}
131}107}
132108
=== modified file 'tests/include/mir_test_framework/stub_input_platform.h'
--- tests/include/mir_test_framework/stub_input_platform.h 2015-10-14 15:22:39 +0000
+++ tests/include/mir_test_framework/stub_input_platform.h 2015-12-14 15:38:49 +0000
@@ -21,6 +21,7 @@
21#include "mir/input/platform.h"21#include "mir/input/platform.h"
22#include <atomic>22#include <atomic>
23#include <memory>23#include <memory>
24#include <mutex>
24#include <vector>25#include <vector>
2526
26namespace mir27namespace mir
@@ -59,6 +60,7 @@
59 std::shared_ptr<mir::input::InputDeviceRegistry> const registry;60 std::shared_ptr<mir::input::InputDeviceRegistry> const registry;
60 static std::atomic<StubInputPlatform*> stub_input_platform;61 static std::atomic<StubInputPlatform*> stub_input_platform;
61 static std::vector<std::weak_ptr<mir::input::InputDevice>> device_store;62 static std::vector<std::weak_ptr<mir::input::InputDevice>> device_store;
63 static std::mutex device_store_guard;
62};64};
6365
64}66}
6567
=== modified file 'tests/mir_test_doubles/test_protobuf_client.cpp'
--- tests/mir_test_doubles/test_protobuf_client.cpp 2015-09-18 14:44:59 +0000
+++ tests/mir_test_doubles/test_protobuf_client.cpp 2015-12-14 15:38:49 +0000
@@ -29,15 +29,16 @@
29#include "mir/dispatch/threaded_dispatcher.h"29#include "mir/dispatch/threaded_dispatcher.h"
30#include "mir/events/event_private.h"30#include "mir/events/event_private.h"
3131
32#include <boost/throw_exception.hpp>
33
34#include <stdexcept>
32#include <thread>35#include <thread>
3336
34namespace mtd = mir::test::doubles;37namespace mtd = mir::test::doubles;
35namespace mclr = mir::client::rpc;38namespace mclr = mir::client::rpc;
36namespace md = mir::dispatch;39namespace md = mir::dispatch;
3740
38mir::test::TestProtobufClient::TestProtobufClient(41mir::test::TestProtobufClient::TestProtobufClient(std::string socket_file, int timeout_ms) :
39 std::string socket_file,
40 int timeout_ms) :
41 rpc_report(std::make_shared<testing::NiceMock<doubles::MockRpcReport>>()),42 rpc_report(std::make_shared<testing::NiceMock<doubles::MockRpcReport>>()),
42 channel(mclr::make_rpc_channel(43 channel(mclr::make_rpc_channel(
43 socket_file,44 socket_file,
@@ -54,13 +55,9 @@
54 create_surface_called(false),55 create_surface_called(false),
55 next_buffer_called(false),56 next_buffer_called(false),
56 exchange_buffer_called(false),57 exchange_buffer_called(false),
57 release_surface_called(false),
58 disconnect_done_called(false),58 disconnect_done_called(false),
59 configure_display_done_called(false),59 configure_display_done_called(false),
60 tfd_done_called(false),60 create_surface_done_count(0)
61 connect_done_count(0),
62 create_surface_done_count(0),
63 disconnect_done_count(0)
64{61{
65 surface_parameters.set_width(640);62 surface_parameters.set_width(640);
66 surface_parameters.set_height(480);63 surface_parameters.set_height(480);
@@ -76,177 +73,133 @@
76 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_create_surface_done));73 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_create_surface_done));
77 ON_CALL(*this, next_buffer_done())74 ON_CALL(*this, next_buffer_done())
78 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_next_buffer_done));75 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_next_buffer_done));
79 ON_CALL(*this, exchange_buffer_done())
80 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_exchange_buffer_done));
81 ON_CALL(*this, release_surface_done())
82 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_release_surface_done));
83 ON_CALL(*this, disconnect_done())76 ON_CALL(*this, disconnect_done())
84 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_disconnect_done));77 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_disconnect_done));
85 ON_CALL(*this, display_configure_done())78 ON_CALL(*this, display_configure_done())
86 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_configure_display_done));79 .WillByDefault(testing::Invoke(this, &TestProtobufClient::on_configure_display_done));
87 ON_CALL(*this, prompt_session_start_done())80}
88 .WillByDefault(testing::Invoke(&wc_prompt_session_start, &WaitCondition::wake_up_everyone));81
89 ON_CALL(*this, prompt_session_stop_done())82void mir::test::TestProtobufClient::signal_condition(bool& condition)
90 .WillByDefault(testing::Invoke(&wc_prompt_session_stop, &WaitCondition::wake_up_everyone));83{
84 std::lock_guard<decltype(guard)> lk{guard};
85 condition = true;
86 cv.notify_all();
87}
88
89void mir::test::TestProtobufClient::reset_condition(bool& condition)
90{
91 std::lock_guard<decltype(guard)> lk{guard};
92 condition = false;
91}93}
9294
93void mir::test::TestProtobufClient::on_connect_done()95void mir::test::TestProtobufClient::on_connect_done()
94{96{
95 connect_done_called.store(true);97 signal_condition(connect_done_called);
96
97 auto old = connect_done_count.load();
98
99 while (!connect_done_count.compare_exchange_weak(old, old+1));
100}98}
10199
102void mir::test::TestProtobufClient::on_create_surface_done()100void mir::test::TestProtobufClient::on_create_surface_done()
103{101{
104 create_surface_called.store(true);102 std::lock_guard<decltype(guard)> lk{guard};
105103 create_surface_called = true;
106 auto old = create_surface_done_count.load();104 create_surface_done_count++;
107105 cv.notify_all();
108 while (!create_surface_done_count.compare_exchange_weak(old, old+1));
109}106}
110107
111void mir::test::TestProtobufClient::on_next_buffer_done()108void mir::test::TestProtobufClient::on_next_buffer_done()
112{109{
113 next_buffer_called.store(true);110 signal_condition(next_buffer_called);
114}
115
116void mir::test::TestProtobufClient::on_exchange_buffer_done()
117{
118 exchange_buffer_called.store(true);
119}
120
121void mir::test::TestProtobufClient::on_release_surface_done()
122{
123 release_surface_called.store(true);
124}111}
125112
126void mir::test::TestProtobufClient::on_disconnect_done()113void mir::test::TestProtobufClient::on_disconnect_done()
127{114{
128 disconnect_done_called.store(true);115 signal_condition(disconnect_done_called);
129
130 auto old = disconnect_done_count.load();
131
132 while (!disconnect_done_count.compare_exchange_weak(old, old+1));
133}116}
134117
135void mir::test::TestProtobufClient::on_configure_display_done()118void mir::test::TestProtobufClient::on_configure_display_done()
136{119{
137 configure_display_done_called.store(true);120 signal_condition(configure_display_done_called);
121}
122
123void mir::test::TestProtobufClient::connect()
124{
125 reset_condition(connect_done_called);
126 display_server.connect(
127 &connect_parameters,
128 &connection,
129 google::protobuf::NewCallback(this, &TestProtobufClient::connect_done));
130}
131
132void mir::test::TestProtobufClient::disconnect()
133{
134 reset_condition(disconnect_done_called);
135 display_server.disconnect(
136 &ignored,
137 &ignored,
138 google::protobuf::NewCallback(this, &TestProtobufClient::disconnect_done));
139}
140
141void mir::test::TestProtobufClient::create_surface()
142{
143 reset_condition(create_surface_called);
144 display_server.create_surface(
145 &surface_parameters,
146 &surface,
147 google::protobuf::NewCallback(this, &TestProtobufClient::create_surface_done));
148}
149
150void mir::test::TestProtobufClient::next_buffer()
151{
152 reset_condition(next_buffer_called);
153 display_server.next_buffer(
154 &surface.id(),
155 surface.mutable_buffer(),
156 google::protobuf::NewCallback(this, &TestProtobufClient::next_buffer_done));
157}
158
159void mir::test::TestProtobufClient::configure_display()
160{
161 reset_condition(configure_display_done_called);
162 display_server.configure_display(
163 &disp_config,
164 &disp_config_response,
165 google::protobuf::NewCallback(this, &TestProtobufClient::display_configure_done));
138}166}
139167
140void mir::test::TestProtobufClient::wait_for_configure_display_done()168void mir::test::TestProtobufClient::wait_for_configure_display_done()
141{169{
142 for (int i = 0; !configure_display_done_called.load() && i < maxwait; ++i)170 wait_for([this]{ return configure_display_done_called; }, "Timed out waiting to configure display");
143 {
144 std::this_thread::sleep_for(std::chrono::milliseconds(1));
145 std::this_thread::yield();
146 }
147
148 configure_display_done_called.store(false);
149}171}
150172
151void mir::test::TestProtobufClient::wait_for_connect_done()173void mir::test::TestProtobufClient::wait_for_connect_done()
152{174{
153 for (int i = 0; !connect_done_called.load() && i < maxwait; ++i)175 wait_for([this]{ return connect_done_called; }, "Timed out waiting to connect");
154 {
155 std::this_thread::sleep_for(std::chrono::milliseconds(1));
156 std::this_thread::yield();
157 }
158
159 connect_done_called.store(false);
160}176}
161177
162void mir::test::TestProtobufClient::wait_for_create_surface()178void mir::test::TestProtobufClient::wait_for_create_surface()
163{179{
164 for (int i = 0; !create_surface_called.load() && i < maxwait; ++i)180 wait_for([this]{ return create_surface_called; }, "Timed out waiting create surface");
165 {
166 std::this_thread::sleep_for(std::chrono::milliseconds(1));
167 std::this_thread::yield();
168 }
169 create_surface_called.store(false);
170}181}
171182
172void mir::test::TestProtobufClient::wait_for_next_buffer()183void mir::test::TestProtobufClient::wait_for_next_buffer()
173{184{
174 for (int i = 0; !next_buffer_called.load() && i < maxwait; ++i)185 wait_for([this] { return next_buffer_called; }, "Timed out waiting for next buffer");
175 {
176 std::this_thread::sleep_for(std::chrono::milliseconds(1));
177 std::this_thread::yield();
178 }
179 next_buffer_called.store(false);
180}
181
182void mir::test::TestProtobufClient::wait_for_exchange_buffer()
183{
184 for (int i = 0; !exchange_buffer_called.load() && i < maxwait; ++i)
185 {
186 std::this_thread::sleep_for(std::chrono::milliseconds(1));
187 std::this_thread::yield();
188 }
189 exchange_buffer_called.store(false);
190}
191
192void mir::test::TestProtobufClient::wait_for_release_surface()
193{
194 for (int i = 0; !release_surface_called.load() && i < maxwait; ++i)
195 {
196 std::this_thread::sleep_for(std::chrono::milliseconds(1));
197 std::this_thread::yield();
198 }
199 release_surface_called.store(false);
200}186}
201187
202void mir::test::TestProtobufClient::wait_for_disconnect_done()188void mir::test::TestProtobufClient::wait_for_disconnect_done()
203{189{
204 for (int i = 0; !disconnect_done_called.load() && i < maxwait; ++i)190 wait_for([this] { return disconnect_done_called; }, "Timed out waiting to disconnect");
205 {
206 std::this_thread::sleep_for(std::chrono::milliseconds(1));
207 std::this_thread::yield();
208 }
209 disconnect_done_called.store(false);
210}191}
211192
212void mir::test::TestProtobufClient::wait_for_surface_count(int count)193void mir::test::TestProtobufClient::wait_for_surface_count(int count)
213{194{
214 for (int i = 0; count != create_surface_done_count.load() && i < 10000; ++i)195 wait_for([this, count] { return create_surface_done_count == count; }, "Timed out waiting for surface count");
215 {196}
216 std::this_thread::sleep_for(std::chrono::milliseconds(10));197
217 std::this_thread::yield();198void mir::test::TestProtobufClient::wait_for(std::function<bool()> const& predicate, std::string const& error_message)
218 }199{
219}200 std::unique_lock<decltype(guard)> lk{guard};
220201 if (!cv.wait_for(lk, std::chrono::milliseconds(maxwait), predicate))
221void mir::test::TestProtobufClient::wait_for_disconnect_count(int count)202 {
222{203 BOOST_THROW_EXCEPTION(std::runtime_error(error_message));
223 for (int i = 0; count != disconnect_done_count.load() && i < 10000; ++i)204 }
224 {
225 std::this_thread::sleep_for(std::chrono::milliseconds(10));
226 std::this_thread::yield();
227 }
228}
229
230void mir::test::TestProtobufClient::tfd_done()
231{
232 tfd_done_called.store(true);
233}
234
235void mir::test::TestProtobufClient::wait_for_tfd_done()
236{
237 for (int i = 0; !tfd_done_called.load() && i < maxwait; ++i)
238 {
239 std::this_thread::sleep_for(std::chrono::milliseconds(1));
240 }
241 tfd_done_called.store(false);
242}
243
244void mir::test::TestProtobufClient::wait_for_prompt_session_start_done()
245{
246 wc_prompt_session_start.wait_for_at_most_seconds(maxwait);
247}
248
249void mir::test::TestProtobufClient::wait_for_prompt_session_stop_done()
250{
251 wc_prompt_session_stop.wait_for_at_most_seconds(maxwait);
252}205}
253206
=== modified file 'tests/mir_test_framework/stub_input_platform.cpp'
--- tests/mir_test_framework/stub_input_platform.cpp 2015-10-14 15:22:39 +0000
+++ tests/mir_test_framework/stub_input_platform.cpp 2015-12-14 15:38:49 +0000
@@ -40,12 +40,14 @@
4040
41mtf::StubInputPlatform::~StubInputPlatform()41mtf::StubInputPlatform::~StubInputPlatform()
42{42{
43 std::lock_guard<decltype(device_store_guard)> lk{device_store_guard};
43 device_store.clear();44 device_store.clear();
44 stub_input_platform = nullptr;45 stub_input_platform = nullptr;
45}46}
4647
47void mtf::StubInputPlatform::start()48void mtf::StubInputPlatform::start()
48{49{
50 std::lock_guard<decltype(device_store_guard)> lk{device_store_guard};
49 for (auto const& dev : device_store)51 for (auto const& dev : device_store)
50 {52 {
51 auto device = dev.lock();53 auto device = dev.lock();
@@ -74,6 +76,7 @@
74 auto input_platform = stub_input_platform.load();76 auto input_platform = stub_input_platform.load();
75 if (!input_platform)77 if (!input_platform)
76 {78 {
79 std::lock_guard<decltype(device_store_guard)> lk{device_store_guard};
77 device_store.push_back(dev);80 device_store.push_back(dev);
78 return;81 return;
79 }82 }
@@ -118,3 +121,4 @@
118121
119std::atomic<mtf::StubInputPlatform*> mtf::StubInputPlatform::stub_input_platform{nullptr};122std::atomic<mtf::StubInputPlatform*> mtf::StubInputPlatform::stub_input_platform{nullptr};
120std::vector<std::weak_ptr<mir::input::InputDevice>> mtf::StubInputPlatform::device_store;123std::vector<std::weak_ptr<mir::input::InputDevice>> mtf::StubInputPlatform::device_store;
124std::mutex mtf::StubInputPlatform::device_store_guard;
121125
=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
--- tests/unit-tests/client/test_client_mir_surface.cpp 2015-12-08 15:02:49 +0000
+++ tests/unit-tests/client/test_client_mir_surface.cpp 2015-12-14 15:38:49 +0000
@@ -98,7 +98,11 @@
98 google::protobuf::Closure* done) override98 google::protobuf::Closure* done) override
99 {99 {
100 create_surface_response(response);100 create_surface_response(response);
101 surface_name = request->surface_name();101 {
102 std::lock_guard<std::mutex> lock(guard);
103 surf_name = request->surface_name();
104 }
105
102 done->Run();106 done->Run();
103 }107 }
104108
105109
=== modified file 'tests/unit-tests/frontend/test_protobuf_reports_errors.cpp'
--- tests/unit-tests/frontend/test_protobuf_reports_errors.cpp 2015-07-28 20:51:25 +0000
+++ tests/unit-tests/frontend/test_protobuf_reports_errors.cpp 2015-12-14 15:38:49 +0000
@@ -81,7 +81,7 @@
81 {81 {
82 stub_services = std::make_shared<mt::ErrorServer>();82 stub_services = std::make_shared<mt::ErrorServer>();
83 server = std::make_shared<mt::TestProtobufServer>("./test_error_fixture", stub_services);83 server = std::make_shared<mt::TestProtobufServer>("./test_error_fixture", stub_services);
84 client = std::make_shared<mt::TestProtobufClient>("./test_error_fixture", 100);84 client = std::make_shared<mt::TestProtobufClient>("./test_error_fixture", 10000);
85 server->comm->start();85 server->comm->start();
86 }86 }
8787
8888
=== modified file 'tests/unit-tests/frontend/test_protobuf_surface_apis.cpp'
--- tests/unit-tests/frontend/test_protobuf_surface_apis.cpp 2015-07-28 20:51:25 +0000
+++ tests/unit-tests/frontend/test_protobuf_surface_apis.cpp 2015-12-14 15:38:49 +0000
@@ -85,7 +85,7 @@
8585
86 stub_server->comm->start();86 stub_server->comm->start();
8787
88 stub_client = std::make_shared<mt::TestProtobufClient>(mtf::test_socket_file(), 100);88 stub_client = std::make_shared<mt::TestProtobufClient>(mtf::test_socket_file(), 10000);
89 stub_client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);89 stub_client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);
90 }90 }
9191
@@ -136,11 +136,7 @@
136136
137 for (int i = 0; i != surface_count; ++i)137 for (int i = 0; i != surface_count; ++i)
138 {138 {
139 stub_client->display_server.create_surface(139 stub_client->create_surface();
140 &stub_client->surface_parameters,
141 &stub_client->surface,
142 google::protobuf::NewCallback(stub_client.get(), &mt::TestProtobufClient::create_surface_done));
143
144 stub_client->wait_for_create_surface();140 stub_client->wait_for_create_surface();
145 }141 }
146142
@@ -182,7 +178,7 @@
182178
183 for(int i=0; i<number_of_clients; i++)179 for(int i=0; i<number_of_clients; i++)
184 {180 {
185 auto client_tmp = std::make_shared<mt::TestProtobufClient>(mtf::test_socket_file(), 100);181 auto client_tmp = std::make_shared<mt::TestProtobufClient>(mtf::test_socket_file(), 10000);
186 clients.push_back(client_tmp);182 clients.push_back(client_tmp);
187 }183 }
188 }184 }
189185
=== modified file 'tests/unit-tests/frontend/test_published_socket_connector.cpp'
--- tests/unit-tests/frontend/test_published_socket_connector.cpp 2015-09-18 14:44:59 +0000
+++ tests/unit-tests/frontend/test_published_socket_connector.cpp 2015-12-14 15:38:49 +0000
@@ -29,20 +29,21 @@
2929
30#include "mir_protobuf.pb.h"30#include "mir_protobuf.pb.h"
3131
32#include "mir/test/doubles/stub_ipc_factory.h"
33#include "mir/test/doubles/stub_session_authorizer.h"
34#include "mir/test/doubles/mock_rpc_report.h"
35#include "mir/test/stub_server_tool.h"32#include "mir/test/stub_server_tool.h"
36#include "mir/test/test_protobuf_client.h"33#include "mir/test/test_protobuf_client.h"
37#include "mir/test/test_protobuf_server.h"34#include "mir/test/test_protobuf_server.h"
35#include "mir/test/wait_condition.h"
36#include "mir/test/doubles/stub_ipc_factory.h"
37#include "mir/test/doubles/stub_session_authorizer.h"
38#include "mir/test/doubles/mock_rpc_report.h"
38#include "mir/test/doubles/stub_ipc_factory.h"39#include "mir/test/doubles/stub_ipc_factory.h"
39#include "mir_test_framework/testing_server_configuration.h"40#include "mir_test_framework/testing_server_configuration.h"
4041
41#include <gtest/gtest.h>42#include <gtest/gtest.h>
42#include <gmock/gmock.h>43#include <gmock/gmock.h>
4344
45#include <memory>
44#include <stdexcept>46#include <stdexcept>
45#include <memory>
46#include <string>47#include <string>
4748
48namespace mf = mir::frontend;49namespace mf = mir::frontend;
@@ -139,11 +140,7 @@
139{140{
140 EXPECT_CALL(*client, create_surface_done()).Times(1);141 EXPECT_CALL(*client, create_surface_done()).Times(1);
141142
142 client->display_server.create_surface(143 client->create_surface();
143 &client->surface_parameters,
144 &client->surface,
145 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
146
147 client->wait_for_create_surface();144 client->wait_for_create_surface();
148}145}
149146
@@ -153,14 +150,10 @@
153150
154 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);151 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);
155152
156 client->display_server.connect(153 client->connect();
157 &client->connect_parameters,
158 &client->connection,
159 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::connect_done));
160
161 client->wait_for_connect_done();154 client->wait_for_connect_done();
162155
163 EXPECT_EQ(__PRETTY_FUNCTION__, stub_server_tool->app_name);156 EXPECT_EQ(__PRETTY_FUNCTION__, stub_server_tool->application_name());
164}157}
165158
166TEST_F(PublishedSocketConnector, create_surface_sets_surface_name)159TEST_F(PublishedSocketConnector, create_surface_sets_surface_name)
@@ -170,36 +163,23 @@
170163
171 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);164 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);
172165
173 client->display_server.connect(166 client->connect();
174 &client->connect_parameters,
175 &client->connection,
176 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::connect_done));
177
178 client->wait_for_connect_done();167 client->wait_for_connect_done();
179168
180 client->surface_parameters.set_surface_name(__PRETTY_FUNCTION__);169 client->surface_parameters.set_surface_name(__PRETTY_FUNCTION__);
181170
182 client->display_server.create_surface(171 client->create_surface();
183 &client->surface_parameters,
184 &client->surface,
185 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
186
187 client->wait_for_create_surface();172 client->wait_for_create_surface();
188173
189 EXPECT_EQ(__PRETTY_FUNCTION__, stub_server_tool->surface_name);174 EXPECT_EQ(__PRETTY_FUNCTION__, stub_server_tool->surface_name());
190}175}
191176
192
193TEST_F(PublishedSocketConnector,177TEST_F(PublishedSocketConnector,
194 create_surface_results_in_a_surface_being_created)178 create_surface_results_in_a_surface_being_created)
195{179{
196 EXPECT_CALL(*client, create_surface_done()).Times(1);180 EXPECT_CALL(*client, create_surface_done()).Times(1);
197181
198 client->display_server.create_surface(182 client->create_surface();
199 &client->surface_parameters,
200 &client->surface,
201 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
202
203 client->wait_for_create_surface();183 client->wait_for_create_surface();
204}184}
205185
@@ -218,19 +198,11 @@
218 using namespace testing;198 using namespace testing;
219199
220 EXPECT_CALL(*client, create_surface_done()).Times(1);200 EXPECT_CALL(*client, create_surface_done()).Times(1);
221 client->display_server.create_surface(201 client->create_surface();
222 &client->surface_parameters,
223 &client->surface,
224 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
225
226 client->wait_for_create_surface();202 client->wait_for_create_surface();
227203
228 EXPECT_CALL(*client, disconnect_done()).Times(1);204 EXPECT_CALL(*client, disconnect_done()).Times(1);
229 client->display_server.disconnect(205 client->disconnect();
230 &client->ignored,
231 &client->ignored,
232 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
233
234 client->wait_for_disconnect_done();206 client->wait_for_disconnect_done();
235207
236 Mock::VerifyAndClearExpectations(client.get());208 Mock::VerifyAndClearExpectations(client.get());
@@ -247,11 +219,7 @@
247219
248 try220 try
249 {221 {
250 client->display_server.disconnect(222 client->disconnect();
251 &client->ignored,
252 &client->ignored,
253 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
254
255 // the write beat the socket closing223 // the write beat the socket closing
256 }224 }
257 catch (std::runtime_error const& x)225 catch (std::runtime_error const& x)
@@ -268,11 +236,7 @@
268 EXPECT_CALL(*client, create_surface_done()).Times(testing::AtLeast(0));236 EXPECT_CALL(*client, create_surface_done()).Times(testing::AtLeast(0));
269 EXPECT_CALL(*client, disconnect_done()).Times(testing::AtLeast(0));237 EXPECT_CALL(*client, disconnect_done()).Times(testing::AtLeast(0));
270238
271 client->display_server.create_surface(239 client->create_surface();
272 &client->surface_parameters,
273 &client->surface,
274 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
275
276 client->wait_for_create_surface();240 client->wait_for_create_surface();
277241
278 EXPECT_TRUE(client->surface.has_buffer());242 EXPECT_TRUE(client->surface.has_buffer());
@@ -280,20 +244,12 @@
280244
281 for (int i = 0; i != 8; ++i)245 for (int i = 0; i != 8; ++i)
282 {246 {
283 client->display_server.next_buffer(247 client->next_buffer();
284 &client->surface.id(),
285 client->surface.mutable_buffer(),
286 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::next_buffer_done));
287
288 client->wait_for_next_buffer();248 client->wait_for_next_buffer();
289 EXPECT_TRUE(client->surface.has_buffer());249 EXPECT_TRUE(client->surface.has_buffer());
290 }250 }
291251
292 client->display_server.disconnect(252 client->disconnect();
293 &client->ignored,
294 &client->ignored,
295 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
296
297 client->wait_for_disconnect_done();253 client->wait_for_disconnect_done();
298}254}
299255
@@ -301,19 +257,11 @@
301 connect_create_surface_then_disconnect_a_session)257 connect_create_surface_then_disconnect_a_session)
302{258{
303 EXPECT_CALL(*client, create_surface_done()).Times(1);259 EXPECT_CALL(*client, create_surface_done()).Times(1);
304 client->display_server.create_surface(260 client->create_surface();
305 &client->surface_parameters,
306 &client->surface,
307 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
308
309 client->wait_for_create_surface();261 client->wait_for_create_surface();
310262
311 EXPECT_CALL(*client, disconnect_done()).Times(1);263 EXPECT_CALL(*client, disconnect_done()).Times(1);
312 client->display_server.disconnect(264 client->disconnect();
313 &client->ignored,
314 &client->ignored,
315 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
316
317 client->wait_for_disconnect_done();265 client->wait_for_disconnect_done();
318}266}
319267
@@ -322,33 +270,22 @@
322 using namespace testing;270 using namespace testing;
323271
324 EXPECT_CALL(*client, create_surface_done()).Times(AnyNumber());272 EXPECT_CALL(*client, create_surface_done()).Times(AnyNumber());
325 client->display_server.create_surface(273 client->create_surface();
326 &client->surface_parameters,
327 &client->surface,
328 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
329
330 client->wait_for_create_surface();274 client->wait_for_create_surface();
331275
332 std::mutex m;276 mt::WaitCondition wc;
333 std::condition_variable cv;
334 bool done = false;
335277
336 ON_CALL(*communicator_report, error(_)).WillByDefault(Invoke([&] (std::exception const&)278 ON_CALL(*communicator_report, error(_)).WillByDefault(Invoke([&wc] (std::exception const&)
337 {279 {
338 std::unique_lock<std::mutex> lock(m);280 wc.wake_up_everyone();
339
340 done = true;
341 cv.notify_all();
342 }));281 }));
343282
344 EXPECT_CALL(*communicator_report, error(_)).Times(1);283 EXPECT_CALL(*communicator_report, error(_)).Times(1);
345284
346 client.reset();285 client.reset();
347286
348 std::unique_lock<std::mutex> lock(m);287 wc.wait_for_at_most_seconds(1);
349288 EXPECT_TRUE(wc.woken());
350 auto const deadline = std::chrono::steady_clock::now() + std::chrono::seconds(1);
351 while (!done && cv.wait_until(lock, deadline) != std::cv_status::timeout);
352}289}
353290
354TEST_F(PublishedSocketConnector, configure_display)291TEST_F(PublishedSocketConnector, configure_display)
@@ -356,11 +293,7 @@
356 EXPECT_CALL(*client, display_configure_done())293 EXPECT_CALL(*client, display_configure_done())
357 .Times(1);294 .Times(1);
358295
359 client->display_server.configure_display(296 client->configure_display();
360 &client->disp_config,
361 &client->disp_config_response,
362 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::display_configure_done));
363
364 client->wait_for_configure_display_done();297 client->wait_for_configure_display_done();
365}298}
366299
@@ -373,20 +306,13 @@
373 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);306 client->connect_parameters.set_application_name(__PRETTY_FUNCTION__);
374307
375 EXPECT_CALL(*client, connect_done()).Times(1);308 EXPECT_CALL(*client, connect_done()).Times(1);
376309 client->connect();
377 client->display_server.connect(310 client->wait_for_connect_done();
378 &client->connect_parameters,
379 &client->connection,
380 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::connect_done));
381311
382 EXPECT_CALL(*client, create_surface_done()).Times(testing::AtLeast(0));312 EXPECT_CALL(*client, create_surface_done()).Times(testing::AtLeast(0));
383 EXPECT_CALL(*client, disconnect_done()).Times(testing::AtLeast(0));313 EXPECT_CALL(*client, disconnect_done()).Times(testing::AtLeast(0));
384314
385 client->display_server.create_surface(315 client->create_surface();
386 &client->surface_parameters,
387 &client->surface,
388 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::create_surface_done));
389
390 client->wait_for_create_surface();316 client->wait_for_create_surface();
391317
392 EXPECT_TRUE(client->surface.has_buffer());318 EXPECT_TRUE(client->surface.has_buffer());
@@ -394,20 +320,12 @@
394320
395 for (int i = 0; i != next_buffer_calls; ++i)321 for (int i = 0; i != next_buffer_calls; ++i)
396 {322 {
397 client->display_server.next_buffer(323 client->next_buffer();
398 &client->surface.id(),
399 client->surface.mutable_buffer(),
400 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::next_buffer_done));
401
402 client->wait_for_next_buffer();324 client->wait_for_next_buffer();
403 EXPECT_TRUE(client->surface.has_buffer());325 EXPECT_TRUE(client->surface.has_buffer());
404 }326 }
405327
406 client->display_server.disconnect(328 client->disconnect();
407 &client->ignored,
408 &client->ignored,
409 google::protobuf::NewCallback(client.get(), &mt::TestProtobufClient::disconnect_done));
410
411 client->wait_for_disconnect_done();329 client->wait_for_disconnect_done();
412330
413 EXPECT_EQ(__PRETTY_FUNCTION__, stub_server_tool->app_name);331 EXPECT_EQ(__PRETTY_FUNCTION__, stub_server_tool->app_name);
414332
=== modified file 'tests/unit-tests/thread/test_basic_thread_pool.cpp'
--- tests/unit-tests/thread/test_basic_thread_pool.cpp 2015-06-25 03:00:08 +0000
+++ tests/unit-tests/thread/test_basic_thread_pool.cpp 2015-12-14 15:38:49 +0000
@@ -22,6 +22,7 @@
22#include "mir/test/current_thread_name.h"22#include "mir/test/current_thread_name.h"
23#include "mir/test/signal.h"23#include "mir/test/signal.h"
2424
25#include <atomic>
25#include <memory>26#include <memory>
2627
27#include <gmock/gmock.h>28#include <gmock/gmock.h>
@@ -100,7 +101,7 @@
100 }101 }
101102
102private:103private:
103 bool called;104 std::atomic<bool> called;
104 bool block;105 bool block;
105 std::string name;106 std::string name;
106 mt::Signal signal;107 mt::Signal signal;

Subscribers

People subscribed via source and target branches