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
Prerequisite: lp:~raof/mir/fix-all-the-CI
Diff against target: 2424 lines (+962/-314)
66 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/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 (+4/-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
Andreas Pokorny (community) Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Cemil Azizoglu Pending
Alan Griffiths Pending
Robert Carr Pending
Daniel van Vugt Pending
Alexandros Frantzis Pending
Review via email: mp+244527@code.launchpad.net

This proposal supersedes a proposal from 2014-11-28.

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

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 : Posted in a previous version of this proposal

(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 : Posted in a previous version of this proposal

(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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> 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 : Posted in a previous version of this proposal

> (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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

> 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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

@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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

$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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

> 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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

> @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 : Posted in a previous version of this proposal

@Cemil - downstreams built and happy.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

(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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

> (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 : Posted in a previous version of this proposal

looks good to me.

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) : Posted in a previous version of this proposal
review: Abstain
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

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

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

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

Still need another merge with lp:mir it seems:
Text conflict in benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp
Text conflict in tests/acceptance-tests/CMakeLists.txt

review: Needs Fixing

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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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:39:36 +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=== added file 'src/client/probing_client_platform_factory.cpp'
1224--- src/client/probing_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
1225+++ src/client/probing_client_platform_factory.cpp 2014-12-12 01:39:36 +0000
1226@@ -0,0 +1,38 @@
1227+#include "probing_client_platform_factory.h"
1228+
1229+#include <boost/exception/all.hpp>
1230+#include <stdexcept>
1231+
1232+namespace mcl = mir::client;
1233+
1234+mcl::ProbingClientPlatformFactory::ProbingClientPlatformFactory(std::vector<std::shared_ptr<mir::SharedLibrary>> const& modules)
1235+ : platform_modules{modules}
1236+{
1237+ if (modules.empty())
1238+ {
1239+ BOOST_THROW_EXCEPTION(
1240+ std::runtime_error{"Attempted to create a ClientPlatformFactory with no platform modules"});
1241+ }
1242+}
1243+
1244+std::shared_ptr<mcl::ClientPlatform>
1245+mcl::ProbingClientPlatformFactory::create_client_platform(mcl::ClientContext* context)
1246+{
1247+ for (auto& module : platform_modules)
1248+ {
1249+ try
1250+ {
1251+ auto probe = module->load_function<mir::client::ClientPlatformProbe>("is_appropriate_module", CLIENT_PLATFORM_VERSION);
1252+ if (probe(context))
1253+ {
1254+ auto factory = module->load_function<mir::client::CreateClientPlatform>("create_client_platform", CLIENT_PLATFORM_VERSION);
1255+ return factory(context);
1256+ }
1257+ }
1258+ catch(std::runtime_error)
1259+ {
1260+ // We were handled a SharedLibrary that's not a client platform module?
1261+ }
1262+ }
1263+ BOOST_THROW_EXCEPTION(std::runtime_error{"No appropriate client platform module found"});
1264+}
1265
1266=== added file 'src/client/probing_client_platform_factory.h'
1267--- src/client/probing_client_platform_factory.h 1970-01-01 00:00:00 +0000
1268+++ src/client/probing_client_platform_factory.h 2014-12-12 01:39:36 +0000
1269@@ -0,0 +1,27 @@
1270+#ifndef MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
1271+#define MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
1272+
1273+#include <vector>
1274+
1275+#include "client_platform_factory.h"
1276+#include "mir/shared_library.h"
1277+
1278+namespace mir
1279+{
1280+namespace client
1281+{
1282+class ProbingClientPlatformFactory : public ClientPlatformFactory
1283+{
1284+public:
1285+ ProbingClientPlatformFactory(std::vector<std::shared_ptr<SharedLibrary>> const& modules);
1286+
1287+ std::shared_ptr<ClientPlatform> create_client_platform(ClientContext *context) override;
1288+private:
1289+ std::vector<std::shared_ptr<SharedLibrary>> platform_modules;
1290+};
1291+
1292+
1293+}
1294+}
1295+
1296+#endif // MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
1297
1298=== modified file 'src/common/symbols.map'
1299--- src/common/symbols.map 2014-12-11 02:43:01 +0000
1300+++ src/common/symbols.map 2014-12-12 01:39:36 +0000
1301@@ -203,11 +203,10 @@
1302 };
1303
1304 MIR_COMMON_3.1 {
1305- global:
1306- extern "C++" {
1307- mir::log*;
1308- mir::logv*;
1309- };
1310- local: *;
1311-};
1312-
1313+ global:
1314+ extern "C++" {
1315+ mir::log*;
1316+ mir::logv*;
1317+ mir::libraries_for_path*;
1318+ };
1319+} MIR_COMMON_3;
1320
1321=== modified file 'tests/CMakeLists.txt'
1322--- tests/CMakeLists.txt 2014-12-08 04:03:47 +0000
1323+++ tests/CMakeLists.txt 2014-12-12 01:39:36 +0000
1324@@ -26,9 +26,17 @@
1325 endif()
1326
1327 if (MIR_TEST_PLATFORM STREQUAL "android")
1328+ add_definitions(-DANDROID)
1329+endif()
1330+
1331+if (MIR_BUILD_PLATFORM_ANDROID)
1332 #avoid complaints about poor quality android headers
1333 include_directories(SYSTEM ${LIBHARDWARE_INCLUDE_DIRS})
1334- add_definitions(-DANDROID)
1335+ add_definitions(-DMIR_BUILD_PLATFORM_ANDROID)
1336+endif()
1337+
1338+if (MIR_BUILD_PLATFORM_MESA)
1339+ add_definitions(-DMIR_BUILD_PLATFORM_MESA)
1340 endif()
1341
1342 include_directories(
1343
1344=== modified file 'tests/acceptance-tests/CMakeLists.txt'
1345--- tests/acceptance-tests/CMakeLists.txt 2014-12-11 02:43:01 +0000
1346+++ tests/acceptance-tests/CMakeLists.txt 2014-12-12 01:39:36 +0000
1347@@ -6,7 +6,6 @@
1348
1349 add_definitions(
1350 -DMIR_PLATFORM_DRIVER_BINARY="${MIR_PLATFORM_DRIVER_BINARY}"
1351- -DMIR_CLIENT_DRIVER_BINARY="${MIR_CLIENT_DRIVER_BINARY}"
1352 )
1353
1354 set(
1355@@ -52,7 +51,7 @@
1356 list(APPEND SOURCES test_symbols_required_by_mesa.cpp)
1357 endif()
1358
1359-add_executable(
1360+mir_add_wrapped_executable(
1361 mir_acceptance_tests
1362
1363 ${SOURCES}
1364@@ -74,9 +73,9 @@
1365 mirplatform
1366
1367 mir-test
1368- mir-test-framework
1369 mir-test-doubles
1370 mir-test-doubles-platform
1371+ mir-test-framework
1372 3rd_party
1373
1374 ${PROTOBUF_LIBRARIES}
1375@@ -97,8 +96,3 @@
1376 if (MIR_RUN_ACCEPTANCE_TESTS)
1377 mir_discover_tests(mir_acceptance_tests)
1378 endif (MIR_RUN_ACCEPTANCE_TESTS)
1379-
1380-install(
1381- TARGETS mir_acceptance_tests
1382- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1383-)
1384
1385=== modified file 'tests/acceptance-tests/test_client_library.cpp'
1386--- tests/acceptance-tests/test_client_library.cpp 2014-12-12 01:39:36 +0000
1387+++ tests/acceptance-tests/test_client_library.cpp 2014-12-12 01:39:36 +0000
1388@@ -20,6 +20,7 @@
1389
1390 #include "mir_test_framework/headless_in_process_server.h"
1391 #include "mir_test_framework/using_stub_client_platform.h"
1392+#include "mir_test_framework/stub_platform_helpers.h"
1393 #include "mir_test/validity_matchers.h"
1394
1395 #include "src/client/client_buffer.h"
1396@@ -546,15 +547,14 @@
1397
1398 TEST_F(ClientLibrary, accesses_platform_package)
1399 {
1400+ using namespace testing;
1401 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
1402
1403 MirPlatformPackage platform_package;
1404- platform_package.data_items = -1;
1405- platform_package.fd_items = -1;
1406+ ::memset(&platform_package, -1, sizeof(platform_package));
1407
1408 mir_connection_get_platform(connection, &platform_package);
1409- EXPECT_GE(0, platform_package.data_items);
1410- EXPECT_GE(0, platform_package.fd_items);
1411+ EXPECT_THAT(platform_package, mtf::IsStubPlatformPackage());
1412
1413 mir_connection_release(connection);
1414 }
1415
1416=== modified file 'tests/acceptance-tests/test_client_library_drm.cpp'
1417--- tests/acceptance-tests/test_client_library_drm.cpp 2014-12-08 04:03:47 +0000
1418+++ tests/acceptance-tests/test_client_library_drm.cpp 2014-12-12 01:39:36 +0000
1419@@ -32,10 +32,15 @@
1420 {
1421 struct gbm_device* dev = reinterpret_cast<struct gbm_device*>(connection);
1422
1423+ MirPlatformPackage pkg;
1424+
1425+ mir_connection_get_platform(connection, &pkg);
1426+ int const previous_data_count{pkg.data_items};
1427+
1428 mir_connection_drm_set_gbm_device(connection, dev);
1429+ mir_connection_get_platform(connection, &pkg);
1430
1431- MirPlatformPackage pkg;
1432- mir_connection_get_platform(connection, &pkg);
1433- EXPECT_THAT(pkg.data_items, Eq(sizeof(dev) / sizeof(int)));
1434- EXPECT_THAT(*reinterpret_cast<struct gbm_device**>(&pkg.data[0]), Eq(dev));
1435+ EXPECT_THAT(pkg.data_items, Eq(previous_data_count + (sizeof(dev) / sizeof(int))));
1436+ EXPECT_THAT(reinterpret_cast<struct gbm_device*>(pkg.data[previous_data_count]),
1437+ Eq(dev));
1438 }
1439
1440=== modified file 'tests/acceptance-tests/test_symbols_required_by_mesa.cpp'
1441--- tests/acceptance-tests/test_symbols_required_by_mesa.cpp 2014-12-08 04:03:47 +0000
1442+++ tests/acceptance-tests/test_symbols_required_by_mesa.cpp 2014-12-12 01:39:36 +0000
1443@@ -21,11 +21,14 @@
1444
1445 #include <dlfcn.h>
1446
1447+#include "mir_test_framework/executable_path.h"
1448+
1449 using namespace testing;
1450+namespace mtf = mir_test_framework;
1451
1452-TEST(SymbolsRequiredByMesa, are_exported_by_libmirclientplatform)
1453+TEST(SymbolsRequiredByMesa, are_exported_by_client_platform_mesa)
1454 {
1455- auto const handle = dlopen(MIR_CLIENT_DRIVER_BINARY, RTLD_LAZY);
1456+ auto const handle = dlopen((mtf::library_path() + "/client-modules/mesa.so").c_str(), RTLD_LAZY);
1457 ASSERT_THAT(handle, NotNull());
1458
1459 auto const sym = dlsym(handle, "mir_client_mesa_egl_native_display_is_valid");
1460
1461=== modified file 'tests/include/mir_test_doubles/mock_client_context.h'
1462--- tests/include/mir_test_doubles/mock_client_context.h 2013-04-24 05:22:20 +0000
1463+++ tests/include/mir_test_doubles/mock_client_context.h 2014-12-12 01:39:36 +0000
1464@@ -33,18 +33,12 @@
1465 struct MockClientContext : public client::ClientContext
1466 {
1467 MockClientContext()
1468- : connection{reinterpret_cast<MirConnection*>(0xabcdef)}
1469 {
1470 using namespace testing;
1471
1472- ON_CALL(*this, mir_connection()).WillByDefault(Return(connection));
1473- EXPECT_CALL(*this, mir_connection()).Times(AtLeast(0));
1474 EXPECT_CALL(*this, populate(_)).Times(AtLeast(0));
1475 }
1476
1477- MirConnection* connection;
1478-
1479- MOCK_METHOD0(mir_connection, MirConnection*());
1480 MOCK_METHOD1(populate, void(MirPlatformPackage&));
1481 };
1482
1483
1484=== modified file 'tests/include/mir_test_doubles/stub_client_buffer.h'
1485--- tests/include/mir_test_doubles/stub_client_buffer.h 2014-11-24 16:04:38 +0000
1486+++ tests/include/mir_test_doubles/stub_client_buffer.h 2014-12-12 01:39:36 +0000
1487@@ -65,7 +65,11 @@
1488
1489 std::shared_ptr<graphics::NativeBuffer> native_buffer_handle() const override
1490 {
1491+#ifndef ANDROID
1492+ return package;
1493+#else
1494 return std::shared_ptr<graphics::NativeBuffer>();
1495+#endif
1496 }
1497 void update_from(MirBufferPackage const&) override {}
1498 void fill_update_msg(MirBufferPackage&) override{}
1499
1500=== added file 'tests/include/mir_test_framework/client_platform_factory.h'
1501--- tests/include/mir_test_framework/client_platform_factory.h 1970-01-01 00:00:00 +0000
1502+++ tests/include/mir_test_framework/client_platform_factory.h 2014-12-12 01:39:36 +0000
1503@@ -0,0 +1,72 @@
1504+/*
1505+ * Copyright © 2014 Canonical Ltd.
1506+ *
1507+ * This program is free software: you can redistribute it and/or modify
1508+ * it under the terms of the GNU General Public License version 3 as
1509+ * published by the Free Software Foundation.
1510+ *
1511+ * This program is distributed in the hope that it will be useful,
1512+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1513+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1514+ * GNU General Public License for more details.
1515+ *
1516+ * You should have received a copy of the GNU General Public License
1517+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1518+ *
1519+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1520+ */
1521+
1522+#ifndef MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
1523+#define MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
1524+
1525+
1526+#include "mir/shared_library.h"
1527+#include "src/client/client_platform_factory.h"
1528+#include "executable_path.h"
1529+#include "mir_test_doubles/mock_client_context.h"
1530+
1531+namespace mtd = mir::test::doubles;
1532+
1533+namespace mir_test_framework
1534+{
1535+std::shared_ptr<mir::SharedLibrary> platform_library;
1536+
1537+std::shared_ptr<mir::client::ClientPlatform> create_android_client_platform()
1538+{
1539+ using namespace testing;
1540+ mtd::MockClientContext ctx;
1541+ ON_CALL(ctx, populate(_))
1542+ .WillByDefault(Invoke([](MirPlatformPackage& package) { ::memset(&package, 0, sizeof(package)); }));
1543+ platform_library = std::make_shared<mir::SharedLibrary>(library_path() + "/client-modules/android.so");
1544+ auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
1545+ return platform_factory(&ctx);
1546+}
1547+
1548+std::shared_ptr<mir::client::ClientPlatform> create_mesa_client_platform()
1549+{
1550+ using namespace testing;
1551+ mtd::MockClientContext ctx;
1552+ ON_CALL(ctx, populate(_))
1553+ .WillByDefault(Invoke([](MirPlatformPackage& package)
1554+ {
1555+ ::memset(&package, 0, sizeof(package));
1556+ package.fd_items = 1;
1557+ }));
1558+ platform_library = std::make_shared<mir::SharedLibrary>(library_path() + "/client-modules/mesa.so");
1559+ auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
1560+ return platform_factory(&ctx);
1561+}
1562+
1563+std::shared_ptr<mir::SharedLibrary>
1564+get_platform_library()
1565+{
1566+ if (!platform_library)
1567+ {
1568+ throw std::logic_error{"Must call one of create_*_client_platform() before calling get_platform_library()"};
1569+ }
1570+ return platform_library;
1571+}
1572+
1573+}
1574+
1575+#endif // MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
1576
1577=== added file 'tests/include/mir_test_framework/stub_client_platform_factory.h'
1578--- tests/include/mir_test_framework/stub_client_platform_factory.h 1970-01-01 00:00:00 +0000
1579+++ tests/include/mir_test_framework/stub_client_platform_factory.h 2014-12-12 01:39:36 +0000
1580@@ -0,0 +1,33 @@
1581+/*
1582+ * Copyright © 2014 Canonical Ltd.
1583+ *
1584+ * This program is free software: you can redistribute it and/or modify it
1585+ * under the terms of the GNU General Public License version 3,
1586+ * as published by the Free Software Foundation.
1587+ *
1588+ * This program is distributed in the hope that it will be useful,
1589+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1590+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1591+ * GNU General Public License for more details.
1592+ *
1593+ * You should have received a copy of the GNU General Public License
1594+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1595+ *
1596+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1597+ */
1598+
1599+#ifndef MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_FACTORY_
1600+#define MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_FACTORY_
1601+
1602+#include "src/client/client_platform_factory.h"
1603+
1604+namespace mir_test_framework
1605+{
1606+
1607+struct StubClientPlatformFactory : public mir::client::ClientPlatformFactory
1608+{
1609+ std::shared_ptr<mir::client::ClientPlatform> create_client_platform(mir::client::ClientContext* context) override;
1610+};
1611+
1612+}
1613+#endif /* MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_ */
1614
1615=== added file 'tests/include/mir_test_framework/stub_platform_helpers.h'
1616--- tests/include/mir_test_framework/stub_platform_helpers.h 1970-01-01 00:00:00 +0000
1617+++ tests/include/mir_test_framework/stub_platform_helpers.h 2014-12-12 01:39:36 +0000
1618@@ -0,0 +1,53 @@
1619+/*
1620+ * Copyright © 2014 Canonical Ltd.
1621+ *
1622+ * This program is free software: you can redistribute it and/or modify
1623+ * it under the terms of the GNU General Public License version 3 as
1624+ * published by the Free Software Foundation.
1625+ *
1626+ * This program is distributed in the hope that it will be useful,
1627+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1628+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1629+ * GNU General Public License for more details.
1630+ *
1631+ * You should have received a copy of the GNU General Public License
1632+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1633+ *
1634+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1635+ */
1636+
1637+#ifndef MIR_TEST_FRAMEWORK_STUB_PLATFORM_HELPERS_H_
1638+#define MIR_TEST_FRAMEWORK_STUB_PLATFORM_HELPERS_H_
1639+
1640+#include "mir/graphics/platform_ipc_package.h"
1641+#include "mir_toolkit/client_types.h"
1642+
1643+#include <gmock/gmock.h>
1644+
1645+namespace mir_test_framework
1646+{
1647+constexpr int stub_data_size{21};
1648+constexpr int stub_data_guard{0x0eadbeef};
1649+
1650+static inline void pack_stub_ipc_package(mir::graphics::PlatformIPCPackage& package)
1651+{
1652+ package.ipc_data = std::vector<int32_t>(stub_data_size, -1);
1653+ package.ipc_data[0] = stub_data_guard;
1654+}
1655+
1656+static inline void create_stub_platform_package(MirPlatformPackage& package)
1657+{
1658+ ::memset(&package, 0, sizeof(package));
1659+ package.data_items = stub_data_size;
1660+ package.data[0] = stub_data_guard;
1661+}
1662+
1663+MATCHER(IsStubPlatformPackage, "")
1664+{
1665+ return (arg.data_items == stub_data_size) &&
1666+ (arg.data[0] == stub_data_guard) &&
1667+ (arg.fd_items == 0);
1668+}
1669+}
1670+
1671+#endif // MIR_TEST_FRAMEWORK_STUB_PLATFORM_HELPERS_H_
1672
1673=== modified file 'tests/integration-tests/CMakeLists.txt'
1674--- tests/integration-tests/CMakeLists.txt 2014-12-08 04:03:47 +0000
1675+++ tests/integration-tests/CMakeLists.txt 2014-12-12 01:39:36 +0000
1676@@ -66,7 +66,7 @@
1677 endif()
1678
1679 link_directories(${LIBRARY_OUTPUT_PATH})
1680-add_executable(
1681+mir_add_wrapped_executable(
1682 mir_integration_tests
1683 ${INTEGRATION_TESTS_SRCS}
1684 ${MIR_SERVER_OBJECTS}
1685@@ -126,8 +126,3 @@
1686 if (MIR_RUN_INTEGRATION_TESTS)
1687 mir_discover_tests(mir_integration_tests)
1688 endif (MIR_RUN_INTEGRATION_TESTS)
1689-
1690-install(
1691- TARGETS mir_integration_tests
1692- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1693-)
1694
1695=== modified file 'tests/mir_test_doubles/CMakeLists.txt'
1696--- tests/mir_test_doubles/CMakeLists.txt 2014-12-08 04:03:47 +0000
1697+++ tests/mir_test_doubles/CMakeLists.txt 2014-12-12 01:39:36 +0000
1698@@ -30,13 +30,14 @@
1699 ${CMAKE_CURRENT_SOURCE_DIR}/mock_gl.cpp
1700 )
1701
1702-if (MIR_TEST_PLATFORM STREQUAL "mesa")
1703+if (MIR_BUILD_PLATFORM_MESA)
1704 include_directories(${DRM_INCLUDE_DIRS} ${GBM_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR})
1705 list(APPEND MIR_TEST_DOUBLES_PLATFORM_SRCS
1706 ${CMAKE_CURRENT_SOURCE_DIR}/mock_drm.cpp
1707 ${CMAKE_CURRENT_SOURCE_DIR}/mock_gbm.cpp
1708 )
1709-elseif (MIR_TEST_PLATFORM STREQUAL "android")
1710+endif()
1711+if (MIR_BUILD_PLATFORM_ANDROID)
1712 list(APPEND MIR_TEST_DOUBLES_PLATFORM_SRCS
1713 ${CMAKE_CURRENT_SOURCE_DIR}/mock_android_hw.cpp
1714 )
1715
1716=== modified file 'tests/mir_test_framework/CMakeLists.txt'
1717--- tests/mir_test_framework/CMakeLists.txt 2014-12-11 02:43:01 +0000
1718+++ tests/mir_test_framework/CMakeLists.txt 2014-12-12 01:39:36 +0000
1719@@ -4,10 +4,11 @@
1720 ${PROJECT_SOURCE_DIR}/src/include/common
1721 ${PROJECT_SOURCE_DIR}/src/include/server
1722 ${PROJECT_SOURCE_DIR}/src/include/client
1723- ${Boost_INCLUDE_DIRS}
1724- ${GLESv2_INCLUDE_DIRS}
1725- ${CMAKE_SOURCE_DIR}
1726- ${UMOCKDEV_INCLUDE_DIRS}
1727+ ${Boost_INCLUDE_DIRS}
1728+ ${GLESv2_INCLUDE_DIRS}
1729+ ${CMAKE_SOURCE_DIR}
1730+ ${UMOCKDEV_INCLUDE_DIRS}
1731+ ${ANDROID_HEADERS_INCLUDE_DIRS}
1732 )
1733
1734 set(
1735@@ -31,6 +32,7 @@
1736 display_server_test_fixture.cpp
1737 process.cpp
1738 using_stub_client_platform.cpp
1739+ stub_client_platform_factory.cpp
1740 udev_environment.cpp
1741 declarative_placement_strategy.cpp
1742 fake_event_hub_server_configuration.cpp
1743@@ -68,6 +70,29 @@
1744 ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
1745 )
1746
1747+set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols-client.map)
1748+
1749+add_library(
1750+ mirclientplatformstub MODULE
1751+
1752+ stub_client_platform_module.cpp
1753+)
1754+
1755+target_link_libraries(
1756+ mirclientplatformstub
1757+
1758+ mir-test-framework
1759+ ${UMOCKDEV_LDFLAGS} ${UMOCKDEV_LIBRARIES}
1760+)
1761+
1762+set_target_properties(
1763+ mirclientplatformstub PROPERTIES;
1764+ LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
1765+ OUTPUT_NAME dummy
1766+ PREFIX ""
1767+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
1768+)
1769+
1770 add_custom_command(TARGET mir-test-framework POST_BUILD
1771 COMMAND ${CMAKE_COMMAND} -E copy_directory
1772 ${CMAKE_CURRENT_SOURCE_DIR}/udev_recordings ${CMAKE_BINARY_DIR}/bin/udev_recordings
1773@@ -96,3 +121,4 @@
1774 )
1775
1776 install(TARGETS mirplatformstub LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
1777+install(TARGETS mirclientplatformstub LIBRARY DESTINATION ${MIR_CLIENT_PLATFORM_PATH})
1778
1779=== added file 'tests/mir_test_framework/stub_client_platform_factory.cpp'
1780--- tests/mir_test_framework/stub_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
1781+++ tests/mir_test_framework/stub_client_platform_factory.cpp 2014-12-12 01:39:36 +0000
1782@@ -0,0 +1,74 @@
1783+/*
1784+ * Copyright © 2014 Canonical Ltd.
1785+ *
1786+ * This program is free software: you can redistribute it and/or modify it
1787+ * under the terms of the GNU General Public License version 3,
1788+ * as published by the Free Software Foundation.
1789+ *
1790+ * This program is distributed in the hope that it will be useful,
1791+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1792+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1793+ * GNU General Public License for more details.
1794+ *
1795+ * You should have received a copy of the GNU General Public License
1796+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1797+ *
1798+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1799+ */
1800+
1801+#include "mir_test_framework/stub_client_platform_factory.h"
1802+#include "mir_test_doubles/stub_client_buffer_factory.h"
1803+#include "src/client/client_buffer_factory.h"
1804+#include "src/client/client_buffer.h"
1805+#include "src/client/client_platform.h"
1806+
1807+#include <string.h>
1808+
1809+namespace mcl = mir::client;
1810+namespace geom = mir::geometry;
1811+namespace mtf = mir_test_framework;
1812+namespace mtd = mir::test::doubles;
1813+
1814+namespace
1815+{
1816+struct StubClientPlatform : public mcl::ClientPlatform
1817+{
1818+ MirPlatformType platform_type() const
1819+ {
1820+ return mir_platform_type_gbm;
1821+ }
1822+
1823+ std::shared_ptr<mcl::ClientBufferFactory> create_buffer_factory()
1824+ {
1825+ return std::make_shared<mtd::StubClientBufferFactory>();
1826+ }
1827+
1828+ std::shared_ptr<EGLNativeWindowType> create_egl_native_window(mcl::ClientSurface*)
1829+ {
1830+ auto fake_window = reinterpret_cast<EGLNativeWindowType>(0x12345678lu);
1831+ return std::make_shared<EGLNativeWindowType>(fake_window);
1832+ }
1833+
1834+ std::shared_ptr<EGLNativeDisplayType> create_egl_native_display()
1835+ {
1836+ auto fake_display = reinterpret_cast<EGLNativeDisplayType>(0x12345678lu);
1837+ return std::make_shared<EGLNativeDisplayType>(fake_display);
1838+ }
1839+
1840+ MirNativeBuffer* convert_native_buffer(mir::graphics::NativeBuffer* buf) const
1841+ {
1842+ static_cast<void>(buf);
1843+#ifndef ANDROID
1844+ return buf;
1845+#else
1846+ return nullptr;
1847+#endif
1848+ }
1849+};
1850+}
1851+
1852+std::shared_ptr<mcl::ClientPlatform>
1853+mtf::StubClientPlatformFactory::create_client_platform(mcl::ClientContext*)
1854+{
1855+ return std::make_shared<StubClientPlatform>();
1856+}
1857
1858=== added file 'tests/mir_test_framework/stub_client_platform_module.cpp'
1859--- tests/mir_test_framework/stub_client_platform_module.cpp 1970-01-01 00:00:00 +0000
1860+++ tests/mir_test_framework/stub_client_platform_module.cpp 2014-12-12 01:39:36 +0000
1861@@ -0,0 +1,41 @@
1862+/*
1863+ * Copyright © 2014 Canonical Ltd.
1864+ *
1865+ * This program is free software: you can redistribute it and/or modify it
1866+ * under the terms of the GNU General Public License version 3,
1867+ * as published by the Free Software Foundation.
1868+ *
1869+ * This program is distributed in the hope that it will be useful,
1870+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1871+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1872+ * GNU General Public License for more details.
1873+ *
1874+ * You should have received a copy of the GNU General Public License
1875+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1876+ *
1877+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>>
1878+ */
1879+
1880+#include "src/client/client_platform_factory.h"
1881+#include "src/client/client_context.h"
1882+
1883+#include "mir_test_framework/stub_client_platform_factory.h"
1884+#include "mir_test_framework/stub_platform_helpers.h"
1885+#include <memory>
1886+#include <gmock/gmock.h>
1887+
1888+namespace mtf = mir_test_framework;
1889+namespace mcl = mir::client;
1890+
1891+extern "C" std::shared_ptr<mcl::ClientPlatform> create_client_platform(mcl::ClientContext* context)
1892+{
1893+ return mtf::StubClientPlatformFactory{}.create_client_platform(context);
1894+}
1895+
1896+extern "C" bool is_appropriate_module(mcl::ClientContext* context)
1897+{
1898+ using namespace testing;
1899+ MirPlatformPackage package;
1900+ context->populate(package);
1901+ return Matches(mtf::IsStubPlatformPackage())(package);
1902+}
1903
1904=== modified file 'tests/mir_test_framework/stubbed_graphics_platform.cpp'
1905--- tests/mir_test_framework/stubbed_graphics_platform.cpp 2014-12-11 02:43:01 +0000
1906+++ tests/mir_test_framework/stubbed_graphics_platform.cpp 2014-12-12 01:39:36 +0000
1907@@ -22,6 +22,8 @@
1908 #include "mir/graphics/buffer_writer.h"
1909 #include "mir/graphics/native_platform.h"
1910
1911+#include "mir_test_framework/stub_platform_helpers.h"
1912+
1913 #include "mir_test_doubles/stub_buffer_allocator.h"
1914 #include "mir_test_doubles/stub_display.h"
1915
1916@@ -146,7 +148,9 @@
1917
1918 std::shared_ptr<mg::PlatformIPCPackage> connection_ipc_package() override
1919 {
1920- return std::make_shared<mg::PlatformIPCPackage>();
1921+ auto package = std::make_shared<mg::PlatformIPCPackage>();
1922+ mtf::pack_stub_ipc_package(*package);
1923+ return package;
1924 }
1925
1926 mg::PlatformIPCPackage platform_operation(
1927
1928=== added file 'tests/mir_test_framework/symbols-client.map'
1929--- tests/mir_test_framework/symbols-client.map 1970-01-01 00:00:00 +0000
1930+++ tests/mir_test_framework/symbols-client.map 2014-12-12 01:39:36 +0000
1931@@ -0,0 +1,7 @@
1932+MIR_CLIENT_PLATFORM_2 {
1933+ global:
1934+ create_client_platform;
1935+ is_appropriate_module;
1936+ local:
1937+ *;
1938+};
1939
1940=== modified file 'tests/unit-tests/CMakeLists.txt'
1941--- tests/unit-tests/CMakeLists.txt 2014-12-08 04:03:47 +0000
1942+++ tests/unit-tests/CMakeLists.txt 2014-12-12 01:39:36 +0000
1943@@ -56,7 +56,7 @@
1944
1945 link_directories(${LIBRARY_OUTPUT_PATH})
1946
1947-add_executable(mir_unit_tests
1948+mir_add_wrapped_executable(mir_unit_tests
1949 ${UNIT_TEST_SOURCES}
1950 ${MIR_SERVER_OBJECTS}
1951 $<TARGET_OBJECTS:mirclientobjects>
1952@@ -117,11 +117,6 @@
1953 mir_discover_tests(mir_unit_tests LD_PRELOAD=libumockdev-preload.so.0 G_SLICE=always-malloc G_DEBUG=gc-friendly)
1954 endif (MIR_RUN_UNIT_TESTS)
1955
1956-install(
1957- TARGETS mir_unit_tests
1958- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1959-)
1960-
1961 add_custom_command(TARGET mir_unit_tests POST_BUILD
1962 COMMAND ${CMAKE_COMMAND} -E copy_directory
1963 ${CMAKE_CURRENT_SOURCE_DIR}/test_data ${CMAKE_BINARY_DIR}/bin/test_data
1964
1965=== modified file 'tests/unit-tests/client/CMakeLists.txt'
1966--- tests/unit-tests/client/CMakeLists.txt 2014-12-08 04:03:47 +0000
1967+++ tests/unit-tests/client/CMakeLists.txt 2014-12-12 01:39:36 +0000
1968@@ -10,6 +10,7 @@
1969 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_display_conf.cpp
1970 ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_screencast.cpp
1971 ${CMAKE_CURRENT_SOURCE_DIR}/test_protobuf_rpc_channel.cpp
1972+ ${CMAKE_CURRENT_SOURCE_DIR}/test_probing_client_platform_factory.cpp
1973 ${CMAKE_CURRENT_SOURCE_DIR}/test_mir_prompt_session.cpp
1974 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_distributor.cpp
1975 ${CMAKE_CURRENT_SOURCE_DIR}/test_periodic_perf_report.cpp
1976
1977=== modified file 'tests/unit-tests/client/android/test_android_client_platform.cpp'
1978--- tests/unit-tests/client/android/test_android_client_platform.cpp 2014-03-06 06:05:17 +0000
1979+++ tests/unit-tests/client/android/test_android_client_platform.cpp 2014-12-12 01:39:36 +0000
1980@@ -17,9 +17,9 @@
1981 */
1982
1983 #include "src/client/client_platform.h"
1984-#include "src/client/android/client_platform_factory.h"
1985 #include "mir_test_doubles/mock_client_context.h"
1986 #include "mir_test_doubles/mock_client_surface.h"
1987+#include "mir_test_framework/client_platform_factory.h"
1988
1989 #include <EGL/egl.h>
1990
1991@@ -28,13 +28,12 @@
1992 namespace mcl = mir::client;
1993 namespace mt = mir::test;
1994 namespace mtd = mt::doubles;
1995+namespace mtf = mir_test_framework;
1996
1997 TEST(AndroidClientPlatformTest, egl_native_display_is_egl_default_display)
1998 {
1999- mtd::MockClientContext context;
2000- mcl::android::ClientPlatformFactory factory;
2001 mtd::MockClientSurface surface;
2002- auto platform = factory.create_client_platform(&context);
2003+ auto platform = mtf::create_android_client_platform();
2004 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
2005 auto native_display = platform->create_egl_native_display();
2006 EXPECT_EQ(EGL_DEFAULT_DISPLAY, *native_display);
2007@@ -42,10 +41,8 @@
2008
2009 TEST(AndroidClientPlatformTest, egl_native_window_is_set)
2010 {
2011- mtd::MockClientContext context;
2012- mcl::android::ClientPlatformFactory factory;
2013 mtd::MockClientSurface surface;
2014- auto platform = factory.create_client_platform(&context);
2015+ auto platform = mtf::create_android_client_platform();
2016 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
2017 auto egl_native_window = platform->create_egl_native_window(&surface);
2018 EXPECT_NE(nullptr, egl_native_window);
2019
2020=== modified file 'tests/unit-tests/client/mesa/test_client_platform.cpp'
2021--- tests/unit-tests/client/mesa/test_client_platform.cpp 2014-03-06 06:05:17 +0000
2022+++ tests/unit-tests/client/mesa/test_client_platform.cpp 2014-12-12 01:39:36 +0000
2023@@ -17,9 +17,9 @@
2024 */
2025
2026 #include "src/client/client_platform.h"
2027-#include "src/client/mesa/client_platform_factory.h"
2028+#include "mir/shared_library.h"
2029 #include "src/client/mesa/mesa_native_display_container.h"
2030-#include "mir_test_doubles/mock_client_context.h"
2031+#include "mir_test_framework/client_platform_factory.h"
2032 #include "mir_test_doubles/mock_client_surface.h"
2033
2034 #include "mir_toolkit/mesa/native_display.h"
2035@@ -30,19 +30,20 @@
2036 namespace mclm = mir::client::mesa;
2037 namespace mt = mir::test;
2038 namespace mtd = mir::test::doubles;
2039+namespace mtf = mir_test_framework;
2040
2041 TEST(MesaClientPlatformTest, egl_native_display_is_valid_until_released)
2042 {
2043- mtd::MockClientContext context;
2044- mclm::ClientPlatformFactory factory;
2045- auto platform = factory.create_client_platform(&context);
2046+ auto platform = mtf::create_mesa_client_platform();
2047+ auto platform_lib = mtf::get_platform_library();
2048
2049 MirMesaEGLNativeDisplay* nd;
2050 {
2051 std::shared_ptr<EGLNativeDisplayType> native_display = platform->create_egl_native_display();
2052
2053 nd = reinterpret_cast<MirMesaEGLNativeDisplay*>(*native_display);
2054- EXPECT_EQ(MIR_MESA_TRUE, mclm::mir_client_mesa_egl_native_display_is_valid(nd));
2055+ auto validate = platform_lib->load_function<MirBool(*)(MirMesaEGLNativeDisplay*)>("mir_client_mesa_egl_native_display_is_valid");
2056+ EXPECT_EQ(MIR_MESA_TRUE, validate(nd));
2057 }
2058 EXPECT_EQ(MIR_MESA_FALSE, mclm::mir_client_mesa_egl_native_display_is_valid(nd));
2059 }
2060
2061=== modified file 'tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp'
2062--- tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp 2014-03-06 06:05:17 +0000
2063+++ tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp 2014-12-12 01:39:36 +0000
2064@@ -40,7 +40,7 @@
2065 }
2066
2067 std::shared_ptr<mclg::MesaNativeDisplayContainer> const container;
2068- MirConnection* connection;
2069+ mir::client::ClientContext* connection;
2070 };
2071
2072 }
2073
2074=== modified file 'tests/unit-tests/client/test_client_platform.cpp'
2075--- tests/unit-tests/client/test_client_platform.cpp 2014-03-06 06:05:17 +0000
2076+++ tests/unit-tests/client/test_client_platform.cpp 2014-12-12 01:39:36 +0000
2077@@ -20,60 +20,153 @@
2078 #include "src/client/mir_client_surface.h"
2079 #include "mir_test_doubles/mock_client_context.h"
2080 #include "mir_test_doubles/mock_client_surface.h"
2081+#include "mir_test_framework/executable_path.h"
2082+#include "mir_test_framework/stub_platform_helpers.h"
2083
2084-#ifdef ANDROID
2085+#ifdef MIR_BUILD_PLATFORM_ANDROID
2086 #include "mir_test_doubles/mock_android_hw.h"
2087-#include "src/client/android/client_platform_factory.h"
2088-#else
2089-#include "src/client/mesa/client_platform_factory.h"
2090 #endif
2091
2092+#include "src/client/client_platform_factory.h"
2093+
2094+#include "mir/shared_library.h"
2095+
2096 #include <gmock/gmock.h>
2097 #include <gtest/gtest.h>
2098
2099 namespace mcl=mir::client;
2100 namespace mtd = mir::test::doubles;
2101-
2102-struct ClientPlatformTest : public ::testing::Test
2103-{
2104+namespace mtf = mir_test_framework;
2105+
2106+namespace
2107+{
2108+struct ClientPlatformTraits
2109+{
2110+ ClientPlatformTraits(std::string const& library,
2111+ std::function<void(MirPlatformPackage&)> populator,
2112+ MirPlatformType type)
2113+ : platform_library_name{library},
2114+ populate_package_for{populator},
2115+ platform_type{type}
2116+ {
2117+ }
2118+
2119+ std::string const platform_library_name;
2120+ std::function<void(MirPlatformPackage&)> const populate_package_for;
2121+ MirPlatformType const platform_type;
2122+};
2123+
2124+struct ClientPlatformTest : public ::testing::TestWithParam<ClientPlatformTraits const*>
2125+{
2126+ ClientPlatformTest()
2127+ : platform_library{mtf::library_path() + "/" + GetParam()->platform_library_name},
2128+ create_client_platform{platform_library.load_function<mcl::CreateClientPlatform>("create_client_platform")},
2129+ probe{platform_library.load_function<mcl::ClientPlatformProbe>("is_appropriate_module")}
2130+ {
2131+ using namespace testing;
2132+ ON_CALL(context, populate(_))
2133+ .WillByDefault(Invoke(GetParam()->populate_package_for));
2134+ }
2135+
2136 mtd::MockClientContext context;
2137-#ifdef ANDROID
2138+#ifdef MIR_BUILD_PLATFORM_ANDROID
2139 testing::NiceMock<mtd::HardwareAccessMock> hw_access_mock;
2140- mcl::android::ClientPlatformFactory factory;
2141-#else
2142- mcl::mesa::ClientPlatformFactory factory;
2143 #endif
2144+ mir::SharedLibrary platform_library;
2145+ mcl::CreateClientPlatform const create_client_platform;
2146+ mcl::ClientPlatformProbe const probe;
2147 };
2148
2149-TEST_F(ClientPlatformTest, platform_name)
2150-{
2151- auto platform = factory.create_client_platform(&context);
2152-#ifdef ANDROID
2153- auto type = mir_platform_type_android;
2154-#else
2155- auto type = mir_platform_type_gbm;
2156-#endif
2157- EXPECT_EQ(type, platform->platform_type());
2158-}
2159-
2160-TEST_F(ClientPlatformTest, platform_creates)
2161-{
2162- auto platform = factory.create_client_platform(&context);
2163+#ifdef MIR_BUILD_PLATFORM_ANDROID
2164+ClientPlatformTraits const android_platform{"/client-modules/android.so",
2165+ [](MirPlatformPackage& pkg)
2166+ {
2167+ ::memset(&pkg, 0, sizeof(pkg));
2168+ },
2169+ mir_platform_type_android
2170+ };
2171+
2172+INSTANTIATE_TEST_CASE_P(Android,
2173+ ClientPlatformTest,
2174+ ::testing::Values(&android_platform));
2175+
2176+#endif
2177+
2178+#ifdef MIR_BUILD_PLATFORM_MESA
2179+ClientPlatformTraits const mesa_platform{"/client-modules/mesa.so",
2180+ [](MirPlatformPackage& pkg)
2181+ {
2182+ ::memset(&pkg, 0, sizeof(pkg));
2183+ pkg.fd_items = 1;
2184+ },
2185+ mir_platform_type_gbm
2186+ };
2187+
2188+INSTANTIATE_TEST_CASE_P(Mesa,
2189+ ClientPlatformTest,
2190+ ::testing::Values(&mesa_platform));
2191+
2192+#endif
2193+
2194+ClientPlatformTraits const dummy_platform{"/client-modules/dummy.so",
2195+ [](MirPlatformPackage& pkg)
2196+ {
2197+ mtf::create_stub_platform_package(pkg);
2198+ },
2199+ mir_platform_type_gbm
2200+ };
2201+
2202+INSTANTIATE_TEST_CASE_P(Dummy,
2203+ ClientPlatformTest,
2204+ ::testing::Values(&dummy_platform));
2205+}
2206+
2207+TEST_P(ClientPlatformTest, platform_name)
2208+{
2209+ auto platform = create_client_platform(&context);
2210+
2211+ EXPECT_EQ(GetParam()->platform_type, platform->platform_type());
2212+}
2213+
2214+TEST_P(ClientPlatformTest, platform_creates)
2215+{
2216+ auto platform = create_client_platform(&context);
2217 auto buffer_factory = platform->create_buffer_factory();
2218 EXPECT_NE(buffer_factory.get(), (mcl::ClientBufferFactory*) NULL);
2219 }
2220
2221-TEST_F(ClientPlatformTest, platform_creates_native_window)
2222+TEST_P(ClientPlatformTest, platform_creates_native_window)
2223 {
2224- auto platform = factory.create_client_platform(&context);
2225+ auto platform = create_client_platform(&context);
2226 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
2227 auto native_window = platform->create_egl_native_window(mock_client_surface.get());
2228 EXPECT_NE(*native_window, (EGLNativeWindowType) NULL);
2229 }
2230
2231-TEST_F(ClientPlatformTest, platform_creates_egl_native_display)
2232+TEST_P(ClientPlatformTest, platform_creates_egl_native_display)
2233 {
2234- auto platform = factory.create_client_platform(&context);
2235+ auto platform = create_client_platform(&context);
2236 auto native_display = platform->create_egl_native_display();
2237 EXPECT_NE(nullptr, native_display.get());
2238 }
2239+
2240+TEST_P(ClientPlatformTest, platform_probe_returns_success_when_matching)
2241+{
2242+ EXPECT_TRUE(probe(&context));
2243+}
2244+
2245+TEST_P(ClientPlatformTest, platform_probe_returns_false_when_not_matching)
2246+{
2247+ using namespace testing;
2248+ ON_CALL(context, populate(_))
2249+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2250+ {
2251+ //Mock up something that hopefully looks nothing like
2252+ //what the platform is expecting...
2253+ ::memset(&pkg, 0, sizeof(pkg));
2254+ pkg.data_items = mir_platform_package_max + 1;
2255+ pkg.fd_items = -23;
2256+ }));
2257+
2258+ EXPECT_FALSE(probe(&context));
2259+}
2260
2261=== added file 'tests/unit-tests/client/test_probing_client_platform_factory.cpp'
2262--- tests/unit-tests/client/test_probing_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
2263+++ tests/unit-tests/client/test_probing_client_platform_factory.cpp 2014-12-12 01:39:36 +0000
2264@@ -0,0 +1,142 @@
2265+/*
2266+ * Copyright © 2014 Canonical Ltd.
2267+ *
2268+ * This program is free software: you can redistribute it and/or modify
2269+ * it under the terms of the GNU General Public License version 3 as
2270+ * published by the Free Software Foundation.
2271+ *
2272+ * This program is distributed in the hope that it will be useful,
2273+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2274+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2275+ * GNU General Public License for more details.
2276+ *
2277+ * You should have received a copy of the GNU General Public License
2278+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2279+ *
2280+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
2281+ */
2282+
2283+#include "src/client/client_platform.h"
2284+#include "src/client/probing_client_platform_factory.h"
2285+
2286+#include "mir_test_doubles/mock_client_context.h"
2287+#include "mir_test_framework/executable_path.h"
2288+#include "mir_test_framework/stub_platform_helpers.h"
2289+
2290+#include <gmock/gmock.h>
2291+#include <gtest/gtest.h>
2292+
2293+namespace mtf = mir_test_framework;
2294+namespace mtd = mir::test::doubles;
2295+
2296+namespace
2297+{
2298+std::vector<std::shared_ptr<mir::SharedLibrary>>
2299+all_available_modules()
2300+{
2301+ std::vector<std::shared_ptr<mir::SharedLibrary>> modules;
2302+#ifdef MIR_BUILD_PLATFORM_MESA
2303+ modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::library_path() + "/client-modules/mesa.so"));
2304+#endif
2305+#ifdef MIR_BUILD_PLATFORM_ANDROID
2306+ modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::library_path() + "/client-modules/android.so"));
2307+#endif
2308+ return modules;
2309+}
2310+}
2311+
2312+TEST(ProbingClientPlatformFactory, ThrowsErrorWhenConstructedWithNoPlatforms)
2313+{
2314+ std::vector<std::shared_ptr<mir::SharedLibrary>> empty_modules;
2315+ EXPECT_THROW(mir::client::ProbingClientPlatformFactory{empty_modules},
2316+ std::runtime_error);
2317+}
2318+
2319+TEST(ProbingClientPlatformFactory, ThrowsErrorWhenNoPlatformPluginProbesSuccessfully)
2320+{
2321+ using namespace testing;
2322+
2323+ mir::client::ProbingClientPlatformFactory factory{all_available_modules()};
2324+
2325+ mtd::MockClientContext context;
2326+ ON_CALL(context, populate(_))
2327+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2328+ {
2329+ ::memset(&pkg, 0, sizeof(MirPlatformPackage));
2330+ // Mock up a platform package that looks nothing like
2331+ // either an Android or Mesa package
2332+ pkg.fd_items = 0xdeadbeef;
2333+ pkg.data_items = -23;
2334+ }));
2335+
2336+ EXPECT_THROW(factory.create_client_platform(&context),
2337+ std::runtime_error);
2338+}
2339+
2340+#ifdef MIR_BUILD_PLATFORM_MESA
2341+TEST(ProbingClientPlatformFactory, CreatesMesaPlatformWhenAppropriate)
2342+#else
2343+TEST(ProbingClientPlatformFactory, DISABLED_CreatesMesaPlatformWhenAppropriate)
2344+#endif
2345+{
2346+ using namespace testing;
2347+
2348+ mir::client::ProbingClientPlatformFactory factory{all_available_modules()};
2349+
2350+ mtd::MockClientContext context;
2351+ ON_CALL(context, populate(_))
2352+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2353+ {
2354+ ::memset(&pkg, 0, sizeof(MirPlatformPackage));
2355+ // Mock up something that looks like a GBM platform package,
2356+ // until we send the actual platform type over the wire!
2357+ pkg.fd_items = 1;
2358+ pkg.fd[0] = 23;
2359+ }));
2360+ auto platform = factory.create_client_platform(&context);
2361+ EXPECT_EQ(mir_platform_type_gbm, platform->platform_type());
2362+}
2363+
2364+#ifdef MIR_BUILD_PLATFORM_ANDROID
2365+TEST(ProbingClientPlatformFactory, CreatesAndroidPlatformWhenAppropriate)
2366+#else
2367+TEST(ProbingClientPlatformFactory, DISABLED_CreatesAndroidPlatformWhenAppropriate)
2368+#endif
2369+{
2370+ using namespace testing;
2371+
2372+ mir::client::ProbingClientPlatformFactory factory{all_available_modules()};
2373+
2374+ mtd::MockClientContext context;
2375+ ON_CALL(context, populate(_))
2376+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2377+ {
2378+ // Mock up something that looks like a Android platform package,
2379+ // until we send the actual platform type over the wire!
2380+ ::memset(&pkg, 0, sizeof(MirPlatformPackage));
2381+ }));
2382+
2383+ auto platform = factory.create_client_platform(&context);
2384+ EXPECT_EQ(mir_platform_type_android, platform->platform_type());
2385+}
2386+
2387+TEST(ProbingClientPlatformFactory, IgnoresNonClientPlatformModules)
2388+{
2389+ using namespace testing;
2390+
2391+ auto modules = all_available_modules();
2392+ // NOTE: For minimum fuss, load something that has minimal side-effects...
2393+ modules.push_back(std::make_shared<mir::SharedLibrary>("libc.so.6"));
2394+ modules.push_back(std::make_shared<mir::SharedLibrary>(mtf::library_path() + "/client-modules/dummy.so"));
2395+
2396+ mir::client::ProbingClientPlatformFactory factory{modules};
2397+
2398+ mtd::MockClientContext context;
2399+ ON_CALL(context, populate(_))
2400+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
2401+ {
2402+ mtf::create_stub_platform_package(pkg);
2403+ }));
2404+
2405+ auto platform = factory.create_client_platform(&context);
2406+}
2407
2408=== modified file 'tests/unit-tests/shared_library_test.cpp'
2409--- tests/unit-tests/shared_library_test.cpp 2014-12-08 04:03:47 +0000
2410+++ tests/unit-tests/shared_library_test.cpp 2014-12-12 01:39:36 +0000
2411@@ -59,10 +59,10 @@
2412 public:
2413 SharedLibrary()
2414 : nonexistent_library{"imma_totally_not_a_library"},
2415- existing_library{mtf::library_path() + "/" MIR_CLIENT_DRIVER_BINARY},
2416+ existing_library{mtf::library_path() + "/client-modules/mesa.so"},
2417 nonexistent_function{"yo_dawg"},
2418- existing_function{"create_client_platform_factory"},
2419- existent_version{"MIR_CLIENTPLATFORM_1"},
2420+ existing_function{"create_client_platform"},
2421+ existent_version{"MIR_CLIENT_PLATFORM_2"},
2422 nonexistent_version{"GOATS_ON_THE_GREEN"}
2423 {
2424 }

Subscribers

People subscribed via source and target branches