Merge lp:~raof/mir/a-little-more-error-checkin into lp:mir
- a-little-more-error-checkin
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alberto Aguirre |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2039 |
Proposed branch: | lp:~raof/mir/a-little-more-error-checkin |
Merge into: | lp:mir |
Diff against target: |
1196 lines (+659/-157) 18 files modified
src/client/mir_connection.cpp (+8/-0) src/client/mir_connection_api.cpp (+12/-4) src/client/mir_connection_api.h (+5/-1) src/client/mir_surface.cpp (+45/-12) src/client/mir_surface.h (+2/-0) src/client/mir_surface_api.cpp (+7/-3) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_client_library.cpp (+0/-38) tests/acceptance-tests/test_client_library_errors.cpp (+338/-0) tests/acceptance-tests/test_server_disconnect.cpp (+4/-1) tests/include/mir_test/stub_server_tool.h (+8/-1) tests/include/mir_test/validity_matchers.h (+64/-0) tests/include/mir_test_framework/using_stub_client_platform.h (+61/-17) tests/integration-tests/client/test_client_render.cpp (+7/-1) tests/integration-tests/test_error_reporting.cpp (+49/-34) tests/mir_test/CMakeLists.txt (+1/-0) tests/mir_test/validity_matchers.cpp (+32/-0) tests/mir_test_framework/using_stub_client_platform.cpp (+15/-45) |
To merge this branch: | bzr merge lp:~raof/mir/a-little-more-error-checkin |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alberto Aguirre (community) | Approve | ||
Alan Griffiths | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Robert Carr (community) | Needs Information | ||
Review via email: mp+232508@code.launchpad.net |
Commit message
Improve error checking and reporting for the client library.
Description of the change
Some more miscellaneous error checking niceties that would have been great to have while developing privatise-
This starts fleshing out the error handling policy I think we settled on in London - *create calls always return a non-null object, but passing error objects to any method other than *_is_valid or *_release is fatal.
Oh, and it also fixes UsingStubClient
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1876
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1878
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1880
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1881
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : | # |
661, 672. Maybe use the new validity matchers here?
Chris Halse Rogers (raof) wrote : | # |
Move to WIP - I can do this better with a real stub platform.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1883
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
538 +TEST_F(
this_is_
Chris Halse Rogers (raof) wrote : | # |
Man, I hope gtest never does anything would break test_names_
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1884
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1884
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1885
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
I am confused as to why “make test” doesn't catch these failures locally. Anyway, let's try this again.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1886
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
67 + return mir_connection_
Looks horrible. But I don't have a better suggestion in mind.
Preview Diff
1 | === modified file 'src/client/mir_connection.cpp' |
2 | --- src/client/mir_connection.cpp 2014-11-03 19:06:48 +0000 |
3 | +++ src/client/mir_connection.cpp 2014-11-05 22:26:46 +0000 |
4 | @@ -34,6 +34,8 @@ |
5 | #include <unistd.h> |
6 | #include <signal.h> |
7 | |
8 | +#include <boost/exception/diagnostic_information.hpp> |
9 | + |
10 | namespace mcl = mir::client; |
11 | namespace mircv = mir::input::receiver; |
12 | namespace gp = google::protobuf; |
13 | @@ -219,6 +221,7 @@ |
14 | void MirConnection::connected(mir_connected_callback callback, void * context) |
15 | { |
16 | bool safe_to_callback = true; |
17 | + try |
18 | { |
19 | std::lock_guard<decltype(mutex)> lock(mutex); |
20 | |
21 | @@ -262,6 +265,11 @@ |
22 | display_configuration->set_configuration(connect_result.display_configuration()); |
23 | lifecycle_control->set_lifecycle_event_handler(default_lifecycle_event_handler); |
24 | } |
25 | + catch (std::exception const& e) |
26 | + { |
27 | + connect_result.set_error(std::string{"Failed to process connect response: "} + |
28 | + boost::diagnostic_information(e)); |
29 | + } |
30 | |
31 | if (safe_to_callback) callback(this, context); |
32 | connect_wait_handle.result_received(); |
33 | |
34 | === modified file 'src/client/mir_connection_api.cpp' |
35 | --- src/client/mir_connection_api.cpp 2014-10-01 06:25:56 +0000 |
36 | +++ src/client/mir_connection_api.cpp 2014-11-05 22:26:46 +0000 |
37 | @@ -53,6 +53,7 @@ |
38 | { |
39 | public: |
40 | MirWaitHandle* connect( |
41 | + mcl::ConfigurationFactory configuration, |
42 | char const* socket_file, |
43 | char const* name, |
44 | mir_connected_callback callback, |
45 | @@ -112,10 +113,13 @@ |
46 | delete connection; |
47 | } |
48 | |
49 | - std::unique_ptr<mcl::ConnectionConfiguration> configuration(std::string const& socket) override |
50 | + mcl::ConfigurationFactory configuration_factory() override |
51 | { |
52 | - return std::unique_ptr<mcl::ConnectionConfiguration>{ |
53 | - new mcl::DefaultConnectionConfiguration{socket}}; |
54 | + return [](std::string const& socket) { |
55 | + return std::unique_ptr<mcl::ConnectionConfiguration>{ |
56 | + new mcl::DefaultConnectionConfiguration{socket} |
57 | + }; |
58 | + }; |
59 | } |
60 | }; |
61 | |
62 | @@ -132,7 +136,11 @@ |
63 | { |
64 | try |
65 | { |
66 | - return mir_connection_api_impl->connect(socket_file, name, callback, context); |
67 | + return mir_connection_api_impl->connect(mir_connection_api_impl->configuration_factory(), |
68 | + socket_file, |
69 | + name, |
70 | + callback, |
71 | + context); |
72 | } |
73 | catch (std::exception const&) |
74 | { |
75 | |
76 | === modified file 'src/client/mir_connection_api.h' |
77 | --- src/client/mir_connection_api.h 2014-10-01 06:25:56 +0000 |
78 | +++ src/client/mir_connection_api.h 2014-11-05 22:26:46 +0000 |
79 | @@ -23,6 +23,7 @@ |
80 | |
81 | #include <string> |
82 | #include <memory> |
83 | +#include <functional> |
84 | |
85 | namespace mir |
86 | { |
87 | @@ -30,12 +31,15 @@ |
88 | { |
89 | class ConnectionConfiguration; |
90 | |
91 | +using ConfigurationFactory = std::function<std::unique_ptr<ConnectionConfiguration>(std::string const&)>; |
92 | + |
93 | class MirConnectionAPI |
94 | { |
95 | public: |
96 | virtual ~MirConnectionAPI() = default; |
97 | |
98 | virtual MirWaitHandle* connect( |
99 | + ConfigurationFactory configuration, |
100 | char const* socket_file, |
101 | char const* name, |
102 | mir_connected_callback callback, |
103 | @@ -43,7 +47,7 @@ |
104 | |
105 | virtual void release(MirConnection* connection) = 0; |
106 | |
107 | - virtual std::unique_ptr<ConnectionConfiguration> configuration(std::string const& socket) = 0; |
108 | + virtual ConfigurationFactory configuration_factory() = 0; |
109 | |
110 | protected: |
111 | MirConnectionAPI() = default; |
112 | |
113 | === modified file 'src/client/mir_surface.cpp' |
114 | --- src/client/mir_surface.cpp 2014-10-28 22:48:39 +0000 |
115 | +++ src/client/mir_surface.cpp 2014-11-05 22:26:46 +0000 |
116 | @@ -30,6 +30,8 @@ |
117 | #include <cassert> |
118 | #include <unistd.h> |
119 | |
120 | +#include <boost/exception/diagnostic_information.hpp> |
121 | + |
122 | namespace geom = mir::geometry; |
123 | namespace mcl = mir::client; |
124 | namespace mircv = mir::input::receiver; |
125 | @@ -39,11 +41,22 @@ |
126 | namespace |
127 | { |
128 | void null_callback(MirSurface*, void*) {} |
129 | +mp::DisplayServer::Stub null_server{nullptr}; |
130 | |
131 | std::mutex handle_mutex; |
132 | std::unordered_set<MirSurface*> valid_surfaces; |
133 | } |
134 | |
135 | +MirSurface::MirSurface(std::string const& error) |
136 | + : server{null_server}, |
137 | + connection{nullptr} |
138 | +{ |
139 | + surface.set_error(error); |
140 | + |
141 | + std::lock_guard<decltype(handle_mutex)> lock(handle_mutex); |
142 | + valid_surfaces.insert(this); |
143 | +} |
144 | + |
145 | MirSurface::MirSurface( |
146 | MirConnection *allocating_connection, |
147 | mp::DisplayServer::Stub & server, |
148 | @@ -258,20 +271,29 @@ |
149 | { |
150 | auto platform = connection->get_client_platform(); |
151 | |
152 | + try |
153 | { |
154 | - std::lock_guard<decltype(mutex)> lock(mutex); |
155 | - |
156 | - process_incoming_buffer(); |
157 | - accelerated_window = platform->create_egl_native_window(this); |
158 | - |
159 | - for(int i = 0; i < surface.attributes_size(); i++) |
160 | { |
161 | - auto const& attrib = surface.attributes(i); |
162 | - attrib_cache[attrib.attrib()] = attrib.ivalue(); |
163 | + std::lock_guard<decltype(mutex)> lock(mutex); |
164 | + |
165 | + process_incoming_buffer(); |
166 | + accelerated_window = platform->create_egl_native_window(this); |
167 | + |
168 | + for(int i = 0; i < surface.attributes_size(); i++) |
169 | + { |
170 | + auto const& attrib = surface.attributes(i); |
171 | + attrib_cache[attrib.attrib()] = attrib.ivalue(); |
172 | + } |
173 | } |
174 | - } |
175 | - |
176 | - connection->on_surface_created(id(), this); |
177 | + |
178 | + connection->on_surface_created(id(), this); |
179 | + } |
180 | + catch (std::exception const& error) |
181 | + { |
182 | + surface.set_error(std::string{"Error processing Surface creating response:"} + |
183 | + boost::diagnostic_information(error)); |
184 | + } |
185 | + |
186 | callback(this, context); |
187 | create_wait_handle.result_received(); |
188 | } |
189 | @@ -296,7 +318,18 @@ |
190 | valid_surfaces.erase(this); |
191 | } |
192 | |
193 | - return connection->release_surface(this, callback, context); |
194 | + MirWaitHandle* wait_handle{nullptr}; |
195 | + if (connection) |
196 | + { |
197 | + wait_handle = connection->release_surface(this, callback, context); |
198 | + } |
199 | + else |
200 | + { |
201 | + callback(this, context); |
202 | + delete this; |
203 | + } |
204 | + |
205 | + return wait_handle; |
206 | } |
207 | |
208 | MirNativeBuffer* MirSurface::get_current_buffer_package() |
209 | |
210 | === modified file 'src/client/mir_surface.h' |
211 | --- src/client/mir_surface.h 2014-10-27 22:31:16 +0000 |
212 | +++ src/client/mir_surface.h 2014-11-05 22:26:46 +0000 |
213 | @@ -59,6 +59,8 @@ |
214 | MirSurface(MirSurface const &) = delete; |
215 | MirSurface& operator=(MirSurface const &) = delete; |
216 | |
217 | + MirSurface(std::string const& error); |
218 | + |
219 | MirSurface( |
220 | MirConnection *allocating_connection, |
221 | mir::protobuf::DisplayServer::Stub & server, |
222 | |
223 | === modified file 'src/client/mir_surface_api.cpp' |
224 | --- src/client/mir_surface_api.cpp 2014-10-27 22:31:16 +0000 |
225 | +++ src/client/mir_surface_api.cpp 2014-11-05 22:26:46 +0000 |
226 | @@ -23,6 +23,8 @@ |
227 | #include "mir_surface.h" |
228 | #include "error_connections.h" |
229 | |
230 | +#include <boost/exception/diagnostic_information.hpp> |
231 | + |
232 | namespace mcl = mir::client; |
233 | |
234 | namespace |
235 | @@ -43,15 +45,17 @@ |
236 | mir_surface_callback callback, |
237 | void* context) |
238 | { |
239 | - if (mcl::ErrorConnections::instance().contains(connection)) return 0; |
240 | + if (!mir_connection_is_valid(connection)) abort(); |
241 | |
242 | try |
243 | { |
244 | return connection->create_surface(*params, callback, context); |
245 | } |
246 | - catch (std::exception const&) |
247 | + catch (std::exception const& error) |
248 | { |
249 | - // TODO callback with an error surface |
250 | + auto error_surf = new MirSurface{std::string{"Failed to create surface: "} + |
251 | + boost::diagnostic_information(error)}; |
252 | + (*callback)(error_surf, context); |
253 | return nullptr; |
254 | } |
255 | } |
256 | |
257 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
258 | --- tests/acceptance-tests/CMakeLists.txt 2014-11-03 19:06:48 +0000 |
259 | +++ tests/acceptance-tests/CMakeLists.txt 2014-11-05 22:26:46 +0000 |
260 | @@ -17,6 +17,7 @@ |
261 | server_signal_handling.cpp |
262 | clients.cpp |
263 | test_client_library.cpp |
264 | + test_client_library_errors.cpp |
265 | test_client_library_old.cpp |
266 | test_client_surface_events.cpp |
267 | test_client_surface_swap_buffers.cpp |
268 | |
269 | === modified file 'tests/acceptance-tests/test_client_library.cpp' |
270 | --- tests/acceptance-tests/test_client_library.cpp 2014-10-29 10:11:50 +0000 |
271 | +++ tests/acceptance-tests/test_client_library.cpp 2014-11-05 22:26:46 +0000 |
272 | @@ -53,8 +53,6 @@ |
273 | { |
274 | struct ClientLibrary : mtf::HeadlessInProcessServer |
275 | { |
276 | - mtf::UsingStubClientPlatform using_stub_client_platform; |
277 | - |
278 | std::set<MirSurface*> surfaces; |
279 | MirConnection* connection = nullptr; |
280 | MirSurface* surface = nullptr; |
281 | @@ -597,42 +595,6 @@ |
282 | mir_connection_release(connection); |
283 | } |
284 | |
285 | -TEST_F(ClientLibrary, connect_errors_handled) |
286 | -{ |
287 | - mir_wait_for(mir_connect("garbage", __PRETTY_FUNCTION__, connection_callback, this)); |
288 | - ASSERT_THAT(connection, NotNull()); |
289 | - |
290 | - char const* error = mir_connection_get_error_message(connection); |
291 | - |
292 | - if (std::strcmp("connect: No such file or directory", error) && |
293 | - std::strcmp("Can't find MIR server", error) && |
294 | - !std::strstr(error, "Failed to connect to server socket")) |
295 | - { |
296 | - FAIL() << error; |
297 | - } |
298 | -} |
299 | - |
300 | -TEST_F(ClientLibrary, connect_errors_dont_blow_up) |
301 | -{ |
302 | - mir_wait_for(mir_connect("garbage", __PRETTY_FUNCTION__, connection_callback, this)); |
303 | - |
304 | - MirSurfaceParameters const request_params = |
305 | - { |
306 | - __PRETTY_FUNCTION__, |
307 | - 640, 480, |
308 | - mir_pixel_format_abgr_8888, |
309 | - mir_buffer_usage_hardware, |
310 | - mir_display_output_id_invalid |
311 | - }; |
312 | - |
313 | - mir_wait_for(mir_connection_create_surface(connection, &request_params, create_surface_callback, this)); |
314 | -// TODO surface_create needs to fail safe too. After that is done we should add the following: |
315 | -// TODO mir_wait_for(mir_surface_swap_buffers(surface, next_buffer_callback, this)); |
316 | -// TODO mir_wait_for(mir_surface_release( surface, release_surface_callback, this)); |
317 | - |
318 | - mir_connection_release(connection); |
319 | -} |
320 | - |
321 | TEST_F(ClientLibrary, MultiSurfaceClientTracksBufferFdsCorrectly) |
322 | { |
323 | mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this)); |
324 | |
325 | === added file 'tests/acceptance-tests/test_client_library_errors.cpp' |
326 | --- tests/acceptance-tests/test_client_library_errors.cpp 1970-01-01 00:00:00 +0000 |
327 | +++ tests/acceptance-tests/test_client_library_errors.cpp 2014-11-05 22:26:46 +0000 |
328 | @@ -0,0 +1,338 @@ |
329 | +/* |
330 | + * Copyright © 2014 Canonical Ltd. |
331 | + * |
332 | + * This program is free software: you can redistribute it and/or modify |
333 | + * it under the terms of the GNU General Public License version 3 as |
334 | + * published by the Free Software Foundation. |
335 | + * |
336 | + * This program is distributed in the hope that it will be useful, |
337 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
338 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
339 | + * GNU General Public License for more details. |
340 | + * |
341 | + * You should have received a copy of the GNU General Public License |
342 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
343 | + * |
344 | + * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> |
345 | + */ |
346 | + |
347 | +#include "mir_toolkit/mir_client_library.h" |
348 | +#include "mir_toolkit/debug/surface.h" |
349 | + |
350 | +#include "src/client/client_platform_factory.h" |
351 | +#include "src/client/client_platform.h" |
352 | +#include "src/client/client_buffer_factory.h" |
353 | + |
354 | +#include "mir_test/validity_matchers.h" |
355 | + |
356 | +#include "mir_test_framework/in_process_server.h" |
357 | +#include "mir_test_framework/stubbed_server_configuration.h" |
358 | +#include "mir_test_framework/using_stub_client_platform.h" |
359 | +#include "mir_test_framework/stub_client_connection_configuration.h" |
360 | + |
361 | +#include <gtest/gtest.h> |
362 | +#include <gmock/gmock.h> |
363 | + |
364 | +#include <stdexcept> |
365 | +#include <boost/throw_exception.hpp> |
366 | +#include <cstring> |
367 | + |
368 | +namespace mcl = mir::client; |
369 | +namespace mtf = mir_test_framework; |
370 | + |
371 | +namespace |
372 | +{ |
373 | +enum Method : uint64_t |
374 | +{ |
375 | + none = 0, |
376 | + the_client_platform_factory = 1<<0, |
377 | + create_client_platform = 1<<1, |
378 | + create_egl_native_window = 1<<2, |
379 | + create_buffer_factory = 1<<3 |
380 | +}; |
381 | + |
382 | +std::string const exception_text{"Ducks!"}; |
383 | + |
384 | +template<Method name, Method failure_set> |
385 | +bool should_fail() |
386 | +{ |
387 | + return (name & failure_set); |
388 | +} |
389 | + |
390 | +class StubClientBufferFactory : public mir::client::ClientBufferFactory |
391 | +{ |
392 | + std::shared_ptr<mir::client::ClientBuffer> create_buffer(const std::shared_ptr<MirBufferPackage>&, |
393 | + mir::geometry::Size, |
394 | + MirPixelFormat) |
395 | + { |
396 | + return std::shared_ptr<mir::client::ClientBuffer>{}; |
397 | + } |
398 | +}; |
399 | + |
400 | +template<Method failure_set> |
401 | +class ConfigurableFailurePlatform : public mir::client::ClientPlatform |
402 | +{ |
403 | + std::shared_ptr<EGLNativeWindowType> create_egl_native_window(mir::client::ClientSurface *) |
404 | + { |
405 | + if (should_fail<Method::create_egl_native_window, failure_set>()) |
406 | + { |
407 | + BOOST_THROW_EXCEPTION(std::runtime_error{exception_text}); |
408 | + } |
409 | + return std::shared_ptr<EGLNativeWindowType>{}; |
410 | + } |
411 | + MirPlatformType platform_type() const |
412 | + { |
413 | + BOOST_THROW_EXCEPTION(std::runtime_error{exception_text}); |
414 | + return MirPlatformType::mir_platform_type_gbm; |
415 | + } |
416 | + std::shared_ptr<mir::client::ClientBufferFactory> create_buffer_factory() |
417 | + { |
418 | + if (should_fail<Method::create_buffer_factory, failure_set>()) |
419 | + { |
420 | + BOOST_THROW_EXCEPTION(std::runtime_error{exception_text}); |
421 | + } |
422 | + return std::make_shared<StubClientBufferFactory>(); |
423 | + } |
424 | + std::shared_ptr<EGLNativeDisplayType> create_egl_native_display() |
425 | + { |
426 | + return std::shared_ptr<EGLNativeDisplayType>{}; |
427 | + } |
428 | + MirNativeBuffer *convert_native_buffer(mir::graphics::NativeBuffer*) const |
429 | + { |
430 | + BOOST_THROW_EXCEPTION(std::runtime_error{exception_text}); |
431 | + return nullptr; |
432 | + } |
433 | +}; |
434 | + |
435 | +template<Method failure_set> |
436 | +class ConfigurableFailureFactory: public mir::client::ClientPlatformFactory |
437 | +{ |
438 | + std::shared_ptr<mir::client::ClientPlatform> |
439 | + create_client_platform(mir::client::ClientContext* /*context*/) override |
440 | + { |
441 | + if (should_fail<Method::create_client_platform, failure_set>()) |
442 | + { |
443 | + BOOST_THROW_EXCEPTION(std::runtime_error{exception_text}); |
444 | + } |
445 | + return std::make_shared<ConfigurableFailurePlatform<failure_set>>(); |
446 | + } |
447 | +}; |
448 | + |
449 | +template<Method failure_set> |
450 | +class ConfigurableFailureConfiguration : public mtf::StubConnectionConfiguration |
451 | +{ |
452 | + using mtf::StubConnectionConfiguration::StubConnectionConfiguration; |
453 | + |
454 | + std::shared_ptr<mir::client::ClientPlatformFactory> the_client_platform_factory() override |
455 | + { |
456 | + if (should_fail<Method::the_client_platform_factory, failure_set>()) |
457 | + { |
458 | + BOOST_THROW_EXCEPTION(std::runtime_error{exception_text}); |
459 | + } |
460 | + return std::make_shared<ConfigurableFailureFactory<failure_set>>(); |
461 | + } |
462 | +}; |
463 | + |
464 | +class ClientLibraryErrors : public mtf::InProcessServer |
465 | +{ |
466 | +private: |
467 | + mtf::StubbedServerConfiguration config; |
468 | + |
469 | + mir::DefaultServerConfiguration &server_config() override |
470 | + { |
471 | + return config; |
472 | + } |
473 | +}; |
474 | +} |
475 | + |
476 | +TEST_F(ClientLibraryErrors, exception_in_client_configuration_constructor_generates_error) |
477 | +{ |
478 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::the_client_platform_factory>> stubby; |
479 | + |
480 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
481 | + |
482 | + EXPECT_FALSE(mir_connection_is_valid(connection)); |
483 | + EXPECT_THAT(mir_connection_get_error_message(connection), testing::HasSubstr(exception_text)); |
484 | + mir_connection_release(connection); |
485 | +} |
486 | + |
487 | +TEST_F(ClientLibraryErrors, exception_in_platform_construction_generates_error) |
488 | +{ |
489 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_client_platform>> stubby; |
490 | + |
491 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
492 | + |
493 | + EXPECT_FALSE(mir_connection_is_valid(connection)); |
494 | + EXPECT_THAT(mir_connection_get_error_message(connection), testing::HasSubstr(exception_text)); |
495 | + mir_connection_release(connection); |
496 | +} |
497 | + |
498 | +TEST_F(ClientLibraryErrors, connecting_to_garbage_socket_returns_appropriate_error) |
499 | +{ |
500 | + using namespace testing; |
501 | + mtf::UsingStubClientPlatform stubby; |
502 | + |
503 | + auto connection = mir_connect_sync("garbage", __PRETTY_FUNCTION__); |
504 | + ASSERT_THAT(connection, NotNull()); |
505 | + |
506 | + char const* error = mir_connection_get_error_message(connection); |
507 | + |
508 | + if (std::strcmp("connect: No such file or directory", error) && |
509 | + std::strcmp("Can't find MIR server", error) && |
510 | + !std::strstr(error, "Failed to connect to server socket")) |
511 | + { |
512 | + FAIL() << error; |
513 | + } |
514 | + mir_connection_release(connection); |
515 | +} |
516 | + |
517 | +TEST_F(ClientLibraryErrors, create_surface_returns_error_object_on_failure) |
518 | +{ |
519 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_buffer_factory>> stubby; |
520 | + |
521 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
522 | + |
523 | + ASSERT_THAT(connection, IsValid()); |
524 | + |
525 | + MirSurfaceParameters const request_params = |
526 | + { |
527 | + __PRETTY_FUNCTION__, |
528 | + 640, 480, |
529 | + mir_pixel_format_abgr_8888, |
530 | + mir_buffer_usage_hardware, |
531 | + mir_display_output_id_invalid |
532 | + }; |
533 | + |
534 | + auto surface = mir_connection_create_surface_sync(connection, &request_params); |
535 | + ASSERT_NE(surface, nullptr); |
536 | + EXPECT_FALSE(mir_surface_is_valid(surface)); |
537 | + EXPECT_THAT(mir_surface_get_error_message(surface), testing::HasSubstr(exception_text)); |
538 | + |
539 | + mir_surface_release_sync(surface); |
540 | + mir_connection_release(connection); |
541 | +} |
542 | + |
543 | +namespace |
544 | +{ |
545 | +void recording_surface_callback(MirSurface*, void* ctx) |
546 | +{ |
547 | + auto called = static_cast<bool*>(ctx); |
548 | + *called = true; |
549 | +} |
550 | +} |
551 | + |
552 | +TEST_F(ClientLibraryErrors, surface_release_on_error_object_still_calls_callback) |
553 | +{ |
554 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_buffer_factory>> stubby; |
555 | + |
556 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
557 | + |
558 | + ASSERT_THAT(connection, IsValid()); |
559 | + |
560 | + MirSurfaceParameters const request_params = |
561 | + { |
562 | + __PRETTY_FUNCTION__, |
563 | + 640, 480, |
564 | + mir_pixel_format_abgr_8888, |
565 | + mir_buffer_usage_hardware, |
566 | + mir_display_output_id_invalid |
567 | + }; |
568 | + |
569 | + auto surface = mir_connection_create_surface_sync(connection, &request_params); |
570 | + ASSERT_NE(surface, nullptr); |
571 | + EXPECT_FALSE(mir_surface_is_valid(surface)); |
572 | + EXPECT_THAT(mir_surface_get_error_message(surface), testing::HasSubstr(exception_text)); |
573 | + |
574 | + bool callback_called{false}; |
575 | + mir_surface_release(surface, &recording_surface_callback, &callback_called); |
576 | + EXPECT_TRUE(callback_called); |
577 | + mir_connection_release(connection); |
578 | +} |
579 | + |
580 | + |
581 | +TEST_F(ClientLibraryErrors, create_surface_returns_error_object_on_failure_in_reply_processing) |
582 | +{ |
583 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_egl_native_window>> stubby; |
584 | + |
585 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
586 | + |
587 | + ASSERT_THAT(connection, IsValid()); |
588 | + |
589 | + MirSurfaceParameters const request_params = |
590 | + { |
591 | + __PRETTY_FUNCTION__, |
592 | + 640, 480, |
593 | + mir_pixel_format_abgr_8888, |
594 | + mir_buffer_usage_hardware, |
595 | + mir_display_output_id_invalid |
596 | + }; |
597 | + |
598 | + auto surface = mir_connection_create_surface_sync(connection, &request_params); |
599 | + ASSERT_NE(surface, nullptr); |
600 | + EXPECT_FALSE(mir_surface_is_valid(surface)); |
601 | + EXPECT_THAT(mir_surface_get_error_message(surface), testing::HasSubstr(exception_text)); |
602 | + |
603 | + mir_surface_release_sync(surface); |
604 | + mir_connection_release(connection); |
605 | +} |
606 | + |
607 | +using ClientLibraryErrorsDeathTest = ClientLibraryErrors; |
608 | + |
609 | + |
610 | +TEST_F(ClientLibraryErrorsDeathTest, createing_surface_on_garbage_connection_is_fatal) |
611 | +{ |
612 | + mtf::UsingStubClientPlatform stubby; |
613 | + |
614 | + auto connection = mir_connect_sync("garbage", __PRETTY_FUNCTION__); |
615 | + |
616 | + MirSurfaceParameters const request_params = |
617 | + { |
618 | + __PRETTY_FUNCTION__, |
619 | + 640, 480, |
620 | + mir_pixel_format_abgr_8888, |
621 | + mir_buffer_usage_hardware, |
622 | + mir_display_output_id_invalid |
623 | + }; |
624 | + |
625 | + ASSERT_FALSE(mir_connection_is_valid(connection)); |
626 | + EXPECT_DEATH(mir_connection_create_surface_sync(connection, &request_params), ""); |
627 | +} |
628 | + |
629 | + |
630 | +TEST_F(ClientLibraryErrorsDeathTest, creating_surface_synchronosly_on_malconstructed_connection_is_fatal) |
631 | +{ |
632 | + MirSurfaceParameters const request_params = |
633 | + { |
634 | + __PRETTY_FUNCTION__, |
635 | + 640, 480, |
636 | + mir_pixel_format_abgr_8888, |
637 | + mir_buffer_usage_hardware, |
638 | + mir_display_output_id_invalid |
639 | + }; |
640 | + |
641 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::the_client_platform_factory>> stubby; |
642 | + |
643 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
644 | + |
645 | + ASSERT_FALSE(mir_connection_is_valid(connection)); |
646 | + EXPECT_DEATH(mir_connection_create_surface_sync(connection, &request_params), ""); |
647 | +} |
648 | + |
649 | +TEST_F(ClientLibraryErrorsDeathTest, creating_surface_synchronosly_on_invalid_connection_is_fatal) |
650 | +{ |
651 | + MirSurfaceParameters const request_params = |
652 | + { |
653 | + __PRETTY_FUNCTION__, |
654 | + 640, 480, |
655 | + mir_pixel_format_abgr_8888, |
656 | + mir_buffer_usage_hardware, |
657 | + mir_display_output_id_invalid |
658 | + }; |
659 | + |
660 | + mtf::UsingClientPlatform<ConfigurableFailureConfiguration<Method::create_client_platform>> stubby; |
661 | + |
662 | + auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
663 | + |
664 | + ASSERT_FALSE(mir_connection_is_valid(connection)); |
665 | + EXPECT_DEATH(mir_connection_create_surface_sync(connection, &request_params), ""); |
666 | +} |
667 | |
668 | === modified file 'tests/acceptance-tests/test_server_disconnect.cpp' |
669 | --- tests/acceptance-tests/test_server_disconnect.cpp 2014-10-01 06:25:56 +0000 |
670 | +++ tests/acceptance-tests/test_server_disconnect.cpp 2014-11-05 22:26:46 +0000 |
671 | @@ -107,7 +107,7 @@ |
672 | mir_buffer_usage_hardware, |
673 | mir_display_output_id_invalid |
674 | }; |
675 | - mir_connection_create_surface_sync(connection, ¶meters); |
676 | + surf = mir_connection_create_surface_sync(connection, ¶meters); |
677 | }); |
678 | |
679 | configure_display.exec([&] { |
680 | @@ -117,6 +117,7 @@ |
681 | }); |
682 | |
683 | disconnect.exec([&] { |
684 | + mir_surface_release_sync(surf); |
685 | mir_connection_release(connection); |
686 | }); |
687 | } |
688 | @@ -129,6 +130,8 @@ |
689 | mt::CrossProcessAction create_surface; |
690 | mt::CrossProcessAction configure_display; |
691 | mt::CrossProcessAction disconnect; |
692 | +private: |
693 | + MirSurface* surf; |
694 | }; |
695 | |
696 | /* |
697 | |
698 | === modified file 'tests/include/mir_test/stub_server_tool.h' |
699 | --- tests/include/mir_test/stub_server_tool.h 2014-10-01 06:25:56 +0000 |
700 | +++ tests/include/mir_test/stub_server_tool.h 2014-11-05 22:26:46 +0000 |
701 | @@ -86,7 +86,14 @@ |
702 | ::google::protobuf::Closure* done) override |
703 | { |
704 | app_name = request->application_name(); |
705 | - connect_msg->set_error(""); |
706 | + // If you check out MirConnection::connected either the platform and display_configuration |
707 | + // have to be set or the error has to be set, otherwise we die and fail to callback. |
708 | + // |
709 | + // Since setting the error to "" means that mir_connection_is_valid will return false |
710 | + // with a confusing non-error-message, instead clear the error and set the platform et al. |
711 | + connect_msg->clear_error(); |
712 | + connect_msg->set_allocated_platform(new mir::protobuf::Platform{}); |
713 | + connect_msg->set_allocated_display_configuration(new mir::protobuf::DisplayConfiguration{}); |
714 | done->Run(); |
715 | } |
716 | |
717 | |
718 | === added file 'tests/include/mir_test/validity_matchers.h' |
719 | --- tests/include/mir_test/validity_matchers.h 1970-01-01 00:00:00 +0000 |
720 | +++ tests/include/mir_test/validity_matchers.h 2014-11-05 22:26:46 +0000 |
721 | @@ -0,0 +1,64 @@ |
722 | +/* |
723 | + * Copyright © 2014 Canonical Ltd. |
724 | + * |
725 | + * This program is free software: you can redistribute it and/or modify it |
726 | + * under the terms of the GNU General Public License version 3, |
727 | + * as published by the Free Software Foundation. |
728 | + * |
729 | + * This program is distributed in the hope that it will be useful, |
730 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
731 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
732 | + * GNU General Public License for more details. |
733 | + * |
734 | + * You should have received a copy of the GNU General Public License |
735 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
736 | + * |
737 | + * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> |
738 | + */ |
739 | + |
740 | +#ifndef MIR_TEST_VALIDITY_MATCHERS_H_ |
741 | +#define MIR_TEST_VALIDITY_MATCHERS_H_ |
742 | + |
743 | +#include <gmock/gmock.h> |
744 | + |
745 | +#include "mir_toolkit/mir_client_library.h" |
746 | + |
747 | +using ::testing::MakePolymorphicMatcher; |
748 | +using ::testing::MatchResultListener; |
749 | +using ::testing::NotNull; |
750 | +using ::testing::PolymorphicMatcher; |
751 | + |
752 | +class IsValidMatcher { |
753 | +public: |
754 | + // To implement a polymorphic matcher, first define a COPYABLE class |
755 | + // that has three members MatchAndExplain(), DescribeTo(), and |
756 | + // DescribeNegationTo(), like the following. |
757 | + |
758 | + // In this example, we want to use NotNull() with any pointer, so |
759 | + // MatchAndExplain() accepts a pointer of any type as its first argument. |
760 | + // In general, you can define MatchAndExplain() as an ordinary method or |
761 | + // a method template, or even overload it. |
762 | + template <typename T> |
763 | + bool MatchAndExplain(T* p, MatchResultListener* listener) const; |
764 | + |
765 | + // Describes the property of a value matching this matcher. |
766 | + void DescribeTo(::std::ostream* os) const { *os << "is valid"; } |
767 | + |
768 | + // Describes the property of a value NOT matching this matcher. |
769 | + void DescribeNegationTo(::std::ostream* os) const { *os << "is not valid"; } |
770 | +}; |
771 | + |
772 | +template<> |
773 | +bool IsValidMatcher::MatchAndExplain(MirConnection* connection, MatchResultListener* listener) const; |
774 | + |
775 | +template<> |
776 | +bool IsValidMatcher::MatchAndExplain(MirSurface* surface, MatchResultListener* listener) const; |
777 | + |
778 | +// To construct a polymorphic matcher, pass an instance of the class |
779 | +// to MakePolymorphicMatcher(). Note the return type. |
780 | +inline PolymorphicMatcher<IsValidMatcher> IsValid() |
781 | +{ |
782 | + return MakePolymorphicMatcher(IsValidMatcher{}); |
783 | +} |
784 | + |
785 | +#endif // MIR_TEST_VALIDITY_MATCHERS_H_ |
786 | |
787 | === modified file 'tests/include/mir_test_framework/using_stub_client_platform.h' |
788 | --- tests/include/mir_test_framework/using_stub_client_platform.h 2014-10-01 06:25:56 +0000 |
789 | +++ tests/include/mir_test_framework/using_stub_client_platform.h 2014-11-05 22:26:46 +0000 |
790 | @@ -20,32 +20,76 @@ |
791 | #define MIR_TEST_FRAMEWORK_USING_STUB_CLIENT_PLATFORM_H_ |
792 | |
793 | #include <memory> |
794 | - |
795 | -namespace mir |
796 | -{ |
797 | -namespace client |
798 | -{ |
799 | -class MirConnectionAPI; |
800 | -} |
801 | -} |
802 | +#include <functional> |
803 | + |
804 | +#include "mir_test_framework/stub_client_connection_configuration.h" |
805 | +#include "src/client/mir_connection_api.h" |
806 | + |
807 | +namespace mcl = mir::client; |
808 | |
809 | namespace mir_test_framework |
810 | { |
811 | |
812 | -class UsingStubClientPlatform |
813 | -{ |
814 | -public: |
815 | - UsingStubClientPlatform(); |
816 | - ~UsingStubClientPlatform(); |
817 | - |
818 | -private: |
819 | - UsingStubClientPlatform(UsingStubClientPlatform const&) = delete; |
820 | - UsingStubClientPlatform operator=(UsingStubClientPlatform const&) = delete; |
821 | +class StubMirConnectionAPI : public mcl::MirConnectionAPI |
822 | +{ |
823 | +public: |
824 | + StubMirConnectionAPI(mcl::MirConnectionAPI* prev_api, |
825 | + mcl::ConfigurationFactory factory) |
826 | + : prev_api{prev_api}, |
827 | + factory{factory} |
828 | + { |
829 | + } |
830 | + |
831 | + MirWaitHandle* connect( |
832 | + mcl::ConfigurationFactory configuration, |
833 | + char const* socket_file, |
834 | + char const* name, |
835 | + mir_connected_callback callback, |
836 | + void* context) override; |
837 | + |
838 | + void release(MirConnection* connection) override; |
839 | + |
840 | + mcl::ConfigurationFactory configuration_factory() override; |
841 | + |
842 | +private: |
843 | + mcl::MirConnectionAPI* const prev_api; |
844 | + mcl::ConfigurationFactory factory; |
845 | +}; |
846 | + |
847 | +template<class ClientConfig> |
848 | +class UsingClientPlatform |
849 | +{ |
850 | +public: |
851 | + UsingClientPlatform() |
852 | + : prev_api{mir_connection_api_impl}, |
853 | + stub_api{new StubMirConnectionAPI{prev_api, make_configuration_factory()}} |
854 | + { |
855 | + mir_connection_api_impl = stub_api.get(); |
856 | + } |
857 | + |
858 | + ~UsingClientPlatform() |
859 | + { |
860 | + mir_connection_api_impl = prev_api; |
861 | + } |
862 | + |
863 | +private: |
864 | + UsingClientPlatform(UsingClientPlatform const&) = delete; |
865 | + UsingClientPlatform operator=(UsingClientPlatform const&) = delete; |
866 | |
867 | mir::client::MirConnectionAPI* prev_api; |
868 | std::unique_ptr<mir::client::MirConnectionAPI> stub_api; |
869 | + |
870 | + mcl::ConfigurationFactory make_configuration_factory() |
871 | + { |
872 | + return [](std::string const& socket) { |
873 | + return std::unique_ptr<mir::client::ConnectionConfiguration>{ |
874 | + new ClientConfig{socket} |
875 | + }; |
876 | + }; |
877 | + } |
878 | }; |
879 | |
880 | +using UsingStubClientPlatform = UsingClientPlatform<StubConnectionConfiguration>; |
881 | } |
882 | |
883 | #endif /* MIR_TEST_FRAMEWORK_USING_STUB_CLIENT_PLATFORM_H_ */ |
884 | |
885 | === modified file 'tests/integration-tests/client/test_client_render.cpp' |
886 | --- tests/integration-tests/client/test_client_render.cpp 2014-10-30 18:37:11 +0000 |
887 | +++ tests/integration-tests/client/test_client_render.cpp 2014-11-05 22:26:46 +0000 |
888 | @@ -28,6 +28,7 @@ |
889 | #include "examples/testdraw/patterns.h" |
890 | #include "mir_test/stub_server_tool.h" |
891 | #include "mir_test/test_protobuf_server.h" |
892 | +#include "mir_test/validity_matchers.h" |
893 | |
894 | #include "mir/frontend/connector.h" |
895 | |
896 | @@ -92,7 +93,9 @@ |
897 | mir_buffer_usage_software, mir_display_output_id_invalid |
898 | }; |
899 | auto connection = mir_connect_sync(socket_file, "test_renderer"); |
900 | + EXPECT_THAT(connection, IsValid()); |
901 | auto surface = mir_connection_create_surface_sync(connection, &surface_parameters); |
902 | + EXPECT_THAT(surface, IsValid()); |
903 | MirGraphicsRegion graphics_region; |
904 | for(int i=0u; i < num_frames; i++) |
905 | { |
906 | @@ -119,6 +122,7 @@ |
907 | process_sync.wait_for_signal_ready_for(); |
908 | |
909 | auto connection = mir_connect_sync(socket_file, "test_renderer"); |
910 | + EXPECT_THAT(connection, IsValid()); |
911 | |
912 | /* set up egl context */ |
913 | int major, minor, n; |
914 | @@ -137,7 +141,9 @@ |
915 | eglInitialize(egl_display, &major, &minor); |
916 | eglChooseConfig(egl_display, attribs, &egl_config, 1, &n); |
917 | |
918 | - auto mir_surface = create_mir_surface(connection, egl_display, egl_config); |
919 | + auto mir_surface = create_mir_surface(connection, egl_display, egl_config); |
920 | + EXPECT_THAT(mir_surface, IsValid()); |
921 | + |
922 | auto native_window = static_cast<EGLNativeWindowType>( |
923 | mir_surface_get_egl_native_window(mir_surface)); |
924 | |
925 | |
926 | === modified file 'tests/integration-tests/test_error_reporting.cpp' |
927 | --- tests/integration-tests/test_error_reporting.cpp 2014-10-01 06:25:56 +0000 |
928 | +++ tests/integration-tests/test_error_reporting.cpp 2014-11-05 22:26:46 +0000 |
929 | @@ -24,6 +24,7 @@ |
930 | #include "mir/frontend/connector.h" |
931 | |
932 | #include "src/server/frontend/display_server.h" |
933 | +#include "src/server/scene/surface_allocator.h" |
934 | |
935 | #include "mir_test_framework/display_server_test_fixture.h" |
936 | #include "mir_test_doubles/stub_ipc_factory.h" |
937 | @@ -34,6 +35,7 @@ |
938 | #include <gmock/gmock.h> |
939 | #include <gtest/gtest.h> |
940 | #include "mir_test/gmock_fixes.h" |
941 | +#include "mir_test/validity_matchers.h" |
942 | |
943 | namespace mc = mir::compositor; |
944 | namespace mf = mir::frontend; |
945 | @@ -45,32 +47,13 @@ |
946 | namespace |
947 | { |
948 | char const* const mir_test_socket = mtf::test_socket_file().c_str(); |
949 | - |
950 | -struct ErrorServer : mf::detail::DisplayServer |
951 | +std::string const test_exception_text{"test exception text"}; |
952 | + |
953 | + |
954 | +struct ConnectionErrorServer : mf::detail::DisplayServer |
955 | { |
956 | void client_pid(int /*pid*/) override {} |
957 | |
958 | - static std::string const test_exception_text; |
959 | - |
960 | - void create_surface( |
961 | - google::protobuf::RpcController*, |
962 | - const mir::protobuf::SurfaceParameters*, |
963 | - mir::protobuf::Surface*, |
964 | - google::protobuf::Closure*) |
965 | - { |
966 | - throw std::runtime_error(test_exception_text); |
967 | - } |
968 | - |
969 | - void release_surface( |
970 | - google::protobuf::RpcController*, |
971 | - const mir::protobuf::SurfaceId*, |
972 | - mir::protobuf::Void*, |
973 | - google::protobuf::Closure*) |
974 | - { |
975 | - throw std::runtime_error(test_exception_text); |
976 | - } |
977 | - |
978 | - |
979 | void connect( |
980 | ::google::protobuf::RpcController*, |
981 | const ::mir::protobuf::ConnectParameters*, |
982 | @@ -90,8 +73,6 @@ |
983 | } |
984 | }; |
985 | |
986 | -std::string const ErrorServer::test_exception_text{"test exception text"}; |
987 | - |
988 | struct SurfaceSync |
989 | { |
990 | SurfaceSync() : |
991 | @@ -193,7 +174,7 @@ |
992 | |
993 | using ErrorReporting = BespokeDisplayServerTestFixture; |
994 | |
995 | -TEST_F(ErrorReporting, c_api_returns_error) |
996 | +TEST_F(ErrorReporting, c_api_returns_connection_error) |
997 | { |
998 | |
999 | struct ServerConfig : TestingServerConfiguration |
1000 | @@ -201,7 +182,7 @@ |
1001 | std::shared_ptr<mf::ProtobufIpcFactory> new_ipc_factory( |
1002 | std::shared_ptr<mf::SessionAuthorizer> const&) override |
1003 | { |
1004 | - static auto error_server = std::make_shared<ErrorServer>(); |
1005 | + static auto error_server = std::make_shared<ConnectionErrorServer>(); |
1006 | return std::make_shared<mtd::StubIpcFactory>(*error_server); |
1007 | } |
1008 | } server_config; |
1009 | @@ -218,7 +199,46 @@ |
1010 | |
1011 | ASSERT_TRUE(connection != NULL); |
1012 | EXPECT_FALSE(mir_connection_is_valid(connection)); |
1013 | - EXPECT_TRUE(std::strstr(mir_connection_get_error_message(connection), ErrorServer::test_exception_text.c_str())); |
1014 | + EXPECT_TRUE(std::strstr(mir_connection_get_error_message(connection), test_exception_text.c_str())); |
1015 | + |
1016 | + mir_connection_release(connection); |
1017 | + } |
1018 | + } client_config; |
1019 | + |
1020 | + launch_client_process(client_config); |
1021 | +} |
1022 | + |
1023 | +TEST_F(ErrorReporting, c_api_returns_surface_creation_error) |
1024 | +{ |
1025 | + |
1026 | + struct ServerConfig : TestingServerConfiguration |
1027 | + { |
1028 | + class BoobytrappedSurfaceFactory : public mir::scene::SurfaceFactory |
1029 | + { |
1030 | + std::shared_ptr<mir::scene::Surface> |
1031 | + create_surface(mir::scene::SurfaceCreationParameters const&) override |
1032 | + { |
1033 | + throw std::runtime_error{test_exception_text}; |
1034 | + } |
1035 | + }; |
1036 | + |
1037 | + std::shared_ptr<mir::scene::SurfaceFactory> the_surface_factory() override |
1038 | + { |
1039 | + return std::make_shared<BoobytrappedSurfaceFactory>(); |
1040 | + } |
1041 | + } server_config; |
1042 | + |
1043 | + launch_server_process(server_config); |
1044 | + |
1045 | + struct ClientConfig : ClientConfigCommon |
1046 | + { |
1047 | + void exec() |
1048 | + { |
1049 | + mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this); |
1050 | + |
1051 | + wait_for_connect(); |
1052 | + |
1053 | + ASSERT_THAT(connection, IsValid()); |
1054 | |
1055 | MirSurfaceParameters const request_params = |
1056 | { |
1057 | @@ -235,12 +255,7 @@ |
1058 | |
1059 | ASSERT_TRUE(ssync->surface != NULL); |
1060 | EXPECT_FALSE(mir_surface_is_valid(ssync->surface)); |
1061 | - EXPECT_TRUE(std::strstr(mir_surface_get_error_message(ssync->surface), ErrorServer::test_exception_text.c_str())); |
1062 | - |
1063 | - EXPECT_NO_THROW({ |
1064 | - MirSurfaceParameters response_params; |
1065 | - mir_surface_get_parameters(ssync->surface, &response_params); |
1066 | - }); |
1067 | + EXPECT_TRUE(std::strstr(mir_surface_get_error_message(ssync->surface), test_exception_text.c_str())); |
1068 | |
1069 | mir_surface_release(ssync->surface, release_surface_callback, ssync); |
1070 | |
1071 | |
1072 | === modified file 'tests/mir_test/CMakeLists.txt' |
1073 | --- tests/mir_test/CMakeLists.txt 2014-11-03 04:01:25 +0000 |
1074 | +++ tests/mir_test/CMakeLists.txt 2014-11-05 22:26:46 +0000 |
1075 | @@ -10,6 +10,7 @@ |
1076 | popen.cpp |
1077 | wait_object.cpp |
1078 | current_thread_name.cpp |
1079 | + validity_matchers.cpp |
1080 | ) |
1081 | |
1082 | target_link_libraries(mir-test mirprotobuf) |
1083 | |
1084 | === added file 'tests/mir_test/validity_matchers.cpp' |
1085 | --- tests/mir_test/validity_matchers.cpp 1970-01-01 00:00:00 +0000 |
1086 | +++ tests/mir_test/validity_matchers.cpp 2014-11-05 22:26:46 +0000 |
1087 | @@ -0,0 +1,32 @@ |
1088 | +#include "mir_test/validity_matchers.h" |
1089 | +#include "mir_toolkit/mir_client_library.h" |
1090 | + |
1091 | +template<> |
1092 | +bool IsValidMatcher::MatchAndExplain(MirConnection* connection, MatchResultListener* listener) const |
1093 | +{ |
1094 | + if (connection == nullptr) |
1095 | + { |
1096 | + return false; |
1097 | + } |
1098 | + if (!mir_connection_is_valid(connection)) |
1099 | + { |
1100 | + *listener << "error is: " << mir_connection_get_error_message(connection); |
1101 | + return false; |
1102 | + } |
1103 | + return true; |
1104 | +} |
1105 | + |
1106 | +template<> |
1107 | +bool IsValidMatcher::MatchAndExplain(MirSurface* surface, MatchResultListener* listener) const |
1108 | +{ |
1109 | + if (surface == nullptr) |
1110 | + { |
1111 | + return false; |
1112 | + } |
1113 | + if (!mir_surface_is_valid(surface)) |
1114 | + { |
1115 | + *listener << "error is: " << mir_surface_get_error_message(surface); |
1116 | + return false; |
1117 | + } |
1118 | + return true; |
1119 | +} |
1120 | |
1121 | === modified file 'tests/mir_test_framework/using_stub_client_platform.cpp' |
1122 | --- tests/mir_test_framework/using_stub_client_platform.cpp 2014-10-27 15:22:31 +0000 |
1123 | +++ tests/mir_test_framework/using_stub_client_platform.cpp 2014-11-05 22:26:46 +0000 |
1124 | @@ -17,57 +17,27 @@ |
1125 | */ |
1126 | |
1127 | #include "mir_test_framework/using_stub_client_platform.h" |
1128 | -#include "mir_test_framework/stub_client_connection_configuration.h" |
1129 | #include "mir_toolkit/mir_client_library.h" |
1130 | -#include "src/client/mir_connection_api.h" |
1131 | |
1132 | namespace mtf = mir_test_framework; |
1133 | namespace mcl = mir::client; |
1134 | |
1135 | -namespace |
1136 | -{ |
1137 | -class StubMirConnectionAPI : public mcl::MirConnectionAPI |
1138 | -{ |
1139 | -public: |
1140 | - StubMirConnectionAPI(mcl::MirConnectionAPI* prev_api) |
1141 | - : prev_api{prev_api} |
1142 | - { |
1143 | - } |
1144 | - |
1145 | - MirWaitHandle* connect( |
1146 | +MirWaitHandle* mtf::StubMirConnectionAPI::connect( |
1147 | + mcl::ConfigurationFactory /*configuration*/, |
1148 | char const* socket_file, |
1149 | char const* name, |
1150 | mir_connected_callback callback, |
1151 | - void* context) override |
1152 | - { |
1153 | - return prev_api->connect(socket_file, name, callback, context); |
1154 | - } |
1155 | - |
1156 | - void release(MirConnection* connection) override |
1157 | - { |
1158 | - return prev_api->release(connection); |
1159 | - } |
1160 | - |
1161 | - std::unique_ptr<mcl::ConnectionConfiguration> configuration(std::string const& socket) override |
1162 | - { |
1163 | - return std::unique_ptr<mcl::ConnectionConfiguration>{ |
1164 | - new mtf::StubConnectionConfiguration{socket}}; |
1165 | - } |
1166 | - |
1167 | -private: |
1168 | - mcl::MirConnectionAPI* const prev_api; |
1169 | -}; |
1170 | - |
1171 | -} |
1172 | - |
1173 | -mtf::UsingStubClientPlatform::UsingStubClientPlatform() |
1174 | - : prev_api{mir_connection_api_impl}, |
1175 | - stub_api{new StubMirConnectionAPI{prev_api}} |
1176 | -{ |
1177 | - mir_connection_api_impl = stub_api.get(); |
1178 | -} |
1179 | - |
1180 | -mtf::UsingStubClientPlatform::~UsingStubClientPlatform() |
1181 | -{ |
1182 | - mir_connection_api_impl = prev_api; |
1183 | + void* context) |
1184 | +{ |
1185 | + return prev_api->connect(configuration_factory(), socket_file, name, callback, context); |
1186 | +} |
1187 | + |
1188 | +void mtf::StubMirConnectionAPI::release(MirConnection* connection) |
1189 | +{ |
1190 | + return prev_api->release(connection); |
1191 | +} |
1192 | + |
1193 | +mcl::ConfigurationFactory mtf::StubMirConnectionAPI::configuration_factory() |
1194 | +{ |
1195 | + return factory; |
1196 | } |
FAILED: Continuous integration, rev:1875 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/2529/ jenkins. qa.ubuntu. com/job/ mir-android- utopic- i386-build/ 1494 jenkins. qa.ubuntu. com/job/ mir-clang- utopic- amd64-build/ 1500 jenkins. qa.ubuntu. com/job/ mir-mediumtests -utopic- touch/1477/ console jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 1051/console jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- utopic- armhf/414 jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- utopic- armhf/414/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/2559/ console s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 12257
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/2529/ rebuild
http://