~bzr-pqm/bzr/bzr.dev

2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
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
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
16
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
17
from cStringIO import StringIO
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
18
import os
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
19
import socket
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
20
import sys
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
21
import threading
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
22
1910.2.64 by Aaron Bentley
Changes from review
23
from bzrlib import (
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
24
    bzrdir,
25
    errors,
26
    inventory,
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
27
    osutils,
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
28
    repository,
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
29
    revision as _mod_revision,
1910.2.64 by Aaron Bentley
Changes from review
30
    treebuilder,
31
    )
3251.4.11 by Aaron Bentley
Fix wrong local lookups
32
from bzrlib.bundle import read_mergeable_from_url
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
33
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
1793.2.3 by Aaron Bentley
Rename read_bundle.py to bundle_data.py
34
from bzrlib.bundle.bundle_data import BundleTree
3750.1.3 by Vincent Ladeuil
Cleanups.
35
from bzrlib.bzrdir import BzrDir
3251.4.11 by Aaron Bentley
Fix wrong local lookups
36
from bzrlib.directory_service import directories
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
37
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
38
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
39
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
2520.4.72 by Aaron Bentley
Rename format to 4alpha
40
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
41
from bzrlib.branch import Branch
1185.82.90 by Aaron Bentley
Reorganized test suite
42
from bzrlib.diff import internal_diff
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
43
from bzrlib.merge import Merge3Merger
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
44
from bzrlib.repofmt import knitrepo
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
45
from bzrlib.osutils import sha_file, sha_string
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
46
from bzrlib.tests import (
47
    SymlinkFeature,
48
    TestCase,
49
    TestCaseInTempDir,
50
    TestCaseWithTransport,
51
    TestSkipped,
3251.4.11 by Aaron Bentley
Fix wrong local lookups
52
    test_read_bundle,
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
53
    test_commit,
54
    )
1185.82.66 by Aaron Bentley
Handle new executable files
55
from bzrlib.transform import TreeTransform
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
56
1185.82.90 by Aaron Bentley
Reorganized test suite
57
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
58
class MockTree(object):
59
    def __init__(self):
1731.1.4 by Aaron Bentley
merge from bzr.dev
60
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
61
        object.__init__(self)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
62
        self.paths = {ROOT_ID: ""}
63
        self.ids = {"": ROOT_ID}
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
64
        self.contents = {}
1731.1.4 by Aaron Bentley
merge from bzr.dev
65
        self.root = InventoryDirectory(ROOT_ID, '', None)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
66
67
    inventory = property(lambda x:x)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
68
69
    def __iter__(self):
70
        return self.paths.iterkeys()
71
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
72
    def __getitem__(self, file_id):
73
        if file_id == self.root.file_id:
74
            return self.root
75
        else:
76
            return self.make_entry(file_id, self.paths[file_id])
77
78
    def parent_id(self, file_id):
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
79
        parent_dir = os.path.dirname(self.paths[file_id])
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
80
        if parent_dir == "":
81
            return None
82
        return self.ids[parent_dir]
83
84
    def iter_entries(self):
85
        for path, file_id in self.ids.iteritems():
86
            yield path, self[file_id]
87
88
    def get_file_kind(self, file_id):
89
        if file_id in self.contents:
90
            kind = 'file'
91
        else:
92
            kind = 'directory'
93
        return kind
94
95
    def make_entry(self, file_id, path):
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
96
        from bzrlib.inventory import (InventoryEntry, InventoryFile
97
                                    , InventoryDirectory, InventoryLink)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
98
        name = os.path.basename(path)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
99
        kind = self.get_file_kind(file_id)
100
        parent_id = self.parent_id(file_id)
101
        text_sha_1, text_size = self.contents_stats(file_id)
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
102
        if kind == 'directory':
103
            ie = InventoryDirectory(file_id, name, parent_id)
104
        elif kind == 'file':
105
            ie = InventoryFile(file_id, name, parent_id)
106
        elif kind == 'symlink':
107
            ie = InventoryLink(file_id, name, parent_id)
108
        else:
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
109
            raise errors.BzrError('unknown kind %r' % kind)
0.5.91 by Aaron Bentley
Updated to match API change
110
        ie.text_sha1 = text_sha_1
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
111
        ie.text_size = text_size
112
        return ie
113
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
114
    def add_dir(self, file_id, path):
115
        self.paths[file_id] = path
116
        self.ids[path] = file_id
117
    
118
    def add_file(self, file_id, path, contents):
119
        self.add_dir(file_id, path)
120
        self.contents[file_id] = contents
121
122
    def path2id(self, path):
123
        return self.ids.get(path)
124
125
    def id2path(self, file_id):
126
        return self.paths.get(file_id)
127
128
    def has_id(self, file_id):
129
        return self.id2path(file_id) is not None
130
131
    def get_file(self, file_id):
132
        result = StringIO()
133
        result.write(self.contents[file_id])
134
        result.seek(0,0)
135
        return result
136
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
137
    def contents_stats(self, file_id):
138
        if file_id not in self.contents:
139
            return None, None
140
        text_sha1 = sha_file(self.get_file(file_id))
141
        return text_sha1, len(self.contents[file_id])
142
143
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
144
class BTreeTester(TestCase):
145
    """A simple unittest tester for the BundleTree class."""
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
146
147
    def make_tree_1(self):
148
        mtree = MockTree()
149
        mtree.add_dir("a", "grandparent")
150
        mtree.add_dir("b", "grandparent/parent")
151
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
152
        mtree.add_dir("d", "grandparent/alt_parent")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
153
        return BundleTree(mtree, ''), mtree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
154
        
155
    def test_renames(self):
156
        """Ensure that file renames have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
157
        btree = self.make_tree_1()[0]
158
        self.assertEqual(btree.old_path("grandparent"), "grandparent")
159
        self.assertEqual(btree.old_path("grandparent/parent"), 
160
                         "grandparent/parent")
161
        self.assertEqual(btree.old_path("grandparent/parent/file"),
162
                         "grandparent/parent/file")
163
164
        self.assertEqual(btree.id2path("a"), "grandparent")
165
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
166
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
167
168
        self.assertEqual(btree.path2id("grandparent"), "a")
169
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
170
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
171
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
172
        self.assertTrue(btree.path2id("grandparent2") is None)
173
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
174
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
175
176
        btree.note_rename("grandparent", "grandparent2")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
177
        self.assertTrue(btree.old_path("grandparent") is None)
178
        self.assertTrue(btree.old_path("grandparent/parent") is None)
179
        self.assertTrue(btree.old_path("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
180
181
        self.assertEqual(btree.id2path("a"), "grandparent2")
182
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
183
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
184
185
        self.assertEqual(btree.path2id("grandparent2"), "a")
186
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
187
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
188
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
189
        self.assertTrue(btree.path2id("grandparent") is None)
190
        self.assertTrue(btree.path2id("grandparent/parent") is None)
191
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
192
193
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
194
        self.assertEqual(btree.id2path("a"), "grandparent2")
195
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
196
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
197
198
        self.assertEqual(btree.path2id("grandparent2"), "a")
199
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
200
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
201
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
202
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
203
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
204
205
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
206
                          "grandparent2/parent2/file2")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
207
        self.assertEqual(btree.id2path("a"), "grandparent2")
208
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
209
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
210
211
        self.assertEqual(btree.path2id("grandparent2"), "a")
212
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
213
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
214
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
215
        self.assertTrue(btree.path2id("grandparent2/parent2/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
216
217
    def test_moves(self):
218
        """Ensure that file moves have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
219
        btree = self.make_tree_1()[0]
220
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
221
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
222
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
223
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
224
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
225
226
    def unified_diff(self, old, new):
227
        out = StringIO()
228
        internal_diff("old", old, "new", new, out)
229
        out.seek(0,0)
230
        return out.read()
231
232
    def make_tree_2(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
233
        btree = self.make_tree_1()[0]
234
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
235
                          "grandparent/alt_parent/file")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
236
        self.assertTrue(btree.id2path("e") is None)
237
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
238
        btree.note_id("e", "grandparent/parent/file")
239
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
240
241
    def test_adds(self):
242
        """File/inventory adds"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
243
        btree = self.make_tree_2()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
244
        add_patch = self.unified_diff([], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
245
        btree.note_patch("grandparent/parent/file", add_patch)
246
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
247
        btree.note_target('grandparent/parent/symlink', 'venus')
248
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
249
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
250
    def adds_test(self, btree):
251
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
252
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
253
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
254
        self.assertEqual(btree.get_symlink_target('f'), 'venus')
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
255
256
    def test_adds2(self):
257
        """File/inventory adds, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
