/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
1
import bzrlib
2
import unittest
3
from StringIO import StringIO
4
5
from bzrlib.selftest import InTempDir
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
6
7
from bzrlib.diff import internal_diff
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
8
from read_changeset import ChangesetTree
9
10
class MockTree(object):
11
    def __init__(self):
12
        object.__init__(self)
13
        self.paths = {}
14
        self.ids = {}
15
        self.contents = {}
16
17
    def __iter__(self):
18
        return self.paths.iterkeys()
19
20
    def add_dir(self, file_id, path):
21
        self.paths[file_id] = path
22
        self.ids[path] = file_id
23
    
24
    def add_file(self, file_id, path, contents):
25
        self.add_dir(file_id, path)
26
        self.contents[file_id] = contents
27
28
    def path2id(self, path):
29
        return self.ids.get(path)
30
31
    def id2path(self, file_id):
32
        return self.paths.get(file_id)
33
34
    def has_id(self, file_id):
35
        return self.id2path(file_id) is not None
36
37
    def get_file(self, file_id):
38
        result = StringIO()
39
        result.write(self.contents[file_id])
40
        result.seek(0,0)
41
        return result
42
43
class CTreeTester(unittest.TestCase):
44
    """A simple unittest tester for the ChangesetTree class."""
45
46
    def make_tree_1(self):
47
        mtree = MockTree()
48
        mtree.add_dir("a", "grandparent")
49
        mtree.add_dir("b", "grandparent/parent")
50
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
51
        mtree.add_dir("d", "grandparent/alt_parent")
52
        return ChangesetTree(mtree), mtree
53
        
54
    def test_renames(self):
55
        """Ensure that file renames have the proper effect on children"""
56
        ctree = self.make_tree_1()[0]
57
        self.assertEqual(ctree.old_path("grandparent"), "grandparent")
58
        self.assertEqual(ctree.old_path("grandparent/parent"), "grandparent/parent")
59
        self.assertEqual(ctree.old_path("grandparent/parent/file"),
60
            "grandparent/parent/file")
61
62
        self.assertEqual(ctree.id2path("a"), "grandparent")
63
        self.assertEqual(ctree.id2path("b"), "grandparent/parent")
64
        self.assertEqual(ctree.id2path("c"), "grandparent/parent/file")
65
66
        self.assertEqual(ctree.path2id("grandparent"), "a")
67
        self.assertEqual(ctree.path2id("grandparent/parent"), "b")
68
        self.assertEqual(ctree.path2id("grandparent/parent/file"), "c")
69
70
        assert ctree.path2id("grandparent2") is None
71
        assert ctree.path2id("grandparent2/parent") is None
72
        assert ctree.path2id("grandparent2/parent/file") is None
73
74
        ctree.note_rename("grandparent", "grandparent2")
75
        assert ctree.old_path("grandparent") is None
76
        assert ctree.old_path("grandparent/parent") is None
77
        assert ctree.old_path("grandparent/parent/file") is None
78
79
        self.assertEqual(ctree.id2path("a"), "grandparent2")
80
        self.assertEqual(ctree.id2path("b"), "grandparent2/parent")
81
        self.assertEqual(ctree.id2path("c"), "grandparent2/parent/file")
82
83
        self.assertEqual(ctree.path2id("grandparent2"), "a")
84
        self.assertEqual(ctree.path2id("grandparent2/parent"), "b")
85
        self.assertEqual(ctree.path2id("grandparent2/parent/file"), "c")
86
87
        assert ctree.path2id("grandparent") is None
88
        assert ctree.path2id("grandparent/parent") is None
89
        assert ctree.path2id("grandparent/parent/file") is None
90
91
        ctree.note_rename("grandparent/parent", "grandparent2/parent2")
92
        self.assertEqual(ctree.id2path("a"), "grandparent2")
93
        self.assertEqual(ctree.id2path("b"), "grandparent2/parent2")
