~bzr-pqm/bzr/bzr.dev

5582.10.2 by Jelmer Vernooij
Move weave repository tests.
1
# Copyright (C) 2006-2010 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
"""Tests for weave repositories.
18
19
For interface tests see tests/per_repository/*.py.
20
21
"""
22
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
23
from __future__ import absolute_import
24
5582.10.56 by Jelmer Vernooij
move xml4 to weave plugin.
25
from cStringIO import StringIO
5582.10.2 by Jelmer Vernooij
Move weave repository tests.
26
from stat import S_ISDIR
27
import sys
28
29
from bzrlib.bzrdir import (
30
    BzrDirMetaFormat1,
31
    )
32
from bzrlib.errors import (
33
    IllegalPath,
34
    NoSuchFile,
35
    )
36
from bzrlib.repository import (
37
    InterRepository,
38
    Repository,
39
    )
5582.10.56 by Jelmer Vernooij
move xml4 to weave plugin.
40
from bzrlib.serializer import (
41
    format_registry as serializer_format_registry,
42
    )
5582.10.2 by Jelmer Vernooij
Move weave repository tests.
43
from bzrlib.tests import (
5582.10.56 by Jelmer Vernooij
move xml4 to weave plugin.
44
    TestCase,
5582.10.2 by Jelmer Vernooij
Move weave repository tests.
45
    TestCaseWithTransport,
46
    )
47
5582.10.56 by Jelmer Vernooij
move xml4 to weave plugin.
48
from bzrlib.plugins.weave_fmt import xml4
5582.10.2 by Jelmer Vernooij
Move weave repository tests.
49
from bzrlib.plugins.weave_fmt.bzrdir import (
50
    BzrDirFormat6,
51
    )
52
from bzrlib.plugins.weave_fmt.repository import (
53
    InterWeaveRepo,
54
    RepositoryFormat4,
55
    RepositoryFormat5,
56
    RepositoryFormat6,
57
    RepositoryFormat7,
58
    )
59
60
61
class TestFormat6(TestCaseWithTransport):
62
63
    def test_attribute__fetch_order(self):
64
        """Weaves need topological data insertion."""
65
        control = BzrDirFormat6().initialize(self.get_url())
66
        repo = RepositoryFormat6().initialize(control)
67
        self.assertEqual('topological', repo._format._fetch_order)
68
69
    def test_attribute__fetch_uses_deltas(self):
70
        """Weaves do not reuse deltas."""
71
        control = BzrDirFormat6().initialize(self.get_url())
72
        repo = RepositoryFormat6().initialize(control)
73
        self.assertEqual(False, repo._format._fetch_uses_deltas)
74
75
    def test_attribute__fetch_reconcile(self):
76
        """Weave repositories need a reconcile after fetch."""
77
        control = BzrDirFormat6().initialize(self.get_url())
78
        repo = RepositoryFormat6().initialize(control)
79
        self.assertEqual(True, repo._format._fetch_reconcile)
80
81
    def test_no_ancestry_weave(self):
82
        control = BzrDirFormat6().initialize(self.get_url())
83
        repo = RepositoryFormat6().initialize(control)
84
        # We no longer need to create the ancestry.weave file
85
        # since it is *never* used.
86
        self.assertRaises(NoSuchFile,
87
                          control.transport.get,
88
                          'ancestry.weave')
89
90
    def test_supports_external_lookups(self):
91
        control = BzrDirFormat6().initialize(self.get_url())
92
        repo = RepositoryFormat6().initialize(control)
93
        self.assertFalse(repo._format.supports_external_lookups)
94
95
96
97
98
class TestFormat7(TestCaseWithTransport):
99
100
    def test_attribute__fetch_order(self):
101
        """Weaves need topological data insertion."""
102
        control = BzrDirMetaFormat1().initialize(self.get_url())
103
        repo = RepositoryFormat7().initialize(control)
104
        self.assertEqual('topological', repo._format._fetch_order)
105
106
    def test_attribute__fetch_uses_deltas(self):
107
        """Weaves do not reuse deltas."""
108
        control = BzrDirMetaFormat1().initialize(self.get_url())
109
        repo = RepositoryFormat7().initialize(control)
110
        self.assertEqual(False, repo._format._fetch_uses_deltas)
111
112
    def test_attribute__fetch_reconcile(self):
113
        """Weave repositories need a reconcile after fetch."""
114
        control = BzrDirMetaFormat1().initialize(self.get_url())
115
        repo = RepositoryFormat7().initialize(control)
116
        self.assertEqual(True, repo._format._fetch_reconcile)
117
118
    def test_disk_layout(self):
119
        control = BzrDirMetaFormat1().initialize(self.get_url())
120
        repo = RepositoryFormat7().initialize(control)
121
        # in case of side effects of locking.
