/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_fetch.py

  • Committer: v.ladeuil+lp at free
  • Date: 2006-10-12 14:29:32 UTC
  • mto: (2145.1.1 keepalive)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: v.ladeuil+lp@free.fr-20061012142932-7221fe16d2b48fa3
Shuffle http related test code. Hopefully it ends up at the right place :)

* bzrlib/tests/HttpServer.py: 
New file. bzrlib.tests.ChrootedTestCase use HttpServer. So the
class can't be defined in bzrlib.tests.HTTPUtils because it
creates a circular dependency (bzrlib.tests.HTTPUtils needs to
import bzrlib.tests).

* bzrlib/transport/http/_urllib.py: 
Transfer test server definition to bzrlib.tests.HttpServer. Clean
up imports.

* bzrlib/transport/http/_pycurl.py: 
Transfer test server definition to bzrlib.tests.HttpServer. Clean
up imports.

* bzrlib/transport/http/__init__.py: 
Transfer all test related code to either bzrlib.tests.HttpServer
and bzrlib.tests.HTTPUtils.
Fix all use of TransportNotPossible and InvalidURL by prefixing it
by 'errors.' (this seems to be the preferred way in the rest of
bzr).
Get rid of unused imports.

* bzrlib/tests/test_transport.py:
(ReadonlyDecoratorTransportTest.test_local_parameters,
FakeNFSDecoratorTests.test_http_parameters): Use HttpServer from
bzrlib.tests.HttpServer instead of bzrlib.transport.http.

* bzrlib/tests/test_sftp_transport.py:
(set_test_transport_to_sftp): Use HttpServer from
bzrlib.tests.HttpServer instead of bzrlib.transport.http.

* bzrlib/tests/test_selftest.py:
(TestTestCaseWithTransport.test_get_readonly_url_http): Use
HttpServer from bzrlib.tests.HttpServer instead of
bzrlib.transport.http.

* bzrlib/tests/test_repository.py: 
Does *not* use HttpServer.

* bzrlib/tests/test_http.py: 
Build on top of bzrlib.tests.HttpServer and bzrlib.tests.HTTPUtils
instead of bzrlib.transport.http.

* bzrlib/tests/test_bzrdir.py:
(ChrootedTests.setUp): Use HttpServer from bzrlib.tests.HttpServer
instead of bzrlib.transport.http.

* bzrlib/tests/branch_implementations/test_http.py:
(HTTPBranchTests.setUp): Use HttpServer from bzrlib.tests.HttpServer
instead of bzrlib.transport.http.

* bzrlib/tests/branch_implementations/test_branch.py:
(ChrootedTests.setUp): Use HttpServer from bzrlib.tests.HttpServer
instead of bzrlib.transport.http.

* bzrlib/tests/__init__.py:
(ChrootedTestCase.setUp): Use HttpServer from
bzrlib.tests.HttpServer instead of bzrlib.transport.http.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 by 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
import os
 
18
import re
 
19
import sys
 
20
 
 
21
from bzrlib.branch import Branch
 
22
from bzrlib.bzrdir import BzrDir
 
23
from bzrlib.builtins import merge
 
24
import bzrlib.errors
 
25
from bzrlib.tests import TestCaseWithTransport
 
26
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
 
27
from bzrlib.tests.test_revision import make_branches
 
28
from bzrlib.trace import mutter
 
29
from bzrlib.workingtree import WorkingTree
 
30
 
 
31
 
 
32
def has_revision(branch, revision_id):
 
33
    return branch.repository.has_revision(revision_id)
 
34
 
 
35
def fetch_steps(self, br_a, br_b, writable_a):
 
36
    """A foreign test method for testing fetch locally and remotely."""
 
37
     
 
38
    # TODO RBC 20060201 make this a repository test.
 
39
    repo_b = br_b.repository
 
40
    self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
 
41
    self.assertTrue(repo_b.has_revision(br_a.revision_history()[2]))
 
42
    self.assertEquals(len(br_b.revision_history()), 7)
 
43
    self.assertEquals(br_b.fetch(br_a, br_a.revision_history()[2])[0], 0)
 