94
        self.assertEqual(ctree.id2path("c"), "grandparent2/parent2/file")
95
96
        self.assertEqual(ctree.path2id("grandparent2"), "a")
97
        self.assertEqual(ctree.path2id("grandparent2/parent2"), "b")
98
        self.assertEqual(ctree.path2id("grandparent2/parent2/file"), "c")
99
100
        assert ctree.path2id("grandparent2/parent") is None
101
        assert ctree.path2id("grandparent2/parent/file") is None
102
103
        ctree.note_rename("grandparent/parent/file", 
104
                          "grandparent2/parent2/file2")
105
        self.assertEqual(ctree.id2path("a"), "grandparent2")
106
        self.assertEqual(ctree.id2path("b"), "grandparent2/parent2")
107
        self.assertEqual(ctree.id2path("c"), "grandparent2/parent2/file2")
108
109
        self.assertEqual(ctree.path2id("grandparent2"), "a")
110
        self.assertEqual(ctree.path2id("grandparent2/parent2"), "b")
111
        self.assertEqual(ctree.path2id("grandparent2/parent2/file2"), "c")
112
113
        assert ctree.path2id("grandparent2/parent2/file") is None
114
115
    def test_moves(self):
116
        """Ensure that file moves have the proper effect on children"""
117
        ctree = self.make_tree_1()[0]
118
        ctree.note_rename("grandparent/parent/file", 
119
                          "grandparent/alt_parent/file")
120
        self.assertEqual(ctree.id2path("c"), "grandparent/alt_parent/file")
121
        self.assertEqual(ctree.path2id("grandparent/alt_parent/file"), "c")
122
        assert ctree.path2id("grandparent/parent/file") is None
123
124
    def unified_diff(self, old, new):
125
        out = StringIO()
126
        internal_diff("old", old, "new", new, out)
127
        out.seek(0,0)
128
        return out.read()
129
130
    def make_tree_2(self):
131
        ctree = self.make_tree_1()[0]
132
        ctree.note_rename("grandparent/parent/file", 
133
                          "grandparent/alt_parent/file")
134
        assert ctree.id2path("e") is None
135
        assert ctree.path2id("grandparent/parent/file") is None
136
        ctree.note_id("e", "grandparent/parent/file")
137
        return ctree
138
139
    def test_adds(self):
140
        """File/inventory adds"""
141
        ctree = self.make_tree_2()
142
        add_patch = self.unified_diff([], ["Extra cheese\n"])
143
        ctree.note_patch("grandparent/parent/file", add_patch)
144
        self.adds_test(ctree)
145
146
    def adds_test(self, ctree):
147
        self.assertEqual(ctree.id2path("e"), "grandparent/parent/file")
148
        self.assertEqual(ctree.path2id("grandparent/parent/file"), "e")
149
        self.assertEqual(ctree.get_file("e").read(), "Extra cheese\n")
150
151
    def test_adds2(self):
152
        """File/inventory adds, with patch-compatibile renames"""
153
        ctree = self.make_tree_2()
154
        ctree.contents_by_id = False
155
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
156
        ctree.note_patch("grandparent/parent/file", add_patch)
157
        self.adds_test(ctree)
158
159
    def make_tree_3(self):
160
        ctree, mtree = self.make_tree_1()
161
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
162
        ctree.note_rename("grandparent/parent/file", 
163
                          "grandparent/alt_parent/file")
164
        ctree.note_rename("grandparent/parent/topping", 
165
                          "grandparent/alt_parent/stopping")
166
        return ctree
167
168
    def get_file_test(self, ctree):
169
        self.assertEqual(ctree.get_file("e").read(), "Lemon\n")
170
        self.assertEqual(ctree.get_file("c").read(), "Hello\n")
171
172
    def test_get_file(self):
173
        """Get file contents"""
174
        ctree = self.make_tree_3()
175
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
176
        ctree.note_patch("grandparent/alt_parent/stopping", mod_patch)
