~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/tree_implementations/__init__.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
18
"""Tree implementation tests for bzr.
19
19
 
20
20
These test the conformance of all the tree variations to the expected API.
21
21
Specific tests for individual variations are in other places such as:
22
 
 - tests/per_workingtree/*.py.
23
22
 - tests/test_tree.py
24
23
 - tests/test_revision.py
25
24
 - tests/test_workingtree.py
 
25
 - tests/workingtree_implementations/*.py.
26
26
"""
27
27
 
28
28
from bzrlib import (
29
29
    errors,
 
30
    osutils,
 
31
    progress,
30
32
    tests,
31
33
    transform,
32
 
    transport,
33
 
    )
34
 
from bzrlib.tests.per_controldir.test_controldir import TestCaseWithControlDir
35
 
from bzrlib.tests.per_workingtree import (
36
 
    make_scenarios as wt_make_scenarios,
37
 
    make_scenario as wt_make_scenario,
38
 
    )
 
34
    )
 
35
from bzrlib.transport import get_transport
 
36
from bzrlib.tests import (
 
37
                          adapt_modules,
 
38
                          default_transport,
 
39
                          TestCaseWithTransport,
 
40
                          TestSkipped,
 
41
                          )
 
42
from bzrlib.tests.bzrdir_implementations.test_bzrdir import TestCaseWithBzrDir
 
43
from bzrlib.tests.workingtree_implementations import (
 
44
    WorkingTreeTestProviderAdapter,
 
45
    )
 
46
from bzrlib.revision import NULL_REVISION
39
47
from bzrlib.revisiontree import RevisionTree
40
48
from bzrlib.transform import TransformPreview
41
 
from bzrlib.tests import (
42
 
    features,
43
 
    )
44
49
from bzrlib.workingtree import (
45
 
    format_registry,
 
50
    WorkingTreeFormat,
 
51
    WorkingTreeFormat3,
 
52
    _legacy_formats,
46
53
    )
47
54
from bzrlib.workingtree_4 import (
48
55
    DirStateRevisionTree,
49
56
    WorkingTreeFormat4,
50
 
    WorkingTreeFormat5,
51
57
    )
52
58
 
53
59
 
79
85
    basis = tree.basis_tree()
80
86
    tt = TransformPreview(basis)
81
87
    testcase.addCleanup(tt.finalize)
 
88
    pp = progress.ProgressPhase('', 1, progress.DummyProgress())
82
89
    tree.lock_read()
83
90
    testcase.addCleanup(tree.unlock)
84
 
    pp = None
