Merge lp:~alecu/ubuntu-sso-client/post-restful-cleanups into lp:ubuntu-sso-client

Proposed by Alejandro J. Cura
Status: Merged
Approved by: Natalia Bidart
Approved revision: 872
Merged at revision: 845
Proposed branch: lp:~alecu/ubuntu-sso-client/post-restful-cleanups
Merge into: lp:ubuntu-sso-client
Diff against target: 910 lines (+250/-187)
12 files modified
run-tests (+8/-4)
ubuntu_sso/account.py (+36/-16)
ubuntu_sso/credentials.py (+9/-12)
ubuntu_sso/tests/test_account.py (+22/-1)
ubuntu_sso/tests/test_credentials.py (+59/-53)
ubuntu_sso/utils/webclient/common.py (+1/-1)
ubuntu_sso/utils/webclient/restful.py (+4/-0)
ubuntu_sso/utils/webclient/tests/__init__.py (+60/-0)
ubuntu_sso/utils/webclient/tests/test_restful.py (+12/-0)
ubuntu_sso/utils/webclient/tests/test_timestamp.py (+16/-32)
ubuntu_sso/utils/webclient/tests/test_webclient.py (+14/-63)
ubuntu_sso/utils/webclient/timestamp.py (+9/-5)
To merge this branch: bzr merge lp:~alecu/ubuntu-sso-client/post-restful-cleanups
Reviewer Review Type Date Requested Status
Manuel de la Peña (community) Approve
Natalia Bidart (community) Approve
Review via email: mp+91157@code.launchpad.net

Commit message

