/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/tests/matchers.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Matchers for breezy.
 
17
"""Matchers for brzlib.
18
18
 
19
 
Primarily test support, Matchers are used by self.assertThat in the breezy
 
19
Primarily test support, Matchers are used by self.assertThat in the brzlib
20
20
test suite. A matcher is a stateful test helper which can be used to determine
21
21
if a passed object 'matches', much like a regex. If the object does not match
22
22
the mismatch can be described in a human readable fashion. assertThat then
28
28
 
29
29
__all__ = [
30
30
    'HasLayout',
31
 
    'HasPathRelations',
32
31
    'MatchesAncestry',
33
32
    'ContainsNoVfsCalls',
34
33
    'ReturnsUnlockable',
35
34
    'RevisionHistoryMatches',
36
35
    ]
37
36
 
38
 
from .. import (
 
37
from brzlib import (
39
38
    osutils,
40
39
    revision as _mod_revision,
41
40
    )
42
 
from .. import lazy_import
 
41
from brzlib import lazy_import
43
42
lazy_import.lazy_import(globals(),
44
 
                        """
45
 
from breezy.bzr.smart.request import request_handlers as smart_request_handlers
46
 
from breezy.bzr.smart import vfs
 
43
"""
 
44
from brzlib.smart.request import request_handlers as smart_request_handlers
 
45
from brzlib.smart import vfs
47
46
""")
48
 
from ..tree import (
49
 
    find_previous_path,
50
 
    InterTree,
51
 
    )
52
47
 
53
48
from testtools.matchers import Equals, Mismatch, Matcher
54
49
 
69
64
 
70
65
    def __str__(self):
71
66
        return ('ReturnsUnlockable(lockable_thing=%s)' %
72
 
                self.lockable_thing)
 
67
            self.lockable_thing)
73
68
 
74
69
    def match(self, lock_method):
75
70
        lock_method().unlock()
118
113
            self.repository, self.revision_id))
119
114
 
120
115
    def match(self, expected):
121
 
        with self.repository.lock_read():
 
116
        self.repository.lock_read()
 
117
        try:
122
118
            graph = self.repository.get_graph()
123
119
            got = [r for r, p in graph.iter_ancestry([self.revision_id])]
124
120
            if _mod_revision.NULL_REVISION in got:
125
121
                got.remove(_mod_revision.NULL_REVISION)
 
122
        finally:
 
123
            self.repository.unlock()
126
124
        if sorted(got) != sorted(expected):
127
125
            return _AncestryMismatch(self.revision_id, sorted(got),
128
 
                                     sorted(expected))
 
126
                sorted(expected))
129
127
 
130
128
 
131
129
class HasLayout(Matcher):
138
136
        Matcher.__init__(self)
139
137
        self.entries = entries
140
138
 
141
 
    def get_tree_layout(self, tree, include_file_ids):
 
139
    def get_tree_layout(self, tree):
142
140
        """Get the (path, file_id) pairs for the current tree."""
143
 
        with tree.lock_read():
 
141
        tree.lock_read()
 
142
        try:
144
143
            for path, ie in tree.iter_entries_by_dir():
145
 
                if path != u'':
146
 
                    path += ie.kind_character()
147
 
                if include_file_ids:
148
 
                    yield (path, ie.file_id)
 
144
                if ie.parent_id is None:
 
145
                    yield (u"", ie.file_id)
149
146
                else:
150
 
                    yield path
 
147
                    yield (path+ie.kind_character(), ie.file_id)
 
148
        finally:
 
149
            tree.unlock()
151
150
 
152
151
    @staticmethod
153
152
    def _strip_unreferenced_directories(entries):
157
156
        """
158
157
        directories = []
159
158
        for entry in entries:
160
 
            if isinstance(entry, str):
 
159
            if isinstance(entry, basestring):
161
160
                path = entry
162
161
            else:
163
162
                path = entry[0]
176
175
        return 'HasLayout(%r)' % self.entries
177
176
 
178
177
    def match(self, tree):
179
 
        include_file_ids = self.entries and not isinstance(
180
 
            self.entries[0], str)
181
 
        actual = list(self.get_tree_layout(
182
 
            tree, include_file_ids=include_file_ids))
 
178
        actual = list(self.get_tree_layout(tree))
 
179
        if self.entries and isinstance(self.entries[0], basestring):
 
180
            actual = [path for (path, fileid) in actual]
183
181
        if not tree.has_versioned_directories():
184
182
            entries = list(self._strip_unreferenced_directories(self.entries))
185
183
        else:
187
185
        return Equals(entries).match(actual)
188
186
 
189
187
 
190
 
class HasPathRelations(Matcher):
191
 
    """Matcher verifies that paths have a relation to those in another tree.
