~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_fetch.py

Replace remaining to unittest.TestResult methods with super

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2007, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
18
18
import re
31
31
from bzrlib.bzrdir import BzrDir
32
32
from bzrlib.repofmt import knitrepo
33
33
from bzrlib.tests import TestCaseWithTransport
34
 
from bzrlib.tests.http_utils import TestCaseWithWebserver
35
34
from bzrlib.tests.test_revision import make_branches
36
35
from bzrlib.trace import mutter
37
36
from bzrlib.upgrade import Convert
38
37
from bzrlib.workingtree import WorkingTree
39
38
 
40
39
# These tests are a bit old; please instead add new tests into
41
 
# interrepository_implementations/ so they'll run on all relevant
 
40
# per_interrepository/ so they'll run on all relevant
42
41
# combinations.
43
42
 
44
43
 
47
46
 
48
47
def fetch_steps(self, br_a, br_b, writable_a):
49
48
    """A foreign test method for testing fetch locally and remotely."""
50
 
     
 
49
 
51
50
    # TODO RBC 20060201 make this a repository test.
52
51
    repo_b = br_b.repository
53
52
    self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
54
53
    self.assertTrue(repo_b.has_revision(br_a.revision_history()[2]))
55
54
    self.assertEquals(len(br_b.revision_history()), 7)
56
 
    self.assertEquals(br_b.fetch(br_a, br_a.revision_history()[2])[0], 0)
 
55
    br_b.fetch(br_a, br_a.revision_history()[2])
57
56
    # branch.fetch is not supposed to alter the revision history
58
57
    self.assertEquals(len(br_b.revision_history()), 7)
59
58
    self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
60
59
 
61
60
    # fetching the next revision up in sample data copies one revision
62
 
    self.assertEquals(br_b.fetch(br_a, br_a.revision_history()[3])[0], 1)
 
61
    br_b.fetch(br_a, br_a.revision_history()[3])
63
62
    self.assertTrue(repo_b.has_revision(br_a.revision_history()[3]))
64
63
    self.assertFalse(has_revision(br_a, br_b.revision_history()[6]))
65
64
    self.assertTrue(br_a.repository.has_revision(br_b.revision_history()[5]))
67
66
    # When a non-branch ancestor is missing, it should be unlisted...
68
67
    # as its not reference from the inventory weave.
69
68
    br_b4 = self.make_branch('br_4')
70
 
    count, failures = br_b4.fetch(br_b)
71
 
    self.assertEqual(count, 7)
72
 
    self.assertEqual(failures, [])
 
69
    br_b4.fetch(br_b)
73
70
 
74
 
    self.assertEqual(writable_a.fetch(br_b)[0], 1)
 
71
    writable_a.fetch(br_b)
75
72
    self.assertTrue(has_revision(br_a, br_b.revision_history()[3]))
76
73
    self.assertTrue(has_revision(br_a, br_b.revision_history()[4]))
77
 
        
 
74
 
78
75
    br_b2 = self.make_branch('br_b2')
79
 
    self.assertEquals(br_b2.fetch(br_b)[0], 7)
 
76
    br_b2.fetch(br_b)
80
77
    self.assertTrue(has_revision(br_b2, br_b.revision_history()[4]))
81
78
    self.assertTrue(has_revision(br_b2, br_a.revision_history()[2]))
82
79
    self.assertFalse(has_revision(br_b2, br_a.revision_history()[3]))
83
80
 
84
81
    br_a2 = self.make_branch('br_a2')
85
 
    self.assertEquals(br_a2.fetch(br_a)[0], 9)
 
82
    br_a2.fetch(br_a)
86
83
    self.assertTrue(has_revision(br_a2, br_b.revision_history()[4]))
87
84
    self.assertTrue(has_revision(br_a2, br_a.revision_history()[3]))
88
85
    self.assertTrue(has_revision(br_a2, br_a.revision_history()[2]))
89
86
 
90
87
    br_a3 = self.make_branch('br_a3')
91
 
    # pulling a branch with no revisions grabs nothing, regardless of 
 
