Merge lp:~marcustomlinson/unity-scopes-api/online_accounts_tests into lp:unity-scopes-api
- online_accounts_tests
- Merge into trunk
Proposed by
Marcus Tomlinson
Status: | Superseded |
---|---|
Proposed branch: | lp:~marcustomlinson/unity-scopes-api/online_accounts_tests |
Merge into: | lp:unity-scopes-api |
Prerequisite: | lp:~marcustomlinson/unity-scopes-api/fix_ui_policy |
Diff against target: |
1558 lines (+1046/-146) 13 files modified
CMakeLists.txt (+1/-1) HACKING (+22/-1) RELEASE_NOTES.md (+5/-0) debian/changelog (+7/-0) debian/control (+3/-1) include/unity/scopes/OnlineAccountClient.h (+15/-9) include/unity/scopes/internal/OnlineAccountClientImpl.h (+24/-13) src/scopes/internal/OnlineAccountClientImpl.cpp (+359/-113) src/scopes/internal/RegistryObject.cpp (+11/-1) test/gtest/scopes/OnlineAccountClient/CMakeLists.txt (+8/-0) test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp (+544/-7) test/gtest/scopes/OnlineAccountClient/data/TestService.service (+26/-0) valgrind-suppress (+21/-0) |
To merge this branch: | bzr merge lp:~marcustomlinson/unity-scopes-api/online_accounts_tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paweł Stołowski (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+237217@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-10-08.
Commit message
Added tests for OnlineAccountClient
Description of the change
To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Approve
(continuous-integration)
- 277. By Marcus Tomlinson
-
Merged devel
- 278. By Marcus Tomlinson
-
Merged fix_ui_policy
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-09-11 08:35:01 +0000 |
3 | +++ CMakeLists.txt 2014-10-08 11:00:01 +0000 |
4 | @@ -195,7 +195,7 @@ |
5 | # API version |
6 | set(UNITY_SCOPES_MAJOR 0) |
7 | set(UNITY_SCOPES_MINOR 6) |
8 | -set(UNITY_SCOPES_MICRO 6) |
9 | +set(UNITY_SCOPES_MICRO 7) |
10 | set(UNITY_SCOPES_SOVERSION 3) |
11 | |
12 | # Version for testing, with all symbols visible |
13 | |
14 | === modified file 'HACKING' |
15 | --- HACKING 2014-09-08 22:15:40 +0000 |
16 | +++ HACKING 2014-10-08 11:00:01 +0000 |
17 | @@ -156,7 +156,28 @@ |
18 | This creates a diff of the symbols in /tmp/symbols.diff. |
19 | (The demangled symbols from the debian build are in ./new_symbols.) |
20 | |
21 | -Review any changes in /tmp/symbols.diff. If they are OK: |
22 | +NOTE: We currently have one architecture-specific symbol: |
23 | + |
24 | +(c++|arch=amd64)"unity::scopes::internal::RegistryObject::ScopeExecData::ScopeExecData(unity::scopes::internal::RegistryObject::ScopeExecData const&)@Base" 0.6.6+14.10.20140916 |
25 | + |
26 | +We need this because the copy-constructor is inlined on i386 and armhf. |
27 | + |
28 | +The above script can't cope with the arch tag at the moment. Until we get |
29 | +around to fixing this, you need to delete the corresponding change from |
30 | +the diff output before applying the diff as a patch. The offending diff |
31 | +will look something like this: |
32 | + |
33 | +@@ -377,7 +378,7 @@ |
34 | + (c++)"unity::scopes::internal::RegistryObject::remove_desktop_file(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.6.6+14.10.20140916 |
35 | + (c++)"unity::scopes::internal::RegistryObject::remove_local_scope(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
36 | + (c++)"unity::scopes::internal::RegistryObject::ScopeExecData::~ScopeExecData()@Base" 0.4.2+14.04.20140404.2 |
37 | +- (c++|arch=amd64)"unity::scopes::internal::RegistryObject::ScopeExecData::ScopeExecData(unity::scopes::internal::RegistryObject::ScopeExecData const&)@Base" 0.6.6+14.10.20140916 |
38 | ++ (c++)"unity::scopes::internal::RegistryObject::ScopeExecData::ScopeExecData(unity::scopes::internal::RegistryObject::ScopeExecData const&)@Base" 0replaceme |
39 | + (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::clear_handle_unlocked()@Base" 0.4.2+14.04.20140404.2 |
40 | + (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::exec(core::posix::ChildProcess::DeathObserver&, std::shared_ptr<unity::scopes::internal::Executor>)@Base" 0.4.3+14.10.20140428 |
41 | + (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::expand_custom_exec()@Base" 0.5.0+14.10.20140619 |
42 | + |
43 | +Review any other changes in /tmp/symbols.diff. If they are OK: |
44 | |
45 | $ cd - |
46 | $ patch -p0 < /tmp/symbols.diff |
47 | |
48 | === modified file 'RELEASE_NOTES.md' |
49 | --- RELEASE_NOTES.md 2014-09-11 08:42:38 +0000 |
50 | +++ RELEASE_NOTES.md 2014-10-08 11:00:01 +0000 |
51 | @@ -1,6 +1,11 @@ |
52 | Release notes |
53 | ============= |
54 | |
55 | +Changes in version 0.6.7 |
56 | +======================== |
57 | + - Added new RunInExternalUiMainLoop option to OnlineAccountClient::MainLoopSelect. |
58 | + - OnlineAccountClient signon UI policy determined by main loop used (shell: show / scope: hide). |
59 | + |
60 | Changes in version 0.6.6 |
61 | ======================== |
62 | - Added support for online accounts (via new OnlineAccountClient class). |
63 | |
64 | === modified file 'debian/changelog' |
65 | --- debian/changelog 2014-10-06 12:03:20 +0000 |
66 | +++ debian/changelog 2014-10-08 11:00:01 +0000 |
67 | @@ -1,3 +1,10 @@ |
68 | +unity-scopes-api (0.6.7-0ubuntu1) UNRELEASED; urgency=medium |
69 | + |
70 | + * Added new RunInExternalUiMainLoop option to OnlineAccountClient::MainLoopSelect. |
71 | + * OnlineAccountClient signon UI policy determined by main loop used (shell: show / scope: hide). |
72 | + |
73 | + -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Wed, 01 Oct 2014 15:46:30 +0200 |
74 | + |
75 | unity-scopes-api (0.6.6+14.10.20141006-0ubuntu1) utopic; urgency=medium |
76 | |
77 | [ Pawel Stolowski ] |
78 | |
79 | === modified file 'debian/control' |
80 | --- debian/control 2014-09-23 08:33:51 +0000 |
81 | +++ debian/control 2014-10-08 11:00:01 +0000 |
82 | @@ -26,6 +26,8 @@ |
83 | libjsoncpp-dev, |
84 | libaccounts-glib-dev, |
85 | libsignon-glib-dev, |
86 | + dbus-test-runner, |
87 | + libdbustest1-dev, |
88 | valgrind, |
89 | Standards-Version: 3.9.5 |
90 | XS-Testsuite: autopkgtest |
91 | @@ -81,4 +83,4 @@ |
92 | Multi-Arch: foreign |
93 | Depends: ${misc:Depends}, |
94 | Description: Documentation for Unity scopes API |
95 | - Library to integrate scopes with the Unity shell (documentation) |
96 | \ No newline at end of file |
97 | + Library to integrate scopes with the Unity shell (documentation) |
98 | |
99 | === modified file 'include/unity/scopes/OnlineAccountClient.h' |
100 | --- include/unity/scopes/OnlineAccountClient.h 2014-09-15 05:10:17 +0000 |
101 | +++ include/unity/scopes/OnlineAccountClient.h 2014-10-08 11:00:01 +0000 |
102 | @@ -37,6 +37,11 @@ |
103 | class OnlineAccountClientImpl; |
104 | } |
105 | |
106 | +namespace testing |
107 | +{ |
108 | +class OnlineAccountClientTest; |
109 | +} |
110 | + |
111 | /** |
112 | \brief A simple interface for integrating online accounts access and monitoring into scopes. |
113 | |
114 | @@ -55,7 +60,7 @@ |
115 | */ |
116 | struct ServiceStatus |
117 | { |
118 | - uint account_id; ///< A unique ID of the online account parenting this service. |
119 | + int account_id; ///< A unique ID of the online account parenting this service. |
120 | bool service_enabled; ///< True if this service is enabled. |
121 | bool service_authenticated; ///< True if this service is authenticated. |
122 | std::string client_id; ///< "ConsumerKey" / "ClientId" OAuth (1 / 2) parameter. |
123 | @@ -68,16 +73,15 @@ |
124 | /** |
125 | \brief Indicates whether an external main loop already exists, or one should be created internally. |
126 | |
127 | - A running main loop is essential in order to receive service update callbacks. When in doubt, set |
128 | - RunInExternalMainLoop and just use refresh_service_statuses() and get_service_statuses() to obtain |
129 | - service statuses. |
130 | + A running main loop is essential in order to receive service updates from the online accounts |
131 | + backend. When in doubt, set to CreateInternalMainLoop. |
132 | */ |
133 | enum MainLoopSelect |
134 | { |
135 | - RunInExternalMainLoop, ///< An external main loop already exists or the service update |
136 | - /// callback is not required. |
137 | - CreateInternalMainLoop ///< An external main loop does not exist and the service update |
138 | - /// callback is required. |
139 | + RunInExternalMainLoop, ///< An external main loop already exists and is running. |
140 | + CreateInternalMainLoop, ///< An external main loop does not exist. |
141 | + RunInExternalUiMainLoop, ///< An external UI main loop exists and is running (Intended for |
142 | + /// shell use only. A scope should not be running a UI main loop). |
143 | }; |
144 | |
145 | /** |
146 | @@ -91,7 +95,7 @@ |
147 | OnlineAccountClient(std::string const& service_name, |
148 | std::string const& service_type, |
149 | std::string const& provider_name, |
150 | - MainLoopSelect main_loop_select = RunInExternalMainLoop); |
151 | + MainLoopSelect main_loop_select = CreateInternalMainLoop); |
152 | |
153 | /// @cond |
154 | ~OnlineAccountClient(); |
155 | @@ -160,6 +164,8 @@ |
156 | |
157 | private: |
158 | std::unique_ptr<internal::OnlineAccountClientImpl> p; |
159 | + |
160 | + friend class testing::OnlineAccountClientTest; |
161 | }; |
162 | |
163 | } // namespace scopes |
164 | |
165 | === modified file 'include/unity/scopes/internal/OnlineAccountClientImpl.h' |
166 | --- include/unity/scopes/internal/OnlineAccountClientImpl.h 2014-09-11 11:29:29 +0000 |
167 | +++ include/unity/scopes/internal/OnlineAccountClientImpl.h 2014-10-08 11:00:01 +0000 |
168 | @@ -19,6 +19,7 @@ |
169 | #ifndef UNITY_SCOPES_INTERNAL_ONLINEACCOUNTCLIENTIMPL_H |
170 | #define UNITY_SCOPES_INTERNAL_ONLINEACCOUNTCLIENTIMPL_H |
171 | |
172 | +#include <unity/scopes/internal/MiddlewareBase.h> |
173 | #include <unity/scopes/OnlineAccountClient.h> |
174 | |
175 | #include <libaccounts-glib/accounts-glib.h> |
176 | @@ -78,42 +79,52 @@ |
177 | OnlineAccountClient::PostLoginAction login_failed_action); |
178 | |
179 | // Methods used only by impl |
180 | - void flush_pending_sessions(); |
181 | + void construct(); |
182 | + void tear_down(); |
183 | + |
184 | + void flush_pending_session(AgAccountId const& account_id, std::unique_lock<std::mutex>& lock); |
185 | |
186 | void main_loop_state_notify(bool is_running); |
187 | |
188 | + std::shared_ptr<AgManager> manager(); |
189 | std::string service_name(); |
190 | - void callback(OnlineAccountClient::ServiceStatus const& service_status); |
191 | + OnlineAccountClient::MainLoopSelect main_loop_select(); |
192 | + std::shared_ptr<GMainContext> main_loop_context(); |
193 | + |
194 | + void callback(AccountInfo const* info, std::string const& error = ""); |
195 | |
196 | bool has_account(AgAccountId const& account_id); |
197 | void add_account(AgAccountId const& account_id, std::shared_ptr<AccountInfo> account_info); |
198 | void remove_account(AgAccountId const& account_id); |
199 | |
200 | - bool inc_logins(); |
201 | - void dec_logins(); |
202 | - |
203 | private: |
204 | - std::string service_name_; |
205 | - std::string service_type_; |
206 | - std::string provider_name_; |
207 | + std::string const service_name_; |
208 | + std::string const service_type_; |
209 | + std::string const provider_name_; |
210 | + OnlineAccountClient::MainLoopSelect const main_loop_select_; |
211 | + |
212 | + std::mutex callback_mutex_; |
213 | OnlineAccountClient::ServiceUpdateCallback callback_; |
214 | - bool use_external_main_loop_; |
215 | |
216 | - std::thread main_loop_thread_; |
217 | - std::mutex callback_mutex_; |
218 | std::mutex mutex_; |
219 | std::condition_variable cond_; |
220 | + std::thread main_loop_thread_; |
221 | bool main_loop_is_running_; |
222 | - bool client_stopping_; |
223 | - int logins_busy_; |
224 | + std::exception_ptr thread_exception_; |
225 | gulong account_enabled_signal_id_; |
226 | gulong account_deleted_signal_id_; |
227 | |
228 | std::shared_ptr<GMainLoop> main_loop_; |
229 | + std::shared_ptr<GMainContext> main_loop_context_; |
230 | std::shared_ptr<AgManager> manager_; |
231 | std::map<AgAccountId, std::shared_ptr<AccountInfo>> accounts_; |
232 | |
233 | + MiddlewareBase::SPtr mw_; |
234 | + MWPublisher::UPtr auth_publisher_; |
235 | + MWSubscriber::UPtr auth_subscriber_; |
236 | + |
237 | void main_loop_thread(); |
238 | + void auth_callback(std::string const& details_json); |
239 | }; |
240 | |
241 | } // namespace internal |
242 | |
243 | === modified file 'src/scopes/internal/OnlineAccountClientImpl.cpp' |
244 | --- src/scopes/internal/OnlineAccountClientImpl.cpp 2014-09-15 07:06:51 +0000 |
245 | +++ src/scopes/internal/OnlineAccountClientImpl.cpp 2014-10-08 11:00:01 +0000 |
246 | @@ -17,7 +17,12 @@ |
247 | */ |
248 | |
249 | #include <unity/scopes/internal/OnlineAccountClientImpl.h> |
250 | -#include <unity/util/ResourcePtr.h> |
251 | + |
252 | +#include <unity/scopes/internal/JsonCppNode.h> |
253 | +#include <unity/scopes/internal/MiddlewareFactory.h> |
254 | +#include <unity/scopes/internal/RuntimeConfig.h> |
255 | +#include <unity/scopes/internal/RuntimeImpl.h> |
256 | +#include <unity/UnityExceptions.h> |
257 | |
258 | #include <iostream> |
259 | |
260 | @@ -88,7 +93,41 @@ |
261 | return service_status; |
262 | } |
263 | |
264 | -static void clear_session_info(AccountInfo* info) |
265 | +static std::string details_to_json(OnlineAccountClient::ServiceStatus const& details) |
266 | +{ |
267 | + VariantMap vm; |
268 | + vm["account_id"] = details.account_id; |
269 | + vm["service_enabled"] = details.service_enabled; |
270 | + vm["service_authenticated"] = details.service_authenticated; |
271 | + vm["client_id"] = details.client_id; |
272 | + vm["client_secret"] = details.client_secret; |
273 | + vm["access_token"] = details.access_token; |
274 | + vm["token_secret"] = details.token_secret; |
275 | + vm["error"] = details.error; |
276 | + |
277 | + Variant var(vm); |
278 | + JsonCppNode node(var); |
279 | + return node.to_json_string(); |
280 | +} |
281 | + |
282 | +static OnlineAccountClient::ServiceStatus json_to_details(std::string const& json) |
283 | +{ |
284 | + OnlineAccountClient::ServiceStatus details; |
285 | + JsonCppNode node(json); |
286 | + |
287 | + details.account_id = node.get_node("account_id")->as_int(); |
288 | + details.service_enabled = node.get_node("service_enabled")->as_bool(); |
289 | + details.service_authenticated = node.get_node("service_authenticated")->as_bool(); |
290 | + details.client_id = node.get_node("client_id")->as_string(); |
291 | + details.client_secret = node.get_node("client_secret")->as_string(); |
292 | + details.access_token = node.get_node("access_token")->as_string(); |
293 | + details.token_secret = node.get_node("token_secret")->as_string(); |
294 | + details.error = node.get_node("error")->as_string(); |
295 | + |
296 | + return details; |
297 | +} |
298 | + |
299 | +static void clear_session(AccountInfo* info) |
300 | { |
301 | if (info->session) |
302 | { |
303 | @@ -96,8 +135,6 @@ |
304 | signon_auth_session_cancel(info->session.get()); |
305 | } |
306 | info->session = nullptr; |
307 | - info->auth_params = nullptr; |
308 | - info->session_data = nullptr; |
309 | } |
310 | |
311 | static gboolean main_loop_is_running_cb(void* user_data) |
312 | @@ -107,6 +144,13 @@ |
313 | return G_SOURCE_REMOVE; |
314 | } |
315 | |
316 | +static gboolean main_loop_is_stopping_cb(void* user_data) |
317 | +{ |
318 | + OnlineAccountClientImpl* account_client = reinterpret_cast<OnlineAccountClientImpl*>(user_data); |
319 | + account_client->main_loop_state_notify(false); |
320 | + return G_SOURCE_REMOVE; |
321 | +} |
322 | + |
323 | static gboolean wake_up_event_loop_cb(void* user_data) |
324 | { |
325 | GMainLoop* event_loop = reinterpret_cast<GMainLoop*>(user_data); |
326 | @@ -116,58 +160,75 @@ |
327 | |
328 | static void service_login_cb(GObject* source, GAsyncResult* result, void* user_data) |
329 | { |
330 | - GError* error = nullptr; |
331 | - util::ResourcePtr<GError*, decltype(&g_error_free)> error_cleanup(error, free_error); |
332 | - |
333 | SignonAuthSession* session = reinterpret_cast<SignonAuthSession*>(source); |
334 | AccountInfo* info = reinterpret_cast<AccountInfo*>(user_data); |
335 | |
336 | // Get session data then send a notification with the login result |
337 | + GError* error = nullptr; |
338 | info->session_data.reset(signon_auth_session_process_finish(session, result, &error), free_variant); |
339 | - info->account_client->callback(info_to_details(info, error ? error->message : "")); |
340 | - info->account_client->dec_logins(); |
341 | + std::shared_ptr<GError> error_cleanup(error, free_error); |
342 | + |
343 | + info->account_client->callback(info, error ? error->message : ""); |
344 | + |
345 | + // Clear session info |
346 | + clear_session(info); |
347 | } |
348 | |
349 | static void service_update_cb(AgAccountService* account_service, gboolean enabled, AccountInfo* info) |
350 | { |
351 | - GError* error = nullptr; |
352 | - util::ResourcePtr<GError*, decltype(&g_error_free)> error_cleanup(error, free_error); |
353 | - |
354 | // Service state has updated, clear the old session data |
355 | info->service_enabled = enabled; |
356 | - clear_session_info(info); |
357 | + clear_session(info); |
358 | |
359 | if (enabled) |
360 | { |
361 | // Get authorization data then create a new authorization session |
362 | std::shared_ptr<AgAuthData> auth_data(ag_account_service_get_auth_data(account_service), ag_auth_data_unref); |
363 | + |
364 | + GError* error = nullptr; |
365 | info->session.reset(signon_auth_session_new( |
366 | ag_auth_data_get_credentials_id(auth_data.get()), ag_auth_data_get_method(auth_data.get()), &error), g_object_unref); |
367 | + std::shared_ptr<GError> error_cleanup(error, free_error); |
368 | + |
369 | if (error) |
370 | { |
371 | // Send notification that the authorization session failed |
372 | - info->account_client->callback(info_to_details(info, error->message)); |
373 | + info->account_client->callback(info, error->message); // LCOV_EXCL_LINE |
374 | return; |
375 | } |
376 | |
377 | // Get authorization parameters then attempt to signon |
378 | + GVariantBuilder builder; |
379 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); |
380 | + |
381 | + if (info->account_client->main_loop_select() == OnlineAccountClient::RunInExternalUiMainLoop) |
382 | + { |
383 | + g_variant_builder_add(&builder, "{sv}", |
384 | + SIGNON_SESSION_DATA_UI_POLICY, |
385 | + g_variant_new_int32(SIGNON_POLICY_DEFAULT)); // LCOV_EXCL_LINE |
386 | + } |
387 | + else |
388 | + { |
389 | + g_variant_builder_add(&builder, "{sv}", |
390 | + SIGNON_SESSION_DATA_UI_POLICY, |
391 | + g_variant_new_int32(SIGNON_POLICY_NO_USER_INTERACTION)); |
392 | + } |
393 | + |
394 | info->auth_params.reset( |
395 | - g_variant_ref_sink(ag_auth_data_get_login_parameters(auth_data.get(), nullptr)), free_variant); |
396 | + g_variant_ref_sink(ag_auth_data_get_login_parameters(auth_data.get(), g_variant_builder_end(&builder))), free_variant); |
397 | |
398 | - if (info->account_client->inc_logins()) |
399 | - { |
400 | - signon_auth_session_process_async(info->session.get(), |
401 | - info->auth_params.get(), |
402 | - ag_auth_data_get_mechanism(auth_data.get()), |
403 | - nullptr, |
404 | - service_login_cb, |
405 | - info); |
406 | - } |
407 | + // Start signon process |
408 | + signon_auth_session_process_async(info->session.get(), |
409 | + info->auth_params.get(), |
410 | + ag_auth_data_get_mechanism(auth_data.get()), |
411 | + nullptr, |
412 | + service_login_cb, |
413 | + info); |
414 | } |
415 | else |
416 | { |
417 | // Send notification that account has been disabled |
418 | - info->account_client->callback(info_to_details(info)); |
419 | + info->account_client->callback(info); |
420 | } |
421 | } |
422 | |
423 | @@ -182,7 +243,7 @@ |
424 | if (!account) |
425 | { |
426 | // The account was not found |
427 | - return; |
428 | + return; // LCOV_EXCL_LINE |
429 | } |
430 | // Find the service we're concerned with |
431 | std::shared_ptr<GList> services(ag_account_list_services(account.get()), ag_service_list_free); |
432 | @@ -193,7 +254,7 @@ |
433 | if (account_client->service_name() == ag_service_get_name(service)) |
434 | { |
435 | std::shared_ptr<AgAccountService> account_service(ag_account_service_new(account.get(), service), g_object_unref); |
436 | - std::shared_ptr<AccountInfo> info(new AccountInfo, [](AccountInfo* info){ info->account_client = nullptr; delete info; }); |
437 | + std::shared_ptr<AccountInfo> info(new AccountInfo); |
438 | info->service_enabled = false; |
439 | info->account_client = account_client; |
440 | info->account_service.reset(reinterpret_cast<AgAccountService*>(g_object_ref(account_service.get())), g_object_unref); |
441 | @@ -226,51 +287,99 @@ |
442 | : service_name_(service_name) |
443 | , service_type_(service_type) |
444 | , provider_name_(provider_name) |
445 | - , use_external_main_loop_(main_loop_select == OnlineAccountClient::RunInExternalMainLoop) |
446 | - , main_loop_is_running_(false) |
447 | - , client_stopping_(false) |
448 | - , logins_busy_(0) |
449 | + , main_loop_select_(main_loop_select) |
450 | + , main_loop_is_running_(main_loop_select != OnlineAccountClient::CreateInternalMainLoop) |
451 | { |
452 | + // Set up authentication pub/sub |
453 | + std::string oa_id = provider_name + ":" + service_type + ":" + service_name; |
454 | + RuntimeImpl::UPtr rt = RuntimeImpl::create(oa_id); |
455 | + MiddlewareFactory mw_factory(rt.get()); |
456 | + RuntimeConfig rt_config(""); |
457 | + |
458 | + mw_ = mw_factory.create(oa_id, rt_config.default_middleware(), rt_config.default_middleware_configfile()); |
459 | + if (main_loop_select == OnlineAccountClient::RunInExternalUiMainLoop) |
460 | + { |
461 | + // If this client was created by the shell, set up as the publisher |
462 | + auth_publisher_ = mw_->create_publisher(oa_id); |
463 | + } |
464 | + else |
465 | + { |
466 | + // If this client was created by a scope, set up as a subscriber |
467 | + auth_subscriber_ = mw_->create_subscriber(oa_id); |
468 | + auth_subscriber_->message_received().connect(std::bind(&OnlineAccountClientImpl::auth_callback, this, std::placeholders::_1)); |
469 | + } |
470 | + |
471 | // If we are responsible for the main loop |
472 | - if (!use_external_main_loop_) |
473 | + if (main_loop_select_ == OnlineAccountClient::CreateInternalMainLoop) |
474 | { |
475 | // Wait here until either the main loop begins running, or the thread exits |
476 | - std::unique_lock<std::mutex> lock(mutex_); |
477 | - main_loop_thread_ = std::thread(&OnlineAccountClientImpl::main_loop_thread, this); |
478 | - cond_.wait(lock, [this] { return main_loop_is_running_; }); |
479 | - } |
480 | - |
481 | - manager_.reset(ag_manager_new_for_service_type(service_type_.c_str()), g_object_unref); |
482 | - |
483 | - // Watch for changes to accounts |
484 | - account_enabled_signal_id_ = g_signal_connect(manager_.get(), "enabled-event", G_CALLBACK(account_enabled_cb), this); |
485 | - account_deleted_signal_id_ = g_signal_connect(manager_.get(), "account-deleted", G_CALLBACK(account_deleted_cb), this); |
486 | - |
487 | - // Now check initial state |
488 | - refresh_service_statuses(); |
489 | + { |
490 | + std::unique_lock<std::mutex> lock(mutex_); |
491 | + main_loop_thread_ = std::thread(&OnlineAccountClientImpl::main_loop_thread, this); |
492 | + cond_.wait_for(lock, std::chrono::seconds(5), [this] { return main_loop_is_running_; }); |
493 | + } |
494 | + if (!main_loop_is_running_) |
495 | + { |
496 | + // LCOV_EXCL_START |
497 | + if (main_loop_) |
498 | + { |
499 | + // Quit the main loop, causing the thread to exit |
500 | + g_main_loop_quit(main_loop_.get()); |
501 | + if (main_loop_thread_.joinable()) |
502 | + { |
503 | + main_loop_thread_.join(); |
504 | + } |
505 | + } |
506 | + if (thread_exception_) |
507 | + { |
508 | + std::rethrow_exception(thread_exception_); |
509 | + } |
510 | + else |
511 | + { |
512 | + throw unity::ResourceException("OnlineAccountClientImpl(): main_loop_thread failed to start."); |
513 | + } |
514 | + // LCOV_EXCL_STOP |
515 | + } |
516 | + } |
517 | + else |
518 | + { |
519 | + construct(); |
520 | + } |
521 | } |
522 | |
523 | OnlineAccountClientImpl::~OnlineAccountClientImpl() |
524 | { |
525 | - // Disconnect all signal handlers |
526 | - g_signal_handler_disconnect(manager_.get(), account_enabled_signal_id_); |
527 | - g_signal_handler_disconnect(manager_.get(), account_deleted_signal_id_); |
528 | - |
529 | - for (auto info : accounts_) |
530 | - { |
531 | - g_signal_handler_disconnect(info.second->account_service.get(), info.second->service_update_signal_id_); |
532 | - } |
533 | - |
534 | - // Wait until all currently running login sessions are done |
535 | - { |
536 | - std::unique_lock<std::mutex> lock(mutex_); |
537 | - client_stopping_ = true; |
538 | - } |
539 | - flush_pending_sessions(); |
540 | - |
541 | - // If we are responsible for the main loop, quit it on destruction |
542 | - if (main_loop_) |
543 | - { |
544 | + { |
545 | + std::lock_guard<std::mutex> lock(mutex_); |
546 | + if (thread_exception_) |
547 | + { |
548 | + // LCOV_EXCL_START |
549 | + try |
550 | + { |
551 | + std::rethrow_exception(thread_exception_); |
552 | + } |
553 | + catch (std::exception const& e) |
554 | + { |
555 | + std::cerr << "~OnlineAccountClientImpl(): main_loop_thread threw an exception: " << e.what() << std::endl; |
556 | + } |
557 | + catch (...) |
558 | + { |
559 | + std::cerr << "~OnlineAccountClientImpl(): main_loop_thread threw an unknown exception" << std::endl; |
560 | + } |
561 | + // LCOV_EXCL_STOP |
562 | + } |
563 | + } |
564 | + |
565 | + // If we are responsible for the main loop |
566 | + if (main_loop_select_ == OnlineAccountClient::CreateInternalMainLoop) |
567 | + { |
568 | + // Invoke tear_down() from within the main loop |
569 | + { |
570 | + std::unique_lock<std::mutex> lock(mutex_); |
571 | + g_main_context_invoke(main_loop_context_.get(), main_loop_is_stopping_cb, this); |
572 | + cond_.wait(lock, [this] { return !main_loop_is_running_; }); |
573 | + } |
574 | + |
575 | // Quit the main loop, causing the thread to exit |
576 | g_main_loop_quit(main_loop_.get()); |
577 | if (main_loop_thread_.joinable()) |
578 | @@ -278,16 +387,32 @@ |
579 | main_loop_thread_.join(); |
580 | } |
581 | } |
582 | + else |
583 | + { |
584 | + tear_down(); |
585 | + } |
586 | } |
587 | |
588 | void OnlineAccountClientImpl::set_service_update_callback(OnlineAccountClient::ServiceUpdateCallback callback) |
589 | { |
590 | - std::lock_guard<std::mutex> lock(callback_mutex_); |
591 | + std::lock_guard<std::mutex> lock(mutex_); |
592 | + if (thread_exception_) |
593 | + { |
594 | + std::rethrow_exception(thread_exception_); // LCOV_EXCL_LINE |
595 | + } |
596 | + |
597 | + std::lock_guard<std::mutex> callback_lock(callback_mutex_); |
598 | callback_ = callback; |
599 | } |
600 | |
601 | void OnlineAccountClientImpl::refresh_service_statuses() |
602 | { |
603 | + std::unique_lock<std::mutex> lock(mutex_); |
604 | + if (thread_exception_) |
605 | + { |
606 | + std::rethrow_exception(thread_exception_); // LCOV_EXCL_LINE |
607 | + } |
608 | + |
609 | std::shared_ptr<GList> enabled_accounts(ag_manager_list(manager_.get()), ag_manager_list_free); |
610 | GList* it; |
611 | for (it = enabled_accounts.get(); it; it = it->next) |
612 | @@ -297,19 +422,25 @@ |
613 | std::string provider_name = ag_account_get_provider_name(account.get()); |
614 | if (provider_name == provider_name_) |
615 | { |
616 | + lock.unlock(); |
617 | account_enabled_cb(manager_.get(), account_id, this); |
618 | + lock.lock(); |
619 | } |
620 | + flush_pending_session(account_id, lock); |
621 | } |
622 | - flush_pending_sessions(); |
623 | } |
624 | |
625 | std::vector<OnlineAccountClient::ServiceStatus> OnlineAccountClientImpl::get_service_statuses() |
626 | { |
627 | std::lock_guard<std::mutex> lock(mutex_); |
628 | + if (thread_exception_) |
629 | + { |
630 | + std::rethrow_exception(thread_exception_); // LCOV_EXCL_LINE |
631 | + } |
632 | |
633 | // Return all service statuses |
634 | std::vector<OnlineAccountClient::ServiceStatus> service_statuses; |
635 | - for (auto const info : accounts_) |
636 | + for (auto const& info : accounts_) |
637 | { |
638 | service_statuses.push_back(info_to_details(info.second.get())); |
639 | } |
640 | @@ -352,42 +483,117 @@ |
641 | widget.add_attribute_value("online_account_details", Variant(account_details_map)); |
642 | } |
643 | |
644 | -void OnlineAccountClientImpl::flush_pending_sessions() |
645 | -{ |
646 | +void OnlineAccountClientImpl::construct() |
647 | +{ |
648 | + manager_.reset(ag_manager_new_for_service_type(service_type_.c_str()), g_object_unref); |
649 | + |
650 | + // Watch for changes to accounts |
651 | + account_enabled_signal_id_ = g_signal_connect(manager_.get(), "enabled-event", G_CALLBACK(account_enabled_cb), this); |
652 | + account_deleted_signal_id_ = g_signal_connect(manager_.get(), "account-deleted", G_CALLBACK(account_deleted_cb), this); |
653 | + |
654 | + // Now check initial state |
655 | + refresh_service_statuses(); |
656 | +} |
657 | + |
658 | +void OnlineAccountClientImpl::tear_down() |
659 | +{ |
660 | + // Disconnect signal handlers |
661 | + g_signal_handler_disconnect(manager_.get(), account_enabled_signal_id_); |
662 | + g_signal_handler_disconnect(manager_.get(), account_deleted_signal_id_); |
663 | + |
664 | + // Remove all accounts |
665 | + { |
666 | + std::unique_lock<std::mutex> lock(mutex_); |
667 | + for (auto const& info : accounts_) |
668 | + { |
669 | + // Before we nuke the map, ensure that any pending sessions are done |
670 | + g_signal_handler_disconnect(info.second->account_service.get(), info.second->service_update_signal_id_); |
671 | + clear_session(info.second.get()); |
672 | + flush_pending_session(info.second->account_id, lock); |
673 | + } |
674 | + accounts_.clear(); |
675 | + } |
676 | +} |
677 | + |
678 | +void OnlineAccountClientImpl::flush_pending_session(AgAccountId const& account_id, std::unique_lock<std::mutex>& lock) |
679 | +{ |
680 | + // Get account info |
681 | + auto info_it = accounts_.find(account_id); |
682 | + if (info_it == accounts_.end()) |
683 | + { |
684 | + return; |
685 | + } |
686 | + auto info = info_it->second; |
687 | + |
688 | // Wait until all currently running login sessions are done |
689 | // (ensures that accounts_ is up to date) |
690 | - std::unique_lock<std::mutex> lock(mutex_); |
691 | + std::shared_ptr<GMainLoop> event_loop; |
692 | + event_loop.reset(g_main_loop_new(g_main_context_get_thread_default(), true), g_main_loop_unref); |
693 | + while(info->session) |
694 | { |
695 | - std::shared_ptr<GMainLoop> event_loop; |
696 | - event_loop.reset(g_main_loop_new(nullptr, true), g_main_loop_unref); |
697 | - while(logins_busy_ > 0) |
698 | - { |
699 | - // We need to wait inside an event loop to allow for the main application loop to |
700 | - // process its pending events |
701 | - g_timeout_add(100, wake_up_event_loop_cb, event_loop.get()); |
702 | - lock.unlock(); |
703 | - g_main_loop_run(event_loop.get()); |
704 | - lock.lock(); |
705 | - } |
706 | + // We need to wait inside an event loop to allow for the main application loop to |
707 | + // process its pending events |
708 | + std::shared_ptr<GSource> source; |
709 | + source.reset(g_timeout_source_new(10), g_source_unref); |
710 | + g_source_set_callback(source.get(), wake_up_event_loop_cb, event_loop.get(), NULL); |
711 | + g_source_attach(source.get(), g_main_context_get_thread_default()); |
712 | + |
713 | + lock.unlock(); |
714 | + g_main_loop_run(event_loop.get()); |
715 | + lock.lock(); |
716 | } |
717 | } |
718 | |
719 | void OnlineAccountClientImpl::main_loop_state_notify(bool is_running) |
720 | { |
721 | + bool was_running = false; |
722 | + { |
723 | + std::lock_guard<std::mutex> lock(mutex_); |
724 | + was_running = main_loop_is_running_; |
725 | + } |
726 | + if (!was_running && is_running) |
727 | + { |
728 | + construct(); |
729 | + } |
730 | + else if (was_running && !is_running) |
731 | + { |
732 | + tear_down(); |
733 | + } |
734 | + |
735 | std::lock_guard<std::mutex> lock(mutex_); |
736 | main_loop_is_running_ = is_running; |
737 | cond_.notify_all(); |
738 | } |
739 | |
740 | +std::shared_ptr<AgManager> OnlineAccountClientImpl::manager() |
741 | +{ |
742 | + return manager_; |
743 | +} |
744 | + |
745 | std::string OnlineAccountClientImpl::service_name() |
746 | { |
747 | std::lock_guard<std::mutex> lock(mutex_); |
748 | return service_name_; |
749 | } |
750 | |
751 | -void OnlineAccountClientImpl::callback(OnlineAccountClient::ServiceStatus const& service_status) |
752 | +OnlineAccountClient::MainLoopSelect OnlineAccountClientImpl::main_loop_select() |
753 | +{ |
754 | + return main_loop_select_; |
755 | +} |
756 | + |
757 | +std::shared_ptr<GMainContext> OnlineAccountClientImpl::main_loop_context() |
758 | +{ |
759 | + return main_loop_context_; |
760 | +} |
761 | + |
762 | +void OnlineAccountClientImpl::callback(AccountInfo const* info, std::string const& error) |
763 | { |
764 | std::lock_guard<std::mutex> lock(callback_mutex_); |
765 | + auto service_status = info_to_details(info, error); |
766 | + if (service_status.service_authenticated && auth_publisher_) |
767 | + { |
768 | + auth_publisher_->send_message(details_to_json(service_status)); |
769 | + } |
770 | if (callback_) |
771 | { |
772 | callback_(service_status); |
773 | @@ -408,42 +614,82 @@ |
774 | |
775 | void OnlineAccountClientImpl::remove_account(AgAccountId const& account_id) |
776 | { |
777 | - std::lock_guard<std::mutex> lock(mutex_); |
778 | + std::unique_lock<std::mutex> lock(mutex_); |
779 | + |
780 | + // Get account info |
781 | + auto info_it = accounts_.find(account_id); |
782 | + if (info_it == accounts_.end()) |
783 | + { |
784 | + return; |
785 | + } |
786 | + auto info = info_it->second; |
787 | + |
788 | + // Before we nuke the pointer, ensure that any pending sessions are done |
789 | + g_signal_handler_disconnect(info->account_service.get(), info->service_update_signal_id_); |
790 | + clear_session(info.get()); |
791 | + flush_pending_session(account_id, lock); |
792 | + |
793 | + // Remove account info from accounts_ map |
794 | accounts_.erase(account_id); |
795 | } |
796 | |
797 | -bool OnlineAccountClientImpl::inc_logins() |
798 | -{ |
799 | - std::lock_guard<std::mutex> lock(mutex_); |
800 | - if (!client_stopping_) |
801 | - { |
802 | - // Increment number of logins busy |
803 | - ++logins_busy_; |
804 | - return true; |
805 | - } |
806 | - // Client is stopping so don't increment |
807 | - return false; |
808 | -} |
809 | - |
810 | -void OnlineAccountClientImpl::dec_logins() |
811 | -{ |
812 | - // Decrement number of logins busy |
813 | - std::lock_guard<std::mutex> lock(mutex_); |
814 | - --logins_busy_; |
815 | -} |
816 | - |
817 | void OnlineAccountClientImpl::main_loop_thread() |
818 | { |
819 | - // If something goes wrong causing the main loop not to run, the destruction of this pointer |
820 | - // will break the constructor from its wait |
821 | - std::shared_ptr<void> thread_exit_notifier(nullptr, [this](void*){ main_loop_state_notify(true); }); |
822 | - |
823 | - // Stick a method call into the main loop to notify the constructor when the main loop begins running |
824 | - g_idle_add(main_loop_is_running_cb, this); |
825 | - |
826 | - // Run the main loop |
827 | - main_loop_.reset(g_main_loop_new(nullptr, true), g_main_loop_unref); |
828 | - g_main_loop_run(main_loop_.get()); |
829 | + // If something goes wrong causing the thread to abort, the destruction of this pointer update the |
830 | + // main_loop_is_running_ state accordingly. |
831 | + std::shared_ptr<void> thread_exit_notifier(nullptr, [this](void*){ main_loop_state_notify(false); }); |
832 | + |
833 | + try |
834 | + { |
835 | + main_loop_context_.reset(g_main_context_new(), g_main_context_unref); |
836 | + g_main_context_push_thread_default(main_loop_context_.get()); |
837 | + |
838 | + // Stick a method call into the main loop to notify the constructor when the main loop begins running |
839 | + g_main_context_invoke(main_loop_context_.get(), main_loop_is_running_cb, this); |
840 | + |
841 | + // Run the main loop |
842 | + main_loop_.reset(g_main_loop_new(main_loop_context_.get(), true), g_main_loop_unref); |
843 | + g_main_loop_run(main_loop_.get()); |
844 | + } |
845 | + // LCOV_EXCL_START |
846 | + catch (std::exception const& e) |
847 | + { |
848 | + std::cerr << "OnlineAccountClientImpl::main_loop_thread(): Thread aborted: " << e.what() << std::endl; |
849 | + std::lock_guard<std::mutex> lock(mutex_); |
850 | + thread_exception_ = std::current_exception(); |
851 | + } |
852 | + catch (...) |
853 | + { |
854 | + std::cerr << "OnlineAccountClientImpl::main_loop_thread(): Thread aborted: unknown exception" << std::endl; |
855 | + std::lock_guard<std::mutex> lock(mutex_); |
856 | + thread_exception_ = std::current_exception(); |
857 | + } |
858 | + // LCOV_EXCL_STOP |
859 | +} |
860 | + |
861 | +void OnlineAccountClientImpl::auth_callback(std::string const& details_json) |
862 | +{ |
863 | + OnlineAccountClient::ServiceStatus details = json_to_details(details_json); |
864 | + |
865 | + // Update account info |
866 | + { |
867 | + std::lock_guard<std::mutex> lock(mutex_); |
868 | + auto info_it = accounts_.find(details.account_id); |
869 | + if (info_it == accounts_.end()) |
870 | + { |
871 | + return; |
872 | + } |
873 | + auto info = info_it->second; |
874 | + |
875 | + GVariantDict dict; |
876 | + g_variant_dict_init(&dict, nullptr); |
877 | + g_variant_dict_insert(&dict, "AccessToken", "s", details.access_token.c_str()); |
878 | + g_variant_dict_insert(&dict, "TokenSecret", "s", details.token_secret.c_str()); |
879 | + info->session_data.reset(g_variant_ref_sink(g_variant_dict_end(&dict)), free_variant); |
880 | + } |
881 | + |
882 | + std::lock_guard<std::mutex> lock(callback_mutex_); |
883 | + callback_(details); |
884 | } |
885 | |
886 | } // namespace internal |
887 | |
888 | === modified file 'src/scopes/internal/RegistryObject.cpp' |
889 | --- src/scopes/internal/RegistryObject.cpp 2014-09-15 18:33:08 +0000 |
890 | +++ src/scopes/internal/RegistryObject.cpp 2014-10-08 11:00:01 +0000 |
891 | @@ -33,6 +33,7 @@ |
892 | #include <cassert> |
893 | #include <fstream> |
894 | #include <wordexp.h> |
895 | +#include <iostream> |
896 | |
897 | using namespace std; |
898 | |
899 | @@ -385,7 +386,16 @@ |
900 | desktop_file << "Type=Application" << std::endl; |
901 | desktop_file << "NoDisplay=true" << std::endl; |
902 | desktop_file << "Name=" << metadata.display_name() << std::endl; |
903 | - desktop_file << "Icon=" << metadata.icon() << std::endl; |
904 | + desktop_file << "Icon="; |
905 | + try |
906 | + { |
907 | + desktop_file << metadata.icon(); |
908 | + } |
909 | + catch (NotFoundException const&) |
910 | + { |
911 | + // Icon is optional. |
912 | + } |
913 | + desktop_file << endl; |
914 | desktop_file.close(); |
915 | } |
916 | |
917 | |
918 | === modified file 'test/gtest/scopes/OnlineAccountClient/CMakeLists.txt' |
919 | --- test/gtest/scopes/OnlineAccountClient/CMakeLists.txt 2014-09-10 08:45:38 +0000 |
920 | +++ test/gtest/scopes/OnlineAccountClient/CMakeLists.txt 2014-10-08 11:00:01 +0000 |
921 | @@ -1,4 +1,12 @@ |
922 | add_executable(OnlineAccountClient_test OnlineAccountClient_test.cpp) |
923 | + |
924 | +pkg_check_modules(DBUSTEST REQUIRED dbustest-1) |
925 | +include_directories(${DBUSTEST_INCLUDE_DIRS}) |
926 | +target_link_libraries(OnlineAccountClient_test ${DBUSTEST_LDFLAGS}) |
927 | + |
928 | +add_definitions(-DTEST_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") |
929 | +add_definitions(-DTEST_DB_DIR="${CMAKE_CURRENT_BINARY_DIR}") |
930 | + |
931 | target_link_libraries(OnlineAccountClient_test ${TESTLIBS}) |
932 | |
933 | add_test(OnlineAccountClient OnlineAccountClient_test) |
934 | |
935 | === modified file 'test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp' |
936 | --- test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp 2014-09-10 08:57:42 +0000 |
937 | +++ test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp 2014-10-08 11:00:01 +0000 |
938 | @@ -16,15 +16,552 @@ |
939 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
940 | */ |
941 | |
942 | +#include <unity/scopes/OnlineAccountClient.h> |
943 | +#include <unity/scopes/internal/OnlineAccountClientImpl.h> |
944 | + |
945 | +#include <unity/scopes/CategorisedResult.h> |
946 | +#include <unity/scopes/CategoryRenderer.h> |
947 | +#include <unity/scopes/internal/CategoryRegistry.h> |
948 | +#include <unity/scopes/PreviewWidget.h> |
949 | +#include <unity/scopes/Variant.h> |
950 | + |
951 | +#include <boost/filesystem/operations.hpp> |
952 | +#include <condition_variable> |
953 | +#include <functional> |
954 | #include <gtest/gtest.h> |
955 | -#include <unity/scopes/OnlineAccountClient.h> |
956 | - |
957 | +#include <libaccounts-glib/accounts-glib.h> |
958 | +#include <libdbustest/dbus-test.h> |
959 | #include <thread> |
960 | |
961 | +using namespace unity; |
962 | using namespace unity::scopes; |
963 | - |
964 | -TEST(OnlineAccountClient, basic) |
965 | -{ |
966 | - OnlineAccountClient oa_client("com.ubuntu.scopes.youtube_youtube", "sharing", "google"); |
967 | - auto service_statuses = oa_client.get_service_statuses(); |
968 | +using namespace unity::scopes::testing; |
969 | +using namespace unity::scopes::internal; |
970 | + |
971 | +namespace unity |
972 | +{ |
973 | +namespace scopes |
974 | +{ |
975 | +namespace testing |
976 | +{ |
977 | + |
978 | +class OnlineAccountClientTest : public ::testing::Test |
979 | +{ |
980 | +public: |
981 | + OnlineAccountClientTest(OnlineAccountClient::MainLoopSelect main_loop_select = OnlineAccountClient::CreateInternalMainLoop) |
982 | + { |
983 | + boost::filesystem::remove(TEST_DB_DIR "/accounts.db"); |
984 | + |
985 | + setenv("XDG_RUNTIME_DIR", "/tmp", true); |
986 | + setenv("ACCOUNTS", TEST_DB_DIR, false); |
987 | + setenv("AG_SERVICES", TEST_DATA_DIR, false); |
988 | + setenv("AG_SERVICE_TYPES", TEST_DATA_DIR, false); |
989 | + setenv("AG_PROVIDERS", TEST_DATA_DIR, false); |
990 | + |
991 | + oa_client_.reset(new OnlineAccountClient("TestService", "sharing", "TestProvider", main_loop_select)); |
992 | + |
993 | + manager_ = oa_client_->p->manager(); |
994 | + main_loop_context_ = oa_client_->p->main_loop_context(); |
995 | + } |
996 | + |
997 | + ~OnlineAccountClientTest() |
998 | + { |
999 | + account_ = nullptr; |
1000 | + manager_ = nullptr; |
1001 | + oa_client_ = nullptr; |
1002 | + } |
1003 | + |
1004 | + std::shared_ptr<OnlineAccountClient> oa_client() |
1005 | + { |
1006 | + return oa_client_; |
1007 | + } |
1008 | + |
1009 | + void create_account() |
1010 | + { |
1011 | + run_in_main_loop_(std::bind(&OnlineAccountClientTest::create_account_, this)); |
1012 | + } |
1013 | + |
1014 | + void delete_account() |
1015 | + { |
1016 | + run_in_main_loop_(std::bind(&OnlineAccountClientTest::delete_account_, this)); |
1017 | + } |
1018 | + |
1019 | + void enable_service() |
1020 | + { |
1021 | + run_in_main_loop_(std::bind(&OnlineAccountClientTest::enable_service_, this)); |
1022 | + } |
1023 | + |
1024 | + void disable_service() |
1025 | + { |
1026 | + run_in_main_loop_(std::bind(&OnlineAccountClientTest::disable_service_, this)); |
1027 | + } |
1028 | + |
1029 | + void disable_account() |
1030 | + { |
1031 | + run_in_main_loop_(std::bind(&OnlineAccountClientTest::disable_account_, this)); |
1032 | + } |
1033 | + |
1034 | + void enable_account() |
1035 | + { |
1036 | + run_in_main_loop_(std::bind(&OnlineAccountClientTest::enable_account_, this)); |
1037 | + } |
1038 | + |
1039 | + void service_update_enabled(OnlineAccountClient::ServiceStatus const& status) |
1040 | + { |
1041 | + EXPECT_EQ(1, status.account_id); |
1042 | + EXPECT_EQ(true, status.service_enabled); |
1043 | + EXPECT_EQ(false, status.service_authenticated); |
1044 | + EXPECT_EQ("69842936499-sdflkbhslufhgrjamwlicefhb.apps.test.com", status.client_id); |
1045 | + EXPECT_EQ("lj3i8iorep0w03994jwjef0j", status.client_secret); |
1046 | + EXPECT_EQ("", status.access_token); |
1047 | + EXPECT_EQ("", status.token_secret); |
1048 | + EXPECT_NE("", status.error); |
1049 | + |
1050 | + std::lock_guard<std::mutex> lock(mutex_); |
1051 | + got_update_ = true; |
1052 | + cond_.notify_all(); |
1053 | + } |
1054 | + |
1055 | + void service_update_disabled(OnlineAccountClient::ServiceStatus const& status) |
1056 | + { |
1057 | + EXPECT_EQ(1, status.account_id); |
1058 | + EXPECT_EQ(false, status.service_enabled); |
1059 | + EXPECT_EQ(false, status.service_authenticated); |
1060 | + EXPECT_EQ("69842936499-sdflkbhslufhgrjamwlicefhb.apps.test.com", status.client_id); |
1061 | + EXPECT_EQ("lj3i8iorep0w03994jwjef0j", status.client_secret); |
1062 | + EXPECT_EQ("", status.access_token); |
1063 | + EXPECT_EQ("", status.token_secret); |
1064 | + EXPECT_EQ("", status.error); |
1065 | + |
1066 | + std::lock_guard<std::mutex> lock(mutex_); |
1067 | + got_update_ = true; |
1068 | + cond_.notify_all(); |
1069 | + } |
1070 | + |
1071 | + void service_update_none(OnlineAccountClient::ServiceStatus const& status) |
1072 | + { |
1073 | + EXPECT_EQ(1, status.account_id); |
1074 | + EXPECT_EQ(false, status.service_enabled); |
1075 | + EXPECT_EQ(false, status.service_authenticated); |
1076 | + EXPECT_EQ("", status.client_id); |
1077 | + EXPECT_EQ("", status.client_secret); |
1078 | + EXPECT_EQ("", status.access_token); |
1079 | + EXPECT_EQ("", status.token_secret); |
1080 | + EXPECT_EQ("", status.error); |
1081 | + |
1082 | + std::lock_guard<std::mutex> lock(mutex_); |
1083 | + got_update_ = true; |
1084 | + cond_.notify_all(); |
1085 | + } |
1086 | + |
1087 | + void service_update_auth(OnlineAccountClient::ServiceStatus const& status) |
1088 | + { |
1089 | + EXPECT_EQ(1, status.account_id); |
1090 | + EXPECT_EQ(true, status.service_enabled); |
1091 | + EXPECT_EQ(true, status.service_authenticated); |
1092 | + EXPECT_EQ("isuertbiseruy87srkuthksvu", status.client_id); |
1093 | + EXPECT_EQ("rytwekfgiodng523dr4", status.client_secret); |
1094 | + EXPECT_EQ("sfhgbfgutgi9ugwirheg74", status.access_token); |
1095 | + EXPECT_EQ("qwpeurylsfdg83", status.token_secret); |
1096 | + EXPECT_EQ("not really an error, but just to test", status.error); |
1097 | + |
1098 | + std::lock_guard<std::mutex> lock(mutex_); |
1099 | + got_update_ = true; |
1100 | + cond_.notify_all(); |
1101 | + } |
1102 | + |
1103 | + bool wait_for_service_update() |
1104 | + { |
1105 | + std::unique_lock<std::mutex> lock(mutex_); |
1106 | + EXPECT_TRUE(cond_.wait_for(lock, std::chrono::seconds(1), [this]{ return got_update_; })) << "service update callback not triggered"; |
1107 | + bool result = got_update_; |
1108 | + got_update_ = false; |
1109 | + return result; |
1110 | + } |
1111 | + |
1112 | + void invoke_callback(std::shared_ptr<OnlineAccountClient> oa_client, AccountInfo const* info, std::string const& error) |
1113 | + { |
1114 | + oa_client->p->callback(info, error); |
1115 | + } |
1116 | + |
1117 | + static void safe_g_error_free_(GError* e) |
1118 | + { |
1119 | + if (e) |
1120 | + { |
1121 | + g_error_free(e); |
1122 | + } |
1123 | + } |
1124 | + |
1125 | + static void safe_g_variant_free_(GVariant* v) |
1126 | + { |
1127 | + if (v) |
1128 | + { |
1129 | + g_variant_unref(v); |
1130 | + } |
1131 | + } |
1132 | + |
1133 | +private: |
1134 | + std::shared_ptr<OnlineAccountClient> oa_client_; |
1135 | + std::shared_ptr<AgManager> manager_; |
1136 | + std::shared_ptr<AgAccount> account_; |
1137 | + std::shared_ptr<GMainContext> main_loop_context_; |
1138 | + |
1139 | + bool got_update_; |
1140 | + std::mutex mutex_; |
1141 | + std::condition_variable cond_; |
1142 | + |
1143 | +private: |
1144 | + void run_in_main_loop_(std::function<void()> func) |
1145 | + { |
1146 | + auto func_task = [](void* user_data) |
1147 | + { |
1148 | + auto cb_data = reinterpret_cast<std::pair<std::function<void()>*, GMainLoop*>*>(user_data); |
1149 | + auto func = cb_data->first; |
1150 | + auto event_loop = cb_data->second; |
1151 | + |
1152 | + (*func)(); |
1153 | + |
1154 | + while (!g_main_loop_is_running(event_loop)); |
1155 | + g_main_loop_quit(event_loop); |
1156 | + |
1157 | + return G_SOURCE_REMOVE; |
1158 | + }; |
1159 | + |
1160 | + std::shared_ptr<GMainLoop> event_loop; |
1161 | + if (main_loop_context_) |
1162 | + { |
1163 | + event_loop.reset(g_main_loop_new(main_loop_context_.get(), false), g_main_loop_unref); |
1164 | + auto cb_data = std::make_pair(&func, event_loop.get()); |
1165 | + g_main_context_invoke(main_loop_context_.get(), func_task, &cb_data); |
1166 | + } |
1167 | + else |
1168 | + { |
1169 | + event_loop.reset(g_main_loop_new(nullptr, false), g_main_loop_unref); |
1170 | + auto cb_data = std::make_pair(&func, event_loop.get()); |
1171 | + g_idle_add(func_task, &cb_data); |
1172 | + } |
1173 | + g_main_loop_run(event_loop.get()); |
1174 | + } |
1175 | + |
1176 | + void create_account_() |
1177 | + { |
1178 | + account_.reset(ag_manager_create_account(manager_.get(), "TestProvider"), g_object_unref); |
1179 | + ag_account_select_service(account_.get(), nullptr); |
1180 | + ag_account_set_enabled(account_.get(), true); |
1181 | + |
1182 | + GError* error = nullptr; |
1183 | + bool stored = ag_account_store_blocking(account_.get(), &error); |
1184 | + std::shared_ptr<GError> error_cleanup(error, safe_g_error_free_); |
1185 | + |
1186 | + EXPECT_TRUE(stored); |
1187 | + EXPECT_EQ(nullptr, error); |
1188 | + } |
1189 | + |
1190 | + void delete_account_() |
1191 | + { |
1192 | + ag_account_delete(account_.get()); |
1193 | + |
1194 | + GError* error = nullptr; |
1195 | + bool stored = ag_account_store_blocking(account_.get(), &error); |
1196 | + std::shared_ptr<GError> error_cleanup(error, safe_g_error_free_); |
1197 | + |
1198 | + account_ = nullptr; |
1199 | + |
1200 | + EXPECT_TRUE(stored); |
1201 | + EXPECT_EQ(nullptr, error); |
1202 | + } |
1203 | + |
1204 | + void enable_service_() |
1205 | + { |
1206 | + auto service = ag_manager_get_service(manager_.get(), "TestService"); |
1207 | + ag_account_select_service(account_.get(), service); |
1208 | + ag_account_set_enabled(account_.get(), true); |
1209 | + |
1210 | + GError* error = nullptr; |
1211 | + bool stored = ag_account_store_blocking(account_.get(), &error); |
1212 | + std::shared_ptr<GError> error_cleanup(error, safe_g_error_free_); |
1213 | + |
1214 | + EXPECT_TRUE(stored); |
1215 | + EXPECT_EQ(nullptr, error); |
1216 | + } |
1217 | + |
1218 | + void disable_service_() |
1219 | + { |
1220 | + auto service = ag_manager_get_service(manager_.get(), "TestService"); |
1221 | + ag_account_select_service(account_.get(), service); |
1222 | + ag_account_set_enabled(account_.get(), false); |
1223 | + |
1224 | + GError* error = nullptr; |
1225 | + bool stored = ag_account_store_blocking(account_.get(), &error); |
1226 | + std::shared_ptr<GError> error_cleanup(error, safe_g_error_free_); |
1227 | + |
1228 | + EXPECT_TRUE(stored); |
1229 | + EXPECT_EQ(nullptr, error); |
1230 | + } |
1231 | + |
1232 | + void disable_account_() |
1233 | + { |
1234 | + ag_account_set_enabled(account_.get(), false); |
1235 | + |
1236 | + GError* error = nullptr; |
1237 | + bool stored = ag_account_store_blocking(account_.get(), &error); |
1238 | + std::shared_ptr<GError> error_cleanup(error, safe_g_error_free_); |
1239 | + |
1240 | + EXPECT_TRUE(stored); |
1241 | + EXPECT_EQ(nullptr, error); |
1242 | + } |
1243 | + |
1244 | + void enable_account_() |
1245 | + { |
1246 | + ag_account_set_enabled(account_.get(), true); |
1247 | + |
1248 | + GError* error = nullptr; |
1249 | + bool stored = ag_account_store_blocking(account_.get(), &error); |
1250 | + std::shared_ptr<GError> error_cleanup(error, safe_g_error_free_); |
1251 | + |
1252 | + EXPECT_TRUE(stored); |
1253 | + EXPECT_EQ(nullptr, error); |
1254 | + } |
1255 | +}; |
1256 | + |
1257 | +class OnlineAccountClientTestNoMainLoop : public OnlineAccountClientTest |
1258 | +{ |
1259 | +public: |
1260 | + OnlineAccountClientTestNoMainLoop() |
1261 | + : OnlineAccountClientTest(OnlineAccountClient::RunInExternalMainLoop) {} |
1262 | +}; |
1263 | + |
1264 | +} // namespace testing |
1265 | +} // namespace scopes |
1266 | +} // namespace unity |
1267 | + |
1268 | +TEST_F(OnlineAccountClientTest, register_account_login_result) |
1269 | +{ |
1270 | + OnlineAccountClient oa_client("test_service_name", "test_service_type", "test_provider"); |
1271 | + |
1272 | + CategoryRegistry reg; |
1273 | + auto cat = reg.register_category("1", "title", "icon", nullptr, CategoryRenderer()); |
1274 | + CategorisedResult result(cat); |
1275 | + |
1276 | + oa_client.register_account_login_item(result, CannedQuery("test"), OnlineAccountClient::InvalidateResults, OnlineAccountClient::DoNothing); |
1277 | + |
1278 | + EXPECT_TRUE(result.contains("online_account_details")); |
1279 | + |
1280 | + VariantMap details = result.value("online_account_details").get_dict(); |
1281 | + |
1282 | + EXPECT_NE(details.end(), details.find("service_name")); |
1283 | + EXPECT_NE(details.end(), details.find("service_type")); |
1284 | + EXPECT_NE(details.end(), details.find("provider_name")); |
1285 | + EXPECT_NE(details.end(), details.find("login_passed_action")); |
1286 | + EXPECT_NE(details.end(), details.find("login_failed_action")); |
1287 | + |
1288 | + EXPECT_EQ("test_service_name", details.at("service_name").get_string()); |
1289 | + EXPECT_EQ("test_service_type", details.at("service_type").get_string()); |
1290 | + EXPECT_EQ("test_provider", details.at("provider_name").get_string()); |
1291 | + EXPECT_EQ(OnlineAccountClient::InvalidateResults, static_cast<OnlineAccountClient::PostLoginAction>(details.at("login_passed_action").get_int())); |
1292 | + EXPECT_EQ(OnlineAccountClient::DoNothing, static_cast<OnlineAccountClient::PostLoginAction>(details.at("login_failed_action").get_int())); |
1293 | +} |
1294 | + |
1295 | +TEST_F(OnlineAccountClientTest, register_account_login_widget) |
1296 | +{ |
1297 | + OnlineAccountClient oa_client("test_service_name", "test_service_type", "test_provider"); |
1298 | + |
1299 | + PreviewWidget widget("i1", "image"); |
1300 | + |
1301 | + oa_client.register_account_login_item(widget, OnlineAccountClient::ContinueActivation, OnlineAccountClient::DoNothing); |
1302 | + |
1303 | + VariantMap values = widget.attribute_values(); |
1304 | + |
1305 | + EXPECT_NE(values.end(), values.find("online_account_details")); |
1306 | + |
1307 | + VariantMap details = values.at("online_account_details").get_dict(); |
1308 | + |
1309 | + EXPECT_NE(details.end(), details.find("service_name")); |
1310 | + EXPECT_NE(details.end(), details.find("service_type")); |
1311 | + EXPECT_NE(details.end(), details.find("provider_name")); |
1312 | + EXPECT_NE(details.end(), details.find("login_passed_action")); |
1313 | + EXPECT_NE(details.end(), details.find("login_failed_action")); |
1314 | + |
1315 | + EXPECT_EQ("test_service_name", details.at("service_name").get_string()); |
1316 | + EXPECT_EQ("test_service_type", details.at("service_type").get_string()); |
1317 | + EXPECT_EQ("test_provider", details.at("provider_name").get_string()); |
1318 | + EXPECT_EQ(OnlineAccountClient::ContinueActivation, static_cast<OnlineAccountClient::PostLoginAction>(details.at("login_passed_action").get_int())); |
1319 | + EXPECT_EQ(OnlineAccountClient::DoNothing, static_cast<OnlineAccountClient::PostLoginAction>(details.at("login_failed_action").get_int())); |
1320 | +} |
1321 | + |
1322 | +TEST_F(OnlineAccountClientTest, refresh_services_main_loop) |
1323 | +{ |
1324 | + auto statuses = oa_client()->get_service_statuses(); |
1325 | + EXPECT_EQ(0, statuses.size()); |
1326 | + |
1327 | + create_account(); |
1328 | + oa_client()->refresh_service_statuses(); |
1329 | + |
1330 | + statuses = oa_client()->get_service_statuses(); |
1331 | + EXPECT_EQ(1, statuses.size()); |
1332 | + EXPECT_FALSE(statuses[0].service_enabled); |
1333 | + |
1334 | + enable_service(); |
1335 | + oa_client()->refresh_service_statuses(); |
1336 | + |
1337 | + statuses = oa_client()->get_service_statuses(); |
1338 | + EXPECT_TRUE(statuses[0].service_enabled); |
1339 | + |
1340 | + disable_service(); |
1341 | + oa_client()->refresh_service_statuses(); |
1342 | + |
1343 | + statuses = oa_client()->get_service_statuses(); |
1344 | + EXPECT_FALSE(statuses[0].service_enabled); |
1345 | + |
1346 | + enable_service(); |
1347 | + oa_client()->refresh_service_statuses(); |
1348 | + |
1349 | + statuses = oa_client()->get_service_statuses(); |
1350 | + EXPECT_TRUE(statuses[0].service_enabled); |
1351 | + |
1352 | + disable_account(); |
1353 | + oa_client()->refresh_service_statuses(); |
1354 | + |
1355 | + statuses = oa_client()->get_service_statuses(); |
1356 | + EXPECT_FALSE(statuses[0].service_enabled); |
1357 | + |
1358 | + enable_account(); |
1359 | + oa_client()->refresh_service_statuses(); |
1360 | + |
1361 | + statuses = oa_client()->get_service_statuses(); |
1362 | + EXPECT_TRUE(statuses[0].service_enabled); |
1363 | + |
1364 | + delete_account(); |
1365 | + oa_client()->refresh_service_statuses(); |
1366 | + |
1367 | + statuses = oa_client()->get_service_statuses(); |
1368 | + EXPECT_EQ(0, statuses.size()); |
1369 | +} |
1370 | + |
1371 | +TEST_F(OnlineAccountClientTest, service_update_callback) |
1372 | +{ |
1373 | + auto statuses = oa_client()->get_service_statuses(); |
1374 | + EXPECT_EQ(0, statuses.size()); |
1375 | + |
1376 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_none, this, std::placeholders::_1)); |
1377 | + create_account(); |
1378 | + wait_for_service_update(); |
1379 | + |
1380 | + statuses = oa_client()->get_service_statuses(); |
1381 | + EXPECT_EQ(1, statuses.size()); |
1382 | + |
1383 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_enabled, this, std::placeholders::_1)); |
1384 | + enable_service(); |
1385 | + wait_for_service_update(); |
1386 | + |
1387 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_disabled, this, std::placeholders::_1)); |
1388 | + disable_service(); |
1389 | + wait_for_service_update(); |
1390 | + |
1391 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_enabled, this, std::placeholders::_1)); |
1392 | + enable_service(); |
1393 | + wait_for_service_update(); |
1394 | + |
1395 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_disabled, this, std::placeholders::_1)); |
1396 | + disable_account(); |
1397 | + wait_for_service_update(); |
1398 | + |
1399 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_enabled, this, std::placeholders::_1)); |
1400 | + enable_account(); |
1401 | + wait_for_service_update(); |
1402 | + |
1403 | + oa_client()->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_disabled, this, std::placeholders::_1)); |
1404 | + delete_account(); |
1405 | + wait_for_service_update(); |
1406 | + |
1407 | + statuses = oa_client()->get_service_statuses(); |
1408 | + EXPECT_EQ(0, statuses.size()); |
1409 | +} |
1410 | + |
1411 | +TEST_F(OnlineAccountClientTestNoMainLoop, refresh_services_no_main_loop) |
1412 | +{ |
1413 | + auto statuses = oa_client()->get_service_statuses(); |
1414 | + EXPECT_EQ(0, statuses.size()); |
1415 | + |
1416 | + create_account(); |
1417 | + oa_client()->refresh_service_statuses(); |
1418 | + |
1419 | + statuses = oa_client()->get_service_statuses(); |
1420 | + EXPECT_EQ(1, statuses.size()); |
1421 | + EXPECT_FALSE(statuses[0].service_enabled); |
1422 | + |
1423 | + enable_service(); |
1424 | + oa_client()->refresh_service_statuses(); |
1425 | + |
1426 | + statuses = oa_client()->get_service_statuses(); |
1427 | + EXPECT_TRUE(statuses[0].service_enabled); |
1428 | + |
1429 | + disable_service(); |
1430 | + oa_client()->refresh_service_statuses(); |
1431 | + |
1432 | + statuses = oa_client()->get_service_statuses(); |
1433 | + EXPECT_FALSE(statuses[0].service_enabled); |
1434 | + |
1435 | + enable_service(); |
1436 | + oa_client()->refresh_service_statuses(); |
1437 | + |
1438 | + statuses = oa_client()->get_service_statuses(); |
1439 | + EXPECT_TRUE(statuses[0].service_enabled); |
1440 | + |
1441 | + disable_account(); |
1442 | + oa_client()->refresh_service_statuses(); |
1443 | + |
1444 | + statuses = oa_client()->get_service_statuses(); |
1445 | + EXPECT_FALSE(statuses[0].service_enabled); |
1446 | + |
1447 | + enable_account(); |
1448 | + oa_client()->refresh_service_statuses(); |
1449 | + |
1450 | + statuses = oa_client()->get_service_statuses(); |
1451 | + EXPECT_TRUE(statuses[0].service_enabled); |
1452 | +} |
1453 | + |
1454 | +TEST_F(OnlineAccountClientTestNoMainLoop, pub_sub_authentication) |
1455 | +{ |
1456 | + std::shared_ptr<OnlineAccountClient> shell_oa_client; |
1457 | + shell_oa_client.reset(new OnlineAccountClient("TestService", "sharing", "TestProvider", OnlineAccountClient::RunInExternalUiMainLoop)); |
1458 | + |
1459 | + std::shared_ptr<OnlineAccountClient> scope_oa_client; |
1460 | + scope_oa_client.reset(new OnlineAccountClient("TestService", "sharing", "TestProvider", OnlineAccountClient::RunInExternalMainLoop)); |
1461 | + |
1462 | + create_account(); |
1463 | + scope_oa_client->refresh_service_statuses(); |
1464 | + |
1465 | + std::shared_ptr<AccountInfo> info(new AccountInfo); |
1466 | + info->account_id = 1; |
1467 | + info->service_enabled = true; |
1468 | + { |
1469 | + GVariantDict dict; |
1470 | + g_variant_dict_init(&dict, nullptr); |
1471 | + g_variant_dict_insert(&dict, "ConsumerKey", "s", "isuertbiseruy87srkuthksvu"); |
1472 | + g_variant_dict_insert(&dict, "ConsumerSecret", "s", "rytwekfgiodng523dr4"); |
1473 | + info->auth_params.reset(g_variant_ref_sink(g_variant_dict_end(&dict)), safe_g_variant_free_); |
1474 | + } |
1475 | + { |
1476 | + GVariantDict dict; |
1477 | + g_variant_dict_init(&dict, nullptr); |
1478 | + g_variant_dict_insert(&dict, "AccessToken", "s", "sfhgbfgutgi9ugwirheg74"); |
1479 | + g_variant_dict_insert(&dict, "TokenSecret", "s", "qwpeurylsfdg83"); |
1480 | + info->session_data.reset(g_variant_ref_sink(g_variant_dict_end(&dict)), safe_g_variant_free_); |
1481 | + } |
1482 | + |
1483 | + // Invoke callback on shell_oa_client which should invoke a callback on scope_oa_client via pub/sub |
1484 | + scope_oa_client->set_service_update_callback(std::bind(&OnlineAccountClientTest::service_update_auth, this, std::placeholders::_1)); |
1485 | + invoke_callback(shell_oa_client, info.get(), "not really an error, but just to test"); |
1486 | + wait_for_service_update(); |
1487 | +} |
1488 | + |
1489 | +int main(int argc, char **argv) |
1490 | +{ |
1491 | + std::shared_ptr<DbusTestService> dbus_test_service; |
1492 | + dbus_test_service.reset(dbus_test_service_new(nullptr), g_object_unref); |
1493 | + dbus_test_service_run(dbus_test_service.get()); |
1494 | + |
1495 | + ::testing::InitGoogleTest(&argc, argv); |
1496 | + return RUN_ALL_TESTS(); |
1497 | } |
1498 | |
1499 | === added directory 'test/gtest/scopes/OnlineAccountClient/data' |
1500 | === added file 'test/gtest/scopes/OnlineAccountClient/data/TestService.service' |
1501 | --- test/gtest/scopes/OnlineAccountClient/data/TestService.service 1970-01-01 00:00:00 +0000 |
1502 | +++ test/gtest/scopes/OnlineAccountClient/data/TestService.service 2014-10-08 11:00:01 +0000 |
1503 | @@ -0,0 +1,26 @@ |
1504 | +<?xml version="1.0" encoding="UTF-8" ?> |
1505 | +<service id="TestService"> |
1506 | + <type>sharing</type> |
1507 | + <name>Test Service</name> |
1508 | + <provider>TestProvider</provider> |
1509 | + <template> |
1510 | + <group name="auth"> |
1511 | + <setting name="method">oauth2</setting> |
1512 | + <setting name="mechanism">web_server</setting> |
1513 | + <group name="oauth2"> |
1514 | + <group name="web_server"> |
1515 | + <setting name="Host">accounts.test.com</setting> |
1516 | + |
1517 | + <setting name="AuthPath">o/oauth2/auth?access_type=offline</setting> |
1518 | + <setting name="TokenPath">o/oauth2/token</setting> |
1519 | + <setting name="RedirectUri">https://wiki.ubuntu.com/</setting> |
1520 | + <setting name="ResponseType">code</setting> |
1521 | + <setting type="as" name="Scope">['https://www.test.com/auth/test.readonly']</setting> |
1522 | + <setting name="ClientId">69842936499-sdflkbhslufhgrjamwlicefhb.apps.test.com</setting> |
1523 | + <setting name="ClientSecret">lj3i8iorep0w03994jwjef0j</setting> |
1524 | + <setting type="as" name="AllowedSchemes">['https','http']</setting> |
1525 | + </group> |
1526 | + </group> |
1527 | + </group> |
1528 | + </template> |
1529 | +</service> |
1530 | |
1531 | === modified file 'valgrind-suppress' |
1532 | --- valgrind-suppress 2014-09-25 09:43:35 +0000 |
1533 | +++ valgrind-suppress 2014-10-08 11:00:01 +0000 |
1534 | @@ -212,3 +212,24 @@ |
1535 | Memcheck:Cond |
1536 | fun:ag_auth_data_unref |
1537 | } |
1538 | + |
1539 | +{ |
1540 | + malloc[Memcheck:Leak] |
1541 | + Memcheck:Leak |
1542 | + fun:malloc |
1543 | + fun:g_malloc |
1544 | + fun:g_slice_alloc |
1545 | + fun:g_slice_alloc0 |
1546 | + ... |
1547 | + fun:ag_manager_get_service |
1548 | + ... |
1549 | + fun:ag_manager_list_services_by_type |
1550 | + fun:ag_account_list_services |
1551 | +} |
1552 | + |
1553 | +{ |
1554 | + operator new(unsigned long)[Memcheck:Leak] |
1555 | + Memcheck:Leak |
1556 | + fun:_Znwm |
1557 | + fun:_ZNSs4_Rep9_S_createEmmRKSaIcE |
1558 | +} |
PASSED: Continuous integration, rev:276 jenkins. qa.ubuntu. com/job/ unity-scopes- api-ci/ 472/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- amd64-ci/ 99 jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- armhf-ci/ 99 jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- armhf-ci/ 99/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- i386-ci/ 99
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-ci/ 472/rebuild
http://