85
 
    transform._prepare_revert_transform(basis, tree, tt, None, False, None,
 
91
    transform._prepare_revert_transform(basis, tree, tt, None, False, pp,
86
92
                                        basis, {})
87
93
    preview_tree = tt.get_preview_tree()
88
94
    preview_tree.set_parent_ids(tree.get_parent_ids())
89
95
    return preview_tree
90
96
 
91
97
 
92
 
class TestTreeImplementationSupport(tests.TestCaseWithTransport):
 
98
class TestTreeImplementationSupport(TestCaseWithTransport):
93
99
 
94
100
    def test_revision_tree_from_workingtree(self):
95
101
        tree = self.make_branch_and_tree('.')
97
103
        self.assertIsInstance(tree, RevisionTree)
98
104
 
99
105
 
100
 
class TestCaseWithTree(TestCaseWithControlDir):
 
106
class TestCaseWithTree(TestCaseWithBzrDir):
101
107
 
102
108
    def make_branch_and_tree(self, relpath):
103
 
        bzrdir_format = self.workingtree_format.get_controldir_for_branch()
104
 
        made_control = self.make_bzrdir(relpath, format=bzrdir_format)
 
109
        made_control = self.make_bzrdir(relpath, format=
 
110
            self.workingtree_format._matchingbzrdir)
105
111
        made_control.create_repository()
106
 
        b = made_control.create_branch()
107
 
        if getattr(self, 'repo_is_remote', False):
108
 
            # If the repo is remote, then we just create a local lightweight
109
 
            # checkout
110
 
            # XXX: This duplicates a lot of Branch.create_checkout, but we know
111
 
            #      we want a) lightweight, and b) a specific WT format. We also
112
 
            #      know that nothing should already exist, etc.
113
 
            t = transport.get_transport(relpath)
114
 
            t.ensure_base()
115
 
            wt_dir = bzrdir_format.initialize_on_transport(t)
116
 
            branch_ref = wt_dir.set_branch_reference(b)
117
 
            wt = wt_dir.create_workingtree(None, from_branch=branch_ref)
118
 
        else:
119
 
            wt = self.workingtree_format.initialize(made_control)
120
 
        return wt
 
112
        made_control.create_branch()
 
113
        return self.workingtree_format.initialize(made_control)
121
114
 
122
115
    def workingtree_to_test_tree(self, tree):
123
116
        return self._workingtree_to_test_tree(self, tree)
131
124
 
132
125
    def get_tree_no_parents_no_content(self, empty_tree, converter=None):
133
126
        """Make a tree with no parents and no contents from empty_tree.
134
 
 
 
127
        
135
128
        :param empty_tree: A working tree with no content and no parents to
136
129
            modify.
137
130
        """
153
146
 
154
147
    def get_tree_no_parents_abc_content_2(self, tree, converter=None):
155
148
        """return a test tree with a, b/, b/c contents.
156
 
 
 
149
        
157
150
        This variation changes the content of 'a' to foobar\n.
158
151
        """
159
152
        self._make_abc_tree(tree)
166
159
 
167
160
    def get_tree_no_parents_abc_content_3(self, tree, converter=None):
168
161
        """return a test tree with a, b/, b/c contents.
169
 
 
 
162
        
170
163
        This variation changes the executable flag of b/c to True.
171
164
        """
172
165
        self._make_abc_tree(tree)
178
171
 
179
172
    def get_tree_no_parents_abc_content_4(self, tree, converter=None):
180
173
        """return a test tree with d, b/, b/c contents.
181
 
 
 
174
        
182
175
        This variation renames a to d.
183
176
        """
184
177
        self._make_abc_tree(tree)
187
180
 
188
181
    def get_tree_no_parents_abc_content_5(self, tree, converter=None):
189
182
        """return a test tree with d, b/, b/c contents.
190
 
 
 
183
        
191
184
        This variation renames a to d and alters its content to 'bar\n'.
192
185
        """
193
186
        self._make_abc_tree(tree)
201
194
 
202
195
    def get_tree_no_parents_abc_content_6(self, tree, converter=None):
203
196
        """return a test tree with a, b/, e contents.
204
 
 
 
197
        
205
198
        This variation renames b/c to e, and makes it executable.
206
199
        """
207
200
        self._make_abc_tree(tree)
213
206
        tt.apply()
214
207
        return self._convert_tree(tree, converter)
215
208
 
216
 
    def get_tree_no_parents_abc_content_7(self, tree, converter=None):
217
 
        """return a test tree with a, b/, d/e contents.
218
 
 
219
 
        This variation adds a dir 'd' ('d-id'), renames b to d/e.
220
 
        """
221
 
        self._make_abc_tree(tree)
222
 
        self.build_tree(['d/'], transport=tree.bzrdir.root_transport)
223
 
        tree.add(['d'], ['d-id'])
224
 
        tt = transform.TreeTransform(tree)
225
 
        trans_id = tt.trans_id_tree_path('b')
226
 
        parent_trans_id = tt.trans_id_tree_path('d')
227
 
        tt.adjust_path('e', parent_trans_id, trans_id)
228
 
        tt.apply()
229
 
        return self._convert_tree(tree, converter)
230
 
 
231
209
    def get_tree_with_subdirs_and_all_content_types(self):
232
210
        """Return a test tree with subdirs and all content types.
233
211
        See get_tree_with_subdirs_and_all_supported_content_types for details.
256
234
        where each component has the type of its name -
257
235
        i.e. '1file..' is afile.
258
236
 
259
 
        note that the order of the paths and fileids is deliberately
 
237
        note that the order of the paths and fileids is deliberately 
260
238
        mismatched to ensure that the result order is path based.
261
239
        """
262
 
        self.requireFeature(features.UnicodeFilenameFeature)
263
240
        tree = self.make_branch_and_tree('.')
264
241
        paths = ['0file',
265
242
            '1top-dir/',
274
251
            '1file-in-1topdir',
275
252
            '0dir-in-1topdir'
276
253
            ]
277
 
        self.build_tree(paths)
 
254
        try:
 
255
            self.build_tree(paths)
 
256
        except UnicodeError:
 
257
            raise TestSkipped(
 
258
                'This platform does not support unicode file paths.')
278
259
        tree.add(paths, ids)
279
260
        tt = transform.TreeTransform(tree)
280
261
        if symlinks:
291
272
 
292
273
    def _create_tree_with_utf8(self, tree):
293
274
        """Generate a tree with a utf8 revision and unicode paths."""
294
 
        self.requireFeature(features.UnicodeFilenameFeature)
295
 
        # We avoid combining characters in file names here, normalization
296
 
        # checks (as performed by some file systems (OSX) are outside the scope
297
 
        # of these tests).  We use the euro sign \N{Euro Sign} or \u20ac in
298
 
        # unicode strings or '\xe2\x82\ac' (its utf-8 encoding) in raw strings.
299
275
        paths = [u'',
300
 
                 u'fo\N{Euro Sign}o',
301
 
                 u'ba\N{Euro Sign}r/',
302
 
                 u'ba\N{Euro Sign}r/ba\N{Euro Sign}z',
 
276
                 u'f\xf6',
 
277
                 u'b\xe5r/',
 
278
                 u'b\xe5r/b\xe1z',
303
279
                ]
304
280
        # bzr itself does not create unicode file ids, but we want them for
305
281
        # testing.
306
282
        file_ids = ['TREE_ROOT',
307
 
                    'fo\xe2\x82\xaco-id',
308
 
                    'ba\xe2\x82\xacr-id',
309
 
                    'ba\xe2\x82\xacz-id',
 
283
                    'f\xc3\xb6-id',
 
284
                    'b\xc3\xa5r-id',
 
285
                    'b\xc3\xa1z-id',
310
286
                   ]
311
 
        self.build_tree(paths[1:])
 
287
        try:
 
288
            self.build_tree(paths[1:])
 
289
        except UnicodeError:
 
290
            raise tests.TestSkipped('filesystem does not support unicode.')
312
291
        if tree.get_root_id() is None:
313
292
            # Some trees do not have a root yet.
314
293
            tree.add(paths, file_ids)
325
304
        """Generate a tree with utf8 ancestors."""
326
305
        self._create_tree_with_utf8(tree)
327
306
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
328
 
        self.build_tree([u'tree2/ba\N{Euro Sign}r/qu\N{Euro Sign}x'])
329
 
        tree2.add([u'ba\N{Euro Sign}r/qu\N{Euro Sign}x'],
330
 
                  [u'qu\N{Euro Sign}x-id'.encode('utf-8')])
 
307
        self.build_tree([u'tree2/b\xe5r/z\xf7z'])
 
308
        tree2.add([u'b\xe5r/z\xf7z'], [u'z\xf7z-id'.encode('utf-8')])
331
309
        tree2.commit(u'to m\xe9rge', rev_id=u'r\xe9v-2'.encode('utf8'))
332
310
 
333
311
        tree.merge_from_branch(tree2.branch)
335
313
        return self.workingtree_to_test_tree(tree)
336
314
 
337
315
 
338
 
def make_scenarios(transport_server, transport_readonly_server, formats):
 
316
class TreeTestProviderAdapter(WorkingTreeTestProviderAdapter):
339
317
    """Generate test suites for each Tree implementation in bzrlib.
340
318
 
341
319
    Currently this covers all working tree formats, and RevisionTree and
342
320
    DirStateRevisionTree by committing a working tree to create the revision
343
321
    tree.
344
322
    """
345
 
    scenarios = wt_make_scenarios(transport_server, transport_readonly_server,
346
 
        formats)
347
 
    # now adjust the scenarios and add the non-working-tree tree scenarios.
348
 
    for scenario in scenarios:
349
 
        # for working tree format tests, preserve the tree
350
 
        scenario[1]["_workingtree_to_test_tree"] = return_parameter
351
 
    # add RevisionTree scenario
352
 
    workingtree_format = format_registry.get_default()
353
 
    scenarios.append((RevisionTree.__name__,
354
 
        create_tree_scenario(transport_server, transport_readonly_server,
355
 
        workingtree_format, revision_tree_from_workingtree,)))
356
 
 
357
 
    # also test WorkingTree4/5's RevisionTree implementation which is
358
 
    # specialised.
359
 
    # XXX: Ask igc if WT5 revision tree actually is different.
360
 
    scenarios.append((DirStateRevisionTree.__name__ + ",WT4",
361
 
        create_tree_scenario(transport_server, transport_readonly_server,
362
 
        WorkingTreeFormat4(), _dirstate_tree_from_workingtree)))
363
 
    scenarios.append((DirStateRevisionTree.__name__ + ",WT5",
364
 
        create_tree_scenario(transport_server, transport_readonly_server,
365
 
        WorkingTreeFormat5(), _dirstate_tree_from_workingtree)))
366
 
    scenarios.append(("PreviewTree", create_tree_scenario(transport_server,
367
 
        transport_readonly_server, workingtree_format, preview_tree_pre)))
368
 
    scenarios.append(("PreviewTreePost", create_tree_scenario(transport_server,
369
 
        transport_readonly_server, workingtree_format, preview_tree_post)))
370
 
    return scenarios
371
 
 
372
 
 
373
 
def create_tree_scenario(transport_server, transport_readonly_server,
374
 
    workingtree_format, converter):
375
 
    """Create a scenario for the specified converter
376
 
 
377
 
    :param converter: A function that converts a workingtree into the
378
 
        desired format.
379
 
    :param workingtree_format: The particular workingtree format to
380
 
        convert from.
381
 
    :return: a (name, options) tuple, where options is a dict of values
382
 
        to be used as members of the TestCase.
383
 
    """
384
 
    scenario_options = wt_make_scenario(transport_server,
385
 
                                        transport_readonly_server,
386
 
                                        workingtree_format)
387
 
    scenario_options["_workingtree_to_test_tree"] = converter
388
 
    return scenario_options
389
 
 
390
 
 
391
 
def load_tests(standard_tests, module, loader):
392
 
    per_tree_mod_names = [
393
 
        'annotate_iter',
394
 
        'export',
395
 
        'get_file_mtime',
396
 
        'get_file_with_stat',
397
 
        'get_root_id',
398
 
        'get_symlink_target',
399
 
        'ids',
400
 
        'inv',
401
 
        'iter_search_rules',
402
 
        'is_executable',
403
 
        'list_files',
404
 
        'locking',
405
 
        'path_content_summary',
406
 
        'revision_tree',
407
 
        'test_trees',
408
 
        'tree',
409
 
        'walkdirs',
 
323
 
 
324
    def __init__(self, transport_server, transport_readonly_server, formats):
 
325
        """Create a TreeTestProviderAdapter.
 
326
 
 
327
        :param formats: [workingtree_format]
 
328
        """
 
329
        super(TreeTestProviderAdapter, self).__init__(transport_server,
 
330
            transport_readonly_server, formats)
 
331
        # now adjust the scenarios and add the non-working-tree tree scenarios.
 
332
        for scenario in self.scenarios:
 
333
            # for working tree adapted tests, preserve the tree
 
334
            scenario[1]["_workingtree_to_test_tree"] = return_parameter
 
335
        # add RevisionTree scenario
 
336
        self.scenarios.append(self.create_tree_scenario(RevisionTree.__name__,
 
337
                              revision_tree_from_workingtree,))
 
338
 
 
339
        # also test WorkingTree4's RevisionTree implementation which is
 
340
        # specialised.
 
341
        self.scenarios.append(self.create_tree_scenario(
 
342
            DirStateRevisionTree.__name__, _dirstate_tree_from_workingtree,
 
343
            WorkingTreeFormat4()))
 
344
        self.scenarios.append(self.create_tree_scenario('PreviewTree',
 
345
            preview_tree_pre))
 
346
        self.scenarios.append(self.create_tree_scenario('PreviewTreePost',
 
347
            preview_tree_post))
 
348
 
 
349
    def create_tree_scenario(self, name, converter, workingtree_format=None):
 
350
        """Create a scenario for the specified converter
 
351
 
 
352
        :param name: The name to append to tests using this converter
 
353
        :param converter: A function that converts a workingtree into the
 
354
            desired format.
 
355
        :param workingtree_format: The particular workingtree format to
 
356
            convert from.
 
357
        :return: a (name, options) tuple, where options is a dict of values
 
358
            to be used as members of the TestCase.
 
359
        """
 
360
        if workingtree_format is None:
 
361
            workingtree_format = WorkingTreeFormat._default_format
 
362
        scenario_options = WorkingTreeTestProviderAdapter.create_scenario(self,
 
363
            workingtree_format)[1]
 
364
        scenario_options["_workingtree_to_test_tree"] = converter
 
365
        return name, scenario_options
 
366
 
 
367
 
 
368
def load_tests(basic_tests, module, loader):
 
369
    result = loader.suiteClass()
 
370
    # add the tests for this module
 
371
    result.addTests(basic_tests)
 
372
 
 
373
    test_tree_implementations = [
 
374
        'bzrlib.tests.tree_implementations.test_annotate_iter',
 
375
        'bzrlib.tests.tree_implementations.test_get_file_mtime',
 
376
        'bzrlib.tests.tree_implementations.test_get_root_id',
 
377
        'bzrlib.tests.tree_implementations.test_get_symlink_target',
 
378
        'bzrlib.tests.tree_implementations.test_inv',
 
379
        'bzrlib.tests.tree_implementations.test_iter_search_rules',
 
380
        'bzrlib.tests.tree_implementations.test_list_files',
 
381
        'bzrlib.tests.tree_implementations.test_path_content_summary',
 
382
        'bzrlib.tests.tree_implementations.test_revision_tree',
 
383
        'bzrlib.tests.tree_implementations.test_test_trees',
 
384
        'bzrlib.tests.tree_implementations.test_tree',
 
385
        'bzrlib.tests.tree_implementations.test_walkdirs',
410
386
        ]
411
 
    submod_tests = loader.loadTestsFromModuleNames(
412
 
        ['bzrlib.tests.per_tree.test_' + name
413
 
         for name in per_tree_mod_names])
414
 
    scenarios = make_scenarios(
415
 
        tests.default_transport,
 
387
 
 
388
    adapter = TreeTestProviderAdapter(
 
389
        default_transport,
416
390
        # None here will cause a readonly decorator to be created
417
391
        # by the TestCaseWithTransport.get_readonly_transport method.
418
392
        None,
419
 
        format_registry._get_all())
 
393
        WorkingTreeFormat._formats.values() + _legacy_formats)
 
394
 
420
395
    # add the tests for the sub modules
421
 
    return tests.multiply_tests(submod_tests, scenarios, standard_tests)
 
396
    adapt_modules(test_tree_implementations, adapter, loader, result)
 
397
    return result