122
        repo.lock_write()
123
        repo.unlock()
124
        # we want:
125
        # format 'Bazaar-NG Repository format 7'
126
        # lock ''
127
        # inventory.weave == empty_weave
128
        # empty revision-store directory
129
        # empty weaves directory
130
        t = control.get_repository_transport(None)
131
        self.assertEqualDiff('Bazaar-NG Repository format 7',
132
                             t.get('format').read())
133
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
134
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
135
        self.assertEqualDiff('# bzr weave file v5\n'
136
                             'w\n'
137
                             'W\n',
138
                             t.get('inventory.weave').read())
139
        # Creating a file with id Foo:Bar results in a non-escaped file name on
140
        # disk.
141
        control.create_branch()
142
        tree = control.create_workingtree()
143
        tree.add(['foo'], ['Foo:Bar'], ['file'])
144
        tree.put_file_bytes_non_atomic('Foo:Bar', 'content\n')
145
        try:
146
            tree.commit('first post', rev_id='first')
147
        except IllegalPath:
148
            if sys.platform != 'win32':
149
                raise
150
            self.knownFailure('Foo:Bar cannot be used as a file-id on windows'
151
                              ' in repo format 7')
152
            return
153
        self.assertEqualDiff(
154
            '# bzr weave file v5\n'
155
            'i\n'
156
            '1 7fe70820e08a1aac0ef224d9c66ab66831cc4ab1\n'
157
            'n first\n'
158
            '\n'
159
            'w\n'
160
            '{ 0\n'
161
            '. content\n'
162
            '}\n'
163
            'W\n',
164
            t.get('weaves/74/Foo%3ABar.weave').read())
165
166
    def test_shared_disk_layout(self):
167
        control = BzrDirMetaFormat1().initialize(self.get_url())
168
        repo = RepositoryFormat7().initialize(control, shared=True)
169
        # we want:
170
        # format 'Bazaar-NG Repository format 7'
171
        # inventory.weave == empty_weave
172
        # empty revision-store directory
173
        # empty weaves directory
174
        # a 'shared-storage' marker file.
175
        # lock is not present when unlocked
176
        t = control.get_repository_transport(None)
177
        self.assertEqualDiff('Bazaar-NG Repository format 7',
178
                             t.get('format').read())
179
        self.assertEqualDiff('', t.get('shared-storage').read())
180
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
181
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
182
        self.assertEqualDiff('# bzr weave file v5\n'
183
                             'w\n'
184
                             'W\n',
185
                             t.get('inventory.weave').read())
186
        self.assertFalse(t.has('branch-lock'))
187
188
    def test_creates_lockdir(self):
189
        """Make sure it appears to be controlled by a LockDir existence"""
190
        control = BzrDirMetaFormat1().initialize(self.get_url())
191
        repo = RepositoryFormat7().initialize(control, shared=True)
192
        t = control.get_repository_transport(None)
193
        # TODO: Should check there is a 'lock' toplevel directory,
194
        # regardless of contents
195
        self.assertFalse(t.has('lock/held/info'))
196
        repo.lock_write()
197
        try:
198
            self.assertTrue(t.has('lock/held/info'))
199
        finally:
200
            # unlock so we don't get a warning about failing to do so
201
            repo.unlock()
202
203
    def test_uses_lockdir(self):
204
        """repo format 7 actually locks on lockdir"""
205
        base_url = self.get_url()
206
        control = BzrDirMetaFormat1().initialize(base_url)
207
        repo = RepositoryFormat7().initialize(control, shared=True)
208
        t = control.get_repository_transport(None)
209
        repo.lock_write()
210
        repo.unlock()
211
        del repo
212
        # make sure the same lock is created by opening it
213
        repo = Repository.open(base_url)
214
        repo.lock_write()
215
        self.assertTrue(t.has('lock/held/info'))
216
        repo.unlock()
217
        self.assertFalse(t.has('lock/held/info'))
218
219
    def test_shared_no_tree_disk_layout(self):
220
        control = BzrDirMetaFormat1().initialize(self.get_url())
221
        repo = RepositoryFormat7().initialize(control, shared=True)
222
        repo.set_make_working_trees(False)
223
        # we want:
224
        # format 'Bazaar-NG Repository format 7'
225
        # lock ''
226
        # inventory.weave == empty_weave
227
        # empty revision-store directory
228
        # empty weaves directory
229
        # a 'shared-storage' marker file.
230
        t = control.get_repository_transport(None)
231
        self.assertEqualDiff('Bazaar-NG Repository format 7',
232
                             t.get('format').read())
233
        ## self.assertEqualDiff('', t.get('lock').read())
234
        self.assertEqualDiff('', t.get('shared-storage').read())
235
        self.assertEqualDiff('', t.get('no-working-trees').read())