44
    # branch.fetch is not supposed to alter the revision history
 
45
    self.assertEquals(len(br_b.revision_history()), 7)
 
46
    self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
 
47
 
 
48
    # fetching the next revision up in sample data copies one revision
 
49
    self.assertEquals(br_b.fetch(br_a, br_a.revision_history()[3])[0], 1)
 
50
    self.assertTrue(repo_b.has_revision(br_a.revision_history()[3]))
 
51
    self.assertFalse(has_revision(br_a, br_b.revision_history()[6]))
 
52
    self.assertTrue(br_a.repository.has_revision(br_b.revision_history()[5]))
 
53
 
 
54
    # When a non-branch ancestor is missing, it should be unlisted...
 
55
    # as its not reference from the inventory weave.
 
56
    br_b4 = self.make_branch('br_4')
 
57
    count, failures = br_b4.fetch(br_b)
 
58
    self.assertEqual(count, 7)
 
59
    self.assertEqual(failures, [])
 
60
 
 
61
    self.assertEqual(writable_a.fetch(br_b)[0], 1)
 
62
    self.assertTrue(has_revision(br_a, br_b.revision_history()[3]))
 
63
    self.assertTrue(has_revision(br_a, br_b.revision_history()[4]))
 
64
        
 
65
    br_b2 = self.make_branch('br_b2')
 
66
    self.assertEquals(br_b2.fetch(br_b)[0], 7)
 
67
    self.assertTrue(has_revision(br_b2, br_b.revision_history()[4]))
 
68
    self.assertTrue(has_revision(br_b2, br_a.revision_history()[2]))
 
69
    self.assertFalse(has_revision(br_b2, br_a.revision_history()[3]))
 
70
 
 
71
    br_a2 = self.make_branch('br_a2')
 
72
    self.assertEquals(br_a2.fetch(br_a)[0], 9)
 
73
    self.assertTrue(has_revision(br_a2, br_b.revision_history()[4]))
 
74
    self.assertTrue(has_revision(br_a2, br_a.revision_history()[3]))
 
75
    self.assertTrue(has_revision(br_a2, br_a.revision_history()[2]))
 
76
 
 
77
    br_a3 = self.make_branch('br_a3')
 
78
    # pulling a branch with no revisions grabs nothing, regardless of 
 
79
    # whats in the inventory.
 
80
    self.assertEquals(br_a3.fetch(br_a2)[0], 0)
 
81
    for revno in range(4):
 
82
        self.assertFalse(
 
83
            br_a3.repository.has_revision(br_a.revision_history()[revno]))
 
84
    self.assertEqual(br_a3.fetch(br_a2, br_a.revision_history()[2])[0], 3)
 
85
    # pull the 3 revisions introduced by a@u-0-3
 
86
    fetched = br_a3.fetch(br_a2, br_a.revision_history()[3])[0]
 
87
    self.assertEquals(fetched, 3, "fetched %d instead of 3" % fetched)
 
88
    # InstallFailed should be raised if the branch is missing the revision
 
89
    # that was requested.
 
90
    self.assertRaises(bzrlib.errors.InstallFailed, br_a3.fetch, br_a2, 'pizza')
 
91
    # InstallFailed should be raised if the branch is missing a revision
 
92
    # from its own revision history
 
93
    br_a2.append_revision('a-b-c')
 
94
    self.assertRaises(bzrlib.errors.InstallFailed, br_a3.fetch, br_a2)
 
95
 
 
96
    # TODO: jam 20051218 Branch should no longer allow append_revision for revisions
 
97
    #       which don't exist. So this test needs to be rewritten
 
98
    #       RBC 20060403 the way to do this is to uncommit the revision from the
 
99
    #           repository after the commit
 
100
 
 
101
    #TODO: test that fetch correctly does reweaving when needed. RBC 20051008
 
102
    # Note that this means - updating the weave when ghosts are filled in to 
 
103
    # add the right parents.
 
104
 
 
105
 
 
106
class TestFetch(TestCaseWithTransport):
 
