Mir

Merge lp:~raof/mir/probe-client-drivers into lp:mir

Proposed by Chris Halse Rogers
Status: Superseded
Proposed branch: lp:~raof/mir/probe-client-drivers
Merge into: lp:mir
Diff against target: 2452 lines (+967/-316)
67 files modified
benchmarks/frame-uniformity/main.cpp (+7/-0)
benchmarks/frame-uniformity/touch_measuring_client.cpp (+11/-2)
benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp (+8/-3)
cmake/FindGtest.cmake (+2/-3)
cmake/MirCommon.cmake (+23/-0)
cmake/src/wrapper.c (+16/-0)
debian/control (+5/-5)
debian/create_postinst_prerm_scripts.sh (+1/-1)
debian/mir-client-platform-android.install (+1/-1)
debian/mir-client-platform-mesa.install (+1/-1)
debian/mir-test-tools.install (+1/-0)
debian/rules (+3/-6)
examples/CMakeLists.txt (+19/-48)
playground/demo-shell/CMakeLists.txt (+1/-3)
src/CMakeLists.txt (+1/-0)
src/client/CMakeLists.txt (+18/-16)
src/client/android/CMakeLists.txt (+7/-22)
src/client/android/android_native_display_container.cpp (+12/-4)
src/client/android/android_native_display_container.h (+10/-3)
src/client/android/client_platform_factory.cpp (+22/-5)
src/client/android/client_platform_factory.h (+2/-5)
src/client/android/symbols.map (+5/-4)
src/client/client_context.h (+2/-1)
src/client/client_platform_factory.h (+5/-2)
src/client/connection_configuration.h (+0/-3)
src/client/default_connection_configuration.cpp (+23/-18)
src/client/default_connection_configuration.h (+0/-4)
src/client/egl_native_display_container.h (+3/-1)
src/client/mesa/CMakeLists.txt (+6/-22)
src/client/mesa/client_platform.cpp (+1/-1)
src/client/mesa/client_platform_factory.cpp (+20/-5)
src/client/mesa/client_platform_factory.h (+0/-5)
src/client/mesa/mesa_native_display_container.cpp (+5/-5)
src/client/mesa/mesa_native_display_container.h (+1/-1)
src/client/mesa/native_surface.cpp (+0/-1)
src/client/mesa/symbols.map (+6/-4)
src/client/mir_connection.cpp (+7/-9)
src/client/mir_connection.h (+2/-2)
src/client/mir_surface_api.cpp (+4/-2)
src/client/probing_client_platform_factory.cpp (+38/-0)
src/client/probing_client_platform_factory.h (+27/-0)
src/common/symbols.map (+7/-8)
tests/CMakeLists.txt (+9/-1)
tests/acceptance-tests/CMakeLists.txt (+2/-8)
tests/acceptance-tests/test_client_library.cpp (+5/-4)
tests/acceptance-tests/test_client_library_drm.cpp (+9/-4)
tests/acceptance-tests/test_symbols_required_by_mesa.cpp (+5/-2)
tests/include/mir_test_doubles/mock_client_context.h (+0/-6)
tests/include/mir_test_doubles/stub_client_buffer.h (+4/-0)
tests/include/mir_test_framework/client_platform_factory.h (+72/-0)
tests/include/mir_test_framework/stub_client_platform_factory.h (+33/-0)
tests/include/mir_test_framework/stub_platform_helpers.h (+53/-0)
tests/integration-tests/CMakeLists.txt (+1/-6)
tests/mir_test_doubles/CMakeLists.txt (+3/-2)
tests/mir_test_framework/CMakeLists.txt (+30/-4)
tests/mir_test_framework/stub_client_platform_factory.cpp (+74/-0)
tests/mir_test_framework/stub_client_platform_module.cpp (+41/-0)
tests/mir_test_framework/stubbed_graphics_platform.cpp (+5/-1)
tests/mir_test_framework/symbols-client.map (+7/-0)
tests/unit-tests/CMakeLists.txt (+1/-6)
tests/unit-tests/client/CMakeLists.txt (+1/-0)
tests/unit-tests/client/android/test_android_client_platform.cpp (+4/-7)
tests/unit-tests/client/mesa/test_client_platform.cpp (+7/-6)
tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp (+1/-1)
tests/unit-tests/client/test_client_platform.cpp (+122/-29)
tests/unit-tests/client/test_probing_client_platform_factory.cpp (+142/-0)
tests/unit-tests/shared_library_test.cpp (+3/-3)
To merge this branch: bzr merge lp:~raof/mir/probe-client-drivers
Reviewer Review Type Date Requested Status
Robert Carr (community) Approve
Alexandros Frantzis (community) Abstain
PS Jenkins bot (community) continuous-integration Needs Fixing
Daniel van Vugt Abstain
Alan Griffiths Needs Fixing
Andreas Pokorny (community) Approve
Cemil Azizoglu (community) Approve
Review via email: mp+243103@code.launchpad.net

This proposal has been superseded by a proposal from 2014-12-12.

Commit message

Add probing for client platform modules.