88
    # pulling a branch with no revisions grabs nothing, regardless of
92
89
    # whats in the inventory.
93
 
    self.assertEquals(br_a3.fetch(br_a2)[0], 0)
 
90
    br_a3.fetch(br_a2)
94
91
    for revno in range(4):
95
92
        self.assertFalse(
96
93
            br_a3.repository.has_revision(br_a.revision_history()[revno]))
97
 
    self.assertEqual(br_a3.fetch(br_a2, br_a.revision_history()[2])[0], 3)
 
94
    br_a3.fetch(br_a2, br_a.revision_history()[2])
98
95
    # pull the 3 revisions introduced by a@u-0-3
99
 
    fetched = br_a3.fetch(br_a2, br_a.revision_history()[3])[0]
100
 
    self.assertEquals(fetched, 3, "fetched %d instead of 3" % fetched)
101
 
    # InstallFailed should be raised if the branch is missing the revision
 
96
    br_a3.fetch(br_a2, br_a.revision_history()[3])
 
97
    # NoSuchRevision should be raised if the branch is missing the revision
102
98
    # that was requested.
103
 
    self.assertRaises(errors.InstallFailed, br_a3.fetch, br_a2, 'pizza')
 
99
    self.assertRaises(errors.NoSuchRevision, br_a3.fetch, br_a2, 'pizza')
104
100
 
105
101
    # TODO: Test trying to fetch from a branch that points to a revision not
106
102
    # actually present in its repository.  Not every branch format allows you
109
105
    # every branch supports that.  -- mbp 20070814
110
106
 
111
107
    #TODO: test that fetch correctly does reweaving when needed. RBC 20051008
112
 
    # Note that this means - updating the weave when ghosts are filled in to 
 
108
    # Note that this means - updating the weave when ghosts are filled in to
113
109
    # add the right parents.
114
110
 
115
111
 
122
118
 
123
119
    def test_fetch_self(self):
124
120
        wt = self.make_branch_and_tree('br')
125
 
        self.assertEqual(wt.branch.fetch(wt.branch), (0, []))
 
121
        wt.branch.fetch(wt.branch)
126
122
 
127
123
    def test_fetch_root_knit(self):
128
124
        """Ensure that knit2.fetch() updates the root knit
129
 
        
 
125
 
130
126
        This tests the case where the root has a new revision, but there are no
131
127
        corresponding filename, parent, contents or other changes.
132
128
        """
251
247
                    rev_id).get_file_text('this-file-id'), text)
252
248
 
253
249
 
254
 
class TestHttpFetch(TestCaseWithWebserver):
255
 
    # FIXME RBC 20060124 this really isn't web specific, perhaps an
256
 
    # instrumented readonly transport? Can we do an instrumented
257
 
    # adapter and use self.get_readonly_url ?
258
 
 
259
 
    def test_fetch(self):
260
 
        #highest indices a: 5, b: 7
261
 
        br_a, br_b = make_branches(self)
262
 
        br_rem_a = Branch.open(self.get_readonly_url('branch1'))
263
 
        fetch_steps(self, br_rem_a, br_b, br_a)
264
 
 
265
 
    def _count_log_matches(self, target, logs):
266
 
        """Count the number of times the target file pattern was fetched in an http log"""
267
 
        get_succeeds_re = re.compile(
268
 
            '.*"GET .*%s HTTP/1.1" 20[06] - "-" "bzr/%s' %
269
 
            (     target,                    bzrlib.__version__))
270
 
        c = 0
271
 
        for line in logs:
272
 
            if get_succeeds_re.match(line):
273
 
                c += 1
274
 
        return c
275
 
 
276
 
    def test_weaves_are_retrieved_once(self):
277
 
        self.build_tree(("source/", "source/file", "target/"))
278
 
        # This test depends on knit dasta storage.
279
 
        wt = self.make_branch_and_tree('source', format='dirstate-tags')
280
 
        branch = wt.branch
281
 
        wt.add(["file"], ["id"])
282
 
        wt.commit("added file")
283
 
        open("source/file", 'w').write("blah\n")