258
        btree = self.make_tree_2()
259
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
260
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
261
        btree.note_patch("grandparent/parent/file", add_patch)
262
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
263
        btree.note_target('grandparent/parent/symlink', 'venus')
264
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
265
266
    def make_tree_3(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
267
        btree, mtree = self.make_tree_1()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
268
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
269
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
270
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
271
        btree.note_rename("grandparent/parent/topping", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
272
                          "grandparent/alt_parent/stopping")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
273
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
274
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
275
    def get_file_test(self, btree):
276
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
277
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
278
279
    def test_get_file(self):
280
        """Get file contents"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
281
        btree = self.make_tree_3()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
282
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
283
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
284
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
285
286
    def test_get_file2(self):
287
        """Get file contents, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
288
        btree = self.make_tree_3()
289
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
290
        mod_patch = self.unified_diff([], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
291
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
292
        mod_patch = self.unified_diff([], ["Hello\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
293
        btree.note_patch("grandparent/alt_parent/file", mod_patch)
294
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
295
296
    def test_delete(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
297
        "Deletion by bundle"
298
        btree = self.make_tree_1()[0]
299
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
300
        btree.note_deletion("grandparent/parent/file")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
301
        self.assertTrue(btree.id2path("c") is None)
302
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
303
304
    def sorted_ids(self, tree):
305
        ids = list(tree)
306
        ids.sort()
307
        return ids
308
309
    def test_iteration(self):
310
        """Ensure that iteration through ids works properly"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
311
        btree = self.make_tree_1()[0]
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
312
        self.assertEqual(self.sorted_ids(btree),
313
            [inventory.ROOT_ID, 'a', 'b', 'c', 'd'])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
314
        btree.note_deletion("grandparent/parent/file")
315
        btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
316
        btree.note_last_changed("grandparent/alt_parent/fool", 
1185.82.95 by Aaron Bentley
Restore path-orientation of ChangesetTree
317
                                "revisionidiguess")
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
318
        self.assertEqual(self.sorted_ids(btree),
319
            [inventory.ROOT_ID, 'a', 'b', 'd', 'e'])
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
320
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
321
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
322
class BundleTester1(TestCaseWithTransport):
323
324
    def test_mismatched_bundle(self):
325
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
326
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
327
        serializer = BundleSerializerV08('0.8')
328
        b = self.make_branch('.', format=format)
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
329
        self.assertRaises(errors.IncompatibleBundleFormat, serializer.write, 
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
330
                          b.repository, [], {}, StringIO())
331
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
332
    def test_matched_bundle(self):
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
333
        """Don't raise IncompatibleBundleFormat for knit2 and bundle0.9"""
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
334
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
335
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
336
        serializer = BundleSerializerV09('0.9')
337
        b = self.make_branch('.', format=format)
338
        serializer.write(b.repository, [], {}, StringIO())
339
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
340
    def test_mismatched_model(self):
341
        """Try copying a bundle from knit2 to knit1"""
342
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
343
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
344
        source = self.make_branch_and_tree('source', format=format)
345
        source.commit('one', rev_id='one-id')
346
        source.commit('two', rev_id='two-id')
347
        text = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
348
        write_bundle(source.branch.repository, 'two-id', 'null:', text,
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
349
                     format='0.9')
350
        text.seek(0)
351
352
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
353
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
354
        target = self.make_branch('target', format=format)
355
        self.assertRaises(errors.IncompatibleRevision, install_bundle, 
356
                          target.repository, read_bundle(text))
357
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
358
2520.4.43 by Aaron Bentley
Fix test suite
359
class BundleTester(object):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
360
361
    def bzrdir_format(self):
362
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
363
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
364
        return format
365
366
    def make_branch_and_tree(self, path, format=None):
367
        if format is None:
368
            format = self.bzrdir_format()
369
        return TestCaseWithTransport.make_branch_and_tree(self, path, format)
370
371
    def make_branch(self, path, format=None):
372
        if format is None:
373
            format = self.bzrdir_format()
374
        return TestCaseWithTransport.make_branch(self, path, format)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
375
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
376
    def create_bundle_text(self, base_rev_id, rev_id):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
377
        bundle_txt = StringIO()
378
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
379
                               bundle_txt, format=self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
380
        bundle_txt.seek(0)
381
        self.assertEqual(bundle_txt.readline(), 
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
382
                         '# Bazaar revision bundle v%s\n' % self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
383
        self.assertEqual(bundle_txt.readline(), '#\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
384
1185.82.14 by Aaron Bentley
API updates
385
        rev = self.b1.repository.get_revision(rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
386
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
387
                         u'# message:\n')
388
        bundle_txt.seek(0)
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
389
        return bundle_txt, rev_ids
390
391
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
392
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
393
        Make sure that the text generated is valid, and that it
394
        can be applied against the base, and generate the same information.
395
        
396
        :return: The in-memory bundle 
397
        """
398
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
399
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
400
        # This should also validate the generated bundle 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
401
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
402
        repository = self.b1.repository
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
403
        for bundle_rev in bundle.real_revisions:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
404
            # These really should have already been checked when we read the
405
            # bundle, since it computes the sha1 hash for the revision, which
406
            # only will match if everything is okay, but lets be explicit about
407
            # it
408
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1185.82.33 by Aaron Bentley
Strengthen tests
409
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
410
                      'timestamp', 'timezone', 'message', 'committer', 
411
                      'parent_ids', 'properties'):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
412
                self.assertEqual(getattr(branch_rev, a), 
413
                                 getattr(bundle_rev, a))
414
            self.assertEqual(len(branch_rev.parent_ids), 
415
                             len(bundle_rev.parent_ids))
1185.82.47 by Aaron Bentley
Ensure all intended rev_ids end up in the revision
416
        self.assertEqual(rev_ids, 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
417
                         [r.revision_id for r in bundle.real_revisions])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
418
        self.valid_apply_bundle(base_rev_id, bundle,
1185.82.89 by Aaron Bentley
Remove auto_commit stuff
419
                                   checkout_dir=checkout_dir)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
420
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
421
        return bundle
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
422
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
423
    def get_invalid_bundle(self, base_rev_id, rev_id):
424
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
425
        Munge the text so that it's invalid.
426
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
427
        :return: The in-memory bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
428
        """
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
429
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
430
        new_text = bundle_txt.getvalue().replace('executable:no', 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
431
                                               'executable:yes')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
432
        bundle_txt = StringIO(new_text)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
433
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
434
        self.valid_apply_bundle(base_rev_id, bundle)
435
        return bundle 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
436
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
437
    def test_non_bundle(self):
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
438
        self.assertRaises(errors.NotABundle,
439
                          read_bundle, StringIO('#!/bin/sh\n'))
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
440
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
441
    def test_malformed(self):
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
442
        self.assertRaises(errors.BadBundle, read_bundle,
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
443
                          StringIO('# Bazaar revision bundle v'))
444
445
    def test_crlf_bundle(self):
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
446
        try:
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
447
            read_bundle(StringIO('# Bazaar revision bundle v0.8\r\n'))
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
448
        except errors.BadBundle:
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
449
            # It is currently permitted for bundles with crlf line endings to
450
            # make read_bundle raise a BadBundle, but this should be fixed.
1793.2.10 by Aaron Bentley
Whitespace/comment fix
451
            # Anything else, especially NotABundle, is an error.
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
452
            pass
453
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
454
    def get_checkout(self, rev_id, checkout_dir=None):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
455
        """Get a new tree, with the specified revision in it.
456
        """
457
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
458
        if checkout_dir is None:
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
459
            checkout_dir = osutils.mkdtemp(prefix='test-branch-', dir='.')
0.5.89 by John Arbash Meinel
Updating for explicitly defined directories.
460
        else:
461
            if not os.path.exists(checkout_dir):
462
                os.mkdir(checkout_dir)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
463
        tree = self.make_branch_and_tree(checkout_dir)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
464
        s = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
465
        ancestors = write_bundle(self.b1.repository, rev_id, 'null:', s,
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
466
                                 format=self.format)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
467
        s.seek(0)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
468
        self.assertIsInstance(s.getvalue(), str)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
469
        install_bundle(tree.branch.repository, read_bundle(s))
1185.82.41 by Aaron Bentley
More work on installing changesets
470
        for ancestor in ancestors:
471
            old = self.b1.repository.revision_tree(ancestor)
472
            new = tree.branch.repository.revision_tree(ancestor)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
473
            old.lock_read()
474
            new.lock_read()
475
            try:
476
                # Check that there aren't any inventory level changes
477
                delta = new.changes_from(old)
478
                self.assertFalse(delta.has_changed(),
479
                                 'Revision %s not copied correctly.'
480
                                 % (ancestor,))
481
482
                # Now check that the file contents are all correct
483
                for inventory_id in old:
484
                    try:
485
                        old_file = old.get_file(inventory_id)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
486
                    except errors.NoSuchFile:
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
487
                        continue
488
                    if old_file is None:
489
                        continue
490
                    self.assertEqual(old_file.read(),
491
                                     new.get_file(inventory_id).read())
492
            finally:
493
                new.unlock()
494
                old.unlock()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
495
        if not _mod_revision.is_null(rev_id):
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
496
            rh = self.b1.revision_history()
497
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
498
            tree.update()
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
499
            delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
500
            self.assertFalse(delta.has_changed(),
2255.10.5 by John Arbash Meinel
Fix a small bug when we have a symlink that does not need to be re-read.
501
                             'Working tree has modifications: %s' % delta)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
502
        return tree
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
503
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
504
    def valid_apply_bundle(self, base_rev_id, info, checkout_dir=None):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
505
        """Get the base revision, apply the changes, and make
506
        sure everything matches the builtin branch.
507
        """
1185.82.17 by Aaron Bentley
More API updates
508
        to_tree = self.get_checkout(base_rev_id, checkout_dir=checkout_dir)
3146.4.11 by Aaron Bentley
Fix lock errors in bundle tests
509
        to_tree.lock_write()
510
        try:
511
            self._valid_apply_bundle(base_rev_id, info, to_tree)
512
        finally:
513
            to_tree.unlock()
514
515
    def _valid_apply_bundle(self, base_rev_id, info, to_tree):
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
516
        original_parents = to_tree.get_parent_ids()
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
517
        repository = to_tree.branch.repository
1927.2.1 by Robert Collins
Alter set_pending_merges to shove the left most merge into the trees last-revision if that is not set. Related bugfixes include basis_tree handling ghosts, de-duping the merges with the last-revision and update changing where and how it adds its pending merge.
518
        original_parents = to_tree.get_parent_ids()
1185.82.41 by Aaron Bentley
More work on installing changesets
519
        self.assertIs(repository.has_revision(base_rev_id), True)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
520
        for rev in info.real_revisions:
521
            self.assert_(not repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
522
                'Revision {%s} present before applying bundle' 
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
523
                % rev.revision_id)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
524
        merge_bundle(info, to_tree, True, Merge3Merger, False, False)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
525
526
        for rev in info.real_revisions:
1185.82.17 by Aaron Bentley
More API updates
527
            self.assert_(repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
528
                'Missing revision {%s} after applying bundle' 
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
529
                % rev.revision_id)
530
1185.82.17 by Aaron Bentley
More API updates
531
        self.assert_(to_tree.branch.repository.has_revision(info.target))
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
532
        # Do we also want to verify that all the texts have been added?
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
533
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
534
        self.assertEqual(original_parents + [info.target],
535
            to_tree.get_parent_ids())
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
536
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
537
        rev = info.real_revisions[-1]
1185.82.17 by Aaron Bentley
More API updates
538
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
539
        to_tree = to_tree.branch.repository.revision_tree(rev.revision_id)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
540
        
541
        # TODO: make sure the target tree is identical to base tree
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
542
        #       we might also check the working tree.
543
544
        base_files = list(base_tree.list_files())
545
        to_files = list(to_tree.list_files())
546
        self.assertEqual(len(base_files), len(to_files))
1185.82.66 by Aaron Bentley
Handle new executable files
547
        for base_file, to_file in zip(base_files, to_files):
548
            self.assertEqual(base_file, to_file)
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
549
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
550
        for path, status, kind, fileid, entry in base_files:
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
551
            # Check that the meta information is the same
552
            self.assertEqual(base_tree.get_file_size(fileid),
553
                    to_tree.get_file_size(fileid))
554
            self.assertEqual(base_tree.get_file_sha1(fileid),
555
                    to_tree.get_file_sha1(fileid))
556
            # Check that the contents are the same
557
            # This is pretty expensive
558
            # self.assertEqual(base_tree.get_file(fileid).read(),
559
            #         to_tree.get_file(fileid).read())
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
560
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
561
    def test_bundle(self):
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
562
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.14 by Aaron Bentley
API updates
563
        self.b1 = self.tree1.branch
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
564
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
565
        open('b1/one', 'wb').write('one\n')
1185.82.14 by Aaron Bentley
API updates
566
        self.tree1.add('one')
567
        self.tree1.commit('add one', rev_id='a@cset-0-1')
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
568
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
569
        bundle = self.get_valid_bundle('null:', 'a@cset-0-1')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
570
571
        # Make sure we can handle files with spaces, tabs, other
572
        # bogus characters
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
573
        self.build_tree([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
574
                'b1/with space.txt'
575
                , 'b1/dir/'
576
                , 'b1/dir/filein subdir.c'
577
                , 'b1/dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
578
                , 'b1/dir/ pre space'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
579
                , 'b1/sub/'
580
                , 'b1/sub/sub/'
581
                , 'b1/sub/sub/nonempty.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
582
                ])
0.5.84 by John Arbash Meinel
(broken) problem with removes.
583
        open('b1/sub/sub/emptyfile.txt', 'wb').close()
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
584
        open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
1185.82.66 by Aaron Bentley
Handle new executable files
585
        tt = TreeTransform(self.tree1)
586
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
587
        tt.apply()
2520.4.84 by Aaron Bentley
Fix heisenbug record-rewriting test
588
        # have to fix length of file-id so that we can predictably rewrite
589
        # a (length-prefixed) record containing it later.
590
        self.tree1.add('with space.txt', 'withspace-id')
1185.82.14 by Aaron Bentley
API updates
591
        self.tree1.add([
2520.4.84 by Aaron Bentley
Fix heisenbug record-rewriting test
592
                  'dir'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
593
                , 'dir/filein subdir.c'
594
                , 'dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
595
                , 'dir/ pre space'
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
596
                , 'dir/nolastnewline.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
597
                , 'sub'
598
                , 'sub/sub'
599
                , 'sub/sub/nonempty.txt'
600
                , 'sub/sub/emptyfile.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
601
                ])
1185.82.14 by Aaron Bentley
API updates
602
        self.tree1.commit('add whitespace', rev_id='a@cset-0-2')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
603
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
604
        bundle = self.get_valid_bundle('a@cset-0-1', 'a@cset-0-2')
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
605
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
606
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
607
        bundle = self.get_valid_bundle('null:', 'a@cset-0-2')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
608
609
        # Now delete entries
1185.82.21 by Aaron Bentley
Stop using deprecated function
610
        self.tree1.remove(
0.5.118 by John Arbash Meinel
Got most of test_changeset to work. Still needs work for Aaron's test code.
611
                ['sub/sub/nonempty.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
612
                , 'sub/sub/emptyfile.txt'
0.5.118 by John Arbash Meinel
Got most of test_changeset to work. Still needs work for Aaron's test code.
613
                , 'sub/sub'
614
                ])
1185.82.68 by Aaron Bentley
Handle execute bit on modified files
615
        tt = TreeTransform(self.tree1)
616
        trans_id = tt.trans_id_tree_file_id('exe-1')
617
        tt.set_executability(False, trans_id)
618
        tt.apply()
1185.82.19 by Aaron Bentley
More API updates
619
        self.tree1.commit('removed', rev_id='a@cset-0-3')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
620
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
621
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
622
        self.assertRaises((errors.TestamentMismatch,
2520.4.71 by Aaron Bentley
Update test to accept VersionedFileInvalidChecksum instead of TestamentMismatch
623
            errors.VersionedFileInvalidChecksum), self.get_invalid_bundle,
624
            'a@cset-0-2', 'a@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
625
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
626
        bundle = self.get_valid_bundle('null:', 'a@cset-0-3')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
627
628
        # Now move the directory
1185.82.19 by Aaron Bentley
More API updates
629
        self.tree1.rename_one('dir', 'sub/dir')
630
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
631
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
632
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
633
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
634
        bundle = self.get_valid_bundle('null:', 'a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
635
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
636
        # Modified files
637
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
2520.4.83 by Aaron Bentley
Clean up tests
638
        open('b1/sub/dir/ pre space', 'ab').write(
639
             '\r\nAdding some\r\nDOS format lines\r\n')
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
640
        open('b1/sub/dir/nolastnewline.txt', 'ab').write('\n')
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
641
        self.tree1.rename_one('sub/dir/ pre space', 
642
                              'sub/ start space')
1185.82.19 by Aaron Bentley
More API updates
643
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
644
        bundle = self.get_valid_bundle('a@cset-0-4', 'a@cset-0-5')
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
645
1185.82.70 by Aaron Bentley
Handle renamed files better
646
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
647
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
648
        self.tree1.rename_one('temp', 'with space.txt')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
649
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
650
                          verbose=False)
651
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
652
        other = self.get_checkout('a@cset-0-5')
1910.2.62 by Aaron Bentley
Cleanups
653
        tree1_inv = self.tree1.branch.repository.get_inventory_xml(
654
            'a@cset-0-5')
1910.2.54 by Aaron Bentley
Implement testament format 3 strict
655
        tree2_inv = other.branch.repository.get_inventory_xml('a@cset-0-5')
656
        self.assertEqualDiff(tree1_inv, tree2_inv)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
657
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
658
        other.commit('rename file', rev_id='a@cset-0-6b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
659
        self.tree1.merge_from_branch(other.branch)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
660
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
1185.82.70 by Aaron Bentley
Handle renamed files better
661
                          verbose=False)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
662
        bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
1185.82.72 by Aaron Bentley
Always use leftmost base for changesets
663
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
664
    def test_symlink_bundle(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
665
        self.requireFeature(SymlinkFeature)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
666
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.87 by Aaron Bentley
Got symlink adding working
667
        self.b1 = self.tree1.branch
668
        tt = TreeTransform(self.tree1)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
669
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
1185.82.87 by Aaron Bentley
Got symlink adding working
670
        tt.apply()
671
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
672
        self.get_valid_bundle('null:', 'l@cset-0-1')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
673
        tt = TreeTransform(self.tree1)
674
        trans_id = tt.trans_id_tree_file_id('link-1')
675
        tt.adjust_path('link2', tt.root, trans_id)
676
        tt.delete_contents(trans_id)
677
        tt.create_symlink('mars', trans_id)
678
        tt.apply()
679
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
680
        self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
681
        tt = TreeTransform(self.tree1)
682
        trans_id = tt.trans_id_tree_file_id('link-1')
683
        tt.delete_contents(trans_id)
684
        tt.create_symlink('jupiter', trans_id)
685
        tt.apply()
686
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
687
        self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
688
        tt = TreeTransform(self.tree1)
689
        trans_id = tt.trans_id_tree_file_id('link-1')
690
        tt.delete_contents(trans_id)
691
        tt.apply()
692
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
693
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
1185.82.96 by Aaron Bentley
Got first binary test passing
694
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
695
    def test_binary_bundle(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
696
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.96 by Aaron Bentley
Got first binary test passing
697
        self.b1 = self.tree1.branch
698
        tt = TreeTransform(self.tree1)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
699
        
700
        # Add
701
        tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
2520.4.83 by Aaron Bentley
Clean up tests
702
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff',
703
            'binary-2')
1185.82.96 by Aaron Bentley
Got first binary test passing
704
        tt.apply()
705
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
706
        self.get_valid_bundle('null:', 'b@cset-0-1')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
707
708
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
709
        tt = TreeTransform(self.tree1)
710
        trans_id = tt.trans_id_tree_file_id('binary-1')
711
        tt.delete_contents(trans_id)
712
        tt.apply()
713
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
714
        self.get_valid_bundle('b@cset-0-1', 'b@cset-0-2')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
715
716
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
717
        tt = TreeTransform(self.tree1)
718
        trans_id = tt.trans_id_tree_file_id('binary-2')
719
        tt.adjust_path('file3', tt.root, trans_id)
720
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
721
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
722
        tt.apply()
723
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
724
        self.get_valid_bundle('b@cset-0-2', 'b@cset-0-3')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
725
726
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
727
        tt = TreeTransform(self.tree1)
728
        trans_id = tt.trans_id_tree_file_id('binary-2')
729
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
730
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
731
        tt.apply()
732
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
733
        self.get_valid_bundle('b@cset-0-3', 'b@cset-0-4')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
734
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
735
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
736
        self.get_valid_bundle('null:', 'b@cset-0-4')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
737
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
738
    def test_last_modified(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
739
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
740
        self.b1 = self.tree1.branch
741
        tt = TreeTransform(self.tree1)
742
        tt.new_file('file', tt.root, 'file', 'file')
743
        tt.apply()
744
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
745
746
        tt = TreeTransform(self.tree1)
747
        trans_id = tt.trans_id_tree_file_id('file')
748
        tt.delete_contents(trans_id)
749
        tt.create_file('file2', trans_id)
750
        tt.apply()
751
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
752
753
        other = self.get_checkout('a@lmod-0-1')
754
        tt = TreeTransform(other)
755
        trans_id = tt.trans_id_tree_file_id('file')
756
        tt.delete_contents(trans_id)
757
        tt.create_file('file2', trans_id)
758
        tt.apply()
759
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
760
        self.tree1.merge_from_branch(other.branch)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
761
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
762
                          verbose=False)
763
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
764
        bundle = self.get_valid_bundle('a@lmod-0-2a', 'a@lmod-0-4')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
765
766
    def test_hide_history(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
767
        self.tree1 = self.make_branch_and_tree('b1')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
768
        self.b1 = self.tree1.branch
769
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
770
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
771
        self.tree1.add('one')
772
        self.tree1.commit('add file', rev_id='a@cset-0-1')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
773
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
774
        self.tree1.commit('modify', rev_id='a@cset-0-2')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
775
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
776
        self.tree1.commit('modify', rev_id='a@cset-0-3')
777
        bundle_file = StringIO()
778
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
779
                               'a@cset-0-1', bundle_file, format=self.format)
2382.1.1 by Ian Clatworthy
Fixes #98510 - bundle selftest fails if email has 'two' embedded
780
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
2520.4.32 by Aaron Bentley
Fix test case
781
        self.assertContainsRe(self.get_raw(bundle_file), 'one')
782
        self.assertContainsRe(self.get_raw(bundle_file), 'three')
783
2520.4.75 by Aaron Bentley
Fix traceback on empty bundles.
784
    def test_bundle_same_basis(self):
785
        """Ensure using the basis as the target doesn't cause an error"""
786
        self.tree1 = self.make_branch_and_tree('b1')
787
        self.tree1.commit('add file', rev_id='a@cset-0-1')
788
        bundle_file = StringIO()
789
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-1',
790
                               'a@cset-0-1', bundle_file)
791
2520.4.32 by Aaron Bentley
Fix test case
792
    @staticmethod
793
    def get_raw(bundle_file):
794
        return bundle_file.getvalue()
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
795
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
796
    def test_unicode_bundle(self):
797
        # Handle international characters
798
        os.mkdir('b1')
799
        try:
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
800
            f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
801
        except UnicodeEncodeError:
802
            raise TestSkipped("Filesystem doesn't support unicode")
803
804
        self.tree1 = self.make_branch_and_tree('b1')
805
        self.b1 = self.tree1.branch
806
807
        f.write((u'A file\n'
808
            u'With international man of mystery\n'
809
            u'William Dod\xe9\n').encode('utf-8'))
810
        f.close()
811
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
812
        self.tree1.add([u'with Dod\N{Euro Sign}'], ['withdod-id'])
2386.1.1 by John Arbash Meinel
Update test_unicode_bundle, since we know how it fails on Mac OSX
813
        self.tree1.commit(u'i18n commit from William Dod\xe9',
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
814
                          rev_id='i18n-1', committer=u'William Dod\xe9')
815
816
        # Add
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
817
        bundle = self.get_valid_bundle('null:', 'i18n-1')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
818
819
        # Modified
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
820
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
821
        f.write(u'Modified \xb5\n'.encode('utf8'))
822
        f.close()
823
        self.tree1.commit(u'modified', rev_id='i18n-2')
824
825
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
826
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
827
        # Renamed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
828
        self.tree1.rename_one(u'with Dod\N{Euro Sign}', u'B\N{Euro Sign}gfors')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
829
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
830
                          committer=u'Erik B\xe5gfors')
831
832
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
833
834
        # Removed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
835
        self.tree1.remove([u'B\N{Euro Sign}gfors'])
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
836
        self.tree1.commit(u'removed', rev_id='i18n-4')
837
838
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
839
840
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
841
        bundle = self.get_valid_bundle('null:', 'i18n-4')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
842
843
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
844
    def test_whitespace_bundle(self):
845
        if sys.platform in ('win32', 'cygwin'):
846
            raise TestSkipped('Windows doesn\'t support filenames'
847
                              ' with tabs or trailing spaces')
848
        self.tree1 = self.make_branch_and_tree('b1')
849
        self.b1 = self.tree1.branch
850
851
        self.build_tree(['b1/trailing space '])
852
        self.tree1.add(['trailing space '])
853
        # TODO: jam 20060701 Check for handling files with '\t' characters
854
        #       once we actually support them
855
856
        # Added
857
        self.tree1.commit('funky whitespace', rev_id='white-1')
858
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
859
        bundle = self.get_valid_bundle('null:', 'white-1')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
860
861
        # Modified
862
        open('b1/trailing space ', 'ab').write('add some text\n')
863
        self.tree1.commit('add text', rev_id='white-2')
864
865
        bundle = self.get_valid_bundle('white-1', 'white-2')
866
867
        # Renamed
868
        self.tree1.rename_one('trailing space ', ' start and end space ')
869
        self.tree1.commit('rename', rev_id='white-3')
870
871
        bundle = self.get_valid_bundle('white-2', 'white-3')
872
873
        # Removed
874
        self.tree1.remove([' start and end space '])
875
        self.tree1.commit('removed', rev_id='white-4')
876
877
        bundle = self.get_valid_bundle('white-3', 'white-4')
878
        
879
        # Now test a complet roll-up
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
880
        bundle = self.get_valid_bundle('null:', 'white-4')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
881
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
882
    def test_alt_timezone_bundle(self):
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
883
        self.tree1 = self.make_branch_and_memory_tree('b1')
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
884
        self.b1 = self.tree1.branch
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
885
        builder = treebuilder.TreeBuilder()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
886
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
887
        self.tree1.lock_write()
888
        builder.start_tree(self.tree1)
889
        builder.build(['newfile'])
890
        builder.finish_tree()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
891
892
        # Asia/Colombo offset = 5 hours 30 minutes
893
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
894
                          timezone=19800, timestamp=1152544886.0)
895
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
896
        bundle = self.get_valid_bundle('null:', 'tz-1')
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
897
        
898
        rev = bundle.revisions[0]
899
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
900
        self.assertEqual(19800, rev.timezone)
901
        self.assertEqual(1152544886.0, rev.timestamp)
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
902
        self.tree1.unlock()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
903
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
904
    def test_bundle_root_id(self):
905
        self.tree1 = self.make_branch_and_tree('b1')
906
        self.b1 = self.tree1.branch
907
        self.tree1.commit('message', rev_id='revid1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
908
        bundle = self.get_valid_bundle('null:', 'revid1')
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
909
        tree = self.get_bundle_tree(bundle, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
910
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
911
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
912
    def test_install_revisions(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
913
        self.tree1 = self.make_branch_and_tree('b1')
914
        self.b1 = self.tree1.branch
915
        self.tree1.commit('message', rev_id='rev2a')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
916
        bundle = self.get_valid_bundle('null:', 'rev2a')
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
917
        branch2 = self.make_branch('b2')
918
        self.assertFalse(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
919
        target_revision = bundle.install_revisions(branch2.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
920
        self.assertTrue(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
921
        self.assertEqual('rev2a', target_revision)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
922
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
923
    def test_bundle_empty_property(self):
924
        """Test serializing revision properties with an empty value."""
925
        tree = self.make_branch_and_memory_tree('tree')
926
        tree.lock_write()
927
        self.addCleanup(tree.unlock)
928
        tree.add([''], ['TREE_ROOT'])
929
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
930
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
931
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
932
        bundle = read_bundle(bundle_sio)
933
        revision_info = bundle.revisions[0]
934
        self.assertEqual('rev1', revision_info.revision_id)
935
        rev = revision_info.as_revision()
936
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
937
                         rev.properties)
938
939
    def test_bundle_sorted_properties(self):
940
        """For stability the writer should write properties in sorted order."""
941
        tree = self.make_branch_and_memory_tree('tree')
942
        tree.lock_write()
943
        self.addCleanup(tree.unlock)
944
945
        tree.add([''], ['TREE_ROOT'])
946
        tree.commit('One', rev_id='rev1',
947
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
948
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
949
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
950
        bundle = read_bundle(bundle_sio)
951
        revision_info = bundle.revisions[0]
952
        self.assertEqual('rev1', revision_info.revision_id)
953
        rev = revision_info.as_revision()
954
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
955
                          'd':'1'}, rev.properties)
956
957
    def test_bundle_unicode_properties(self):
958
        """We should be able to round trip a non-ascii property."""
959
        tree = self.make_branch_and_memory_tree('tree')
960
        tree.lock_write()
961
        self.addCleanup(tree.unlock)
962
963
        tree.add([''], ['TREE_ROOT'])
964
        # Revisions themselves do not require anything about revision property
965
        # keys, other than that they are a basestring, and do not contain
966
        # whitespace.
967
        # However, Testaments assert than they are str(), and thus should not
968
        # be Unicode.
969
        tree.commit('One', rev_id='rev1',
970
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
971
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
972
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
973
        bundle = read_bundle(bundle_sio)
974
        revision_info = bundle.revisions[0]
975
        self.assertEqual('rev1', revision_info.revision_id)
976
        rev = revision_info.as_revision()
977
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
978
                          'alpha':u'\u03b1'}, rev.properties)
979
2520.4.43 by Aaron Bentley
Fix test suite
980
    def test_bundle_with_ghosts(self):
981
        tree = self.make_branch_and_tree('tree')
982
        self.b1 = tree.branch
983
        self.build_tree_contents([('tree/file', 'content1')])
984
        tree.add(['file'])
985
        tree.commit('rev1')
986
        self.build_tree_contents([('tree/file', 'content2')])
987
        tree.add_parent_tree_id('ghost')
988
        tree.commit('rev2', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
989
        bundle = self.get_valid_bundle('null:', 'rev2')
2520.4.43 by Aaron Bentley
Fix test suite
990
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
991
    def make_simple_tree(self, format=None):
992
        tree = self.make_branch_and_tree('b1', format=format)
993
        self.b1 = tree.branch
994
        self.build_tree(['b1/file'])
995
        tree.add('file')
996
        return tree
997
998
    def test_across_serializers(self):
999
        tree = self.make_simple_tree('knit')
1000
        tree.commit('hello', rev_id='rev1')
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
1001
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1002
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1003
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1004
        bundle.install_revisions(repo)
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
1005
        inv_text = repo.get_inventory_xml('rev2')
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1006
        self.assertNotContainsRe(inv_text, 'format="5"')
2520.4.99 by Aaron Bentley
Test conversion across models
1007
        self.assertContainsRe(inv_text, 'format="7"')
1008
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1009
    def make_repo_with_installed_revisions(self):
1010
        tree = self.make_simple_tree('knit')
1011
        tree.commit('hello', rev_id='rev1')
1012
        tree.commit('hello', rev_id='rev2')
1013
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1014
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1015
        bundle.install_revisions(repo)
1016
        return repo
1017
2520.4.99 by Aaron Bentley
Test conversion across models
1018
    def test_across_models(self):
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1019
        repo = self.make_repo_with_installed_revisions()
3380.1.12 by Aaron Bentley
fix test
1020
        inv = repo.get_inventory('rev2')
2520.4.99 by Aaron Bentley
Test conversion across models
1021
        self.assertEqual('rev2', inv.root.revision)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1022
        root_id = inv.root.file_id
1023
        repo.lock_read()
1024
        self.addCleanup(repo.unlock)
1025
        self.assertEqual({(root_id, 'rev1'):(),
1026
            (root_id, 'rev2'):((root_id, 'rev1'),)},
1027
            repo.texts.get_parent_map([(root_id, 'rev1'), (root_id, 'rev2')]))
2520.4.99 by Aaron Bentley
Test conversion across models
1028
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1029
    def test_inv_hash_across_serializers(self):
1030
        repo = self.make_repo_with_installed_revisions()
1031
        recorded_inv_sha1 = repo.get_inventory_sha1('rev2')
1032
        xml = repo.get_inventory_xml('rev2')
1033
        self.assertEqual(sha_string(xml), recorded_inv_sha1)
1034
2520.4.99 by Aaron Bentley
Test conversion across models
1035
    def test_across_models_incompatible(self):
1036
        tree = self.make_simple_tree('dirstate-with-subtree')
1037
        tree.commit('hello', rev_id='rev1')
1038
        tree.commit('hello', rev_id='rev2')
1039
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1040
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1041
        except errors.IncompatibleBundleFormat:
1042
            raise TestSkipped("Format 0.8 doesn't work with knit3")
1043
        repo = self.make_repository('repo', format='knit')
1044
        bundle.install_revisions(repo)
1045
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1046
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1047
        self.assertRaises(errors.IncompatibleRevision,
1048
                          bundle.install_revisions, repo)
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1049
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1050
    def test_get_merge_request(self):
1051
        tree = self.make_simple_tree()
1052
        tree.commit('hello', rev_id='rev1')
1053
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1054
        bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1055
        result = bundle.get_merge_request(tree.branch.repository)
1056
        self.assertEqual((None, 'rev1', 'inapplicable'), result)
1057
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1058
    def test_with_subtree(self):
1059
        tree = self.make_branch_and_tree('tree',
1060
                                         format='dirstate-with-subtree')
1061
        self.b1 = tree.branch
1062
        subtree = self.make_branch_and_tree('tree/subtree',
1063
                                            format='dirstate-with-subtree')
1064
        tree.add('subtree')
1065
        tree.commit('hello', rev_id='rev1')
1066
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1067
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1068
        except errors.IncompatibleBundleFormat:
1069
            raise TestSkipped("Format 0.8 doesn't work with knit3")
1070
        if isinstance(bundle, v09.BundleInfo09):
1071
            raise TestSkipped("Format 0.9 doesn't work with subtrees")
1072
        repo = self.make_repository('repo', format='knit')
1073
        self.assertRaises(errors.IncompatibleRevision,
1074
                          bundle.install_revisions, repo)
1075
        repo2 = self.make_repository('repo2', format='dirstate-with-subtree')
1076
        bundle.install_revisions(repo2)
1077
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1078
    def test_revision_id_with_slash(self):
1079
        self.tree1 = self.make_branch_and_tree('tree')
1080
        self.b1 = self.tree1.branch
1081
        try:
1082
            self.tree1.commit('Revision/id/with/slashes', rev_id='rev/id')
1083
        except ValueError:
1084
            raise TestSkipped("Repository doesn't support revision ids with"
1085
                              " slashes")
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1086
        bundle = self.get_valid_bundle('null:', 'rev/id')
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1087
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1088
    def test_skip_file(self):
1089
        """Make sure we don't accidentally write to the wrong versionedfile"""
1090
        self.tree1 = self.make_branch_and_tree('tree')
1091
        self.b1 = self.tree1.branch
1092
        # rev1 is not present in bundle, done by fetch
1093
        self.build_tree_contents([('tree/file2', 'contents1')])
1094
        self.tree1.add('file2', 'file2-id')
1095
        self.tree1.commit('rev1', rev_id='reva')
1096
        self.build_tree_contents([('tree/file3', 'contents2')])
1097
        # rev2 is present in bundle, and done by fetch
1098
        # having file1 in the bunle causes file1's versionedfile to be opened.
1099
        self.tree1.add('file3', 'file3-id')
1100
        self.tree1.commit('rev2')
1101
        # Updating file2 should not cause an attempt to add to file1's vf
1102
        target = self.tree1.bzrdir.sprout('target').open_workingtree()
1103
        self.build_tree_contents([('tree/file2', 'contents3')])
1104
        self.tree1.commit('rev3', rev_id='rev3')
1105
        bundle = self.get_valid_bundle('reva', 'rev3')
2520.6.5 by Aaron Bentley
Skip for bundle formats that don't provide get_bundle_reader
1106
        if getattr(bundle, 'get_bundle_reader', None) is None:
1107
            raise TestSkipped('Bundle format cannot provide reader')
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1108
        # be sure that file1 comes before file2
1109
        for b, m, k, r, f in bundle.get_bundle_reader().iter_records():
1110
            if f == 'file3-id':
1111
                break
1112
            self.assertNotEqual(f, 'file2-id')
1113
        bundle.install_revisions(target.branch.repository)
1114
2520.4.43 by Aaron Bentley
Fix test suite
1115
1116
class V08BundleTester(BundleTester, TestCaseWithTransport):
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
1117
1118
    format = '0.8'
1119
1120
    def test_bundle_empty_property(self):
1121
        """Test serializing revision properties with an empty value."""
1122
        tree = self.make_branch_and_memory_tree('tree')
1123
        tree.lock_write()
1124
        self.addCleanup(tree.unlock)
1125
        tree.add([''], ['TREE_ROOT'])
1126
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1127
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1128
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1129
        self.assertContainsRe(bundle_sio.getvalue(),
1130
                              '# properties:\n'
1131
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1132
                              '#   empty: \n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1133
                              '#   one: two\n'
1134
                             )
1135
        bundle = read_bundle(bundle_sio)
1136
        revision_info = bundle.revisions[0]
1137
        self.assertEqual('rev1', revision_info.revision_id)
1138
        rev = revision_info.as_revision()
1139
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1140
                         rev.properties)
1141
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1142
    def get_bundle_tree(self, bundle, revision_id):
1143
        repository = self.make_repository('repo')
1144
        return bundle.revision_tree(repository, 'revid1')
1145
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1146
    def test_bundle_empty_property_alt(self):
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1147
        """Test serializing revision properties with an empty value.
1148
1149
        Older readers had a bug when reading an empty property.
1150
        They assumed that all keys ended in ': \n'. However they would write an
1151
        empty value as ':\n'. This tests make sure that all newer bzr versions
1152
        can handle th second form.
1153
        """
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1154
        tree = self.make_branch_and_memory_tree('tree')
1155
        tree.lock_write()
1156
        self.addCleanup(tree.unlock)
1157
        tree.add([''], ['TREE_ROOT'])
1158
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1159
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1160
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1161
        txt = bundle_sio.getvalue()
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1162
        loc = txt.find('#   empty: ') + len('#   empty:')
1163
        # Create a new bundle, which strips the trailing space after empty
1164
        bundle_sio = StringIO(txt[:loc] + txt[loc+1:])
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1165
1166
        self.assertContainsRe(bundle_sio.getvalue(),
1167
                              '# properties:\n'
1168
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1169
                              '#   empty:\n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1170
                              '#   one: two\n'
1171
                             )
1172
        bundle = read_bundle(bundle_sio)
1173
        revision_info = bundle.revisions[0]
1174
        self.assertEqual('rev1', revision_info.revision_id)
1175
        rev = revision_info.as_revision()
1176
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1177
                         rev.properties)
1178
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1179
    def test_bundle_sorted_properties(self):
1180
        """For stability the writer should write properties in sorted order."""
1181
        tree = self.make_branch_and_memory_tree('tree')
1182
        tree.lock_write()
1183
        self.addCleanup(tree.unlock)
1184
1185
        tree.add([''], ['TREE_ROOT'])
1186
        tree.commit('One', rev_id='rev1',
1187
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
1188
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1189
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1190
        self.assertContainsRe(bundle_sio.getvalue(),
1191
                              '# properties:\n'
1192
                              '#   a: 4\n'
1193
                              '#   b: 3\n'
1194
                              '#   branch-nick: tree\n'
1195
                              '#   c: 2\n'
1196
                              '#   d: 1\n'
1197
                             )
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1198
        bundle = read_bundle(bundle_sio)
1199
        revision_info = bundle.revisions[0]
1200
        self.assertEqual('rev1', revision_info.revision_id)
1201
        rev = revision_info.as_revision()
1202
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
1203
                          'd':'1'}, rev.properties)
1204
1205
    def test_bundle_unicode_properties(self):
1206
        """We should be able to round trip a non-ascii property."""
1207
        tree = self.make_branch_and_memory_tree('tree')
1208
        tree.lock_write()
1209
        self.addCleanup(tree.unlock)
1210
1211
        tree.add([''], ['TREE_ROOT'])
1212
        # Revisions themselves do not require anything about revision property
1213
        # keys, other than that they are a basestring, and do not contain
1214
        # whitespace.
1215
        # However, Testaments assert than they are str(), and thus should not
1216
        # be Unicode.
1217
        tree.commit('One', rev_id='rev1',
1218
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1219
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1220
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1221
        self.assertContainsRe(bundle_sio.getvalue(),
1222
                              '# properties:\n'
1223
                              '#   alpha: \xce\xb1\n'
1224
                              '#   branch-nick: tree\n'
1225
                              '#   omega: \xce\xa9\n'
1226
                             )
1227
        bundle = read_bundle(bundle_sio)
1228
        revision_info = bundle.revisions[0]
1229
        self.assertEqual('rev1', revision_info.revision_id)
1230
        rev = revision_info.as_revision()
1231
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
1232
                          'alpha':u'\u03b1'}, rev.properties)
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1233
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1234
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1235
class V09BundleKnit2Tester(V08BundleTester):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1236
1237
    format = '0.9'
1238
1239
    def bzrdir_format(self):
1240
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
1241
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1242
        return format
1243
1244
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1245
class V09BundleKnit1Tester(V08BundleTester):
1246
1247
    format = '0.9'
1248
1249
    def bzrdir_format(self):
1250
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1251
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1252
        return format
1253
1254
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1255
class V4BundleTester(BundleTester, TestCaseWithTransport):
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1256
2520.4.136 by Aaron Bentley
Fix format strings
1257
    format = '4'
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1258
1259
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
1260
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1261
        Make sure that the text generated is valid, and that it
1262
        can be applied against the base, and generate the same information.
1263
        
1264
        :return: The in-memory bundle 
1265
        """
1266
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1267
1268
        # This should also validate the generated bundle 
1269
        bundle = read_bundle(bundle_txt)
1270
        repository = self.b1.repository
1271
        for bundle_rev in bundle.real_revisions:
1272
            # These really should have already been checked when we read the
1273
            # bundle, since it computes the sha1 hash for the revision, which
1274
            # only will match if everything is okay, but lets be explicit about
1275
            # it
1276
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1277
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
1278
                      'timestamp', 'timezone', 'message', 'committer', 
1279
                      'parent_ids', 'properties'):
1280
                self.assertEqual(getattr(branch_rev, a), 
1281
                                 getattr(bundle_rev, a))
1282
            self.assertEqual(len(branch_rev.parent_ids), 
1283
                             len(bundle_rev.parent_ids))
2520.4.29 by Aaron Bentley
Reactivate some testing, fix topo_iter
1284
        self.assertEqual(set(rev_ids),
1285
                         set([r.revision_id for r in bundle.real_revisions]))
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1286
        self.valid_apply_bundle(base_rev_id, bundle,
1287
                                   checkout_dir=checkout_dir)
1288
1289
        return bundle
1290
2520.4.34 by Aaron Bentley
Add signature support
1291
    def get_invalid_bundle(self, base_rev_id, rev_id):
1292
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1293
        Munge the text so that it's invalid.
1294
1295
        :return: The in-memory bundle
1296
        """
1297
        from bzrlib.bundle import serializer
1298
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1299
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1300
        new_text = new_text.replace('<file file_id="exe-1"',
1301
                                    '<file executable="y" file_id="exe-1"')
2520.4.143 by Aaron Bentley
Fix invalid bundle test
1302
        new_text = new_text.replace('B222', 'B237')
2520.4.34 by Aaron Bentley
Add signature support
1303
        bundle_txt = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1304
        bundle_txt.write(serializer._get_bundle_header('4'))
2520.4.34 by Aaron Bentley
Add signature support
1305
        bundle_txt.write('\n')
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1306
        bundle_txt.write(new_text.encode('bz2'))
2520.4.34 by Aaron Bentley
Add signature support
1307
        bundle_txt.seek(0)
1308
        bundle = read_bundle(bundle_txt)
1309
        self.valid_apply_bundle(base_rev_id, bundle)
1310
        return bundle
1311
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1312
    def create_bundle_text(self, base_rev_id, rev_id):
1313
        bundle_txt = StringIO()
1314
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
1315
                               bundle_txt, format=self.format)
1316
        bundle_txt.seek(0)
1317
        self.assertEqual(bundle_txt.readline(), 
1318
                         '# Bazaar revision bundle v%s\n' % self.format)
1319
        self.assertEqual(bundle_txt.readline(), '#\n')
1320
        rev = self.b1.repository.get_revision(rev_id)
1321
        bundle_txt.seek(0)
1322
        return bundle_txt, rev_ids
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1323
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1324
    def get_bundle_tree(self, bundle, revision_id):
1325
        repository = self.make_repository('repo')
1326
        bundle.install_revisions(repository)
1327
        return repository.revision_tree(revision_id)
1328
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1329
    def test_creation(self):
1330
        tree = self.make_branch_and_tree('tree')
2520.4.8 by Aaron Bentley
Serialize inventory
1331
        self.build_tree_contents([('tree/file', 'contents1\nstatic\n')])
2520.4.6 by Aaron Bentley
Get installation started
1332
        tree.add('file', 'fileid-2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1333
        tree.commit('added file', rev_id='rev1')
2520.4.8 by Aaron Bentley
Serialize inventory
1334
        self.build_tree_contents([('tree/file', 'contents2\nstatic\n')])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1335
        tree.commit('changed file', rev_id='rev2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1336
        s = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1337
        serializer = BundleSerializerV4('1.0')
2520.4.8 by Aaron Bentley
Serialize inventory
1338
        serializer.write(tree.branch.repository, ['rev1', 'rev2'], {}, s)
2520.4.5 by Aaron Bentley
Start work on reading mpbundles
1339
        s.seek(0)
2520.4.6 by Aaron Bentley
Get installation started
1340
        tree2 = self.make_branch_and_tree('target')
1341
        target_repo = tree2.branch.repository
1342
        install_bundle(target_repo, serializer.read(s))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1343
        target_repo.lock_read()
1344
        self.addCleanup(target_repo.unlock)
1345
        self.assertEqual({'1':'contents1\nstatic\n',
1346
            '2':'contents2\nstatic\n'},
1347
            dict(target_repo.iter_files_bytes(
1348
                [('fileid-2', 'rev1', '1'), ('fileid-2', 'rev2', '2')])))
2520.4.8 by Aaron Bentley
Serialize inventory
1349
        rtree = target_repo.revision_tree('rev2')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1350
        inventory_vf = target_repo.inventories
1351
        # If the inventory store has a graph, it must match the revision graph.
1352
        self.assertSubset(
1353
            [inventory_vf.get_parent_map([('rev2',)])[('rev2',)]],
1354
            [None, (('rev1',),)])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1355
        self.assertEqual('changed file',
1356
                         target_repo.get_revision('rev2').message)
2520.4.6 by Aaron Bentley
Get installation started
1357
2520.4.32 by Aaron Bentley
Fix test case
1358
    @staticmethod
1359
    def get_raw(bundle_file):
1360
        bundle_file.seek(0)
2520.4.70 by Aaron Bentley
Yank patch-handling functionality
1361
        line = bundle_file.readline()
1362
        line = bundle_file.readline()
2520.4.32 by Aaron Bentley
Fix test case
1363
        lines = bundle_file.readlines()
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1364
        return ''.join(lines).decode('bz2')
2520.4.32 by Aaron Bentley
Fix test case
1365
2520.4.34 by Aaron Bentley
Add signature support
1366
    def test_copy_signatures(self):
1367
        tree_a = self.make_branch_and_tree('tree_a')
1368
        import bzrlib.gpg
1369
        import bzrlib.commit as commit
1370
        oldstrategy = bzrlib.gpg.GPGStrategy
1371
        branch = tree_a.branch
1372
        repo_a = branch.repository
1373
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1374
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1375
        try:
1376
            from bzrlib.testament import Testament
1377
            # monkey patch gpg signing mechanism
1378
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
1379
            new_config = test_commit.MustSignConfig(branch)
1380
            commit.Commit(config=new_config).commit(message="base",
1381
                                                    allow_pointless=True,
1382
                                                    rev_id='B',
1383
                                                    working_tree=tree_a)
1384
            def sign(text):
1385
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
1386
            self.assertTrue(repo_a.has_signature_for_revision_id('B'))
1387
        finally:
1388
            bzrlib.gpg.GPGStrategy = oldstrategy
1389
        tree_b = self.make_branch_and_tree('tree_b')
1390
        repo_b = tree_b.branch.repository
1391
        s = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1392
        serializer = BundleSerializerV4('4')
2520.4.34 by Aaron Bentley
Add signature support
1393
        serializer.write(tree_a.branch.repository, ['A', 'B'], {}, s)
1394
        s.seek(0)
1395
        install_bundle(repo_b, serializer.read(s))
1396
        self.assertTrue(repo_b.has_signature_for_revision_id('B'))
1397
        self.assertEqual(repo_b.get_signature_text('B'),
1398
                         repo_a.get_signature_text('B'))
2520.4.100 by Aaron Bentley
Fix repeat signature installs
1399
        s.seek(0)
1400
        # ensure repeat installs are harmless
1401
        install_bundle(repo_b, serializer.read(s))
2520.4.34 by Aaron Bentley
Add signature support
1402
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1403
2520.4.90 by Aaron Bentley
Handle \r terminated lines in Weaves properly
1404
class V4WeaveBundleTester(V4BundleTester):
1405
1406
    def bzrdir_format(self):
2520.4.91 by Aaron Bentley
Okay, so I meant metaweave. I think.
1407
        return 'metaweave'
2520.4.90 by Aaron Bentley
Handle \r terminated lines in Weaves properly
1408
1409
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1410
class MungedBundleTester(object):
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1411
1412
    def build_test_bundle(self):
1413
        wt = self.make_branch_and_tree('b1')
1414
1415
        self.build_tree(['b1/one'])
1416
        wt.add('one')
1417
        wt.commit('add one', rev_id='a@cset-0-1')
1418
        self.build_tree(['b1/two'])
1419
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1420
        wt.commit('add two', rev_id='a@cset-0-2',
1421
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1422
1423
        bundle_txt = StringIO()
1424
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1425
                               'a@cset-0-1', bundle_txt, self.format)
1426
        self.assertEqual(set(['a@cset-0-2']), set(rev_ids))
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1427
        bundle_txt.seek(0, 0)
1428
        return bundle_txt
1429
1430
    def check_valid(self, bundle):
1431
        """Check that after whatever munging, the final object is valid."""
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1432
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1433
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1434
1435
    def test_extra_whitespace(self):
1436
        bundle_txt = self.build_test_bundle()
1437
1438
        # Seek to the end of the file
1439
        # Adding one extra newline used to give us
1440
        # TypeError: float() argument must be a string or a number
1441
        bundle_txt.seek(0, 2)
1442
        bundle_txt.write('\n')
1443
        bundle_txt.seek(0)
1444
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1445
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1446
        self.check_valid(bundle)
1447
1448
    def test_extra_whitespace_2(self):
1449
        bundle_txt = self.build_test_bundle()
1450
1451
        # Seek to the end of the file
1452
        # Adding two extra newlines used to give us
1453
        # MalformedPatches: The first line of all patches should be ...
1454
        bundle_txt.seek(0, 2)
1455
        bundle_txt.write('\n\n')
1456
        bundle_txt.seek(0)
1457
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1458
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1459
        self.check_valid(bundle)
1460
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1461
1462
class MungedBundleTesterV09(TestCaseWithTransport, MungedBundleTester):
1463
1464
    format = '0.9'
1465
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1466
    def test_missing_trailing_whitespace(self):
1467
        bundle_txt = self.build_test_bundle()
1468
1469
        # Remove a trailing newline, it shouldn't kill the parser
1470
        raw = bundle_txt.getvalue()
1471
        # The contents of the bundle don't have to be this, but this
1472
        # test is concerned with the exact case where the serializer
1473
        # creates a blank line at the end, and fails if that
1474
        # line is stripped
1475
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1476
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1477
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1478
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1479
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1480
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
1481
    def test_opening_text(self):
1482
        bundle_txt = self.build_test_bundle()
1483
1484
        bundle_txt = StringIO("Some random\nemail comments\n"
1485
                              + bundle_txt.getvalue())
1486
1487
        bundle = read_bundle(bundle_txt)
1488
        self.check_valid(bundle)
1489
1490
    def test_trailing_text(self):
1491
        bundle_txt = self.build_test_bundle()
1492
1493
        bundle_txt = StringIO(bundle_txt.getvalue() +
1494
                              "Some trailing\nrandom\ntext\n")
1495
1496
        bundle = read_bundle(bundle_txt)
1497
        self.check_valid(bundle)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1498
1499
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1500
class MungedBundleTesterV4(TestCaseWithTransport, MungedBundleTester):
1501
2520.4.136 by Aaron Bentley
Fix format strings
1502
    format = '4'
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1503
1504
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1505
class TestBundleWriterReader(TestCase):
1506
1507
    def test_roundtrip_record(self):
1508
        fileobj = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1509
        writer = v4.BundleWriter(fileobj)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1510
        writer.begin()
2520.4.95 by Aaron Bentley
Add support for header/info records
1511
        writer.add_info_record(foo='bar')
1512
        writer._add_record("Record body", {'parents': ['1', '3'],
1513
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1514
        writer.end()
1515
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1516
        reader = v4.BundleReader(fileobj, stream_input=True)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1517
        record_iter = reader.iter_records()
1518
        record = record_iter.next()
1519
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1520
            'info', None, None), record)
1521
        record = record_iter.next()
1522
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1523
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1524
                          record)
1525
1526
    def test_roundtrip_record_memory_hungry(self):
1527
        fileobj = StringIO()
1528
        writer = v4.BundleWriter(fileobj)
1529
        writer.begin()
1530
        writer.add_info_record(foo='bar')
1531
        writer._add_record("Record body", {'parents': ['1', '3'],
1532
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
1533
        writer.end()
1534
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1535
        reader = v4.BundleReader(fileobj, stream_input=False)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1536
        record_iter = reader.iter_records()
2520.4.95 by Aaron Bentley
Add support for header/info records
1537
        record = record_iter.next()
1538
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1539
            'info', None, None), record)
1540
        record = record_iter.next()
1541
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1542
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1543
                          record)
1544
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1545
    def test_encode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1546
        self.assertEqual('revision/rev1',
1547
            v4.BundleWriter.encode_name('revision', 'rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1548
        self.assertEqual('file/rev//1/file-id-1',
1549
            v4.BundleWriter.encode_name('file', 'rev/1', 'file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1550
        self.assertEqual('info',
1551
            v4.BundleWriter.encode_name('info', None, None))
1552
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1553
    def test_decode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1554
        self.assertEqual(('revision', 'rev1', None),
1555
            v4.BundleReader.decode_name('revision/rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1556
        self.assertEqual(('file', 'rev/1', 'file-id-1'),
1557
            v4.BundleReader.decode_name('file/rev//1/file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1558
        self.assertEqual(('info', None, None),
1559
                         v4.BundleReader.decode_name('info'))
2520.4.131 by Aaron Bentley
Raise BadBundle for records with wrong number of names
1560
1561
    def test_too_many_names(self):
1562
        fileobj = StringIO()
1563
        writer = v4.BundleWriter(fileobj)
1564
        writer.begin()
1565
        writer.add_info_record(foo='bar')
1566
        writer._container.add_bytes_record('blah', ['two', 'names'])
1567
        writer.end()
1568
        fileobj.seek(0)
1569
        record_iter = v4.BundleReader(fileobj).iter_records()
1570
        record = record_iter.next()
1571
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1572
            'info', None, None), record)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
1573
        self.assertRaises(errors.BadBundle, record_iter.next)
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1574
1575
1576
class TestReadMergeableFromUrl(TestCaseWithTransport):
1577
1578
    def test_read_mergeable_skips_local(self):
1579
        """A local bundle named like the URL should not be read.
1580
        """
1581
        out, wt = test_read_bundle.create_bundle_file(self)
1582
        class FooService(object):
1583
            """A directory service that always returns source"""
1584
1585
            def look_up(self, name, url):
1586
                return 'source'
3251.4.12 by Aaron Bentley
Updates from review
1587
        directories.register('foo:', FooService, 'Testing directory service')
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1588
        self.addCleanup(lambda: directories.remove('foo:'))
1589
        self.build_tree_contents([('./foo:bar', out.getvalue())])
1590
        self.assertRaises(errors.NotABundle, read_mergeable_from_url,
1591
                          'foo:bar')
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1592
1593
    def test_smart_server_connection_reset(self):
1594
        """If a smart server connection fails during the attempt to read a
1595
        bundle, then the ConnectionReset error should be propagated.
1596
        """
1597
        # Instantiate a server that will provoke a ConnectionReset
1598
        sock_server = _DisconnectingTCPServer()
1599
        sock_server.setUp()
1600
        self.addCleanup(sock_server.tearDown)
3750.1.3 by Vincent Ladeuil
Cleanups.
1601
        # We don't really care what the url is since the server will close the
1602
        # connection without interpreting it
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1603
        url = sock_server.get_url()
1604
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
1605
1606
1607
class _DisconnectingTCPServer(object):
1608
    """A TCP server that immediately closes any connection made to it."""
1609
1610
    def setUp(self):
1611
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1612
        self.sock.bind(('127.0.0.1', 0))
1613
        self.sock.listen(1)
1614
        self.port = self.sock.getsockname()[1]
1615
        self.thread = threading.Thread(
1616
            name='%s (port %d)' % (self.__class__.__name__, self.port),
1617
            target=self.accept_and_close)
1618
        self.thread.start()
1619
1620
    def accept_and_close(self):
1621
        conn, addr = self.sock.accept()
1622
        conn.shutdown(socket.SHUT_RDWR)
1623
        conn.close()
1624
1625
    def get_url(self):
1626
        return 'bzr://127.0.0.1:%d/' % (self.port,)
1627
1628
    def tearDown(self):
1629
        try:
1630
            # make sure the thread dies by connecting to the listening socket,
1631
            # just in case the test failed to do so.
1632
            conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1633
            conn.connect(self.sock.getsockname())
1634
            conn.close()
1635
        except socket.error:
1636
            pass
1637
        self.sock.close()
1638
        self.thread.join()
1639