1
# Copyright (C) 2006-2009, 2011 Canonical Ltd
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.
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.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for MultiWalker."""
24
from breezy.tests import (
25
TestCaseWithTransport,
29
class TestMultiWalker(TestCaseWithTransport):
31
def assertStepOne(self, has_more, path, file_id, iterator):
32
retval = multiwalker.MultiWalker._step_one(iterator)
34
self.assertIs(None, path)
35
self.assertIs(None, file_id)
36
self.assertEqual((False, None, None), retval)
38
self.assertEqual((has_more, path, file_id),
39
(retval[0], retval[1], retval[2].file_id))
41
def test__step_one_empty(self):
42
tree = self.make_branch_and_tree('empty')
43
repo = tree.branch.repository
44
empty_tree = repo.revision_tree(revision.NULL_REVISION)
46
iterator = empty_tree.iter_entries_by_dir()
47
self.assertStepOne(False, None, None, iterator)
48
self.assertStepOne(False, None, None, iterator)
50
def test__step_one(self):
51
tree = self.make_branch_and_tree('tree')
52
self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
53
tree.add(['a', 'b', 'b/c'], [b'a-id', b'b-id', b'c-id'])
55
iterator = tree.iter_entries_by_dir()
57
self.addCleanup(tree.unlock)
59
root_id = tree.path2id('')
60
self.assertStepOne(True, '', root_id, iterator)
61
self.assertStepOne(True, 'a', b'a-id', iterator)
62
self.assertStepOne(True, 'b', b'b-id', iterator)
63
self.assertStepOne(True, 'b/c', b'c-id', iterator)
64
self.assertStepOne(False, None, None, iterator)
65
self.assertStepOne(False, None, None, iterator)
67
def assertWalkerNext(self, exp_path, exp_file_id, master_has_node,
68
exp_other_paths, iterator):
69
"""Check what happens when we step the iterator.
71
:param path: The path for this entry
72
:param file_id: The file_id for this entry
73
:param master_has_node: Does the master tree have this entry?
74
:param exp_other_paths: A list of other_path values.
75
:param iterator: The iterator to step
77
path, file_id, master_ie, other_values = next(iterator)
78
self.assertEqual((exp_path, exp_file_id), (path, file_id),
79
'Master entry did not match')
81
self.assertIsNot(None, master_ie, 'master should have an entry')
83
self.assertIs(None, master_ie, 'master should not have an entry')
84
self.assertEqual(len(exp_other_paths), len(other_values),
85
'Wrong number of other entries')
88
for path, ie in other_values:
89
other_paths.append(path)
91
other_file_ids.append(None)
93
other_file_ids.append(ie.file_id)
96
for path in exp_other_paths:
98
exp_file_ids.append(None)
100
exp_file_ids.append(file_id)
101
self.assertEqual(exp_other_paths, other_paths, "Other paths incorrect")
102
self.assertEqual(exp_file_ids, other_file_ids,
103
"Other file_ids incorrect")
105
def lock_and_get_basis_and_root_id(self, tree):
107
self.addCleanup(tree.unlock)
108
basis_tree = tree.basis_tree()
109
basis_tree.lock_read()
110
self.addCleanup(basis_tree.unlock)
111
root_id = tree.path2id('')
112
return basis_tree, root_id
114
def test_simple_stepping(self):
115
tree = self.make_branch_and_tree('tree')
116
self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
117
tree.add(['a', 'b', 'b/c'], [b'a-id', b'b-id', b'c-id'])
119
tree.commit('first', rev_id=b'first-rev-id')
121
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
123
walker = multiwalker.MultiWalker(tree, [basis_tree])
124
iterator = walker.iter_all()
125
self.assertWalkerNext(u'', root_id, True, [u''], iterator)
126
self.assertWalkerNext(u'a', b'a-id', True, [u'a'], iterator)
127
self.assertWalkerNext(u'b', b'b-id', True, [u'b'], iterator)
128
self.assertWalkerNext(u'b/c', b'c-id', True, [u'b/c'], iterator)
129
self.assertRaises(StopIteration, next, iterator)
131
def test_master_has_extra(self):
132
tree = self.make_branch_and_tree('tree')
133
self.build_tree(['tree/a', 'tree/b/', 'tree/c', 'tree/d'])
134
tree.add(['a', 'b', 'd'], [b'a-id', b'b-id', b'd-id'])
136
tree.commit('first', rev_id=b'first-rev-id')
138
tree.add(['c'], [b'c-id'])
139
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
141
walker = multiwalker.MultiWalker(tree, [basis_tree])
142
iterator = walker.iter_all()
143
self.assertWalkerNext(u'', root_id, True, [u''], iterator)
144
self.assertWalkerNext(u'a', b'a-id', True, [u'a'], iterator)
145
self.assertWalkerNext(u'b', b'b-id', True, [u'b'], iterator)
146
self.assertWalkerNext(u'c', b'c-id', True, [None], iterator)
147
self.assertWalkerNext(u'd', b'd-id', True, [u'd'], iterator)
148
self.assertRaises(StopIteration, next, iterator)
150
def test_master_renamed_to_earlier(self):
151
"""The record is still present, it just shows up early."""
152
tree = self.make_branch_and_tree('tree')
153
self.build_tree(['tree/a', 'tree/c', 'tree/d'])
154
tree.add(['a', 'c', 'd'], [b'a-id', b'c-id', b'd-id'])
155
tree.commit('first', rev_id=b'first-rev-id')
156
tree.rename_one('d', 'b')
158
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
160
walker = multiwalker.MultiWalker(tree, [basis_tree])
161
iterator = walker.iter_all()
162
self.assertWalkerNext(u'', root_id, True, [u''], iterator)
163
self.assertWalkerNext(u'a', b'a-id', True, [u'a'], iterator)
164
self.assertWalkerNext(u'b', b'd-id', True, [u'd'], iterator)
165
self.assertWalkerNext(u'c', b'c-id', True, [u'c'], iterator)
166
self.assertRaises(StopIteration, next, iterator)
168
def test_master_renamed_to_later(self):
169
tree = self.make_branch_and_tree('tree')
170
self.build_tree(['tree/a', 'tree/b', 'tree/d'])
171
tree.add(['a', 'b', 'd'], [b'a-id', b'b-id', b'd-id'])
172
tree.commit('first', rev_id=b'first-rev-id')
173
tree.rename_one('b', 'e')
175
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
177
walker = multiwalker.MultiWalker(tree, [basis_tree])
178
iterator = walker.iter_all()
179
self.assertWalkerNext(u'', root_id, True, [u''], iterator)
180
self.assertWalkerNext(u'a', b'a-id', True, [u'a'], iterator)
181
self.assertWalkerNext(u'd', b'd-id', True, [u'd'], iterator)
182
self.assertWalkerNext(u'e', b'b-id', True, [u'b'], iterator)
183
self.assertRaises(StopIteration, next, iterator)
185
def test_other_extra_in_middle(self):
186
tree = self.make_branch_and_tree('tree')
187
self.build_tree(['tree/a', 'tree/b', 'tree/d'])
188
tree.add(['a', 'b', 'd'], [b'a-id', b'b-id', b'd-id'])
189
tree.commit('first', rev_id=b'first-rev-id')
192
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
193
walker = multiwalker.MultiWalker(tree, [basis_tree])
194
iterator = walker.iter_all()
195
self.assertWalkerNext(u'', root_id, True, [u''], iterator)
196
self.assertWalkerNext(u'a', b'a-id', True, [u'a'], iterator)
197
self.assertWalkerNext(u'd', b'd-id', True, [u'd'], iterator)
198
self.assertWalkerNext(u'b', b'b-id', False, [u'b'], iterator)
199
self.assertRaises(StopIteration, next, iterator)
201
def test_other_extra_at_end(self):
202
tree = self.make_branch_and_tree('tree')
203
self.build_tree(['tree/a', 'tree/b', 'tree/d'])
204
tree.add(['a', 'b', 'd'], [b'a-id', b'b-id', b'd-id'])
205
tree.commit('first', rev_id=b'first-rev-id')
208
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
209
walker = multiwalker.MultiWalker(tree, [basis_tree])
210
iterator = walker.iter_all()
211
self.assertWalkerNext(u'', root_id, True, [u''], iterator)
212
self.assertWalkerNext(u'a', b'a-id', True, [u'a'], iterator)
213
self.assertWalkerNext(u'b', b'b-id', True, [u'b'], iterator)
214
self.assertWalkerNext(u'd', b'd-id', False, [u'd'], iterator)
215
self.assertRaises(StopIteration, next, iterator)
217
def test_others_extra_at_end(self):
218
tree = self.make_branch_and_tree('tree')
219
self.build_tree(['tree/a', 'tree/b', 'tree/c', 'tree/d', 'tree/e'])
220
tree.add(['a', 'b', 'c', 'd', 'e'],
221
[b'a-id', b'b-id', b'c-id', b'd-id', b'e-id'])
222
tree.commit('first', rev_id=b'first-rev-id')
224
tree.commit('second', rev_id=b'second-rev-id')
226
tree.commit('third', rev_id=b'third-rev-id')
229
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
230
first_tree = tree.branch.repository.revision_tree(b'first-rev-id')
231
second_tree = tree.branch.repository.revision_tree(b'second-rev-id')
232
walker = multiwalker.MultiWalker(
233
tree, [basis_tree, first_tree, second_tree])
234
iterator = walker.iter_all()
235
self.assertWalkerNext(u'', root_id, True, [u'', u'', u''], iterator)
236
self.assertWalkerNext(u'a', b'a-id', True,
237
[u'a', u'a', u'a'], iterator)
238
self.assertWalkerNext(u'b', b'b-id', True,
239
[u'b', u'b', u'b'], iterator)
240
self.assertWalkerNext(u'c', b'c-id', False,
241
[u'c', u'c', u'c'], iterator)
242
self.assertWalkerNext(u'd', b'd-id', False,
243
[None, u'd', u'd'], iterator)
244
self.assertWalkerNext(u'e', b'e-id', False,
245
[None, u'e', None], iterator)
246
self.assertRaises(StopIteration, next, iterator)
248
def test_different_file_id_in_others(self):
249
tree = self.make_branch_and_tree('tree')
250
self.build_tree(['tree/a', 'tree/b', 'tree/c/'])
251
tree.add(['a', 'b', 'c'], [b'a-id', b'b-id', b'c-id'])
252
tree.commit('first', rev_id=b'first-rev-id')
254
tree.rename_one('b', 'c/d')
255
self.build_tree(['tree/b'])
256
tree.add(['b'], [b'b2-id'])
257
tree.commit('second', rev_id=b'second-rev-id')
259
tree.rename_one('a', 'c/e')
260
self.build_tree(['tree/a'])
261
tree.add(['a'], [b'a2-id'])
263
basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
264
first_tree = tree.branch.repository.revision_tree(b'first-rev-id')
265
walker = multiwalker.MultiWalker(tree, [basis_tree, first_tree])
267
iterator = walker.iter_all()
268
self.assertWalkerNext(u'', root_id, True, [u'', u''], iterator)
269
self.assertWalkerNext(u'a', b'a2-id', True, [None, None], iterator)
270
self.assertWalkerNext(u'b', b'b2-id', True, [u'b', None], iterator)
271
self.assertWalkerNext(u'c', b'c-id', True, [u'c', u'c'], iterator)
272
self.assertWalkerNext(u'c/d', b'b-id', True, [u'c/d', u'b'], iterator)
273
self.assertWalkerNext(u'c/e', b'a-id', True, [u'a', u'a'], iterator)
274
self.assertRaises(StopIteration, next, iterator)
276
def assertLtByDirblock(self, lt_val, path1, path2):
278
lt_val, multiwalker.MultiWalker._lt_path_by_dirblock(path1, path2))
280
def test__lt_path_by_dirblock(self):
281
# We only support Unicode strings at this point
283
TypeError, multiwalker.MultiWalker._lt_path_by_dirblock, b'', b'b')
284
self.assertLtByDirblock(False, u'', u'')
285
self.assertLtByDirblock(False, u'a', u'a')
286
self.assertLtByDirblock(False, u'a/b', u'a/b')
287
self.assertLtByDirblock(False, u'a/b/c', u'a/b/c')
288
self.assertLtByDirblock(False, u'a-a', u'a')
289
self.assertLtByDirblock(True, u'a-a', u'a/a')
290
self.assertLtByDirblock(True, u'a=a', u'a/a')
291
self.assertLtByDirblock(False, u'a-a/a', u'a/a')
292
self.assertLtByDirblock(False, u'a=a/a', u'a/a')
293
self.assertLtByDirblock(False, u'a-a/a', u'a/a/a')
294
self.assertLtByDirblock(False, u'a=a/a', u'a/a/a')
295
self.assertLtByDirblock(False, u'a-a/a/a', u'a/a/a')
296
self.assertLtByDirblock(False, u'a=a/a/a', u'a/a/a')
298
def assertPathToKey(self, expected, path):
299
self.assertEqual(expected, multiwalker.MultiWalker._path_to_key(path))
301
def test__path_to_key(self):
302
self.assertPathToKey(([u''], u''), u'')
303
self.assertPathToKey(([u''], u'a'), u'a')
304
self.assertPathToKey(([u'a'], u'b'), u'a/b')
305
self.assertPathToKey(([u'a', u'b'], u'c'), u'a/b/c')