~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/repository_implementations/test_reconcile.py

  • Committer: Robert Collins
  • Date: 2006-05-02 12:32:40 UTC
  • mto: (1692.4.1 integration)
  • mto: This revision was merged to the branch mainline in revision 1694.
  • Revision ID: robertc@robertcollins.net-20060502123240-525d74f55b034ede
Teach reconcile to check the left-most parent is correct in the revision graph.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
import bzrlib.errors as errors
22
22
from bzrlib.reconcile import reconcile, Reconciler
23
23
from bzrlib.revision import Revision
 
24
from bzrlib.tests import TestSkipped
24
25
from bzrlib.tests.repository_implementations.test_repository import TestCaseWithRepository
25
26
from bzrlib.transport import get_transport
26
27
from bzrlib.tree import EmptyTree
 
28
from bzrlib.uncommit import uncommit
27
29
from bzrlib.workingtree import WorkingTree
28
30
 
29
31
 
30
 
class TestsNeedingReweave(TestCaseWithRepository):
 
32
class TestReconcile(TestCaseWithRepository):
 
33
 
 
34
    def checkUnreconciled(self, d, reconciler):
 
35
        """Check that d did not get reconciled."""
 
36
        # nothing should have been fixed yet:
 
37
        self.assertEqual(0, reconciler.inconsistent_parents)
 
38
        # and no garbage inventories
 
39
        self.assertEqual(0, reconciler.garbage_inventories)
 
40
        self.checkNoBackupInventory(d)
 
41
 
 
42
    def checkNoBackupInventory(self, aBzrDir):
 
43
        """Check that there is no backup inventory in aBzrDir."""
 
44
        repo = aBzrDir.open_repository()
 
45
        self.assertRaises(errors.NoSuchFile,
 
46
                          repo.control_weaves.get_weave,
 
47
                          'inventory.backup',
 
48
                          repo.get_transaction())
 
49
 
 
50
 
 
51
class TestsNeedingReweave(TestReconcile):
31
52
 
32
53
    def setUp(self):
33
54
        super(TestsNeedingReweave, self).setUp()
76
97
        rev.parent_ids = []
77
98
        repo.add_revision('the_ghost', rev)
78
99
 
79
 
    def checkNoBackupInventory(self, aBzrDir):
80
 
        """Check that there is no backup inventory in aBzrDir."""
81
 
        repo = aBzrDir.open_repository()
82
 
        self.assertRaises(errors.NoSuchFile,
83
 
                          repo.control_weaves.get_weave,
84
 
                          'inventory.backup',
85
 
                          repo.get_transaction())
86
 
 
87
100
    def checkEmptyReconcile(self, **kwargs):
88
101
        """Check a reconcile on an empty repository."""
89
102
        self.make_repository('empty')
161
174
        # actual low level test.
162
175
        d = bzrlib.bzrdir.BzrDir.open('inventory_without_revision')
163
176
        repo = d.open_repository()
164
 
        repo.reconcile()
165
177
        self.checkUnreconciled(d, repo.reconcile())
166
178
        # nothing should have been altered yet : inventories without
167
179
        # revisions are not data loss incurring for current format
206
218
        self.assertEqual([None, 'the_ghost', 'ghost'], repo.get_ancestry('ghost'))
207
219
        self.assertEqual([None, 'the_ghost'], repo.get_ancestry('the_ghost'))
208
220
 
209
 
    def checkUnreconciled(self, d, reconciler):
210
 
        """Check that d did not get reconciled."""
211
 
        # nothing should have been fixed yet:
212
 
        self.assertEqual(0, reconciler.inconsistent_parents)
 
221
 
 
222
class TestReconcileWithIncorrectRevisionCache(TestReconcile):
 
223
    """Ancestry data gets cached in knits and weaves should be reconcilable.
 
224
 
 
225
    This class tests that reconcile can correct invalid caches (such as after
 
226
    a reconcile).
 
227
    """
 
228
 
 
229
    def setUp(self):
 
230
        super(TestReconcileWithIncorrectRevisionCache, self).setUp()
 
