Mir

Merge lp:~raof/mir/client-driver-probing into lp:mir

Proposed by Chris Halse Rogers
Status: Merged
Merged at revision: 2179
Proposed branch: lp:~raof/mir/client-driver-probing
Merge into: lp:mir
Diff against target: 1581 lines (+677/-201)
41 files modified
benchmarks/frame-uniformity/CMakeLists.txt (+2/-2)
src/client/CMakeLists.txt (+17/-13)
src/client/android/CMakeLists.txt (+7/-22)
src/client/android/android_native_display_container.cpp (+16/-4)
src/client/android/android_native_display_container.h (+8/-1)
src/client/android/client_platform_factory.cpp (+21/-5)
src/client/android/client_platform_factory.h (+2/-5)
src/client/android/symbols.map (+5/-4)
src/client/client_context.h (+0/-1)
src/client/client_platform_factory.h (+5/-2)
src/client/connection_configuration.h (+0/-3)
src/client/default_connection_configuration.cpp (+23/-18)
src/client/default_connection_configuration.h (+0/-4)
src/client/egl_native_display_container.h (+3/-1)
src/client/mesa/CMakeLists.txt (+6/-22)
src/client/mesa/client_platform.cpp (+1/-1)
src/client/mesa/client_platform_factory.cpp (+19/-5)
src/client/mesa/client_platform_factory.h (+0/-5)
src/client/mesa/mesa_native_display_container.cpp (+5/-5)
src/client/mesa/mesa_native_display_container.h (+1/-1)
src/client/mesa/native_surface.cpp (+0/-1)
src/client/mesa/symbols.map (+6/-4)
src/client/mir_connection.cpp (+7/-9)
src/client/mir_connection.h (+2/-2)
src/client/probing_client_platform_factory.cpp (+38/-0)
src/client/probing_client_platform_factory.h (+27/-0)
src/common/symbols.map (+1/-0)
tests/acceptance-tests/CMakeLists.txt (+4/-3)
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_framework/client_platform_factory.h (+72/-0)
tests/include/mir_test_framework/stub_client_platform_factory.h (+33/-0)
tests/mir_test_framework/CMakeLists.txt (+28/-4)
tests/mir_test_framework/stub_client_platform_factory.cpp (+147/-0)
tests/mir_test_framework/stub_client_platform_module.cpp (+35/-0)
tests/mir_test_framework/symbols-client.map (+7/-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 (+109/-29)
tests/unit-tests/shared_library_test.cpp (+3/-3)
To merge this branch: bzr merge lp:~raof/mir/client-driver-probing
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Mir development team Pending
Review via email: mp+242865@code.launchpad.net

Commit message

Blank commit message; this is not expected to be landed individually.

Description of the change

First part of split-out privatise-all-the-things, adding the client-side bits.

Broken up to assist in review. Not expected to pass CI, because the packaging infrastructure isn't updated.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (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/CMakeLists.txt'
2--- benchmarks/frame-uniformity/CMakeLists.txt 2014-11-20 09:53:04 +0000
3+++ benchmarks/frame-uniformity/CMakeLists.txt 2014-11-26 06:34:08 +0000
4@@ -24,15 +24,15 @@
5 target_link_libraries(frame_uniformity_test_client
6 mirserver
7 mirclient
8+ mirplatform
9
10 mir-test
11- mir-test-framework
12 mir-test-doubles
13 mir-test-doubles-platform
14+ mir-test-framework
15
16 # Why does this have to come after mir-test-framework here but not in tests/acceptance-tests/
17 # /CMakeLists.txt? ~racarr
18- mirplatform
19
20 3rd_party
21 ${PROTOBUF_LIBRARIES}
22
23=== modified file 'src/client/CMakeLists.txt'
24--- src/client/CMakeLists.txt 2014-11-25 02:07:32 +0000
25+++ src/client/CMakeLists.txt 2014-11-26 06:34:08 +0000
26@@ -1,13 +1,3 @@
27-set(MIRCLIENT_ABI 8)
28-set(CLIENT_DRIVER client${MIRCLIENT_ABI}driver)
29-set(MIR_CLIENT_DRIVER mir${CLIENT_DRIVER})
30-set(MIR_CLIENT_DRIVER_BINARY lib${MIR_CLIENT_DRIVER}.so
31- CACHE STRING "File name of Mir client drivers")
32-add_definitions(
33- -DMIR_CLIENT_DRIVER_BINARY="${MIR_CLIENT_DRIVER_BINARY}"
34- -DMIR_LOGGING_COMPONENT_FALLBACK="mirclient"
35-)
36-
37 set(PREFIX "${CMAKE_INSTALL_PREFIX}")
38 set(EXEC_PREFIX "${CMAKE_INSTALL_PREFIX}")
39 set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}")
40@@ -33,6 +23,19 @@
41 ${DRM_INCLUDE_DIRS}
42 )
43
44+set(MIRCLIENT_ABI 8)
45+set(CLIENT_PLATFORM_VERSION "MIR_CLIENT_PLATFORM_2")
46+set(symbol_map ${CMAKE_SOURCE_DIR}/src/client/symbols.map)
47+
48+set(MIR_CLIENT_PLATFORM_PATH
49+ ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/mir/client-platform
50+)
51+
52+add_definitions(-DMIR_CLIENT_PLATFORM_PATH="${MIR_CLIENT_PLATFORM_PATH}/")
53+add_definitions(-DCLIENT_PLATFORM_VERSION="${CLIENT_PLATFORM_VERSION}")
54+add_definitions(-DMIR_LOGGING_COMPONENT_FALLBACK="mirclient")
55+
56+
57 add_subdirectory(rpc/)
58 add_subdirectory(lttng/)
59
60@@ -72,6 +75,7 @@
61 mir_prompt_session.cpp
62 mir_prompt_session_api.cpp
63 mir_event_distributor.cpp
64+ probing_client_platform_factory.cpp
65 periodic_perf_report.cpp
66 )
67
68@@ -81,8 +85,6 @@
69 $<TARGET_OBJECTS:mirclientobjects>
70 )
71
72-set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols.map)
73-
74 set_target_properties(
75 mirclient
76
77@@ -91,7 +93,9 @@
78 LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
79 )
80
81-target_link_libraries(mirclient
82+target_link_libraries(
83+ mirclient
84+
85 mirclientrpc
86 mirclientlttngstatic
87 mircommon
88
89=== modified file 'src/client/android/CMakeLists.txt'
90--- src/client/android/CMakeLists.txt 2014-10-29 06:21:10 +0000
91+++ src/client/android/CMakeLists.txt 2014-11-26 06:34:08 +0000
92@@ -14,17 +14,18 @@
93 )
94
95 add_library(
96- mirclientplatformandroid SHARED
97-
98+ mirclientplatformandroid MODULE
99+
100 $<TARGET_OBJECTS:mirclientplatformandroidobjects>
101 $<TARGET_OBJECTS:mirclient_platformimpl>
102 )
103
104 set_target_properties(
105 mirclientplatformandroid PROPERTIES
106- OUTPUT_NAME ${MIR_CLIENT_DRIVER}
107- LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/android
108- LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
109+ OUTPUT_NAME android
110+ LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
111+ PREFIX ""
112+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
113 )
114
115 target_link_libraries(mirclientplatformandroid
116@@ -33,20 +34,4 @@
117 ${LIBHARDWARE_LIBRARIES}
118 )
119
120-install(TARGETS mirclientplatformandroid LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/mir/${CLIENT_DRIVER}/android)
121-
122-if (MIR_TEST_PLATFORM STREQUAL "android")
123- add_custom_command(TARGET mirclientplatformandroid
124- POST_BUILD
125- COMMAND ${CMAKE_COMMAND} -E remove ${MIR_CLIENT_DRIVER_BINARY}
126- COMMAND ${CMAKE_COMMAND} -E create_symlink android/$<TARGET_FILE_NAME:mirclientplatformandroid> ${MIR_CLIENT_DRIVER_BINARY}
127- WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
128- )
129-
130- install(CODE
131- "execute_process(
132- COMMAND ln -sf mir/${CLIENT_DRIVER}/android/${MIR_CLIENT_DRIVER_BINARY}
133- WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
134- )"
135- )
136-endif()
137+install(TARGETS mirclientplatformandroid LIBRARY DESTINATION ${MIR_CLIENT_PLATFORM_PATH})
138
139=== modified file 'src/client/android/android_native_display_container.cpp'
140--- src/client/android/android_native_display_container.cpp 2014-10-29 06:21:10 +0000
141+++ src/client/android/android_native_display_container.cpp 2014-11-26 06:34:08 +0000
142@@ -62,16 +62,28 @@
143 bool
144 mcla::AndroidNativeDisplayContainer::validate(MirEGLNativeDisplayType display) const
145 {
146- return mir_connection_is_valid(static_cast<MirConnection*>(display));
147+ std::lock_guard<std::mutex> lg(guard);
148+ return (valid_displays.find(display) != valid_displays.end());
149 }
150
151 MirEGLNativeDisplayType
152-mcla::AndroidNativeDisplayContainer::create(MirConnection* connection)
153+mcla::AndroidNativeDisplayContainer::create(ClientContext* context)
154 {
155- return static_cast<MirEGLNativeDisplayType>(connection);
156+ std::lock_guard<std::mutex> lg(guard);
157+ auto egl_display = static_cast<MirEGLNativeDisplayType>(context);
158+ valid_displays.insert(egl_display);
159+
160+ return egl_display;
161 }
162
163 void
164-mcla::AndroidNativeDisplayContainer::release(MirEGLNativeDisplayType /* display */)
165+mcla::AndroidNativeDisplayContainer::release(MirEGLNativeDisplayType display)
166 {
167+ std::lock_guard<std::mutex> lg(guard);
168+
169+ auto it = valid_displays.find(display);
170+ if (it == valid_displays.end())
171+ return;
172+
173+ valid_displays.erase(it);
174 }
175
176=== modified file 'src/client/android/android_native_display_container.h'
177--- src/client/android/android_native_display_container.h 2013-05-02 00:11:18 +0000
178+++ src/client/android/android_native_display_container.h 2014-11-26 06:34:08 +0000
179@@ -23,6 +23,9 @@
180
181 #include "mir_toolkit/client_types.h"
182
183+#include <unordered_set>
184+#include <mutex>
185+
186 namespace mir
187 {
188 namespace client
189@@ -36,7 +39,7 @@
190 AndroidNativeDisplayContainer();
191 virtual ~AndroidNativeDisplayContainer();
192
193- MirEGLNativeDisplayType create(MirConnection* connection);
194+ MirEGLNativeDisplayType create(ClientContext* context) override;
195 void release(MirEGLNativeDisplayType display);
196
197 bool validate(MirEGLNativeDisplayType display) const;
198@@ -44,6 +47,10 @@
199 protected:
200 AndroidNativeDisplayContainer(AndroidNativeDisplayContainer const&) = delete;
201 AndroidNativeDisplayContainer& operator=(AndroidNativeDisplayContainer const&) = delete;
202+
203+private:
204+ std::mutex mutable guard;
205+ std::unordered_set<MirEGLNativeDisplayType> valid_displays;
206 };
207
208 }
209
210=== modified file 'src/client/android/client_platform_factory.cpp'
211--- src/client/android/client_platform_factory.cpp 2014-02-07 15:43:41 +0000
212+++ src/client/android/client_platform_factory.cpp 2014-11-26 06:34:08 +0000
213@@ -16,19 +16,35 @@
214 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
215 */
216
217-#include "client_platform_factory.h"
218+#include "../client_platform_factory.h"
219+#include "mir_toolkit/client_types.h"
220+#include "../client_context.h"
221 #include "android_client_platform.h"
222
223+#include <stdexcept>
224+
225 namespace mcl = mir::client;
226 namespace mcla = mcl::android;
227
228-std::shared_ptr<mcl::ClientPlatform>
229-mcla::ClientPlatformFactory::create_client_platform(mcl::ClientContext* /*context*/)
230+extern "C" std::shared_ptr<mcl::ClientPlatform>
231+mcl::create_client_platform(mcl::ClientContext* context)
232 {
233+ MirPlatformPackage platform;
234+ context->populate(platform);
235+ if (platform.data_items != 0 || platform.fd_items != 0)
236+ {
237+ throw new std::runtime_error{"Attempted to create Android client platform on non-Android server"};
238+ }
239 return std::make_shared<mcla::AndroidClientPlatform>();
240 }
241
242-extern "C" std::shared_ptr<mcl::ClientPlatformFactory> mcl::create_client_platform_factory()
243+extern "C" bool
244+mcl::is_appropriate_module(mcl::ClientContext* context)
245 {
246- return std::make_shared<mcla::ClientPlatformFactory>();
247+ MirPlatformPackage platform;
248+ context->populate(platform);
249+ // TODO: Actually check what platform we're using, rather than blindly
250+ // hope we can distinguish them from the stuff they've put in the
251+ // PlatformPackage.
252+ return platform.data_items == 0 && platform.fd_items == 0;
253 }
254
255=== modified file 'src/client/android/client_platform_factory.h'
256--- src/client/android/client_platform_factory.h 2014-02-07 15:43:41 +0000
257+++ src/client/android/client_platform_factory.h 2014-11-26 06:34:08 +0000
258@@ -28,11 +28,8 @@
259 namespace android
260 {
261
262-class ClientPlatformFactory : public client::ClientPlatformFactory
263-{
264-public:
265- std::shared_ptr<ClientPlatform> create_client_platform(ClientContext* context) override;
266-};
267+extern "C" std::shared_ptr<ClientPlatform>
268+create_client_platform(ClientContext* context);
269
270 }
271 }
272
273=== modified file 'src/client/android/symbols.map'
274--- src/client/android/symbols.map 2014-10-29 06:21:10 +0000
275+++ src/client/android/symbols.map 2014-11-26 06:34:08 +0000
276@@ -1,5 +1,6 @@
277-MIR_CLIENTPLATFORM_1 {
278- global:
279- create_client_platform_factory;
280+MIR_CLIENT_PLATFORM_2 {
281+ global:
282+ create_client_platform;
283+ is_appropriate_module;
284 local: *;
285-};
286\ No newline at end of file
287+};
288
289=== modified file 'src/client/client_context.h'
290--- src/client/client_context.h 2013-08-28 03:41:48 +0000
291+++ src/client/client_context.h 2014-11-26 06:34:08 +0000
292@@ -29,7 +29,6 @@
293 public:
294 virtual ~ClientContext() {}
295
296- virtual MirConnection* mir_connection() = 0;
297 virtual void populate(MirPlatformPackage& platform_package) = 0;
298
299 protected:
300
301=== modified file 'src/client/client_platform_factory.h'
302--- src/client/client_platform_factory.h 2014-03-06 06:05:17 +0000
303+++ src/client/client_platform_factory.h 2014-11-26 06:34:08 +0000
304@@ -41,8 +41,11 @@
305 ClientPlatformFactory& operator=(ClientPlatformFactory const& p) = delete;
306 };
307
308-extern "C" typedef std::shared_ptr<ClientPlatformFactory>(*CreateClientPlatformFactory)();
309-extern "C" std::shared_ptr<ClientPlatformFactory> create_client_platform_factory();
310+extern "C" typedef std::shared_ptr<ClientPlatform>(*CreateClientPlatform)(ClientContext* context);
311+extern "C" std::shared_ptr<ClientPlatform> create_client_platform(ClientContext* context);
312+
313+extern "C" typedef bool (*ClientPlatformProbe)(ClientContext* context);
314+extern "C" bool is_appropriate_module(ClientContext* context);
315
316 }
317 }
318
319=== modified file 'src/client/connection_configuration.h'
320--- src/client/connection_configuration.h 2014-10-29 06:21:10 +0000
321+++ src/client/connection_configuration.h 2014-11-26 06:34:08 +0000
322@@ -39,8 +39,6 @@
323 class Logger;
324 }
325
326-class SharedLibrary;
327-
328 namespace client
329 {
330 class ConnectionSurfaceMap;
331@@ -65,7 +63,6 @@
332 virtual std::shared_ptr<LifecycleControl> the_lifecycle_control() = 0;
333 virtual std::shared_ptr<EventSink> the_event_sink() = 0;
334 virtual std::shared_ptr<EventHandlerRegister> the_event_handler_register() = 0;
335- virtual std::shared_ptr<SharedLibrary> the_platform_library() = 0;
336
337 protected:
338 ConnectionConfiguration() = default;
339
340=== modified file 'src/client/default_connection_configuration.cpp'
341--- src/client/default_connection_configuration.cpp 2014-10-29 06:21:10 +0000
342+++ src/client/default_connection_configuration.cpp 2014-11-26 06:34:08 +0000
343@@ -35,6 +35,7 @@
344 #include "lifecycle_control.h"
345 #include "mir/shared_library.h"
346 #include "client_platform_factory.h"
347+#include "probing_client_platform_factory.h"
348 #include "mir_event_distributor.h"
349 #include "mir/shared_library_prober.h"
350
351@@ -47,7 +48,10 @@
352 std::string const off_opt_val{"off"};
353 std::string const log_opt_val{"log"};
354 std::string const lttng_opt_val{"lttng"};
355-std::string const default_platform_lib{MIR_CLIENT_DRIVER_BINARY};
356+
357+// Shove this here until we properly manage the lifetime of our
358+// loadable modules
359+std::shared_ptr<mcl::ProbingClientPlatformFactory> the_platform_prober;
360
361 // Hack around the way Qt loads mir:
362 // qtmir and therefore Mir are loaded via dlopen(..., RTLD_LOCAL).
363@@ -108,11 +112,23 @@
364 return client_platform_factory(
365 [this]
366 {
367- auto const create_client_platform_factory =
368- the_platform_library()->load_function<mcl::CreateClientPlatformFactory>(
369- "create_client_platform_factory");
370-
371- return create_client_platform_factory();
372+ ensure_loaded_with_rtld_global();
373+ auto const platform_override = getenv("MIR_CLIENT_PLATFORM_LIB");
374+ std::vector<std::shared_ptr<mir::SharedLibrary>> platform_plugins;
375+ if (platform_override)
376+ {
377+ platform_plugins.push_back(std::make_shared<mir::SharedLibrary>(platform_override));
378+ }
379+ else
380+ {
381+ auto const platform_path_override = getenv("MIR_CLIENT_PLATFORM_PATH");
382+ auto const platform_path = platform_path_override ? platform_path_override : MIR_CLIENT_PLATFORM_PATH;
383+ platform_plugins = mir::libraries_for_path(platform_path, *the_shared_library_prober_report());
384+ }
385+
386+ the_platform_prober = std::make_shared<mcl::ProbingClientPlatformFactory>(platform_plugins);
387+
388+ return the_platform_prober;
389 });
390 }
391
392@@ -211,6 +227,7 @@
393 {
394 auto val_raw = getenv("MIR_CLIENT_SHARED_LIBRARY_PROBER_REPORT");
395 std::string const val{val_raw ? val_raw : off_opt_val};
396+
397 if (val == log_opt_val)
398 return std::make_shared<mir::logging::SharedLibraryProberReport>(the_logger());
399 else if (val == lttng_opt_val)
400@@ -219,15 +236,3 @@
401 return std::make_shared<mir::logging::NullSharedLibraryProberReport>();
402 });
403 }
404-
405-std::shared_ptr<mir::SharedLibrary> mcl::DefaultConnectionConfiguration::the_platform_library()
406-{
407- if (!platform_library)
408- {
409- ensure_loaded_with_rtld_global();
410- auto const val_raw = getenv("MIR_CLIENT_PLATFORM_LIB");
411- std::string const libname{val_raw ? val_raw : default_platform_lib};
412- platform_library = std::make_shared<mir::SharedLibrary>(libname);
413- }
414- return platform_library;
415-}
416
417=== modified file 'src/client/default_connection_configuration.h'
418--- src/client/default_connection_configuration.h 2014-11-05 03:25:04 +0000
419+++ src/client/default_connection_configuration.h 2014-11-26 06:34:08 +0000
420@@ -60,16 +60,12 @@
421 std::shared_ptr<EventSink> the_event_sink() override;
422 std::shared_ptr<EventHandlerRegister> the_event_handler_register() override;
423 std::shared_ptr<mir::SharedLibraryProberReport> the_shared_library_prober_report();
424- std::shared_ptr<SharedLibrary> the_platform_library() override;
425
426 virtual std::string the_socket_file();
427 virtual std::shared_ptr<rpc::RpcReport> the_rpc_report();
428 virtual std::shared_ptr<input::receiver::InputReceiverReport> the_input_receiver_report();
429
430 protected:
431- // MUST be first data member so it is destroyed last.
432- std::shared_ptr<mir::SharedLibrary> platform_library;
433-
434 CachedPtr<google::protobuf::RpcChannel> rpc_channel;
435 CachedPtr<mir::logging::Logger> logger;
436 CachedPtr<ClientPlatformFactory> client_platform_factory;
437
438=== modified file 'src/client/egl_native_display_container.h'
439--- src/client/egl_native_display_container.h 2014-03-06 06:05:17 +0000
440+++ src/client/egl_native_display_container.h 2014-11-26 06:34:08 +0000
441@@ -26,12 +26,14 @@
442 namespace client
443 {
444
445+class ClientContext;
446+
447 class EGLNativeDisplayContainer
448 {
449 public:
450 virtual ~EGLNativeDisplayContainer() {}
451
452- virtual MirEGLNativeDisplayType create(MirConnection* connection) = 0;
453+ virtual MirEGLNativeDisplayType create(ClientContext* context) = 0;
454 virtual void release(MirEGLNativeDisplayType display) = 0;
455
456 virtual bool validate(MirEGLNativeDisplayType display) const = 0;
457
458=== modified file 'src/client/mesa/CMakeLists.txt'
459--- src/client/mesa/CMakeLists.txt 2014-10-29 06:21:10 +0000
460+++ src/client/mesa/CMakeLists.txt 2014-11-26 06:34:08 +0000
461@@ -15,7 +15,7 @@
462 )
463
464 add_library(
465- mirclientplatformmesa SHARED
466+ mirclientplatformmesa MODULE
467
468 $<TARGET_OBJECTS:mirclientplatformmesaobjects>
469 $<TARGET_OBJECTS:mirclient_platformimpl>
470@@ -23,9 +23,10 @@
471
472 set_target_properties(
473 mirclientplatformmesa PROPERTIES
474- OUTPUT_NAME ${MIR_CLIENT_DRIVER}
475- LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/mesa
476- LINK_FLAGS "-Wl,--exclude-libs=ALL -Wl,--version-script,${symbol_map}"
477+ OUTPUT_NAME mesa
478+ LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}/client-modules
479+ PREFIX ""
480+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
481 )
482
483 target_link_libraries(mirclientplatformmesa
484@@ -33,21 +34,4 @@
485 ${DRM_LDFLAGS} ${DRM_LIBRARIES}
486 )
487
488-install(TARGETS mirclientplatformmesa LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/mir/${CLIENT_DRIVER}/mesa)
489-
490-if (MIR_TEST_PLATFORM STREQUAL "mesa")
491- add_custom_command(TARGET mirclientplatformmesa
492- POST_BUILD
493- COMMAND ${CMAKE_COMMAND} -E remove ${MIR_CLIENT_DRIVER_BINARY}
494- COMMAND ${CMAKE_COMMAND} -E create_symlink mesa/$<TARGET_FILE_NAME:mirclientplatformmesa> ${MIR_CLIENT_DRIVER_BINARY}
495- WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
496- )
497-
498- install(CODE
499- "execute_process(
500- COMMAND ln -sf mir/${CLIENT_DRIVER}/mesa/${MIR_CLIENT_DRIVER_BINARY}
501- WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
502- )"
503- )
504-endif()
505-
506+install(TARGETS mirclientplatformmesa LIBRARY DESTINATION ${MIR_CLIENT_PLATFORM_PATH})
507
508=== modified file 'src/client/mesa/client_platform.cpp'
509--- src/client/mesa/client_platform.cpp 2014-03-06 06:05:17 +0000
510+++ src/client/mesa/client_platform.cpp 2014-11-26 06:34:08 +0000
511@@ -95,7 +95,7 @@
512 std::shared_ptr<EGLNativeDisplayType> mclm::ClientPlatform::create_egl_native_display()
513 {
514 MirEGLNativeDisplayType *mir_native_display = new MirEGLNativeDisplayType;
515- *mir_native_display = display_container.create(context->mir_connection());
516+ *mir_native_display = display_container.create(context);
517 auto egl_native_display = reinterpret_cast<EGLNativeDisplayType*>(mir_native_display);
518
519 return std::shared_ptr<EGLNativeDisplayType>(egl_native_display, NativeDisplayDeleter(display_container));
520
521=== modified file 'src/client/mesa/client_platform_factory.cpp'
522--- src/client/mesa/client_platform_factory.cpp 2014-02-07 15:43:41 +0000
523+++ src/client/mesa/client_platform_factory.cpp 2014-11-26 06:34:08 +0000
524@@ -16,13 +16,16 @@
525 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
526 */
527
528-#include "client_platform_factory.h"
529+#include "../client_platform_factory.h"
530 #include "client_platform.h"
531+#include "mir_toolkit/client_types.h"
532+#include "../client_context.h"
533 #include "buffer_file_ops.h"
534 #include "../egl_native_display_container.h"
535
536 #include <sys/mman.h>
537 #include <unistd.h>
538+#include <stdexcept>
539
540 namespace mcl = mir::client;
541 namespace mclm = mcl::mesa;
542@@ -57,15 +60,26 @@
543
544 }
545
546-std::shared_ptr<mcl::ClientPlatform>
547-mclm::ClientPlatformFactory::create_client_platform(mcl::ClientContext* context)
548+extern "C" std::shared_ptr<mcl::ClientPlatform> mcl::create_client_platform(mcl::ClientContext* context)
549 {
550+ MirPlatformPackage package;
551+ context->populate(package);
552+ if (package.data_items != 0 || package.fd_items != 1)
553+ {
554+ throw std::runtime_error{"Attempted to create Mesa client platform on non-Mesa server"};
555+ }
556 auto buffer_file_ops = std::make_shared<RealBufferFileOps>();
557 return std::make_shared<mclm::ClientPlatform>(
558 context, buffer_file_ops, mcl::EGLNativeDisplayContainer::instance());
559 }
560
561-extern "C" std::shared_ptr<mcl::ClientPlatformFactory> mcl::create_client_platform_factory()
562+extern "C" bool
563+mcl::is_appropriate_module(mcl::ClientContext* context)
564 {
565- return std::make_shared<mclm::ClientPlatformFactory>();
566+ MirPlatformPackage platform;
567+ context->populate(platform);
568+ // TODO: Actually check what platform we're using, rather than blindly
569+ // hope we can distinguish them from the stuff they've put in the
570+ // PlatformPackage.
571+ return platform.data_items == 0 && platform.fd_items == 1;
572 }
573
574=== modified file 'src/client/mesa/client_platform_factory.h'
575--- src/client/mesa/client_platform_factory.h 2014-02-07 15:43:41 +0000
576+++ src/client/mesa/client_platform_factory.h 2014-11-26 06:34:08 +0000
577@@ -28,11 +28,6 @@
578 namespace mesa
579 {
580
581-class ClientPlatformFactory : public client::ClientPlatformFactory
582-{
583-public:
584- std::shared_ptr<ClientPlatform> create_client_platform(ClientContext* context) override;
585-};
586
587 }
588 }
589
590=== modified file 'src/client/mesa/mesa_native_display_container.cpp'
591--- src/client/mesa/mesa_native_display_container.cpp 2014-10-29 06:21:10 +0000
592+++ src/client/mesa/mesa_native_display_container.cpp 2014-11-26 06:34:08 +0000
593@@ -18,7 +18,7 @@
594
595 #include "mesa_native_display_container.h"
596
597-#include "mir_toolkit/mir_client_library.h"
598+#include "../client_context.h"
599
600 #include <cstring>
601 #include <unordered_set>
602@@ -35,8 +35,8 @@
603 static int egl_display_get_platform(MirMesaEGLNativeDisplay* display,
604 MirPlatformPackage* package)
605 {
606- auto connection = static_cast<MirConnection*>(display->context);
607- mir_connection_get_platform(connection, package);
608+ auto context = static_cast<mcl::ClientContext*>(display->context);
609+ context->populate(*package);
610 return MIR_MESA_TRUE;
611 }
612
613@@ -93,11 +93,11 @@
614 }
615
616 MirEGLNativeDisplayType
617-mclm::MesaNativeDisplayContainer::create(MirConnection* connection)
618+mclm::MesaNativeDisplayContainer::create(ClientContext* context)
619 {
620 MirMesaEGLNativeDisplay* display = new MirMesaEGLNativeDisplay();
621 display->display_get_platform = egl_display_get_platform;
622- display->context = connection;
623+ display->context = context;
624
625 std::lock_guard<std::mutex> lg(guard);
626 auto egl_display = static_cast<MirEGLNativeDisplayType>(display);
627
628=== modified file 'src/client/mesa/mesa_native_display_container.h'
629--- src/client/mesa/mesa_native_display_container.h 2014-03-06 06:05:17 +0000
630+++ src/client/mesa/mesa_native_display_container.h 2014-11-26 06:34:08 +0000
631@@ -40,7 +40,7 @@
632 MesaNativeDisplayContainer();
633 virtual ~MesaNativeDisplayContainer();
634
635- MirEGLNativeDisplayType create(MirConnection* connection);
636+ MirEGLNativeDisplayType create(ClientContext* context);
637 void release(MirEGLNativeDisplayType display);
638
639 bool validate(MirEGLNativeDisplayType display) const;
640
641=== modified file 'src/client/mesa/native_surface.cpp'
642--- src/client/mesa/native_surface.cpp 2014-10-29 06:21:10 +0000
643+++ src/client/mesa/native_surface.cpp 2014-11-26 06:34:08 +0000
644@@ -20,7 +20,6 @@
645 #include "../client_buffer.h"
646 #include "native_surface.h"
647
648-#include <iostream>
649 #include <boost/exception/diagnostic_information.hpp>
650
651 namespace mclm=mir::client::mesa;
652
653=== modified file 'src/client/mesa/symbols.map'
654--- src/client/mesa/symbols.map 2014-10-29 06:21:10 +0000
655+++ src/client/mesa/symbols.map 2014-11-26 06:34:08 +0000
656@@ -1,7 +1,9 @@
657-MIR_CLIENTPLATFORM_1 {
658- global:
659- create_client_platform_factory;
660+MIR_CLIENT_PLATFORM_2 {
661+ global:
662+ create_client_platform;
663+ is_appropriate_module;
664 # Needed by our Mesa EGL platform
665 mir_client_mesa_egl_native_display_is_valid;
666- local: *;
667+ local:
668+ *;
669 };
670
671=== modified file 'src/client/mir_connection.cpp'
672--- src/client/mir_connection.cpp 2014-11-12 07:07:06 +0000
673+++ src/client/mir_connection.cpp 2014-11-26 06:34:08 +0000
674@@ -95,11 +95,11 @@
675 MirConnection::MirConnection(
676 mir::client::ConnectionConfiguration& conf) :
677 deregisterer{this},
678- platform_library{conf.the_platform_library()},
679 channel(conf.the_rpc_channel()),
680 server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
681 debug(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
682 logger(conf.the_logger()),
683+ connect_done{false},
684 client_platform_factory(conf.the_client_platform_factory()),
685 input_platform(conf.the_input_platform()),
686 display_configuration(conf.the_display_configuration()),
687@@ -235,6 +235,9 @@
688 set_error_message("Connect failed");
689 }
690 }
691+
692+ connect_done = true;
693+
694 /*
695 * We need to create the client platform after the connection has been
696 * established, to ensure that the client platform has access to all
697@@ -370,9 +373,9 @@
698
699 void MirConnection::populate(MirPlatformPackage& platform_package)
700 {
701- std::lock_guard<decltype(mutex)> lock(mutex);
702-
703- if (!connect_result.has_error() && connect_result.has_platform())
704+ // connect_result is write-once: once it's valid, we don't need to lock
705+ // to use it.
706+ if (connect_done && !connect_result.has_error() && connect_result.has_platform())
707 {
708 auto const& platform = connect_result.platform();
709
710@@ -428,11 +431,6 @@
711 return platform;
712 }
713
714-MirConnection* MirConnection::mir_connection()
715-{
716- return this;
717-}
718-
719 EGLNativeDisplayType MirConnection::egl_native_display()
720 {
721 std::lock_guard<decltype(mutex)> lock(mutex);
722
723=== modified file 'src/client/mir_connection.h'
724--- src/client/mir_connection.h 2014-10-29 06:21:10 +0000
725+++ src/client/mir_connection.h 2014-11-26 06:34:08 +0000
726@@ -22,6 +22,7 @@
727 #include <memory>
728 #include <unordered_set>
729 #include <unordered_map>
730+#include <atomic>
731
732 #include <mutex>
733
734@@ -117,8 +118,6 @@
735
736 static bool is_valid(MirConnection *connection);
737
738- MirConnection* mir_connection();
739-
740 EGLNativeDisplayType egl_native_display();
741
742 void on_surface_created(int id, MirSurface* surface);
743@@ -153,6 +152,7 @@
744 std::shared_ptr<mir::logging::Logger> const logger;
745 mir::protobuf::Void void_response;
746 mir::protobuf::Connection connect_result;
747+ std::atomic<bool> connect_done;
748 mir::protobuf::Void ignored;
749 mir::protobuf::ConnectParameters connect_parameters;
750 mir::protobuf::DRMAuthMagicStatus drm_auth_magic_status;
751
752=== added file 'src/client/probing_client_platform_factory.cpp'
753--- src/client/probing_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
754+++ src/client/probing_client_platform_factory.cpp 2014-11-26 06:34:08 +0000
755@@ -0,0 +1,38 @@
756+#include "probing_client_platform_factory.h"
757+
758+#include <boost/exception/all.hpp>
759+#include <stdexcept>
760+
761+namespace mcl = mir::client;
762+
763+mcl::ProbingClientPlatformFactory::ProbingClientPlatformFactory(std::vector<std::shared_ptr<mir::SharedLibrary>> const& modules)
764+ : platform_modules{modules}
765+{
766+ if (modules.empty())
767+ {
768+ BOOST_THROW_EXCEPTION(
769+ std::runtime_error{"Attempted to create a ClientPlatformFactory with no platform modules"});
770+ }
771+}
772+
773+std::shared_ptr<mcl::ClientPlatform>
774+mcl::ProbingClientPlatformFactory::create_client_platform(mcl::ClientContext* context)
775+{
776+ for (auto& module : platform_modules)
777+ {
778+ try
779+ {
780+ auto probe = module->load_function<mir::client::ClientPlatformProbe>("is_appropriate_module", CLIENT_PLATFORM_VERSION);
781+ if (probe(context))
782+ {
783+ auto factory = module->load_function<mir::client::CreateClientPlatform>("create_client_platform", CLIENT_PLATFORM_VERSION);
784+ return factory(context);
785+ }
786+ }
787+ catch(std::runtime_error)
788+ {
789+ // We were handled a SharedLibrary that's not a client platform module?
790+ }
791+ }
792+ BOOST_THROW_EXCEPTION(std::runtime_error{"No appropriate client platform module found"});
793+}
794
795=== added file 'src/client/probing_client_platform_factory.h'
796--- src/client/probing_client_platform_factory.h 1970-01-01 00:00:00 +0000
797+++ src/client/probing_client_platform_factory.h 2014-11-26 06:34:08 +0000
798@@ -0,0 +1,27 @@
799+#ifndef MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
800+#define MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
801+
802+#include <vector>
803+
804+#include "client_platform_factory.h"
805+#include "mir/shared_library.h"
806+
807+namespace mir
808+{
809+namespace client
810+{
811+class ProbingClientPlatformFactory : public ClientPlatformFactory
812+{
813+public:
814+ ProbingClientPlatformFactory(std::vector<std::shared_ptr<SharedLibrary>> const& modules);
815+
816+ std::shared_ptr<ClientPlatform> create_client_platform(ClientContext *context) override;
817+private:
818+ std::vector<std::shared_ptr<SharedLibrary>> platform_modules;
819+};
820+
821+
822+}
823+}
824+
825+#endif // MIR_CLIENT_PROBING_CLIENT_PLATFORM_FACTORY_H_
826
827=== modified file 'src/common/symbols.map'
828--- src/common/symbols.map 2014-11-21 12:16:36 +0000
829+++ src/common/symbols.map 2014-11-26 06:34:08 +0000
830@@ -150,6 +150,7 @@
831 # but they are used by libmirplatform, libmirclient or libmirserver
832 mir::default_server_socket;
833 mir::input::android::Lexicon::translate*;
834+ mir::libraries_for_path*;
835 mir::logging::input_timestamp*;
836 mir::logging::log*;
837 mir::logging::set_logger*;
838
839=== modified file 'tests/acceptance-tests/CMakeLists.txt'
840--- tests/acceptance-tests/CMakeLists.txt 2014-11-21 12:16:36 +0000
841+++ tests/acceptance-tests/CMakeLists.txt 2014-11-26 06:34:08 +0000
842@@ -6,7 +6,6 @@
843
844 add_definitions(
845 -DMIR_PLATFORM_DRIVER_BINARY="${MIR_PLATFORM_DRIVER_BINARY}"
846- -DMIR_CLIENT_DRIVER_BINARY="${MIR_CLIENT_DRIVER_BINARY}"
847 )
848
849 set(
850@@ -75,9 +74,9 @@
851 mirplatform
852
853 mir-test
854- mir-test-framework
855 mir-test-doubles
856 mir-test-doubles-platform
857+ mir-test-framework
858 3rd_party
859
860 ${PROTOBUF_LIBRARIES}
861@@ -95,8 +94,10 @@
862 "MIR_BUILD_ACCEPTANCE_TESTS"
863 OFF)
864
865+set (MIR_CLIENT_PLATFORM client-platform-dummy.so)
866+
867 if (MIR_RUN_ACCEPTANCE_TESTS)
868- mir_discover_tests(mir_acceptance_tests)
869+ mir_discover_tests(mir_acceptance_tests MIR_CLIENT_PLATFORM_LIB=${LIBRARY_OUTPUT_PATH}/${MIR_CLIENT_PLATFORM})
870 endif (MIR_RUN_ACCEPTANCE_TESTS)
871
872 install(
873
874=== modified file 'tests/acceptance-tests/test_symbols_required_by_mesa.cpp'
875--- tests/acceptance-tests/test_symbols_required_by_mesa.cpp 2014-10-29 06:21:10 +0000
876+++ tests/acceptance-tests/test_symbols_required_by_mesa.cpp 2014-11-26 06:34:08 +0000
877@@ -21,11 +21,14 @@
878
879 #include <dlfcn.h>
880
881+#include "mir_test_framework/executable_path.h"
882+
883 using namespace testing;
884+namespace mtf = mir_test_framework;
885
886-TEST(SymbolsRequiredByMesa, are_exported_by_libmirclientplatform)
887+TEST(SymbolsRequiredByMesa, are_exported_by_client_platform_mesa)
888 {
889- auto const handle = dlopen(MIR_CLIENT_DRIVER_BINARY, RTLD_LAZY);
890+ auto const handle = dlopen((mtf::library_path() + "/client-modules/mesa.so").c_str(), RTLD_LAZY);
891 ASSERT_THAT(handle, NotNull());
892
893 auto const sym = dlsym(handle, "mir_client_mesa_egl_native_display_is_valid");
894
895=== modified file 'tests/include/mir_test_doubles/mock_client_context.h'
896--- tests/include/mir_test_doubles/mock_client_context.h 2013-04-24 05:22:20 +0000
897+++ tests/include/mir_test_doubles/mock_client_context.h 2014-11-26 06:34:08 +0000
898@@ -33,18 +33,12 @@
899 struct MockClientContext : public client::ClientContext
900 {
901 MockClientContext()
902- : connection{reinterpret_cast<MirConnection*>(0xabcdef)}
903 {
904 using namespace testing;
905
906- ON_CALL(*this, mir_connection()).WillByDefault(Return(connection));
907- EXPECT_CALL(*this, mir_connection()).Times(AtLeast(0));
908 EXPECT_CALL(*this, populate(_)).Times(AtLeast(0));
909 }
910
911- MirConnection* connection;
912-
913- MOCK_METHOD0(mir_connection, MirConnection*());
914 MOCK_METHOD1(populate, void(MirPlatformPackage&));
915 };
916
917
918=== added file 'tests/include/mir_test_framework/client_platform_factory.h'
919--- tests/include/mir_test_framework/client_platform_factory.h 1970-01-01 00:00:00 +0000
920+++ tests/include/mir_test_framework/client_platform_factory.h 2014-11-26 06:34:08 +0000
921@@ -0,0 +1,72 @@
922+/*
923+ * Copyright © 2014 Canonical Ltd.
924+ *
925+ * This program is free software: you can redistribute it and/or modify
926+ * it under the terms of the GNU General Public License version 3 as
927+ * published by the Free Software Foundation.
928+ *
929+ * This program is distributed in the hope that it will be useful,
930+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
931+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
932+ * GNU General Public License for more details.
933+ *
934+ * You should have received a copy of the GNU General Public License
935+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
936+ *
937+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
938+ */
939+
940+#ifndef MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
941+#define MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
942+
943+
944+#include "mir/shared_library.h"
945+#include "src/client/client_platform_factory.h"
946+#include "executable_path.h"
947+#include "mir_test_doubles/mock_client_context.h"
948+
949+namespace mtd = mir::test::doubles;
950+
951+namespace mir_test_framework
952+{
953+std::shared_ptr<mir::SharedLibrary> platform_library;
954+
955+std::shared_ptr<mir::client::ClientPlatform> create_android_client_platform()
956+{
957+ using namespace testing;
958+ mtd::MockClientContext ctx;
959+ ON_CALL(ctx, populate(_))
960+ .WillByDefault(Invoke([](MirPlatformPackage& package) { ::memset(&package, 0, sizeof(package)); }));
961+ platform_library = std::make_shared<mir::SharedLibrary>(library_path() + "/client-modules/android.so");
962+ auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
963+ return platform_factory(&ctx);
964+}
965+
966+std::shared_ptr<mir::client::ClientPlatform> create_mesa_client_platform()
967+{
968+ using namespace testing;
969+ mtd::MockClientContext ctx;
970+ ON_CALL(ctx, populate(_))
971+ .WillByDefault(Invoke([](MirPlatformPackage& package)
972+ {
973+ ::memset(&package, 0, sizeof(package));
974+ package.fd_items = 1;
975+ }));
976+ platform_library = std::make_shared<mir::SharedLibrary>(library_path() + "/client-modules/mesa.so");
977+ auto platform_factory = platform_library->load_function<mir::client::CreateClientPlatform>("create_client_platform");
978+ return platform_factory(&ctx);
979+}
980+
981+std::shared_ptr<mir::SharedLibrary>
982+get_platform_library()
983+{
984+ if (!platform_library)
985+ {
986+ throw std::logic_error{"Must call one of create_*_client_platform() before calling get_platform_library()"};
987+ }
988+ return platform_library;
989+}
990+
991+}
992+
993+#endif // MIR_TEST_FRAMEWORK_CLIENT_PLATFORM_FACTORY_H_
994
995=== added file 'tests/include/mir_test_framework/stub_client_platform_factory.h'
996--- tests/include/mir_test_framework/stub_client_platform_factory.h 1970-01-01 00:00:00 +0000
997+++ tests/include/mir_test_framework/stub_client_platform_factory.h 2014-11-26 06:34:08 +0000
998@@ -0,0 +1,33 @@
999+/*
1000+ * Copyright © 2014 Canonical Ltd.
1001+ *
1002+ * This program is free software: you can redistribute it and/or modify it
1003+ * under the terms of the GNU General Public License version 3,
1004+ * as published by the Free Software Foundation.
1005+ *
1006+ * This program is distributed in the hope that it will be useful,
1007+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1008+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1009+ * GNU General Public License for more details.
1010+ *
1011+ * You should have received a copy of the GNU General Public License
1012+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1013+ *
1014+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1015+ */
1016+
1017+#ifndef MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_FACTORY_
1018+#define MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_FACTORY_
1019+
1020+#include "src/client/client_platform_factory.h"
1021+
1022+namespace mir_test_framework
1023+{
1024+
1025+struct StubClientPlatformFactory : public mir::client::ClientPlatformFactory
1026+{
1027+ std::shared_ptr<mir::client::ClientPlatform> create_client_platform(mir::client::ClientContext* context) override;
1028+};
1029+
1030+}
1031+#endif /* MIR_TEST_FRAMEWORK_STUB_CLIENT_PLATFORM_ */
1032
1033=== modified file 'tests/mir_test_framework/CMakeLists.txt'
1034--- tests/mir_test_framework/CMakeLists.txt 2014-11-22 11:19:02 +0000
1035+++ tests/mir_test_framework/CMakeLists.txt 2014-11-26 06:34:08 +0000
1036@@ -4,10 +4,11 @@
1037 ${PROJECT_SOURCE_DIR}/src/include/common
1038 ${PROJECT_SOURCE_DIR}/src/include/server
1039 ${PROJECT_SOURCE_DIR}/src/include/client
1040- ${Boost_INCLUDE_DIRS}
1041- ${GLESv2_INCLUDE_DIRS}
1042- ${CMAKE_SOURCE_DIR}
1043- ${UMOCKDEV_INCLUDE_DIRS}
1044+ ${Boost_INCLUDE_DIRS}
1045+ ${GLESv2_INCLUDE_DIRS}
1046+ ${CMAKE_SOURCE_DIR}
1047+ ${UMOCKDEV_INCLUDE_DIRS}
1048+ ${ANDROID_HEADERS_INCLUDE_DIRS}
1049 )
1050
1051 set(
1052@@ -31,6 +32,7 @@
1053 display_server_test_fixture.cpp
1054 process.cpp
1055 using_stub_client_platform.cpp
1056+ stub_client_platform_factory.cpp
1057 udev_environment.cpp
1058 declarative_placement_strategy.cpp
1059 fake_event_hub_server_configuration.cpp
1060@@ -67,6 +69,28 @@
1061 ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
1062 )
1063
1064+set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols-client.map)
1065+
1066+add_library(
1067+ mirclientplatformstub MODULE
1068+
1069+ stub_client_platform_module.cpp
1070+)
1071+
1072+target_link_libraries(
1073+ mirclientplatformstub
1074+
1075+ mir-test-framework
1076+ ${UMOCKDEV_LDFLAGS} ${UMOCKDEV_LIBRARIES}
1077+)
1078+
1079+set_target_properties(
1080+ mirclientplatformstub PROPERTIES;
1081+ OUTPUT_NAME client-platform-dummy
1082+ PREFIX ""
1083+ LINK_FLAGS "-Wl,--version-script,${symbol_map}"
1084+)
1085+
1086 add_custom_command(TARGET mir-test-framework POST_BUILD
1087 COMMAND ${CMAKE_COMMAND} -E copy_directory
1088 ${CMAKE_CURRENT_SOURCE_DIR}/udev_recordings ${CMAKE_BINARY_DIR}/bin/udev_recordings
1089
1090=== added file 'tests/mir_test_framework/stub_client_platform_factory.cpp'
1091--- tests/mir_test_framework/stub_client_platform_factory.cpp 1970-01-01 00:00:00 +0000
1092+++ tests/mir_test_framework/stub_client_platform_factory.cpp 2014-11-26 06:34:08 +0000
1093@@ -0,0 +1,147 @@
1094+/*
1095+ * Copyright © 2014 Canonical Ltd.
1096+ *
1097+ * This program is free software: you can redistribute it and/or modify it
1098+ * under the terms of the GNU General Public License version 3,
1099+ * as published by the Free Software Foundation.
1100+ *
1101+ * This program is distributed in the hope that it will be useful,
1102+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1103+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1104+ * GNU General Public License for more details.
1105+ *
1106+ * You should have received a copy of the GNU General Public License
1107+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1108+ *
1109+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
1110+ */
1111+
1112+#include "mir_test_framework/stub_client_platform_factory.h"
1113+#include "src/client/client_buffer_factory.h"
1114+#include "src/client/client_buffer.h"
1115+#include "src/client/client_platform.h"
1116+
1117+#include <string.h>
1118+
1119+namespace mcl = mir::client;
1120+namespace geom = mir::geometry;
1121+namespace mtf = mir_test_framework;
1122+
1123+namespace
1124+{
1125+class StubClientBuffer : public mcl::ClientBuffer
1126+{
1127+public:
1128+ StubClientBuffer(std::shared_ptr<MirBufferPackage> const& package)
1129+ {
1130+ static_cast<void>(package);
1131+#ifndef ANDROID
1132+ native = package;
1133+#endif
1134+ }
1135+
1136+ std::shared_ptr<mcl::MemoryRegion> secure_for_cpu_write()
1137+ {
1138+ return nullptr;
1139+ }
1140+
1141+ geom::Size size() const
1142+ {
1143+ return geom::Size{};
1144+ }
1145+
1146+ geom::Stride stride() const
1147+ {
1148+ return geom::Stride{};
1149+ }
1150+
1151+ MirPixelFormat pixel_format() const
1152+ {
1153+ return mir_pixel_format_abgr_8888;
1154+ }
1155+
1156+ uint32_t age() const
1157+ {
1158+ return 0;
1159+ }
1160+ void increment_age()
1161+ {
1162+ }
1163+ void mark_as_submitted()
1164+ {
1165+ }
1166+ std::shared_ptr<mir::graphics::NativeBuffer> native_buffer_handle() const
1167+ {
1168+#ifdef ANDROID
1169+ return nullptr;
1170+#else
1171+ return native;
1172+#endif
1173+ }
1174+ void update_from(MirBufferPackage const& package) override
1175+ {
1176+ static_cast<void>(package);
1177+#ifndef ANDROID
1178+ ::memcpy(native.get(), &package, sizeof(package));
1179+#endif
1180+ }
1181+private:
1182+#ifndef ANDROID
1183+ std::shared_ptr<mir::graphics::NativeBuffer> native;
1184+#endif
1185+
1186+ virtual void fill_update_msg(MirBufferPackage& /*message*/) override
1187+ {
1188+ }
1189+};
1190+
1191+struct StubClientBufferFactory : public mcl::ClientBufferFactory
1192+{
1193+ std::shared_ptr<mcl::ClientBuffer> create_buffer(std::shared_ptr<MirBufferPackage> const& package,
1194+ geom::Size, MirPixelFormat)
1195+ {
1196+ return std::make_shared<StubClientBuffer>(package);
1197+ }
1198+};
1199+
1200+struct StubClientPlatform : public mcl::ClientPlatform
1201+{
1202+ MirPlatformType platform_type() const
1203+ {
1204+ return mir_platform_type_gbm;
1205+ }
1206+
1207+ std::shared_ptr<mcl::ClientBufferFactory> create_buffer_factory()
1208+ {
1209+ return std::make_shared<StubClientBufferFactory>();
1210+ }
1211+
1212+ std::shared_ptr<EGLNativeWindowType> create_egl_native_window(mcl::ClientSurface*)
1213+ {
1214+ auto fake_window = reinterpret_cast<EGLNativeWindowType>(0x12345678lu);
1215+ return std::make_shared<EGLNativeWindowType>(fake_window);
1216+ }
1217+
1218+ std::shared_ptr<EGLNativeDisplayType> create_egl_native_display()
1219+ {
1220+ auto fake_display = reinterpret_cast<EGLNativeDisplayType>(0x12345678lu);
1221+ return std::make_shared<EGLNativeDisplayType>(fake_display);
1222+ }
1223+
1224+ MirNativeBuffer* convert_native_buffer(mir::graphics::NativeBuffer* buf) const
1225+ {
1226+ static_cast<void>(buf);
1227+#ifndef ANDROID
1228+ return buf;
1229+#else
1230+ return nullptr;
1231+#endif
1232+ }
1233+};
1234+}
1235+
1236+std::shared_ptr<mcl::ClientPlatform>
1237+mtf::StubClientPlatformFactory::create_client_platform(mcl::ClientContext*)
1238+{
1239+ return std::make_shared<StubClientPlatform>();
1240+}
1241
1242=== added file 'tests/mir_test_framework/stub_client_platform_module.cpp'
1243--- tests/mir_test_framework/stub_client_platform_module.cpp 1970-01-01 00:00:00 +0000
1244+++ tests/mir_test_framework/stub_client_platform_module.cpp 2014-11-26 06:34:08 +0000
1245@@ -0,0 +1,35 @@
1246+/*
1247+ * Copyright © 2014 Canonical Ltd.
1248+ *
1249+ * This program is free software: you can redistribute it and/or modify it
1250+ * under the terms of the GNU General Public License version 3,
1251+ * as published by the Free Software Foundation.
1252+ *
1253+ * This program is distributed in the hope that it will be useful,
1254+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1255+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1256+ * GNU General Public License for more details.
1257+ *
1258+ * You should have received a copy of the GNU General Public License
1259+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1260+ *
1261+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>>
1262+ */
1263+
1264+#include "src/client/client_platform_factory.h"
1265+
1266+#include "mir_test_framework/stub_client_platform_factory.h"
1267+#include <memory>
1268+
1269+namespace mtf = mir_test_framework;
1270+namespace mcl = mir::client;
1271+
1272+extern "C" std::shared_ptr<mcl::ClientPlatform> create_client_platform(mcl::ClientContext* context)
1273+{
1274+ return mtf::StubClientPlatformFactory{}.create_client_platform(context);
1275+}
1276+
1277+extern "C" bool is_appropriate_module(mcl::ClientContext* /*context*/)
1278+{
1279+ return true;
1280+}
1281
1282=== added file 'tests/mir_test_framework/symbols-client.map'
1283--- tests/mir_test_framework/symbols-client.map 1970-01-01 00:00:00 +0000
1284+++ tests/mir_test_framework/symbols-client.map 2014-11-26 06:34:08 +0000
1285@@ -0,0 +1,7 @@
1286+MIR_CLIENT_PLATFORM_2 {
1287+ global:
1288+ create_client_platform;
1289+ is_appropriate_module;
1290+ local:
1291+ *;
1292+};
1293
1294=== modified file 'tests/unit-tests/client/android/test_android_client_platform.cpp'
1295--- tests/unit-tests/client/android/test_android_client_platform.cpp 2014-03-06 06:05:17 +0000
1296+++ tests/unit-tests/client/android/test_android_client_platform.cpp 2014-11-26 06:34:08 +0000
1297@@ -17,9 +17,9 @@
1298 */
1299
1300 #include "src/client/client_platform.h"
1301-#include "src/client/android/client_platform_factory.h"
1302 #include "mir_test_doubles/mock_client_context.h"
1303 #include "mir_test_doubles/mock_client_surface.h"
1304+#include "mir_test_framework/client_platform_factory.h"
1305
1306 #include <EGL/egl.h>
1307
1308@@ -28,13 +28,12 @@
1309 namespace mcl = mir::client;
1310 namespace mt = mir::test;
1311 namespace mtd = mt::doubles;
1312+namespace mtf = mir_test_framework;
1313
1314 TEST(AndroidClientPlatformTest, egl_native_display_is_egl_default_display)
1315 {
1316- mtd::MockClientContext context;
1317- mcl::android::ClientPlatformFactory factory;
1318 mtd::MockClientSurface surface;
1319- auto platform = factory.create_client_platform(&context);
1320+ auto platform = mtf::create_android_client_platform();
1321 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
1322 auto native_display = platform->create_egl_native_display();
1323 EXPECT_EQ(EGL_DEFAULT_DISPLAY, *native_display);
1324@@ -42,10 +41,8 @@
1325
1326 TEST(AndroidClientPlatformTest, egl_native_window_is_set)
1327 {
1328- mtd::MockClientContext context;
1329- mcl::android::ClientPlatformFactory factory;
1330 mtd::MockClientSurface surface;
1331- auto platform = factory.create_client_platform(&context);
1332+ auto platform = mtf::create_android_client_platform();
1333 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
1334 auto egl_native_window = platform->create_egl_native_window(&surface);
1335 EXPECT_NE(nullptr, egl_native_window);
1336
1337=== modified file 'tests/unit-tests/client/mesa/test_client_platform.cpp'
1338--- tests/unit-tests/client/mesa/test_client_platform.cpp 2014-03-06 06:05:17 +0000
1339+++ tests/unit-tests/client/mesa/test_client_platform.cpp 2014-11-26 06:34:08 +0000
1340@@ -17,9 +17,9 @@
1341 */
1342
1343 #include "src/client/client_platform.h"
1344-#include "src/client/mesa/client_platform_factory.h"
1345+#include "mir/shared_library.h"
1346 #include "src/client/mesa/mesa_native_display_container.h"
1347-#include "mir_test_doubles/mock_client_context.h"
1348+#include "mir_test_framework/client_platform_factory.h"
1349 #include "mir_test_doubles/mock_client_surface.h"
1350
1351 #include "mir_toolkit/mesa/native_display.h"
1352@@ -30,19 +30,20 @@
1353 namespace mclm = mir::client::mesa;
1354 namespace mt = mir::test;
1355 namespace mtd = mir::test::doubles;
1356+namespace mtf = mir_test_framework;
1357
1358 TEST(MesaClientPlatformTest, egl_native_display_is_valid_until_released)
1359 {
1360- mtd::MockClientContext context;
1361- mclm::ClientPlatformFactory factory;
1362- auto platform = factory.create_client_platform(&context);
1363+ auto platform = mtf::create_mesa_client_platform();
1364+ auto platform_lib = mtf::get_platform_library();
1365
1366 MirMesaEGLNativeDisplay* nd;
1367 {
1368 std::shared_ptr<EGLNativeDisplayType> native_display = platform->create_egl_native_display();
1369
1370 nd = reinterpret_cast<MirMesaEGLNativeDisplay*>(*native_display);
1371- EXPECT_EQ(MIR_MESA_TRUE, mclm::mir_client_mesa_egl_native_display_is_valid(nd));
1372+ auto validate = platform_lib->load_function<MirBool(*)(MirMesaEGLNativeDisplay*)>("mir_client_mesa_egl_native_display_is_valid");
1373+ EXPECT_EQ(MIR_MESA_TRUE, validate(nd));
1374 }
1375 EXPECT_EQ(MIR_MESA_FALSE, mclm::mir_client_mesa_egl_native_display_is_valid(nd));
1376 }
1377
1378=== modified file 'tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp'
1379--- tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp 2014-03-06 06:05:17 +0000
1380+++ tests/unit-tests/client/mesa/test_mesa_native_display_container.cpp 2014-11-26 06:34:08 +0000
1381@@ -40,7 +40,7 @@
1382 }
1383
1384 std::shared_ptr<mclg::MesaNativeDisplayContainer> const container;
1385- MirConnection* connection;
1386+ mir::client::ClientContext* connection;
1387 };
1388
1389 }
1390
1391=== modified file 'tests/unit-tests/client/test_client_platform.cpp'
1392--- tests/unit-tests/client/test_client_platform.cpp 2014-03-06 06:05:17 +0000
1393+++ tests/unit-tests/client/test_client_platform.cpp 2014-11-26 06:34:08 +0000
1394@@ -20,60 +20,140 @@
1395 #include "src/client/mir_client_surface.h"
1396 #include "mir_test_doubles/mock_client_context.h"
1397 #include "mir_test_doubles/mock_client_surface.h"
1398+#include "mir_test_framework/executable_path.h"
1399
1400-#ifdef ANDROID
1401+#ifdef MIR_BUILD_PLATFORM_ANDROID
1402 #include "mir_test_doubles/mock_android_hw.h"
1403-#include "src/client/android/client_platform_factory.h"
1404-#else
1405-#include "src/client/mesa/client_platform_factory.h"
1406 #endif
1407
1408+#include "src/client/client_platform_factory.h"
1409+
1410+#include "mir/shared_library.h"
1411+
1412 #include <gmock/gmock.h>
1413 #include <gtest/gtest.h>
1414
1415 namespace mcl=mir::client;
1416 namespace mtd = mir::test::doubles;
1417-
1418-struct ClientPlatformTest : public ::testing::Test
1419-{
1420+namespace mtf = mir_test_framework;
1421+
1422+namespace
1423+{
1424+struct ClientPlatformTraits
1425+{
1426+ ClientPlatformTraits(std::string const& library,
1427+ std::function<void(MirPlatformPackage&)> populator,
1428+ MirPlatformType type)
1429+ : platform_library_name{library},
1430+ populate_package_for{populator},
1431+ platform_type{type}
1432+ {
1433+ }
1434+
1435+ std::string const platform_library_name;
1436+ std::function<void(MirPlatformPackage&)> const populate_package_for;
1437+ MirPlatformType const platform_type;
1438+};
1439+
1440+struct ClientPlatformTest : public ::testing::TestWithParam<ClientPlatformTraits const*>
1441+{
1442+ ClientPlatformTest()
1443+ : platform_library{mtf::library_path() + "/" + GetParam()->platform_library_name},
1444+ create_client_platform{platform_library.load_function<mcl::CreateClientPlatform>("create_client_platform")},
1445+ probe{platform_library.load_function<mcl::ClientPlatformProbe>("is_appropriate_module")}
1446+ {
1447+ using namespace testing;
1448+ ON_CALL(context, populate(_))
1449+ .WillByDefault(Invoke(GetParam()->populate_package_for));
1450+ }
1451+
1452 mtd::MockClientContext context;
1453-#ifdef ANDROID
1454+#ifdef MIR_BUILD_PLATFORM_ANDROID
1455 testing::NiceMock<mtd::HardwareAccessMock> hw_access_mock;
1456- mcl::android::ClientPlatformFactory factory;
1457-#else
1458- mcl::mesa::ClientPlatformFactory factory;
1459 #endif
1460+ mir::SharedLibrary platform_library;
1461+ mcl::CreateClientPlatform const create_client_platform;
1462+ mcl::ClientPlatformProbe const probe;
1463 };
1464
1465-TEST_F(ClientPlatformTest, platform_name)
1466-{
1467- auto platform = factory.create_client_platform(&context);
1468-#ifdef ANDROID
1469- auto type = mir_platform_type_android;
1470-#else
1471- auto type = mir_platform_type_gbm;
1472-#endif
1473- EXPECT_EQ(type, platform->platform_type());
1474-}
1475-
1476-TEST_F(ClientPlatformTest, platform_creates)
1477-{
1478- auto platform = factory.create_client_platform(&context);
1479+#ifdef MIR_BUILD_PLATFORM_ANDROID
1480+ClientPlatformTraits const android_platform{"/client-modules/android.so",
1481+ [](MirPlatformPackage& pkg)
1482+ {
1483+ ::memset(&pkg, 0, sizeof(pkg));
1484+ },
1485+ mir_platform_type_android
1486+ };
1487+
1488+INSTANTIATE_TEST_CASE_P(Android,
1489+ ClientPlatformTest,
1490+ ::testing::Values(&android_platform));
1491+
1492+#endif
1493+
1494+#ifdef MIR_BUILD_PLATFORM_MESA
1495+ClientPlatformTraits const mesa_platform{"/client-modules/mesa.so",
1496+ [](MirPlatformPackage& pkg)
1497+ {
1498+ ::memset(&pkg, 0, sizeof(pkg));
1499+ pkg.fd_items = 1;
1500+ },
1501+ mir_platform_type_gbm
1502+ };
1503+
1504+INSTANTIATE_TEST_CASE_P(Mesa,
1505+ ClientPlatformTest,
1506+ ::testing::Values(&mesa_platform));
1507+
1508+#endif
1509+}
1510+
1511+TEST_P(ClientPlatformTest, platform_name)
1512+{
1513+ auto platform = create_client_platform(&context);
1514+
1515+ EXPECT_EQ(GetParam()->platform_type, platform->platform_type());
1516+}
1517+
1518+TEST_P(ClientPlatformTest, platform_creates)
1519+{
1520+ auto platform = create_client_platform(&context);
1521 auto buffer_factory = platform->create_buffer_factory();
1522 EXPECT_NE(buffer_factory.get(), (mcl::ClientBufferFactory*) NULL);
1523 }
1524
1525-TEST_F(ClientPlatformTest, platform_creates_native_window)
1526+TEST_P(ClientPlatformTest, platform_creates_native_window)
1527 {
1528- auto platform = factory.create_client_platform(&context);
1529+ auto platform = create_client_platform(&context);
1530 auto mock_client_surface = std::make_shared<mtd::MockClientSurface>();
1531 auto native_window = platform->create_egl_native_window(mock_client_surface.get());
1532 EXPECT_NE(*native_window, (EGLNativeWindowType) NULL);
1533 }
1534
1535-TEST_F(ClientPlatformTest, platform_creates_egl_native_display)
1536+TEST_P(ClientPlatformTest, platform_creates_egl_native_display)
1537 {
1538- auto platform = factory.create_client_platform(&context);
1539+ auto platform = create_client_platform(&context);
1540 auto native_display = platform->create_egl_native_display();
1541 EXPECT_NE(nullptr, native_display.get());
1542 }
1543+
1544+TEST_P(ClientPlatformTest, platform_probe_returns_success_when_matching)
1545+{
1546+ EXPECT_TRUE(probe(&context));
1547+}
1548+
1549+TEST_P(ClientPlatformTest, platform_probe_returns_false_when_not_matching)
1550+{
1551+ using namespace testing;
1552+ ON_CALL(context, populate(_))
1553+ .WillByDefault(Invoke([](MirPlatformPackage& pkg)
1554+ {
1555+ //Mock up something that hopefully looks nothing like
1556+ //what the platform is expecting...
1557+ ::memset(&pkg, 0, sizeof(pkg));
1558+ pkg.data_items = 0xdeadbeef;
1559+ pkg.fd_items = -23;
1560+ }));
1561+
1562+ EXPECT_FALSE(probe(&context));
1563+}
1564
1565=== modified file 'tests/unit-tests/shared_library_test.cpp'
1566--- tests/unit-tests/shared_library_test.cpp 2014-10-29 06:21:10 +0000
1567+++ tests/unit-tests/shared_library_test.cpp 2014-11-26 06:34:08 +0000
1568@@ -59,10 +59,10 @@
1569 public:
1570 SharedLibrary()
1571 : nonexistent_library{"imma_totally_not_a_library"},
1572- existing_library{mtf::library_path() + "/" MIR_CLIENT_DRIVER_BINARY},
1573+ existing_library{mtf::library_path() + "/client-modules/mesa.so"},
1574 nonexistent_function{"yo_dawg"},
1575- existing_function{"create_client_platform_factory"},
1576- existent_version{"MIR_CLIENTPLATFORM_1"},
1577+ existing_function{"create_client_platform"},
1578+ existent_version{"MIR_CLIENT_PLATFORM_2"},
1579 nonexistent_version{"GOATS_ON_THE_GREEN"}
1580 {
1581 }

Subscribers

People subscribed via source and target branches