/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
1
# Copyright (C) 2007 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
2745.6.44 by Andrew Bennetts
More docstring and formatting tweaks.
17
"""Tests that use BrokenRepoScenario objects.
18
19
That is, tests for reconcile and check.
20
"""
21
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
22
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
23
import sha
24
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
25
from bzrlib.inventory import Inventory, InventoryFile
26
from bzrlib.revision import Revision
27
from bzrlib.tests import TestNotApplicable
28
from bzrlib.tests.repository_implementations import TestCaseWithRepository
29
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
30
31
class TestFileParentReconciliation(TestCaseWithRepository):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
32
    """Tests for how reconcile corrects errors in parents of file versions."""
33
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
34
    def make_populated_repository(self, factory):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
35
        """Create a new repository populated by the given factory."""
36
        repo = self.make_repository('broken-repo')
37
        repo.lock_write()
38
        try:
39
            repo.start_write_group()
40
            try:
41
                factory(repo)
42
                repo.commit_write_group()
43
                return repo
44
            except:
45
                repo.abort_write_group()
46
                raise
47
        finally:
48
            repo.unlock()
49
50
    def add_revision(self, repo, revision_id, inv, parent_ids):
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
51
        """Add a revision with a given inventory and parents to a repository.
52
        
53
        :param repo: a repository.
54
        :param revision_id: the revision ID for the new revision.
55
        :param inv: an inventory (such as created by
56
            `make_one_file_inventory`).
57
        :param parent_ids: the parents for the new revision.
58
        """
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
59
        inv.revision_id = revision_id
60
        inv.root.revision = revision_id
61
        repo.add_inventory(revision_id, inv, parent_ids)
62
        revision = Revision(revision_id, committer='jrandom@example.com',
63
            timestamp=0, inventory_sha1='', timezone=0, message='foo',
64
            parent_ids=parent_ids)
65
        repo.add_revision(revision_id,revision, inv)
66
67
    def make_one_file_inventory(self, repo, revision, parents,
68
                                inv_revision=None, root_revision=None):
69
        """Make an inventory containing a version of a file with ID 'a-file'.
70
71
        The file's ID will be 'a-file', and its filename will be 'a file name',
72
        stored at the tree root.
73
74
        :param repo: a repository to add the new file version to.
75
        :param revision: the revision ID of the new inventory.
76
        :param parents: the parents for this revision of 'a-file'.
77
        :param inv_revision: if not None, the revision ID to store in the
78
            inventory entry.  Otherwise, this defaults to revision.
79
        :param root_revision: if not None, the inventory's root.revision will
80
            be set to this.
81
        """
82
        inv = Inventory(revision_id=revision)
83
        if root_revision is not None:
84
            inv.root.revision = root_revision
85
        file_id = 'a-file-id'
86
        entry = InventoryFile(file_id, 'a file name', 'TREE_ROOT')
87
        if inv_revision is not None:
88
            entry.revision = inv_revision
89
        else:
90
            entry.revision = revision
91
        entry.text_size = 0
92
        file_contents = '%sline\n' % entry.revision
93
        entry.text_sha1 = sha.sha(file_contents).hexdigest()
94
        inv.add(entry)
95
        vf = repo.weave_store.get_weave_or_empty(file_id,
96
                                                 repo.get_transaction())
97
        vf.add_lines(revision, parents, [file_contents])
98
        return inv
99
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
100
    def require_repo_suffers_text_parent_corruption(self, repo):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
101
        if not repo._reconcile_fixes_text_parents:
102
            raise TestNotApplicable(
103
                    "Format does not support text parent reconciliation")
104
105
    def file_parents(self, repo, revision_id):
106
        return repo.weave_store.get_weave('a-file-id',
107
            repo.get_transaction()).get_parents(revision_id)
108
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
109
    def assertParentsMatch(self, expected_parents_for_versions, repo,
110
                           when_description):
111
        for expected_parents, version in expected_parents_for_versions:
112
            found_parents = self.file_parents(repo, version)
113
            self.assertEqual(expected_parents, found_parents,
114
                "Expected version %s of a-file-id to have parents %s %s "
115
                "reconcile, but it has %s instead."
116
                % (version, expected_parents, when_description, found_parents))
117
118
    def shas_for_versions_of_file(self, repo, versions):
119
        """Get the SHA-1 hashes of the versions of 'a-file' in the repository.
120
        
121
        :param repo: the repository to get the hashes from.
122
        :param versions: a list of versions to get hashes for.
123
124
        :returns: A dict of `{version: hash}`.
125
        """
126
        vf = repo.weave_store.get_weave('a-file-id', repo.get_transaction())
127
        return dict((v, vf.get_sha1(v)) for v in versions)
128
129
    def test_reconcile_behaviour(self):
130
        """Populate a repository and reconcile it, verifying the state before
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
131
        and after.
132
        """
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
133
        scenario = self.scenario_class(self)
134
        repo = self.make_populated_repository(scenario.populate_repository)
135
        self.require_repo_suffers_text_parent_corruption(repo)
136
        self.assertParentsMatch(scenario.populated_parents(), repo, 'before')
137
        vf_shas = self.shas_for_versions_of_file(repo, scenario.all_versions())
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
138
        result = repo.reconcile(thorough=True)
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
139
        self.assertParentsMatch(scenario.corrected_parents(), repo, 'after')
140
        # The contents of the versions in the versionedfile should be the same
141
        # after the reconcile.
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
142
        self.assertEqual(
2745.6.44 by Andrew Bennetts
More docstring and formatting tweaks.
143
            vf_shas,
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
144
            self.shas_for_versions_of_file(repo, scenario.all_versions()))
145
146
    def test_check_behaviour(self):
147
        """Populate a repository and check it, and verify the output."""
148
        scenario = self.scenario_class(self)
149
        repo = self.make_populated_repository(scenario.populate_repository)
150
        self.require_repo_suffers_text_parent_corruption(repo)
151
        check_result = repo.check()
152
        check_result.report_results(verbose=True)
153
        for pattern in scenario.check_regexes():
154
            self.assertContainsRe(
155
                self._get_log(keep_log_file=True),
156
                pattern)
157