Merge lp:~thomas-voss/location-service/add-testing-for-remote-provider into lp:location-service/trunk
- add-testing-for-remote-provider
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Loïc Minier |
Approved revision: | 106 |
Merged at revision: | 103 |
Proposed branch: | lp:~thomas-voss/location-service/add-testing-for-remote-provider |
Merge into: | lp:location-service/trunk |
Diff against target: |
1413 lines (+1032/-182) 8 files modified
src/location_service/com/ubuntu/location/providers/remote/provider.cpp (+66/-47) src/location_service/com/ubuntu/location/providers/remote/provider.h (+8/-4) src/location_service/com/ubuntu/location/providers/remote/remote_interface.h (+138/-39) tests/CMakeLists.txt (+3/-19) tests/controller_test.cpp (+2/-31) tests/espoo_provider_test.cpp (+399/-0) tests/mock_provider.h (+71/-0) tests/remote_provider_test.cpp (+345/-42) |
To merge this branch: | bzr merge lp:~thomas-voss/location-service/add-testing-for-remote-provider |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Loïc Minier | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+234194@code.launchpad.net |
Commit message
Somewhat clean up remote provider and add an acceptance-style test.
Description of the change
Somewhat clean up remote provider and add an acceptance-style test.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 104. By Thomas Voß
-
Add a standalone test for integration with the espoo provider.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:104
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 105. By Thomas Voß
-
Make sure the signal trap is setup prior to connectivty worker thread being started.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:105
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 106. By Thomas Voß
-
Adjust reporting format.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:106
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Loïc Minier (lool) wrote : | # |
I've built my own binaries of r105 (r106 just added a test) and ran them on mako + utopic-proposed just fine.
(Not top-approving this yet as I haven't tested the binaries though.)
Loïc Minier (lool) wrote : | # |
Are there any related MPs required for this MP to build/function as expected? Please list.
I've tested with updated espoo binaries which need to land at the same time as updated packages; the espoo MP is already merged though.
Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes)
Yes
Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator?
On device
Did you successfully run all tests found in your component's Test Plan (https:/
Ran most of the tests; discovered some not directly related issues, but no regressions
If you changed the UI, was the change specified/approved by design?
No UI change
If you changed the packaging (debian), did you subscribe a core-dev to this MP?
No packaging change
Did CI run pass? If not, please explain why.
CI passed
Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
I'm filling it instead
Preview Diff
1 | === modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.cpp' |
2 | --- src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2014-08-27 09:13:42 +0000 |
3 | +++ src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2014-09-11 20:20:36 +0000 |
4 | @@ -27,11 +27,20 @@ |
5 | |
6 | namespace cul = com::ubuntu::location; |
7 | namespace culpr = com::ubuntu::location::providers::remote; |
8 | - |
9 | +namespace cur = com::ubuntu::remote; |
10 | namespace dbus = core::dbus; |
11 | |
12 | namespace |
13 | { |
14 | +template<typename T> |
15 | +void throw_if_error(const dbus::Result<T>& result) |
16 | +{ |
17 | + if (result.is_error()) throw std::runtime_error |
18 | + { |
19 | + result.error().print() |
20 | + }; |
21 | +} |
22 | + |
23 | dbus::Bus::Ptr the_system_bus() |
24 | { |
25 | dbus::Bus::Ptr system_bus = std::make_shared<dbus::Bus>(dbus::WellKnownBus::system); |
26 | @@ -42,38 +51,18 @@ |
27 | |
28 | struct culpr::Provider::Private |
29 | { |
30 | - typedef core::dbus::Signal< |
31 | - com::ubuntu::remote::RemoteInterface::Signals::PositionChanged, |
32 | - com::ubuntu::remote::RemoteInterface::Signals::PositionChanged::ArgumentType |
33 | - > PositionChanged; |
34 | - |
35 | Private(const culpr::Provider::Configuration& config) |
36 | : bus(config.connection), |
37 | service(dbus::Service::use_service(bus, config.name)), |
38 | object(service->object_for_path(config.path)), |
39 | - signal_position_changed(object->get_signal<com::ubuntu::remote::RemoteInterface::Signals::PositionChanged>()) |
40 | - { |
41 | - } |
42 | - |
43 | - void start() |
44 | - { |
45 | - VLOG(10) << __PRETTY_FUNCTION__; |
46 | - if (!worker.joinable()) |
47 | - worker = std::move(std::thread{std::bind(&dbus::Bus::run, bus)}); |
48 | - } |
49 | - |
50 | - void stop() |
51 | - { |
52 | - VLOG(10) << __PRETTY_FUNCTION__; |
53 | - try |
54 | - { |
55 | - bus->stop(); |
56 | - } |
57 | - catch(...) |
58 | - { |
59 | - // can happen if the start method was not called |
60 | - VLOG(10) << "Stopping not started remote provider."; |
61 | - } |
62 | + stub(object), |
63 | + worker([this]() { bus->run(); }) |
64 | + { |
65 | + } |
66 | + |
67 | + ~Private() |
68 | + { |
69 | + bus->stop(); |
70 | |
71 | if (worker.joinable()) |
72 | worker.join(); |
73 | @@ -82,8 +71,8 @@ |
74 | dbus::Bus::Ptr bus; |
75 | dbus::Service::Ptr service; |
76 | dbus::Object::Ptr object; |
77 | - PositionChanged::Ptr signal_position_changed; |
78 | - PositionChanged::SubscriptionToken position_updates_connection; |
79 | + |
80 | + com::ubuntu::remote::RemoteInterface::Stub stub; |
81 | |
82 | std::thread worker; |
83 | }; |
84 | @@ -108,22 +97,28 @@ |
85 | : com::ubuntu::location::Provider(config.features, config.requirements), |
86 | d(new Private(config)) |
87 | { |
88 | - d->position_updates_connection = |
89 | - d->signal_position_changed->connect( |
90 | - [this](const com::ubuntu::remote::RemoteInterface::Signals::PositionChanged::ArgumentType& arg) |
91 | - { |
92 | - this->on_position_changed(arg); |
93 | - }); |
94 | + d->stub.signals.position_changed->connect( |
95 | + [this](const cur::RemoteInterface::Signals::PositionChanged::ArgumentType& arg) |
96 | + { |
97 | + VLOG(50) << "culpr::Provider::PositionChanged: " << arg; |
98 | + mutable_updates().position(arg); |
99 | + }); |
100 | + d->stub.signals.heading_changed->connect( |
101 | + [this](const cur::RemoteInterface::Signals::HeadingChanged::ArgumentType& arg) |
102 | + { |
103 | + VLOG(50) << "culpr::Provider::HeadingChanged: " << arg; |
104 | + mutable_updates().heading(arg); |
105 | + }); |
106 | + d->stub.signals.velocity_changed->connect( |
107 | + [this](const cur::RemoteInterface::Signals::VelocityChanged::ArgumentType& arg) |
108 | + { |
109 | + VLOG(50) << "culpr::Provider::VelocityChanged: " << arg; |
110 | + mutable_updates().velocity(arg); |
111 | + }); |
112 | } |
113 | |
114 | culpr::Provider::~Provider() noexcept |
115 | { |
116 | - d->stop(); |
117 | -} |
118 | - |
119 | -void culpr::Provider::on_position_changed(const com::ubuntu::remote::RemoteInterface::Signals::PositionChanged::ArgumentType& arg) |
120 | -{ |
121 | - mutable_updates().position(arg); |
122 | } |
123 | |
124 | bool culpr::Provider::matches_criteria(const cul::Criteria&) |
125 | @@ -133,12 +128,36 @@ |
126 | |
127 | void culpr::Provider::start_position_updates() |
128 | { |
129 | - VLOG(10) << "Starting remote provider\n"; |
130 | - d->start(); |
131 | + VLOG(10) << __PRETTY_FUNCTION__; |
132 | + throw_if_error(d->stub.object->transact_method<cur::RemoteInterface::StartPositionUpdates, void>()); |
133 | } |
134 | |
135 | void culpr::Provider::stop_position_updates() |
136 | { |
137 | - VLOG(10) << "Stopping remote provider\n"; |
138 | - d->stop(); |
139 | + VLOG(10) << __PRETTY_FUNCTION__; |
140 | + throw_if_error(d->stub.object->transact_method<cur::RemoteInterface::StopPositionUpdates, void>()); |
141 | +} |
142 | + |
143 | +void culpr::Provider::start_heading_updates() |
144 | +{ |
145 | + VLOG(10) << __PRETTY_FUNCTION__; |
146 | + throw_if_error(d->stub.object->transact_method<cur::RemoteInterface::StartHeadingUpdates, void>()); |
147 | +} |
148 | + |
149 | +void culpr::Provider::stop_heading_updates() |
150 | +{ |
151 | + VLOG(10) << __PRETTY_FUNCTION__; |
152 | + throw_if_error(d->stub.object->transact_method<cur::RemoteInterface::StopHeadingUpdates, void>()); |
153 | +} |
154 | + |
155 | +void culpr::Provider::start_velocity_updates() |
156 | +{ |
157 | + VLOG(10) << __PRETTY_FUNCTION__; |
158 | + throw_if_error(d->stub.object->transact_method<cur::RemoteInterface::StartVelocityUpdates, void>()); |
159 | +} |
160 | + |
161 | +void culpr::Provider::stop_velocity_updates() |
162 | +{ |
163 | + VLOG(10) << __PRETTY_FUNCTION__; |
164 | + throw_if_error(d->stub.object->transact_method<cur::RemoteInterface::StopVelocityUpdates, void>()); |
165 | } |
166 | |
167 | === modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.h' |
168 | --- src/location_service/com/ubuntu/location/providers/remote/provider.h 2014-08-26 16:04:02 +0000 |
169 | +++ src/location_service/com/ubuntu/location/providers/remote/provider.h 2014-09-11 20:20:36 +0000 |
170 | @@ -66,10 +66,14 @@ |
171 | |
172 | virtual bool matches_criteria(const Criteria&); |
173 | |
174 | - virtual void start_position_updates(); |
175 | - virtual void stop_position_updates(); |
176 | - |
177 | - void on_position_changed(const com::ubuntu::remote::RemoteInterface::Signals::PositionChanged::ArgumentType& arg); |
178 | + virtual void start_position_updates() override; |
179 | + virtual void stop_position_updates() override; |
180 | + |
181 | + virtual void start_heading_updates() override; |
182 | + virtual void stop_heading_updates() override; |
183 | + |
184 | + virtual void start_velocity_updates() override; |
185 | + virtual void stop_velocity_updates() override; |
186 | |
187 | private: |
188 | struct Private; |
189 | |
190 | === modified file 'src/location_service/com/ubuntu/location/providers/remote/remote_interface.h' |
191 | --- src/location_service/com/ubuntu/location/providers/remote/remote_interface.h 2014-08-29 10:41:36 +0000 |
192 | +++ src/location_service/com/ubuntu/location/providers/remote/remote_interface.h 2014-09-11 20:20:36 +0000 |
193 | @@ -20,11 +20,18 @@ |
194 | #define CORE_UBUNTU_ESPOO_PROVIDER_P_H_ |
195 | |
196 | #include <core/dbus/macros.h> |
197 | +#include <core/dbus/object.h> |
198 | +#include <core/dbus/property.h> |
199 | +#include <core/dbus/signal.h> |
200 | + |
201 | #include <core/dbus/traits/service.h> |
202 | |
203 | #include <com/ubuntu/location/codec.h> |
204 | #include <com/ubuntu/location/update.h> |
205 | + |
206 | +#include <com/ubuntu/location/heading.h> |
207 | #include <com/ubuntu/location/position.h> |
208 | +#include <com/ubuntu/location/velocity.h> |
209 | |
210 | namespace cul = com::ubuntu::location; |
211 | |
212 | @@ -36,7 +43,6 @@ |
213 | { |
214 | struct RemoteInterface |
215 | { |
216 | - |
217 | static const std::string& name() |
218 | { |
219 | static const std::string s{"com.ubuntu.remote.Service.Provider"}; |
220 | @@ -52,18 +58,9 @@ |
221 | |
222 | struct Signals |
223 | { |
224 | - struct PositionChanged |
225 | - { |
226 | - inline static std::string name() |
227 | - { |
228 | - return "PositionChanged"; |
229 | - }; |
230 | - typedef RemoteInterface Interface; |
231 | - typedef cul::Position ArgumentType; |
232 | - }; |
233 | - |
234 | - DBUS_CPP_SIGNAL_DEF(HeadingChanged, RemoteInterface, double) |
235 | - DBUS_CPP_SIGNAL_DEF(VelocityChanged, RemoteInterface, double) |
236 | + DBUS_CPP_SIGNAL_DEF(PositionChanged, RemoteInterface, cul::Position) |
237 | + DBUS_CPP_SIGNAL_DEF(HeadingChanged, RemoteInterface, cul::Heading) |
238 | + DBUS_CPP_SIGNAL_DEF(VelocityChanged, RemoteInterface, cul::Velocity) |
239 | }; |
240 | |
241 | struct Properties |
242 | @@ -80,35 +77,137 @@ |
243 | DBUS_CPP_READABLE_PROPERTY_DEF(AreVelocityUpdatesRunning, RemoteInterface, bool) |
244 | }; |
245 | |
246 | + struct Skeleton |
247 | + { |
248 | + // Creates a new skeleton instance and installs the interface |
249 | + // com::ubuntu::remote::Interface on it. |
250 | + Skeleton(const core::dbus::Object::Ptr& object) |
251 | + : object{object}, |
252 | + properties |
253 | + { |
254 | + object->get_property<Properties::HasPosition>(), |
255 | + object->get_property<Properties::HasVelocity>(), |
256 | + object->get_property<Properties::HasHeading>(), |
257 | + object->get_property<Properties::RequiresSatellites>(), |
258 | + object->get_property<Properties::RequiresCellNetwork>(), |
259 | + object->get_property<Properties::RequiresDataNetwork>(), |
260 | + object->get_property<Properties::RequiresMonetarySpending>(), |
261 | + object->get_property<Properties::ArePositionUpdatesRunning>(), |
262 | + object->get_property<Properties::AreHeadingUpdatesRunning>(), |
263 | + object->get_property<Properties::AreVelocityUpdatesRunning>() |
264 | + }, |
265 | + signals |
266 | + { |
267 | + object->get_signal<Signals::PositionChanged>(), |
268 | + object->get_signal<Signals::HeadingChanged>(), |
269 | + object->get_signal<Signals::VelocityChanged>() |
270 | + } |
271 | + { |
272 | + } |
273 | + |
274 | + // The object that the interface is installed on. |
275 | + core::dbus::Object::Ptr object; |
276 | + // All known properties. |
277 | + struct |
278 | + { |
279 | + std::shared_ptr<core::dbus::Property<Properties::HasPosition>> has_position; |
280 | + std::shared_ptr<core::dbus::Property<Properties::HasVelocity>> has_velocity; |
281 | + std::shared_ptr<core::dbus::Property<Properties::HasHeading>> has_heading; |
282 | + std::shared_ptr<core::dbus::Property<Properties::RequiresSatellites>> requires_satellites; |
283 | + std::shared_ptr<core::dbus::Property<Properties::RequiresCellNetwork>> requires_cell_network; |
284 | + std::shared_ptr<core::dbus::Property<Properties::RequiresDataNetwork>> requires_data_network; |
285 | + std::shared_ptr<core::dbus::Property<Properties::RequiresMonetarySpending>> requires_monetary_spending; |
286 | + std::shared_ptr<core::dbus::Property<Properties::ArePositionUpdatesRunning>> are_position_updates_running; |
287 | + std::shared_ptr<core::dbus::Property<Properties::AreHeadingUpdatesRunning>> are_heading_updates_running; |
288 | + std::shared_ptr<core::dbus::Property<Properties::AreVelocityUpdatesRunning>> are_velocity_updates_running; |
289 | + } properties; |
290 | + // All known signals. |
291 | + struct |
292 | + { |
293 | + std::shared_ptr<core::dbus::Signal< |
294 | + Signals::PositionChanged, |
295 | + Signals::PositionChanged::ArgumentType |
296 | + >> position_changed; |
297 | + |
298 | + std::shared_ptr<core::dbus::Signal< |
299 | + Signals::HeadingChanged, |
300 | + Signals::HeadingChanged::ArgumentType |
301 | + >> heading_changed; |
302 | + |
303 | + std::shared_ptr<core::dbus::Signal< |
304 | + Signals::VelocityChanged, |
305 | + Signals::VelocityChanged::ArgumentType |
306 | + >> velocity_changed; |
307 | + } signals; |
308 | + }; |
309 | + |
310 | + struct Stub |
311 | + { |
312 | + // Creates a new skeleton instance and installs the interface |
313 | + // com::ubuntu::remote::Interface on it. |
314 | + Stub(const core::dbus::Object::Ptr& object) |
315 | + : object{object}, |
316 | + properties |
317 | + { |
318 | + object->get_property<Properties::HasPosition>(), |
319 | + object->get_property<Properties::HasVelocity>(), |
320 | + object->get_property<Properties::HasHeading>(), |
321 | + object->get_property<Properties::RequiresSatellites>(), |
322 | + object->get_property<Properties::RequiresCellNetwork>(), |
323 | + object->get_property<Properties::RequiresDataNetwork>(), |
324 | + object->get_property<Properties::RequiresMonetarySpending>(), |
325 | + object->get_property<Properties::ArePositionUpdatesRunning>(), |
326 | + object->get_property<Properties::AreHeadingUpdatesRunning>(), |
327 | + object->get_property<Properties::AreVelocityUpdatesRunning>() |
328 | + }, |
329 | + signals |
330 | + { |
331 | + object->get_signal<Signals::PositionChanged>(), |
332 | + object->get_signal<Signals::HeadingChanged>(), |
333 | + object->get_signal<Signals::VelocityChanged>() |
334 | + } |
335 | + { |
336 | + } |
337 | + |
338 | + // The object that the interface is installed on. |
339 | + core::dbus::Object::Ptr object; |
340 | + // All known properties. |
341 | + struct |
342 | + { |
343 | + std::shared_ptr<core::dbus::Property<Properties::HasPosition>> has_position; |
344 | + std::shared_ptr<core::dbus::Property<Properties::HasVelocity>> has_velocity; |
345 | + std::shared_ptr<core::dbus::Property<Properties::HasHeading>> has_heading; |
346 | + std::shared_ptr<core::dbus::Property<Properties::RequiresSatellites>> requires_satellites; |
347 | + std::shared_ptr<core::dbus::Property<Properties::RequiresCellNetwork>> requires_cell_network; |
348 | + std::shared_ptr<core::dbus::Property<Properties::RequiresDataNetwork>> requires_data_network; |
349 | + std::shared_ptr<core::dbus::Property<Properties::RequiresMonetarySpending>> requires_monetary_spending; |
350 | + std::shared_ptr<core::dbus::Property<Properties::ArePositionUpdatesRunning>> are_position_updates_running; |
351 | + std::shared_ptr<core::dbus::Property<Properties::AreHeadingUpdatesRunning>> are_heading_updates_running; |
352 | + std::shared_ptr<core::dbus::Property<Properties::AreVelocityUpdatesRunning>> are_velocity_updates_running; |
353 | + } properties; |
354 | + // All known signals. |
355 | + struct |
356 | + { |
357 | + std::shared_ptr<core::dbus::Signal< |
358 | + Signals::PositionChanged, |
359 | + Signals::PositionChanged::ArgumentType |
360 | + >> position_changed; |
361 | + |
362 | + std::shared_ptr<core::dbus::Signal< |
363 | + Signals::HeadingChanged, |
364 | + Signals::HeadingChanged::ArgumentType |
365 | + >> heading_changed; |
366 | + |
367 | + std::shared_ptr<core::dbus::Signal< |
368 | + Signals::VelocityChanged, |
369 | + Signals::VelocityChanged::ArgumentType |
370 | + >> velocity_changed; |
371 | + } signals; |
372 | + }; |
373 | + |
374 | }; |
375 | } // remote |
376 | } // ubuntu |
377 | } // core |
378 | |
379 | -namespace core |
380 | -{ |
381 | -namespace dbus |
382 | -{ |
383 | -namespace traits |
384 | -{ |
385 | -template<> |
386 | -struct Service<com::ubuntu::remote::RemoteInterface> |
387 | -{ |
388 | - static const std::string& interface_name() |
389 | - { |
390 | - static const std::string s{"com.ubuntu.espoo.Service.Provider"}; |
391 | - return s; |
392 | - } |
393 | - |
394 | - inline static const std::string& object_path() |
395 | - { |
396 | - static const std::string s{"/com/ubuntu/espoo/Service/Provider"}; |
397 | - return s; |
398 | - } |
399 | - |
400 | -}; |
401 | -} |
402 | -} |
403 | -} |
404 | - |
405 | #endif |
406 | |
407 | === modified file 'tests/CMakeLists.txt' |
408 | --- tests/CMakeLists.txt 2014-08-26 16:04:02 +0000 |
409 | +++ tests/CMakeLists.txt 2014-09-11 20:20:36 +0000 |
410 | @@ -53,7 +53,7 @@ |
411 | gtest |
412 | gtest_main) |
413 | |
414 | - add_test(${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${test_name} --gtest_filter=*-*requires_hardware) |
415 | + add_test(${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${test_name} --gtest_filter=*-*requires*) |
416 | |
417 | # Address android's limit on cmdline length and distill ubuntu-location-service into uls |
418 | install( |
419 | @@ -118,22 +118,6 @@ |
420 | endif (LOCATION_SERVICE_ENABLE_GEOCLUE_PROVIDERS) |
421 | |
422 | if (LOCATION_SERVICE_ENABLE_REMOTE_PROVIDER) |
423 | - add_executable(remote_provider_test remote_provider_test.cpp) |
424 | - target_link_libraries( |
425 | - remote_provider_test |
426 | - |
427 | - ubuntu-location-service |
428 | - |
429 | - ${CMAKE_THREAD_LIBS_INIT} |
430 | - ${Boost_LIBRARIES} |
431 | - ${PROCESS_CPP_LIBRARIES} |
432 | - ${ARGN} |
433 | - |
434 | - gmock |
435 | - |
436 | - gtest |
437 | - gtest_main |
438 | - ) |
439 | - |
440 | - add_test(remote_provider_test ${CMAKE_CURRENT_BINARY_DIR}/remote_provider_test) |
441 | + LOCATION_SERVICE_ADD_TEST(remote_provider_test remote_provider_test.cpp) |
442 | + LOCATION_SERVICE_ADD_TEST(espoo_provider_test espoo_provider_test.cpp) |
443 | endif (LOCATION_SERVICE_ENABLE_REMOTE_PROVIDER) |
444 | |
445 | === modified file 'tests/controller_test.cpp' |
446 | --- tests/controller_test.cpp 2014-01-20 13:03:19 +0000 |
447 | +++ tests/controller_test.cpp 2014-09-11 20:20:36 +0000 |
448 | @@ -17,6 +17,8 @@ |
449 | */ |
450 | #include <com/ubuntu/location/provider.h> |
451 | |
452 | +#include "mock_provider.h" |
453 | + |
454 | #include <gmock/gmock.h> |
455 | #include <gtest/gtest.h> |
456 | |
457 | @@ -24,37 +26,6 @@ |
458 | |
459 | namespace |
460 | { |
461 | -struct MockProvider : public cul::Provider |
462 | -{ |
463 | - MockProvider() : cul::Provider() |
464 | - { |
465 | - } |
466 | - |
467 | - MOCK_METHOD0(start_position_updates, void()); |
468 | - MOCK_METHOD0(stop_position_updates, void()); |
469 | - |
470 | - MOCK_METHOD0(start_heading_updates, void()); |
471 | - MOCK_METHOD0(stop_heading_updates, void()); |
472 | - |
473 | - MOCK_METHOD0(start_velocity_updates, void()); |
474 | - MOCK_METHOD0(stop_velocity_updates, void()); |
475 | - |
476 | - void inject_update(const cul::Update<cul::Position>& update) |
477 | - { |
478 | - mutable_updates().position(update); |
479 | - } |
480 | - |
481 | - void inject_update(const cul::Update<cul::Velocity>& update) |
482 | - { |
483 | - mutable_updates().velocity(update); |
484 | - } |
485 | - |
486 | - void inject_update(const cul::Update<cul::Heading>& update) |
487 | - { |
488 | - mutable_updates().heading(update); |
489 | - } |
490 | -}; |
491 | - |
492 | auto timestamp = com::ubuntu::location::Clock::now(); |
493 | |
494 | com::ubuntu::location::Update<com::ubuntu::location::Position> reference_position_update |
495 | |
496 | === added file 'tests/espoo_provider_test.cpp' |
497 | --- tests/espoo_provider_test.cpp 1970-01-01 00:00:00 +0000 |
498 | +++ tests/espoo_provider_test.cpp 2014-09-11 20:20:36 +0000 |
499 | @@ -0,0 +1,399 @@ |
500 | +/* |
501 | + * Copyright © 2014 Canonical Ltd. |
502 | + * |
503 | + * This program is free software: you can redistribute it and/or modify it |
504 | + * under the terms of the GNU Lesser General Public License version 3, |
505 | + * as published by the Free Software Foundation. |
506 | + * |
507 | + * This program is distributed in the hope that it will be useful, |
508 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
509 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
510 | + * GNU Lesser General Public License for more details. |
511 | + * |
512 | + * You should have received a copy of the GNU Lesser General Public License |
513 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
514 | + * |
515 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
516 | + */ |
517 | + |
518 | +#include <com/ubuntu/location/providers/remote/provider.h> |
519 | + |
520 | +#include <com/ubuntu/location/logging.h> |
521 | + |
522 | +#include <com/ubuntu/location/connectivity/manager.h> |
523 | + |
524 | +#include <core/dbus/asio/executor.h> |
525 | + |
526 | +#include <core/posix/signal.h> |
527 | +#include <core/posix/this_process.h> |
528 | + |
529 | +#include <boost/accumulators/accumulators.hpp> |
530 | +#include <boost/accumulators/statistics/stats.hpp> |
531 | +#include <boost/accumulators/statistics/count.hpp> |
532 | +#include <boost/accumulators/statistics/max.hpp> |
533 | +#include <boost/accumulators/statistics/mean.hpp> |
534 | +#include <boost/accumulators/statistics/min.hpp> |
535 | +#include <boost/accumulators/statistics/variance.hpp> |
536 | + |
537 | +#include <gtest/gtest.h> |
538 | + |
539 | +namespace cul = com::ubuntu::location; |
540 | +namespace remote = com::ubuntu::location::providers::remote; |
541 | +namespace statistics = boost::accumulators; |
542 | + |
543 | +namespace |
544 | +{ |
545 | +// A simple counter to keep track of events. |
546 | +struct Counter |
547 | +{ |
548 | + Counter(const std::string& name) : name{name}, value{0} |
549 | + { |
550 | + } |
551 | + |
552 | + Counter& operator++() |
553 | + { |
554 | + value++; return *this; |
555 | + } |
556 | + |
557 | + Counter operator++(int) |
558 | + { |
559 | + auto copy = *this; ++*this; return copy; |
560 | + } |
561 | + |
562 | + Counter& operator--() |
563 | + { |
564 | + value--; return *this; |
565 | + } |
566 | + |
567 | + Counter operator--(int) |
568 | + { |
569 | + auto copy = *this; --*this; return copy; |
570 | + } |
571 | + |
572 | + std::uint64_t operator*() const |
573 | + { |
574 | + return value; |
575 | + } |
576 | + |
577 | + void reset() |
578 | + { |
579 | + value = 0; |
580 | + } |
581 | + |
582 | + std::string name; |
583 | + std::uint64_t value; |
584 | +}; |
585 | + |
586 | +std::ostream& operator<<(std::ostream& out, const Counter& counter) |
587 | +{ |
588 | + return out << counter.name << ": " << counter.value; |
589 | +} |
590 | + |
591 | +// Helps in tracking time differences. |
592 | +struct StopWatch |
593 | +{ |
594 | + StopWatch(const std::string& name) |
595 | + : start{std::chrono::system_clock::now()}, |
596 | + name{name} |
597 | + { |
598 | + } |
599 | + |
600 | + void reset() |
601 | + { |
602 | + start = std::chrono::system_clock::now(); |
603 | + } |
604 | + |
605 | + std::chrono::system_clock::duration stop() |
606 | + { |
607 | + return std::chrono::system_clock::now() - start; |
608 | + } |
609 | + |
610 | + std::chrono::system_clock::time_point start; |
611 | + std::string name; |
612 | +}; |
613 | + |
614 | +struct Statistics |
615 | +{ |
616 | + typedef std::int64_t ValueType; |
617 | + // We accumulate size, mean, min, max and variance of a sample |
618 | + typedef statistics::accumulator_set |
619 | + < |
620 | + ValueType, |
621 | + statistics::stats |
622 | + < |
623 | + statistics::tag::count, |
624 | + statistics::tag::mean, |
625 | + statistics::tag::min, |
626 | + statistics::tag::max, |
627 | + statistics::tag::variance |
628 | + > |
629 | + > Accumulator; |
630 | + |
631 | + Statistics(const std::string& name) : name{name} |
632 | + { |
633 | + } |
634 | + |
635 | + template<typename NumericType> |
636 | + void update(NumericType value) |
637 | + { |
638 | + accumulator(value); |
639 | + } |
640 | + |
641 | + void reset() |
642 | + { |
643 | + accumulator = Accumulator{}; |
644 | + } |
645 | + |
646 | + ValueType min() const |
647 | + { |
648 | + return statistics::min(accumulator); |
649 | + } |
650 | + |
651 | + ValueType max() const |
652 | + { |
653 | + return statistics::max(accumulator); |
654 | + } |
655 | + |
656 | + ValueType mean() const |
657 | + { |
658 | + return statistics::mean(accumulator); |
659 | + } |
660 | + |
661 | + ValueType variance() const |
662 | + { |
663 | + return statistics::variance(accumulator); |
664 | + } |
665 | + |
666 | + std::size_t count() const |
667 | + { |
668 | + return statistics::count(accumulator); |
669 | + } |
670 | + |
671 | + Accumulator accumulator; |
672 | + std::string name; |
673 | +}; |
674 | + |
675 | +struct EspooProviderTest : public ::testing::Test |
676 | +{ |
677 | + // All known environment variables. |
678 | + struct Parameters |
679 | + { |
680 | + struct Bus |
681 | + { |
682 | + static constexpr const char* name |
683 | + { |
684 | + "ESPOO_PROVIDER_TEST_BUS" |
685 | + }; |
686 | + |
687 | + static constexpr const char* default_value |
688 | + { |
689 | + "session" |
690 | + }; |
691 | + }; |
692 | + }; |
693 | + |
694 | + static core::dbus::Bus::Ptr bus_instance_according_to_env() |
695 | + { |
696 | + auto value = core::posix::this_process::env::get(Parameters::Bus::name, Parameters::Bus::default_value); |
697 | + |
698 | + core::dbus::WellKnownBus bus{core::dbus::WellKnownBus::starter}; |
699 | + |
700 | + if (value == "session") |
701 | + bus = core::dbus::WellKnownBus::session; |
702 | + else if (value == "system") |
703 | + bus = core::dbus::WellKnownBus::system; |
704 | + |
705 | + auto result = std::make_shared<core::dbus::Bus>(bus); |
706 | + result->install_executor(core::dbus::asio::make_executor(result)); |
707 | + |
708 | + return result; |
709 | + } |
710 | + |
711 | + static constexpr const char* service_name |
712 | + { |
713 | + "com.ubuntu.espoo.Service.Provider" |
714 | + }; |
715 | + |
716 | + static constexpr const char* path |
717 | + { |
718 | + "/com/ubuntu/espoo/Service/Provider" |
719 | + }; |
720 | + |
721 | + static std::uint64_t numeric_cell_id_from_cell(const cul::connectivity::RadioCell::Ptr& cell) |
722 | + { |
723 | + std::uint64_t cid; |
724 | + switch (cell->type()) |
725 | + { |
726 | + case cul::connectivity::RadioCell::Type::gsm: |
727 | + cid = cell->gsm().id.get(); |
728 | + break; |
729 | + case cul::connectivity::RadioCell::Type::umts: |
730 | + cid = cell->umts().id.get(); |
731 | + break; |
732 | + case cul::connectivity::RadioCell::Type::lte: |
733 | + cid = cell->lte().id.get(); |
734 | + break; |
735 | + default: |
736 | + cid = std::numeric_limits<std::uint64_t>::max(); |
737 | + break; |
738 | + } |
739 | + return cid; |
740 | + } |
741 | + |
742 | + EspooProviderTest() |
743 | + : bus{bus_instance_according_to_env()}, |
744 | + trap{core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_int})}, |
745 | + cm{cul::connectivity::platform_default_manager()} |
746 | + { |
747 | + // Bootstrap wifi stats |
748 | + cm->enumerate_visible_wireless_networks([this](const cul::connectivity::WirelessNetwork::Ptr&) |
749 | + { |
750 | + ++connectivity_stats.wifi_counter; |
751 | + }); |
752 | + |
753 | + connectivity_stats.over_wifi_count.update(*connectivity_stats.wifi_counter); |
754 | + |
755 | + cm->wireless_network_added().connect([this](const cul::connectivity::WirelessNetwork::Ptr&) |
756 | + { |
757 | + connectivity_stats.over_wifi_count.update(*(++connectivity_stats.wifi_counter)); |
758 | + }); |
759 | + |
760 | + cm->wireless_network_removed().connect([this](const cul::connectivity::WirelessNetwork::Ptr&) |
761 | + { |
762 | + connectivity_stats.over_wifi_count.update(*(--connectivity_stats.wifi_counter)); |
763 | + }); |
764 | + |
765 | + // Bootstrap cell stats |
766 | + cm->enumerate_connected_radio_cells([this](const cul::connectivity::RadioCell::Ptr& cell) |
767 | + { |
768 | + on_radio_cell_added(cell); |
769 | + }); |
770 | + |
771 | + cm->connected_cell_added().connect([this](const cul::connectivity::RadioCell::Ptr& cell) |
772 | + { |
773 | + on_radio_cell_added(cell); |
774 | + }); |
775 | + |
776 | + cm->connected_cell_removed().connect([this](const cul::connectivity::RadioCell::Ptr& cell) |
777 | + { |
778 | + cells_to_ids.erase(cell); |
779 | + }); |
780 | + } |
781 | + |
782 | + void on_radio_cell_added(const cul::connectivity::RadioCell::Ptr& cell) |
783 | + { |
784 | + // We store the cell characteristics here. |
785 | + cells_to_ids.insert(std::make_pair(cell, std::make_tuple(cell->type(), numeric_cell_id_from_cell(cell)))); |
786 | + |
787 | + std::weak_ptr<cul::connectivity::RadioCell> wp{cell}; |
788 | + |
789 | + // Subscribe to changes on the cell |
790 | + cell->changed().connect([wp, this]() |
791 | + { |
792 | + auto sp = wp.lock(); |
793 | + |
794 | + if (not sp) |
795 | + return; |
796 | + |
797 | + if (cells_to_ids.count(sp) > 0) |
798 | + { |
799 | + auto tuple = cells_to_ids.at(sp); |
800 | + |
801 | + // The technology changed. |
802 | + if (std::get<0>(tuple) != sp->type()) |
803 | + { |
804 | + |
805 | + ++connectivity_stats.cell_changes_counter; |
806 | + } |
807 | + else // No change in technology, comparing actual ids. |
808 | + { |
809 | + if (std::get<1>(tuple) != numeric_cell_id_from_cell(sp)) |
810 | + ++connectivity_stats.cell_changes_counter; |
811 | + } |
812 | + |
813 | + // Update last known values. |
814 | + cells_to_ids.at(sp) = std::make_tuple(sp->type(), numeric_cell_id_from_cell(sp)); |
815 | + } |
816 | + }); |
817 | + } |
818 | + |
819 | + // The bus connection for reaching out to the espoo provider. |
820 | + core::dbus::Bus::Ptr bus; |
821 | + // Our signal trap. |
822 | + std::shared_ptr<core::posix::SignalTrap> trap; |
823 | + // We monitor the connectivity subsystems. |
824 | + std::shared_ptr<cul::connectivity::Manager> cm; |
825 | + // We store individual cell ids together with their type. |
826 | + std::map |
827 | + < |
828 | + cul::connectivity::RadioCell::Ptr, |
829 | + std::tuple<cul::connectivity::RadioCell::Type, std::uint64_t> |
830 | + > cells_to_ids; |
831 | + struct |
832 | + { |
833 | + Counter wifi_counter{"Wifi counter"}; |
834 | + Statistics over_wifi_count{"Wifi count stats"}; |
835 | + Counter cell_changes_counter{"Cell changes"}; |
836 | + } connectivity_stats; |
837 | +}; |
838 | +} |
839 | + |
840 | +TEST_F(EspooProviderTest, receives_position_updates_requires_daemons) |
841 | +{ |
842 | + trap->signal_raised().connect([this](core::posix::Signal) |
843 | + { |
844 | + trap->stop(); |
845 | + }); |
846 | + |
847 | + remote::Provider::Configuration config; |
848 | + config.name = EspooProviderTest::service_name; |
849 | + config.path = EspooProviderTest::path; |
850 | + config.connection = bus; |
851 | + |
852 | + // We keep track of some characteristics. |
853 | + struct Stats |
854 | + { |
855 | + StopWatch execution_time{"Execution time of test"}; // The total execution time of the test. |
856 | + StopWatch position_updates_duration{"Position updates duration"}; // Time between position updates. |
857 | + Statistics position_updates_duration_stats{"Position updates duration stats"}; |
858 | + Counter position_updates_counter{"Position updates"}; // The number of position updates we received. |
859 | + } stats; |
860 | + |
861 | + remote::Provider provider{config}; |
862 | + |
863 | + provider.updates().position.connect([&stats](const cul::Update<cul::Position>& update) |
864 | + { |
865 | + VLOG(1) << update; |
866 | + // We track the number of position updates |
867 | + stats.position_updates_counter++; |
868 | + // And we update our statistics by querying our stopwatch. |
869 | + stats.position_updates_duration_stats.update(stats.position_updates_duration.stop().count()); |
870 | + // And we reset it. |
871 | + stats.position_updates_duration.reset(); |
872 | + }); |
873 | + |
874 | + // provider.start_position_updates(); |
875 | + trap->run(); |
876 | + // provider.stop_position_updates(); |
877 | + |
878 | + // Finally printing some statistics |
879 | + std::cout << "Total execution time: " |
880 | + << std::chrono::duration_cast<std::chrono::seconds>(stats.execution_time.stop()).count() << " [s]" << std::endl; |
881 | + std::cout << stats.position_updates_counter << std::endl; |
882 | + |
883 | + std::cout << "Min time in [s] between position updates: " |
884 | + << std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::duration{stats.position_updates_duration_stats.min()}).count() << std::endl; |
885 | + std::cout << "Max time in [s] between position updates: " |
886 | + << std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::duration{stats.position_updates_duration_stats.max()}).count() << std::endl; |
887 | + std::cout << "Mean time in [s] between position updates: " |
888 | + << std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::duration{stats.position_updates_duration_stats.mean()}).count() << std::endl; |
889 | + std::cout << "Std.dev. of time in [s] between position updates: " |
890 | + << std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::duration{(std::int64_t)std::sqrt(stats.position_updates_duration_stats.variance())}).count() << std::endl; |
891 | + |
892 | + std::cout << "Min # of visible wifis: " |
893 | + << connectivity_stats.over_wifi_count.min() << std::endl; |
894 | + std::cout << "Max # of visible wifis: " |
895 | + << connectivity_stats.over_wifi_count.max() << std::endl; |
896 | + std::cout << "Mean # of visible wifis: " |
897 | + << connectivity_stats.over_wifi_count.mean() << std::endl; |
898 | +} |
899 | |
900 | === added file 'tests/mock_provider.h' |
901 | --- tests/mock_provider.h 1970-01-01 00:00:00 +0000 |
902 | +++ tests/mock_provider.h 2014-09-11 20:20:36 +0000 |
903 | @@ -0,0 +1,71 @@ |
904 | +/* |
905 | + * Copyright © 2014 Canonical Ltd. |
906 | + * |
907 | + * This program is free software: you can redistribute it and/or modify it |
908 | + * under the terms of the GNU Lesser General Public License version 3, |
909 | + * as published by the Free Software Foundation. |
910 | + * |
911 | + * This program is distributed in the hope that it will be useful, |
912 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
913 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
914 | + * GNU Lesser General Public License for more details. |
915 | + * |
916 | + * You should have received a copy of the GNU Lesser General Public License |
917 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
918 | + * |
919 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
920 | + */ |
921 | +#ifndef MOCK_PROVIDER_H_ |
922 | +#define MOCK_PROVIDER_H_ |
923 | + |
924 | +#include <com/ubuntu/location/provider.h> |
925 | + |
926 | +#include <gmock/gmock.h> |
927 | + |
928 | +struct MockProvider : public com::ubuntu::location::Provider |
929 | +{ |
930 | + MockProvider() : com::ubuntu::location::Provider() |
931 | + { |
932 | + } |
933 | + |
934 | + // Called by the engine whenever the wifi and cell ID reporting state changes. |
935 | + MOCK_METHOD1(on_wifi_and_cell_reporting_state_changed, void(com::ubuntu::location::WifiAndCellIdReportingState state)); |
936 | + |
937 | + // Called by the engine whenever the reference location changed. |
938 | + MOCK_METHOD1(on_reference_location_updated, void(const com::ubuntu::location::Update<com::ubuntu::location::Position>& position)); |
939 | + |
940 | + // Called by the engine whenever the reference velocity changed. |
941 | + MOCK_METHOD1(on_reference_velocity_updated, void(const com::ubuntu::location::Update<com::ubuntu::location::Velocity>& velocity)); |
942 | + |
943 | + // Called by the engine whenever the reference heading changed. |
944 | + MOCK_METHOD1(on_reference_heading_updated, void(const com::ubuntu::location::Update<com::ubuntu::location::Heading>& heading)); |
945 | + |
946 | + MOCK_METHOD0(start_position_updates, void()); |
947 | + MOCK_METHOD0(stop_position_updates, void()); |
948 | + |
949 | + MOCK_METHOD0(start_heading_updates, void()); |
950 | + MOCK_METHOD0(stop_heading_updates, void()); |
951 | + |
952 | + MOCK_METHOD0(start_velocity_updates, void()); |
953 | + MOCK_METHOD0(stop_velocity_updates, void()); |
954 | + |
955 | + // Inject a position update from the outside. |
956 | + void inject_update(const com::ubuntu::location::Update<com::ubuntu::location::Position>& update) |
957 | + { |
958 | + mutable_updates().position(update); |
959 | + } |
960 | + |
961 | + // Inject a velocity update from the outside. |
962 | + void inject_update(const com::ubuntu::location::Update<com::ubuntu::location::Velocity>& update) |
963 | + { |
964 | + mutable_updates().velocity(update); |
965 | + } |
966 | + |
967 | + // Inject a heading update from the outside. |
968 | + void inject_update(const com::ubuntu::location::Update<com::ubuntu::location::Heading>& update) |
969 | + { |
970 | + mutable_updates().heading(update); |
971 | + } |
972 | +}; |
973 | + |
974 | +#endif // MOCK_PROVIDER_H_ |
975 | |
976 | === modified file 'tests/remote_provider_test.cpp' |
977 | --- tests/remote_provider_test.cpp 2014-08-27 09:13:42 +0000 |
978 | +++ tests/remote_provider_test.cpp 2014-09-11 20:20:36 +0000 |
979 | @@ -16,22 +16,33 @@ |
980 | * Authored by: Manuel de la Peña <manuel.delapena@canonical.com> |
981 | */ |
982 | |
983 | +#include <com/ubuntu/location/logging.h> |
984 | #include <com/ubuntu/location/provider.h> |
985 | -#include <com/ubuntu/location/proxy_provider.h> |
986 | #include <com/ubuntu/location/providers/remote/provider.h> |
987 | |
988 | +#include "mock_provider.h" |
989 | + |
990 | #include <core/dbus/fixture.h> |
991 | +#include <core/dbus/asio/executor.h> |
992 | + |
993 | +#include <core/posix/fork.h> |
994 | +#include <core/posix/signal.h> |
995 | + |
996 | +#include <core/testing/fork_and_run.h> |
997 | |
998 | #include <gmock/gmock.h> |
999 | #include <gtest/gtest.h> |
1000 | |
1001 | namespace cul = com::ubuntu::location; |
1002 | +namespace cur = com::ubuntu::remote; |
1003 | +namespace dbus = core::dbus; |
1004 | namespace remote = com::ubuntu::location::providers::remote; |
1005 | |
1006 | using namespace ::testing; |
1007 | |
1008 | |
1009 | -MATCHER_P(postion_equals_tuple, value, "Returns if the string maps are equal.") { |
1010 | +MATCHER_P(PositionUpdatesAreEqualExceptForTiming, value, "Returns true if the positions in both updates are equal.") |
1011 | +{ |
1012 | auto pos = arg.value; |
1013 | |
1014 | return value.longitude == pos.longitude && value.latitude == pos.latitude && value.altitude == pos.altitude |
1015 | @@ -39,66 +50,358 @@ |
1016 | && pos.accuracy.vertical == value.accuracy.vertical; |
1017 | } |
1018 | |
1019 | +MATCHER_P(HeadingUpdatesAreEqualExceptForTiming, value, "Returns true if the heading in both updates are equal.") |
1020 | +{ |
1021 | + auto heading = arg.value; |
1022 | + return heading == value; |
1023 | +} |
1024 | + |
1025 | +MATCHER_P(VelocityUpdatesAreEqualExceptForTiming, value, "Returns true if the velocity in both updates are equal.") |
1026 | +{ |
1027 | + auto velocity = arg.value; |
1028 | + return velocity == value; |
1029 | +} |
1030 | + |
1031 | namespace |
1032 | { |
1033 | +::testing::AssertionResult did_finish_successfully(const core::posix::wait::Result& result) |
1034 | +{ |
1035 | + if (result.status != core::posix::wait::Result::Status::exited) |
1036 | + return ::testing::AssertionFailure() << "Process did not exit, but: " << (int)result.status; |
1037 | + if (result.detail.if_exited.status != core::posix::exit::Status::success) |
1038 | + return ::testing::AssertionFailure() << "Process did exit with failure."; |
1039 | + |
1040 | + return ::testing::AssertionSuccess(); |
1041 | +} |
1042 | + |
1043 | struct RemoteProvider : public core::dbus::testing::Fixture |
1044 | { |
1045 | + static constexpr const char* stub_remote_provider_service_name |
1046 | + { |
1047 | + "does.not.exist.remote.Provider" |
1048 | + }; |
1049 | |
1050 | + static constexpr const char* stub_remote_provider_path |
1051 | + { |
1052 | + "/com/ubuntu/remote/Provider" |
1053 | + }; |
1054 | }; |
1055 | |
1056 | class MockEventConsumer |
1057 | { |
1058 | public: |
1059 | - MockEventConsumer() {} |
1060 | + MockEventConsumer() |
1061 | + { |
1062 | + using namespace ::testing; |
1063 | + |
1064 | + ON_CALL(*this, on_new_position(_)) |
1065 | + .WillByDefault( |
1066 | + InvokeWithoutArgs( |
1067 | + this, |
1068 | + &MockEventConsumer::notify_position_update_arrived)); |
1069 | + ON_CALL(*this, on_new_heading(_)) |
1070 | + .WillByDefault( |
1071 | + InvokeWithoutArgs( |
1072 | + this, |
1073 | + &MockEventConsumer::notify_heading_update_arrived)); |
1074 | + ON_CALL(*this, on_new_velocity(_)) |
1075 | + .WillByDefault( |
1076 | + InvokeWithoutArgs( |
1077 | + this, |
1078 | + &MockEventConsumer::notify_velocity_update_arrived)); |
1079 | + } |
1080 | + |
1081 | + bool wait_for_position_update_for(const std::chrono::milliseconds& timeout) |
1082 | + { |
1083 | + std::unique_lock<std::mutex> ul{position.guard}; |
1084 | + return position.wait_condition.wait_for(ul, timeout, [this] { return position.update_arrived; }); |
1085 | + } |
1086 | + |
1087 | + bool wait_for_heading_update_for(const std::chrono::milliseconds& timeout) |
1088 | + { |
1089 | + std::unique_lock<std::mutex> ul{heading.guard}; |
1090 | + return heading.wait_condition.wait_for(ul, timeout, [this] { return heading.update_arrived; }); |
1091 | + } |
1092 | + |
1093 | + bool wait_for_velocity_update_for(const std::chrono::milliseconds& timeout) |
1094 | + { |
1095 | + std::unique_lock<std::mutex> ul{velocity.guard}; |
1096 | + return velocity.wait_condition.wait_for(ul, timeout, [this] { return velocity.update_arrived; }); |
1097 | + } |
1098 | |
1099 | MOCK_METHOD1(on_new_position, void(const cul::Update<cul::Position>&)); |
1100 | + MOCK_METHOD1(on_new_heading, void(const cul::Update<cul::Heading>&)); |
1101 | + MOCK_METHOD1(on_new_velocity, void(const cul::Update<cul::Velocity>&)); |
1102 | + |
1103 | +private: |
1104 | + // Notes down the arrival of a position update |
1105 | + // and notifies any waiting threads about the event. |
1106 | + void notify_position_update_arrived() |
1107 | + { |
1108 | + position.update_arrived = true; |
1109 | + position.wait_condition.notify_all(); |
1110 | + } |
1111 | + |
1112 | + // Notes down the arrival of a heading update |
1113 | + // and notifies any waiting threads about the event. |
1114 | + void notify_heading_update_arrived() |
1115 | + { |
1116 | + heading.update_arrived = true; |
1117 | + heading.wait_condition.notify_all(); |
1118 | + } |
1119 | + |
1120 | + // Notes down the arrival of a heading update |
1121 | + // and notifies any waiting threads about the event. |
1122 | + void notify_velocity_update_arrived() |
1123 | + { |
1124 | + velocity.update_arrived = true; |
1125 | + velocity.wait_condition.notify_all(); |
1126 | + } |
1127 | + |
1128 | + struct |
1129 | + { |
1130 | + std::mutex guard; |
1131 | + std::condition_variable wait_condition; |
1132 | + bool update_arrived{false}; |
1133 | + } position; |
1134 | + |
1135 | + struct |
1136 | + { |
1137 | + std::mutex guard; |
1138 | + std::condition_variable wait_condition; |
1139 | + bool update_arrived{false}; |
1140 | + } heading; |
1141 | + |
1142 | + struct |
1143 | + { |
1144 | + std::mutex guard; |
1145 | + std::condition_variable wait_condition; |
1146 | + bool update_arrived{false}; |
1147 | + } velocity; |
1148 | }; |
1149 | } |
1150 | -TEST_F(RemoteProvider, matches_criteria) |
1151 | + |
1152 | +TEST_F(RemoteProvider, updates_are_fwd) |
1153 | +{ |
1154 | + using namespace ::testing; |
1155 | + |
1156 | + static const cul::Position position |
1157 | + { |
1158 | + cul::wgs84::Latitude{2* cul::units::Degrees}, |
1159 | + cul::wgs84::Longitude{3* cul::units::Degrees}, |
1160 | + cul::wgs84::Altitude{4* cul::units::Meters}, |
1161 | + cul::Position::Accuracy::Horizontal(5* cul::units::Meters), |
1162 | + cul::Position::Accuracy::Vertical(6* cul::units::Meters) |
1163 | + }; |
1164 | + |
1165 | + static const cul::Heading heading |
1166 | + { |
1167 | + 120. * cul::units::Degrees |
1168 | + }; |
1169 | + |
1170 | + static const cul::Velocity velocity |
1171 | + { |
1172 | + 5. * cul::units::MetersPerSecond |
1173 | + }; |
1174 | + |
1175 | + auto skeleton = core::posix::fork([this]() |
1176 | + { |
1177 | + bool running{true}; |
1178 | + auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term}); |
1179 | + |
1180 | + trap->signal_raised().connect([trap, &running](core::posix::Signal) |
1181 | + { |
1182 | + trap->stop(); |
1183 | + running = false; |
1184 | + }); |
1185 | + |
1186 | + auto bus = session_bus(); |
1187 | + bus->install_executor(dbus::asio::make_executor(bus)); |
1188 | + |
1189 | + std::thread worker([bus]() |
1190 | + { |
1191 | + bus->run(); |
1192 | + }); |
1193 | + |
1194 | + auto object = dbus::Service::add_service( |
1195 | + bus, |
1196 | + RemoteProvider::stub_remote_provider_service_name) |
1197 | + ->add_object_for_path( |
1198 | + dbus::types::ObjectPath{RemoteProvider::stub_remote_provider_path}); |
1199 | + |
1200 | + // We use this instance to capture incoming requests. |
1201 | + NiceMock<MockProvider> mock_provider; |
1202 | + |
1203 | + EXPECT_CALL(mock_provider, start_position_updates()).Times(1); |
1204 | + EXPECT_CALL(mock_provider, start_heading_updates()).Times(1); |
1205 | + EXPECT_CALL(mock_provider, start_velocity_updates()).Times(1); |
1206 | + EXPECT_CALL(mock_provider, stop_position_updates()).Times(1); |
1207 | + EXPECT_CALL(mock_provider, stop_heading_updates()).Times(1); |
1208 | + EXPECT_CALL(mock_provider, stop_velocity_updates()).Times(1); |
1209 | + |
1210 | + cur::RemoteInterface::Skeleton remote_provider{object}; |
1211 | + |
1212 | + remote_provider.object->install_method_handler<cur::RemoteInterface::StartPositionUpdates>([bus, &mock_provider](const dbus::Message::Ptr & msg) |
1213 | + { |
1214 | + VLOG(1) << "StartPositionUpdates"; |
1215 | + mock_provider.start_position_updates(); |
1216 | + bus->send(dbus::Message::make_method_return(msg)); |
1217 | + }); |
1218 | + |
1219 | + remote_provider.object->install_method_handler<cur::RemoteInterface::StopPositionUpdates>([bus, &mock_provider](const dbus::Message::Ptr & msg) |
1220 | + { |
1221 | + VLOG(1) << "StopPositionUpdates"; |
1222 | + mock_provider.stop_position_updates(); |
1223 | + bus->send(dbus::Message::make_method_return(msg)); |
1224 | + }); |
1225 | + |
1226 | + remote_provider.object->install_method_handler<cur::RemoteInterface::StartHeadingUpdates>([bus, &mock_provider](const dbus::Message::Ptr & msg) |
1227 | + { |
1228 | + VLOG(1) << "StartHeadingUpdates"; |
1229 | + mock_provider.start_heading_updates(); |
1230 | + bus->send(dbus::Message::make_method_return(msg)); |
1231 | + }); |
1232 | + |
1233 | + remote_provider.object->install_method_handler<cur::RemoteInterface::StopHeadingUpdates>([bus, &mock_provider](const dbus::Message::Ptr & msg) |
1234 | + { |
1235 | + VLOG(1) << "StopHeadingUpdates"; |
1236 | + mock_provider.stop_heading_updates(); |
1237 | + bus->send(dbus::Message::make_method_return(msg)); |
1238 | + }); |
1239 | + |
1240 | + remote_provider.object->install_method_handler<cur::RemoteInterface::StartVelocityUpdates>([bus, &mock_provider](const dbus::Message::Ptr & msg) |
1241 | + { |
1242 | + VLOG(1) << "StartVelocityUpdates"; |
1243 | + mock_provider.start_velocity_updates(); |
1244 | + bus->send(dbus::Message::make_method_return(msg)); |
1245 | + }); |
1246 | + |
1247 | + remote_provider.object->install_method_handler<cur::RemoteInterface::StopVelocityUpdates>([bus, &mock_provider](const dbus::Message::Ptr & msg) |
1248 | + { |
1249 | + VLOG(1) << "StartVelocityUpdates"; |
1250 | + mock_provider.stop_velocity_updates(); |
1251 | + bus->send(dbus::Message::make_method_return(msg)); |
1252 | + }); |
1253 | + |
1254 | + std::thread position_updates_injector{[&remote_provider, &running]() |
1255 | + { |
1256 | + while (running) |
1257 | + { |
1258 | + remote_provider.signals.position_changed->emit(position); |
1259 | + std::this_thread::sleep_for(std::chrono::milliseconds{10}); |
1260 | + } |
1261 | + }}; |
1262 | + |
1263 | + std::thread heading_updates_injector{[&remote_provider, &running]() |
1264 | + { |
1265 | + while (running) |
1266 | + { |
1267 | + remote_provider.signals.heading_changed->emit(heading); |
1268 | + std::this_thread::sleep_for(std::chrono::milliseconds{10}); |
1269 | + } |
1270 | + }}; |
1271 | + |
1272 | + std::thread velocity_updates_injector{[&remote_provider, &running]() |
1273 | + { |
1274 | + while (running) |
1275 | + { |
1276 | + remote_provider.signals.velocity_changed->emit(velocity); |
1277 | + std::this_thread::sleep_for(std::chrono::milliseconds{10}); |
1278 | + } |
1279 | + }}; |
1280 | + |
1281 | + trap->run(); |
1282 | + |
1283 | + if (position_updates_injector.joinable()) |
1284 | + position_updates_injector.join(); |
1285 | + |
1286 | + if (heading_updates_injector.joinable()) |
1287 | + heading_updates_injector.join(); |
1288 | + |
1289 | + if (velocity_updates_injector.joinable()) |
1290 | + velocity_updates_injector.join(); |
1291 | + |
1292 | + bus->stop(); |
1293 | + |
1294 | + if (worker.joinable()) |
1295 | + worker.join(); |
1296 | + |
1297 | + return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : |
1298 | + core::posix::exit::Status::success; |
1299 | + }, core::posix::StandardStream::empty); |
1300 | + |
1301 | + std::this_thread::sleep_for(std::chrono::milliseconds{500}); |
1302 | + |
1303 | + auto stub = core::posix::fork([this]() |
1304 | + { |
1305 | + auto conf = remote::Provider::Configuration{}; |
1306 | + conf.name = RemoteProvider::stub_remote_provider_service_name; |
1307 | + conf.path = RemoteProvider::stub_remote_provider_path; |
1308 | + conf.connection = session_bus(); |
1309 | + conf.connection->install_executor(dbus::asio::make_executor(conf.connection)); |
1310 | + |
1311 | + remote::Provider provider{conf}; |
1312 | + provider.start_position_updates(); |
1313 | + provider.start_heading_updates(); |
1314 | + provider.start_velocity_updates(); |
1315 | + |
1316 | + MockEventConsumer mec; |
1317 | + EXPECT_CALL(mec, on_new_position(PositionUpdatesAreEqualExceptForTiming(position))).Times(AtLeast(1)); |
1318 | + EXPECT_CALL(mec, on_new_heading(HeadingUpdatesAreEqualExceptForTiming(heading))).Times(AtLeast(1)); |
1319 | + EXPECT_CALL(mec, on_new_velocity(VelocityUpdatesAreEqualExceptForTiming(velocity))).Times(AtLeast(1)); |
1320 | + |
1321 | + core::ScopedConnection sc1 |
1322 | + { |
1323 | + provider.updates().position.connect([&mec](const cul::Update<cul::Position>& p) |
1324 | + { |
1325 | + mec.on_new_position(p); |
1326 | + }) |
1327 | + }; |
1328 | + |
1329 | + core::ScopedConnection sc2 |
1330 | + { |
1331 | + provider.updates().heading.connect([&mec](const cul::Update<cul::Heading>& h) |
1332 | + { |
1333 | + mec.on_new_heading(h); |
1334 | + }) |
1335 | + }; |
1336 | + |
1337 | + core::ScopedConnection sc3 |
1338 | + { |
1339 | + provider.updates().velocity.connect([&mec](const cul::Update<cul::Velocity>& v) |
1340 | + { |
1341 | + mec.on_new_velocity(v); |
1342 | + }) |
1343 | + }; |
1344 | + |
1345 | + EXPECT_TRUE(mec.wait_for_position_update_for(std::chrono::milliseconds{1000})); |
1346 | + EXPECT_TRUE(mec.wait_for_heading_update_for(std::chrono::milliseconds{1000})); |
1347 | + EXPECT_TRUE(mec.wait_for_velocity_update_for(std::chrono::milliseconds{1000})); |
1348 | + |
1349 | + provider.stop_position_updates(); |
1350 | + provider.stop_heading_updates(); |
1351 | + provider.stop_velocity_updates(); |
1352 | + |
1353 | + return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : |
1354 | + core::posix::exit::Status::success; |
1355 | + }, core::posix::StandardStream::empty); |
1356 | + |
1357 | + EXPECT_TRUE(did_finish_successfully(stub.wait_for(core::posix::wait::Flags::untraced))); |
1358 | + skeleton.send_signal_or_throw(core::posix::Signal::sig_term); |
1359 | + EXPECT_TRUE(did_finish_successfully(skeleton.wait_for(core::posix::wait::Flags::untraced))); |
1360 | +} |
1361 | + |
1362 | +TESTP_F(RemoteProvider, matches_criteria, |
1363 | { |
1364 | auto conf = remote::Provider::Configuration{}; |
1365 | - conf.name = "com.ubuntu.espoo.Service.Provider"; |
1366 | - conf.path = "/com/ubuntu/espoo/Service/Provider"; |
1367 | + conf.name = RemoteProvider::stub_remote_provider_service_name; |
1368 | + conf.path = RemoteProvider::stub_remote_provider_path; |
1369 | conf.connection = session_bus(); |
1370 | + conf.connection->install_executor(dbus::asio::make_executor(conf.connection)); |
1371 | remote::Provider provider(conf); |
1372 | |
1373 | EXPECT_FALSE(provider.requires(com::ubuntu::location::Provider::Requirements::satellites)); |
1374 | EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::cell_network)); |
1375 | EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::data_network)); |
1376 | EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::monetary_spending)); |
1377 | -} |
1378 | - |
1379 | -TEST_F(RemoteProvider, updates_are_fwd) |
1380 | -{ |
1381 | - // update received from the remote provider in a tuple |
1382 | - cul::Position update |
1383 | - { |
1384 | - cul::wgs84::Latitude{2* cul::units::Degrees}, |
1385 | - cul::wgs84::Longitude{3* cul::units::Degrees} |
1386 | - }; |
1387 | - |
1388 | - update.altitude = cul::wgs84::Altitude{4* cul::units::Meters}; |
1389 | - update.accuracy.horizontal = cul::Position::Accuracy::Horizontal(5* cul::units::Meters); |
1390 | - update.accuracy.vertical = cul::Position::Accuracy::Vertical(6* cul::units::Meters); |
1391 | - |
1392 | - auto conf = remote::Provider::Configuration{}; |
1393 | - conf.name = "com.ubuntu.espoo.Service.Provider"; |
1394 | - conf.path = "/com/ubuntu/espoo/Service/Provider"; |
1395 | - conf.connection = session_bus(); |
1396 | - |
1397 | - remote::Provider provider{conf}; |
1398 | - |
1399 | - cul::Provider::Ptr p1{std::addressof(provider), [](cul::Provider*){}}; |
1400 | - |
1401 | - cul::ProviderSelection selection{p1, p1, p1}; |
1402 | - |
1403 | - cul::ProxyProvider pp{selection}; |
1404 | - |
1405 | - MockEventConsumer mec; |
1406 | - EXPECT_CALL(mec, on_new_position(postion_equals_tuple(update))).Times(1); |
1407 | - |
1408 | - pp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);}); |
1409 | - |
1410 | - // create an update to be processed |
1411 | - provider.on_position_changed(update); |
1412 | -} |
1413 | +}) |
FAILED: Continuous integration, rev:103 jenkins. qa.ubuntu. com/job/ location- service- ci/273/ jenkins. qa.ubuntu. com/job/ location- service- utopic- amd64-ci/ 180/console jenkins. qa.ubuntu. com/job/ location- service- utopic- armhf-ci/ 180/console jenkins. qa.ubuntu. com/job/ location- service- utopic- i386-ci/ 180/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/location- service- ci/273/ rebuild
http://