~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugins/launchpad/test_lp_api_lite.py

(vila) Forbid more operations on ReadonlyTransportDecorator (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 doctest
 
21
import socket
 
22
 
 
23
from bzrlib import tests
 
24
from bzrlib.tests import features
 
25
from bzrlib.plugins import launchpad
 
26
from bzrlib.plugins.launchpad import lp_api_lite
 
27
from testtools.matchers import DocTestMatches
 
28
 
 
29
 
 
30
class _JSONParserFeature(features.Feature):
 
31
 
 
32
    def _probe(self):
 
33
        return lp_api_lite.json is not None
 
34
 
 
35
    def feature_name(self):
 
36
        return 'simplejson or json'
 
37
 
 
38
 
 
39
JSONParserFeature = _JSONParserFeature()
 
40
 
 
41
 
 
42
_example_response = r"""
 
43
{
 
44
    "total_size": 2,
 
45
    "start": 0,
 
46
    "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",
 
47
    "entries": [
 
48
        {
 
49
            "package_creator_link": "https://api.launchpad.net/1.0/~maxb",
 
50
            "package_signer_link": "https://api.launchpad.net/1.0/~jelmer",
 
51
            "source_package_name": "bzr",
 
52
            "removal_comment": null,
 
53
            "display_name": "bzr 2.1.4-0ubuntu1 in lucid",
 
54
            "date_made_pending": null,
 
55
            "source_package_version": "2.1.4-0ubuntu1",
 
56
            "date_superseded": null,
 
57
            "http_etag": "\"9ba966152dec474dc0fe1629d0bbce2452efaf3b-5f4c3fbb3eaf26d502db4089777a9b6a0537ffab\"",
 
58
            "self_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary/+sourcepub/1750327",
 
59
            "distro_series_link": "https://api.launchpad.net/1.0/ubuntu/lucid",
 
60
            "component_name": "main",
 
61
            "status": "Published",
 
62
            "date_removed": null,
 
63
            "pocket": "Updates",
 
64
            "date_published": "2011-05-30T06:09:58.653984+00:00",
 
65
            "removed_by_link": null,
 
66
            "section_name": "devel",
 
67
            "resource_type_link": "https://api.launchpad.net/1.0/#source_package_publishing_history",
 
68
            "archive_link": "https://api.launchpad.net/1.0/ubuntu/+archive/primary",
 
69
            "package_maintainer_link": "https://api.launchpad.net/1.0/~ubuntu-devel-discuss-lists",
 
70
            "date_created": "2011-05-30T05:19:12.233621+00:00",
 
71
            "scheduled_deletion_date": null
 
72
        }
 
73
    ]
 
74
}"""
 
75
 
 
76
_no_versions_response = '{"total_size": 0, "start": 0, "entries": []}'
 
77
 
 
78
 
 
79
class TestLatestPublication(tests.TestCase):
 
80
 
 
81
    def make_latest_publication(self, archive='ubuntu', series='natty',
 
82
                                project='bzr'):
 
83
        return lp_api_lite.LatestPublication(archive, series, project)
 
84
 
 
85
    def assertPlace(self, place, archive, series, project):
 
86
        lp = lp_api_lite.LatestPublication(archive, series, project)
 
87
        self.assertEqual(place, lp.place())
 
88
 
 
89
    def test_init(self):
 
90
        latest_pub = self.make_latest_publication()
 
91
        self.assertEqual('ubuntu', latest_pub._archive)
 
92
        self.assertEqual('natty', latest_pub._series)
 
93
        self.assertEqual('bzr', latest_pub._project)
 
94
        self.assertEqual('Release', latest_pub._pocket)
 
95
 
 
96
    def test__archive_URL(self):
 
97
        latest_pub = self.make_latest_publication()
 
98
        self.assertEqual(
 
99
            'https://api.launchpad.net/1.0/ubuntu/+archive/primary',
 
100
            latest_pub._archive_URL())
 
101
 
 
102
    def test__publication_status_for_ubuntu(self):
 
103
        latest_pub = self.make_latest_publication()
 
104
        self.assertEqual('Published', latest_pub._publication_status())
 
105
 
 
106
    def test__publication_status_for_debian(self):
 
107
        latest_pub = self.make_latest_publication(archive='debian')
 
108
        self.assertEqual('Pending', latest_pub._publication_status())
 
109
 
 
110
    def test_pocket(self):
 
111
        latest_pub = self.make_latest_publication(series='natty-proposed')
 
112
        self.assertEqual('natty', latest_pub._series)
 
113
        self.assertEqual('Proposed', latest_pub._pocket)
 
114
 
 
115
    def test_series_None(self):
 
116
        latest_pub = self.make_latest_publication(series=None)
 
117
        self.assertEqual('ubuntu', latest_pub._archive)
 
118
        self.assertEqual(None, latest_pub._series)
 
119
        self.assertEqual('bzr', latest_pub._project)
 
120
        self.assertEqual('Release', latest_pub._pocket)
 
121
 
 
122
    def test__query_params(self):
 
123
        latest_pub = self.make_latest_publication()
 
124
        self.assertEqual({'ws.op': 'getPublishedSources',
 
125
                          'exact_match': 'true',
 
126
                          'source_name': '"bzr"',
 
127
                          'status': 'Published',
 
128
                          'ws.size': '1',
 
129
                          'distro_series': '/ubuntu/natty',
 
130
                          'pocket': 'Release',
 
131
                         }, latest_pub._query_params())
 
132
 
 
133
    def test__query_params_no_series(self):
 
134
        latest_pub = self.make_latest_publication(series=None)
 
135
        self.assertEqual({'ws.op': 'getPublishedSources',
 
136
                          'exact_match': 'true',
 
137
                          'source_name': '"bzr"',
 
138
                          'status': 'Published',
 
139
                          'ws.size': '1',
 
140
                          'pocket': 'Release',
 
141
                         }, latest_pub._query_params())
 
142
 
 
143
    def test__query_params_pocket(self):
 
144
        latest_pub = self.make_latest_publication(series='natty-proposed')
 
145
        self.assertEqual({'ws.op': 'getPublishedSources',
 
146
                          'exact_match': 'true',
 
147
                          'source_name': '"bzr"',
 
148
                          'status': 'Published',
 
149
                          'ws.size': '1',
 
150
                          'distro_series': '/ubuntu/natty',
 
151
                          'pocket': 'Proposed',
 
152
                         }, latest_pub._query_params())
 
153
 
 
154
    def test__query_URL(self):
 
155
        latest_pub = self.make_latest_publication()
 
156
        # we explicitly sort params, so we can be sure this URL matches exactly
 
157
        self.assertEqual(
 
158
            'https://api.launchpad.net/1.0/ubuntu/+archive/primary'
 
159
            '?distro_series=%2Fubuntu%2Fnatty&exact_match=true'
 
160
            '&pocket=Release&source_name=%22bzr%22&status=Published'
 
161
            '&ws.op=getPublishedSources&ws.size=1',
 
162
            latest_pub._query_URL())
 
163
 
 
164
    def DONT_test__gracefully_handle_failed_rpc_connection(self):
 
165
        # TODO: This test kind of sucks. We intentionally create an arbitrary
 
166
        #       port and don't listen to it, because we want the request to fail.
 
167
        #       However, it seems to take 1s for it to timeout. Is there a way
 
168
        #       to make it fail faster?
 
169
        latest_pub = self.make_latest_publication()
 
170
        s = socket.socket()
 
171
        s.bind(('127.0.0.1', 0))
 
172
        addr, port = s.getsockname()
 
173
        latest_pub.LP_API_ROOT = 'http://%s:%s/' % (addr, port)
 
174
        s.close()
 
175
        self.assertIs(None, latest_pub._get_lp_info())
 
176
 
 
177
    def DONT_test__query_launchpad(self):
 
178
        # TODO: This is a test that we are making a valid request against
 
179
        #       launchpad. This seems important, but it is slow, requires net
 
180
        #       access, and requires launchpad to be up and running. So for
 
181
        #       now, it is commented out for production tests.
 
182
        latest_pub = self.make_latest_publication()
 
183
        json_txt = latest_pub._get_lp_info()
 
184
        self.assertIsNot(None, json_txt)
 
185
        if lp_api_lite.json is None:
 
186
            # We don't have a way to parse the text
 
187
            return
 
188
        # The content should be a valid json result
 
189
        content = lp_api_lite.json.loads(json_txt)
 
190
        entries = content['entries']  # It should have an 'entries' field.
 
191
        # ws.size should mean we get 0 or 1, and there should be something
 
192
        self.assertEqual(1, len(entries))
 
193
        entry = entries[0]
 
194
        self.assertEqual('bzr', entry['source_package_name'])
 
195
        version = entry['source_package_version']
 
196
        self.assertIsNot(None, version)
 
197
 
 
198
    def test__get_lp_info_no_json(self):
 
199
        # If we can't parse the json, we don't make the query.
 
200
        self.overrideAttr(lp_api_lite, 'json', None)
 
201
        latest_pub = self.make_latest_publication()
 
202
        self.assertIs(None, latest_pub._get_lp_info())
 
203
 
 
204
    def test__parse_json_info_no_module(self):
 
205
        # If a json parsing module isn't available, we just return None here.
 
206
        self.overrideAttr(lp_api_lite, 'json', None)
 
207
        latest_pub = self.make_latest_publication()
 
208
        self.assertIs(None, latest_pub._parse_json_info(_example_response))
 
209
 
 
210
    def test__parse_json_example_response(self):
 
211
        self.requireFeature(JSONParserFeature)
 
212
        latest_pub = self.make_latest_publication()
 
213
        content = latest_pub._parse_json_info(_example_response)
 
214
        self.assertIsNot(None, content)
 
215
        self.assertEqual(2, content['total_size'])
 
216
        entries = content['entries']
 
217
        self.assertEqual(1, len(entries))
 
218
        entry = entries[0]
 
219
        self.assertEqual('bzr', entry['source_package_name'])
 
220
        self.assertEqual("2.1.4-0ubuntu1", entry["source_package_version"])
 
221
 
 
222
    def test__parse_json_not_json(self):
 
223
        self.requireFeature(JSONParserFeature)
 
224
        latest_pub = self.make_latest_publication()
 
225
        self.assertIs(None, latest_pub._parse_json_info('Not_valid_json'))
 
226
 
 
227
    def test_get_latest_version_no_response(self):
 
228
        latest_pub = self.make_latest_publication()
 
229
        latest_pub._get_lp_info = lambda: None
 
230
        self.assertEqual(None, latest_pub.get_latest_version())
 
231
 
 
232
    def test_get_latest_version_no_json(self):
 
233
        self.overrideAttr(lp_api_lite, 'json', None)
 
234
        latest_pub = self.make_latest_publication()
 
235
        self.assertEqual(None, latest_pub.get_latest_version())
 
236
 
 
237
    def test_get_latest_version_invalid_json(self):
 
238
        self.requireFeature(JSONParserFeature)
 
239
        latest_pub = self.make_latest_publication()
 
240
        latest_pub._get_lp_info = lambda: "not json"
 
241
        self.assertEqual(None, latest_pub.get_latest_version())
 
242
 
 
243
    def test_get_latest_version_no_versions(self):
 
244
        self.requireFeature(JSONParserFeature)
 
245
        latest_pub = self.make_latest_publication()
 
246
        latest_pub._get_lp_info = lambda: _no_versions_response
 
247
        self.assertEqual(None, latest_pub.get_latest_version())
 
248
 
 
249
    def test_get_latest_version_missing_entries(self):
 
250
        # Launchpad's no-entries response does have an empty entries value.
 
251
        # However, lets test that we handle other failures without tracebacks
 
252
        self.requireFeature(JSONParserFeature)
 
253
        latest_pub = self.make_latest_publication()
 
254
        latest_pub._get_lp_info = lambda: '{}'
 
255
        self.assertEqual(None, latest_pub.get_latest_version())
 
256
 
 
257
    def test_get_latest_version_invalid_entries(self):
 
258
        # Make sure we sanely handle a json response we don't understand
 
259
        self.requireFeature(JSONParserFeature)
 
260
        latest_pub = self.make_latest_publication()
 
261
        latest_pub._get_lp_info = lambda: '{"entries": {"a": 1}}'
 
262
        self.assertEqual(None, latest_pub.get_latest_version())
 
263
 
 
264
    def test_get_latest_version_example(self):
 
265
        self.requireFeature(JSONParserFeature)
 
266
        latest_pub = self.make_latest_publication()
 
267
        latest_pub._get_lp_info = lambda: _example_response
 
268
        self.assertEqual("2.1.4-0ubuntu1", latest_pub.get_latest_version())
 
269
 
 
270
    def DONT_test_get_latest_version_from_launchpad(self):
 
271
        self.requireFeature(JSONParserFeature)
 
272
        latest_pub = self.make_latest_publication()
 
273
        self.assertIsNot(None, latest_pub.get_latest_version())
 
274
 
 
275
    def test_place(self):
 
276
        self.assertPlace('Ubuntu', 'ubuntu', None, 'bzr')
 
277
        self.assertPlace('Ubuntu Natty', 'ubuntu', 'natty', 'bzr')
 
278
        self.assertPlace('Ubuntu Natty Proposed', 'ubuntu', 'natty-proposed',
 
279
                         'bzr')
 
280
        self.assertPlace('Debian', 'debian', None, 'bzr')
 
281
        self.assertPlace('Debian Sid', 'debian', 'sid', 'bzr')
 
282
 
 
283
 
 
284
class TestIsUpToDate(tests.TestCase):
 
285
 
 
286
    def assertPackageBranchRe(self, url, user, archive, series, project):
 
287
        m = launchpad._package_branch.search(url)
 
288
        if m is None:
 
289
            self.fail('package_branch regex did not match url: %s' % (url,))
 
290
        self.assertEqual(
 
291
            (user, archive, series, project),
 
292
            m.group('user', 'archive', 'series', 'project'))
 
293
 
 
294
    def assertNotPackageBranch(self, url):
 
295
        self.assertIs(None, launchpad._get_package_branch_info(url))
 
296
 
 
297
    def assertBranchInfo(self, url, archive, series, project):
 
298
        self.assertEqual((archive, series, project),
 
299
            launchpad._get_package_branch_info(url))
 
300
 
 
301
    def test_package_branch_regex(self):
 
302
        self.assertPackageBranchRe(
 
303
            'http://bazaar.launchpad.net/+branch/ubuntu/foo',
 
304
            None, 'ubuntu', None, 'foo')
 
305
        self.assertPackageBranchRe(
 
306
            'bzr+ssh://bazaar.launchpad.net/+branch/ubuntu/natty/foo',
 
307
            None, 'ubuntu', 'natty/', 'foo')
 
308
        self.assertPackageBranchRe(
 
309
            'sftp://bazaar.launchpad.net/+branch/debian/foo',
 
310
            None, 'debian', None, 'foo')
 
311
        self.assertPackageBranchRe(
 
312
            'http://bazaar.launchpad.net/+branch/debian/sid/foo',
 
313
            None, 'debian', 'sid/', 'foo')
 
314
        self.assertPackageBranchRe(
 
315
            'http://bazaar.launchpad.net/+branch'
 
316
            '/~ubuntu-branches/ubuntu/natty/foo/natty',
 
317
            '~ubuntu-branches/', 'ubuntu', 'natty/', 'foo')
 
318
        self.assertPackageBranchRe(
 
319
            'http://bazaar.launchpad.net/+branch'
 
320
            '/~user/ubuntu/natty/foo/test',
 
321
            '~user/', 'ubuntu', 'natty/', 'foo')
 
322
 
 
323
    def test_package_branch_doesnt_match(self):
 
324
        self.assertNotPackageBranch('http://example.com/ubuntu/foo')
 
325
        self.assertNotPackageBranch(
 
326
            'http://bazaar.launchpad.net/+branch/bzr')
 
327
        self.assertNotPackageBranch(
 
328
            'http://bazaar.launchpad.net/+branch/~bzr-pqm/bzr/bzr.dev')
 
329
        # Not a packaging branch because ~user isn't ~ubuntu-branches
 
330
        self.assertNotPackageBranch(
 
331
            'http://bazaar.launchpad.net/+branch'
 
332
            '/~user/ubuntu/natty/foo/natty')
 
333
        # Older versions of bzr-svn/hg/git did not set Branch.base until after
 
334
        # they called Branch.__init__().
 
335
        self.assertNotPackageBranch(None)
 
336
 
 
337
    def test__get_package_branch_info(self):
 
338
        self.assertBranchInfo(
 
339
            'bzr+ssh://bazaar.launchpad.net/+branch/ubuntu/natty/foo',
 
340
            'ubuntu', 'natty', 'foo')
 
341
        self.assertBranchInfo(
 
342
            'bzr+ssh://bazaar.launchpad.net/+branch'
 
343
            '/~ubuntu-branches/ubuntu/natty/foo/natty',
 
344
            'ubuntu', 'natty', 'foo')
 
345
        self.assertBranchInfo(
 
346
            'http://bazaar.launchpad.net/+branch'
 
347
            '/~ubuntu-branches/debian/sid/foo/sid',
 
348
            'debian', 'sid', 'foo')
 
349
 
 
350
 
 
351
class TestGetMostRecentTag(tests.TestCaseWithMemoryTransport):
 
352
 
 
353
    def make_simple_builder(self):
 
354
        builder = self.make_branch_builder('tip')
 
355
        builder.build_snapshot('A', [], [
 
356
            ('add', ('', 'root-id', 'directory', None))])
 
357
        b = builder.get_branch()
 
358
        b.tags.set_tag('tip-1.0', 'A')
 
359
        return builder, b, b.tags.get_tag_dict()
 
360
 
 
361
    def test_get_most_recent_tag_tip(self):
 
362
        builder, b, tag_dict = self.make_simple_builder()
 
363
        self.assertEqual('tip-1.0',
 
364
                         lp_api_lite.get_most_recent_tag(tag_dict, b))
 
365
 
 
366
    def test_get_most_recent_tag_older(self):
 
367
        builder, b, tag_dict = self.make_simple_builder()
 
368
        builder.build_snapshot('B', ['A'], [])
 
369
        self.assertEqual('B', b.last_revision())
 
370
        self.assertEqual('tip-1.0',
 
371
                         lp_api_lite.get_most_recent_tag(tag_dict, b))
 
372
 
 
373
 
 
374
class StubLatestPublication(object):
 
375
 
 
376
    def __init__(self, latest):
 
377
        self.called = False
 
378
        self.latest = latest
 
379
 
 
380
    def get_latest_version(self):
 
381
        self.called = True
 
382
        return self.latest
 
383
 
 
384
    def place(self):
 
385
        return 'Ubuntu Natty'
 
386
 
 
387
 
 
388
class TestReportFreshness(tests.TestCaseWithMemoryTransport):
 
389
 
 
390
    def setUp(self):
 
391
        super(TestReportFreshness, self).setUp()
 
392
        builder = self.make_branch_builder('tip')
 
393
        builder.build_snapshot('A', [], [
 
394
            ('add', ('', 'root-id', 'directory', None))])
 
395
        self.branch = builder.get_branch()
 
396
 
 
397
    def assertFreshnessReports(self, verbosity, latest_version, content):
 
398
        """Assert that lp_api_lite.report_freshness reports the given content.
 
399
 
 
400
        :param verbosity: The reporting level
 
401
        :param latest_version: The version reported by StubLatestPublication
 
402
        :param content: The expected content. This should be in DocTest form.
 
403
        """
 
404
        orig_log_len = len(self.get_log())
 
405
        lp_api_lite.report_freshness(self.branch, verbosity,
 
406
            StubLatestPublication(latest_version))
 
407
        new_content = self.get_log()[orig_log_len:]
 
408
        # Strip out lines that have LatestPublication.get_* because those are
 
409
        # timing related lines. While interesting to log for now, they aren't
 
410
        # something we want to be testing
 
411
        new_content = new_content.split('\n')
 
412
        for i in range(2):
 
413
            if (len(new_content) > 0
 
414
                and 'LatestPublication.get_' in new_content[0]):
 
415
                new_content = new_content[1:]
 
416
        new_content = '\n'.join(new_content)
 
417
        self.assertThat(new_content,
 
418
            DocTestMatches(content,
 
419
                doctest.ELLIPSIS | doctest.REPORT_UDIFF))
 
420
 
 
421
    def test_verbosity_off_skips_check(self):
 
422
        # We force _get_package_branch_info so that we know it would otherwise
 
423
        # try to connect to launcphad
 
424
        self.overrideAttr(launchpad, '_get_package_branch_info',
 
425
            lambda x: ('ubuntu', 'natty', 'bzr'))
 
426
        self.overrideAttr(lp_api_lite, 'LatestPublication',
 
427
            lambda *args: self.fail('Tried to query launchpad'))
 
428
        c = self.branch.get_config_stack()
 
429
        c.set('launchpad.packaging_verbosity', 'off')
 
430
        orig_log_len = len(self.get_log())
 
431
        launchpad._check_is_up_to_date(self.branch)
 
432
        new_content = self.get_log()[orig_log_len:]
 
433
        self.assertContainsRe(new_content,
 
434
            'not checking memory.*/tip/ because verbosity is turned off')
 
435
 
 
436
    def test_verbosity_off(self):
 
437
        latest_pub = StubLatestPublication('1.0-1ubuntu2')
 
438
        lp_api_lite.report_freshness(self.branch, 'off', latest_pub)
 
439
        self.assertFalse(latest_pub.called)
 
440
 
 
441
    def test_verbosity_all_out_of_date_smoke(self):
 
442
        self.branch.tags.set_tag('1.0-1ubuntu1', 'A')
 
443
        self.assertFreshnessReports('all', '1.0-1ubuntu2',
 
444
             '    INFO  Most recent Ubuntu Natty version: 1.0-1ubuntu2\n'
 
445
             'Packaging branch version: 1.0-1ubuntu1\n'
 
446
             'Packaging branch status: OUT-OF-DATE\n')
 
447
 
 
448
 
 
449
class Test_GetNewestVersions(tests.TestCaseWithMemoryTransport):
 
450
 
 
451
    def setUp(self):
 
452
        super(Test_GetNewestVersions, self).setUp()
 
453
        builder = self.make_branch_builder('tip')
 
454
        builder.build_snapshot('A', [], [
 
455
            ('add', ('', 'root-id', 'directory', None))])
 
456
        self.branch = builder.get_branch()
 
457
 
 
458
    def assertLatestVersions(self, latest_branch_version, pub_version):
 
459
        if latest_branch_version is not None:
 
460
            self.branch.tags.set_tag(latest_branch_version, 'A')
 
461
        latest_pub = StubLatestPublication(pub_version)
 
462
        self.assertEqual((pub_version, latest_branch_version),
 
463
            lp_api_lite._get_newest_versions(self.branch, latest_pub))
 
464
 
 
465
    def test_no_tags(self):
 
466
        self.assertLatestVersions(None, '1.0-1ubuntu2')
 
467
 
 
468
    def test_out_of_date(self):
 
469
        self.assertLatestVersions('1.0-1ubuntu1', '1.0-1ubuntu2')
 
470
 
 
471
    def test_up_to_date(self):
 
472
        self.assertLatestVersions('1.0-1ubuntu2', '1.0-1ubuntu2')
 
473
 
 
474
    def test_missing(self):
 
475
        self.assertLatestVersions(None, None)
 
476
 
 
477
 
 
478
class Test_ReportFreshness(tests.TestCase):
 
479
 
 
480
    def assertReportedFreshness(self, verbosity, latest_ver, branch_latest_ver,
 
481
                               content, place='Ubuntu Natty'):
 
482
        """Assert that lp_api_lite.report_freshness reports the given content.
 
483
        """
 
484
        reported = []
 
485
        def report_func(value):
 
486
            reported.append(value)
 
487
 
 
488
        lp_api_lite._report_freshness(latest_ver, branch_latest_ver, place,
 
489
                                      verbosity, report_func)
 
490
        new_content = '\n'.join(reported)
 
491
        self.assertThat(new_content,
 
492
            DocTestMatches(content,
 
493
                doctest.ELLIPSIS | doctest.REPORT_UDIFF))
 
494
 
 
495
    def test_verbosity_minimal_no_tags(self):
 
496
        self.assertReportedFreshness('minimal', '1.0-1ubuntu2', None,
 
497
            'Branch is OUT-OF-DATE, Ubuntu Natty has 1.0-1ubuntu2\n')
 
498
 
 
499
    def test_verbosity_minimal_out_of_date(self):
 
500
        self.assertReportedFreshness('minimal', '1.0-1ubuntu2', '1.0-1ubuntu1',
 
501
            '1.0-1ubuntu1 is OUT-OF-DATE,'
 
502
            ' Ubuntu Natty has 1.0-1ubuntu2\n')
 
503
 
 
504
    def test_verbosity_minimal_up_to_date(self):
 
505
        self.assertReportedFreshness('minimal', '1.0-1ubuntu2', '1.0-1ubuntu2',
 
506
             '')
 
507
 
 
508
    def test_verbosity_minimal_missing(self):
 
509
        self.assertReportedFreshness('minimal', None, None,
 
510
             '')
 
511
 
 
512
    def test_verbosity_short_out_of_date(self):
 
513
        self.assertReportedFreshness('short', '1.0-1ubuntu2', '1.0-1ubuntu1',
 
514
            '1.0-1ubuntu1 is OUT-OF-DATE,'
 
515
            ' Ubuntu Natty has 1.0-1ubuntu2\n')
 
516
 
 
517
    def test_verbosity_short_up_to_date(self):
 
518
        self.assertReportedFreshness('short', '1.0-1ubuntu2', '1.0-1ubuntu2',
 
519
             '1.0-1ubuntu2 is CURRENT in Ubuntu Natty')
 
520
 
 
521
    def test_verbosity_short_missing(self):
 
522
        self.assertReportedFreshness('short', None, None,
 
523
             'Ubuntu Natty is MISSING a version')
 
524
 
 
525
    def test_verbosity_all_no_tags(self):
 
526
        self.assertReportedFreshness('all', '1.0-1ubuntu2', None,
 
527
             'Most recent Ubuntu Natty version: 1.0-1ubuntu2\n'
 
528
             'Packaging branch version: None\n'
 
529
             'Packaging branch status: OUT-OF-DATE\n')
 
530
 
 
531
    def test_verbosity_all_out_of_date(self):
 
532
        self.assertReportedFreshness('all', '1.0-1ubuntu2', '1.0-1ubuntu1',
 
533
             'Most recent Ubuntu Natty version: 1.0-1ubuntu2\n'
 
534
             'Packaging branch version: 1.0-1ubuntu1\n'
 
535
             'Packaging branch status: OUT-OF-DATE\n')
 
536
 
 
537
    def test_verbosity_all_up_to_date(self):
 
538
        self.assertReportedFreshness('all', '1.0-1ubuntu2', '1.0-1ubuntu2',
 
539
             'Most recent Ubuntu Natty version: 1.0-1ubuntu2\n'
 
540
             'Packaging branch status: CURRENT\n')
 
541
 
 
542
    def test_verbosity_all_missing(self):
 
543
        self.assertReportedFreshness('all', None, None,
 
544
             'Most recent Ubuntu Natty version: MISSING\n')
 
545
 
 
546
    def test_verbosity_None_is_all(self):
 
547
        self.assertReportedFreshness(None, '1.0-1ubuntu2', '1.0-1ubuntu2',
 
548
             'Most recent Ubuntu Natty version: 1.0-1ubuntu2\n'
 
549
             'Packaging branch status: CURRENT\n')