- Replace urllib2.Request with common web-client (LP: #884972).
- Replace urllib2.urlopen with common web-client (LP: #884975).
- Fix tests failing in sso with test_webclient (LP: #920591).

Description of the change

- Replace urllib2.Request with common web-client (LP: #884972).
- Replace urllib2.urlopen with common web-client (LP: #884975).
- Fix tests failing in sso with test_webclient (LP: #920591).

To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Looks good!

review: Approve
Revision history for this message
Manuel de la Peña (mandel) wrote :

Great work!

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (37.2 KiB)

The attempt to merge lp:~alecu/ubuntu-sso-client/post-restful-cleanups into lp:ubuntu-sso-client failed. Below is the output from the failed tests.

*** Running test suite for ubuntu_sso ***
ubuntu_sso.tests.test_account
  AccountTestCase
    test_generate_captcha ... [OK]
    test_is_not_validated ... [OK]
    test_is_not_validated_empty_result ... [OK]
    test_is_validated ... [OK]
    test_login_if_http_error ... [OK]
    test_login_if_no_error ... [OK]
    test_register_user_checks_valid_email ... [OK]
    test_register_user_checks_valid_password ... [OK]
    test_register_user_if_status_error ... [OK]
    test_register_user_if_status_error_with_string_message ... [OK]
    test_register_user_if_status_ok ... [OK]
    test_register_user_if_status_unknown ... [OK]
    test_request_password_reset_token_if_http_error ... [OK]
    test_request_password_reset_token_if_status_ok ... [OK]
    test_request_password_reset_token_if_status_unknown ... [OK]
    test_set_new_password_if_http_error ... [OK]
    test_set_new_password_if_status_ok ... [OK]
    test_set_new_password_if_status_unknown ... [OK]
    test_validate_email_if_status_error ... [OK]
    test_validate_email_if_status_error_with_string_message ... [OK]
    test_validate_email_if_status_ok ... [OK]
    test_validate_email_if_status_unknown ... [OK]
  EnvironOverridesTestCase
    test_no_override_service_url ... [OK]
    test_override_service_url ... [OK]
    test_service_url_as_parameter ... [OK]
twisted.trial.unittest
  TestCase
    runTest ... [OK]
ubuntu_sso.tests.test_account
  TimestampedAuthorizerTestCase
    test_authorize_request_includes_timestamp ... [OK]
ubuntu_sso.tests.test_credentials
  BasicTestCase
    runTest ... [OK]
  ClearCredentialsTestCase
    test_clear_credentials ... [OK]
    test_keyring_failure ... [OK]
  CredentialsAuthDeniedTestCase
    test_auth_denial_cb ... [OK]
  CredentialsCallbacksTestCase
    test_callbacks_are_stored ... [OK]
    test_callbacks_default_to_no_op ... [OK]
    test_creation_parameters_are_stored ... ...

Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (37.2 KiB)

The attempt to merge lp:~alecu/ubuntu-sso-client/post-restful-cleanups into lp:ubuntu-sso-client failed. Below is the output from the failed tests.

*** Running test suite for ubuntu_sso ***
ubuntu_sso.tests.test_account
  AccountTestCase
    test_generate_captcha ... [OK]
    test_is_not_validated ... [OK]
    test_is_not_validated_empty_result ... [OK]
    test_is_validated ... [OK]
    test_login_if_http_error ... [OK]
    test_login_if_no_error ... [OK]
    test_register_user_checks_valid_email ... [OK]
    test_register_user_checks_valid_password ... [OK]
    test_register_user_if_status_error ... [OK]
    test_register_user_if_status_error_with_string_message ... [OK]
    test_register_user_if_status_ok ... [OK]
    test_register_user_if_status_unknown ... [OK]
    test_request_password_reset_token_if_http_error ... [OK]
    test_request_password_reset_token_if_status_ok ... [OK]
    test_request_password_reset_token_if_status_unknown ... [OK]
    test_set_new_password_if_http_error ... [OK]
    test_set_new_password_if_status_ok ... [OK]
    test_set_new_password_if_status_unknown ... [OK]
    test_validate_email_if_status_error ... [OK]
    test_validate_email_if_status_error_with_string_message ... [OK]
    test_validate_email_if_status_ok ... [OK]
    test_validate_email_if_status_unknown ... [OK]
  EnvironOverridesTestCase
    test_no_override_service_url ... [OK]
    test_override_service_url ... [OK]
    test_service_url_as_parameter ... [OK]
twisted.trial.unittest
  TestCase
    runTest ... [OK]
ubuntu_sso.tests.test_account
  TimestampedAuthorizerTestCase
    test_authorize_request_includes_timestamp ... [OK]
ubuntu_sso.tests.test_credentials
  BasicTestCase
    runTest ... [OK]
  ClearCredentialsTestCase
    test_clear_credentials ... [OK]
    test_keyring_failure ... [OK]
  CredentialsAuthDeniedTestCase
    test_auth_denial_cb ... [OK]
  CredentialsCallbacksTestCase
    test_callbacks_are_stored ... [OK]
    test_callbacks_default_to_no_op ... [OK]
    test_creation_parameters_are_stored ... ...

872. By Alejandro J. Cura

fix xvfb-run command line

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'run-tests'
2--- run-tests 2012-02-02 18:09:21 +0000
3+++ run-tests 2012-02-03 17:25:21 +0000
4@@ -38,20 +38,24 @@
5 echo "Please install the 'pep8' package."
6 fi
7 }
8-
9 unset GTK_MODULES
10
11+XVFB=$(which xvfb-run)
12+if [ $XVFB ]; then
13+ XVFB_CMDLINE="$XVFB -a"
14+fi
15+
16 echo "*** Running test suite for ""$MODULE"" ***"
17-`which xvfb-run` u1trial --reactor=gi -p "$QT_TESTS_PATH, $GTK_TESTS_PATH" -i "test_windows.py" "$MODULE"
18+$XVFB_CMDLINE u1trial --reactor=gi -p "$QT_TESTS_PATH, $GTK_TESTS_PATH" -i "test_windows.py" "$MODULE"
19 rm -rf _trial_temp
20
21 echo "*** Running GTK test suite ***"
22-`which xvfb-run` u1trial --reactor=gi --gui "$GTK_TESTS_PATH"
23+$XVFB_CMDLINE u1trial --reactor=gi --gui "$GTK_TESTS_PATH"
24 rm -rf _trial_temp
25
26 echo "*** Running QT test suite ***"
27 ./setup.py build
28-USE_QT_MAINLOOP=True `which xvfb-run` u1trial --reactor=qt4 --gui "$QT_TESTS_PATH"
29+USE_QT_MAINLOOP=True $XVFB_CMDLINE u1trial --reactor=qt4 --gui "$QT_TESTS_PATH"
30 rm -rf _trial_temp
31 rm -rf build
32
33
34=== modified file 'ubuntu_sso/account.py'
35--- ubuntu_sso/account.py 2012-01-26 18:52:23 +0000
36+++ ubuntu_sso/account.py 2012-02-03 17:25:21 +0000
37@@ -134,7 +134,10 @@
38 logger.debug('generate_captcha: requesting captcha, filename: %r',
39 filename)
40 restful_client = restful.RestfulClient(self.service_url)
41- captcha = yield restful_client.restcall(u"captchas.new")
42+ try:
43+ captcha = yield restful_client.restcall(u"captchas.new")
44+ finally:
45+ restful_client.shutdown()
46
47 # download captcha and save to 'filename'
48 logger.debug('generate_captcha: server answered: %r', captcha)
49@@ -147,6 +150,8 @@
50 msg = 'generate_captcha crashed while downloading the image.'
51 logger.exception(msg)
52 raise
53+ finally:
54+ wc.shutdown()
55
56 defer.returnValue(captcha['captcha_id'])
57
58@@ -158,19 +163,22 @@
59 'displayname: %r, captcha_id: %r, captcha_solution: %r',
60 email, displayname, captcha_id, captcha_solution)
61 restful_client = restful.RestfulClient(self.service_url)
62- if not self._valid_email(email):
63- logger.error('register_user: InvalidEmailError for email: %r',
64- email)
65- raise InvalidEmailError()
66- if not self._valid_password(password):
67- logger.error('register_user: InvalidPasswordError')
68- raise InvalidPasswordError()
69+ try:
70+ if not self._valid_email(email):
71+ logger.error('register_user: InvalidEmailError for email: %r',
72+ email)
73+ raise InvalidEmailError()
74+ if not self._valid_password(password):
75+ logger.error('register_user: InvalidPasswordError')
76+ raise InvalidPasswordError()
77
78- result = yield restful_client.restcall(u"registration.register",
79- email=email, password=password,
80- displayname=displayname,
81- captcha_id=captcha_id,
82- captcha_solution=captcha_solution)
83+ result = yield restful_client.restcall(u"registration.register",
84+ email=email, password=password,
85+ displayname=displayname,
86+ captcha_id=captcha_id,
87+ captcha_solution=captcha_solution)
88+ finally:
89+ restful_client.shutdown()
90 logger.info('register_user: email: %r result: %r', email, result)
91
92 if result['status'].lower() == SSO_STATUS_ERROR:
93@@ -196,6 +204,8 @@
94 except WebClientError:
95 logger.exception('login failed with:')
96 raise AuthenticationError()
97+ finally:
98+ restful_client.shutdown()
99
100 logger.debug('login: authentication successful! consumer_key: %r, ' \
101 'token_name: %r', credentials['consumer_key'], token_name)
102@@ -207,7 +217,10 @@
103 logger.debug('is_validated: requesting accounts.me() info.')
104 restful_client = restful.RestfulClient(self.service_url,
105 oauth_credentials=token)
106- me_info = yield restful_client.restcall(u"accounts.me")
107+ try:
108+ me_info = yield restful_client.restcall(u"accounts.me")
109+ finally:
110+ restful_client.shutdown()
111 key = 'preferred_email'
112 result = key in me_info and me_info[key] != None
113
114@@ -225,8 +238,11 @@
115 token_name=token_name)
116 restful_client = restful.RestfulClient(self.service_url,
117 oauth_credentials=credentials)
118- result = yield restful_client.restcall(u"accounts.validate_email",
119- email_token=email_token)
120+ try:
121+ result = yield restful_client.restcall(u"accounts.validate_email",
122+ email_token=email_token)
123+ finally:
124+ restful_client.shutdown()
125 logger.info('validate_email: email: %r result: %r', email, result)
126 if 'errors' in result:
127 errorsdict = self._format_webservice_errors(result['errors'])
128@@ -246,6 +262,8 @@
129 except WebClientError, e:
130 logger.exception('request_password_reset_token failed with:')
131 raise ResetPasswordTokenError(e[1].split('\n')[0])
132+ finally:
133+ restful_client.shutdown()
134
135 if result['status'].lower() == SSO_STATUS_OK:
136 defer.returnValue(email)
137@@ -270,6 +288,8 @@
138 except WebClientError, e:
139 logger.exception('set_new_password failed with:')
140 raise NewPasswordError(e[1].split('\n')[0])
141+ finally:
142+ restful_client.shutdown()
143
144 if result['status'].lower() == SSO_STATUS_OK:
145 defer.returnValue(email)
146
147=== modified file 'ubuntu_sso/credentials.py'
148--- ubuntu_sso/credentials.py 2012-01-10 17:28:08 +0000
149+++ ubuntu_sso/credentials.py 2012-02-03 17:25:21 +0000
150@@ -39,15 +39,15 @@
151
152 import sys
153 import traceback
154-import urllib2
155
156 from functools import wraps
157
158 from twisted.internet import defer
159
160-from ubuntu_sso import NO_OP, utils
161+from ubuntu_sso import NO_OP
162 from ubuntu_sso.keyring import Keyring
163 from ubuntu_sso.logger import setup_logging
164+from ubuntu_sso.utils import webclient
165
166 logger = setup_logging('ubuntu_sso.credentials')
167
168@@ -216,6 +216,7 @@
169 self.denial_cb(app_name)
170
171 @handle_failures(msg='Problem opening the ping_url')
172+ @defer.inlineCallbacks
173 def _ping_url(self, app_name, email, credentials):
174 """Ping the self.ping_url with the email attached.
175
176@@ -235,16 +236,12 @@
177 'appending email (%r).', self.ping_url, email)
178 url = self.ping_url + email
179
180- headers = utils.oauth_headers(url, credentials)
181- request = urllib2.Request(url, headers=headers)
182- logger.debug('Opening the url %r with urllib2.urlopen.',
183- request.get_full_url())
184- # This code is blocking, we should change this.
185- # I've tried with deferToThread an twisted.web.client.getPage
186- # but the returned deferred will never be fired (nataliabidart).
187- response = urllib2.urlopen(request)
188- logger.debug('Url opened. Response: %s.', response.code)
189- return defer.succeed(response)
190+ wc = webclient.webclient_factory()
191+ try:
192+ response = yield wc.request(url, oauth_credentials=credentials)
193+ defer.returnValue(response)
194+ finally:
195+ wc.shutdown()
196
197 @handle_exceptions(msg='Problem opening the Ubuntu SSO user interface')
198 def _show_ui(self, login_only):
199
200=== modified file 'ubuntu_sso/tests/test_account.py'
201--- ubuntu_sso/tests/test_account.py 2012-01-26 18:52:23 +0000
202+++ ubuntu_sso/tests/test_account.py 2012-02-03 17:25:21 +0000
203@@ -82,16 +82,30 @@
204 class FakeWebClient(object):
205 """A fake webclient."""
206
207+ def __init__(self):
208+ self.started = True
209+
210 def request(self, url):
211 """Do a fake request, return a fake Response."""
212 return FakeWebClientResponse()
213
214+ def shutdown(self):
215+ """Turn off this webclient."""
216+ self.started = False
217+
218
219 class FakeRestfulClient(object):
220 """A fake restfulclient."""
221
222 preferred_email = EMAIL
223
224+ def __init__(self):
225+ self.started = True
226+
227+ def shutdown(self):
228+ """Stop this restfulclient."""
229+ self.started = False
230+
231 def fake_captchas_new(self):
232 """Return a local fake captcha."""
233 return FAKE_NEW_CAPTCHA
234@@ -231,6 +245,11 @@
235 self.frc = FakeRestfulClient()
236 self.patch(account.restful, "RestfulClient",
237 lambda *args, **kwargs: self.frc)
238+ self.addCleanup(self.verify_frc_shutdown)
239+
240+ def verify_frc_shutdown(self):
241+ """Verify that the FakeRestfulClient was stopped."""
242+ assert self.frc.started == False, "Restfulclient must be shut down."
243
244 @defer.inlineCallbacks
245 def tearDown(self):
246@@ -244,7 +263,8 @@
247 filename = self.mktemp()
248 self.addCleanup(lambda: os.remove(filename)
249 if os.path.exists(filename) else None)
250- self.patch(account.webclient, "webclient_factory", FakeWebClient)
251+ wc = FakeWebClient()
252+ self.patch(account.webclient, "webclient_factory", lambda: wc)
253 captcha_id = yield self.processor.generate_captcha(filename)
254 self.assertEqual(CAPTCHA_ID, captcha_id, 'captcha id must be correct.')
255 self.assertTrue(os.path.isfile(filename), '%s must exist.' % filename)
256@@ -254,6 +274,7 @@
257 with open(filename) as f:
258 actual = f.read()
259 self.assertEqual(expected, actual, 'captcha image must be correct.')
260+ self.assertFalse(wc.started, "Webclient must be shut down.")
261
262 @defer.inlineCallbacks
263 def test_register_user_checks_valid_email(self):
264
265=== modified file 'ubuntu_sso/tests/test_credentials.py'
266--- ubuntu_sso/tests/test_credentials.py 2011-12-21 21:38:15 +0000
267+++ ubuntu_sso/tests/test_credentials.py 2012-02-03 17:25:21 +0000
268@@ -16,12 +16,9 @@
269 """Tests for the Credentials module."""
270
271 import logging
272-import os
273-import time
274-import urllib2
275
276 from twisted.internet import defer
277-from twisted.trial.unittest import TestCase, FailTest
278+from twisted.trial.unittest import TestCase
279 from ubuntuone.devtools.handlers import MementoHandler
280
281 from ubuntu_sso import credentials
282@@ -293,8 +290,11 @@
283 self.patch(credentials.Keyring, 'get_credentials',
284 lambda kr, app: defer.succeed(TOKEN))
285 error = 'Bla'
286- self.patch(credentials.urllib2, 'urlopen',
287- lambda *a, **kw: self.fail(error))
288+ exception = SampleMiscException(error)
289+ failing_request = lambda *args, **kwargs: defer.fail(exception)
290+ self.patch(credentials.webclient.webclient_module().WebClient,
291+ "request", failing_request)
292+
293 self._cred_cleared = False
294 self.patch(self.obj, 'clear_credentials',
295 lambda: setattr(self, '_cred_cleared', True))
296@@ -303,14 +303,15 @@
297
298 # error cb called correctly
299 msg = 'Problem opening the ping_url'
300- self.assert_error_cb_called(msg=msg, detailed_error=FailTest(error))
301+ self.assert_error_cb_called(msg=msg, detailed_error=exception)
302 self.assertEqual(result, None)
303
304 # credentials cleared
305 self.assertTrue(self._cred_cleared)
306
307 # exception logged
308- self.assertTrue(self.memento.check_exception(FailTest, error))
309+ self.assertTrue(self.memento.check_exception(SampleMiscException,
310+ error))
311
312 @defer.inlineCallbacks
313 def test_pings_url(self):
314@@ -356,31 +357,35 @@
315 self.assertEqual(self._called, (('denial', APP_NAME), {}))
316
317
318+class FakeWebclient(object):
319+ """A fake webclient."""
320+
321+ def __init__(self):
322+ self.called = []
323+
324+ def request(self, *args, **kwargs):
325+ """Save a webclient request."""
326+ self.called.append((args, kwargs))
327+ return "response"
328+
329+ def shutdown(self):
330+ """Shutdown this fake webclient."""
331+
332+
333 class PingUrlTestCase(CredentialsTestCase):
334 """Test suite for the URL pinging."""
335
336 @defer.inlineCallbacks
337 def setUp(self):
338 yield super(PingUrlTestCase, self).setUp()
339- self._request = None
340-
341- def faked_urlopen(request):
342- """Fake urlopener."""
343- self._request = request
344- response = urllib2.addinfourl(fp=open(os.path.devnull),
345- headers=request.headers,
346- url=request.get_full_url(),
347- code=200)
348- return response
349-
350- self.patch(credentials.urllib2, 'urlopen', faked_urlopen)
351- self.patch(credentials.utils.timestamp_checker, "get_faithful_time",
352- time.time)
353+ self.wc = FakeWebclient()
354+ self.patch(credentials.webclient, "webclient_factory",
355+ lambda *args: self.wc)
356
357 @defer.inlineCallbacks
358 def test_ping_url_if_url_is_none(self):
359 """self.ping_url is opened."""
360- self.patch(credentials.urllib2, 'urlopen', self.fail)
361+ self.patch(self.wc, 'request', lambda *args, **kwargs: defer.fail())
362 self.obj.ping_url = None
363 yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
364 credentials=TOKEN)
365@@ -392,77 +397,78 @@
366 yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
367 credentials=TOKEN)
368
369- self.assertIsInstance(self._request, credentials.urllib2.Request)
370- self.assertEqual(self._request.get_full_url(),
371- self.obj.ping_url + EMAIL)
372+ args, _kwargs = self.wc.called[0]
373+ self.assertEqual(args[0], self.obj.ping_url + EMAIL)
374
375 @defer.inlineCallbacks
376 def test_request_is_signed_with_credentials(self):
377 """The http request to self.ping_url is signed with the credentials."""
378-
379- def fake_it(*a, **kw):
380- """Fake oauth_headers."""
381- self._set_called(*a, **kw)
382- return {}
383-
384- self.patch(credentials.utils, 'oauth_headers', fake_it)
385- result = yield self.obj._ping_url(APP_NAME, EMAIL, TOKEN)
386-
387- self.assertEqual(self._called,
388- ((self.obj.ping_url + EMAIL, TOKEN), {}))
389- self.assertEqual(result.code, 200)
390+ yield self.obj._ping_url(APP_NAME, EMAIL, TOKEN)
391+
392+ _args, kwargs = self.wc.called[0]
393+ self.assertEqual(kwargs["oauth_credentials"], TOKEN)
394
395 @defer.inlineCallbacks
396 def test_ping_url_error(self):
397 """Exception is handled if ping fails."""
398 error = 'Blu'
399- self.patch(credentials.urllib2, 'urlopen', lambda r: self.fail(error))
400-
401+ exception = SampleMiscException(error)
402+ self.patch(self.wc, "request",
403+ lambda *args, **kwargs: defer.fail(exception))
404 yield self.obj._ping_url(APP_NAME, EMAIL, TOKEN)
405
406 msg = 'Problem opening the ping_url'
407- self.assert_error_cb_called(msg=msg, detailed_error=FailTest(error))
408- self.assertTrue(self.memento.check_exception(FailTest, error))
409+ self.assert_error_cb_called(msg=msg, detailed_error=exception)
410+ self.assertTrue(self.memento.check_exception(SampleMiscException,
411+ error))
412
413 @defer.inlineCallbacks
414 def test_ping_url_formatting(self):
415 """The email is added as the first formatting argument."""
416 self.obj.ping_url = u'http://example.com/{email}/something/else'
417- result = yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
418+ yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
419 credentials=TOKEN)
420
421 expected = self.obj.ping_url.format(email=EMAIL)
422- self.assertEqual(expected, result.url)
423+ assert len(self.wc.called) > 0
424+ args, _kwargs = self.wc.called[0]
425+ self.assertEqual(expected, args[0])
426
427 @defer.inlineCallbacks
428 def test_ping_url_formatting_with_query_params(self):
429 """The email is added as the first formatting argument."""
430 self.obj.ping_url = u'http://example.com/{email}?something=else'
431- result = yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
432- credentials=TOKEN)
433+ yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
434+ credentials=TOKEN)
435
436 expected = self.obj.ping_url.format(email=EMAIL)
437- self.assertEqual(expected, result.url)
438+ assert len(self.wc.called) > 0
439+ args, _kwargs = self.wc.called[0]
440+ self.assertEqual(expected, args[0])
441
442 @defer.inlineCallbacks
443 def test_ping_url_formatting_no_email_kwarg(self):
444 """The email is added as the first formatting argument."""
445 self.obj.ping_url = u'http://example.com/{0}/yadda/?something=else'
446- result = yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
447- credentials=TOKEN)
448+ yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
449+ credentials=TOKEN)
450
451 expected = self.obj.ping_url.format(EMAIL)
452- self.assertEqual(expected, result.url)
453+ assert len(self.wc.called) > 0
454+ args, _kwargs = self.wc.called[0]
455+ self.assertEqual(expected, args[0])
456
457 @defer.inlineCallbacks
458 def test_ping_url_formatting_no_format(self):
459 """The email is appended if formatting could not be accomplished."""
460 self.obj.ping_url = u'http://example.com/yadda/'
461- result = yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
462- credentials=TOKEN)
463+ yield self.obj._ping_url(app_name=APP_NAME, email=EMAIL,
464+ credentials=TOKEN)
465
466 expected = self.obj.ping_url + EMAIL
467- self.assertEqual(expected, result.url)
468+ assert len(self.wc.called) > 0
469+ args, _kwargs = self.wc.called[0]
470+ self.assertEqual(expected, args[0])
471
472
473 class FindCredentialsTestCase(CredentialsTestCase):
474
475=== modified file 'ubuntu_sso/utils/webclient/common.py'
476--- ubuntu_sso/utils/webclient/common.py 2012-01-27 20:05:41 +0000
477+++ ubuntu_sso/utils/webclient/common.py 2012-02-03 17:25:21 +0000
478@@ -90,7 +90,7 @@
479 def get_timestamp_checker(cls):
480 """Get the timestamp checker for this class of webclient."""
481 if cls.timestamp_checker is None:
482- cls.timestamp_checker = TimestampChecker(cls())
483+ cls.timestamp_checker = TimestampChecker(cls)
484 return cls.timestamp_checker
485
486 def get_timestamp(self):
487
488=== modified file 'ubuntu_sso/utils/webclient/restful.py'
489--- ubuntu_sso/utils/webclient/restful.py 2012-01-25 15:02:50 +0000
490+++ ubuntu_sso/utils/webclient/restful.py 2012-02-03 17:25:21 +0000
491@@ -59,3 +59,7 @@
492 post_content=encoded_args,
493 extra_headers=POST_HEADERS)
494 defer.returnValue(json.loads(result.content))
495+
496+ def shutdown(self):
497+ """Stop the webclient used by this class."""
498+ self.webclient.shutdown()
499
500=== modified file 'ubuntu_sso/utils/webclient/tests/__init__.py'
501--- ubuntu_sso/utils/webclient/tests/__init__.py 2011-12-15 16:16:37 +0000
502+++ ubuntu_sso/utils/webclient/tests/__init__.py 2012-02-03 17:25:21 +0000
503@@ -15,3 +15,63 @@
504 # with this program. If not, see <http://www.gnu.org/licenses/>.
505
506 """Tests for the proxy-aware webclient."""
507+
508+from twisted.application import internet, service
509+from twisted.web import http, server
510+
511+
512+class SaveHTTPChannel(http.HTTPChannel):
513+ """A save protocol to be used in tests."""
514+
515+ protocolInstance = None
516+
517+ # pylint: disable=C0103
518+ def connectionMade(self):
519+ """Keep track of the given protocol."""
520+ SaveHTTPChannel.protocolInstance = self
521+ http.HTTPChannel.connectionMade(self)
522+
523+
524+class SaveSite(server.Site):
525+ """A site that let us know when it closed."""
526+
527+ protocol = SaveHTTPChannel
528+
529+ def __init__(self, *args, **kwargs):
530+ """Create a new instance."""
531+ server.Site.__init__(self, *args, **kwargs)
532+ # we disable the timeout in the tests, we will deal with it manually.
533+ # pylint: disable=C0103
534+ self.timeOut = None
535+
536+
537+class BaseMockWebServer(object):
538+ """A mock webserver for testing"""
539+
540+ def __init__(self):
541+ """Start up this instance."""
542+ self.root = self.get_root_resource()
543+ self.site = SaveSite(self.root)
544+ application = service.Application('web')
545+ self.service_collection = service.IServiceCollection(application)
546+ #pylint: disable=E1101
547+ self.tcpserver = internet.TCPServer(0, self.site)
548+ self.tcpserver.setServiceParent(self.service_collection)
549+ self.service_collection.startService()
550+
551+ def get_root_resource(self):
552+ """Get the root resource with all the children."""
553+ raise NotImplementedError
554+
555+ def get_iri(self):
556+ """Build the iri for this mock server."""
557+ #pylint: disable=W0212
558+ port_num = self.tcpserver._port.getHost().port
559+ return u"http://127.0.0.1:%d/" % port_num
560+
561+ def stop(self):
562+ """Shut it down."""
563+ #pylint: disable=E1101
564+ if self.site.protocol.protocolInstance:
565+ self.site.protocol.protocolInstance.timeoutConnection()
566+ return self.service_collection.stopService()
567
568=== modified file 'ubuntu_sso/utils/webclient/tests/test_restful.py'
569--- ubuntu_sso/utils/webclient/tests/test_restful.py 2012-01-25 15:02:50 +0000
570+++ ubuntu_sso/utils/webclient/tests/test_restful.py 2012-02-03 17:25:21 +0000
571@@ -43,12 +43,17 @@
572 self.return_value = SAMPLE_RESPONSE
573 self.called = []
574 self.init_kwargs = kwargs
575+ self.running = True
576
577 def request(self, iri, *args, **kwargs):
578 """Return a deferred that will be fired with a Response object."""
579 self.called.append((iri, args, kwargs))
580 return defer.succeed(Response(self.return_value))
581
582+ def shutdown(self):
583+ """Stop this fake webclient."""
584+ self.running = False
585+
586
587 class BaseTestCase(TestCase):
588 """The base for the Restful Client testcases."""
589@@ -75,11 +80,18 @@
590 """Initialize this testcase."""
591 yield super(RestfulClientTestCase, self).setUp()
592 self.rc = restful.RestfulClient(SAMPLE_SERVICE_IRI)
593+ self.addCleanup(self.rc.shutdown)
594
595 def test_has_a_webclient(self):
596 """The RC has a webclient."""
597 self.assertEqual(self.rc.webclient, self.wc)
598
599+ def test_shutsdown_the_webclient(self):
600+ """Calling shutdown on the restful shuts down the webclient too."""
601+ self.rc.shutdown()
602+ # pylint: disable=E1101
603+ self.assertFalse(self.rc.webclient.running, "The webclient is stopped")
604+
605 @defer.inlineCallbacks
606 def test_can_make_calls(self):
607 """The RC can make webcalls."""
608
609=== modified file 'ubuntu_sso/utils/webclient/tests/test_timestamp.py'
610--- ubuntu_sso/utils/webclient/tests/test_timestamp.py 2012-01-19 00:39:05 +0000
611+++ ubuntu_sso/utils/webclient/tests/test_timestamp.py 2012-02-03 17:25:21 +0000
612@@ -15,12 +15,12 @@
613 # with this program. If not, see <http://www.gnu.org/licenses/>.
614 """Tests for the timestamp sync classes."""
615
616-from twisted.application import internet, service
617 from twisted.internet import defer
618 from twisted.trial.unittest import TestCase
619-from twisted.web import server, resource
620+from twisted.web import resource
621
622-from ubuntu_sso.utils.webclient import timestamp, webclient_factory
623+from ubuntu_sso.utils.webclient import timestamp, webclient_module
624+from ubuntu_sso.utils.webclient.tests import BaseMockWebServer
625
626
627 class FakedError(Exception):
628@@ -46,61 +46,45 @@
629 return ""
630
631
632-class MockWebServer(object):
633+class MockWebServer(BaseMockWebServer):
634 """A mock webserver for testing."""
635
636- # pylint: disable=E1101
637- def __init__(self):
638- """Start up this instance."""
639- self.root = RootResource()
640- site = server.Site(self.root)
641- application = service.Application('web')
642- self.service_collection = service.IServiceCollection(application)
643- self.tcpserver = internet.TCPServer(0, site)
644- self.tcpserver.setServiceParent(self.service_collection)
645- self.service_collection.startService()
646-
647- def get_iri(self):
648- """Build the url for this mock server."""
649- # pylint: disable=W0212
650- port_num = self.tcpserver._port.getHost().port
651- return u"http://localhost:%d/" % port_num
652-
653- def stop(self):
654- """Shut it down."""
655- self.service_collection.stopService()
656+ def get_root_resource(self):
657+ """Get the root resource with all the children."""
658+ return RootResource()
659
660
661 class TimestampCheckerTestCase(TestCase):
662 """Tests for the timestamp checker."""
663
664+ timeout = 1
665+
666 @defer.inlineCallbacks
667 def setUp(self):
668 yield super(TimestampCheckerTestCase, self).setUp()
669 self.ws = MockWebServer()
670 self.addCleanup(self.ws.stop)
671- self.wc = webclient_factory()
672- self.addCleanup(self.wc.shutdown)
673+ self.webclient_class = webclient_module().WebClient
674 self.patch(timestamp.TimestampChecker, "SERVER_IRI", self.ws.get_iri())
675
676 @defer.inlineCallbacks
677 def test_returned_value_is_int(self):
678 """The returned value is an integer."""
679- checker = timestamp.TimestampChecker(self.wc)
680+ checker = timestamp.TimestampChecker(self.webclient_class)
681 result = yield checker.get_faithful_time()
682 self.assertEqual(type(result), int)
683
684 @defer.inlineCallbacks
685 def test_first_call_does_head(self):
686 """The first call gets the clock from our web."""
687- checker = timestamp.TimestampChecker(self.wc)
688+ checker = timestamp.TimestampChecker(self.webclient_class)
689 yield checker.get_faithful_time()
690 self.assertEqual(self.ws.root.count, 1)
691
692 @defer.inlineCallbacks
693 def test_second_call_is_cached(self):
694 """For the second call, the time is cached."""
695- checker = timestamp.TimestampChecker(self.wc)
696+ checker = timestamp.TimestampChecker(self.webclient_class)
697 yield checker.get_faithful_time()
698 yield checker.get_faithful_time()
699 self.assertEqual(self.ws.root.count, 1)
700@@ -110,7 +94,7 @@
701 """After some time, the cache expires."""
702 fake_timestamp = 1
703 self.patch(timestamp.time, "time", lambda: fake_timestamp)
704- checker = timestamp.TimestampChecker(self.wc)
705+ checker = timestamp.TimestampChecker(self.webclient_class)
706 yield checker.get_faithful_time()
707 fake_timestamp += timestamp.TimestampChecker.CHECKING_INTERVAL
708 yield checker.get_faithful_time()
709@@ -121,7 +105,7 @@
710 """When server can't be reached, the skew is not updated."""
711 fake_timestamp = 1
712 self.patch(timestamp.time, "time", lambda: fake_timestamp)
713- checker = timestamp.TimestampChecker(self.wc)
714+ checker = timestamp.TimestampChecker(self.webclient_class)
715 failing_get_server_time = lambda _: defer.fail(FakedError())
716 self.patch(checker, "get_server_time", failing_get_server_time)
717 yield checker.get_faithful_time()
718@@ -132,7 +116,7 @@
719 @defer.inlineCallbacks
720 def test_server_date_sends_nocache_headers(self):
721 """Getting the server date sends the no-cache headers."""
722- checker = timestamp.TimestampChecker(self.wc)
723+ checker = timestamp.TimestampChecker(self.webclient_class)
724 yield checker.get_server_date_header(self.ws.get_iri())
725 self.assertEqual(len(self.ws.root.request_headers), 1)
726 headers = self.ws.root.request_headers[0]
727
728=== modified file 'ubuntu_sso/utils/webclient/tests/test_webclient.py'
729--- ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-02-01 19:21:28 +0000
730+++ ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-02-03 17:25:21 +0000
731@@ -19,10 +19,9 @@
732 import sys
733 import urllib
734
735-from twisted.application import internet, service
736 from twisted.cred import checkers, portal
737 from twisted.internet import defer
738-from twisted.web import http, resource, server, guard
739+from twisted.web import guard, http, resource
740 from urllib2 import urlparse
741
742 from ubuntuone.devtools.testcases import TestCase
743@@ -30,6 +29,7 @@
744
745 from ubuntu_sso.utils import webclient
746 from ubuntu_sso.utils.webclient.common import BaseWebClient, HeaderDict
747+from ubuntu_sso.utils.webclient.tests import BaseMockWebServer
748
749 ANY_VALUE = object()
750 SAMPLE_KEY = "result"
751@@ -148,34 +148,11 @@
752 return "ERROR: Expected OAuth header not present."
753
754
755-class SaveHTTPChannel(http.HTTPChannel):
756- """A save protocol to be used in tests."""
757-
758- protocolInstance = None
759-
760- def connectionMade(self):
761- """Keep track of the given protocol."""
762- SaveHTTPChannel.protocolInstance = self
763- http.HTTPChannel.connectionMade(self)
764-
765-
766-class SaveSite(server.Site):
767- """A site that let us know when it closed."""
768-
769- protocol = SaveHTTPChannel
770-
771- def __init__(self, *args, **kwargs):
772- """Create a new instance."""
773- server.Site.__init__(self, *args, **kwargs)
774- # we disable the timeout in the tests, we will deal with it manually.
775- self.timeOut = None
776-
777-
778-class MockWebServer(object):
779- """A mock webserver for testing"""
780-
781- def __init__(self):
782- """Start up this instance."""
783+class MockWebServer(BaseMockWebServer):
784+ """A mock webserver for the webclient tests."""
785+
786+ def get_root_resource(self):
787+ """Get the root resource with all the children."""
788 root = resource.Resource()
789 root.putChild(SIMPLERESOURCE, SimpleResource())
790 root.putChild(POSTABLERESOURECE, PostableResource())
791@@ -197,27 +174,7 @@
792 guarded_resource = guard.HTTPAuthSessionWrapper(test_portal,
793 [cred_factory])
794 root.putChild(GUARDED, guarded_resource)
795-
796- self.site = SaveSite(root)
797- application = service.Application('web')
798- self.service_collection = service.IServiceCollection(application)
799- #pylint: disable=E1101
800- self.tcpserver = internet.TCPServer(0, self.site)
801- self.tcpserver.setServiceParent(self.service_collection)
802- self.service_collection.startService()
803-
804- def get_iri(self):
805- """Build the iri for this mock server."""
806- #pylint: disable=W0212
807- port_num = self.tcpserver._port.getHost().port
808- return u"http://127.0.0.1:%d/" % port_num
809-
810- def stop(self):
811- """Shut it down."""
812- #pylint: disable=E1101
813- if self.site.protocol.protocolInstance:
814- self.site.protocol.protocolInstance.timeoutConnection()
815- return self.service_collection.stopService()
816+ return root
817
818
819 class FakeReactor(object):
820@@ -261,7 +218,7 @@
821 class WebClientTestCase(TestCase):
822 """Test for the webclient."""
823
824- timeout = 8
825+ timeout = 1
826
827 @defer.inlineCallbacks
828 def setUp(self):
829@@ -271,8 +228,6 @@
830 self.base_iri = self.ws.get_iri()
831 self.wc = webclient.webclient_factory()
832 self.addCleanup(self.wc.shutdown)
833- # pylint: disable=W0511
834- # TODO: skewed timestamp correction
835
836 @defer.inlineCallbacks
837 def test_request_takes_an_iri(self):
838@@ -343,6 +298,8 @@
839 @defer.inlineCallbacks
840 def test_request_is_oauth_signed(self):
841 """The request is oauth signed."""
842+ tsc = self.wc.get_timestamp_checker()
843+ self.patch(tsc, "get_faithful_time", lambda: defer.succeed(1))
844 result = yield self.wc.request(self.base_iri + OAUTHRESOURCE,
845 oauth_credentials=SAMPLE_CREDENTIALS)
846 self.assertEqual(SAMPLE_RESOURCE, result.content)
847@@ -366,15 +323,14 @@
848 @defer.inlineCallbacks
849 def test_returned_content_are_bytes(self):
850 """The returned content are bytes."""
851+ tsc = self.wc.get_timestamp_checker()
852+ self.patch(tsc, "get_faithful_time", lambda: defer.succeed(1))
853 result = yield self.wc.request(self.base_iri + OAUTHRESOURCE,
854 oauth_credentials=SAMPLE_CREDENTIALS)
855 self.assertTrue(isinstance(result.content, bytes),
856 "The type of %r must be bytes" % result.content)
857
858
859-WebClientTestCase.skip = 'Tests failing, see bug #920591.'
860-
861-
862 class TimestampCheckerTestCase(TestCase):
863 """Tests for the timestampchecker classmethod."""
864
865@@ -388,12 +344,7 @@
866 def test_timestamp_checker_has_the_same_class_as_the_creator(self):
867 """The TimestampChecker has the same class."""
868 tsc = self.wc.get_timestamp_checker()
869- self.assertEqual(tsc.webclient.__class__, self.wc.__class__)
870-
871- def test_timestamp_checker_uses_different_webclient_than_the_creator(self):
872- """The TimestampChecker uses a different webclient than the creator."""
873- tsc = self.wc.get_timestamp_checker()
874- self.assertNotEqual(tsc.webclient, self.wc)
875+ self.assertEqual(tsc.webclient_class, self.wc.__class__)
876
877 def test_timestamp_checker_is_the_same_for_all_webclients(self):
878 """The TimestampChecker is the same for all webclients."""
879
880=== modified file 'ubuntu_sso/utils/webclient/timestamp.py'
881--- ubuntu_sso/utils/webclient/timestamp.py 2012-01-25 15:02:50 +0000
882+++ ubuntu_sso/utils/webclient/timestamp.py 2012-02-03 17:25:21 +0000
883@@ -33,18 +33,22 @@
884 ERROR_INTERVAL = 30 # in seconds
885 SERVER_IRI = u"http://one.ubuntu.com/api/time"
886
887- def __init__(self, webclient):
888+ def __init__(self, webclient_class):
889 """Initialize this instance."""
890 self.next_check = time.time()
891 self.skew = 0
892- self.webclient = webclient
893+ self.webclient_class = webclient_class
894
895 @defer.inlineCallbacks
896 def get_server_date_header(self, server_iri):
897 """Get the server date using twisted webclient."""
898- response = yield self.webclient.request(server_iri, method="HEAD",
899- extra_headers=NOCACHE_HEADERS)
900- defer.returnValue(response.headers["Date"][0])
901+ webclient = self.webclient_class()
902+ try:
903+ response = yield webclient.request(server_iri, method="HEAD",
904+ extra_headers=NOCACHE_HEADERS)
905+ defer.returnValue(response.headers["Date"][0])
906+ finally:
907+ webclient.shutdown()
908
909 @defer.inlineCallbacks
910 def get_server_time(self):

Subscribers

People subscribed via source and target branches