284
 
        wt.commit("changed file")
285
 
        target = BzrDir.create_branch_and_repo("target/")
286
 
        source = Branch.open(self.get_readonly_url("source/"))
287
 
        self.assertEqual(target.fetch(source), (2, []))
288
 
        # this is the path to the literal file. As format changes 
289
 
        # occur it needs to be updated. FIXME: ask the store for the
290
 
        # path.
291
 
        self.log("web server logs are:")
292
 
        http_logs = self.get_readonly_server().logs
293
 
        self.log('\n'.join(http_logs))
294
 
        # unfortunately this log entry is branch format specific. We could 
295
 
        # factor out the 'what files does this format use' to a method on the 
296
 
        # repository, which would let us to this generically. RBC 20060419
297
 
        # RBC 20080408: Or perhaps we can assert that no files are fully read
298
 
        # twice?
299
 
        self.assertEqual(1, self._count_log_matches('/ce/id.kndx', http_logs))
300
 
        self.assertEqual(1, self._count_log_matches('/ce/id.knit', http_logs))
301
 
        self.assertEqual(1, self._count_log_matches('inventory.kndx', http_logs))
302
 
        # this r-h check test will prevent regressions, but it currently already 
303
 
        # passes, before the patch to cache-rh is applied :[
304
 
        self.assertTrue(1 >= self._count_log_matches('revision-history',
305
 
                                                     http_logs))
306
 
        self.assertTrue(1 >= self._count_log_matches('last-revision',
307
 
                                                     http_logs))
308
 
        # FIXME naughty poking in there.
309
 
        self.get_readonly_server().logs = []
310
 
        # check there is nothing more to fetch.  We take care to re-use the
311
 
        # existing transport so that the request logs we're about to examine
312
 
        # aren't cluttered with redundant probes for a smart server.
313
 
        # XXX: Perhaps this further parameterisation: test http with smart
314
 
        # server, and test http without smart server?
315
 
        source = Branch.open(
316
 
            self.get_readonly_url("source/"),
317
 
            possible_transports=[source.bzrdir.root_transport])
318
 
        self.assertEqual(target.fetch(source), (0, []))
319
 
        # should make just two requests
320
 
        http_logs = self.get_readonly_server().logs
321
 
        self.log("web server logs are:")
322
 
        self.log('\n'.join(http_logs))
323
 
        self.assertEqual(1, self._count_log_matches('branch-format', http_logs))
324
 
        self.assertEqual(1, self._count_log_matches('branch/format', http_logs))
325
 
        self.assertEqual(1, self._count_log_matches('repository/format',
326
 
            http_logs))
327
 
        self.assertTrue(1 >= self._count_log_matches('revision-history',
328
 
                                                     http_logs))
329
 
        self.assertTrue(1 >= self._count_log_matches('last-revision',
330
 
                                                     http_logs))
331
 
        self.assertEqual(4, len(http_logs))
332
 
 
333
 
 
334
250
class TestKnitToPackFetch(TestCaseWithTransport):
335
251
 
336
 
    def find_get_record_stream(self, calls):
337
 
        """In a list of calls, find 'get_record_stream' calls.
 
252
    def find_get_record_stream(self, calls, expected_count=1):
 
253
        """In a list of calls, find the last 'get_record_stream'.
338
254
 
339
 
        This also ensures that there is only one get_record_stream call.
 
255
        :param expected_count: The number of calls we should exepect to find.
 
256
            If a different number is found, an assertion is raised.
