Merge lp:~thomas-voss/location-service/factor-out-runtime into lp:location-service/15.04
- factor-out-runtime
- Merge into 15.04
Proposed by
Thomas Voß
Status: | Merged |
---|---|
Approved by: | Alberto Mardegan |
Approved revision: | 138 |
Merged at revision: | 205 |
Proposed branch: | lp:~thomas-voss/location-service/factor-out-runtime |
Merge into: | lp:location-service/15.04 |
Diff against target: |
613 lines (+351/-72) 9 files modified
src/location_service/com/ubuntu/location/CMakeLists.txt (+1/-0) src/location_service/com/ubuntu/location/service/daemon.cpp (+10/-43) src/location_service/com/ubuntu/location/service/provider_daemon.cpp (+11/-16) src/location_service/com/ubuntu/location/service/runtime.cpp (+109/-0) src/location_service/com/ubuntu/location/service/runtime.h (+90/-0) tests/CMakeLists.txt (+1/-0) tests/acceptance_tests.cpp (+10/-12) tests/position_test.cpp (+1/-1) tests/runtime_test.cpp (+118/-0) |
To merge this branch: | bzr merge lp:~thomas-voss/location-service/factor-out-runtime |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alberto Mardegan (community) | Approve | ||
Review via email: mp+278674@code.launchpad.net |
This proposal supersedes a proposal from 2015-11-19.
Commit message
- Factor out service::Runtime from daemon.cpp into its own .h/.cpp pair of files.
- Add test cases around correct operation of service::Runtime.
Description of the change
- Factor out service::Runtime from daemon.cpp into its own .h/.cpp pair of files.
- Add test cases around correct operation of service::Runtime.
To post a comment you must log in.
- 138. By Thomas Voß
-
Remove dependency on robustify-...
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt' | |||
2 | --- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-04-23 14:48:44 +0000 | |||
3 | +++ src/location_service/com/ubuntu/location/CMakeLists.txt 2015-11-26 08:30:38 +0000 | |||
4 | @@ -38,6 +38,7 @@ | |||
5 | 38 | service/harvester.cpp | 38 | service/harvester.cpp |
6 | 39 | service/demultiplexing_reporter.h | 39 | service/demultiplexing_reporter.h |
7 | 40 | service/demultiplexing_reporter.cpp | 40 | service/demultiplexing_reporter.cpp |
8 | 41 | service/runtime.cpp | ||
9 | 41 | service/runtime_tests.h | 42 | service/runtime_tests.h |
10 | 42 | service/runtime_tests.cpp | 43 | service/runtime_tests.cpp |
11 | 43 | service/trust_store_permission_manager.cpp | 44 | service/trust_store_permission_manager.cpp |
12 | 44 | 45 | ||
13 | === modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp' | |||
14 | --- src/location_service/com/ubuntu/location/service/daemon.cpp 2015-10-23 13:43:32 +0000 | |||
15 | +++ src/location_service/com/ubuntu/location/service/daemon.cpp 2015-11-26 08:30:38 +0000 | |||
16 | @@ -20,6 +20,7 @@ | |||
17 | 20 | #include <com/ubuntu/location/boost_ptree_settings.h> | 20 | #include <com/ubuntu/location/boost_ptree_settings.h> |
18 | 21 | #include <com/ubuntu/location/provider_factory.h> | 21 | #include <com/ubuntu/location/provider_factory.h> |
19 | 22 | 22 | ||
20 | 23 | #include <com/ubuntu/location/logging.h> | ||
21 | 23 | #include <com/ubuntu/location/connectivity/dummy_connectivity_manager.h> | 24 | #include <com/ubuntu/location/connectivity/dummy_connectivity_manager.h> |
22 | 24 | 25 | ||
23 | 25 | #include <com/ubuntu/location/service/default_configuration.h> | 26 | #include <com/ubuntu/location/service/default_configuration.h> |
24 | @@ -32,6 +33,7 @@ | |||
25 | 32 | 33 | ||
26 | 33 | #include "program_options.h" | 34 | #include "program_options.h" |
27 | 34 | #include "daemon.h" | 35 | #include "daemon.h" |
28 | 36 | #include "runtime.h" | ||
29 | 35 | 37 | ||
30 | 36 | #include <core/dbus/announcer.h> | 38 | #include <core/dbus/announcer.h> |
31 | 37 | #include <core/dbus/resolver.h> | 39 | #include <core/dbus/resolver.h> |
32 | @@ -39,6 +41,8 @@ | |||
33 | 39 | 41 | ||
34 | 40 | #include <core/posix/signal.h> | 42 | #include <core/posix/signal.h> |
35 | 41 | 43 | ||
36 | 44 | #include <boost/asio.hpp> | ||
37 | 45 | |||
38 | 42 | #include <system_error> | 46 | #include <system_error> |
39 | 43 | #include <thread> | 47 | #include <thread> |
40 | 44 | 48 | ||
41 | @@ -177,6 +181,8 @@ | |||
42 | 177 | trap->stop(); | 181 | trap->stop(); |
43 | 178 | }); | 182 | }); |
44 | 179 | 183 | ||
45 | 184 | auto runtime = location::service::Runtime::create(); | ||
46 | 185 | |||
47 | 180 | const location::Configuration empty_provider_configuration; | 186 | const location::Configuration empty_provider_configuration; |
48 | 181 | 187 | ||
49 | 182 | std::set<location::Provider::Ptr> instantiated_providers; | 188 | std::set<location::Provider::Ptr> instantiated_providers; |
50 | @@ -203,8 +209,10 @@ | |||
51 | 203 | } | 209 | } |
52 | 204 | } | 210 | } |
53 | 205 | 211 | ||
56 | 206 | config.incoming->install_executor(dbus::asio::make_executor(config.incoming)); | 212 | config.incoming->install_executor(dbus::asio::make_executor(config.incoming, runtime->service())); |
57 | 207 | config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing)); | 213 | config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing, runtime->service())); |
58 | 214 | |||
59 | 215 | runtime->start(); | ||
60 | 208 | 216 | ||
61 | 209 | location::service::DefaultConfiguration dc; | 217 | location::service::DefaultConfiguration dc; |
62 | 210 | 218 | ||
63 | @@ -222,50 +230,9 @@ | |||
64 | 222 | }; | 230 | }; |
65 | 223 | 231 | ||
66 | 224 | auto location_service = std::make_shared<location::service::Implementation>(configuration); | 232 | auto location_service = std::make_shared<location::service::Implementation>(configuration); |
67 | 225 | // We need to ensure that any exception raised by the executor does not crash the app | ||
68 | 226 | // and also gets logged. | ||
69 | 227 | auto execute = [] (std::shared_ptr<core::dbus::Bus> bus) { | ||
70 | 228 | while(true) | ||
71 | 229 | { | ||
72 | 230 | try | ||
73 | 231 | { | ||
74 | 232 | VLOG(10) << "Starting a bus executor"; | ||
75 | 233 | bus->run(); | ||
76 | 234 | break; // run() exited normally | ||
77 | 235 | } | ||
78 | 236 | catch (const std::exception& e) | ||
79 | 237 | { | ||
80 | 238 | LOG(WARNING) << e.what(); | ||
81 | 239 | } | ||
82 | 240 | catch (...) | ||
83 | 241 | { | ||
84 | 242 | LOG(WARNING) << "Unexpected exception was raised by the bus executor"; | ||
85 | 243 | } | ||
86 | 244 | } | ||
87 | 245 | }; | ||
88 | 246 | |||
89 | 247 | std::thread t1{execute, config.incoming}; | ||
90 | 248 | std::thread t2{execute, config.incoming}; | ||
91 | 249 | std::thread t3{execute, config.incoming}; | ||
92 | 250 | std::thread t4{execute, config.outgoing}; | ||
93 | 251 | 233 | ||
94 | 252 | trap->run(); | 234 | trap->run(); |
95 | 253 | 235 | ||
96 | 254 | config.incoming->stop(); | ||
97 | 255 | config.outgoing->stop(); | ||
98 | 256 | |||
99 | 257 | if (t1.joinable()) | ||
100 | 258 | t1.join(); | ||
101 | 259 | |||
102 | 260 | if (t2.joinable()) | ||
103 | 261 | t2.join(); | ||
104 | 262 | |||
105 | 263 | if (t3.joinable()) | ||
106 | 264 | t3.join(); | ||
107 | 265 | |||
108 | 266 | if (t4.joinable()) | ||
109 | 267 | t4.join(); | ||
110 | 268 | |||
111 | 269 | return EXIT_SUCCESS; | 236 | return EXIT_SUCCESS; |
112 | 270 | } | 237 | } |
113 | 271 | 238 | ||
114 | 272 | 239 | ||
115 | === modified file 'src/location_service/com/ubuntu/location/service/provider_daemon.cpp' | |||
116 | --- src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2014-10-27 21:58:16 +0000 | |||
117 | +++ src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2015-11-26 08:30:38 +0000 | |||
118 | @@ -25,6 +25,7 @@ | |||
119 | 25 | 25 | ||
120 | 26 | #include <com/ubuntu/location/service/configuration.h> | 26 | #include <com/ubuntu/location/service/configuration.h> |
121 | 27 | #include <com/ubuntu/location/service/program_options.h> | 27 | #include <com/ubuntu/location/service/program_options.h> |
122 | 28 | #include <com/ubuntu/location/service/runtime.h> | ||
123 | 28 | 29 | ||
124 | 29 | #include <core/dbus/asio/executor.h> | 30 | #include <core/dbus/asio/executor.h> |
125 | 30 | 31 | ||
126 | @@ -65,7 +66,6 @@ | |||
127 | 65 | location::service::ProviderDaemon::Configuration result; | 66 | location::service::ProviderDaemon::Configuration result; |
128 | 66 | 67 | ||
129 | 67 | result.connection = factory(mutable_daemon_options().bus()); | 68 | result.connection = factory(mutable_daemon_options().bus()); |
130 | 68 | result.connection->install_executor(core::dbus::asio::make_executor(result.connection)); | ||
131 | 69 | 69 | ||
132 | 70 | auto service = core::dbus::Service::add_service( | 70 | auto service = core::dbus::Service::add_service( |
133 | 71 | result.connection, | 71 | result.connection, |
134 | @@ -108,7 +108,7 @@ | |||
135 | 108 | return result; | 108 | return result; |
136 | 109 | } | 109 | } |
137 | 110 | 110 | ||
139 | 111 | int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& configuration) | 111 | int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& config) |
140 | 112 | { | 112 | { |
141 | 113 | auto trap = core::posix::trap_signals_for_all_subsequent_threads( | 113 | auto trap = core::posix::trap_signals_for_all_subsequent_threads( |
142 | 114 | { | 114 | { |
143 | @@ -121,27 +121,22 @@ | |||
144 | 121 | trap->stop(); | 121 | trap->stop(); |
145 | 122 | }); | 122 | }); |
146 | 123 | 123 | ||
154 | 124 | std::thread worker | 124 | auto runtime = location::service::Runtime::create(1); |
155 | 125 | { | 125 | |
156 | 126 | [configuration]() | 126 | config.connection->install_executor(core::dbus::asio::make_executor(config.connection, runtime->service())); |
150 | 127 | { | ||
151 | 128 | configuration.connection->run(); | ||
152 | 129 | } | ||
153 | 130 | }; | ||
157 | 131 | 127 | ||
158 | 132 | auto skeleton = location::providers::remote::skeleton::create_with_configuration(location::providers::remote::skeleton::Configuration | 128 | auto skeleton = location::providers::remote::skeleton::create_with_configuration(location::providers::remote::skeleton::Configuration |
159 | 133 | { | 129 | { |
163 | 134 | configuration.object, | 130 | config.object, |
164 | 135 | configuration.connection, | 131 | config.connection, |
165 | 136 | configuration.provider | 132 | config.provider |
166 | 137 | }); | 133 | }); |
167 | 138 | 134 | ||
168 | 135 | runtime->start(); | ||
169 | 136 | |||
170 | 139 | trap->run(); | 137 | trap->run(); |
171 | 140 | 138 | ||
176 | 141 | configuration.connection->stop(); | 139 | config.connection->stop(); |
173 | 142 | |||
174 | 143 | if (worker.joinable()) | ||
175 | 144 | worker.join(); | ||
177 | 145 | 140 | ||
178 | 146 | return EXIT_SUCCESS; | 141 | return EXIT_SUCCESS; |
179 | 147 | } | 142 | } |
180 | 148 | 143 | ||
181 | === added file 'src/location_service/com/ubuntu/location/service/runtime.cpp' | |||
182 | --- src/location_service/com/ubuntu/location/service/runtime.cpp 1970-01-01 00:00:00 +0000 | |||
183 | +++ src/location_service/com/ubuntu/location/service/runtime.cpp 2015-11-26 08:30:38 +0000 | |||
184 | @@ -0,0 +1,109 @@ | |||
185 | 1 | /* | ||
186 | 2 | * Copyright © 2015 Canonical Ltd. | ||
187 | 3 | * | ||
188 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
189 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
190 | 6 | * as published by the Free Software Foundation. | ||
191 | 7 | * | ||
192 | 8 | * This program is distributed in the hope that it will be useful, | ||
193 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
194 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the | ||
195 | 11 | * GNU Lesser General Public License for more details. | ||
196 | 12 | * | ||
197 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
198 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
199 | 15 | * | ||
200 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
201 | 17 | */ | ||
202 | 18 | #include <com/ubuntu/location/service/runtime.h> | ||
203 | 19 | |||
204 | 20 | #include <com/ubuntu/location/logging.h> | ||
205 | 21 | |||
206 | 22 | namespace culs = com::ubuntu::location::service; | ||
207 | 23 | |||
208 | 24 | namespace | ||
209 | 25 | { | ||
210 | 26 | // exception_safe_run runs service, catching all exceptions and | ||
211 | 27 | // restarting operation until an explicit shutdown has been requested. | ||
212 | 28 | // | ||
213 | 29 | // TODO(tvoss): Catching all exceptions is risky as they might signal unrecoverable | ||
214 | 30 | // errors. We should enable calling code to decide whether an exception should be considered | ||
215 | 31 | // fatal or not. | ||
216 | 32 | void exception_safe_run(boost::asio::io_service& service) | ||
217 | 33 | { | ||
218 | 34 | while (true) | ||
219 | 35 | { | ||
220 | 36 | try | ||
221 | 37 | { | ||
222 | 38 | service.run(); | ||
223 | 39 | // a clean return from run only happens in case of | ||
224 | 40 | // stop() being called (we are keeping the service alive with | ||
225 | 41 | // a service::work instance). | ||
226 | 42 | break; | ||
227 | 43 | } | ||
228 | 44 | catch (const std::exception& e) | ||
229 | 45 | { | ||
230 | 46 | LOG(WARNING) << e.what(); | ||
231 | 47 | } | ||
232 | 48 | catch (...) | ||
233 | 49 | { | ||
234 | 50 | LOG(WARNING) << "Unknown exception caught while executing boost::asio::io_service"; | ||
235 | 51 | } | ||
236 | 52 | } | ||
237 | 53 | } | ||
238 | 54 | } | ||
239 | 55 | |||
240 | 56 | std::shared_ptr<culs::Runtime> culs::Runtime::create(std::uint32_t pool_size) | ||
241 | 57 | { | ||
242 | 58 | return std::shared_ptr<culs::Runtime>(new culs::Runtime(pool_size)); | ||
243 | 59 | } | ||
244 | 60 | |||
245 | 61 | culs::Runtime::Runtime(std::uint32_t pool_size) | ||
246 | 62 | : pool_size_{pool_size}, | ||
247 | 63 | service_{pool_size_}, | ||
248 | 64 | strand_{service_}, | ||
249 | 65 | keep_alive_{service_} | ||
250 | 66 | { | ||
251 | 67 | } | ||
252 | 68 | |||
253 | 69 | culs::Runtime::~Runtime() | ||
254 | 70 | { | ||
255 | 71 | try | ||
256 | 72 | { | ||
257 | 73 | stop(); | ||
258 | 74 | } catch(...) | ||
259 | 75 | { | ||
260 | 76 | // Dropping all exceptions to satisfy the nothrow guarantee. | ||
261 | 77 | } | ||
262 | 78 | } | ||
263 | 79 | |||
264 | 80 | void culs::Runtime::start() | ||
265 | 81 | { | ||
266 | 82 | for (unsigned int i = 0; i < pool_size_; i++) | ||
267 | 83 | workers_.push_back(std::thread{exception_safe_run, std::ref(service_)}); | ||
268 | 84 | } | ||
269 | 85 | |||
270 | 86 | void culs::Runtime::stop() | ||
271 | 87 | { | ||
272 | 88 | service_.stop(); | ||
273 | 89 | |||
274 | 90 | for (auto& worker : workers_) | ||
275 | 91 | if (worker.joinable()) | ||
276 | 92 | worker.join(); | ||
277 | 93 | } | ||
278 | 94 | |||
279 | 95 | std::function<void(std::function<void()>)> culs::Runtime::to_dispatcher_functional() | ||
280 | 96 | { | ||
281 | 97 | // We have to make sure that we stay alive for as long as | ||
282 | 98 | // calling code requires the dispatcher to work. | ||
283 | 99 | auto sp = shared_from_this(); | ||
284 | 100 | return [sp](std::function<void()> task) | ||
285 | 101 | { | ||
286 | 102 | sp->strand_.post(task); | ||
287 | 103 | }; | ||
288 | 104 | } | ||
289 | 105 | |||
290 | 106 | boost::asio::io_service& culs::Runtime::service() | ||
291 | 107 | { | ||
292 | 108 | return service_; | ||
293 | 109 | } | ||
294 | 0 | 110 | ||
295 | === added file 'src/location_service/com/ubuntu/location/service/runtime.h' | |||
296 | --- src/location_service/com/ubuntu/location/service/runtime.h 1970-01-01 00:00:00 +0000 | |||
297 | +++ src/location_service/com/ubuntu/location/service/runtime.h 2015-11-26 08:30:38 +0000 | |||
298 | @@ -0,0 +1,90 @@ | |||
299 | 1 | /* | ||
300 | 2 | * Copyright © 2015 Canonical Ltd. | ||
301 | 3 | * | ||
302 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
303 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
304 | 6 | * as published by the Free Software Foundation. | ||
305 | 7 | * | ||
306 | 8 | * This program is distributed in the hope that it will be useful, | ||
307 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
308 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the | ||
309 | 11 | * GNU Lesser General Public License for more details. | ||
310 | 12 | * | ||
311 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
312 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
313 | 15 | * | ||
314 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
315 | 17 | */ | ||
316 | 18 | #ifndef COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_ | ||
317 | 19 | #define COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_ | ||
318 | 20 | |||
319 | 21 | #include <boost/asio.hpp> | ||
320 | 22 | |||
321 | 23 | #include <functional> | ||
322 | 24 | #include <memory> | ||
323 | 25 | #include <thread> | ||
324 | 26 | #include <vector> | ||
325 | 27 | |||
326 | 28 | #include <cstdint> | ||
327 | 29 | |||
328 | 30 | namespace com | ||
329 | 31 | { | ||
330 | 32 | namespace ubuntu | ||
331 | 33 | { | ||
332 | 34 | namespace location | ||
333 | 35 | { | ||
334 | 36 | namespace service | ||
335 | 37 | { | ||
336 | 38 | // We bundle our "global" runtime dependencies here, specifically | ||
337 | 39 | // a dispatcher to decouple multiple in-process providers from one | ||
338 | 40 | // another , forcing execution to a well known set of threads. | ||
339 | 41 | class Runtime : public std::enable_shared_from_this<Runtime> | ||
340 | 42 | { | ||
341 | 43 | public: | ||
342 | 44 | // Our default concurrency setup. | ||
343 | 45 | static constexpr const std::uint32_t worker_threads = 2; | ||
344 | 46 | |||
345 | 47 | // create returns a Runtime instance with pool_size worker threads | ||
346 | 48 | // executing the underlying service. | ||
347 | 49 | static std::shared_ptr<Runtime> create(std::uint32_t pool_size = worker_threads); | ||
348 | 50 | |||
349 | 51 | Runtime(const Runtime&) = delete; | ||
350 | 52 | Runtime(Runtime&&) = delete; | ||
351 | 53 | // Tears down the runtime, stopping all worker threads. | ||
352 | 54 | ~Runtime() noexcept(true); | ||
353 | 55 | Runtime& operator=(const Runtime&) = delete; | ||
354 | 56 | Runtime& operator=(Runtime&&) = delete; | ||
355 | 57 | |||
356 | 58 | // start executes the underlying io_service on a thread pool with | ||
357 | 59 | // the size configured at creation time. | ||
358 | 60 | void start(); | ||
359 | 61 | |||
360 | 62 | // stop cleanly shuts down a Runtime instance, | ||
361 | 63 | // joining all worker threads. | ||
362 | 64 | void stop(); | ||
363 | 65 | |||
364 | 66 | // to_dispatcher_functional returns a function for integration | ||
365 | 67 | // with components that expect a dispatcher for operation. | ||
366 | 68 | std::function<void(std::function<void()>)> to_dispatcher_functional(); | ||
367 | 69 | |||
368 | 70 | // service returns the underlying boost::asio::io_service that is executed | ||
369 | 71 | // by the Runtime. | ||
370 | 72 | boost::asio::io_service& service(); | ||
371 | 73 | |||
372 | 74 | private: | ||
373 | 75 | // Runtime constructs a new instance, firing up pool_size | ||
374 | 76 | // worker threads. | ||
375 | 77 | Runtime(std::uint32_t pool_size); | ||
376 | 78 | |||
377 | 79 | std::uint32_t pool_size_; | ||
378 | 80 | boost::asio::io_service service_; | ||
379 | 81 | boost::asio::io_service::strand strand_; | ||
380 | 82 | boost::asio::io_service::work keep_alive_; | ||
381 | 83 | std::vector<std::thread> workers_; | ||
382 | 84 | }; | ||
383 | 85 | } | ||
384 | 86 | } | ||
385 | 87 | } | ||
386 | 88 | } | ||
387 | 89 | |||
388 | 90 | #endif // COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_ | ||
389 | 0 | 91 | ||
390 | === modified file 'tests/CMakeLists.txt' | |||
391 | --- tests/CMakeLists.txt 2015-04-23 17:04:09 +0000 | |||
392 | +++ tests/CMakeLists.txt 2015-11-26 08:30:38 +0000 | |||
393 | @@ -92,6 +92,7 @@ | |||
394 | 92 | LOCATION_SERVICE_ADD_TEST(provider_test provider_test.cpp) | 92 | LOCATION_SERVICE_ADD_TEST(provider_test provider_test.cpp) |
395 | 93 | LOCATION_SERVICE_ADD_TEST(wgs84_test wgs84_test.cpp) | 93 | LOCATION_SERVICE_ADD_TEST(wgs84_test wgs84_test.cpp) |
396 | 94 | LOCATION_SERVICE_ADD_TEST(trust_store_permission_manager_test trust_store_permission_manager_test.cpp) | 94 | LOCATION_SERVICE_ADD_TEST(trust_store_permission_manager_test trust_store_permission_manager_test.cpp) |
397 | 95 | LOCATION_SERVICE_ADD_TEST(runtime_test runtime_test.cpp) | ||
398 | 95 | 96 | ||
399 | 96 | # Provider-specific test-cases go here. | 97 | # Provider-specific test-cases go here. |
400 | 97 | if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER) | 98 | if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER) |
401 | 98 | 99 | ||
402 | === modified file 'tests/acceptance_tests.cpp' | |||
403 | --- tests/acceptance_tests.cpp 2015-02-13 13:19:18 +0000 | |||
404 | +++ tests/acceptance_tests.cpp 2015-11-26 08:30:38 +0000 | |||
405 | @@ -38,12 +38,14 @@ | |||
406 | 38 | #include <com/ubuntu/location/service/stub.h> | 38 | #include <com/ubuntu/location/service/stub.h> |
407 | 39 | 39 | ||
408 | 40 | #include <core/dbus/announcer.h> | 40 | #include <core/dbus/announcer.h> |
409 | 41 | #include <core/dbus/bus.h> | ||
410 | 41 | #include <core/dbus/fixture.h> | 42 | #include <core/dbus/fixture.h> |
411 | 42 | #include <core/dbus/resolver.h> | 43 | #include <core/dbus/resolver.h> |
412 | 43 | 44 | ||
413 | 44 | #include <core/dbus/asio/executor.h> | 45 | #include <core/dbus/asio/executor.h> |
414 | 45 | 46 | ||
415 | 46 | #include <core/posix/signal.h> | 47 | #include <core/posix/signal.h> |
416 | 48 | #include <core/posix/this_process.h> | ||
417 | 47 | 49 | ||
418 | 48 | #include <core/testing/cross_process_sync.h> | 50 | #include <core/testing/cross_process_sync.h> |
419 | 49 | #include <core/testing/fork_and_run.h> | 51 | #include <core/testing/fork_and_run.h> |
420 | @@ -708,7 +710,7 @@ | |||
421 | 708 | 710 | ||
422 | 709 | options.add(Keys::update_period, | 711 | options.add(Keys::update_period, |
423 | 710 | "Update period length for dummy::Provider setup.", | 712 | "Update period length for dummy::Provider setup.", |
425 | 711 | std::uint32_t{100}); | 713 | std::uint32_t{10}); |
426 | 712 | 714 | ||
427 | 713 | options.add(Keys::client_count, | 715 | options.add(Keys::client_count, |
428 | 714 | "Number of clients that should be fired up.", | 716 | "Number of clients that should be fired up.", |
429 | @@ -761,6 +763,8 @@ | |||
430 | 761 | }; | 763 | }; |
431 | 762 | } | 764 | } |
432 | 763 | 765 | ||
433 | 766 | #include "did_finish_successfully.h" | ||
434 | 767 | |||
435 | 764 | TEST_F(LocationServiceStandaloneLoad, MultipleClientsConnectingAndDisconnectingWorks) | 768 | TEST_F(LocationServiceStandaloneLoad, MultipleClientsConnectingAndDisconnectingWorks) |
436 | 765 | { | 769 | { |
437 | 766 | EXPECT_TRUE(trust_store_is_set_up_for_testing); | 770 | EXPECT_TRUE(trust_store_is_set_up_for_testing); |
438 | @@ -801,8 +805,8 @@ | |||
439 | 801 | }; | 805 | }; |
440 | 802 | 806 | ||
441 | 803 | cul::service::Daemon::Configuration config; | 807 | cul::service::Daemon::Configuration config; |
444 | 804 | config.incoming = session_bus(); | 808 | config.incoming = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS")); |
445 | 805 | config.outgoing = session_bus(); | 809 | config.outgoing = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS")); |
446 | 806 | config.is_testing_enabled = false; | 810 | config.is_testing_enabled = false; |
447 | 807 | config.providers = | 811 | config.providers = |
448 | 808 | { | 812 | { |
449 | @@ -829,7 +833,7 @@ | |||
450 | 829 | status; | 833 | status; |
451 | 830 | }, core::posix::StandardStream::empty); | 834 | }, core::posix::StandardStream::empty); |
452 | 831 | 835 | ||
454 | 832 | std::this_thread::sleep_for(std::chrono::seconds{2}); | 836 | std::this_thread::sleep_for(std::chrono::seconds{15}); |
455 | 833 | 837 | ||
456 | 834 | auto client = [this]() | 838 | auto client = [this]() |
457 | 835 | { | 839 | { |
458 | @@ -957,17 +961,11 @@ | |||
459 | 957 | { | 961 | { |
460 | 958 | VLOG(1) << "Stopping client...: " << client.pid(); | 962 | VLOG(1) << "Stopping client...: " << client.pid(); |
461 | 959 | client.send_signal_or_throw(core::posix::Signal::sig_term); | 963 | client.send_signal_or_throw(core::posix::Signal::sig_term); |
466 | 960 | auto result = client.wait_for(core::posix::wait::Flags::untraced); | 964 | EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced))); |
463 | 961 | |||
464 | 962 | EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); | ||
465 | 963 | EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); | ||
467 | 964 | } | 965 | } |
468 | 965 | 966 | ||
469 | 966 | VLOG(1) << "Cleaned up clients, shutting down the service..."; | 967 | VLOG(1) << "Cleaned up clients, shutting down the service..."; |
470 | 967 | 968 | ||
471 | 968 | server.send_signal_or_throw(core::posix::Signal::sig_term); | 969 | server.send_signal_or_throw(core::posix::Signal::sig_term); |
476 | 969 | auto result = server.wait_for(core::posix::wait::Flags::untraced); | 970 | EXPECT_TRUE(did_finish_successfully(server.wait_for(core::posix::wait::Flags::untraced))); |
473 | 970 | |||
474 | 971 | EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status); | ||
475 | 972 | EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status); | ||
477 | 973 | } | 971 | } |
478 | 974 | 972 | ||
479 | === modified file 'tests/position_test.cpp' | |||
480 | --- tests/position_test.cpp 2014-06-20 07:40:34 +0000 | |||
481 | +++ tests/position_test.cpp 2015-11-26 08:30:38 +0000 | |||
482 | @@ -40,7 +40,7 @@ | |||
483 | 40 | cul::wgs84::Latitude{}, | 40 | cul::wgs84::Latitude{}, |
484 | 41 | cul::wgs84::Longitude{}, | 41 | cul::wgs84::Longitude{}, |
485 | 42 | cul::wgs84::Altitude{}}; | 42 | cul::wgs84::Altitude{}}; |
487 | 43 | EXPECT_TRUE(p.altitude); | 43 | EXPECT_TRUE(p.altitude ? true : false); |
488 | 44 | } | 44 | } |
489 | 45 | 45 | ||
490 | 46 | #include <com/ubuntu/location/codec.h> | 46 | #include <com/ubuntu/location/codec.h> |
491 | 47 | 47 | ||
492 | === added file 'tests/runtime_test.cpp' | |||
493 | --- tests/runtime_test.cpp 1970-01-01 00:00:00 +0000 | |||
494 | +++ tests/runtime_test.cpp 2015-11-26 08:30:38 +0000 | |||
495 | @@ -0,0 +1,118 @@ | |||
496 | 1 | /* | ||
497 | 2 | * Copyright © 2015Canonical Ltd. | ||
498 | 3 | * | ||
499 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
500 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
501 | 6 | * as published by the Free Software Foundation. | ||
502 | 7 | * | ||
503 | 8 | * This program is distributed in the hope that it will be useful, | ||
504 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
505 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
506 | 11 | * GNU Lesser General Public License for more details. | ||
507 | 12 | * | ||
508 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
509 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
510 | 15 | * | ||
511 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
512 | 17 | */ | ||
513 | 18 | #include <com/ubuntu/location/service/runtime.h> | ||
514 | 19 | |||
515 | 20 | #include <gtest/gtest.h> | ||
516 | 21 | |||
517 | 22 | #include <condition_variable> | ||
518 | 23 | #include <thread> | ||
519 | 24 | |||
520 | 25 | namespace culs = com::ubuntu::location::service; | ||
521 | 26 | |||
522 | 27 | TEST(Runtime, cleanly_shuts_down_threads) | ||
523 | 28 | { | ||
524 | 29 | culs::Runtime::create(); | ||
525 | 30 | } | ||
526 | 31 | |||
527 | 32 | TEST(Runtime, executes_service) | ||
528 | 33 | { | ||
529 | 34 | std::mutex m; | ||
530 | 35 | std::unique_lock<std::mutex> ul{m}; | ||
531 | 36 | std::condition_variable wc; | ||
532 | 37 | |||
533 | 38 | bool signaled = false; | ||
534 | 39 | |||
535 | 40 | auto rt = culs::Runtime::create(); | ||
536 | 41 | rt->start(); | ||
537 | 42 | boost::asio::deadline_timer timer{rt->service(), boost::posix_time::milliseconds(500)}; | ||
538 | 43 | timer.async_wait([&wc, &signaled](const boost::system::error_code&) | ||
539 | 44 | { | ||
540 | 45 | signaled = true; | ||
541 | 46 | wc.notify_all(); | ||
542 | 47 | }); | ||
543 | 48 | |||
544 | 49 | auto result = wc.wait_for(ul, std::chrono::seconds{1}, [&signaled]() { return signaled; }); | ||
545 | 50 | EXPECT_TRUE(result); | ||
546 | 51 | } | ||
547 | 52 | |||
548 | 53 | TEST(Runtime, catches_exceptions_thrown_from_handlers) | ||
549 | 54 | { | ||
550 | 55 | std::mutex m; | ||
551 | 56 | std::unique_lock<std::mutex> ul{m}; | ||
552 | 57 | std::condition_variable wc; | ||
553 | 58 | |||
554 | 59 | bool signaled = false; | ||
555 | 60 | |||
556 | 61 | auto rt = culs::Runtime::create(); | ||
557 | 62 | rt->start(); | ||
558 | 63 | boost::asio::deadline_timer fast{rt->service(), boost::posix_time::milliseconds(100)}; | ||
559 | 64 | fast.async_wait([](const boost::system::error_code&) | ||
560 | 65 | { | ||
561 | 66 | throw std::runtime_error{"Should not propagate"}; | ||
562 | 67 | }); | ||
563 | 68 | |||
564 | 69 | boost::asio::deadline_timer slow{rt->service(), boost::posix_time::milliseconds(500)}; | ||
565 | 70 | slow.async_wait([&wc, &signaled](const boost::system::error_code&) | ||
566 | 71 | { | ||
567 | 72 | signaled = true; | ||
568 | 73 | wc.notify_all(); | ||
569 | 74 | }); | ||
570 | 75 | |||
571 | 76 | auto result = wc.wait_for(ul, std::chrono::seconds{1}, [&signaled]() { return signaled; }); | ||
572 | 77 | EXPECT_TRUE(result); | ||
573 | 78 | } | ||
574 | 79 | |||
575 | 80 | // sets_up_pool_of_threads ensures that the pool size | ||
576 | 81 | // passed to the Runtime on construction is honored. The idea is simple: | ||
577 | 82 | // We set up two deadline timers, fast and slow. fast fires before slow, | ||
578 | 83 | // with fast blocking in a wait on a common condition_variable. When slow | ||
579 | 84 | // fires, it notifies the condition variable, thereby unblocking the handler of fast, | ||
580 | 85 | // enabling clean shutdown without errors and timeouts. This only works if the | ||
581 | 86 | // pool contains at least 2 threads. Otherwise, the handler of slow would not be executed | ||
582 | 87 | // until the handler of fast times out in the wait, marking the test as failed. | ||
583 | 88 | TEST(Runtime, sets_up_pool_of_threads) | ||
584 | 89 | { | ||
585 | 90 | struct State | ||
586 | 91 | { | ||
587 | 92 | bool signaled{false}; | ||
588 | 93 | std::mutex m; | ||
589 | 94 | std::condition_variable wc; | ||
590 | 95 | }; | ||
591 | 96 | |||
592 | 97 | auto state = std::make_shared<State>(); | ||
593 | 98 | |||
594 | 99 | auto rt = culs::Runtime::create(2); | ||
595 | 100 | rt->start(); | ||
596 | 101 | boost::asio::deadline_timer fast{rt->service(), boost::posix_time::milliseconds(100)}; | ||
597 | 102 | fast.async_wait([state](const boost::system::error_code&) | ||
598 | 103 | { | ||
599 | 104 | std::unique_lock<std::mutex> ul{state->m}; | ||
600 | 105 | EXPECT_TRUE(state->wc.wait_for(ul, std::chrono::seconds{1}, [state]() { return state->signaled; })); | ||
601 | 106 | }); | ||
602 | 107 | |||
603 | 108 | boost::asio::deadline_timer slow{rt->service(), boost::posix_time::milliseconds(500)}; | ||
604 | 109 | slow.async_wait([state](const boost::system::error_code&) | ||
605 | 110 | { | ||
606 | 111 | state->signaled = true; | ||
607 | 112 | state->wc.notify_all(); | ||
608 | 113 | }); | ||
609 | 114 | |||
610 | 115 | std::unique_lock<std::mutex> ul{state->m}; | ||
611 | 116 | auto result = state->wc.wait_for(ul, std::chrono::seconds{1}, [state]() { return state->signaled; }); | ||
612 | 117 | EXPECT_TRUE(result); | ||
613 | 118 | } |
LGTM!