1# Copyright (C) 2006-2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
18"""WorkingTree implementation tests for bzr.
19
20This test the conformance of all the workingtre variations to the expected API.
21Specific tests for individual formats are in the tests/test_workingtree file
22rather than in tests/per_workingtree/*.py.
23"""
24
25from breezy import (
26    branchbuilder,
27    tests,
28    transport,
29    workingtree,
30    )
31from breezy.transport import memory
32from breezy.tests import (
33    per_controldir,
34    test_server,
35    )
36
37
38def make_scenarios(transport_server, transport_readonly_server, formats,
39                   remote_server=None, remote_readonly_server=None,
40                   remote_backing_server=None):
41    result = []
42    for workingtree_format in formats:
43        result.append((workingtree_format.__class__.__name__,
44                       make_scenario(transport_server,
45                                     transport_readonly_server,
46                                     workingtree_format)))
47    default_wt_format = workingtree.format_registry.get_default()
48    if remote_server is None:
49        remote_server = test_server.SmartTCPServer_for_testing
50    if remote_readonly_server is None:
51        remote_readonly_server = test_server.ReadonlySmartTCPServer_for_testing
52    if remote_backing_server is None:
53        remote_backing_server = memory.MemoryServer
54    scenario = make_scenario(remote_server, remote_readonly_server,
55                             default_wt_format)
56    scenario['repo_is_remote'] = True
57    scenario['vfs_transport_factory'] = remote_backing_server
58    result.append((default_wt_format.__class__.__name__ + ',remote', scenario))
59    return result
60
61
62def make_scenario(transport_server, transport_readonly_server,
63                  workingtree_format):
64    return {
65        "transport_server": transport_server,
66        "transport_readonly_server": transport_readonly_server,
67        "bzrdir_format": workingtree_format._matchingcontroldir,
68        "workingtree_format": workingtree_format,
69        }
70
71
72def wt_scenarios():
73    """Returns the scenarios for all registered working trees.
74
75    This can used by plugins that want to define tests against these working
76    trees.
77    """
78    scenarios = make_scenarios(
79        tests.default_transport,
80        # None here will cause a readonly decorator to be created
81        # by the TestCaseWithTransport.get_readonly_transport method.
82        None,
83        workingtree.format_registry._get_all()
84        )
85    return scenarios
86
87
88class TestCaseWithWorkingTree(per_controldir.TestCaseWithControlDir):
89
90    def make_branch_and_tree(self, relpath, format=None):
91        made_control = self.make_controldir(relpath, format=format)
92        made_control.create_repository()
93        b = made_control.create_branch()
94        if getattr(self, 'repo_is_remote', False):
95            # If the repo is remote, then we just create a local lightweight
96            # checkout
97            # XXX: This duplicates a lot of Branch.create_checkout, but we know
98            #      we want a) lightweight, and b) a specific WT format. We also
99            #      know that nothing should already exist, etc.
100            t = transport.get_transport(relpath)
101            t.ensure_base()
102            bzrdir_format = self.workingtree_format.get_controldir_for_branch()
103            wt_dir = bzrdir_format.initialize_on_transport(t)
104            branch_ref = wt_dir.set_branch_reference(b)
105            wt = wt_dir.create_workingtree(None, from_branch=branch_ref)
106        else:
107            wt = self.workingtree_format.initialize(made_control)
108        return wt
109
110    def make_branch_builder(self, relpath, format=None):
111        if format is None:
112            format = self.workingtree_format.get_controldir_for_branch()
113        builder = branchbuilder.BranchBuilder(self.get_transport(relpath),
114                                              format=format)
115        return builder
116
117
118def load_tests(loader, standard_tests, pattern):
119    test_names = [
120        'add_reference',
121        'add',
122        'annotate_iter',
123        'basis_inventory',
124        'basis_tree',
125        'break_lock',
126        'canonical_path',
127        'changes_from',
128        'check',
129        'check_state',
130        'content_filters',
131        'commit',
132        'eol_conversion',
133        'executable',
134        'flush',
135        'get_file_mtime',
136        'get_parent_ids',
137        'inv',
138        'is_control_filename',
139        'is_ignored',
140        'locking',
141        'merge_from_branch',
142        'mkdir',
143        'move',
144        'nested_specifics',
145        'parents',
146        'paths2ids',
147        'pull',
148        'put_file',
149        'readonly',
150        'read_working_inventory',
151        'remove',
152        'rename_one',
153        'revision_tree',
154        'set_root_id',
155        'shelf_manager',
156        'smart_add',
157        'symlinks',
158        'transform',
159        'uncommit',
160        'unversion',
161        'views',
162        'walkdirs',
163        'workingtree',
164        ]
165    test_workingtree_implementations = [
166        'breezy.tests.per_workingtree.test_' + name for
167        name in test_names]
168
169    scenarios = wt_scenarios()
170
171    # add the tests for the sub modules
172    return tests.multiply_tests(
173        loader.loadTestsFromModuleNames(test_workingtree_implementations),
174        scenarios, standard_tests)
175
176
177class TestWtScenarios(tests.TestCase):
178
179    def test_protect_wt_scenarios(self):
180        # Just make sure we don't accidentally delete the helper again
181        scenarios = wt_scenarios()
182