192
 
 
193
 
    :ivar previous_tree: tree to compare to
194
 
    :ivar previous_entries: List of expected entries, as (path, previous_path) pairs.
195
 
    """
196
 
 
197
 
    def __init__(self, previous_tree, previous_entries):
198
 
        Matcher.__init__(self)
199
 
        self.previous_tree = previous_tree
200
 
        self.previous_entries = previous_entries
201
 
 
202
 
    def get_path_map(self, tree):
203
 
        """Get the (path, previous_path) pairs for the current tree."""
204
 
        previous_intertree = InterTree.get(self.previous_tree, tree)
205
 
        with tree.lock_read(), self.previous_tree.lock_read():
206
 
            for path, ie in tree.iter_entries_by_dir():
207
 
                if tree.supports_rename_tracking():
208
 
                    previous_path = previous_intertree.find_source_path(path)
209
 
                else:
210
 
                    if self.previous_tree.is_versioned(path):
211
 
                        previous_path = path
212
 
                    else:
213
 
                        previous_path = None
214
 
                if previous_path:
215
 
                    kind = self.previous_tree.kind(previous_path)
216
 
                    if kind == 'directory':
217
 
                        previous_path += '/'
218
 
                if path == u'':
219
 
                    yield (u"", previous_path)
220
 
                else:
221
 
                    yield (path + ie.kind_character(), previous_path)
222
 
 
223
 
    @staticmethod
224
 
    def _strip_unreferenced_directories(entries):
225
 
        """Strip all directories that don't (in)directly contain any files.
226
 
 
227
 
        :param entries: List of path strings or (path, previous_path) tuples to process
228
 
        """
229
 
        directory_used = set()
230
 
        directories = []
231
 
        for (path, previous_path) in entries:
232
 
            if not path or path[-1] == "/":
233
 
                # directory
234
 
                directories.append((path, previous_path))
235
 
            else:
236
 
                # Yield the referenced parent directories
237
 
                for direntry in directories:
238
 
                    if osutils.is_inside(direntry[0], path):
239
 
                        directory_used.add(direntry[0])
240
 
        for (path, previous_path) in entries:
241
 
            if (not path.endswith("/")) or path in directory_used:
242
 
                yield (path, previous_path)
243
 
 
244
 
    def __str__(self):
245
 
        return 'HasPathRelations(%r, %r)' % (self.previous_tree, self.previous_entries)
246
 
 
247
 
    def match(self, tree):
248
 
        actual = list(self.get_path_map(tree))
249
 
        if not tree.has_versioned_directories():
250
 
            entries = list(self._strip_unreferenced_directories(
251
 
                self.previous_entries))
252
 
        else:
253
 
            entries = self.previous_entries
254
 
        if not tree.supports_rename_tracking():
255
 
            entries = [
256
 
                (path, path if self.previous_tree.is_versioned(path) else None)
257
 
                for (path, previous_path) in entries]
258
 
        return Equals(entries).match(actual)
259
 
 
260
 
 
261
188
class RevisionHistoryMatches(Matcher):
262
189
    """A matcher that checks if a branch has a specific revision history.
263
190
 
272
199
        return 'RevisionHistoryMatches(%r)' % self.expected
273
200
 
274
201
    def match(self, branch):
275
 
        with branch.lock_read():
 
202
        branch.lock_read()
 
203
        try:
276
204
            graph = branch.repository.get_graph()
277
205
            history = list(graph.iter_lefthand_ancestry(
278
206
                branch.last_revision(), [_mod_revision.NULL_REVISION]))
279
207
            history.reverse()
 
208
        finally:
 
209
            branch.unlock()
280
210
        return Equals(self.expected).match(history)
281
211
 
282
212
 
289
219
    def describe(self):
290
220
        return "no VFS calls expected, got: %s" % ",".join([
291
221
            "%s(%s)" % (c.method,
292
 
                        ", ".join([repr(a) for a in c.args])) for c in self.vfs_calls])
 
222
                ", ".join([repr(a) for a in c.args])) for c in self.vfs_calls])
293
223
 
294
224
 
295
225
class ContainsNoVfsCalls(Matcher):