340
257
        """
341
258
        get_record_call = None
 
259
        call_count = 0
342
260
        for call in calls:
343
261
            if call[0] == 'get_record_stream':
344
 
                self.assertIs(None, get_record_call,
345
 
                              "there should only be one call to"
346
 
                              " get_record_stream")
 
262
                call_count += 1
347
263
                get_record_call = call
348
 
        self.assertIsNot(None, get_record_call,
349
 
                         "there should be exactly one call to "
350
 
                         " get_record_stream")
 
264
        self.assertEqual(expected_count, call_count)
351
265
        return get_record_call
352
266
 
353
267
    def test_fetch_with_deltas_no_delta_closure(self):
367
281
        source.inventories = versionedfile.RecordingVersionedFilesDecorator(
368
282
                        source.inventories)
369
283
        # precondition
370
 
        self.assertTrue(target._fetch_uses_deltas)
 
284
        self.assertTrue(target._format._fetch_uses_deltas)
371
285
        target.fetch(source, revision_id='rev-one')
372
286
        self.assertEqual(('get_record_stream', [('file-id', 'rev-one')],
373
 
                          target._fetch_order, False),
 
287
                          target._format._fetch_order, False),
374
288
                         self.find_get_record_stream(source.texts.calls))
375
289
        self.assertEqual(('get_record_stream', [('rev-one',)],
376
 
                          target._fetch_order, False),
377
 
                         self.find_get_record_stream(source.inventories.calls))
 
290
          target._format._fetch_order, False),
 
291
          self.find_get_record_stream(source.inventories.calls, 2))
378
292
        self.assertEqual(('get_record_stream', [('rev-one',)],
379
 
                          target._fetch_order, False),
 
293
                          target._format._fetch_order, False),
380
294
                         self.find_get_record_stream(source.revisions.calls))
381
295
        # XXX: Signatures is special, and slightly broken. The
382
296
        # standard item_keys_introduced_by actually does a lookup for every
387
301
        # we care about.
388
302
        signature_calls = source.signatures.calls[-1:]
389
303
        self.assertEqual(('get_record_stream', [('rev-one',)],
390
 
                          target._fetch_order, False),
 
304
                          target._format._fetch_order, False),
391
305
                         self.find_get_record_stream(signature_calls))
392
306
 
393
307
    def test_fetch_no_deltas_with_delta_closure(self):
406
320
                        source.revisions)
407
321
        source.inventories = versionedfile.RecordingVersionedFilesDecorator(
408
322
                        source.inventories)
409
 
        target._fetch_uses_deltas = False
 
323
        # XXX: This won't work in general, but for the dirstate format it does.
 
324
        self.overrideAttr(target._format, '_fetch_uses_deltas', False)
410
325
        target.fetch(source, revision_id='rev-one')
411
326
        self.assertEqual(('get_record_stream', [('file-id', 'rev-one')],
412
 
                          target._fetch_order, True),
 
327
                          target._format._fetch_order, True),
413
328
                         self.find_get_record_stream(source.texts.calls))
414
329
        self.assertEqual(('get_record_stream', [('rev-one',)],
415
 
                          target._fetch_order, True),
416
 
                         self.find_get_record_stream(source.inventories.calls))
 
330
            target._format._fetch_order, True),
 
331
            self.find_get_record_stream(source.inventories.calls, 2))
417
332
        self.assertEqual(('get_record_stream', [('rev-one',)],
418
 
                          target._fetch_order, True),
 
333
                          target._format._fetch_order, True),
419
334
                         self.find_get_record_stream(source.revisions.calls))
420
335
        # XXX: Signatures is special, and slightly broken. The
421
336
        # standard item_keys_introduced_by actually does a lookup for every
426
341
        # we care about.
427
342
        signature_calls = source.signatures.calls[-1:]
428
343
        self.assertEqual(('get_record_stream', [('rev-one',)],
429
 
                          target._fetch_order, True),
 
344
                          target._format._fetch_order, True),
430
345
                         self.find_get_record_stream(signature_calls))
431
346
 
432
347
    def test_fetch_revisions_with_deltas_into_pack(self):
576
491
        self.repo.fetch(self.tree.branch.repository, 'second-id')
577
492
        root_id = self.tree.get_root_id()
578
493
        self.assertEqual(
579
 
            ((root_id, 'left-parent'), (root_id, 'ghost-parent'),
580
 
             (root_id, 'not-ghost-parent')),
 
494
            ((root_id, 'left-parent'), (root_id, 'not-ghost-parent')),
581
495
            self.get_parents(root_id, 'second-id'))
582
496
 
583
497
    def make_two_commits(self, change_root, fetch_twice):