Merge lp:~canonical-platform-qa/uoa-integration-tests/python-testability into lp:uoa-integration-tests

Proposed by Leo Arias
Status: Merged
Merged at revision: 15
Proposed branch: lp:~canonical-platform-qa/uoa-integration-tests/python-testability
Merge into: lp:uoa-integration-tests
Diff against target: 365 lines (+346/-0)
3 files modified
python/uoa_integration_tests/evernote.py (+41/-0)
python/uoa_integration_tests/onlineaccounts.py (+233/-0)
python/uoa_integration_tests/tests/test_evernote_online_accounts.py (+72/-0)
To merge this branch: bzr merge lp:~canonical-platform-qa/uoa-integration-tests/python-testability
Reviewer Review Type Date Requested Status
Online Accounts Pending
Review via email: mp+241815@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'python'
2=== added directory 'python/uoa_integration_tests'
3=== added file 'python/uoa_integration_tests/__init__.py'
4=== added file 'python/uoa_integration_tests/evernote.py'
5--- python/uoa_integration_tests/evernote.py 1970-01-01 00:00:00 +0000
6+++ python/uoa_integration_tests/evernote.py 2014-11-14 14:59:44 +0000
7@@ -0,0 +1,41 @@
8+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
9+#
10+# Copyright (C) 2014 Canonical Ltd.
11+#
12+# This program is free software; you can redistribute it and/or modify
13+# it under the terms of the GNU General Public License version 3, as published
14+# by the Free Software Foundation.
15+#
16+# This program is distributed in the hope that it will be useful,
17+# but WITHOUT ANY WARRANTY; without even the implied warranty of
18+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+# GNU General Public License for more details.
20+#
21+# You should have received a copy of the GNU General Public License
22+# along with this program. If not, see <http://www.gnu.org/licenses/>.
23+
24+import logging
25+
26+from uoa_integration_tests import onlineaccounts
27+
28+
29+logger = logging.getLogger(__name__)
30+
31+
32+class EvernoteOnlineAccounts():
33+
34+ @classmethod
35+ def add_evernote_sandbox_account_with_oauth_token(
36+ cls, user_name, password, oauth_token):
37+ """Add an Evernote Sandbox account .
38+
39+ :param user_name: The user name of the account.
40+ :param password: The password of the account.
41+ :param oauth_token: The oauth token of the account.
42+
43+ """
44+ accounts_manager = onlineaccounts.AccountsManager()
45+ provider_id = 'com.ubuntu.reminders_evernote-account-plugin-sandbox'
46+ service_id = 'com.ubuntu.reminders_reminders-sandbox'
47+ return accounts_manager.add_account_with_oauth_token(
48+ provider_id, service_id, user_name, password, oauth_token)
49
50=== added file 'python/uoa_integration_tests/onlineaccounts.py'
51--- python/uoa_integration_tests/onlineaccounts.py 1970-01-01 00:00:00 +0000
52+++ python/uoa_integration_tests/onlineaccounts.py 2014-11-14 14:59:44 +0000
53@@ -0,0 +1,233 @@
54+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
55+#
56+# Copyright (C) 2014 Canonical Ltd.
57+#
58+# This program is free software; you can redistribute it and/or modify
59+# it under the terms of the GNU General Public License version 3, as published
60+# by the Free Software Foundation.
61+#
62+# This program is distributed in the hope that it will be useful,
63+# but WITHOUT ANY WARRANTY; without even the implied warranty of
64+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65+# GNU General Public License for more details.
66+#
67+# You should have received a copy of the GNU General Public License
68+# along with this program. If not, see <http://www.gnu.org/licenses/>.
69+
70+import logging
71+import time
72+import threading
73+
74+from gi.repository import Accounts, GLib, Signon
75+
76+
77+logger = logging.getLogger(__name__)
78+
79+
80+class CredentialsException(Exception):
81+
82+ """Exception for credentials problems."""
83+
84+
85+class AccountsManager(object):
86+
87+ """Manager for online accounts."""
88+
89+ def __init__(self):
90+ self._manager = Accounts.Manager.new()
91+
92+ def _start_main_loop(self):
93+ self.error = None
94+ self._main_loop = GLib.MainLoop()
95+ self._main_loop_thread = threading.Thread(
96+ target=self._main_loop.run)
97+ self._main_loop_thread.start()
98+
99+ def _join_main_loop(self):
100+ self._main_loop_thread.join()
101+ if self.error is not None:
102+ raise CredentialsException(self.error)
103+
104+ def add_account_with_oauth_token(
105+ self, provider_id, service_id, user_name, password, oauth_token):
106+ """Add an account with an oauth token.
107+
108+ :param provider_id: The identifier of the account provider.
109+ :param servide_id: The identifier of the service that will use the
110+ account.
111+ :param user_name: The user name of the account.
112+ :param password: The password of the account.
113+ :param oauth_token: The oauth token of the account.
114+
115+ """
116+ logger.info('Add an account for provider {} and service {}.'.format(
117+ provider_id, service_id))
118+ logger.info('user name: {}, password: {}, oauth_token: {}.'.format(
119+ user_name, password, oauth_token))
120+ self._start_main_loop()
121+
122+ account = self._create_account(provider_id)
123+ logger.debug('account %s' % account.get_settings_dict())
124+
125+ if not account.get_settings_dict():
126+ self._delete_account_on_error(account)
127+ self._quit_main_loop_on_error('account is blank', 'add account')
128+
129+ info = self._get_identity_info(user_name, password)
130+
131+ identity = Signon.Identity.new()
132+ identity.store_credentials_with_info(
133+ info, self._set_credentials_id_to_account,
134+ {'account': account, 'oauth_token': oauth_token})
135+ logger.debug('identity %s' % identity.list_properties())
136+
137+ logger.debug('Joining loop')
138+
139+ self._join_main_loop()
140+
141+ # XXX Sometimes, the account fails to be enabled. This sleep seems to
142+ # fix it but we haven't yet found the reason. --elopio - 2014-06-25
143+ time.sleep(10)
144+ self._enable_service(account, service_id)
145+
146+ logger.info('Created the account with id: {}.'.format(account.id))
147+ self._log_accounts_info()
148+ return account
149+
150+ def _create_account(self, provider_id):
151+ logger.debug('Creating the Evernote account.')
152+ account = self._manager.create_account(provider_id)
153+ account.set_enabled(True)
154+ account.store(self._on_account_created, None)
155+ return account
156+
157+ def _on_account_created(self, account, error, _):
158+ if error:
159+ self._quit_main_loop_on_error(error, 'storing account')
160+
161+ def _delete_account_on_error(self, account):
162+ # attempt to clean up after ourselves, since normal
163+ # addCleanups will not run in this case
164+ try:
165+ logger.debug('Cleaning up account %s' % account.id)
166+ account.delete()
167+ account.store(self._on_account_deleted, None)
168+ except:
169+ logger.warn('Failed to cleanup account')
170+
171+ def _quit_main_loop_on_error(self, error, step):
172+ logger.error('Error {}.'.format(step))
173+ self.error = error
174+ self._main_loop.quit()
175+ raise CredentialsException(error)
176+
177+ def _get_identity_info(self, user_name, password):
178+ info = Signon.IdentityInfo.new()
179+ info.set_username(user_name)
180+ info.set_caption(user_name)
181+ info.set_secret(password, True)
182+ return info
183+
184+ def _set_credentials_id_to_account(
185+ self, identity, id_, error, account_dict):
186+ if error:
187+ self._quit_main_loop_on_error(
188+ error, 'storing credentials with info')
189+
190+ logger.debug('Setting credentials to account.')
191+ account = account_dict.get('account')
192+ oauth_token = account_dict.get('oauth_token')
193+ account.set_variant('CredentialsId', GLib.Variant('u', id_))
194+ account.store(self._process_session, oauth_token)
195+ logger.debug('Account stored')
196+
197+ def _process_session(self, account, error, oauth_token):
198+ if error:
199+ self._quit_main_loop_on_error(
200+ error, 'setting credentials id to account')
201+
202+ logger.debug('Processing session.')
203+ account_service = Accounts.AccountService.new(account, None)
204+ logger.debug('account_service %s' % account_service.list_properties())
205+ auth_data = account_service.get_auth_data()
206+ logger.debug('auth_data %s' % auth_data.get_parameters())
207+ identity = auth_data.get_credentials_id()
208+ method = auth_data.get_method()
209+ if method is None:
210+ self._delete_account_on_error(account)
211+ self._quit_main_loop_on_error('Method is none',
212+ 'processing auth data')
213+ mechanism = auth_data.get_mechanism()
214+ session_data = auth_data.get_parameters()
215+ session_data['ProvidedTokens'] = GLib.Variant('a{sv}', {
216+ 'TokenSecret': GLib.Variant('s', 'dummy'),
217+ 'AccessToken': GLib.Variant('s', oauth_token),
218+ })
219+ logger.debug('session_data %s' % session_data)
220+ logger.debug('Authenticating session %s, %s' % (identity, method))
221+ session = Signon.AuthSession.new(identity, method)
222+ logger.debug('Send session %s' % session)
223+ session.process(
224+ session_data, mechanism, self._on_login_processed, None)
225+ logger.debug('Session processed')
226+
227+ def _on_login_processed(self, session, reply, error, userdata):
228+ if error:
229+ self._quit_main_loop_on_error(error, 'processing session')
230+
231+ else:
232+ self._main_loop.quit()
233+
234+ def _enable_service(self, account, service_id):
235+ logger.debug('Enabling evernote service.')
236+ service = self._manager.get_service(service_id)
237+ account.select_service(service)
238+ account.set_enabled(True)
239+ account.store(self._on_service_enabled, None)
240+
241+ def _on_service_enabled(self, account, error, _):
242+ if error:
243+ self._quit_main_loop_on_error(error, 'enabling service')
244+
245+ def _log_accounts_info(self):
246+ account_ids = self._manager.list()
247+ logger.debug('Existing accounts: {}.'.format(account_ids))
248+ for id_ in account_ids:
249+ account = self._manager.get_account(id_)
250+ self._log_account_info(account)
251+
252+ def _log_account_info(self, account):
253+ logger.debug('Account info:')
254+ logger.debug('id: {}'.format(account.id))
255+ logger.debug('provider: {}'.format(account.get_provider_name()))
256+ logger.debug('enabled: {}'.format(account.get_enabled()))
257+ logger.debug('Account services:')
258+ for service in account.list_services():
259+ logger.debug('name: {}'.format(service.get_name()))
260+ account_service = Accounts.AccountService.new(account, service)
261+ logger.debug('enabled: {}'.format(account_service.get_enabled()))
262+
263+ def get_accounts_list(self):
264+ return self._manager.list()
265+
266+ def delete_account(self, account):
267+ """Delete an account.
268+
269+ :param account: The account to delete.
270+
271+ """
272+ logger.info('Deleting the account with id {}.'.format(account.id))
273+ self._start_main_loop()
274+ # XXX There seems to be a problem when we try to delete the account too
275+ # soon after starting the main loop.
276+ # Reported as bug http://pad.lv/1363604. --elopio - 2014-09-01
277+ time.sleep(10)
278+ account.delete()
279+ account.store(self._on_account_deleted, None)
280+ self._join_main_loop()
281+
282+ def _on_account_deleted(self, account, error, _):
283+ if error:
284+ self._quit_main_loop_on_error(error, 'deleting account')
285+ else:
286+ self._main_loop.quit()
287
288=== added directory 'python/uoa_integration_tests/tests'
289=== added file 'python/uoa_integration_tests/tests/__init__.py'
290=== added file 'python/uoa_integration_tests/tests/test_evernote_online_accounts.py'
291--- python/uoa_integration_tests/tests/test_evernote_online_accounts.py 1970-01-01 00:00:00 +0000
292+++ python/uoa_integration_tests/tests/test_evernote_online_accounts.py 2014-11-14 14:59:44 +0000
293@@ -0,0 +1,72 @@
294+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
295+#
296+# Copyright (C) 2014 Canonical Ltd
297+#
298+# This program is free software: you can redistribute it and/or modify
299+# it under the terms of the GNU General Public License version 3 as
300+# published by the Free Software Foundation.
301+#
302+# This program is distributed in the hope that it will be useful,
303+# but WITHOUT ANY WARRANTY; without even the implied warranty of
304+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
305+# GNU General Public License for more details.
306+#
307+# You should have received a copy of the GNU General Public License
308+# along with this program. If not, see <http://www.gnu.org/licenses/>.
309+
310+import logging
311+
312+import testtools
313+from gi.repository import Accounts
314+from testtools.matchers import HasLength
315+
316+from uoa_integration_tests import onlineaccounts, evernote
317+
318+
319+logger = logging.getLogger(__name__)
320+
321+
322+class EvernoteCredentialsTestCase(testtools.TestCase):
323+
324+ def setUp(self):
325+ super(EvernoteCredentialsTestCase, self).setUp()
326+ self.accounts_manager = onlineaccounts.AccountsManager()
327+
328+ def add_evernote_sandbox_account(self):
329+ accounts = evernote.EvernoteOnlineAccounts
330+ add_account = accounts.add_evernote_sandbox_account_with_oauth_token
331+ account = add_account('dummy', 'dummy', 'dummy')
332+ self.addCleanup(self.delete_account, account)
333+ return account
334+
335+ def delete_account(self, account):
336+ if account.id in self.account_manager.get_accounts_list():
337+ self.accounts_manager.delete_account(account)
338+
339+ def test_add_evernote_sandbox_account_must_enable_it(self):
340+ account = self.add_evernote_sandbox_account()
341+
342+ self.assertTrue(account.get_enabled())
343+
344+ def test_add_evernote_sandbox_account_must_set_provider(self):
345+ account = self.add_evernote_sandbox_account()
346+
347+ provider_id = 'com.ubuntu.reminders_evernote-account-plugin-sandbox'
348+ self.assertEqual(account.get_provider_name(), provider_id)
349+
350+ def test_add_evernote_sandbox_account_must_enable_evernote_service(self):
351+ account = self.add_evernote_sandbox_account()
352+ services = account.list_services()
353+
354+ self.assertThat(services, HasLength(1))
355+ service_id = 'com.ubuntu.reminders_reminders-sandbox'
356+ self.assertEqual(services[0].get_name(), service_id)
357+ service = Accounts.AccountService.new(account, services[0])
358+ self.assertTrue(service.get_enabled())
359+
360+ def test_delete_evernote_sandbox_account_must_remove_it(self):
361+ account = self.add_evernote_sandbox_account()
362+ self.assertThat(self.account_manager._manager.list(), HasLength(1))
363+
364+ self.account_manager.delete_account(account)
365+ self.assertThat(self.account_manager._manager.list(), HasLength(0))

Subscribers

People subscribed via source and target branches