236
        repo.set_make_working_trees(True)
237
        self.assertFalse(t.has('no-working-trees'))
238
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
239
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
240
        self.assertEqualDiff('# bzr weave file v5\n'
241
                             'w\n'
242
                             'W\n',
243
                             t.get('inventory.weave').read())
244
245
    def test_supports_external_lookups(self):
246
        control = BzrDirMetaFormat1().initialize(self.get_url())
247
        repo = RepositoryFormat7().initialize(control)
248
        self.assertFalse(repo._format.supports_external_lookups)
249
250
251
class TestInterWeaveRepo(TestCaseWithTransport):
252
253
    def test_is_compatible_and_registered(self):
254
        # InterWeaveRepo is compatible when either side
255
        # is a format 5/6/7 branch
256
        from bzrlib.repofmt import knitrepo
257
        formats = [RepositoryFormat5(),
258
                   RepositoryFormat6(),
259
                   RepositoryFormat7()]
260
        incompatible_formats = [RepositoryFormat4(),
261
                                knitrepo.RepositoryFormatKnit1(),
262
                                ]
263
        repo_a = self.make_repository('a')
264
        repo_b = self.make_repository('b')
265
        is_compatible = InterWeaveRepo.is_compatible
266
        for source in incompatible_formats:
267
            # force incompatible left then right
268
            repo_a._format = source
269
            repo_b._format = formats[0]
270
            self.assertFalse(is_compatible(repo_a, repo_b))
271
            self.assertFalse(is_compatible(repo_b, repo_a))
272
        for source in formats:
273
            repo_a._format = source
274
            for target in formats:
275
                repo_b._format = target
276
                self.assertTrue(is_compatible(repo_a, repo_b))
277
        self.assertEqual(InterWeaveRepo,
278
                         InterRepository.get(repo_a, repo_b).__class__)
5582.10.56 by Jelmer Vernooij
move xml4 to weave plugin.
279
280
281
_working_inventory_v4 = """<inventory file_id="TREE_ROOT">
282
<entry file_id="bar-20050901064931-73b4b1138abc9cd2" kind="file" name="bar" parent_id="TREE_ROOT" />
283
<entry file_id="foo-20050801201819-4139aa4a272f4250" kind="directory" name="foo" parent_id="TREE_ROOT" />
284
<entry file_id="bar-20050824000535-6bc48cfad47ed134" kind="file" name="bar" parent_id="foo-20050801201819-4139aa4a272f4250" />
285
</inventory>"""
286
287
288
_revision_v4 = """<revision committer="Martin Pool &lt;mbp@sourcefrog.net&gt;"
289
    inventory_id="mbp@sourcefrog.net-20050905080035-e0439293f8b6b9f9"
290
    inventory_sha1="e79c31c1deb64c163cf660fdedd476dd579ffd41"
291
    revision_id="mbp@sourcefrog.net-20050905080035-e0439293f8b6b9f9"
292
    timestamp="1125907235.212"
293
    timezone="36000">
294
<message>- start splitting code for xml (de)serialization away from objects
295
  preparatory to supporting multiple formats by a single library
296
</message>
297
<parents>
298
<revision_ref revision_id="mbp@sourcefrog.net-20050905063503-43948f59fa127d92" revision_sha1="7bdf4cc8c5bdac739f8cf9b10b78cf4b68f915ff" />
299
</parents>
300
</revision>
301
"""
302
303
304
class TestSerializer(TestCase):
305
    """Test serializer"""
306
307
    def test_registry(self):
308
        self.assertIs(xml4.serializer_v4,
309
                      serializer_format_registry.get('4'))
310
311
    def test_canned_inventory(self):
312
        """Test unpacked a canned inventory v4 file."""
313
        inp = StringIO(_working_inventory_v4)
314
        inv = xml4.serializer_v4.read_inventory(inp)
315
        self.assertEqual(len(inv), 4)
5967.7.3 by Martin Pool
Fix up additional callers that count on inventory.__contains__
316
        self.assert_(inv.has_id('bar-20050901064931-73b4b1138abc9cd2'))
5582.10.56 by Jelmer Vernooij
move xml4 to weave plugin.
317
318
    def test_unpack_revision(self):
319
        """Test unpacking a canned revision v4"""
320
        inp = StringIO(_revision_v4)
321
        rev = xml4.serializer_v4.read_revision(inp)
322
        eq = self.assertEqual
323
        eq(rev.committer,
324
           "Martin Pool <mbp@sourcefrog.net>")
325
        eq(rev.inventory_id,
326
           "mbp@sourcefrog.net-20050905080035-e0439293f8b6b9f9")
327
        eq(len(rev.parent_ids), 1)
328
        eq(rev.parent_ids[0],
329
           "mbp@sourcefrog.net-20050905063503-43948f59fa127d92")
330
331