177
        self.get_file_test(ctree)
178
179
    def test_get_file2(self):
180
        """Get file contents, with patch-compatibile renames"""
181
        ctree = self.make_tree_3()
182
        ctree.contents_by_id = False
183
        mod_patch = self.unified_diff([], ["Lemon\n"])
184
        ctree.note_patch("grandparent/alt_parent/stopping", mod_patch)
185
        mod_patch = self.unified_diff([], ["Hello\n"])
186
        ctree.note_patch("grandparent/alt_parent/file", mod_patch)
187
        self.get_file_test(ctree)
188
189
    def test_delete(self):
190
        "Deletion by changeset"
191
        ctree = self.make_tree_1()[0]
192
        self.assertEqual(ctree.get_file("c").read(), "Hello\n")
193
        ctree.note_deletion("grandparent/parent/file")
194
        assert ctree.id2path("c") is None
195
        assert ctree.path2id("grandparent/parent/file") is None
196
197
    def sorted_ids(self, tree):
198
        ids = list(tree)
199
        ids.sort()
200
        return ids
201
202
    def test_iteration(self):
203
        """Ensure that iteration through ids works properly"""
204
        ctree = self.make_tree_1()[0]
205
        self.assertEqual(self.sorted_ids(ctree), ['a', 'b', 'c', 'd'])
206
        ctree.note_deletion("grandparent/parent/file")
207
        ctree.note_id("e", "grandparent/alt_parent/fool")
208
        self.assertEqual(self.sorted_ids(ctree), ['a', 'b', 'd', 'e'])
209
210
class CSetTester(InTempDir):
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
211
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
212
    def get_valid_cset(self, base_rev_id, rev_id):
213
        """Create a changeset from base_rev_id -> rev_id in built-in branch.
214
        Make sure that the text generated is valid, and that it
215
        can be applied against the base, and generate the same information.
216
        
217
        :return: The in-memory changeset
218
        """
219
        from cStringIO import StringIO
220
        from gen_changeset import show_changeset
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
221
        from read_changeset import read_changeset
222
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
223
        cset_txt = StringIO()
224
        show_changeset(self.b1, base_rev_id, self.b1, rev_id, to_file=cset_txt)
225
        cset_txt.seek(0)
226
        self.assertEqual(cset_txt.readline(), '# Bazaar-NG changeset v0.0.5\n')
227
        self.assertEqual(cset_txt.readline(), '# \n')
228
229
        rev = self.b1.get_revision(rev_id)
230
        self.assertEqual(cset_txt.readline(), '# committer: %s\n' % rev.committer)
231
232
        open(',,cset', 'wb').write(cset_txt.getvalue())
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
233
        cset_txt.seek(0)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
234
        # This should also validate the generate changeset
235
        cset = read_changeset(cset_txt, self.b1)
236
        info, tree = cset
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
237
        for cset_rev in info.real_revisions:
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
238
            # These really should have already been checked in read_changeset
239
            # since it computes the sha1 hash for the revision, which
240
            # only will match if everything is okay, but lets be
241
            # explicit about it
242
            branch_rev = self.b1.get_revision(cset_rev.revision_id)
243
            for a in ('inventory_id', 'inventory_sha1', 'revision_id',
244
                    'timestamp', 'timezone', 'message', 'committer'):
245
                self.assertEqual(getattr(branch_rev, a), getattr(cset_rev, a))
246
            self.assertEqual(len(branch_rev.parents), len(cset_rev.parents))
247
            for b_par, c_par in zip(branch_rev.parents, cset_rev.parents):
248
                self.assertEqual(b_par.revision_id, c_par.revision_id)
249
                # Foolishly, pending-merges generates parents which
250
                # may not have revision entries
251
                if b_par.revision_sha1 is None:
252
                    if b_par.revision_id in self.b1.revision_store:
253
                        sha1 = self.b1.get_revision_sha1(b_par.revision_id)