107
 
 
108
    def test_fetch(self):
 
109
        #highest indices a: 5, b: 7
 
110
        br_a, br_b = make_branches(self)
 
111
        fetch_steps(self, br_a, br_b, br_a)
 
112
 
 
113
    def test_fetch_self(self):
 
114
        wt = self.make_branch_and_tree('br')
 
115
        self.assertEqual(wt.branch.fetch(wt.branch), (0, []))
 
116
 
 
117
 
 
118
class TestMergeFetch(TestCaseWithTransport):
 
119
 
 
120
    def test_merge_fetches_unrelated(self):
 
121
        """Merge brings across history from unrelated source"""
 
122
        wt1 = self.make_branch_and_tree('br1')
 
123
        br1 = wt1.branch
 
124
        wt1.commit(message='rev 1-1', rev_id='1-1')
 
125
        wt1.commit(message='rev 1-2', rev_id='1-2')
 
126
        wt2 = self.make_branch_and_tree('br2')
 
127
        br2 = wt2.branch
 
128
        wt2.commit(message='rev 2-1', rev_id='2-1')
 
129
        merge(other_revision=['br1', -1], base_revision=['br1', 0],
 
130
              this_dir='br2')
 
131
        self._check_revs_present(br2)
 
132
 
 
133
    def test_merge_fetches(self):
 
134
        """Merge brings across history from source"""
 
135
        wt1 = self.make_branch_and_tree('br1')
 
136
        br1 = wt1.branch
 
137
        wt1.commit(message='rev 1-1', rev_id='1-1')
 
138
        dir_2 = br1.bzrdir.sprout('br2')
 
139
        br2 = dir_2.open_branch()
 
140
        wt1.commit(message='rev 1-2', rev_id='1-2')
 
141
        dir_2.open_workingtree().commit(message='rev 2-1', rev_id='2-1')
 
142
        merge(other_revision=['br1', -1], base_revision=[None, None], 
 
143
              this_dir='br2')
 
144
        self._check_revs_present(br2)
 
145
 
 
146
    def _check_revs_present(self, br2):
 
147
        for rev_id in '1-1', '1-2', '2-1':
 
148
            self.assertTrue(br2.repository.has_revision(rev_id))
 
149
            rev = br2.repository.get_revision(rev_id)
 
150
            self.assertEqual(rev.revision_id, rev_id)
 
151
            self.assertTrue(br2.repository.get_inventory(rev_id))
 
152
 
 
153
 
 
154
class TestMergeFileHistory(TestCaseWithTransport):
 
155
 
 
156
    def setUp(self):
 
157
        super(TestMergeFileHistory, self).setUp()
 
158
        wt1 = self.make_branch_and_tree('br1')
 
159
        br1 = wt1.branch
 
160
        self.build_tree_contents([('br1/file', 'original contents\n')])
 
161
        wt1.add('file', 'this-file-id')
 
162
        wt1.commit(message='rev 1-1', rev_id='1-1')
 
163
        dir_2 = br1.bzrdir.sprout('br2')
 
164
        br2 = dir_2.open_branch()
 
165
        wt2 = dir_2.open_workingtree()
 
166
        self.build_tree_contents([('br1/file', 'original from 1\n')])
 
167
        wt1.commit(message='rev 1-2', rev_id='1-2')
 
168
        self.build_tree_contents([('br1/file', 'agreement\n')])
 
169
        wt1.commit(message='rev 1-3', rev_id='1-3')
 
170
        self.build_tree_contents([('br2/file', 'contents in 2\n')])
 
171
        wt2.commit(message='rev 2-1', rev_id='2-1')
 
172
        self.build_tree_contents([('br2/file', 'agreement\n')])
 
173
        wt2.commit(message='rev 2-2', rev_id='2-2')
 
174
 
 
175
    def test_merge_fetches_file_history(self):
 
176
        """Merge brings across file histories"""
 
177
        br2 = Branch.open('br2')
 
178
        merge(other_revision=['br1', -1], base_revision=[None, None], 
 
179
              this_dir='br2')
 
