/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
1
# Copyright (C) 2011 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
"""Tools for dealing with the Launchpad API without using launchpadlib.
18
"""
19
20
import socket
21
22
from bzrlib import tests
6034.2.2 by Martin Pool
lp_api_lite tests update for move of Feature api into tests.features
23
from bzrlib.tests import features
6024.3.3 by John Arbash Meinel
Start at least testing the package_branch regex.
24
from bzrlib.plugins import launchpad
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
25
from bzrlib.plugins.launchpad import lp_api_lite
26
6034.2.2 by Martin Pool
lp_api_lite tests update for move of Feature api into tests.features
27
28
class _JSONParserFeature(features.Feature):
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
29
30
    def _probe(self):
31
        return lp_api_lite.json is not None
32
33
    def feature_name(self):
34
        return 'simplejson or json'
35
6034.2.2 by Martin Pool
lp_api_lite tests update for move of Feature api into tests.features
36
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
37
JSONParserFeature = _JSONParserFeature()
38
6034.2.2 by Martin Pool
lp_api_lite tests update for move of Feature api into tests.features
39
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
40
_example_response = r"""
41
{
42
    "total_size": 2,
43
    "start": 0,
44
    "next_collection_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary?distro_series=%2Fubuntu%2Flucid&exact_match=true&source_name=%22bzr%22&status=Published&ws.op=getPublishedSources&ws.start=1&ws.size=1",
45
    "entries": [
46
        {
47
            "package_creator_link": "https://api.launchpad.net/1.0/~maxb",
48
            "package_signer_link": "https://api.launchpad.net/1.0/~jelmer",
49
            "source_package_name": "bzr",
50
            "removal_comment": null,
51
            "display_name": "bzr 2.1.4-0ubuntu1 in lucid",
52
            "date_made_pending": null,
53
            "source_package_version": "2.1.4-0ubuntu1",
54
            "date_superseded": null,
55
            "http_etag": "\"9ba966152dec474dc0fe1629d0bbce2452efaf3b-5f4c3fbb3eaf26d502db4089777a9b6a0537ffab\"",
56
            "self_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary/+sourcepub/1750327",
57
            "distro_series_link": "https://api.launchpad.net/1.0/ubuntu/lucid",
58
            "component_name": "main",
59
            "status": "Published",
60
            "date_removed": null,
61
            "pocket": "Updates",
62
            "date_published": "2011-05-30T06:09:58.653984+00:00",
63
            "removed_by_link": null,
64
            "section_name": "devel",
65
            "resource_type_link": "https://api.launchpad.net/1.0/#source_package_publishing_history",
66
            "archive_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary",
67
            "package_maintainer_link": "https://api.launchpad.net/1.0/~ubuntu-devel-discuss-lists",
68
            "date_created": "2011-05-30T05:19:12.233621+00:00",
69
            "scheduled_deletion_date": null
70
        }
71
    ]
72
}"""
73
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
74
_no_versions_response = '{"total_size": 0, "start": 0, "entries": []}'
75
76
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
77
class TestLatestPublication(tests.TestCase):
78
79
    def make_latest_publication(self, archive='ubuntu', series='natty',
80
                                project='bzr'):
81
        return lp_api_lite.LatestPublication(archive, series, project)
82
83
    def test_init(self):
84
        latest_pub = self.make_latest_publication()
85
        self.assertEqual('ubuntu', latest_pub._archive)
86
        self.assertEqual('natty', latest_pub._series)
87
        self.assertEqual('bzr', latest_pub._project)
5050.79.8 by John Arbash Meinel
We should supply pocket=Release when none is supplied.
88
        self.assertEqual('Release', latest_pub._pocket)
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
89
90
    def test__archive_URL(self):
91
        latest_pub = self.make_latest_publication()
92
        self.assertEqual(
93
            'https://api.launchpad.net/1.0/ubuntu/+archive/primary',
94
            latest_pub._archive_URL())
95
96
    def test__publication_status_for_ubuntu(self):
97
        latest_pub = self.make_latest_publication()
98
        self.assertEqual('Published', latest_pub._publication_status())
99
100
    def test__publication_status_for_debian(self):
101
        latest_pub = self.make_latest_publication(archive='debian')
102
        self.assertEqual('Pending', latest_pub._publication_status())
103
104
    def test_pocket(self):
105
        latest_pub = self.make_latest_publication(series='natty-proposed')
106
        self.assertEqual('natty', latest_pub._series)
107
        self.assertEqual('Proposed', latest_pub._pocket)
