/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
2951.1.5 by Robert Collins
Some work towards including the correct changes for TREE_ROOT in check parameterised tests.
61
        if repo.supports_rich_root():
62
            root_id = inv.root.file_id
63
            vf = repo.weave_store.get_weave_or_empty(root_id,
64
                repo.get_transaction())
65
            vf.add_lines(revision_id, [], [])
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
66
        repo.add_inventory(revision_id, inv, parent_ids)
67
        revision = Revision(revision_id, committer='jrandom@example.com',
68
            timestamp=0, inventory_sha1='', timezone=0, message='foo',
69
            parent_ids=parent_ids)
70
        repo.add_revision(revision_id,revision, inv)
71
72
    def make_one_file_inventory(self, repo, revision, parents,
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
73
                                inv_revision=None, root_revision=None,
2927.2.4 by Andrew Bennetts
Don't create a 'rev3' file version in the test.
74
                                file_contents=None, make_file_version=True):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
75
        """Make an inventory containing a version of a file with ID 'a-file'.
76
77
        The file's ID will be 'a-file', and its filename will be 'a file name',
78
        stored at the tree root.
79
80
        :param repo: a repository to add the new file version to.
81
        :param revision: the revision ID of the new inventory.
82
        :param parents: the parents for this revision of 'a-file'.
83
        :param inv_revision: if not None, the revision ID to store in the
84
            inventory entry.  Otherwise, this defaults to revision.
85
        :param root_revision: if not None, the inventory's root.revision will
86
            be set to this.
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
87
        :param file_contents: if not None, the contents of this file version.
88
            Otherwise a unique default (based on revision ID) will be
89
            generated.
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
90
        """
91
        inv = Inventory(revision_id=revision)
92
        if root_revision is not None:
93
            inv.root.revision = root_revision
94
        file_id = 'a-file-id'
95
        entry = InventoryFile(file_id, 'a file name', 'TREE_ROOT')
96
        if inv_revision is not None:
97
            entry.revision = inv_revision
98
        else:
99
            entry.revision = revision
100
        entry.text_size = 0
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
101
        if file_contents is None:
102
            file_contents = '%sline\n' % entry.revision
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
103
        entry.text_sha1 = sha.sha(file_contents).hexdigest()
104
        inv.add(entry)
2927.2.4 by Andrew Bennetts
Don't create a 'rev3' file version in the test.
105
        if make_file_version:
106
            vf = repo.weave_store.get_weave_or_empty(file_id,
107
                                                     repo.get_transaction())
108
            vf.add_lines(revision, parents, [file_contents])
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
109
        return inv
110
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
111
    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.
112
        if not repo._reconcile_fixes_text_parents:
113
            raise TestNotApplicable(
114
                    "Format does not support text parent reconciliation")
115
116
    def file_parents(self, repo, revision_id):
2592.3.214 by Robert Collins
Merge bzr.dev.
117
        return tuple(repo.weave_store.get_weave('a-file-id',
118
            repo.get_transaction()).get_parents(revision_id))
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
119
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
120
    def assertFileVersionAbsent(self, repo, revision_id):
121
        self.assertFalse(repo.weave_store.get_weave('a-file-id',
122
            repo.get_transaction()).has_version(revision_id),
123
            'File version %s wrongly present.' % (revision_id,))
124
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
125
    def assertParentsMatch(self, expected_parents_for_versions, repo,
126
                           when_description):
127
        for expected_parents, version in expected_parents_for_versions:
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
128
            if expected_parents is None:
129
                self.assertFileVersionAbsent(repo, version)
130
            else:
131
                found_parents = self.file_parents(repo, version)
132
                self.assertEqual(expected_parents, found_parents,
2927.2.7 by Andrew Bennetts
Condense assertion message.
133
                    "%s reconcile %s has parents %s, should have %s."
134
                    % (when_description, version, found_parents,
135
                       expected_parents))
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
136
137
    def shas_for_versions_of_file(self, repo, versions):
138
        """Get the SHA-1 hashes of the versions of 'a-file' in the repository.
139
        
140
        :param repo: the repository to get the hashes from.
141
        :param versions: a list of versions to get hashes for.
142
143
        :returns: A dict of `{version: hash}`.
144
        """
145
        vf = repo.weave_store.get_weave('a-file-id', repo.get_transaction())
146
        return dict((v, vf.get_sha1(v)) for v in versions)
147
148
    def test_reconcile_behaviour(self):
149
        """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.
150
        and after.
151
        """
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
152
        scenario = self.scenario_class(self)
153
        repo = self.make_populated_repository(scenario.populate_repository)
154
        self.require_repo_suffers_text_parent_corruption(repo)
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
155
        repo.lock_read()
156
        try:
157
            self.assertParentsMatch(scenario.populated_parents(), repo,
158
                'before')
159
            vf_shas = self.shas_for_versions_of_file(
160
                repo, scenario.all_versions_after_reconcile())
161
        finally:
162
            repo.unlock()
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
163
        result = repo.reconcile(thorough=True)
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
164
        repo.lock_read()
165
        try:
166
            self.assertParentsMatch(scenario.corrected_parents(), repo,
167
                'after')
168
            # The contents of the versions in the versionedfile should be the
169
            # same after the reconcile.
170
            self.assertEqual(
171
                vf_shas,
172
                self.shas_for_versions_of_file(
173
                    repo, scenario.all_versions_after_reconcile()))
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
174
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
175
            for file_version in scenario.corrected_fulltexts():
176
                vf = repo.weave_store.get_weave(
177
                    'a-file-id', repo.get_transaction())
178
                self.assertEqual('fulltext',
179
                    vf._index.get_method(file_version),
180
                    '%r should be fulltext' % (file_version,))
181
        finally:
182
            repo.unlock()
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
183
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
184
    def test_check_behaviour(self):
185
        """Populate a repository and check it, and verify the output."""
186
        scenario = self.scenario_class(self)
187
        repo = self.make_populated_repository(scenario.populate_repository)
188
        self.require_repo_suffers_text_parent_corruption(repo)
189
        check_result = repo.check()
190
        check_result.report_results(verbose=True)
2951.1.6 by Robert Collins
All check/reconcile tests passing now.
191
        for pattern in scenario.check_regexes(repo):
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
192
            self.assertContainsRe(
193
                self._get_log(keep_log_file=True),
194
                pattern)
195