180
        for rev_id, text in [('1-2', 'original from 1\n'),
 
181
                             ('1-3', 'agreement\n'),
 
182
                             ('2-1', 'contents in 2\n'),
 
183
                             ('2-2', 'agreement\n')]:
 
184
            self.assertEqualDiff(
 
185
                br2.repository.revision_tree(
 
186
                    rev_id).get_file_text('this-file-id'), text)
 
187
 
 
188
 
 
189
class TestHttpFetch(TestCaseWithWebserver):
 
190
    # FIXME RBC 20060124 this really isn't web specific, perhaps an
 
191
    # instrumented readonly transport? Can we do an instrumented
 
192
    # adapter and use self.get_readonly_url ?
 
193
 
 
194
    def test_fetch(self):
 
195
        #highest indices a: 5, b: 7
 
196
        br_a, br_b = make_branches(self)
 
197
        br_rem_a = Branch.open(self.get_readonly_url('branch1'))
 
198
        fetch_steps(self, br_rem_a, br_b, br_a)
 
199
 
 
200
    def _count_log_matches(self, target, logs):
 
201
        """Count the number of times the target file pattern was fetched in an http log"""
 
202
        get_succeeds_re = re.compile(
 
203
            '.*"GET .*%s HTTP/1.1" 20[06] - "-" "bzr/%s' %
 
204
            (     target,                    bzrlib.__version__))
 
205
        c = 0
 
206
        for line in logs:
 
207
            if get_succeeds_re.match(line):
 
208
                c += 1
 
209
        return c
 
210
 
 
211
    def test_weaves_are_retrieved_once(self):
 
212
        self.build_tree(("source/", "source/file", "target/"))
 
213
        wt = self.make_branch_and_tree('source')
 
214
        branch = wt.branch
 
215
        wt.add(["file"], ["id"])
 
216
        wt.commit("added file")
 
217
        print >>open("source/file", 'w'), "blah"
 
218
        wt.commit("changed file")
 
219
        target = BzrDir.create_branch_and_repo("target/")
 
220
        source = Branch.open(self.get_readonly_url("source/"))
 
221
        self.assertEqual(target.fetch(source), (2, []))
 
222
        # this is the path to the literal file. As format changes 
 
223
        # occur it needs to be updated. FIXME: ask the store for the
 
224
        # path.
 
225
        self.log("web server logs are:")
 
226
        http_logs = self.get_readonly_server().logs
 
227
        self.log('\n'.join(http_logs))
 
228
        # unfortunately this log entry is branch format specific. We could 
 
229
        # factor out the 'what files does this format use' to a method on the 
 
230
        # repository, which would let us to this generically. RBC 20060419
 
231
        self.assertEqual(1, self._count_log_matches('/ce/id.kndx', http_logs))
 
232
        self.assertEqual(1, self._count_log_matches('/ce/id.knit', http_logs))
 
233
        self.assertEqual(1, self._count_log_matches('inventory.kndx', http_logs))
 
234
        # this r-h check test will prevent regressions, but it currently already 
 
235
        # passes, before the patch to cache-rh is applied :[
 
236
        self.assertEqual(1, self._count_log_matches('revision-history', http_logs))
 
237
        # FIXME naughty poking in there.
 
238
        self.get_readonly_server().logs = []
 
239
        # check there is nothing more to fetch
 
240
        source = Branch.open(self.get_readonly_url("source/"))
 
241
        self.assertEqual(target.fetch(source), (0, []))
 
242
        # should make just two requests
 
243
        http_logs = self.get_readonly_server().logs
 
244
        self.log("web server logs are:")
 
245
        self.log('\n'.join(http_logs))
 
246
        self.assertEqual(1, self._count_log_matches('branch-format', http_logs))
 
247
        self.assertEqual(1, self._count_log_matches('branch/format', http_logs))
 
248
        self.assertEqual(1, self._count_log_matches('repository/format', http_logs))
 
249
        self.assertEqual(1, self._count_log_matches('revision-history', http_logs))
 
250
        self.assertEqual(4, len(http_logs))