Merge lp:~nataliabidart/ubuntuone-control-panel/webclient-shutdowns into lp:ubuntuone-control-panel

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 224
Merged at revision: 228
Proposed branch: lp:~nataliabidart/ubuntuone-control-panel/webclient-shutdowns
Merge into: lp:ubuntuone-control-panel
Diff against target: 228 lines (+192/-1)
3 files modified
ubuntuone/controlpanel/web_client/tests/__init__.py (+19/-0)
ubuntuone/controlpanel/web_client/tests/test_txwebclient.py (+155/-0)
ubuntuone/controlpanel/web_client/txwebclient.py (+18/-1)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-control-panel/webclient-shutdowns
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) Approve
Roberto Alsina (community) Approve
Natalia Bidart Approve
Review via email: mp+75609@code.launchpad.net

Commit message

- Do not throw a webclient error when closing, all credits to alecu (LP: #845105).

To post a comment you must log in.
224. By Natalia Bidart on 2011-09-15

Attaching bug #845105.

Natalia Bidart (nataliabidart) wrote :

This is Alecu's code, and looks great.

review: Approve
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Alejandro J. Cura (alecu) wrote :

All tests pass, and the code looks great :P

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'ubuntuone/controlpanel/web_client/tests'
=== added file 'ubuntuone/controlpanel/web_client/tests/__init__.py'
--- ubuntuone/controlpanel/web_client/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntuone/controlpanel/web_client/tests/__init__.py 2011-09-15 18:43:24 +0000
@@ -0,0 +1,19 @@
1# -*- coding: utf-8 -*-
2
3# Authors: Alejandro J. Cura <alecu@canonical.com>
4#
5# Copyright 2011 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""Unit tests for the control panel backend webservice clients."""
020
=== added file 'ubuntuone/controlpanel/web_client/tests/test_txwebclient.py'
--- ubuntuone/controlpanel/web_client/tests/test_txwebclient.py 1970-01-01 00:00:00 +0000
+++ ubuntuone/controlpanel/web_client/tests/test_txwebclient.py 2011-09-15 18:43:24 +0000
@@ -0,0 +1,155 @@
1# -*- coding: utf-8 -*-
2
3# Authors: Alejandro J. Cura <alecu@canonical.com>
4#
5# Copyright 2011 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""Unit tests for the control panel backend twisted webservice client."""
20
21from twisted.application import internet, service
22from twisted.internet import defer, reactor
23from twisted.internet.defer import inlineCallbacks
24from twisted.web import server, resource
25from ubuntuone.devtools.testcase import skipIfOS
26
27from ubuntuone.controlpanel.web_client import txwebclient
28from ubuntuone.controlpanel.tests import TestCase
29
30
31SAMPLE_KEY = "result"
32SAMPLE_VALUE = "sample result"
33SAMPLE_RESOURCE = '{"%s": "%s"}' % (SAMPLE_KEY, SAMPLE_VALUE)
34SAMPLE_CREDENTIALS = dict(
35 consumer_key="consumer key",
36 consumer_secret="consumer secret",
37 token="the real token",
38 token_secret="the token secret",
39)
40
41
42def sample_get_credentials():
43 """Will return the sample credentials right now."""
44 return defer.succeed(SAMPLE_CREDENTIALS)
45
46
47class MockResource(resource.Resource):
48 """A simple web resource."""
49 isLeaf = True
50 contents = ""
51
52 # pylint: disable=C0103
53 # t.w.resource methods have freeform cased names
54
55 def getChild(self, name, request):
56 """Get a given child resource."""
57 if name == '':
58 return self
59 return resource.Resource.getChild(self, name, request)
60
61 def render_GET(self, request):
62 """Make a bit of html out of these resource's content."""
63 return self.contents
64
65
66class MockWebService(object):
67 """A mock webservice for testing"""
68
69 def __init__(self):
70 """Start up this instance."""
71 root = resource.Resource()
72 devices_resource = MockResource()
73 devices_resource.contents = SAMPLE_RESOURCE
74 root.putChild("devices", devices_resource)
75 root.putChild("throwerror", resource.NoResource())
76 unauthorized = resource.ErrorPage(resource.http.UNAUTHORIZED,
77 "Unauthrorized", "Unauthrorized")
78 root.putChild("unauthorized", unauthorized)
79
80 site = server.Site(root)
81 application = service.Application('web')
82 self.service_collection = service.IServiceCollection(application)
83 #pylint: disable=E1101
84 self.tcpserver = internet.TCPServer(0, site)
85 self.tcpserver.setServiceParent(self.service_collection)
86 self.service_collection.startService()
87
88 def get_url(self):
89 """Build the url for this mock server."""
90 #pylint: disable=W0212
91 port_num = self.tcpserver._port.getHost().port
92 return "http://localhost:%d/" % port_num
93
94 def stop(self):
95 """Shut it down."""
96 #pylint: disable=E1101
97 self.service_collection.stopService()
98
99
100class WebClientTestCase(TestCase):
101 """Test for the webservice client."""
102
103 timeout = 8
104
105 def setUp(self):
106 super(WebClientTestCase, self).setUp()
107 self.ws = MockWebService()
108 test_base_url = self.ws.get_url()
109 self.wc = txwebclient.WebClient(sample_get_credentials, test_base_url)
110
111 @inlineCallbacks
112 def tearDown(self):
113 super(WebClientTestCase, self).tearDown()
114 yield self.ws.stop()
115 self.wc.shutdown()
116
117 @inlineCallbacks
118 def test_get_url(self):
119 """A method is successfully called in the mock webservice."""
120 result = yield self.wc.call_api("devices")
121 self.assertIn(SAMPLE_KEY, result)
122 self.assertEqual(SAMPLE_VALUE, result[SAMPLE_KEY])
123
124 @inlineCallbacks
125 def test_get_url_error(self):
126 """The errback is called when there's some error."""
127 yield self.assertFailure(self.wc.call_api("throwerror"),
128 txwebclient.WebClientError)
129
130 @inlineCallbacks
131 def test_unauthorized(self):
132 """Detect when a request failed with UNAUTHORIZED."""
133 yield self.assertFailure(self.wc.call_api("unauthorized"),
134 txwebclient.UnauthorizedError)
135
136
137class WebClientShutdownTestCase(TestCase):
138 """The webclient behaviour during shutdown."""
139
140 @skipIfOS('win32', 'Failing on windows, see LP: #851158.')
141 @inlineCallbacks
142 def test_shutdown(self):
143 """The webclient behaves well during shutdown."""
144 d3 = defer.Deferred()
145 # pylint: disable=E1101
146 reactor.callLater(1, d3.callback, None)
147 ws = MockWebService()
148 test_base_url = ws.get_url()
149 wc = txwebclient.WebClient(sample_get_credentials, test_base_url)
150 d1 = wc.call_api("throwerror")
151 d2 = ws.stop()
152 wc.shutdown()
153 yield d2
154 yield defer.DeferredList([d1, d3], fireOnOneCallback=True,
155 fireOnOneErrback=True)
0156
=== modified file 'ubuntuone/controlpanel/web_client/txwebclient.py'
--- ubuntuone/controlpanel/web_client/txwebclient.py 2011-06-02 13:14:51 +0000
+++ ubuntuone/controlpanel/web_client/txwebclient.py 2011-09-15 18:43:24 +0000
@@ -20,6 +20,7 @@
2020
21import simplejson21import simplejson
2222
23from twisted.internet import defer, reactor
23from twisted.web import client, error, http24from twisted.web import client, error, http
2425
25from ubuntuone.controlpanel import WEBSERVICE_BASE_URL26from ubuntuone.controlpanel import WEBSERVICE_BASE_URL
@@ -39,6 +40,10 @@
39 """Initialize the webclient."""40 """Initialize the webclient."""
40 self.base_url = base_url41 self.base_url = base_url
41 self.get_credentials = get_credentials42 self.get_credentials = get_credentials
43 self.running = True
44 # pylint: disable=E1101
45 self.trigger_id = reactor.addSystemEventTrigger("before", "shutdown",
46 self.shutdown)
4247
43 def _handle_response(self, result):48 def _handle_response(self, result):
44 """Handle the response of the webservice call."""49 """Handle the response of the webservice call."""
@@ -74,7 +79,19 @@
74 d = self.get_credentials()79 d = self.get_credentials()
75 d.addErrback(self._handle_error)80 d.addErrback(self._handle_error)
76 d.addCallback(self._call_api_with_creds, api_name)81 d.addCallback(self._call_api_with_creds, api_name)
77 return d82 d2 = defer.Deferred()
83 d.addCallback(d2.callback)
84
85 def mask_errors_on_shutdown(failure):
86 """Do not fire the errbacks if we are shutting down."""
87 if self.running:
88 d2.errback(failure)
89
90 d.addErrback(mask_errors_on_shutdown)
91 return d2
7892
79 def shutdown(self):93 def shutdown(self):
80 """End the pending webclient calls."""94 """End the pending webclient calls."""
95 self.running = False
96 # pylint: disable=E1101
97 reactor.removeSystemEventTrigger(self.trigger_id)

Subscribers

People subscribed via source and target branches