Mir

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

Proposed by Andreas Pokorny
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 2179
Proposed branch: lp:~mir-team/mir/probe-client-drivers
Merge into: lp:mir
Prerequisite: lp:~raof/mir/fix-all-the-CI
Diff against target: 2440 lines (+954/-387)
65 files modified
benchmarks/frame-uniformity/main.cpp (+7/-0)
benchmarks/frame-uniformity/touch_measuring_client.cpp (+11/-2)
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 (+17/-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 (+0/-41)
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 (+22/-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/-41)
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 (+26/-0)
src/common/symbols.map (+12/-12)
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:~mir-team/mir/probe-client-drivers
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Approve
Andreas Pokorny (community) Approve
Chris Halse Rogers Approve
Robert Carr (community) Approve
Daniel van Vugt Pending
Cemil Azizoglu Pending
Alexandros Frantzis Pending
Review via email: mp+244963@code.launchpad.net

This proposal supersedes a proposal from 2014-12-12.

Commit message

Add probing for client platform modules.

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

Description of the change

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

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote : 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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote : Posted in a previous version of this proposal

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
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

I merged with the new changes on lp:mir and made tiny tweaks to share the SharedLibraryProberReport through mircommon..

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

Still lgtm

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

Still looks sensible to me

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

(2) Spurious whitespace:
511 target_link_libraries(mirclient
512 +

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

(9) I think we can do better than the wrapper approach. And I might do a proof of concept for rpath magic. It would be easier to get it in from the beginning than to have to unwind and remove all the wrapper stuff later.

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

> (9) I think we can do better than the wrapper approach. And I might do a proof
> of concept for rpath magic. It would be easier to get it in from the beginning
> than to have to unwind and remove all the wrapper stuff later.

I doubt rpath magic can that..

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

>
> > (9) I think we can do better than the wrapper approach. And I might do a
> proof
> > of concept for rpath magic. It would be easier to get it in from the
> beginning
> > than to have to unwind and remove all the wrapper stuff later.
>
> I doubt rpath magic can that..

I mean the wrapper solves knowing in which directory to search for platform modules to load and probe, while rpath solves finding a library through a (path-free) library file name - by adding more search paths.

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 :

[ FAILED ] 1 test, listed below:
[ FAILED ] TestClientInput.hidden_clients_do_not_receive_pointer_events

1 FAILED TEST
 YOU HAVE 8 DISABLED TESTS

not related to this change.

--

lgtm

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

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 + }

wouldn't "#undef NDEBUG" before including <cassert> be simpler and clearer?

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

995 === modified file 'src/client/mesa/client_platform_factory.h'

This file is /1/ effectively empty and /2/ isn't referenced. It can be removed. (Also the android counterpart)

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

On Thu, Dec 18, 2014 at 11:46 PM, Alan Griffiths <email address hidden>
wrote:
> 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 + }
>
> wouldn't "#undef NDEBUG" before including <cassert> be simpler and
> clearer?

No, because that wouldn't print any diagnostics as to why the
connection/surface was invalid. I added those when debugging why the
frame_uniformity test was assert()ing :)

There might be an argument for having mir_assert_*_is_valid convenience
functions in the client library that do this, now that we've got client
library logging!

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

Yes, rpath will have limitations. But there might be other alternatives to wrapping that are possible. Not sure yet, and I'm not blocking on the hypothesis.

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

OK. I still have some misgivings, but nothing to block on. And the changes are useful.

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

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

Subscribers

People subscribed via source and target branches