108
109
    def test_series_None(self):
110
        latest_pub = self.make_latest_publication(series=None)
111
        self.assertEqual('ubuntu', latest_pub._archive)
112
        self.assertEqual(None, latest_pub._series)
113
        self.assertEqual('bzr', latest_pub._project)
5050.79.8 by John Arbash Meinel
We should supply pocket=Release when none is supplied.
114
        self.assertEqual('Release', latest_pub._pocket)
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
115
116
    def test__query_params(self):
117
        latest_pub = self.make_latest_publication()
118
        self.assertEqual({'ws.op': 'getPublishedSources',
119
                          'exact_match': 'true',
120
                          'source_name': '"bzr"',
121
                          'status': 'Published',
122
                          'ws.size': '1',
123
                          'distro_series': '/ubuntu/natty',
5050.79.8 by John Arbash Meinel
We should supply pocket=Release when none is supplied.
124
                          'pocket': 'Release',
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
125
                         }, latest_pub._query_params())
126
127
    def test__query_params_no_series(self):
128
        latest_pub = self.make_latest_publication(series=None)
129
        self.assertEqual({'ws.op': 'getPublishedSources',
130
                          'exact_match': 'true',
131
                          'source_name': '"bzr"',
132
                          'status': 'Published',
133
                          'ws.size': '1',
5050.79.8 by John Arbash Meinel
We should supply pocket=Release when none is supplied.
134
                          'pocket': 'Release',
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
135
                         }, latest_pub._query_params())
136
137
    def test__query_params_pocket(self):
138
        latest_pub = self.make_latest_publication(series='natty-proposed')
139
        self.assertEqual({'ws.op': 'getPublishedSources',
140
                          'exact_match': 'true',
141
                          'source_name': '"bzr"',
142
                          'status': 'Published',
143
                          'ws.size': '1',
144
                          'distro_series': '/ubuntu/natty',
145
                          'pocket': 'Proposed',
146
                         }, latest_pub._query_params())
147
148
    def test__query_URL(self):
149
        latest_pub = self.make_latest_publication()
150
        # we explicitly sort params, so we can be sure this URL matches exactly
151
        self.assertEqual(
152
            'https://api.launchpad.net/1.0/ubuntu/+archive/primary'
153
            '?distro_series=%2Fubuntu%2Fnatty&exact_match=true'
5050.79.8 by John Arbash Meinel
We should supply pocket=Release when none is supplied.
154
            '&pocket=Release&source_name=%22bzr%22&status=Published'
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
155
            '&ws.op=getPublishedSources&ws.size=1',
156
            latest_pub._query_URL())
157
158
    def DONT_test__gracefully_handle_failed_rpc_connection(self):
159
        # TODO: This test kind of sucks. We intentionally create an arbitrary
160
        #       port and don't listen to it, because we want the request to fail.
161
        #       However, it seems to take 1s for it to timeout. Is there a way
162
        #       to make it fail faster?
163
        latest_pub = self.make_latest_publication()
164
        s = socket.socket()
165
        s.bind(('127.0.0.1', 0))
166
        addr, port = s.getsockname()
167
        latest_pub.LP_API_ROOT = 'http://%s:%s/' % (addr, port)
168
        s.close()
169
        self.assertIs(None, latest_pub._get_lp_info())
170
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
171
    def DONT_test__query_launchpad(self):
5050.79.2 by John Arbash Meinel
Start refactoring lp_api_lite and making it testable.
172
        # TODO: This is a test that we are making a valid request against
173
        #       launchpad. This seems important, but it is slow, requires net
174
        #       access, and requires launchpad to be up and running. So for
175
        #       now, it is commented out for production tests.
176
        latest_pub = self.make_latest_publication()
177
        json_txt = latest_pub._get_lp_info()
178
        self.assertIsNot(None, json_txt)
179
        if lp_api_lite.json is None:
180
            # We don't have a way to parse the text
181
            return
182
        # The content should be a valid json result
183
        content = lp_api_lite.json.loads(json_txt)
184
        entries = content['entries'] # It should have an 'entries' field.
185
        # ws.size should mean we get 0 or 1, and there should be something
186
        self.assertEqual(1, len(entries))
187
        entry = entries[0]
188
        self.assertEqual('bzr', entry['source_package_name'])
189
        version = entry['source_package_version']
190
        self.assertIsNot(None, version)
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
191
192
    def test__get_lp_info_no_json(self):
193
        # If we can't parse the json, we don't make the query.