The client library now looks in MIR_CLIENT_PLATFORM_PATH (usually /usr/lib/*/mir/client-platform) and loads all the modules it finds in there. At connection time each of those modules are checked whether the MirPlatformPackage matches what they expect; the first one that matches is used.

Description of the change

The smallest individually landable piece of proper driver probing; the client library side of it.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(1) Orphaned comment now needs removing:
16 # Why does this have to come after mir-test-framework here but not in tests/acceptance-tests/
17 # /CMakeLists.txt? ~racarr
18 - mirplatform

(2) Unnecessary (and undesirable) formatting changes:
221 -target_link_libraries(mirclient
222 +target_link_libraries(
223 + mirclient
224 +
because the first parameter is special and independent of those that follow it.

(3) Remind me why we wanted a C calling convention for C++ code?
372 +extern "C" std::shared_ptr<mcl::ClientPlatform>

(4) Minor optimization: You can avoid a template instantiation using std::atomic_bool for
898 + std::atomic<bool> connect_done;

(5) Fatal: Clients don't start any more:
$ bin/mir_demo_client_egltriangle
Can't get connection
$ bin/mir_demo_client_flicker
Starting
mir_demo_client_flicker: /home/dan/bzr/mir/tmp.pcd/examples/flicker.c:134: main: Assertion `mir_connection_is_valid(connection)' failed.

(6) ProbingClientPlatformFactory sounds a bit awkward. Although I haven't stopped to understand the code enough to suggest anything better yet.

(7) New (old) function exposed without a new stanza. Should be MIR_COMMON_3.1 (?)
980 +++ src/common/symbols.map 2014-11-28 05:44:33 +0000
981 @@ -150,6 +150,7 @@
982 # but they are used by libmirplatform, libmirclient or libmirserver
983 mir::default_server_socket;
984 mir::input::android::Lexicon::translate*;
985 + mir::libraries_for_path*;

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote :

(3) We need C calling convention because I'm not going to write load_symbol("_Zsharedptr23mirZclientZ23PIZZA22112stinkybobo888zzz") :)

(5) PEBCAK - You're trying to run those uninstalled; the client library is (probably) looking for platform modules in /usr/local/mir/client-platform/, and not finding them. If our examples actually called mir_connection_get_error() then you'd see that error :).

Set MIR_CLIENT_PLATFORM_PATH=$(pwd)/lib/client-modules and it'll work uninstalled.

I'll fix the rest.

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

> Set MIR_CLIENT_PLATFORM_PATH=$(pwd)/lib/client-modules and it'll work uninstalled.

Note that it's not just the examples but also the tests that need this.

This is bad in two ways:

1. It's more complicated to run executables from inside the build dir.
2. Forgetting to set the proper path may lead to platform libraries from the system being used inadvertently, instead of the expected ones from inside the build dir.

Until now, executing anything from inside the build dir was guaranteed to prefer code from that directory (due to cmake setting RPATH). This setup has served us well and I think we should keep it, even if doing so involves some hackery.

One way would be to search for platform libs in all the places the dynamic linker would look for, but unfortunately there doesn't seem to be a way to access the shared library search paths directly.

Another way would be to take advantage of the RPATH setting, for example:

1. Create a mir/libmirtestconfig.so which exports symbols/functions to get the test platform search path
2. Build it in build/lib/, but don't install it.
3. When figuring out where to search for the platform libs ([1]), try to load the mir/libmirtestconfig.so library and get the test path.
  3.1. In case of an executable/library from the build dir, mir/libmirtestconfig.so will be found (due to RPATH) and the test values will be used.
  3.2. In case of an installed executable/library no RPATH is present and mir/libmirtestconfig.so will not be found.

[1] In mcl::DefaultConnectionConfiguration::the_client_platform_factory()

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

> (5) PEBCAK - You're trying to run those uninstalled; the client library is
> (probably) looking for platform modules in /usr/local/mir/client-platform/,
> and not finding them. If our examples actually called
> mir_connection_get_error() then you'd see that error :).
>
> Set MIR_CLIENT_PLATFORM_PATH=$(pwd)/lib/client-modules and it'll work
> uninstalled.

That doesn't seem like an adequate answer:

We've always been able to run the built binaries from within the build tree (cmake does rpath magic).

This makes it far too easy to accidentally load the wrong (installed) binaries. Could we e.g. look relative to the current library?

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Seems ok but yeah it would be nice to load from the build dir. One trick ive seen is to use wrapper scripts for the binaries in the build-dir (not installed of course) which exports the appropriate var.

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 :

I like the idea of taking advantage of RPATH. One of the best (and worst) things about CMake is its RPATH behaviour. And it's designed that way precisely so you can run things in-situ within the source tree. Haven't assessed alf's plan in detail though.

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

There's a hint in the dlopen docs about how it might be achieved:

   dlopen()
       ...
       o (ELF only) If the executable file for the calling program contains
           a DT_RPATH tag, and does not contain a DT_RUNPATH tag, then the
           directories listed in the DT_RPATH tag are searched.

Revision history for this message
Chris Halse Rogers (raof) wrote :

Yeah, dlopen("libmirtestconfig.so") would work.

I'm doing the CMakery required to provide wrapper scripts, though. I
strongly prefer that the release build not contain code required only
to set up the test environment.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> I'm doing the CMakery required to provide wrapper scripts, though

Please make sure that it's still easy to run the examples and tests with gdb/valgrind/other tools.

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Needs information:

Has this been tested under chroot/sbuild? (We don't wanna have last minute packaging issues during release.)

Nits/Comments:
719 + // TODO: Actually check what platform we're using, rather than blindly

Perhaps MirPlatformPackage should include a "platform signature". Something like "MESA", "ANDR", "STUB".
-----------------------
android.so, mesa.so, dummy.so are too generic. client-platform-{android|mesa|dummy}.so perhaps?

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

@Cemil - tested, and passed, under sbuild.

I think I'd like to handle platform discovery a slightly different way; at the moment, MirPlatformPackage contains enough data to be a unique signature in itself.

The drivers are android.so, mesa.so, etc because they're in the client-platform/ directory. Their full name looks like client-platform/mesa.so, client-platform/android.so, etc.

I think client-platform/client-platform-mesa.so, etc look a bit silly :)

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
Alan Griffiths (alan-griffiths) wrote :

$MIR_CLIENT_PLATFORM_PATH and the executable_path() hack looks fragile.

We could write DefaultConnectionConfiguration::the_client_platform_factory() to use dladdr() to locate libmirclient.so and locate the client-modules directory relative to that? (which should be the same in tree and installed.)

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote :

I'm not entirely sure what you think is fragile about executable_path()? We're already using it elsewhere in the tests.

If you're concerned about the ../lib/ relative path, then; whoops! Now uses mtf::library_path().

I much prefer the current solution to using dladdr() in the release code. Using dladdr() we make some assumptions about the code that the compiler emits and if those assumptions fail then our release code fails. If the assumptions we set MIR_CLIENT_PLATFORM_PATH based on fail then at worst our test suite fails.

Regardless of how we find the platform libraries by default we'll want a MIR_CLIENT_PLATFORM_PATH option for roughly the same reasons that we have a MIR_CLIENT_PLATFORM_LIB option.

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

There already is a stub_client_buffer{_factory}.h do we need a different one?

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

> I'm not entirely sure what you think is fragile about executable_path()? We're
> already using it elsewhere in the tests.

Having looked again I think I misunderstood how this solution works. It isn't as bad as I thought.

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

183 === added file 'cmake/wrapper-script'
184 --- cmake/wrapper-script 1970-01-01 00:00:00 +0000
185 +++ cmake/wrapper-script 2014-12-03 22:58:17 +0000
186 @@ -0,0 +1,5 @@
187 +#!/bin/sh
188 +
189 +export MIR_CLIENT_PLATFORM_PATH=@BUILD_PREFIX@/lib/client-modules
190 +
191 +exec @BUILD_PREFIX@/bin/@EXECUTABLE@ $@

Isn't this obsolete?

review: Needs Fixing
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

> @Cemil - tested, and passed, under sbuild.

Great. How about testing downstreams by installing the generated packages?

review: Needs Information
Revision history for this message
Chris Halse Rogers (raof) wrote :

@Cemil - downstreams built and happy.

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

62 +#include <error.h>
...
73 + error(1, 0, "Surface creation failed: %s\n", mir_surface_get_error_message(surface));

I think this is our first use of this GNU extension. I'm not opposed, but think it needs discussion before adding this dependency.

~~~~

671 + auto it = valid_displays.find(display);
672 + if (it == valid_displays.end())
673 + return;
674 +
675 + valid_displays.erase(it);

AFICS this is a verbose and inefficient

    valid_displays.erase(display);

But I wouldn't block on it as it isn't a critical path.

~~~~

741 + throw new std::runtime_error{"Attempted to create Android client platform on non-Android server"};

1. Don't throw pointers
2. Use BOOST_THROW_EXCEPTION

~~~~

1067 + throw std::runtime_error{"Attempted to create Mesa client platform on non-Mesa server"};
...
1602 + throw std::logic_error{"Must call one of create_*_client_platform() before calling get_platform_library()"};

Use BOOST_THROW_EXCEPTION

review: Needs Fixing
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Assuming downstreams not just build, but also run happily, I have no more to add.

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

Diff against target: 2448 lines (+975/-294) 68 files modified (has conflicts)

Text conflict in examples/CMakeLists.txt

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

(2) Unnecessary (and undesirable) formatting changes:
575 -target_link_libraries(mirclient
576 +target_link_libraries(
577 + mirclient
578 +
because the first parameter is special and independent of those that follow it.

(4) Minor optimization: You can avoid a template instantiation using std::atomic_bool for
1250 + std::atomic<bool> connect_done;

(8) The library re-ordering appears to be pointless, or is there a reason?...
benchmarks/frame-uniformity/CMakeLists.txt
Can we revert all changes to that file?

(9) Clients now start, but the wrapper that makes it possible feels inelegant...
$ ls -a bin/
mir_acceptance_tests
.mir_acceptance_tests-uninstalled
mir_demo_client_basic
.mir_demo_client_basic-uninstalled
mir_demo_client_cursors
.mir_demo_client_cursors-uninstalled
mir_demo_client_display_config
.mir_demo_client_display_config-uninstalled
mir_demo_client_eglcounter
.mir_demo_client_eglcounter-uninstalled
...
I suspect we can do better without needing a wrapper. But if we do use this then please don't hide binaries from developers: ".foo-uninstalled" should be "foo.bin"

(10) wrapper.c compiles to 10KB, but could be replaced with a trivial shell script instead.

(11) This is new on the end. What's it do?
1343 +} MIR_COMMON_3;

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote :

On Wed, Dec 10, 2014 at 2:44 PM, Daniel van Vugt
<email address hidden> wrote:
> Review: Needs Fixing
>
> (2) Unnecessary (and undesirable) formatting changes:
> 575 -target_link_libraries(mirclient
> 576 +target_link_libraries(
> 577 + mirclient
> 578 +
> because the first parameter is special and independent of those that
> follow it.
>
> (4) Minor optimization: You can avoid a template instantiation using
> std::atomic_bool for
> 1250 + std::atomic<bool> connect_done;
>
> (8) The library re-ordering appears to be pointless, or is there a
> reason?...
> benchmarks/frame-uniformity/CMakeLists.txt
> Can we revert all changes to that file?
>
> (9) Clients now start, but the wrapper that makes it possible feels
> inelegant...
> $ ls -a bin/
> mir_acceptance_tests
> .mir_acceptance_tests-uninstalled
> mir_demo_client_basic
> .mir_demo_client_basic-uninstalled
> mir_demo_client_cursors
> .mir_demo_client_cursors-uninstalled
> mir_demo_client_display_config
> .mir_demo_client_display_config-uninstalled
> mir_demo_client_eglcounter
> .mir_demo_client_eglcounter-uninstalled
> ...
> I suspect we can do better without needing a wrapper. But if we do
> use this then please don't hide binaries from developers:
> ".foo-uninstalled" should be "foo.bin"

I think we need one of (a) a wrapper, or (b) code in the libraries we
release solely there to negate the need for a trivial wrapper.

Choosing (b) introduces the possibility of otherwise-unnecessary code
having user-visible bugs, so I chose (a).

I hid the real binaries in the time-honoured tradition of libtool
(which uses wrapper scripts, and hides everything in a .libs/
directory). You've got a choice between developers going “why are
there all these *.bin that don't work when I try to run them lying
around in my build tree” and “why are there all these hidden
binaries lying around in my build tree”.

I think hidden files are less confusing. The (normal) directory listing
lists everything you should be running.

> (10) wrapper.c compiles to 10KB, but could be replaced with a trivial
> shell script instead.

Said shell script makes it more difficult to run gdb which is why I
switched to wrapper.c.

>
> (11) This is new on the end. What's it do?
> 1343 +} MIR_COMMON_3;

“MIR_COMMON_3.1 depends on MIR_COMMON_3”

Revision history for this message
Chris Halse Rogers (raof) wrote :

> (4) Minor optimization: You can avoid a template instantiation using
> std::atomic_bool for
> 1250 + std::atomic<bool> connect_done;

We already use std::atomic<bool> elsewhere, so this saves no template instatiations.

Also, std::atomic_bool is not the same as std::atomic<bool>. It's a vestigial attempt to match possibly C1y threading support.

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

looks good to me.

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

I'm not keen on the wrapper trick, but won't block when I don't have a better idea.

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

Text conflict in benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp
1 conflicts encountered.

review: Needs Fixing
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 :

I still believe we could bend rpath* to our will and avoid wrappers. Although it's not impossible to figure that part out later and then drop the wrapper.

As for the minor cleanups, I still recommend resolving them. But I haven't revised this branch in detail. The end goal is rather important even if parts of the solution feel a bit ugly. I don't want to block it either.

review: Abstain
Revision history for this message
Chris Halse Rogers (raof) wrote :

I think I *have* resolved all your minor cleanups, with the exception
of replacing std::atomic<bool> with the non-equivalent std::atomic_bool.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) :
review: Abstain
Revision history for this message
Robert Carr (robertcarr) wrote :

LGTM. Happy we can still run gdb on the wrappers.

Surprised by the gtest matcher used outside of expectation setting at l1901

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'benchmarks/frame-uniformity/main.cpp'
2--- benchmarks/frame-uniformity/main.cpp 2014-10-26 02:13:36 +0000
3+++ benchmarks/frame-uniformity/main.cpp 2014-12-12 01:38:38 +0000
4@@ -17,6 +17,7 @@
5 */
6
7 #include "frame_uniformity_test.h"
8+#include "mir_test_framework/executable_path.h"
9
10 #include <assert.h>
11 #include <cmath>
12@@ -27,6 +28,7 @@
13 #include <gtest/gtest.h>
14
15 namespace geom = mir::geometry;
16+namespace mtf = mir_test_framework;
17
18 namespace
19 {
20@@ -116,6 +118,11 @@
21 int const run_count = 1;
22 double average_lag = 0, average_uniformity = 0;
23
24+ // Ensure we load the correct platform libraries
25+ setenv("MIR_CLIENT_PLATFORM_PATH",
26+ (mtf::library_path() + "/client-modules").c_str(),
27+ true);
28+
29 for (int i = 0; i < run_count; i++)
30 {
31 FrameUniformityTest t({screen_size, touch_start_point, touch_end_point, touch_duration});
32
33=== modified file 'benchmarks/frame-uniformity/touch_measuring_client.cpp'
34--- benchmarks/frame-uniformity/touch_measuring_client.cpp 2014-10-26 02:13:36 +0000
35+++ benchmarks/frame-uniformity/touch_measuring_client.cpp 2014-12-12 01:38:38 +0000
36@@ -26,6 +26,7 @@
37 #include <memory>
38 #include <vector>
39
40+#include <iostream>
41 #include <assert.h>
42
43 namespace mt = mir::test;
44@@ -45,7 +46,11 @@
45 mir_display_output_id_invalid};
46
47 auto surface = mir_connection_create_surface_sync(connection, &surface_params);
48- assert(mir_surface_is_valid(surface));
49+ if (!mir_surface_is_valid(surface))
50+ {
51+ std::cerr << "Surface creation failed: " << mir_surface_get_error_message(surface) << std::endl;
52+ exit(1);
53+ }
54
55 return surface;
56 }
57@@ -93,7 +98,11 @@
58 void TouchMeasuringClient::run(std::string const& connect_string)
59 {
60 auto connection = mir_connect_sync(connect_string.c_str(), "frame-uniformity-test");
61- assert(mir_connection_is_valid(connection));
62+ if (!mir_connection_is_valid(connection))
63+ {
64+ std::cerr << "Connection to Mir failed: " << mir_connection_get_error_message(connection) << std::endl;
65+ exit(1);
66+ }
67
68 /*
69 * Set a null callback to avoid killing the process
70
71=== modified file 'benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp'
72--- benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp 2014-12-10 06:31:45 +0000
73+++ benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp 2014-12-12 01:38:38 +0000
74@@ -24,9 +24,11 @@
75
76 #include "mir_test_doubles/stub_buffer_allocator.h"
77 #include "mir_test_doubles/stub_display.h"
78+#include "mir_test_framework/stub_platform_helpers.h"
79
80 #include <chrono>
81 #include <functional>
82+#include <boost/throw_exception.hpp>
83
84 namespace mg = mir::graphics;
85 namespace geom = mir::geometry;
86@@ -59,12 +61,15 @@
87
88 std::shared_ptr<mg::PlatformIPCPackage> connection_ipc_package() override
89 {
90- return std::make_shared<mg::PlatformIPCPackage>();
91+ auto package = std::make_shared<mg::PlatformIPCPackage>();
92+ mir_test_framework::pack_stub_ipc_package(*package);
93+ return package;
94 }
95
96- mg::PlatformIPCPackage platform_operation(unsigned int const, mg::PlatformIPCPackage const&) override
97+ mg::PlatformIPCPackage platform_operation(const unsigned int,
98+ mg::PlatformIPCPackage const&) override
99 {
100- return mg::PlatformIPCPackage();
101+ BOOST_THROW_EXCEPTION((std::runtime_error{"Stub platform has no operations"}));
102 }
103 };
104
105
106=== modified file 'cmake/FindGtest.cmake'
107--- cmake/FindGtest.cmake 2014-11-24 03:09:00 +0000
108+++ cmake/FindGtest.cmake 2014-12-12 01:38:38 +0000
109@@ -20,10 +20,9 @@
110 set(GMOCK_BINARY_DIR ${CMAKE_BINARY_DIR}/${GMOCK_PREFIX}/libs)
111 set(GTEST_BINARY_DIR ${GMOCK_BINARY_DIR}/gtest)
112
113-set(GTEST_CMAKE_ARGS "")
114+set(GTEST_CMAKE_ARGS "-DCMAKE_CXX_FLAGS=-fPIC")
115 if (${CMAKE_CROSSCOMPILING})
116- set(GTEST_CMAKE_ARGS
117- -DCMAKE_TOOLCHAIN_FILE=${CMAKE_MODULE_PATH}/LinuxCrossCompile.cmake)
118+ list(APPEND GTEST_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_MODULE_PATH}/LinuxCrossCompile.cmake)
119 endif()
120
121 ExternalProject_Add(
122
123=== modified file 'cmake/MirCommon.cmake'
124--- cmake/MirCommon.cmake 2014-12-08 04:03:47 +0000
125+++ cmake/MirCommon.cmake 2014-12-12 01:38:38 +0000
126@@ -168,3 +168,26 @@
127 add_dependencies(${TARGET} ${TARGET}_pch)
128 endif()
129 endfunction()
130+
131+function (mir_add_wrapped_executable TARGET)
132+ set(REAL_EXECUTABLE .${TARGET}-uninstalled)
133+ add_executable(${TARGET} ${ARGN})
134+ set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${REAL_EXECUTABLE})
135+
136+ add_executable(${TARGET}-wrapper ${PROJECT_SOURCE_DIR}/cmake/src/wrapper.c)
137+ set_property(TARGET ${TARGET}-wrapper
138+ APPEND_STRING PROPERTY COMPILE_FLAGS " -DEXECUTABLE=\\\"${REAL_EXECUTABLE}\\\"")
139+ set_property(TARGET ${TARGET}-wrapper
140+ APPEND_STRING PROPERTY COMPILE_FLAGS " -DBUILD_PREFIX=\\\"${CMAKE_BINARY_DIR}\\\"")
141+ set_property(TARGET ${TARGET}-wrapper
142+ APPEND_STRING PROPERTY COMPILE_FLAGS " -D_BSD_SOURCE")
143+ set_property(TARGET ${TARGET}-wrapper
144+ PROPERTY OUTPUT_NAME ${TARGET})
145+
146+ add_dependencies(${TARGET} ${TARGET}-wrapper)
147+
148+ install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/${REAL_EXECUTABLE}
149+ DESTINATION ${CMAKE_INSTALL_BINDIR}
150+ RENAME ${TARGET}
151+ )
152+endfunction()
153
154=== added file 'cmake/src/wrapper.c'
155--- cmake/src/wrapper.c 1970-01-01 00:00:00 +0000
156+++ cmake/src/wrapper.c 2014-12-12 01:38:38 +0000
157@@ -0,0 +1,16 @@
158+#include <stdlib.h>
159+#include <stdio.h>
160+#include <unistd.h>
161+#include <assert.h>
162+
163+int main(int argc, char** argv)
164+{
165+ assert(argc > 0);
166+ setenv("MIR_CLIENT_PLATFORM_PATH", BUILD_PREFIX "/lib/client-modules/", 1);
167+
168+ argv[0] = BUILD_PREFIX "/bin/" EXECUTABLE;
169+ execv(argv[0], argv);
170+
171+ perror("Failed to execute real binary " EXECUTABLE);
172+ return 1;
173+}
174
175=== modified file 'debian/control'
176--- debian/control 2014-12-08 04:03:47 +0000
177+++ debian/control 2014-12-12 01:38:38 +0000
178@@ -143,7 +143,7 @@
179 Pre-Depends: ${misc:Pre-Depends}
180 Depends: ${misc:Depends},
181 ${shlibs:Depends},
182- libmir${client-driver}-mesa | libmir${client-driver}-android,
183+ mir-client-platform-mesa | mir-client-platform-android,
184 Description: Display server for Ubuntu - client library
185 Mir is a display server running on linux systems, with a focus on efficiency,
186 robust operation and a well-defined driver model.
187@@ -265,7 +265,7 @@
188 Contains the shared libraries required for the Mir server and client.
189
190 # Longer-term these drivers should move out-of-tree
191-Package: libmirclient8driver-mesa
192+Package: mir-client-platform-mesa
193 Section: libs
194 Architecture: i386 amd64 armhf arm64
195 Multi-Arch: same
196@@ -279,7 +279,7 @@
197 Contains the shared libraries required for the Mir clients to interact with
198 the underlying hardware platform using the Mesa drivers.
199
200-Package: libmirclient8driver-android
201+Package: mir-client-platform-android
202 Section: libs
203 Architecture: i386 amd64 armhf
204 Multi-Arch: same
205@@ -328,7 +328,7 @@
206 Pre-Depends: ${misc:Pre-Depends}
207 Depends: ${misc:Depends},
208 libmir${platform-driver}-mesa,
209- libmir${client-driver}-mesa
210+ mir-client-platform-mesa
211 Description: Display server for Ubuntu - desktop driver metapackage
212 Mir is a display server running on linux systems, with a focus on efficiency,
213 robust operation and a well-defined driver model.
214@@ -343,7 +343,7 @@
215 Pre-Depends: ${misc:Pre-Depends}
216 Depends: ${misc:Depends},
217 libmir${platform-driver}-android,
218- libmir${client-driver}-android
219+ mir-client-platform-android
220 Description: Display server for Ubuntu - android driver metapackage
221 Mir is a display server running on linux systems, with a focus on efficiency,
222 robust operation and a well-defined driver model.
223
224=== modified file 'debian/create_postinst_prerm_scripts.sh'
225--- debian/create_postinst_prerm_scripts.sh 2014-12-08 04:03:47 +0000
226+++ debian/create_postinst_prerm_scripts.sh 2014-12-12 01:38:38 +0000
227@@ -6,7 +6,7 @@
228 deb_host_arch=$1
229 deb_host_multiarch=$2
230
231-mir_platform_types="${PLATFORM_DRIVER} ${CLIENT_DRIVER}"
232+mir_platform_types="${PLATFORM_DRIVER}"
233 case $deb_host_arch in
234 arm64)
235 mir_platforms="mesa"
236
237=== renamed file 'debian/libmirclient8driver-android.install' => 'debian/mir-client-platform-android.install'
238--- debian/libmirclient8driver-android.install 2014-12-08 04:03:47 +0000
239+++ debian/mir-client-platform-android.install 2014-12-12 01:38:38 +0000
240@@ -1,1 +1,1 @@
241-usr/lib/*/mir/client*driver/android/*
242+usr/lib/*/mir/client-platform/android.so
243
244=== renamed file 'debian/libmirclient8driver-mesa.install' => 'debian/mir-client-platform-mesa.install'
245--- debian/libmirclient8driver-mesa.install 2014-12-08 04:03:47 +0000
246+++ debian/mir-client-platform-mesa.install 2014-12-12 01:38:38 +0000
247@@ -1,1 +1,1 @@
248-usr/lib/*/mir/client*driver/mesa/*
249+usr/lib/*/mir/client-platform/mesa.so
250
251=== modified file 'debian/mir-test-tools.install'
252--- debian/mir-test-tools.install 2014-12-08 04:03:47 +0000
253+++ debian/mir-test-tools.install 2014-12-12 01:38:38 +0000
254@@ -6,3 +6,4 @@
255 usr/lib/*/mir/tools/libmirclientlttng.so
256 usr/lib/*/mir/tools/libmirserverlttng.so
257 usr/lib/*/libmirplatformstub.so
258+usr/lib/*/mir/client-platform/dummy.so
259
260=== modified file 'debian/rules'
261--- debian/rules 2014-12-08 04:03:47 +0000
262+++ debian/rules 2014-12-12 01:38:38 +0000
263@@ -14,7 +14,6 @@
264 export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.9
265
266 export PLATFORM_DRIVER = platform5driver
267-export CLIENT_DRIVER = client8driver
268
269 %:
270 dh $@ --parallel --fail-missing
271@@ -57,10 +56,9 @@
272 # Nothing outside Mir should link to libmirprotobuf directly.
273 # Delete the symlink so that --fail-missing doesn't think we've missed it
274 # accidentally.
275- rm debian/tmp/usr/lib/*/libmirprotobuf.so
276+ -rm debian/tmp/usr/lib/*/libmirprotobuf.so
277 dh_install --fail-missing \
278- -Xusr/lib/$(DEB_HOST_MULTIARCH)/libmir$(PLATFORM_DRIVER).so \
279- -Xusr/lib/$(DEB_HOST_MULTIARCH)/libmir$(CLIENT_DRIVER).so
280+ -Xusr/lib/$(DEB_HOST_MULTIARCH)/libmir$(PLATFORM_DRIVER).so
281 sh debian/install_ld_so_conf.sh $(DEB_HOST_ARCH) $(DEB_HOST_MULTIARCH)
282
283 override_dh_installdeb:
284@@ -70,5 +68,4 @@
285
286 override_dh_gencontrol:
287 dh_gencontrol -- \
288- -Vplatform-driver=$(PLATFORM_DRIVER) \
289- -Vclient-driver=$(CLIENT_DRIVER)
290+ -Vplatform-driver=$(PLATFORM_DRIVER)
291
292=== modified file 'examples/CMakeLists.txt'
293--- examples/CMakeLists.txt 2014-12-11 03:56:10 +0000
294+++ examples/CMakeLists.txt 2014-12-12 01:38:38 +0000
295@@ -31,38 +31,38 @@
296 ${EGL_LIBRARIES}
297 ${GLESv2_LIBRARIES}
298 )
299-add_executable(mir_demo_client_eglflash
300+mir_add_wrapped_executable(mir_demo_client_eglflash
301 eglflash.c
302 )
303 target_link_libraries(mir_demo_client_eglflash
304 eglapp
305 )
306-add_executable(mir_demo_client_egltriangle
307+mir_add_wrapped_executable(mir_demo_client_egltriangle
308 egltriangle.c
309 )
310 target_link_libraries(mir_demo_client_egltriangle
311 eglapp
312 )
313-add_executable(mir_demo_client_eglcounter
314+mir_add_wrapped_executable(mir_demo_client_eglcounter
315 eglcounter.cpp
316 )
317 target_link_libraries(mir_demo_client_eglcounter
318 eglapp
319 )
320-add_executable(mir_demo_client_eglplasma
321+mir_add_wrapped_executable(mir_demo_client_eglplasma
322 eglplasma.c
323 )
324 target_link_libraries(mir_demo_client_eglplasma
325 eglapp
326 )
327-add_executable(mir_demo_client_cursors
328+mir_add_wrapped_executable(mir_demo_client_cursors
329 cursors_demo_client.c
330 )
331 target_link_libraries(mir_demo_client_cursors
332 eglapp
333 )
334
335-add_executable(mir_demo_client_basic
336+mir_add_wrapped_executable(mir_demo_client_basic
337 basic.c
338 )
339
340@@ -74,22 +74,22 @@
341 ${CMAKE_THREAD_LIBS_INIT}
342 )
343
344-add_executable(mir_test_client_release_at_exit release_at_exit.c)
345-target_link_libraries(mir_test_client_release_at_exit mirclient)
346+mir_add_wrapped_executable(mir_demo_client_release_at_exit release_at_exit.c)
347+target_link_libraries(mir_demo_client_release_at_exit mirclient)
348
349-add_executable(mir_demo_client_multiwin multiwin.c)
350+mir_add_wrapped_executable(mir_demo_client_multiwin multiwin.c)
351 target_link_libraries(mir_demo_client_multiwin mirclient)
352
353-add_executable(mir_demo_client_fingerpaint fingerpaint.c)
354+mir_add_wrapped_executable(mir_demo_client_fingerpaint fingerpaint.c)
355 target_link_libraries(mir_demo_client_fingerpaint mirclient)
356
357-add_executable(mir_demo_client_progressbar progressbar.c)
358+mir_add_wrapped_executable(mir_demo_client_progressbar progressbar.c)
359 target_link_libraries(mir_demo_client_progressbar mirclient)
360
361-add_executable(mir_demo_client_display_config demo_client_display_config.c)
362+mir_add_wrapped_executable(mir_demo_client_display_config demo_client_display_config.c)
363 target_link_libraries(mir_demo_client_display_config eglapp)
364
365-add_executable(mir_demo_client_flicker
366+mir_add_wrapped_executable(mir_demo_client_flicker
367 flicker.c
368 )
369
370@@ -101,7 +101,7 @@
371 ${CMAKE_THREAD_LIBS_INIT}
372 )
373
374-add_executable(mir_demo_client_scroll
375+mir_add_wrapped_executable(mir_demo_client_scroll
376 scroll.cpp
377 )
378
379@@ -117,7 +117,7 @@
380
381 )
382
383-add_executable(mir_demo_client_prompt_session prompt_session.c)
384+mir_add_wrapped_executable(mir_demo_client_prompt_session prompt_session.c)
385 target_link_libraries(mir_demo_client_prompt_session mirclient)
386
387 add_library(mirdraw STATIC graphics_utils.cpp)
388@@ -130,7 +130,7 @@
389 ${GLESv2_INCLUDE_DIRS}
390 )
391
392-add_executable(mir_demo_standalone_render_to_fb
393+mir_add_wrapped_executable(mir_demo_standalone_render_to_fb
394 render_to_fb.cpp
395 )
396
397@@ -140,25 +140,7 @@
398 ${Boost_LIBRARIES}
399 )
400
401-set (INSTALL_DEMOS
402- mir_demo_client_basic
403- mir_demo_client_flicker
404- mir_demo_client_scroll
405- mir_demo_client_eglflash
406- mir_demo_client_egltriangle
407- mir_demo_client_eglplasma
408- mir_demo_client_eglcounter
409- mir_demo_client_fingerpaint
410- mir_demo_client_multiwin
411- mir_demo_client_display_config
412- mir_demo_client_progressbar
413- mir_demo_client_prompt_session
414- mir_demo_standalone_render_to_fb
415-)
416-
417-install(TARGETS ${INSTALL_DEMOS} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
418-
419-add_executable(mir_demo_server_basic
420+mir_add_wrapped_executable(mir_demo_server_basic
421 server_example.cpp
422 glog_logger.cpp
423 )
424@@ -171,17 +153,10 @@
425 ${Boost_LIBRARIES}
426 )
427
428-install(TARGETS mir_demo_server_basic
429- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
430-)
431-
432-add_executable(mir_demo_server_minimal server_minimal.cpp)
433+mir_add_wrapped_executable(mir_demo_server_minimal server_minimal.cpp)
434 target_link_libraries(mir_demo_server_minimal mirserver)
435-install(TARGETS mir_demo_server_minimal
436- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
437-)
438
439-add_executable(mir_demo_standalone_render_overlays
440+mir_add_wrapped_executable(mir_demo_standalone_render_overlays
441 render_overlays.cpp
442 )
443
444@@ -189,7 +164,3 @@
445 mirserver
446 mircommon
447 )
448-
449-install(TARGETS mir_demo_standalone_render_overlays
450- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
451-)
452
453=== modified file 'playground/demo-shell/CMakeLists.txt'
454--- playground/demo-shell/CMakeLists.txt 2014-12-11 02:43:01 +0000
455+++ playground/demo-shell/CMakeLists.txt 2014-12-12 01:38:38 +0000
456@@ -4,7 +4,7 @@
457 window_manager.cpp
458 )
459
460-add_executable(mir_demo_server_shell
461+mir_add_wrapped_executable(mir_demo_server_shell
462 demo_shell.cpp
463 )
464
465@@ -14,5 +14,3 @@
466 playgroundserverconfig
467 exampleserverconfig
468 )
469-
470-install(TARGETS mir_demo_server_shell RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
471
472=== modified file 'src/CMakeLists.txt'
473--- src/CMakeLists.txt 2014-12-08 04:03:47 +0000
474+++ src/CMakeLists.txt 2014-12-12 01:38:38 +0000
475@@ -20,3 +20,4 @@
476 set(MIR_PLATFORM_REFERENCES ${MIR_PLATFORM_REFERENCES} PARENT_SCOPE)
477 set(MIR_COMMON_OBJECTS ${MIR_COMMON_OBJECTS} PARENT_SCOPE)
478 set(MIR_COMMON_REFERENCES ${MIR_COMMON_REFERENCES} PARENT_SCOPE)
479+set(MIR_CLIENT_PLATFORM_PATH ${MIR_CLIENT_PLATFORM_PATH} PARENT_SCOPE)
480
481=== modified file 'src/client/CMakeLists.txt'
482--- src/client/CMakeLists.txt 2014-12-11 02:43:01 +0000
483+++ src/client/CMakeLists.txt 2014-12-12 01:38:38 +0000
484@@ -1,13 +1,3 @@
485-set(MIRCLIENT_ABI 8)
486-set(CLIENT_DRIVER client${MIRCLIENT_ABI}driver)
487-set(MIR_CLIENT_DRIVER mir${CLIENT_DRIVER})
488-set(MIR_CLIENT_DRIVER_BINARY lib${MIR_CLIENT_DRIVER}.so
489- CACHE STRING "File name of Mir client drivers")
490-add_definitions(
491- -DMIR_CLIENT_DRIVER_BINARY="${MIR_CLIENT_DRIVER_BINARY}"
492- -DMIR_LOG_COMPONENT_FALLBACK="mirclient"
493-)
494-
495 set(PREFIX "${CMAKE_INSTALL_PREFIX}")
496 set(EXEC_PREFIX "${CMAKE_INSTALL_PREFIX}")
497 set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}")
498@@ -33,6 +23,20 @@
499 ${DRM_INCLUDE_DIRS}
500 )
501
502+set(MIRCLIENT_ABI 8)
503+set(CLIENT_PLATFORM_VERSION "MIR_CLIENT_PLATFORM_2")
504+set(symbol_map ${CMAKE_SOURCE_DIR}/src/client/symbols.map)
505+
506+set(MIR_CLIENT_PLATFORM_PATH
507+ ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/mir/client-platform
508+)
509+set(MIR_CLIENT_PLATFORM_PATH ${MIR_CLIENT_PLATFORM_PATH} PARENT_SCOPE)
510+
511+add_definitions(-DMIR_CLIENT_PLATFORM_PATH="${MIR_CLIENT_PLATFORM_PATH}/")
512+add_definitions(-DCLIENT_PLATFORM_VERSION="${CLIENT_PLATFORM_VERSION}")
513+add_definitions(-DMIR_LOGGING_COMPONENT_FALLBACK="mirclient")
514+
515+
516 add_subdirectory(rpc/)
517 add_subdirectory(lttng/)
518
519@@ -72,19 +76,16 @@
520 mir_prompt_session.cpp
521 mir_prompt_session_api.cpp
522 mir_event_distributor.cpp
523+ probing_client_platform_factory.cpp
524 periodic_perf_report.cpp
525 )
526
527-add_library(
528- mirclient SHARED
529+add_library(mirclient SHARED
530
531 $<TARGET_OBJECTS:mirclientobjects>
532 )
533
534-set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols.map)
535-
536-set_target_properties(
537- mirclient
538+set_target_properties(mirclient
539
540 PROPERTIES
541 SOVERSION ${MIRCLIENT_ABI}
542@@ -92,6 +93,7 @@
543 )
544
545 target_link_libraries(mirclient
546+
547 mirclientrpc
548 mirclientlttngstatic
549 mircommon
550
551=== modified file 'src/client/android/CMakeLists.txt'
552--- src/client/android/CMakeLists.txt 2014-12-08 04:03:47 +0000
553+++ src/client/android/CMakeLists.txt 2014-12-12 01:38:38 +0000
554@@ -14,17 +14,18 @@
555 )
556
557 add_library(
558- mirclientplatformandroid SHARED
559-
560+ mirclientplatformandroid MODULE
561+
562 $<TARGET_OBJECTS:mirclientplatformandroidobjects>
563 $<TARGET_OBJECTS:mirclient_platformimpl>
564 )
565
566 set_target_properties(
567 mirclientplatformandroid PROPERTIES
568- OUTPUT_NAME ${MIR_CLIENT_DRIVER}
569- LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/android
570- LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
571+ OUTPUT_NAME android
572+ LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
573+ PREFIX ""
574+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
575 )
576
577 target_link_libraries(mirclientplatformandroid
578@@ -33,20 +34,4 @@
579 ${LIBHARDWARE_LIBRARIES}
580 )
581
582-install(TARGETS mirclientplatformandroid LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/mir/${CLIENT_DRIVER}/android)
583-
584-if (MIR_TEST_PLATFORM STREQUAL "android")
585- add_custom_command(TARGET mirclientplatformandroid
586- POST_BUILD
587- COMMAND ${CMAKE_COMMAND} -E remove ${MIR_CLIENT_DRIVER_BINARY}
588- COMMAND ${CMAKE_COMMAND} -E create_symlink android/$<TARGET_FILE_NAME:mirclientplatformandroid> ${MIR_CLIENT_DRIVER_BINARY}
589- WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
590- )
591-
592- install(CODE
593- "execute_process(
594- COMMAND ln -sf mir/${CLIENT_DRIVER}/android/${MIR_CLIENT_DRIVER_BINARY}
595- WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
596- )"
597- )
598-endif()
599+install(TARGETS mirclientplatformandroid LIBRARY DESTINATION ${MIR_CLIENT_PLATFORM_PATH})
600
601=== modified file 'src/client/android/android_native_display_container.cpp'
602--- src/client/android/android_native_display_container.cpp 2014-12-08 04:03:47 +0000
603+++ src/client/android/android_native_display_container.cpp 2014-12-12 01:38:38 +0000
604@@ -62,16 +62,24 @@
605 bool
606 mcla::AndroidNativeDisplayContainer::validate(MirEGLNativeDisplayType display) const
607 {
608- return mir_connection_is_valid(static_cast<MirConnection*>(display));
609+ std::lock_guard<std::mutex> lg(guard);
610+ return (valid_displays.find(display) != valid_displays.end());
611 }
612
613 MirEGLNativeDisplayType
614-mcla::AndroidNativeDisplayContainer::create(MirConnection* connection)
615+mcla::AndroidNativeDisplayContainer::create(ClientContext* context)
616 {
617- return static_cast<MirEGLNativeDisplayType>(connection);
618+ std::lock_guard<std::mutex> lg(guard);
619+ auto egl_display = static_cast<MirEGLNativeDisplayType>(context);
620+ valid_displays.insert(egl_display);
621+
622+ return egl_display;
623 }
624
625 void
626-mcla::AndroidNativeDisplayContainer::release(MirEGLNativeDisplayType /* display */)
627+mcla::AndroidNativeDisplayContainer::release(MirEGLNativeDisplayType display)
628 {
629+ std::lock_guard<std::mutex> lg(guard);
630+
631+ valid_displays.erase(display);
632 }
633
634=== modified file 'src/client/android/android_native_display_container.h'
635--- src/client/android/android_native_display_container.h 2013-05-02 00:11:18 +0000
636+++ src/client/android/android_native_display_container.h 2014-12-12 01:38:38 +0000
637@@ -23,6 +23,9 @@
638
639 #include "mir_toolkit/client_types.h"
640
641+#include <unordered_set>
642+#include <mutex>
643+
644 namespace mir
645 {
646 namespace client
647@@ -36,14 +39,18 @@
648 AndroidNativeDisplayContainer();
649 virtual ~AndroidNativeDisplayContainer();
650
651- MirEGLNativeDisplayType create(MirConnection* connection);
652- void release(MirEGLNativeDisplayType display);
653+ MirEGLNativeDisplayType create(ClientContext* context) override;
654+ void release(MirEGLNativeDisplayType display) override;
655
656- bool validate(MirEGLNativeDisplayType display) const;
657+ bool validate(MirEGLNativeDisplayType display) const override;
658
659 protected:
660 AndroidNativeDisplayContainer(AndroidNativeDisplayContainer const&) = delete;
661 AndroidNativeDisplayContainer& operator=(AndroidNativeDisplayContainer const&) = delete;
662+
663+private:
664+ std::mutex mutable guard;
665+ std::unordered_set<MirEGLNativeDisplayType> valid_displays;
666 };
667
668 }
669
670=== modified file 'src/client/android/client_platform_factory.cpp'
671--- src/client/android/client_platform_factory.cpp 2014-02-07 15:43:41 +0000
672+++ src/client/android/client_platform_factory.cpp 2014-12-12 01:38:38 +0000
673@@ -16,19 +16,36 @@
674 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
675 */
676
677-#include "client_platform_factory.h"
678+#include "../client_platform_factory.h"
679+#include "mir_toolkit/client_types.h"
680+#include "../client_context.h"
681 #include "android_client_platform.h"
682
683+#include <boost/throw_exception.hpp>
684+#include <stdexcept>
685+
686 namespace mcl = mir::client;
687 namespace mcla = mcl::android;
688
689-std::shared_ptr<mcl::ClientPlatform>
690-mcla::ClientPlatformFactory::create_client_platform(mcl::ClientContext* /*context*/)
691+extern "C" std::shared_ptr<mcl::ClientPlatform>
692+mcl::create_client_platform(mcl::ClientContext* context)
693 {
694+ MirPlatformPackage platform;
695+ context->populate(platform);
696+ if (platform.data_items != 0 || platform.fd_items != 0)
697+ {
698+ BOOST_THROW_EXCEPTION((std::runtime_error{"Attempted to create Android client platform on non-Android server"}));
699+ }
700 return std::make_shared<mcla::AndroidClientPlatform>();
701 }
702
703-extern "C" std::shared_ptr<mcl::ClientPlatformFactory> mcl::create_client_platform_factory()
704+extern "C" bool
705+mcl::is_appropriate_module(mcl::ClientContext* context)
706 {
707- return std::make_shared<mcla::ClientPlatformFactory>();
708+ MirPlatformPackage platform;
709+ context->populate(platform);
710+ // TODO: Actually check what platform we're using, rather than blindly
711+ // hope we can distinguish them from the stuff they've put in the
712+ // PlatformPackage.
713+ return platform.data_items == 0 && platform.fd_items == 0;
714 }
715
716=== modified file 'src/client/android/client_platform_factory.h'
717--- src/client/android/client_platform_factory.h 2014-02-07 15:43:41 +0000
718+++ src/client/android/client_platform_factory.h 2014-12-12 01:38:38 +0000
719@@ -28,11 +28,8 @@
720 namespace android
721 {
722
723-class ClientPlatformFactory : public client::ClientPlatformFactory
724-{
725-public:
726- std::shared_ptr<ClientPlatform> create_client_platform(ClientContext* context) override;
727-};
728+extern "C" std::shared_ptr<ClientPlatform>
729+create_client_platform(ClientContext* context);
730
731 }
732 }
733
734=== modified file 'src/client/android/symbols.map'
735--- src/client/android/symbols.map 2014-12-08 04:03:47 +0000
736+++ src/client/android/symbols.map 2014-12-12 01:38:38 +0000
737@@ -1,5 +1,6 @@
738-MIR_CLIENTPLATFORM_1 {
739- global:
740- create_client_platform_factory;
741+MIR_CLIENT_PLATFORM_2 {
742+ global:
743+ create_client_platform;
744+ is_appropriate_module;
745 local: *;
746-};
747\ No newline at end of file
748+};
749
750=== modified file 'src/client/client_context.h'
751--- src/client/client_context.h 2013-08-28 03:41:48 +0000
752+++ src/client/client_context.h 2014-12-12 01:38:38 +0000
753@@ -19,6 +19,8 @@
754 #ifndef MIR_CLIENT_CLIENT_CONTEXT_H_
755 #define MIR_CLIENT_CLIENT_CONTEXT_H_
756
757+#include "mir_toolkit/client_types.h"
758+
759 namespace mir
760 {
761 namespace client
762@@ -29,7 +31,6 @@
763 public:
764 virtual ~ClientContext() {}
765
766- virtual MirConnection* mir_connection() = 0;
767 virtual void populate(MirPlatformPackage& platform_package) = 0;
768
769 protected:
770
771=== modified file 'src/client/client_platform_factory.h'
772--- src/client/client_platform_factory.h 2014-03-06 06:05:17 +0000
773+++ src/client/client_platform_factory.h 2014-12-12 01:38:38 +0000
774@@ -41,8 +41,11 @@
775 ClientPlatformFactory& operator=(ClientPlatformFactory const& p) = delete;
776 };
777
778-extern "C" typedef std::shared_ptr<ClientPlatformFactory>(*CreateClientPlatformFactory)();
779-extern "C" std::shared_ptr<ClientPlatformFactory> create_client_platform_factory();
780+extern "C" typedef std::shared_ptr<ClientPlatform>(*CreateClientPlatform)(ClientContext* context);
781+extern "C" std::shared_ptr<ClientPlatform> create_client_platform(ClientContext* context);
782+
783+extern "C" typedef bool (*ClientPlatformProbe)(ClientContext* context);
784+extern "C" bool is_appropriate_module(ClientContext* context);
785
786 }
787 }
788
789=== modified file 'src/client/connection_configuration.h'
790--- src/client/connection_configuration.h 2014-12-08 04:03:47 +0000
791+++ src/client/connection_configuration.h 2014-12-12 01:38:38 +0000
792@@ -39,8 +39,6 @@
793 class Logger;
794 }
795
796-class SharedLibrary;
797-
798 namespace client
799 {
800 class ConnectionSurfaceMap;
801@@ -65,7 +63,6 @@
802 virtual std::shared_ptr<LifecycleControl> the_lifecycle_control() = 0;
803 virtual std::shared_ptr<EventSink> the_event_sink() = 0;
804 virtual std::shared_ptr<EventHandlerRegister> the_event_handler_register() = 0;
805- virtual std::shared_ptr<SharedLibrary> the_platform_library() = 0;
806
807 protected:
808 ConnectionConfiguration() = default;
809
810=== modified file 'src/client/default_connection_configuration.cpp'
811--- src/client/default_connection_configuration.cpp 2014-12-08 04:03:47 +0000
812+++ src/client/default_connection_configuration.cpp 2014-12-12 01:38:38 +0000
813@@ -35,6 +35,7 @@
814 #include "lifecycle_control.h"
815 #include "mir/shared_library.h"
816 #include "client_platform_factory.h"
817+#include "probing_client_platform_factory.h"
818 #include "mir_event_distributor.h"
819 #include "mir/shared_library_prober.h"
820
821@@ -47,7 +48,10 @@
822 std::string const off_opt_val{"off"};
823 std::string const log_opt_val{"log"};
824 std::string const lttng_opt_val{"lttng"};
825-std::string const default_platform_lib{MIR_CLIENT_DRIVER_BINARY};
826+
827+// Shove this here until we properly manage the lifetime of our
828+// loadable modules
829+std::shared_ptr<mcl::ProbingClientPlatformFactory> the_platform_prober;
830
831 // Hack around the way Qt loads mir:
832 // qtmir and therefore Mir are loaded via dlopen(..., RTLD_LOCAL).
833@@ -108,11 +112,23 @@
834 return client_platform_factory(
835 [this]
836 {
837- auto const create_client_platform_factory =
838- the_platform_library()->load_function<mcl::CreateClientPlatformFactory>(
839- "create_client_platform_factory");
840-
841- return create_client_platform_factory();
842+ ensure_loaded_with_rtld_global();
843+ auto const platform_override = getenv("MIR_CLIENT_PLATFORM_LIB");
844+ std::vector<std::shared_ptr<mir::SharedLibrary>> platform_plugins;
845+ if (platform_override)
846+ {
847+ platform_plugins.push_back(std::make_shared<mir::SharedLibrary>(platform_override));
848+ }
849+ else
850+ {
851+ auto const platform_path_override = getenv("MIR_CLIENT_PLATFORM_PATH");
852+ auto const platform_path = platform_path_override ? platform_path_override : MIR_CLIENT_PLATFORM_PATH;
853+ platform_plugins = mir::libraries_for_path(platform_path, *the_shared_library_prober_report());
854+ }
855+
856+ the_platform_prober = std::make_shared<mcl::ProbingClientPlatformFactory>(platform_plugins);
857+
858+ return the_platform_prober;
859 });
860 }
861
862@@ -211,6 +227,7 @@
863 {
864 auto val_raw = getenv("MIR_CLIENT_SHARED_LIBRARY_PROBER_REPORT");
865 std::string const val{val_raw ? val_raw : off_opt_val};
866+
867 if (val == log_opt_val)
868 return std::make_shared<mir::logging::SharedLibraryProberReport>(the_logger());
869 else if (val == lttng_opt_val)
870@@ -219,15 +236,3 @@
871 return std::make_shared<mir::logging::NullSharedLibraryProberReport>();
872 });
873 }
874-
875-std::shared_ptr<mir::SharedLibrary> mcl::DefaultConnectionConfiguration::the_platform_library()
876-{
877- if (!platform_library)
878- {
879- ensure_loaded_with_rtld_global();
880- auto const val_raw = getenv("MIR_CLIENT_PLATFORM_LIB");
881- std::string const libname{val_raw ? val_raw : default_platform_lib};
882- platform_library = std::make_shared<mir::SharedLibrary>(libname);
883- }
884- return platform_library;
885-}
886
887=== modified file 'src/client/default_connection_configuration.h'
888--- src/client/default_connection_configuration.h 2014-12-08 04:03:47 +0000
889+++ src/client/default_connection_configuration.h 2014-12-12 01:38:38 +0000
890@@ -60,16 +60,12 @@
891 std::shared_ptr<EventSink> the_event_sink() override;
892 std::shared_ptr<EventHandlerRegister> the_event_handler_register() override;
893 std::shared_ptr<mir::SharedLibraryProberReport> the_shared_library_prober_report();
894- std::shared_ptr<SharedLibrary> the_platform_library() override;
895
896 virtual std::string the_socket_file();
897 virtual std::shared_ptr<rpc::RpcReport> the_rpc_report();
898 virtual std::shared_ptr<input::receiver::InputReceiverReport> the_input_receiver_report();
899
900 protected:
901- // MUST be first data member so it is destroyed last.
902- std::shared_ptr<mir::SharedLibrary> platform_library;
903-
904 CachedPtr<google::protobuf::RpcChannel> rpc_channel;
905 CachedPtr<mir::logging::Logger> logger;
906 CachedPtr<ClientPlatformFactory> client_platform_factory;
907
908=== modified file 'src/client/egl_native_display_container.h'
909--- src/client/egl_native_display_container.h 2014-03-06 06:05:17 +0000
910+++ src/client/egl_native_display_container.h 2014-12-12 01:38:38 +0000
911@@ -26,12 +26,14 @@
912 namespace client
913 {
914
915+class ClientContext;
916+
917 class EGLNativeDisplayContainer
918 {
919 public:
920 virtual ~EGLNativeDisplayContainer() {}
921
922- virtual MirEGLNativeDisplayType create(MirConnection* connection) = 0;
923+ virtual MirEGLNativeDisplayType create(ClientContext* context) = 0;
924 virtual void release(MirEGLNativeDisplayType display) = 0;
925
926 virtual bool validate(MirEGLNativeDisplayType display) const = 0;
927
928=== modified file 'src/client/mesa/CMakeLists.txt'
929--- src/client/mesa/CMakeLists.txt 2014-12-08 04:03:47 +0000
930+++ src/client/mesa/CMakeLists.txt 2014-12-12 01:38:38 +0000
931@@ -15,7 +15,7 @@
932 )
933
934 add_library(
935- mirclientplatformmesa SHARED
936+ mirclientplatformmesa MODULE
937
938 $<TARGET_OBJECTS:mirclientplatformmesaobjects>
939 $<TARGET_OBJECTS:mirclient_platformimpl>
940@@ -23,9 +23,10 @@
941
942 set_target_properties(
943 mirclientplatformmesa PROPERTIES
944- OUTPUT_NAME ${MIR_CLIENT_DRIVER}
945- LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/mesa
946- LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
947+ OUTPUT_NAME mesa
948+ LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
949+ PREFIX ""
950+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
951 )
952
953 target_link_libraries(mirclientplatformmesa
954@@ -33,21 +34,4 @@
955 ${DRM_LDFLAGS} ${DRM_LIBRARIES}
956 )
957
958-install(TARGETS mirclientplatformmesa LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/mir/${CLIENT_DRIVER}/mesa)
959-
960-if (MIR_TEST_PLATFORM STREQUAL "mesa")
961- add_custom_command(TARGET mirclientplatformmesa
962- POST_BUILD
963- COMMAND ${CMAKE_COMMAND} -E remove ${MIR_CLIENT_DRIVER_BINARY}
964- COMMAND ${CMAKE_COMMAND} -E create_symlink mesa/$<TARGET_FILE_NAME:mirclientplatformmesa> ${MIR_CLIENT_DRIVER_BINARY}
965- WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
966- )
967-
968- install(CODE
969- "execute_process(
970- COMMAND ln -sf mir/${CLIENT_DRIVER}/mesa/${MIR_CLIENT_DRIVER_BINARY}
971- WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
972- )"
973- )
974-endif()
975-
976+install(TARGETS mirclientplatformmesa LIBRARY DESTINATION ${MIR_CLIENT_PLATFORM_PATH})
977
978=== modified file 'src/client/mesa/client_platform.cpp'
979--- src/client/mesa/client_platform.cpp 2014-03-06 06:05:17 +0000
980+++ src/client/mesa/client_platform.cpp 2014-12-12 01:38:38 +0000
981@@ -95,7 +95,7 @@
982 std::shared_ptr<EGLNativeDisplayType> mclm::ClientPlatform::create_egl_native_display()
983 {
984 MirEGLNativeDisplayType *mir_native_display = new MirEGLNativeDisplayType;
985- *mir_native_display = display_container.create(context->mir_connection());
986+ *mir_native_display = display_container.create(context);
987 auto egl_native_display = reinterpret_cast<EGLNativeDisplayType*>(mir_native_display);
988
989 return std::shared_ptr<EGLNativeDisplayType>(egl_native_display, NativeDisplayDeleter(display_container));
990
991=== modified file 'src/client/mesa/client_platform_factory.cpp'
992--- src/client/mesa/client_platform_factory.cpp 2014-02-07 15:43:41 +0000
993+++ src/client/mesa/client_platform_factory.cpp 2014-12-12 01:38:38 +0000
994@@ -16,13 +16,17 @@
995 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
996 */
997
998-#include "client_platform_factory.h"
999+#include "../client_platform_factory.h"
1000 #include "client_platform.h"
1001+#include "mir_toolkit/client_types.h"
1002+#include "../client_context.h"
1003 #include "buffer_file_ops.h"
1004 #include "../egl_native_display_container.h"
1005
1006 #include <sys/mman.h>
1007 #include <unistd.h>
1008+#include <stdexcept>
1009+#include <boost/throw_exception.hpp>
1010
1011 namespace mcl = mir::client;
1012 namespace mclm = mcl::mesa;
1013@@ -57,15 +61,26 @@
1014
1015 }
1016
1017-std::shared_ptr<mcl::ClientPlatform>
1018-mclm::ClientPlatformFactory::create_client_platform(mcl::ClientContext* context)
1019+extern "C" std::shared_ptr<mcl::ClientPlatform> mcl::create_client_platform(mcl::ClientContext* context)
1020 {
1021+ MirPlatformPackage package;
1022+ context->populate(package);
1023+ if (package.data_items != 0 || package.fd_items != 1)
1024+ {
1025+ BOOST_THROW_EXCEPTION((std::runtime_error{"Attempted to create Mesa client platform on non-Mesa server"}));
1026+ }
1027 auto buffer_file_ops = std::make_shared<RealBufferFileOps>();
1028 return std::make_shared<mclm::ClientPlatform>(
1029 context, buffer_file_ops, mcl::EGLNativeDisplayContainer::instance());
1030 }
1031
1032-extern "C" std::shared_ptr<mcl::ClientPlatformFactory> mcl::create_client_platform_factory()
1033+extern "C" bool
1034+mcl::is_appropriate_module(mcl::ClientContext* context)
1035 {
1036- return std::make_shared<mclm::ClientPlatformFactory>();
1037+ MirPlatformPackage platform;
1038+ context->populate(platform);
1039+ // TODO: Actually check what platform we're using, rather than blindly
1040+ // hope we can distinguish them from the stuff they've put in the
1041+ // PlatformPackage.
1042+ return platform.data_items == 0 && platform.fd_items == 1;
1043 }
1044
1045=== modified file 'src/client/mesa/client_platform_factory.h'
1046--- src/client/mesa/client_platform_factory.h 2014-02-07 15:43:41 +0000
1047+++ src/client/mesa/client_platform_factory.h 2014-12-12 01:38:38 +0000
1048@@ -28,11 +28,6 @@
1049 namespace mesa
1050 {
1051
1052-class ClientPlatformFactory : public client::ClientPlatformFactory
1053-{
1054-public:
1055- std::shared_ptr<ClientPlatform> create_client_platform(ClientContext* context) override;
1056-};
1057
1058 }
1059 }
1060
1061=== modified file 'src/client/mesa/mesa_native_display_container.cpp'
1062--- src/client/mesa/mesa_native_display_container.cpp 2014-12-08 04:03:47 +0000
1063+++ src/client/mesa/mesa_native_display_container.cpp 2014-12-12 01:38:38 +0000
1064@@ -18,7 +18,7 @@
1065
1066 #include "mesa_native_display_container.h"
1067
1068-#include "mir_toolkit/mir_client_library.h"
1069+#include "../client_context.h"
1070
1071 #include <cstring>
1072 #include <unordered_set>
1073@@ -35,8 +35,8 @@
1074 static int egl_display_get_platform(MirMesaEGLNativeDisplay* display,
1075 MirPlatformPackage* package)
1076 {
1077- auto connection = static_cast<MirConnection*>(display->context);
1078- mir_connection_get_platform(connection, package);
1079+ auto context = static_cast<mcl::ClientContext*>(display->context);
1080+ context->populate(*package);
1081 return MIR_MESA_TRUE;
1082 }
1083
1084@@ -93,11 +93,11 @@
1085 }
1086
1087 MirEGLNativeDisplayType
1088-mclm::MesaNativeDisplayContainer::create(MirConnection* connection)
1089+mclm::MesaNativeDisplayContainer::create(ClientContext* context)
1090 {
1091 MirMesaEGLNativeDisplay* display = new MirMesaEGLNativeDisplay();
1092 display->display_get_platform = egl_display_get_platform;
1093- display->context = connection;
1094+ display->context = context;
1095
1096 std::lock_guard<std::mutex> lg(guard);
1097 auto egl_display = static_cast<MirEGLNativeDisplayType>(display);
1098
1099=== modified file 'src/client/mesa/mesa_native_display_container.h'
1100--- src/client/mesa/mesa_native_display_container.h 2014-03-06 06:05:17 +0000
1101+++ src/client/mesa/mesa_native_display_container.h 2014-12-12 01:38:38 +0000
1102@@ -40,7 +40,7 @@
1103 MesaNativeDisplayContainer();
1104 virtual ~MesaNativeDisplayContainer();
1105
1106- MirEGLNativeDisplayType create(MirConnection* connection);
1107+ MirEGLNativeDisplayType create(ClientContext* context);
1108 void release(MirEGLNativeDisplayType display);
1109
1110 bool validate(MirEGLNativeDisplayType display) const;
1111
1112=== modified file 'src/client/mesa/native_surface.cpp'
1113--- src/client/mesa/native_surface.cpp 2014-12-08 04:03:47 +0000
1114+++ src/client/mesa/native_surface.cpp 2014-12-12 01:38:38 +0000
1115@@ -20,7 +20,6 @@
1116 #include "../client_buffer.h"
1117 #include "native_surface.h"
1118
1119-#include <iostream>
1120 #include <boost/exception/diagnostic_information.hpp>
1121
1122 namespace mclm=mir::client::mesa;
1123
1124=== modified file 'src/client/mesa/symbols.map'
1125--- src/client/mesa/symbols.map 2014-12-08 04:03:47 +0000
1126+++ src/client/mesa/symbols.map 2014-12-12 01:38:38 +0000
1127@@ -1,7 +1,9 @@
1128-MIR_CLIENTPLATFORM_1 {
1129- global:
1130- create_client_platform_factory;
1131+MIR_CLIENT_PLATFORM_2 {
1132+ global:
1133+ create_client_platform;
1134+ is_appropriate_module;
1135 # Needed by our Mesa EGL platform
1136 mir_client_mesa_egl_native_display_is_valid;
1137- local: *;
1138+ local:
1139+ *;
1140 };
1141
1142=== modified file 'src/client/mir_connection.cpp'
1143--- src/client/mir_connection.cpp 2014-12-11 02:43:01 +0000
1144+++ src/client/mir_connection.cpp 2014-12-12 01:38:38 +0000
1145@@ -95,11 +95,11 @@
1146 MirConnection::MirConnection(
1147 mir::client::ConnectionConfiguration& conf) :
1148 deregisterer{this},
1149- platform_library{conf.the_platform_library()},
1150 channel(conf.the_rpc_channel()),
1151 server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
1152 debug(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
1153 logger(conf.the_logger()),
1154+ connect_done{false},
1155 client_platform_factory(conf.the_client_platform_factory()),
1156 input_platform(conf.the_input_platform()),
1157 display_configuration(conf.the_display_configuration()),
1158@@ -235,6 +235,9 @@
1159 set_error_message("Connect failed");
1160 }
1161 }
1162+
1163+ connect_done = true;
1164+
1165 /*
1166 * We need to create the client platform after the connection has been
1167 * established, to ensure that the client platform has access to all
1168@@ -370,9 +373,9 @@
1169
1170 void MirConnection::populate(MirPlatformPackage& platform_package)
1171 {
1172- std::lock_guard<decltype(mutex)> lock(mutex);
1173-
1174- if (!connect_result.has_error() && connect_result.has_platform())
1175+ // connect_result is write-once: once it's valid, we don't need to lock
1176+ // to use it.
1177+ if (connect_done && !connect_result.has_error() && connect_result.has_platform())
1178 {
1179 auto const& platform = connect_result.platform();
1180
1181@@ -428,11 +431,6 @@
1182 return platform;
1183 }
1184
1185-MirConnection* MirConnection::mir_connection()
1186-{
1187- return this;
1188-}
1189-
1190 EGLNativeDisplayType MirConnection::egl_native_display()
1191 {
1192 std::lock_guard<decltype(mutex)> lock(mutex);
1193
1194=== modified file 'src/client/mir_connection.h'
1195--- src/client/mir_connection.h 2014-12-11 02:43:01 +0000
1196+++ src/client/mir_connection.h 2014-12-12 01:38:38 +0000
1197@@ -22,6 +22,7 @@
1198 #include <memory>
1199 #include <unordered_set>
1200 #include <unordered_map>
1201+#include <atomic>
1202
1203 #include <mutex>
1204
1205@@ -117,8 +118,6 @@
1206
1207 static bool is_valid(MirConnection *connection);
1208
1209- MirConnection* mir_connection();
1210-
1211 EGLNativeDisplayType egl_native_display();
1212
1213 void on_surface_created(int id, MirSurface* surface);
1214@@ -153,6 +152,7 @@
1215 std::shared_ptr<mir::logging::Logger> const logger;
1216 mir::protobuf::Void void_response;
1217 mir::protobuf::Connection connect_result;
1218+ std::atomic<bool> connect_done;
1219 mir::protobuf::Void ignored;
1220 mir::protobuf::ConnectParameters connect_parameters;
1221 mir::protobuf::DRMAuthMagicStatus drm_auth_magic_status;
1222
1223=== modified file 'src/client/mir_surface_api.cpp'
1224--- src/client/mir_surface_api.cpp 2014-12-09 03:14:55 +0000
1225+++ src/client/mir_surface_api.cpp 2014-12-12 01:38:38 +0000
1226@@ -83,11 +83,13 @@
1227 params.buffer_usage = requested_specification->buffer_usage;
1228 params.output_id = requested_specification->output_id;
1229
1230+ bool fullscreen_tmp = requested_specification->fullscreen;
1231+
1232 auto shim_callback = new std::function<void(MirSurface*)>;
1233- *shim_callback = [requested_specification, shim_callback, callback, context]
1234+ *shim_callback = [fullscreen_tmp, shim_callback, callback, context]
1235 (MirSurface* surface)
1236 {
1237- if (requested_specification->fullscreen)
1238+ if (fullscreen_tmp)
1239 {
1240 mir_surface_set_state(surface, mir_surface_state_fullscreen);
1241 }
1242
1243=== added file 'src/client/probing_client_platform_factory.cpp'
1244--- src/client/probing_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
1245+++ src/client/probing_client_platform_factory.cpp 2014-12-12 01:38:38 +0000
1246@@ -0,0 +1,38 @@
1247+#include "probing_client_platform_factory.h"
1248+
1249+#include <boost/exception/all.hpp>
1250+#include <stdexcept>
1251+
1252+namespace mcl = mir::client;
1253+
1254+mcl::ProbingClientPlatformFactory::ProbingClientPlatformFactory(std::vector<std::shared_ptr<mir::SharedLibrary>> const& modules)
1255+ : platform_modules{modules}
1256+{
1257+ if (modules.empty())
1258+ {
1259+ BOOST_THROW_EXCEPTION(
1260+ std::runtime_error{"Attempted to create a ClientPlatformFactory with no platform modules"});
1261+ }
1262+}
1263+
1264+std::shared_ptr<mcl::ClientPlatform>
1265+mcl::ProbingClientPlatformFactory::create_client_platform(mcl::ClientContext* context)
1266+{
1267+ for (auto& module : platform_modules)
1268+ {
1269+ try
1270+ {
1271+ auto probe = module->load_function<mir::client::ClientPlatformProbe>("is_appropriate_module", CLIENT_PLATFORM_VERSION);
1272+ if (probe(context))
1273+ {
1274+ auto factory = module->load_function<mir::client::CreateClientPlatform>("create_client_platform", CLIENT_PLATFORM_VERSION);
1275+ return factory(context);
1276+ }
1277+ }
1278+ catch(std::runtime_error)
1279+ {
1280+ // We were handled a SharedLibrary that's not a client platform module?
1281+ }
1282+ }
1283+ BOOST_THROW_EXCEPTION(std::runtime_error{"No appropriate client platform module found"});
1284+}
1285
1286=== added file 'src/client/probing_client_platform_factory.h'
1287--- src/client/probing_client_platform_factory.h 1970-01-01 00:00:00 +0000
1288+++ src/client/probing_client_platform_factory.h 2014-12-12 01:38:38 +0000
1289@@ -0,0 +1,27 @@
1290+#ifndef MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
1291+#define MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
1292+
1293+#include <vector>
1294+
1295+#include "client_platform_factory.h"
1296+#include "mir/shared_library.h"
1297+
1298+namespace mir
1299+{
1300+namespace client
1301+{
1302+class ProbingClientPlatformFactory : public ClientPlatformFactory
1303+{
1304+public:
1305+ ProbingClientPlatformFactory(std::vector<std::shared_ptr<SharedLibrary>> const& modules);
1306+
1307+ std::shared_ptr<ClientPlatform> create_client_platform(ClientContext *context) override;
1308+private:
1309+ std::vector<std::shared_ptr<SharedLibrary>> platform_modules;
1310+};
1311+
1312+
1313+}
1314+}
1315+
1316+#endif // MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
1317
1318=== modified file 'src/common/symbols.map'
1319--- src/common/symbols.map 2014-12-11 02:43:01 +0000
1320+++ src/common/symbols.map 2014-12-12 01:38:38 +0000
1321@@ -203,11 +203,10 @@
1322 };
1323
1324 MIR_COMMON_3.1 {
1325- global:
1326- extern "C++" {
1327- mir::log*;
1328- mir::logv*;
1329- };
1330- local: *;
1331-};
1332-
1333+ global:
1334+ extern "C++" {
1335+ mir::log*;
1336+ mir::logv*;
1337+ mir::libraries_for_path*;
1338+ };
1339+} MIR_COMMON_3;
1340
1341=== modified file 'tests/CMakeLists.txt'
1342--- tests/CMakeLists.txt 2014-12-08 04:03:47 +0000
1343+++ tests/CMakeLists.txt 2014-12-12 01:38:38 +0000
1344@@ -26,9 +26,17 @@
1345 endif()
1346
1347 if (MIR_TEST_PLATFORM STREQUAL "android")
1348+ add_definitions(-DANDROID)
1349+endif()
1350+
1351+if (MIR_BUILD_PLATFORM_ANDROID)
1352 #avoid complaints about poor quality android headers
1353 include_directories(SYSTEM ${LIBHARDWARE_INCLUDE_DIRS})
1354- add_definitions(-DANDROID)
1355+ add_definitions(-DMIR_BUILD_PLATFORM_ANDROID)
1356+endif()
1357+
1358+if (MIR_BUILD_PLATFORM_MESA)
1359+ add_definitions(-DMIR_BUILD_PLATFORM_MESA)
1360 endif()
1361
1362 include_directories(
1363
1364=== modified file 'tests/acceptance-tests/CMakeLists.txt'
1365--- tests/acceptance-tests/CMakeLists.txt 2014-12-11 02:43:01 +0000
1366+++ tests/acceptance-tests/CMakeLists.txt 2014-12-12 01:38:38 +0000
1367@@ -6,7 +6,6 @@
1368
1369 add_definitions(
1370 -DMIR_PLATFORM_DRIVER_BINARY="${MIR_PLATFORM_DRIVER_BINARY}"
1371- -DMIR_CLIENT_DRIVER_BINARY="${MIR_CLIENT_DRIVER_BINARY}"
1372 )
1373
1374 set(
1375@@ -52,7 +51,7 @@
1376 list(APPEND SOURCES test_symbols_required_by_mesa.cpp)
1377 endif()
1378
1379-add_executable(
1380+mir_add_wrapped_executable(
1381 mir_acceptance_tests
1382
1383 ${SOURCES}
1384@@ -74,9 +73,9 @@
1385 mirplatform
1386
1387 mir-test
1388- mir-test-framework
1389 mir-test-doubles
1390 mir-test-doubles-platform
1391+ mir-test-framework
1392 3rd_party
1393
1394 ${PROTOBUF_LIBRARIES}
1395@@ -97,8 +96,3 @@
1396 if (MIR_RUN_ACCEPTANCE_TESTS)
1397 mir_discover_tests(mir_acceptance_tests)
1398 endif (MIR_RUN_ACCEPTANCE_TESTS)
1399-
1400-install(
1401- TARGETS mir_acceptance_tests
1402- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1403-)
1404
1405=== modified file 'tests/acceptance-tests/test_client_library.cpp'
1406--- tests/acceptance-tests/test_client_library.cpp 2014-12-11 02:43:01 +0000
1407+++ tests/acceptance-tests/test_client_library.cpp 2014-12-12 01:38:38 +0000
1408@@ -20,6 +20,7 @@
1409
1410 #include "mir_test_framework/headless_in_process_server.h"
1411 #include "mir_test_framework/using_stub_client_platform.h"
1412+#include "mir_test_framework/stub_platform_helpers.h"
1413 #include "mir_test/validity_matchers.h"
1414
1415 #include "src/client/client_buffer.h"
1416@@ -201,6 +202,7 @@
1417 EXPECT_EQ(request_buffer_usage, response_params.buffer_usage);
1418
1419 mir_wait_for(mir_surface_release( surface, release_surface_callback, this));
1420+ mir_connection_release(connection);
1421 }
1422
1423 TEST_F(ClientLibrary, can_set_surface_types)
1424@@ -545,15 +547,14 @@
1425
1426 TEST_F(ClientLibrary, accesses_platform_package)
1427 {
1428+ using namespace testing;
1429 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
1430
1431 MirPlatformPackage platform_package;
1432- platform_package.data_items = -1;
1433- platform_package.fd_items = -1;
1434+ ::memset(&platform_package, -1, sizeof(platform_package));
1435
1436 mir_connection_get_platform(connection, &platform_package);
1437- EXPECT_GE(0, platform_package.data_items);
1438- EXPECT_GE(0, platform_package.fd_items);
1439+ EXPECT_THAT(platform_package, mtf::IsStubPlatformPackage());
1440
1441 mir_connection_release(connection);
1442 }
1443
1444=== modified file 'tests/acceptance-tests/test_client_library_drm.cpp'
1445--- tests/acceptance-tests/test_client_library_drm.cpp 2014-12-08 04:03:47 +0000
1446+++ tests/acceptance-tests/test_client_library_drm.cpp 2014-12-12 01:38:38 +0000
1447@@ -32,10 +32,15 @@
1448 {
1449 struct gbm_device* dev = reinterpret_cast<struct gbm_device*>(connection);
1450
1451+ MirPlatformPackage pkg;
1452+
1453+ mir_connection_get_platform(connection, &pkg);
1454+ int const previous_data_count{pkg.data_items};
1455+
1456 mir_connection_drm_set_gbm_device(connection, dev);
1457+ mir_connection_get_platform(connection, &pkg);
1458
1459- MirPlatformPackage pkg;
1460- mir_connection_get_platform(connection, &pkg);
1461- EXPECT_THAT(pkg.data_items, Eq(sizeof(dev) / sizeof(int)));
1462- EXPECT_THAT(*reinterpret_cast<struct gbm_device**>(&pkg.data[0]), Eq(dev));
1463+ EXPECT_THAT(pkg.data_items, Eq(previous_data_count + (sizeof(dev) / sizeof(int))));
1464+ EXPECT_THAT(reinterpret_cast<struct gbm_device*>(pkg.data[previous_data_count]),
1465+ Eq(dev));
1466 }
1467
1468=== modified file 'tests/acceptance-tests/test_symbols_required_by_mesa.cpp'
1469--- tests/acceptance-tests/test_symbols_required_by_mesa.cpp 2014-12-08 04:03:47 +0000
1470+++ tests/acceptance-tests/test_symbols_required_by_mesa.cpp 2014-12-12 01:38:38 +0000
1471@@ -21,11 +21,14 @@
1472
1473 #include <dlfcn.h>
1474
1475+#include "mir_test_framework/executable_path.h"
1476+
1477 using namespace testing;
1478+namespace mtf = mir_test_framework;
1479
1480-TEST(SymbolsRequiredByMesa, are_exported_by_libmirclientplatform)
1481+TEST(SymbolsRequiredByMesa, are_exported_by_client_platform_mesa)
1482 {
1483- auto const handle = dlopen(MIR_CLIENT_DRIVER_BINARY, RTLD_LAZY);
1484+ auto const handle = dlopen((mtf::library_path() + "/client-modules/mesa.so").c_str(), RTLD_LAZY);
1485 ASSERT_THAT(handle, NotNull());
1486
1487 auto const sym = dlsym(handle, "mir_client_mesa_egl_native_display_is_valid");
1488
1489=== modified file 'tests/include/mir_test_doubles/mock_client_context.h'
1490--- tests/include/mir_test_doubles/mock_client_context.h 2013-04-24 05:22:20 +0000
1491+++ tests/include/mir_test_doubles/mock_client_context.h 2014-12-12 01:38:38 +0000
1492@@ -33,18 +33,12 @@
1493 struct MockClientContext : public client::ClientContext
1494 {
1495 MockClientContext()
1496- : connection{reinterpret_cast<MirConnection*>(0xabcdef)}
1497 {
1498 using namespace testing;
1499
1500- ON_CALL(*this, mir_connection()).WillByDefault(Return(connection));
1501- EXPECT_CALL(*this, mir_connection()).Times(AtLeast(0));
1502 EXPECT_CALL(*this, populate(_)).Times(AtLeast(0));
1503 }
1504
1505- MirConnection* connection;
1506-
1507- MOCK_METHOD0(mir_connection, MirConnection*());
1508 MOCK_METHOD1(populate, void(MirPlatformPackage&));
1509 };
1510
1511
1512=== modified file 'tests/include/mir_test_doubles/stub_client_buffer.h'
1513--- tests/include/mir_test_doubles/stub_client_buffer.h 2014-11-24 16:04:38 +0000
1514+++ tests/include/mir_test_doubles/stub_client_buffer.h 2014-12-12 01:38:38 +0000
1515@@ -65,7 +65,11 @@
1516
1517 std::shared_ptr<graphics::NativeBuffer> native_buffer_handle() const override
1518 {
1519+#ifndef ANDROID
1520+ return package;
1521+#else
1522 return std::shared_ptr<graphics::NativeBuffer>();
1523+#endif
1524 }
1525 void update_from(MirBufferPackage const&) override {}
1526 void fill_update_msg(MirBufferPackage&) override{}
1527
1528=== added file 'tests/include/mir_test_framework/client_platform_factory.h'
1529--- tests/include/mir_test_framework/client_platform_factory.h 1970-01-01 00:00:00 +0000
1530+++ tests/include/mir_test_framework/client_platform_factory.h 2014-12-12 01:38:38 +0000
1531@@ -0,0 +1,72 @@
1532+/*
1533+ * Copyright © 2014 Canonical Ltd.
1534+ *
1535+ * This program is free software: you can redistribute it and/or modify
1536+ * it under the terms of the GNU General Public License version 3 as
1537+ * published by the Free Software Foundation.
1538+ *
1539+ * This program is distributed in the hope that it will be useful,
1540+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1541+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1542+ * GNU General Public License for more details.
1543+ *
1544+ * You should have received a copy of the GNU General Public License
1545+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1546+ *
1547+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1548+ */
1549+
1550+#ifndef MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
1551+#define MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
1552+
1553+
1554+#include "mir/shared_library.h"
1555+#include "src/client/client_platform_factory.h"
1556+#include "executable_path.h"
1557+#include "mir_test_doubles/mock_client_context.h"
1558+
1559+namespace mtd = mir::test::doubles;
1560+
1561+namespace mir_test_framework
1562+{
1563+std::shared_ptr<mir::SharedLibrary> platform_library;
1564+
1565+std::shared_ptr<mir::client::ClientPlatform> create_android_client_platform()
1566+{
1567+ using namespace testing;
1568+ mtd::MockClientContext ctx;
1569+ ON_CALL(ctx, populate(_))
1570+ .WillByDefault(Invoke([](MirPlatformPackage& package) { ::memset(&package, 0, sizeof(package)); }));
1571+ platform_library = std::make_shared<mir::SharedLibrary>(library_path() + "/client-modules/android.so");
1572+ auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
1573+ return platform_factory(&ctx);
1574+}
1575+
1576+std::shared_ptr<mir::client::ClientPlatform> create_mesa_client_platform()
1577+{
1578+ using namespace testing;
1579+ mtd::MockClientContext ctx;
1580+ ON_CALL(ctx, populate(_))
1581+ .WillByDefault(Invoke([](MirPlatformPackage& package)
1582+ {
1583+ ::memset(&package, 0, sizeof(package));
1584+ package.fd_items = 1;
1585+ }));
1586+ platform_library = std::make_shared<mir::SharedLibrary>(library_path() + "/client-modules/mesa.so");
1587+ auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
1588+ return platform_factory(&ctx);
1589+}
1590+
1591+std::shared_ptr<mir::SharedLibrary>
1592+get_platform_library()
1593+{
1594+ if (!platform_library)
1595+ {
1596+ throw std::logic_error{"Must call one of create_*_client_platform() before calling get_platform_library()"};
1597+ }
1598+ return platform_library;
1599+}
1600+
1601+}
1602+
1603+#endif // MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
1604
1605=== added file 'tests/include/mir_test_framework/stub_client_platform_factory.h'
1606--- tests/include/mir_test_framework/stub_client_platform_factory.h 1970-01-01 00:00:00 +0000
1607+++ tests/include/mir_test_framework/stub_client_platform_factory.h 2014-12-12 01:38:38 +0000
1608@@ -0,0 +1,33 @@
1609+/*
1610+ * Copyright © 2014 Canonical Ltd.
1611+ *
1612+ * This program is free software: you can redistribute it and/or modify it
1613+ * under the terms of the GNU General Public License version 3,
1614+ * as published by the Free Software Foundation.
1615+ *
1616+ * This program is distributed in the hope that it will be useful,
1617+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1618+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1619+ * GNU General Public License for more details.
1620+ *
1621+ * You should have received a copy of the GNU General Public License
1622+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1623+ *
1624+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1625+ */
1626+
1627+#ifndef MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_FACTORY_
1628+#define MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_FACTORY_
1629+
1630+#include "src/client/client_platform_factory.h"
1631+
1632+namespace mir_test_framework
1633+{
1634+
1635+struct StubClientPlatformFactory : public mir::client::ClientPlatformFactory
1636+{
1637+ std::shared_ptr<mir::client::ClientPlatform> create_client_platform(mir::client::ClientContext* context) override;
1638+};
1639+
1640+}
1641+#endif /* MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_ */
1642
1643=== added file 'tests/include/mir_test_framework/stub_platform_helpers.h'
1644--- tests/include/mir_test_framework/stub_platform_helpers.h 1970-01-01 00:00:00 +0000
1645+++ tests/include/mir_test_framework/stub_platform_helpers.h 2014-12-12 01:38:38 +0000
1646@@ -0,0 +1,53 @@
1647+/*
1648+ * Copyright © 2014 Canonical Ltd.
1649+ *
1650+ * This program is free software: you can redistribute it and/or modify
1651+ * it under the terms of the GNU General Public License version 3 as
1652+ * published by the Free Software Foundation.
1653+ *
1654+ * This program is distributed in the hope that it will be useful,
1655+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1656+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1657+ * GNU General Public License for more details.
1658+ *
1659+ * You should have received a copy of the GNU General Public License
1660+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1661+ *
1662+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1663+ */
1664+
1665+#ifndef MIR_TEST_FRAMEWORK_STUB_PLATFORM_HELPERS_H_
1666+#define MIR_TEST_FRAMEWORK_STUB_PLATFORM_HELPERS_H_
1667+
1668+#include "mir/graphics/platform_ipc_package.h"
1669+#include "mir_toolkit/client_types.h"
1670+
1671+#include <gmock/gmock.h>
1672+
1673+namespace mir_test_framework
1674+{
1675+constexpr int stub_data_size{21};
1676+constexpr int stub_data_guard{0x0eadbeef};
1677+
1678+static inline void pack_stub_ipc_package(mir::graphics::PlatformIPCPackage& package)
1679+{
1680+ package.ipc_data = std::vector<int32_t>(stub_data_size, -1);
1681+ package.ipc_data[0] = stub_data_guard;
1682+}
1683+
1684+static inline void create_stub_platform_package(MirPlatformPackage& package)
1685+{
1686+ ::memset(&package, 0, sizeof(package));
1687+ package.data_items = stub_data_size;
1688+ package.data[0] = stub_data_guard;
1689+}
1690+
1691+MATCHER(IsStubPlatformPackage, "")
1692+{
1693+ return (arg.data_items == stub_data_size) &&
1694+ (arg.data[0] == stub_data_guard) &&
1695+ (arg.fd_items == 0);
1696+}
1697+}
1698+
1699+#endif // MIR_TEST_FRAMEWORK_STUB_PLATFORM_HELPERS_H_
1700
1701=== modified file 'tests/integration-tests/CMakeLists.txt'
1702--- tests/integration-tests/CMakeLists.txt 2014-12-08 04:03:47 +0000
1703+++ tests/integration-tests/CMakeLists.txt 2014-12-12 01:38:38 +0000
1704@@ -66,7 +66,7 @@
1705 endif()
1706
1707 link_directories(${LIBRARY_OUTPUT_PATH})
1708-add_executable(
1709+mir_add_wrapped_executable(
1710 mir_integration_tests
1711 ${INTEGRATION_TESTS_SRCS}
1712 ${MIR_SERVER_OBJECTS}
1713@@ -126,8 +126,3 @@
1714 if (MIR_RUN_INTEGRATION_TESTS)
1715 mir_discover_tests(mir_integration_tests)
1716 endif (MIR_RUN_INTEGRATION_TESTS)
1717-
1718-install(
1719- TARGETS mir_integration_tests
1720- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1721-)
1722
1723=== modified file 'tests/mir_test_doubles/CMakeLists.txt'
1724--- tests/mir_test_doubles/CMakeLists.txt 2014-12-08 04:03:47 +0000
1725+++ tests/mir_test_doubles/CMakeLists.txt 2014-12-12 01:38:38 +0000
1726@@ -30,13 +30,14 @@
1727 ${CMAKE_CURRENT_SOURCE_DIR}/mock_gl.cpp
1728 )
1729
1730-if (MIR_TEST_PLATFORM STREQUAL "mesa")
1731+if (MIR_BUILD_PLATFORM_MESA)
1732 include_directories(${DRM_INCLUDE_DIRS} ${GBM_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR})
1733 list(APPEND MIR_TEST_DOUBLES_PLATFORM_SRCS
1734 ${CMAKE_CURRENT_SOURCE_DIR}/mock_drm.cpp
1735 ${CMAKE_CURRENT_SOURCE_DIR}/mock_gbm.cpp
1736 )
1737-elseif (MIR_TEST_PLATFORM STREQUAL "android")
1738+endif()
1739+if (MIR_BUILD_PLATFORM_ANDROID)
1740 list(APPEND MIR_TEST_DOUBLES_PLATFORM_SRCS
1741 ${CMAKE_CURRENT_SOURCE_DIR}/mock_android_hw.cpp
1742 )
1743
1744=== modified file 'tests/mir_test_framework/CMakeLists.txt'
1745--- tests/mir_test_framework/CMakeLists.txt 2014-12-11 02:43:01 +0000
1746+++ tests/mir_test_framework/CMakeLists.txt 2014-12-12 01:38:38 +0000
1747@@ -4,10 +4,11 @@
1748 ${PROJECT_SOURCE_DIR}/src/include/common
1749 ${PROJECT_SOURCE_DIR}/src/include/server
1750 ${PROJECT_SOURCE_DIR}/src/include/client
1751- ${Boost_INCLUDE_DIRS}
1752- ${GLESv2_INCLUDE_DIRS}
1753- ${CMAKE_SOURCE_DIR}
1754- ${UMOCKDEV_INCLUDE_DIRS}
1755+ ${Boost_INCLUDE_DIRS}
1756+ ${GLESv2_INCLUDE_DIRS}
1757+ ${CMAKE_SOURCE_DIR}
1758+ ${UMOCKDEV_INCLUDE_DIRS}
1759+ ${ANDROID_HEADERS_INCLUDE_DIRS}
1760 )
1761
1762 set(
1763@@ -31,6 +32,7 @@
1764 display_server_test_fixture.cpp
1765 process.cpp
1766 using_stub_client_platform.cpp
1767+ stub_client_platform_factory.cpp
1768 udev_environment.cpp
1769 declarative_placement_strategy.cpp
1770 fake_event_hub_server_configuration.cpp
1771@@ -68,6 +70,29 @@
1772 ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
1773 )
1774
1775+set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols-client.map)
1776+
1777+add_library(
1778+ mirclientplatformstub MODULE
1779+
1780+ stub_client_platform_module.cpp
1781+)
1782+
1783+target_link_libraries(
1784+ mirclientplatformstub
1785+
1786+ mir-test-framework
1787+ ${UMOCKDEV_LDFLAGS} ${UMOCKDEV_LIBRARIES}
1788+)
1789+
1790+set_target_properties(
1791+ mirclientplatformstub PROPERTIES;
1792+ LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
1793+ OUTPUT_NAME dummy
1794+ PREFIX ""
1795+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
1796+)
1797+
1798 add_custom_command(TARGET mir-test-framework POST_BUILD
1799 COMMAND ${CMAKE_COMMAND} -E copy_directory
1800 ${CMAKE_CURRENT_SOURCE_DIR}/udev_recordings ${CMAKE_BINARY_DIR}/bin/udev_recordings
1801@@ -96,3 +121,4 @@
1802 )
1803
1804 install(TARGETS mirplatformstub LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
1805+install(TARGETS mirclientplatformstub LIBRARY DESTINATION ${MIR_CLIENT_PLATFORM_PATH})
1806
1807=== added file 'tests/mir_test_framework/stub_client_platform_factory.cpp'
1808--- tests/mir_test_framework/stub_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
1809+++ tests/mir_test_framework/stub_client_platform_factory.cpp 2014-12-12 01:38:38 +0000
1810@@ -0,0 +1,74 @@
1811+/*
1812+ * Copyright © 2014 Canonical Ltd.
1813+ *
1814+ * This program is free software: you can redistribute it and/or modify it
1815+ * under the terms of the GNU General Public License version 3,
1816+ * as published by the Free Software Foundation.
1817+ *
1818+ * This program is distributed in the hope that it will be useful,
1819+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1820+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1821+ * GNU General Public License for more details.
1822+ *
1823+ * You should have received a copy of the GNU General Public License
1824+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1825+ *
1826+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1827+ */
1828+
1829+#include "mir_test_framework/stub_client_platform_factory.h"
1830+#include "mir_test_doubles/stub_client_buffer_factory.h"
1831+#include "src/client/client_buffer_factory.h"
1832+#include "src/client/client_buffer.h"
1833+#include "src/client/client_platform.h"
1834+
1835+#include <string.h>
1836+
1837+namespace mcl = mir::client;
1838+namespace geom = mir::geometry;
1839+namespace mtf = mir_test_framework;
1840+namespace mtd = mir::test::doubles;
1841+
1842+namespace
1843+{
1844+struct StubClientPlatform : public mcl::ClientPlatform
1845+{
1846+ MirPlatformType platform_type() const
1847+ {
1848+ return mir_platform_type_gbm;
1849+ }
1850+
1851+ std::shared_ptr<mcl::ClientBufferFactory> create_buffer_factory()
1852+ {
1853+ return std::make_shared<mtd::StubClientBufferFactory>();
1854+ }
1855+
1856+ std::shared_ptr<EGLNativeWindowType> create_egl_native_window(mcl::ClientSurface*)
1857+ {
1858+ auto fake_window = reinterpret_cast<EGLNativeWindowType>(0x12345678lu);
1859+ return std::make_shared<EGLNativeWindowType>(fake_window);
1860+ }
1861+
1862+ std::shared_ptr<EGLNativeDisplayType> create_egl_native_display()
1863+ {
1864+ auto fake_display = reinterpret_cast<EGLNativeDisplayType>(0x12345678lu);
1865+ return std::make_shared<EGLNativeDisplayType>(fake_display);
1866+ }
1867+
1868+ MirNativeBuffer* convert_native_buffer(mir::graphics::NativeBuffer* buf) const
1869+ {
1870+ static_cast<void>(buf);
1871+#ifndef ANDROID
1872+ return buf;
1873+#else
1874+ return nullptr;
1875+#endif
1876+ }
1877+};
1878+}
1879+
1880+std::shared_ptr<mcl::ClientPlatform>
1881+mtf::StubClientPlatformFactory::create_client_platform(mcl::ClientContext*)
1882+{
1883+ return std::make_shared<StubClientPlatform>();
1884+}
1885
1886=== added file 'tests/mir_test_framework/stub_client_platform_module.cpp'
1887--- tests/mir_test_framework/stub_client_platform_module.cpp 1970-01-01 00:00:00 +0000
1888+++ tests/mir_test_framework/stub_client_platform_module.cpp 2014-12-12 01:38:38 +0000
1889@@ -0,0 +1,41 @@
1890+/*
1891+ * Copyright © 2014 Canonical Ltd.
1892+ *
1893+ * This program is free software: you can redistribute it and/or modify it
1894+ * under the terms of the GNU General Public License version 3,
1895+ * as published by the Free Software Foundation.
1896+ *
1897+ * This program is distributed in the hope that it will be useful,
1898+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1899+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1900+ * GNU General Public License for more details.
1901+ *
1902+ * You should have received a copy of the GNU General Public License
1903+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1904+ *
1905+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>>
1906+ */
1907+
1908+#include "src/client/client_platform_factory.h"
1909+#include "src/client/client_context.h"
1910+
1911+#include "mir_test_framework/stub_client_platform_factory.h"
1912+#include "mir_test_framework/stub_platform_helpers.h"
1913+#include <memory>
1914+#include <gmock/gmock.h>
1915+
1916+namespace mtf = mir_test_framework;
1917+namespace mcl = mir::client;
1918+
1919+extern "C" std::shared_ptr<mcl::ClientPlatform> create_client_platform(mcl::ClientContext* context)
1920+{
1921+ return mtf::StubClientPlatformFactory{}.create_client_platform(context);
1922+}
1923+
1924+extern "C" bool is_appropriate_module(mcl::ClientContext* context)
1925+{
1926+ using namespace testing;
1927+ MirPlatformPackage package;
1928+ context->populate(package);
1929+ return Matches(mtf::IsStubPlatformPackage())(package);
1930+}
1931
1932=== modified file 'tests/mir_test_framework/stubbed_graphics_platform.cpp'
1933--- tests/mir_test_framework/stubbed_graphics_platform.cpp 2014-12-11 02:43:01 +0000
1934+++ tests/mir_test_framework/stubbed_graphics_platform.cpp 2014-12-12 01:38:38 +0000
1935@@ -22,6 +22,8 @@
1936 #include "mir/graphics/buffer_writer.h"
1937 #include "mir/graphics/native_platform.h"
1938
1939+#include "mir_test_framework/stub_platform_helpers.h"
1940+
1941 #include "mir_test_doubles/stub_buffer_allocator.h"
1942 #include "mir_test_doubles/stub_display.h"
1943
1944@@ -146,7 +148,9 @@
1945
1946 std::shared_ptr<mg::PlatformIPCPackage> connection_ipc_package() override
1947 {
1948- return std::make_shared<mg::PlatformIPCPackage>();
1949+ auto package = std::make_shared<mg::PlatformIPCPackage>();
1950+ mtf::pack_stub_ipc_package(*package);
1951+ return package;
1952 }
1953
1954 mg::PlatformIPCPackage platform_operation(
1955
1956=== added file 'tests/mir_test_framework/symbols-client.map'
1957--- tests/mir_test_framework/symbols-client.map 1970-01-01 00:00:00 +0000
1958+++ tests/mir_test_framework/symbols-client.map 2014-12-12 01:38:38 +0000
1959@@ -0,0 +1,7 @@
1960+MIR_CLIENT_PLATFORM_2 {
1961+ global:
1962+ create_client_platform;
1963+ is_appropriate_module;
1964+ local:
1965+ *;
1966+};
1967
1968=== modified file 'tests/unit-tests/CMakeLists.txt'
1969--- tests/unit-tests/CMakeLists.txt 2014-12-08 04:03:47 +0000
1970+++ tests/unit-tests/CMakeLists.txt 2014-12-12 01:38:38 +0000
1971@@ -56,7 +56,7 @@
1972
1973 link_directories(${LIBRARY_OUTPUT_PATH})
1974
1975-add_executable(mir_unit_tests
1976+mir_add_wrapped_executable(mir_unit_tests
1977 ${UNIT_TEST_SOURCES}
1978 ${MIR_SERVER_OBJECTS}
1979 $<TARGET_OBJECTS:mirclientobjects>
1980@@ -117,11 +117,6 @@
1981 mir_discover_tests(mir_unit_tests LD_PRELOAD=libumockdev-preload.so.0 G_SLICE=always-malloc G_DEBUG=gc-friendly)
1982 endif (MIR_RUN_UNIT_TESTS)
1983
1984-install(
1985- TARGETS mir_unit_tests
1986- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1987-)
1988-
1989 add_custom_command(TARGET mir_unit_tests POST_BUILD
1990 COMMAND ${CMAKE_COMMAND} -E copy_directory
1991 ${CMAKE_CURRENT_SOURCE_DIR}/test_data ${CMAKE_BINARY_DIR}/bin/test_data
1992
1993=== modified file 'tests/unit-tests/client/CMakeLists.txt'
1994--- tests/unit-tests/client/CMakeLists.txt 2014-12-08 04:03:47 +0000
1995+++ tests/unit-tests/client/CMakeLists.txt 2014-12-12 01:38:38 +0000
1996@@ -10,6 +10,7 @@
1997 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_display_conf.cpp
1998 ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_screencast.cpp
1999 ${CMAKE_CURRENT_SOURCE_DIR}/test_protobuf_rpc_channel.cpp
2000+ ${CMAKE_CURRENT_SOURCE_DIR}/test_probing_client_platform_factory.cpp
2001 ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_prompt_session.cpp
2002 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_distributor.cpp
2003 ${CMAKE_CURRENT_SOURCE_DIR}/test_periodic_perf_report.cpp
2004
2005=== modified file 'tests/unit-tests/client/android/test_android_client_platform.cpp'
2006--- tests/unit-tests/client/android/test_android_client_platform.cpp 2014-03-06 06:05:17 +0000
2007+++ tests/unit-tests/client/android/test_android_client_platform.cpp 2014-12-12 01:38:38 +0000
2008@@ -17,9 +17,9 @@
2009 */
2010
2011 #include "src/client/client_platform.h"
2012-#include "src/client/android/client_platform_factory.h"
2013 #include "mir_test_doubles/mock_client_context.h"
2014 #include "mir_test_doubles/mock_client_surface.h"
2015+#include "mir_test_framework/client_platform_factory.h"
2016
2017 #include <EGL/egl.h>
2018
2019@@ -28,13 +28,12 @@
2020 namespace mcl = mir::client;
2021 namespace mt = mir::test;
2022 namespace mtd = mt::doubles;
2023+namespace mtf = mir_test_framework;
2024
2025 TEST(AndroidClientPlatformTest, egl_native_display_is_egl_default_display)
2026 {
2027- mtd::MockClientContext context;
2028- mcl::android::ClientPlatformFactory factory;
2029 mtd::MockClientSurface surface;
2030- auto platform = factory.create_client_platform(&context);
2031+ auto platform = mtf::create_android_client_platform();
2032 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
2033 auto native_display = platform->create_egl_native_display();
2034 EXPECT_EQ(EGL_DEFAULT_DISPLAY, *native_display);
2035@@ -42,10 +41,8 @@
2036
2037 TEST(AndroidClientPlatformTest, egl_native_window_is_set)
2038 {
2039- mtd::MockClientContext context;
2040- mcl::android::ClientPlatformFactory factory;
2041 mtd::MockClientSurface surface;
2042- auto platform = factory.create_client_platform(&context);
2043+ auto platform = mtf::create_android_client_platform();
2044 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
2045 auto egl_native_window = platform->create_egl_native_window(&surface);
2046 EXPECT_NE(nullptr, egl_native_window);
2047
2048=== modified file 'tests/unit-tests/client/mesa/test_client_platform.cpp'
2049--- tests/unit-tests/client/mesa/test_client_platform.cpp 2014-03-06 06:05:17 +0000
2050+++ tests/unit-tests/client/mesa/test_client_platform.cpp 2014-12-12 01:38:38 +0000
2051@@ -17,9 +17,9 @@
2052 */
2053
2054 #include "src/client/client_platform.h"
2055-#include "src/client/mesa/client_platform_factory.h"
2056+#include "mir/shared_library.h"
2057 #include "src/client/mesa/mesa_native_display_container.h"
2058-#include "mir_test_doubles/mock_client_context.h"
2059+#include "mir_test_framework/client_platform_factory.h"
2060 #include "mir_test_doubles/mock_client_surface.h"
2061
2062 #include "mir_toolkit/mesa/native_display.h"
2063@@ -30,19 +30,20 @@
2064 namespace mclm = mir::client::mesa;
2065 namespace mt = mir::test;
2066 namespace mtd = mir::test::doubles;
2067+namespace mtf = mir_test_framework;
2068
2069 TEST(MesaClientPlatformTest, egl_native_display_is_valid_until_released)
2070 {
2071- mtd::MockClientContext context;
2072- mclm::ClientPlatformFactory factory;
2073- auto platform = factory.create_client_platform(&context);
2074+ auto platform = mtf::create_mesa_client_platform();
2075+ auto platform_lib = mtf::get_platform_library();
2076
2077 MirMesaEGLNativeDisplay* nd;
2078 {
2079 std::shared_ptr<EGLNativeDisplayType> native_display = platform->create_egl_native_display();
2080
2081 nd = reinterpret_cast<MirMesaEGLNativeDisplay*>(*native_display);
2082- EXPECT_EQ(MIR_MESA_TRUE, mclm::mir_client_mesa_egl_native_display_is_valid(nd));
2083+ auto validate = platform_lib->load_function<MirBool(*)(MirMesaEGLNativeDisplay*)>("mir_client_mesa_egl_native_display_is_valid");
2084+ EXPECT_EQ(MIR_MESA_TRUE, validate(nd));
2085 }
2086 EXPECT_EQ(MIR_MESA_FALSE, mclm::mir_client_mesa_egl_native_display_is_valid(nd));
2087 }
2088
2089=== modified file 'tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp'
2090--- tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp 2014-03-06 06:05:17 +0000
2091+++ tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp 2014-12-12 01:38:38 +0000
2092@@ -40,7 +40,7 @@
2093 }
2094
2095 std::shared_ptr<mclg::MesaNativeDisplayContainer> const container;
2096- MirConnection* connection;
2097+ mir::client::ClientContext* connection;
2098 };
2099
2100 }
2101
2102=== modified file 'tests/unit-tests/client/test_client_platform.cpp'
2103--- tests/unit-tests/client/test_client_platform.cpp 2014-03-06 06:05:17 +0000
2104+++ tests/unit-tests/client/test_client_platform.cpp 2014-12-12 01:38:38 +0000
2105@@ -20,60 +20,153 @@
2106 #include "src/client/mir_client_surface.h"
2107 #include "mir_test_doubles/mock_client_context.h"
2108 #include "mir_test_doubles/mock_client_surface.h"
2109+#include "mir_test_framework/executable_path.h"
2110+#include "mir_test_framework/stub_platform_helpers.h"
2111
2112-#ifdef ANDROID
2113+#ifdef MIR_BUILD_PLATFORM_ANDROID
2114 #include "mir_test_doubles/mock_android_hw.h"
2115-#include "src/client/android/client_platform_factory.h"
2116-#else
2117-#include "src/client/mesa/client_platform_factory.h"
2118 #endif
2119
2120+#include "src/client/client_platform_factory.h"
2121+
2122+#include "mir/shared_library.h"
2123+
2124 #include <gmock/gmock.h>
2125 #include <gtest/gtest.h>
2126
2127 namespace mcl=mir::client;
2128 namespace mtd = mir::test::doubles;
2129-
2130-struct ClientPlatformTest : public ::testing::Test
2131-{
2132+namespace mtf = mir_test_framework;
2133+
2134+namespace
2135+{
2136+struct ClientPlatformTraits
2137+{
2138+ ClientPlatformTraits(std::string const& library,
2139+ std::function<void(MirPlatformPackage&)> populator,
2140+ MirPlatformType type)
2141+ : platform_library_name{library},
2142+ populate_package_for{populator},
2143+ platform_type{type}
2144+ {
2145+ }
2146+
2147+ std::string const platform_library_name;
2148+ std::function<void(MirPlatformPackage&)> const populate_package_for;
2149+ MirPlatformType const platform_type;
2150+};
2151+
2152+struct ClientPlatformTest : public ::testing::TestWithParam<ClientPlatformTraits const*>
2153+{
2154+ ClientPlatformTest()
2155+ : platform_library{mtf::library_path() + "/" + GetParam()->platform_library_name},
2156+ create_client_platform{platform_library.load_function<mcl::CreateClientPlatform>("create_client_platform")},
2157+ probe{platform_library.load_function<mcl::ClientPlatformProbe>("is_appropriate_module")}
2158+ {
2159+ using namespace testing;
2160+ ON_CALL(context, populate(_))
2161+ .WillByDefault(Invoke(GetParam()->populate_package_for));
2162+ }
2163+
2164 mtd::MockClientContext context;
2165-#ifdef ANDROID
2166+#ifdef MIR_BUILD_PLATFORM_ANDROID
2167 testing::NiceMock<mtd::HardwareAccessMock> hw_access_mock;
2168- mcl::android::ClientPlatformFactory factory;
2169-#else
2170- mcl::mesa::ClientPlatformFactory factory;
2171 #endif
2172+ mir::SharedLibrary platform_library;
2173+ mcl::CreateClientPlatform const create_client_platform;
2174+ mcl::ClientPlatformProbe const probe;
2175 };
2176
2177-TEST_F(ClientPlatformTest, platform_name)
2178-{
2179- auto platform = factory.create_client_platform(&context);
2180-#ifdef ANDROID
2181- auto type = mir_platform_type_android;
2182-#else
2183- auto type = mir_platform_type_gbm;
2184-#endif
2185- EXPECT_EQ(type, platform->platform_type());
2186-}
2187-
2188-TEST_F(ClientPlatformTest, platform_creates)
2189-{
2190- auto platform = factory.create_client_platform(&context);
2191+#ifdef MIR_BUILD_PLATFORM_ANDROID
2192+ClientPlatformTraits const android_platform{"/client-modules/android.so",
2193+ [](MirPlatformPackage& pkg)
2194+ {
2195+ ::memset(&pkg, 0, sizeof(pkg));
2196+ },
2197+ mir_platform_type_android
2198+ };
2199+
2200+INSTANTIATE_TEST_CASE_P(Android,
2201+ ClientPlatformTest,
2202+ ::testing::Values(&android_platform));
2203+
2204+#endif
2205+
2206+#ifdef MIR_BUILD_PLATFORM_MESA
2207+ClientPlatformTraits const mesa_platform{"/client-modules/mesa.so",
2208+ [](MirPlatformPackage& pkg)
2209+ {
2210+ ::memset(&pkg, 0, sizeof(pkg));
2211+ pkg.fd_items = 1;
2212+ },
2213+ mir_platform_type_gbm
2214+ };
2215+
2216+INSTANTIATE_TEST_CASE_P(Mesa,
2217+ ClientPlatformTest,
2218+ ::testing::Values(&mesa_platform));
2219+
2220+#endif
2221+
2222+ClientPlatformTraits const dummy_platform{"/client-modules/dummy.so",
2223+ [](MirPlatformPackage& pkg)
2224+ {
2225+ mtf::create_stub_platform_package(pkg);
2226+ },
2227+ mir_platform_type_gbm
2228+ };
2229+
2230+INSTANTIATE_TEST_CASE_P(Dummy,
2231+ ClientPlatformTest,
2232+ ::testing::Values(&dummy_platform));
2233+}
2234+
2235+TEST_P(ClientPlatformTest, platform_name)
2236+{
2237+ auto platform = create_client_platform(&context);
2238+
2239+ EXPECT_EQ(GetParam()->platform_type, platform->platform_type());
2240+}
2241+
2242+TEST_P(ClientPlatformTest, platform_creates)
2243+{
2244+ auto platform = create_client_platform(&context);
2245 auto buffer_factory = platform->create_buffer_factory();
2246 EXPECT_NE(buffer_factory.get(), (mcl::ClientBufferFactory*) NULL);
2247 }
2248
2249-TEST_F(ClientPlatformTest, platform_creates_native_window)
2250+TEST_P(ClientPlatformTest, platform_creates_native_window)
2251 {
2252- auto platform = factory.create_client_platform(&context);
2253+ auto platform = create_client_platform(&context);
2254 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
2255 auto native_window = platform->create_egl_native_window(mock_client_surface.get());
2256 EXPECT_NE(*native_window, (EGLNativeWindowType) NULL);
2257 }
2258
2259-TEST_F(ClientPlatformTest, platform_creates_egl_native_display)
2260+TEST_P(ClientPlatformTest, platform_creates_egl_native_display)
2261 {
2262- auto platform = factory.create_client_platform(&context);
2263+ auto platform = create_client_platform(&context);
2264 auto native_display = platform->create_egl_native_display();
2265 EXPECT_NE(nullptr, native_display.get());
2266 }
2267+
2268+TEST_P(ClientPlatformTest, platform_probe_returns_success_when_matching)
2269+{
2270+ EXPECT_TRUE(probe(&context));
2271+}
2272+
2273+TEST_P(ClientPlatformTest, platform_probe_returns_false_when_not_matching)
2274+{
2275+ using namespace testing;
2276+ ON_CALL(context, populate(_))
2277+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2278+ {
2279+ //Mock up something that hopefully looks nothing like
2280+ //what the platform is expecting...
2281+ ::memset(&pkg, 0, sizeof(pkg));
2282+ pkg.data_items = mir_platform_package_max + 1;
2283+ pkg.fd_items = -23;
2284+ }));
2285+
2286+ EXPECT_FALSE(probe(&context));
2287+}
2288
2289=== added file 'tests/unit-tests/client/test_probing_client_platform_factory.cpp'
2290--- tests/unit-tests/client/test_probing_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
2291+++ tests/unit-tests/client/test_probing_client_platform_factory.cpp 2014-12-12 01:38:38 +0000
2292@@ -0,0 +1,142 @@
2293+/*
2294+ * Copyright © 2014 Canonical Ltd.
2295+ *
2296+ * This program is free software: you can redistribute it and/or modify
2297+ * it under the terms of the GNU General Public License version 3 as
2298+ * published by the Free Software Foundation.
2299+ *
2300+ * This program is distributed in the hope that it will be useful,
2301+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2302+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2303+ * GNU General Public License for more details.
2304+ *
2305+ * You should have received a copy of the GNU General Public License
2306+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2307+ *
2308+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
2309+ */
2310+
2311+#include "src/client/client_platform.h"
2312+#include "src/client/probing_client_platform_factory.h"
2313+
2314+#include "mir_test_doubles/mock_client_context.h"
2315+#include "mir_test_framework/executable_path.h"
2316+#include "mir_test_framework/stub_platform_helpers.h"
2317+
2318+#include <gmock/gmock.h>
2319+#include <gtest/gtest.h>
2320+
2321+namespace mtf = mir_test_framework;
2322+namespace mtd = mir::test::doubles;
2323+
2324+namespace
2325+{
2326+std::vector<std::shared_ptr<mir::SharedLibrary>>
2327+all_available_modules()
2328+{
2329+ std::vector<std::shared_ptr<mir::SharedLibrary>> modules;
2330+#ifdef MIR_BUILD_PLATFORM_MESA
2331+ modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::library_path() + "/client-modules/mesa.so"));
2332+#endif
2333+#ifdef MIR_BUILD_PLATFORM_ANDROID
2334+ modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::library_path() + "/client-modules/android.so"));
2335+#endif
2336+ return modules;
2337+}
2338+}
2339+
2340+TEST(ProbingClientPlatformFactory, ThrowsErrorWhenConstructedWithNoPlatforms)
2341+{
2342+ std::vector<std::shared_ptr<mir::SharedLibrary>> empty_modules;
2343+ EXPECT_THROW(mir::client::ProbingClientPlatformFactory{empty_modules},
2344+ std::runtime_error);
2345+}
2346+
2347+TEST(ProbingClientPlatformFactory, ThrowsErrorWhenNoPlatformPluginProbesSuccessfully)
2348+{
2349+ using namespace testing;
2350+
2351+ mir::client::ProbingClientPlatformFactory factory{all_available_modules()};
2352+
2353+ mtd::MockClientContext context;
2354+ ON_CALL(context, populate(_))
2355+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2356+ {
2357+ ::memset(&pkg, 0, sizeof(MirPlatformPackage));
2358+ // Mock up a platform package that looks nothing like
2359+ // either an Android or Mesa package
2360+ pkg.fd_items = 0xdeadbeef;
2361+ pkg.data_items = -23;
2362+ }));
2363+
2364+ EXPECT_THROW(factory.create_client_platform(&context),
2365+ std::runtime_error);
2366+}
2367+
2368+#ifdef MIR_BUILD_PLATFORM_MESA
2369+TEST(ProbingClientPlatformFactory, CreatesMesaPlatformWhenAppropriate)
2370+#else
2371+TEST(ProbingClientPlatformFactory, DISABLED_CreatesMesaPlatformWhenAppropriate)
2372+#endif
2373+{
2374+ using namespace testing;
2375+
2376+ mir::client::ProbingClientPlatformFactory factory{all_available_modules()};
2377+
2378+ mtd::MockClientContext context;
2379+ ON_CALL(context, populate(_))
2380+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2381+ {
2382+ ::memset(&pkg, 0, sizeof(MirPlatformPackage));
2383+ // Mock up something that looks like a GBM platform package,
2384+ // until we send the actual platform type over the wire!
2385+ pkg.fd_items = 1;
2386+ pkg.fd[0] = 23;
2387+ }));
2388+ auto platform = factory.create_client_platform(&context);
2389+ EXPECT_EQ(mir_platform_type_gbm, platform->platform_type());
2390+}
2391+
2392+#ifdef MIR_BUILD_PLATFORM_ANDROID
2393+TEST(ProbingClientPlatformFactory, CreatesAndroidPlatformWhenAppropriate)
2394+#else
2395+TEST(ProbingClientPlatformFactory, DISABLED_CreatesAndroidPlatformWhenAppropriate)
2396+#endif
2397+{
2398+ using namespace testing;
2399+
2400+ mir::client::ProbingClientPlatformFactory factory{all_available_modules()};
2401+
2402+ mtd::MockClientContext context;
2403+ ON_CALL(context, populate(_))
2404+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2405+ {
2406+ // Mock up something that looks like a Android platform package,
2407+ // until we send the actual platform type over the wire!
2408+ ::memset(&pkg, 0, sizeof(MirPlatformPackage));
2409+ }));
2410+
2411+ auto platform = factory.create_client_platform(&context);
2412+ EXPECT_EQ(mir_platform_type_android, platform->platform_type());
2413+}
2414+
2415+TEST(ProbingClientPlatformFactory, IgnoresNonClientPlatformModules)
2416+{
2417+ using namespace testing;
2418+
2419+ auto modules = all_available_modules();
2420+ // NOTE: For minimum fuss, load something that has minimal side-effects...
2421+ modules.push_back(std::make_shared<mir::SharedLibrary>("libc.so.6"));
2422+ modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::library_path() + "/client-modules/dummy.so"));
2423+
2424+ mir::client::ProbingClientPlatformFactory factory{modules};
2425+
2426+ mtd::MockClientContext context;
2427+ ON_CALL(context, populate(_))
2428+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2429+ {
2430+ mtf::create_stub_platform_package(pkg);
2431+ }));
2432+
2433+ auto platform = factory.create_client_platform(&context);
2434+}
2435
2436=== modified file 'tests/unit-tests/shared_library_test.cpp'
2437--- tests/unit-tests/shared_library_test.cpp 2014-12-08 04:03:47 +0000
2438+++ tests/unit-tests/shared_library_test.cpp 2014-12-12 01:38:38 +0000
2439@@ -59,10 +59,10 @@
2440 public:
2441 SharedLibrary()
2442 : nonexistent_library{"imma_totally_not_a_library"},
2443- existing_library{mtf::library_path() + "/" MIR_CLIENT_DRIVER_BINARY},
2444+ existing_library{mtf::library_path() + "/client-modules/mesa.so"},
2445 nonexistent_function{"yo_dawg"},
2446- existing_function{"create_client_platform_factory"},
2447- existent_version{"MIR_CLIENTPLATFORM_1"},
2448+ existing_function{"create_client_platform"},
2449+ existent_version{"MIR_CLIENT_PLATFORM_2"},
2450 nonexistent_version{"GOATS_ON_THE_GREEN"}
2451 {
2452 }

Subscribers

People subscribed via source and target branches