/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2007-2010 Canonical Ltd
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
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
3734.2.4 by Vincent Ladeuil
Fix python2.6 deprecation warnings related to hashlib.
22
from bzrlib import osutils
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
23
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
24
from bzrlib.inventory import Inventory, InventoryFile
25
from bzrlib.revision import Revision
26
from bzrlib.tests import TestNotApplicable
3689.1.1 by John Arbash Meinel
Rename repository_implementations tests into per_repository tests
27
from bzrlib.tests.per_repository import TestCaseWithRepository
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
28
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
29
30
class TestFileParentReconciliation(TestCaseWithRepository):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
31
    """Tests for how reconcile corrects errors in parents of file versions."""
32
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
33
    def make_populated_repository(self, factory):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
34
        """Create a new repository populated by the given factory."""
35
        repo = self.make_repository('broken-repo')
36
        repo.lock_write()
37
        try:
38
            repo.start_write_group()
39
            try:
40
                factory(repo)
41
                repo.commit_write_group()
42
                return repo
43
            except:
44
                repo.abort_write_group()
45
                raise
46
        finally:
47
            repo.unlock()
48
49
    def add_revision(self, repo, revision_id, inv, parent_ids):
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
50
        """Add a revision with a given inventory and parents to a repository.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
51
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
52
        :param repo: a repository.
53
        :param revision_id: the revision ID for the new revision.
54
        :param inv: an inventory (such as created by
55
            `make_one_file_inventory`).
56
        :param parent_ids: the parents for the new revision.
57
        """
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
58
        inv.revision_id = revision_id
59
        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.
60
        if repo.supports_rich_root():
61
            root_id = inv.root.file_id
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
62
            repo.texts.add_lines((root_id, revision_id), [], [])
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
63
        repo.add_inventory(revision_id, inv, parent_ids)
64
        revision = Revision(revision_id, committer='jrandom@example.com',
65
            timestamp=0, inventory_sha1='', timezone=0, message='foo',
66
            parent_ids=parent_ids)
67
        repo.add_revision(revision_id,revision, inv)
68
69
    def make_one_file_inventory(self, repo, revision, parents,
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
70
                                inv_revision=None, root_revision=None,
2927.2.4 by Andrew Bennetts
Don't create a 'rev3' file version in the test.
71
                                file_contents=None, make_file_version=True):
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
72
        """Make an inventory containing a version of a file with ID 'a-file'.
73
74
        The file's ID will be 'a-file', and its filename will be 'a file name',
75
        stored at the tree root.
76
77
        :param repo: a repository to add the new file version to.
78
        :param revision: the revision ID of the new inventory.
79
        :param parents: the parents for this revision of 'a-file'.
80
        :param inv_revision: if not None, the revision ID to store in the
81
            inventory entry.  Otherwise, this defaults to revision.
82
        :param root_revision: if not None, the inventory's root.revision will
83
            be set to this.
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
84
        :param file_contents: if not None, the contents of this file version.
85
            Otherwise a unique default (based on revision ID) will be
86
            generated.
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
87
        """
88
        inv = Inventory(revision_id=revision)
89
        if root_revision is not None:
90
            inv.root.revision = root_revision
91
        file_id = 'a-file-id'
92
        entry = InventoryFile(file_id, 'a file name', 'TREE_ROOT')
93
        if inv_revision is not None:
94
            entry.revision = inv_revision
95
        else:
96
            entry.revision = revision
97
        entry.text_size = 0
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
98
        if file_contents is None:
99
            file_contents = '%sline\n' % entry.revision
3734.2.4 by Vincent Ladeuil
Fix python2.6 deprecation warnings related to hashlib.
100
        entry.text_sha1 = osutils.sha(file_contents).hexdigest()
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
101
        inv.add(entry)
2927.2.4 by Andrew Bennetts
Don't create a 'rev3' file version in the test.
102
        if make_file_version:
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
103
            repo.texts.add_lines((file_id, revision),
104
                [(file_id, parent) for parent in parents], [file_contents])
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
105
        return inv
106
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
107
    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.
108
        if not repo._reconcile_fixes_text_parents:
109
            raise TestNotApplicable(
110
                    "Format does not support text parent reconciliation")
111
112
    def file_parents(self, repo, revision_id):
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
113
        key = ('a-file-id', revision_id)
114
        parent_map = repo.texts.get_parent_map([key])
115
        return tuple(parent[-1] for parent in parent_map[key])
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
116
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
117
    def assertFileVersionAbsent(self, repo, revision_id):
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
118
        self.assertEqual({},
119
            repo.texts.get_parent_map([('a-file-id', revision_id)]))
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
120
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
121
    def assertParentsMatch(self, expected_parents_for_versions, repo,
122
                           when_description):
123
        for expected_parents, version in expected_parents_for_versions:
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
124
            if expected_parents is None:
125
                self.assertFileVersionAbsent(repo, version)
126
            else:
127
                found_parents = self.file_parents(repo, version)