194
        self.overrideAttr(lp_api_lite, 'json', None)
195
        latest_pub = self.make_latest_publication()
196
        self.assertIs(None, latest_pub._get_lp_info())
197
198
    def test__parse_json_info_no_module(self):
199
        # If a json parsing module isn't available, we just return None here.
200
        self.overrideAttr(lp_api_lite, 'json', None)
201
        latest_pub = self.make_latest_publication()
202
        self.assertIs(None, latest_pub._parse_json_info(_example_response))
203
204
    def test__parse_json_example_response(self):
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
205
        self.requireFeature(JSONParserFeature)
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
206
        latest_pub = self.make_latest_publication()
207
        content = latest_pub._parse_json_info(_example_response)
208
        self.assertIsNot(None, content)
209
        self.assertEqual(2, content['total_size'])
210
        entries = content['entries']
211
        self.assertEqual(1, len(entries))
212
        entry = entries[0]
213
        self.assertEqual('bzr', entry['source_package_name'])
214
        self.assertEqual("2.1.4-0ubuntu1", entry["source_package_version"])
215
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
216
    def test__parse_json_not_json(self):
217
        self.requireFeature(JSONParserFeature)
218
        latest_pub = self.make_latest_publication()
219
        self.assertIs(None, latest_pub._parse_json_info('Not_valid_json'))
220
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
221
    def test_get_latest_version_no_response(self):
222
        latest_pub = self.make_latest_publication()
223
        latest_pub._get_lp_info = lambda: None
224
        self.assertEqual(None, latest_pub.get_latest_version())
225
226
    def test_get_latest_version_no_json(self):
227
        self.overrideAttr(lp_api_lite, 'json', None)
228
        latest_pub = self.make_latest_publication()
229
        self.assertEqual(None, latest_pub.get_latest_version())
230
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
231
    def test_get_latest_version_invalid_json(self):
232
        self.requireFeature(JSONParserFeature)
233
        latest_pub = self.make_latest_publication()
234
        latest_pub._get_lp_info = lambda: "not json"
235
        self.assertEqual(None, latest_pub.get_latest_version())
236
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
237
    def test_get_latest_version_no_versions(self):
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
238
        self.requireFeature(JSONParserFeature)
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
239
        latest_pub = self.make_latest_publication()
240
        latest_pub._get_lp_info = lambda: _no_versions_response
241
        self.assertEqual(None, latest_pub.get_latest_version())
242
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
243
    def test_get_latest_version_missing_entries(self):
244
        # Launchpad's no-entries response does have an empty entries value.
245
        # However, lets test that we handle other failures without tracebacks
246
        self.requireFeature(JSONParserFeature)
247
        latest_pub = self.make_latest_publication()
248
        latest_pub._get_lp_info = lambda: '{}'
249
        self.assertEqual(None, latest_pub.get_latest_version())
250
251
    def test_get_latest_version_invalid_entries(self):
252
        # Make sure we sanely handle a json response we don't understand
253
        self.requireFeature(JSONParserFeature)
254
        latest_pub = self.make_latest_publication()
255
        latest_pub._get_lp_info = lambda: '{"entries": {"a": 1}}'
256
        self.assertEqual(None, latest_pub.get_latest_version())
257
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
258
    def test_get_latest_version_example(self):
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
259
        self.requireFeature(JSONParserFeature)
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
260
        latest_pub = self.make_latest_publication()
261
        latest_pub._get_lp_info = lambda: _example_response
262
        self.assertEqual("2.1.4-0ubuntu1", latest_pub.get_latest_version())
263
264
    def DONT_test_get_latest_version_from_launchpad(self):
5050.79.4 by John Arbash Meinel
Put several tests behind a Feature object.
265
        self.requireFeature(JSONParserFeature)
5050.79.3 by John Arbash Meinel
All the bits are now hooked up. The slow tests are disabled,
266
        latest_pub = self.make_latest_publication()
267
        self.assertIsNot(None, latest_pub.get_latest_version())
6024.3.3 by John Arbash Meinel
Start at least testing the package_branch regex.
268
269
270
class TestIsUpToDate(tests.TestCase):
271
272
    def assertPackageBranchRe(self, url, user, archive, series, project):
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
273
        m = launchpad._package_branch.search(url)
6024.3.3 by John Arbash Meinel
Start at least testing the package_branch regex.
274
        if m is None:
275
            self.fail('package_branch regex did not match url: %s' % (url,))
276
        self.assertEqual(
277
            (user, archive, series, project),
278
            m.group('user', 'archive', 'series', 'project'))