231
        
 
232
        t = get_transport(self.get_url())
 
233
        # we need a revision with two parents in the wrong order
 
234
        # which should trigger reinsertion.
 
235
        # and another with the first one correct but the other two not
 
236
        # which should not trigger reinsertion.
 
237
        # these need to be in different repositories so that we don't
 
238
        # trigger a reconcile based on the other case.
 
239
        # there is no api to construct a broken knit repository at
 
240
        # this point. if we ever encounter a bad graph in a knit repo
 
241
        # we should add a lower level api to allow constructing such cases.
 
242
        
 
243
        # first off the common logic:
 
244
        tree = self.make_branch_and_tree('wrong-first-parent')
 
245
        tree.commit('1', rev_id='1')
 
246
        uncommit(tree.branch, tree=tree)
 
247
        tree.commit('2', rev_id='2')
 
248
        uncommit(tree.branch, tree=tree)
 
249
        tree.commit('3', rev_id='3')
 
250
        uncommit(tree.branch, tree=tree)
 
251
        repo_secondary = tree.bzrdir.clone(
 
252
            'reversed-secondary-parents').open_repository()
 
253
 
 
254
        # now setup the wrong-first parent case
 
255
        repo = tree.branch.repository
 
256
        inv = EmptyTree().inventory
 
257
        sha1 = repo.add_inventory('wrong-first-parent', inv, ['2', '1'])
 
258
        rev = Revision(timestamp=0,
 
259
                       timezone=None,
 
260
                       committer="Foo Bar <foo@example.com>",
 
261
                       message="Message",
 
262
                       inventory_sha1=sha1,
 
263
                       revision_id='wrong-first-parent')
 
264
        rev.parent_ids = ['1', '2']
 
265
        repo.add_revision('wrong-first-parent', rev)
 
266
 
 
267
        # now setup the wrong-secondary parent case
 
268
        repo = repo_secondary
 
269
        inv = EmptyTree().inventory
 
270
        sha1 = repo.add_inventory('wrong-secondary-parent', inv, ['1', '3', '2'])
 
271
        rev = Revision(timestamp=0,
 
272
                       timezone=None,
 
273
                       committer="Foo Bar <foo@example.com>",
 
274
                       message="Message",
 
275
                       inventory_sha1=sha1,
 
276
                       revision_id='wrong-secondary-parent')
 
277
        rev.parent_ids = ['1', '2', '3']
 
278
        repo.add_revision('wrong-secondary-parent', rev)
 
279
 
 
280
    def test_reconcile_wrong_order(self):
 
281
        # a wrong order in primary parents is optionally correctable
 
282
        d = bzrlib.bzrdir.BzrDir.open('wrong-first-parent')
 
283
        repo = d.open_repository()
 
284
        g = repo.get_revision_graph()
 
285
        if g['wrong-first-parent'] == ['1', '2']:
 
286
            raise TestSkipped('wrong-first-parent is not setup for testing')
 
287
        self.checkUnreconciled(d, repo.reconcile())
 
288
        # nothing should have been altered yet : inventories without
 
289
        # revisions are not data loss incurring for current format
 
290
        reconciler = repo.reconcile(thorough=True)
 
291
        # these show up as inconsistent parents
 
292
        self.assertEqual(1, reconciler.inconsistent_parents)
213
293
        # and no garbage inventories
214
294
        self.assertEqual(0, reconciler.garbage_inventories)
215
 
        self.checkNoBackupInventory(d)
 
295
        # and should have been fixed:
 
296
        g = repo.get_revision_graph()
 
297
        self.assertEqual(['1', '2'], g['wrong-first-parent'])
 
298
 
 
299
    def test_reconcile_wrong_order_secondary(self):
 
300
        # a wrong order in secondary parents is ignored.
 
301
        d = bzrlib.bzrdir.BzrDir.open('reversed-secondary-parents')
 
302
        repo = d.open_repository()
 
303
        self.checkUnreconciled(d, repo.reconcile())
 
304
        self.checkUnreconciled(d, repo.reconcile(thorough=True))