254
                    else:
255
                        sha1 = None
256
                else:
257
                    sha1 = b_par.revision_sha1
258
                if sha1 is not None:
259
                    self.assertEqual(sha1, c_par.revision_sha1)
260
261
        self.valid_apply_changeset(base_rev_id, cset)
262
263
        return cset
0.5.83 by John Arbash Meinel
Tests pass. Now ChangesetTree has it's own inventory.
264
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
265
    def get_checkout(self, rev_id):
266
        """Get a new tree, with the specified revision in it.
267
        """
268
        from bzrlib.branch import find_branch
269
        import tempfile
270
        from bzrlib.merge import merge
271
272
        dirname = tempfile.mkdtemp(prefix='test-branch-', dir='.')
273
        to_branch = find_branch(dirname, init=True)
274
        # TODO: Once root ids are established, remove this if
275
        if hasattr(self.b1, 'get_root_id'):
276
            to_branch.set_root_id(self.b1.get_root_id())
277
        if rev_id is not None:
278
            # TODO Worry about making the root id of the branch
279
            # the same
280
            rh = self.b1.revision_history()
281
            self.assert_(rev_id in rh, 'Missing revision %s in base tree' % rev_id)
282
            revno = self.b1.revision_history().index(rev_id) + 1
283
            to_branch.update_revisions(self.b1, stop_revision=revno)
284
            merge((dirname, -1), (dirname, 0), this_dir=dirname,
285
                    check_clean=False, ignore_zero=True)
286
        return to_branch
287
288
    def valid_apply_changeset(self, base_rev_id, cset):
289
        """Get the base revision, apply the changes, and make
290
        sure everything matches the builtin branch.
291
        """
292
        from apply_changeset import _apply_cset
293
294
        to_branch = self.get_checkout(base_rev_id)
295
        _apply_cset(to_branch, cset)
296
297
        info = cset[0]
298
        for rev in info.real_revisions:
299
            self.assert_(rev.revision_id in to_branch.revision_store,
300
                'Missing revision {%s} after applying changeset' 
301
                % rev.revision_id)
302
303
        rev = info.real_revisions[-1]
304
        base_tree = self.b1.revision_tree(rev.revision_id)
305
        to_tree = to_branch.revision_tree(rev.revision_id)
306
        
307
        # TODO: make sure the target tree is identical to base tree
308
309
    def runTest(self):
0.5.81 by John Arbash Meinel
Cleaning up from pychecker.
310
        from bzrlib.branch import find_branch
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
311
        import common
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
312
313
        import os, sys
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
314
        pjoin = os.path.join
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
315
316
        os.mkdir('b1')
317
        self.b1 = find_branch('b1', init=True)
318
319
        open(pjoin('b1/one'), 'wb').write('one\n')
320
        self.b1.add('one')
321
        self.b1.commit('add one', rev_id='a@cset-0-1')
322
323
        cset = self.get_valid_cset(None, 'a@cset-0-1')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
324
325
        # Make sure we can handle files with spaces, tabs, other
326
        # bogus characters
327
        self.build_tree([
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
328
                'b1/with space.txt',
329
                'b1/dir/',
330
                'b1/dir/filein subdir.c',
331
                'b1/dir/WithCaps.txt'
332
                # Tabs are not valid in filenames on windows
333
                #'b1/with\ttab.txt'
334
                ])
335
        self.b1.add([
336
                'with space.txt',
337
                'dir',
338
                'dir/filein subdir.c',
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
339
                'dir/WithCaps.txt'
340
                ])
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
341
        self.b1.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.
342
343
        cset = self.get_valid_cset('a@cset-0-1', 'a@cset-0-2')
344
        # Check a rollup changeset
345
        cset = self.get_valid_cset(None, 'a@cset-0-2')
346
        
347
TEST_CLASSES = [
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
348
    CTreeTester,
349
    CSetTester
350
]
351
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
352