128
                self.assertEqual(expected_parents, found_parents,
2927.2.7 by Andrew Bennetts
Condense assertion message.
129
                    "%s reconcile %s has parents %s, should have %s."
130
                    % (when_description, version, found_parents,
131
                       expected_parents))
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
132
2988.1.2 by Robert Collins
New Repository API find_text_key_references for use by reconcile and check.
133
    def prepare_test_repository(self):
134
        """Prepare a repository to test with from the test scenario.
135
136
        :return: A repository, and the scenario instance.
137
        """
138
        scenario = self.scenario_class(self)
139
        repo = self.make_populated_repository(scenario.populate_repository)
140
        self.require_repo_suffers_text_parent_corruption(repo)
141
        return repo, scenario
142
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
143
    def shas_for_versions_of_file(self, repo, versions):
144
        """Get the SHA-1 hashes of the versions of 'a-file' in the repository.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
145
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
146
        :param repo: the repository to get the hashes from.
147
        :param versions: a list of versions to get hashes for.
148
149
        :returns: A dict of `{version: hash}`.
150
        """
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
151
        keys = [('a-file-id', version) for version in versions]
3350.8.3 by Robert Collins
VF.get_sha1s needed changing to be stackable.
152
        return repo.texts.get_sha1s(keys)
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
153
154
    def test_reconcile_behaviour(self):
155
        """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.
156
        and after.
157
        """
2988.1.2 by Robert Collins
New Repository API find_text_key_references for use by reconcile and check.
158
        repo, scenario = self.prepare_test_repository()
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
159
        repo.lock_read()
160
        try:
161
            self.assertParentsMatch(scenario.populated_parents(), repo,
162
                'before')
163
            vf_shas = self.shas_for_versions_of_file(
164
                repo, scenario.all_versions_after_reconcile())
165
        finally:
166
            repo.unlock()
2745.6.42 by Andrew Bennetts
Use TestScenarioApplier to more cleanly parameterise check and reconcile tests.
167
        result = repo.reconcile(thorough=True)
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
168
        repo.lock_read()
169
        try:
170
            self.assertParentsMatch(scenario.corrected_parents(), repo,
171
                'after')
172
            # The contents of the versions in the versionedfile should be the
173
            # same after the reconcile.
174
            self.assertEqual(
175
                vf_shas,
176
                self.shas_for_versions_of_file(
177
                    repo, scenario.all_versions_after_reconcile()))
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
178
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
179
            # Scenario.corrected_fulltexts contains texts which the test wants
180
            # to assert are now fulltexts. However this is an abstraction
181
            # violation; really we care that:
182
            # - the text is reconstructable
183
            # - it has an empty parents list
184
            # (we specify it this way because a store can use arbitrary
185
            # compression pointers in principle.
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
186
            for file_version in scenario.corrected_fulltexts():
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
187
                key = ('a-file-id', file_version)
188
                self.assertEqual({key:()}, repo.texts.get_parent_map([key]))
189
                self.assertIsInstance(
190
                    repo.texts.get_record_stream([key], 'unordered',
191
                        True).next().get_bytes_as('fulltext'),
192
                    str)
2951.1.4 by Robert Collins
Lock correctness for check/reconcile tests.
193
        finally:
194
            repo.unlock()
2927.2.3 by Andrew Bennetts
Add fulltexts to avoid bug 155730.
195
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
196
    def test_check_behaviour(self):
197
        """Populate a repository and check it, and verify the output."""
2988.1.2 by Robert Collins
New Repository API find_text_key_references for use by reconcile and check.
198
        repo, scenario = self.prepare_test_repository()
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
199
        check_result = repo.check()
200
        check_result.report_results(verbose=True)
4794.1.15 by Robert Collins
Review feedback.
201
        log = self.get_log()
2951.1.6 by Robert Collins
All check/reconcile tests passing now.
202
        for pattern in scenario.check_regexes(repo):
4794.1.8 by Robert Collins
Move the passing of test logs to the result to be via the getDetails API and remove all public use of TestCase._get_log.
203
            self.assertContainsRe(log, pattern)
2745.6.46 by Andrew Bennetts
Improvements to check/reconcile tests suggested by review.
204
2988.1.2 by Robert Collins
New Repository API find_text_key_references for use by reconcile and check.
205
    def test_find_text_key_references(self):
206
        """Test that find_text_key_references finds erroneous references."""
207
        repo, scenario = self.prepare_test_repository()
208
        repo.lock_read()
209
        self.addCleanup(repo.unlock)
210
        self.assertEqual(scenario.repository_text_key_references(),
211
            repo.find_text_key_references())
2988.1.3 by Robert Collins
Add a new repositoy method _generate_text_key_index for use by reconcile/check.
212
213
    def test__generate_text_key_index(self):
214
        """Test that the generated text key index has all entries."""
215
        repo, scenario = self.prepare_test_repository()
216
        repo.lock_read()
217
        self.addCleanup(repo.unlock)
218
        self.assertEqual(scenario.repository_text_key_index(),
219
            repo._generate_text_key_index())