279
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
280
    def assertNotPackageBranch(self, url):
281
        self.assertIs(None, launchpad._get_package_branch_info(url))
282
283
    def assertBranchInfo(self, url, archive, series, project):
284
        self.assertEqual((archive, series, project),
285
            launchpad._get_package_branch_info(url))
286
6024.3.3 by John Arbash Meinel
Start at least testing the package_branch regex.
287
    def test_package_branch_regex(self):
288
        self.assertPackageBranchRe(
289
            'http://bazaar.launchpad.net/+branch/ubuntu/foo',
290
            None, 'ubuntu', None, 'foo')
6024.3.4 by John Arbash Meinel
More tests, and a small fix for the regex.
291
        self.assertPackageBranchRe(
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
292
            'bzr+ssh://bazaar.launchpad.net/+branch/ubuntu/natty/foo',
6024.3.4 by John Arbash Meinel
More tests, and a small fix for the regex.
293
            None, 'ubuntu', 'natty/', 'foo')
294
        self.assertPackageBranchRe(
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
295
            'sftp://bazaar.launchpad.net/+branch/debian/foo',
6024.3.4 by John Arbash Meinel
More tests, and a small fix for the regex.
296
            None, 'debian', None, 'foo')
297
        self.assertPackageBranchRe(
298
            'http://bazaar.launchpad.net/+branch/debian/sid/foo',
299
            None, 'debian', 'sid/', 'foo')
300
        self.assertPackageBranchRe(
301
            'http://bazaar.launchpad.net/+branch'
302
            '/~ubuntu-branches/ubuntu/natty/foo/natty',
303
            '~ubuntu-branches/', 'ubuntu', 'natty/', 'foo')
6024.3.5 by John Arbash Meinel
Pull out code into helper functions, which allows us to test it.
304
        self.assertPackageBranchRe(
305
            'http://bazaar.launchpad.net/+branch'
306
            '/~user/ubuntu/natty/foo/test',
307
            '~user/', 'ubuntu', 'natty/', 'foo')
308
309
    def test_package_branch_doesnt_match(self):
310
        self.assertNotPackageBranch('http://example.com/ubuntu/foo')
311
        self.assertNotPackageBranch(
312
            'http://bazaar.launchpad.net/+branch/bzr')
313
        self.assertNotPackageBranch(
314
            'http://bazaar.launchpad.net/+branch/~bzr-pqm/bzr/bzr.dev')
315
        # Not a packaging branch because ~user isn't ~ubuntu-branches
316
        self.assertNotPackageBranch(
317
            'http://bazaar.launchpad.net/+branch'
318
            '/~user/ubuntu/natty/foo/natty')
319
320
    def test__get_package_branch_info(self):
321
        self.assertBranchInfo(
322
            'bzr+ssh://bazaar.launchpad.net/+branch/ubuntu/natty/foo',
323
            'ubuntu', 'natty', 'foo')
324
        self.assertBranchInfo(
325
            'bzr+ssh://bazaar.launchpad.net/+branch'
326
            '/~ubuntu-branches/ubuntu/natty/foo/natty',
327
            'ubuntu', 'natty', 'foo')
328
        self.assertBranchInfo(
329
            'http://bazaar.launchpad.net/+branch'
330
            '/~ubuntu-branches/debian/sid/foo/sid',
331
            'debian', 'sid', 'foo')
6024.3.7 by John Arbash Meinel
Add code to determine the moste recent tag.
332
333
334
class TestGetMostRecentTag(tests.TestCaseWithMemoryTransport):
335
336
    def make_simple_builder(self):
337
        builder = self.make_branch_builder('tip')
338
        builder.build_snapshot('A', [], [
339
            ('add', ('', 'root-id', 'directory', None))])
340
        b = builder.get_branch()
341
        b.tags.set_tag('tip-1.0', 'A')
342
        return builder, b, b.tags.get_tag_dict()
343
344
    def test_get_most_recent_tag_tip(self):
345
        builder, b, tag_dict = self.make_simple_builder()
346
        self.assertEqual('tip-1.0',
347
                         lp_api_lite.get_most_recent_tag(tag_dict, b))
348
349
    def test_get_most_recent_tag_older(self):
350
        builder, b, tag_dict = self.make_simple_builder()
351
        builder.build_snapshot('B', ['A'], [])
352
        self.assertEqual('B', b.last_revision())
353
        self.assertEqual('tip-1.0',
354
                         lp_api_lite.get_most_recent_tag(tag_dict, b))