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