/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
7015.1.3 by Martin
Tweak copyright headers
1
# Copyright (C) 2005-2012, 2016 Canonical Ltd
2
# Copyright (C) 2017-2018 Breezy developers
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
3
#
750 by Martin Pool
- stubbed-out tests for python plugins
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
8
#
750 by Martin Pool
- stubbed-out tests for python plugins
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
13
#
750 by Martin Pool
- stubbed-out tests for python plugins
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
750 by Martin Pool
- stubbed-out tests for python plugins
17
18
"""Tests for plugins"""
19
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
20
import importlib
2967.4.5 by Daniel Watkins
Added test for badly-named plugins.
21
import logging
1185.16.83 by mbp at sourcefrog
- notes on testability of plugins
22
import os
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
23
import sys
7015.1.1 by Martin
Switch to compatible means of creating a module
24
import types
750 by Martin Pool
- stubbed-out tests for python plugins
25
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
26
import breezy
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
27
from .. import (
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
28
    osutils,
29
    plugin,
30
    tests,
31
    )
7236.3.4 by Jelmer Vernooij
Add tests.
32
from ..tests.features import pkg_resources_feature
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
33
from ..sixish import (
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
34
    StringIO,
35
    viewkeys,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
36
    )
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
37
1185.16.83 by mbp at sourcefrog
- notes on testability of plugins
38
1492 by Robert Collins
Support decoration of commands.
39
# TODO: Write a test for plugin decoration of commands.
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
40
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
41
invalidate_caches = getattr(importlib, "invalidate_caches", lambda: None)
42
43
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
44
class BaseTestPlugins(tests.TestCaseInTempDir):
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
45
    """TestCase that isolates plugin imports and cleans up on completion."""
46
47
    def setUp(self):
48
        super(BaseTestPlugins, self).setUp()
49
        self.module_name = "breezy.testingplugins"
50
        self.module_prefix = self.module_name + "."
7015.1.1 by Martin
Switch to compatible means of creating a module
51
        self.module = types.ModuleType(self.module_name)
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
52
53
        self.overrideAttr(plugin, "_MODULE_PREFIX", self.module_prefix)
54
        self.overrideAttr(breezy, "testingplugins", self.module)
55
56
        sys.modules[self.module_name] = self.module
57
        self.addCleanup(self._unregister_all)
58
        self.addCleanup(self._unregister_finder)
59
60
        invalidate_caches()
61
62
    def reset(self):
63
        """Remove all global testing state and clean up module."""
64
        # GZ 2017-06-02: Ideally don't do this, write new test or generate
65
        # bytecode by other mechanism.
66
        self.log("resetting plugin testing context")
67
        self._unregister_all()
68
        self._unregister_finder()
69
        sys.modules[self.module_name] = self.module
70
        for name in list(self.module.__dict__):
71
            if name[:2] != '__':
72
                delattr(self.module, name)
73
        invalidate_caches()
74
        self.plugins = None
75
76
    def update_module_paths(self, paths):
77
        paths = plugin.extend_path(paths, self.module_name)
78
        self.module.__path__ = paths
79
        self.log("using %r", paths)
80
        return paths
81
82
    def load_with_paths(self, paths):
83
        self.log("loading plugins!")
84
        plugin.load_plugins(self.update_module_paths(paths), state=self)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
85
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
86
    def create_plugin(self, name, source=None, dir='.', file_name=None):
87
        if source is None:
88
            source = '''\
89
"""This is the doc for %s"""
90
''' % (name)
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
91
        if file_name is None:
92
            file_name = name + '.py'
93
        # 'source' must not fail to load
5086.1.7 by Vincent Ladeuil
Cleaner fix for bug #411413.
94
        path = osutils.pathjoin(dir, file_name)
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
95
        with open(path, 'w') as f:
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
96
            f.write(source + '\n')
97
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
98
    def create_plugin_package(self, name, dir=None, source=None):
99
        if dir is None:
100
            dir = name
101
        if source is None:
102
            source = '''\
103
"""This is the doc for %s"""
104
dir_source = '%s'
105
''' % (name, dir)
106
        os.makedirs(dir)
107
        self.create_plugin(name, source, dir,
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
108
                           file_name='__init__.py')
109
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
110
    def promote_cache(self, directory):
111
        """Move bytecode files out of __pycache__ in given directory."""
112
        cache_dir = os.path.join(directory, '__pycache__')
113
        if os.path.isdir(cache_dir):
114
            for name in os.listdir(cache_dir):
115
                magicless_name = '.'.join(name.split('.')[0::name.count('.')])
116
                rel = osutils.relpath(self.test_dir, cache_dir)
117
                self.log("moving %s in %s to %s", name, rel, magicless_name)
118
                os.rename(os.path.join(cache_dir, name),
7143.15.2 by Jelmer Vernooij
Run autopep8.
119
                          os.path.join(directory, magicless_name))
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
120
121
    def _unregister_finder(self):
122
        """Removes any test copies of _PluginsAtFinder from sys.meta_path."""
123
        idx = len(sys.meta_path)
124
        while idx:
125
            idx -= 1
126
            finder = sys.meta_path[idx]
127
            if getattr(finder, "prefix", "") == self.module_prefix:
128
                self.log("removed %r from sys.meta_path", finder)
129
                sys.meta_path.pop(idx)
130
131
    def _unregister_all(self):
132
        """Remove all plugins in the test namespace from sys.modules."""
133
        for name in list(sys.modules):
134
            if name.startswith(self.module_prefix) or name == self.module_name:
135
                self.log("removed %s from sys.modules", name)
136
                del sys.modules[name]
137
138
    def assertPluginModules(self, plugin_dict):
139
        self.assertEqual(
140
            dict((k[len(self.module_prefix):], sys.modules[k])
7143.15.2 by Jelmer Vernooij
Run autopep8.
141
                 for k in sys.modules if k.startswith(self.module_prefix)),
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
142
            plugin_dict)
5268.6.1 by Vincent Ladeuil
Drive-by fix of the submodule leak.
143
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
144
    def assertPluginUnknown(self, name):
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
145
        self.assertTrue(getattr(self.module, name, None) is None)
146
        self.assertFalse(self.module_prefix + name in sys.modules)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
147
148
    def assertPluginKnown(self, name):
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
149
        self.assertTrue(getattr(self.module, name, None) is not None)
150
        self.assertTrue(self.module_prefix + name in sys.modules)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
151
152
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
153
class TestLoadingPlugins(BaseTestPlugins):
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
154
155
    activeattributes = {}
156
157
    def test_plugins_with_the_same_name_are_not_loaded(self):
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
158
        # This test tests that having two plugins in different directories does
159
        # not result in both being loaded when they have the same name.  get a
160
        # file name we can use which is also a valid attribute for accessing in
161
        # activeattributes. - we cannot give import parameters.
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
162
        tempattribute = "0"
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
163
        self.assertFalse(tempattribute in self.activeattributes)
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
164
        # set a place for the plugins to record their loading, and at the same
165
        # time validate that the location the plugins should record to is
166
        # valid and correct.
7143.15.2 by Jelmer Vernooij
Run autopep8.
167
        self.__class__.activeattributes[tempattribute] = []
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
168
        self.assertTrue(tempattribute in self.activeattributes)
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
169
        # create two plugin directories
170
        os.mkdir('first')
171
        os.mkdir('second')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
172
        # write a plugin that will record when its loaded in the
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
173
        # tempattribute list.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
174
        template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
175
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
176
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
177
        with open(os.path.join('first', 'plugin.py'), 'w') as outfile:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
178
            outfile.write(template % (tempattribute, 'first'))
179
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
180
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
181
        with open(os.path.join('second', 'plugin.py'), 'w') as outfile:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
182
            outfile.write(template % (tempattribute, 'second'))
183
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
184
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
185
        try:
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
186
            self.load_with_paths(['first', 'second'])
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
187
            self.assertEqual(['first'], self.activeattributes[tempattribute])
188
        finally:
189
            del self.activeattributes[tempattribute]
190
191
    def test_plugins_from_different_dirs_can_demand_load(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
192
        self.assertFalse('breezy.plugins.pluginone' in sys.modules)
193
        self.assertFalse('breezy.plugins.plugintwo' in sys.modules)
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
194
        # This test tests that having two plugins in different
195
        # directories with different names allows them both to be loaded, when
196
        # we do a direct import statement.
197
        # Determine a file name we can use which is also a valid attribute
198
        # for accessing in activeattributes. - we cannot give import parameters.
199
        tempattribute = "different-dirs"
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
200
        self.assertFalse(tempattribute in self.activeattributes)
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
201
        # set a place for the plugins to record their loading, and at the same
202
        # time validate that the location the plugins should record to is
203
        # valid and correct.
7143.15.2 by Jelmer Vernooij
Run autopep8.
204
        breezy.tests.test_plugins.TestLoadingPlugins.activeattributes[tempattribute] = [
205
            ]
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
206
        self.assertTrue(tempattribute in self.activeattributes)
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
207
        # create two plugin directories
208
        os.mkdir('first')
209
        os.mkdir('second')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
210
        # write plugins that will record when they are loaded in the
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
211
        # tempattribute list.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
212
        template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
213
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
214
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
215
        with open(os.path.join('first', 'pluginone.py'), 'w') as outfile:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
216
            outfile.write(template % (tempattribute, 'first'))
217
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
218
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
219
        with open(os.path.join('second', 'plugintwo.py'), 'w') as outfile:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
220
            outfile.write(template % (tempattribute, 'second'))
221
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
222
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
223
        try:
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
224
            self.assertPluginUnknown('pluginone')
225
            self.assertPluginUnknown('plugintwo')
226
            self.update_module_paths(['first', 'second'])
227
            exec("import %spluginone" % self.module_prefix)
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
228
            self.assertEqual(['first'], self.activeattributes[tempattribute])
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
229
            exec("import %splugintwo" % self.module_prefix)
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
230
            self.assertEqual(['first', 'second'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
231
                             self.activeattributes[tempattribute])
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
232
        finally:
233
            del self.activeattributes[tempattribute]
1516 by Robert Collins
* bzrlib.plugin.all_plugins has been changed from an attribute to a
234
2652.2.1 by Blake Winton
Add a test for BZR_PLUGIN_PATH, and code and another test to allow BZR_PLUGIN_PATH to contain trailing slashes.
235
    def test_plugins_can_load_from_directory_with_trailing_slash(self):
236
        # This test tests that a plugin can load from a directory when the
237
        # directory in the path has a trailing slash.
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
238
        # check the plugin is not loaded already
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
239
        self.assertPluginUnknown('ts_plugin')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
240
        tempattribute = "trailing-slash"
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
241
        self.assertFalse(tempattribute in self.activeattributes)
2652.2.3 by Blake Winton
Understand the code and comments of the test, instead of just cargo-culting them.
242
        # set a place for the plugin to record its loading, and at the same
243
        # time validate that the location the plugin should record to is
2652.2.1 by Blake Winton
Add a test for BZR_PLUGIN_PATH, and code and another test to allow BZR_PLUGIN_PATH to contain trailing slashes.
244
        # valid and correct.
7143.15.2 by Jelmer Vernooij
Run autopep8.
245
        breezy.tests.test_plugins.TestLoadingPlugins.activeattributes[tempattribute] = [
246
            ]
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
247
        self.assertTrue(tempattribute in self.activeattributes)
2652.2.3 by Blake Winton
Understand the code and comments of the test, instead of just cargo-culting them.
248
        # create a directory for the plugin
249
        os.mkdir('plugin_test')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
250
        # write a plugin that will record when its loaded in the
2652.2.1 by Blake Winton
Add a test for BZR_PLUGIN_PATH, and code and another test to allow BZR_PLUGIN_PATH to contain trailing slashes.
251
        # tempattribute list.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
252
        template = ("from breezy.tests.test_plugins import TestLoadingPlugins\n"
2652.2.1 by Blake Winton
Add a test for BZR_PLUGIN_PATH, and code and another test to allow BZR_PLUGIN_PATH to contain trailing slashes.
253
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
254
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
255
        with open(os.path.join('plugin_test', 'ts_plugin.py'), 'w') as outfile:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
256
            outfile.write(template % (tempattribute, 'plugin'))
2911.6.4 by Blake Winton
Fix test failures
257
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
258
2652.2.1 by Blake Winton
Add a test for BZR_PLUGIN_PATH, and code and another test to allow BZR_PLUGIN_PATH to contain trailing slashes.
259
        try:
7143.15.2 by Jelmer Vernooij
Run autopep8.
260
            self.load_with_paths(['plugin_test' + os.sep])
2652.2.3 by Blake Winton
Understand the code and comments of the test, instead of just cargo-culting them.
261
            self.assertEqual(['plugin'], self.activeattributes[tempattribute])
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
262
            self.assertPluginKnown('ts_plugin')
2652.2.1 by Blake Winton
Add a test for BZR_PLUGIN_PATH, and code and another test to allow BZR_PLUGIN_PATH to contain trailing slashes.
263
        finally:
264
            del self.activeattributes[tempattribute]
265
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
266
    def load_and_capture(self, name):
267
        """Load plugins from '.' capturing the output.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
268
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
269
        :param name: The name of the plugin.
270
        :return: A string with the log from the plugin loading call.
271
        """
2967.4.5 by Daniel Watkins
Added test for badly-named plugins.
272
        # Capture output
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
273
        stream = StringIO()
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
274
        try:
275
            handler = logging.StreamHandler(stream)
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
276
            log = logging.getLogger('brz')
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
277
            log.addHandler(handler)
278
            try:
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
279
                self.load_with_paths(['.'])
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
280
            finally:
281
                # Stop capturing output
282
                handler.flush()
283
                handler.close()
284
                log.removeHandler(handler)
285
            return stream.getvalue()
286
        finally:
287
            stream.close()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
288
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
289
    def test_plugin_with_bad_api_version_reports(self):
5616.7.3 by Martin Pool
Put plugin warnings into both the apport and plain crash report
290
        """Try loading a plugin that requests an unsupported api.
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
291
5616.7.12 by Martin Pool
Comment correction
292
        Observe that it records the problem but doesn't complain on stderr.
5616.7.7 by Martin Pool
Paper over test global state dependency
293
294
        See https://bugs.launchpad.net/bzr/+bug/704195
5616.7.3 by Martin Pool
Put plugin warnings into both the apport and plain crash report
295
        """
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
296
        name = 'wants100.py'
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
297
        with open(name, 'w') as f:
6672.1.2 by Jelmer Vernooij
Remove breezy.api.
298
            f.write("import breezy\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
299
                    "from breezy.errors import IncompatibleVersion\n"
300
                    "raise IncompatibleVersion(breezy, [(1, 0, 0)], (0, 0, 5))\n")
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
301
        log = self.load_and_capture(name)
5616.7.1 by Martin Pool
Record but don't show warnings about updated plugins
302
        self.assertNotContainsRe(log,
7143.15.2 by Jelmer Vernooij
Run autopep8.
303
                                 r"It supports breezy version")
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
304
        self.assertEqual({'wants100'}, viewkeys(self.plugin_warnings))
5616.7.1 by Martin Pool
Record but don't show warnings about updated plugins
305
        self.assertContainsRe(
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
306
            self.plugin_warnings['wants100'][0],
6672.1.2 by Jelmer Vernooij
Remove breezy.api.
307
            r"It supports breezy version")
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
308
309
    def test_plugin_with_bad_name_does_not_load(self):
310
        # The file name here invalid for a python module.
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
311
        name = 'brz-bad plugin-name..py'
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
312
        open(name, 'w').close()
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
313
        log = self.load_and_capture(name)
314
        self.assertContainsRe(log,
7143.15.2 by Jelmer Vernooij
Run autopep8.
315
                              r"Unable to load 'brz-bad plugin-name\.' in '\.' as a plugin "
316
                              "because the file path isn't a valid module name; try renaming "
317
                              "it to 'bad_plugin_name_'\\.")
2967.4.5 by Daniel Watkins
Added test for badly-named plugins.
318
1516 by Robert Collins
* bzrlib.plugin.all_plugins has been changed from an attribute to a
319
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
320
class TestPlugins(BaseTestPlugins):
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
321
322
    def setup_plugin(self, source=""):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
323
        # This test tests a new plugin appears in breezy.plugin.plugins().
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
324
        # check the plugin is not loaded already
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
325
        self.assertPluginUnknown('plugin')
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
326
        # write a plugin that _cannot_ fail to load.
7143.15.2 by Jelmer Vernooij
Run autopep8.
327
        with open('plugin.py', 'w') as f:
328
            f.write(source + '\n')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
329
        self.load_with_paths(['.'])
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
330
6759.4.3 by Jelmer Vernooij
Avoid accessing global state.
331
    def test_plugin_loaded(self):
332
        self.assertPluginUnknown('plugin')
333
        self.assertIs(None, breezy.plugin.get_loaded_plugin('plugin'))
334
        self.setup_plugin()
335
        p = breezy.plugin.get_loaded_plugin('plugin')
336
        self.assertIsInstance(p, breezy.plugin.PlugIn)
337
        self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
338
6780.1.1 by Jelmer Vernooij
Check for plugin existing in sys.modules but being None.
339
    def test_plugin_loaded_disabled(self):
340
        self.assertPluginUnknown('plugin')
341
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'plugin')
342
        self.setup_plugin()
343
        self.assertIs(None, breezy.plugin.get_loaded_plugin('plugin'))
344
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
345
    def test_plugin_appears_in_plugins(self):
346
        self.setup_plugin()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
347
        self.assertPluginKnown('plugin')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
348
        p = self.plugins['plugin']
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
349
        self.assertIsInstance(p, breezy.plugin.PlugIn)
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
350
        self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
351
352
    def test_trivial_plugin_get_path(self):
353
        self.setup_plugin()
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
354
        p = self.plugins['plugin']
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
355
        plugin_path = self.test_dir + '/plugin.py'
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
356
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
357
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
358
    def test_plugin_get_path_py_not_pyc(self):
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
359
        # first import creates plugin.pyc
360
        self.setup_plugin()
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
361
        self.promote_cache(self.test_dir)
362
        self.reset()
7143.15.2 by Jelmer Vernooij
Run autopep8.
363
        self.load_with_paths(['.'])  # import plugin.pyc
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
364
        p = plugin.plugins()['plugin']
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
365
        plugin_path = self.test_dir + '/plugin.py'
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
366
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
367
368
    def test_plugin_get_path_pyc_only(self):
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
369
        # first import creates plugin.pyc (or plugin.pyo depending on __debug__)
370
        self.setup_plugin()
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
371
        os.unlink(self.test_dir + '/plugin.py')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
372
        self.promote_cache(self.test_dir)
373
        self.reset()
7143.15.2 by Jelmer Vernooij
Run autopep8.
374
        self.load_with_paths(['.'])  # import plugin.pyc (or .pyo)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
375
        p = plugin.plugins()['plugin']
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
376
        plugin_path = self.test_dir + '/plugin' + plugin.COMPILED_EXT
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
377
        self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
378
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
379
    def test_no_test_suite_gives_None_for_test_suite(self):
380
        self.setup_plugin()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
381
        p = plugin.plugins()['plugin']
382
        self.assertEqual(None, p.test_suite())
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
383
384
    def test_test_suite_gives_test_suite_result(self):
385
        source = """def test_suite(): return 'foo'"""
386
        self.setup_plugin(source)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
387
        p = plugin.plugins()['plugin']
388
        self.assertEqual('foo', p.test_suite())
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
389
3302.8.21 by Vincent Ladeuil
Fixed as per Robert's review.
390
    def test_no_load_plugin_tests_gives_None_for_load_plugin_tests(self):
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
391
        self.setup_plugin()
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
392
        loader = tests.TestUtil.TestLoader()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
393
        p = plugin.plugins()['plugin']
394
        self.assertEqual(None, p.load_plugin_tests(loader))
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
395
3302.8.21 by Vincent Ladeuil
Fixed as per Robert's review.
396
    def test_load_plugin_tests_gives_load_plugin_tests_result(self):
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
397
        source = """
6625.1.5 by Martin
Drop custom load_tests implementation and use unittest signature
398
def load_tests(loader, standard_tests, pattern):
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
399
    return 'foo'"""
400
        self.setup_plugin(source)
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
401
        loader = tests.TestUtil.TestLoader()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
402
        p = plugin.plugins()['plugin']
403
        self.assertEqual('foo', p.load_plugin_tests(loader))
404
405
    def check_version_info(self, expected, source='', name='plugin'):
406
        self.setup_plugin(source)
407
        self.assertEqual(expected, plugin.plugins()[name].version_info())
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
408
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
409
    def test_no_version_info(self):
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
410
        self.check_version_info(None)
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
411
412
    def test_with_version_info(self):
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
413
        self.check_version_info((1, 2, 3, 'dev', 4),
414
                                "version_info = (1, 2, 3, 'dev', 4)")
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
415
416
    def test_short_version_info_gets_padded(self):
417
        # the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
418
        # so we adapt it
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
419
        self.check_version_info((1, 2, 3, 'final', 0),
420
                                "version_info = (1, 2, 3)")
421
422
    def check_version(self, expected, source=None, name='plugin'):
423
        self.setup_plugin(source)
424
        self.assertEqual(expected, plugins[name].__version__)
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
425
426
    def test_no_version_info___version__(self):
427
        self.setup_plugin()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
428
        plugin = breezy.plugin.plugins()['plugin']
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
429
        self.assertEqual("unknown", plugin.__version__)
430
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
431
    def test_str__version__with_version_info(self):
432
        self.setup_plugin("version_info = '1.2.3'")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
433
        plugin = breezy.plugin.plugins()['plugin']
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
434
        self.assertEqual("1.2.3", plugin.__version__)
435
436
    def test_noniterable__version__with_version_info(self):
437
        self.setup_plugin("version_info = (1)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
438
        plugin = breezy.plugin.plugins()['plugin']
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
439
        self.assertEqual("1", plugin.__version__)
440
441
    def test_1__version__with_version_info(self):
442
        self.setup_plugin("version_info = (1,)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
443
        plugin = breezy.plugin.plugins()['plugin']
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
444
        self.assertEqual("1", plugin.__version__)
445
446
    def test_1_2__version__with_version_info(self):
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
447
        self.setup_plugin("version_info = (1, 2)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
448
        plugin = breezy.plugin.plugins()['plugin']
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
449
        self.assertEqual("1.2", plugin.__version__)
450
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
451
    def test_1_2_3__version__with_version_info(self):
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
452
        self.setup_plugin("version_info = (1, 2, 3)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
453
        plugin = breezy.plugin.plugins()['plugin']
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
454
        self.assertEqual("1.2.3", plugin.__version__)
455
456
    def test_candidate__version__with_version_info(self):
3777.6.4 by Marius Kruger
fix tests
457
        self.setup_plugin("version_info = (1, 2, 3, 'candidate', 1)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
458
        plugin = breezy.plugin.plugins()['plugin']
3777.6.4 by Marius Kruger
fix tests
459
        self.assertEqual("1.2.3rc1", plugin.__version__)
460
461
    def test_dev__version__with_version_info(self):
462
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 0)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
463
        plugin = breezy.plugin.plugins()['plugin']
3777.6.4 by Marius Kruger
fix tests
464
        self.assertEqual("1.2.3dev", plugin.__version__)
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
465
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
466
    def test_dev_fallback__version__with_version_info(self):
467
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
468
        plugin = breezy.plugin.plugins()['plugin']
4634.50.6 by John Arbash Meinel
Handle a plugin fallback versioning issue.
469
        self.assertEqual("1.2.3dev4", plugin.__version__)
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
470
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
471
    def test_final__version__with_version_info(self):
3777.6.4 by Marius Kruger
fix tests
472
        self.setup_plugin("version_info = (1, 2, 3, 'final', 0)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
473
        plugin = breezy.plugin.plugins()['plugin']
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
474
        self.assertEqual("1.2.3", plugin.__version__)
475
4634.50.6 by John Arbash Meinel
Handle a plugin fallback versioning issue.
476
    def test_final_fallback__version__with_version_info(self):
477
        self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
478
        plugin = breezy.plugin.plugins()['plugin']
5851.2.2 by Martin Pool
Format plugin version as 1.2.3.2 not 1.2.3.final.2
479
        self.assertEqual("1.2.3.2", plugin.__version__)
4634.50.6 by John Arbash Meinel
Handle a plugin fallback versioning issue.
480
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
481
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
482
class TestHelpIndex(tests.TestCase):
483
    """Tests for the PluginsHelpIndex class."""
484
485
    def test_default_constructable(self):
486
        index = plugin.PluginsHelpIndex()
487
488
    def test_get_topics_None(self):
489
        """Searching for None returns an empty list."""
490
        index = plugin.PluginsHelpIndex()
491
        self.assertEqual([], index.get_topics(None))
492
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
493
    def test_get_topics_for_plugin(self):
494
        """Searching for plugin name gets its docstring."""
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
495
        index = plugin.PluginsHelpIndex()
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
496
        # make a new plugin here for this test, even if we're run with
497
        # --no-plugins
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
498
        self.assertFalse('breezy.plugins.demo_module' in sys.modules)
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
499
        demo_module = FakeModule('', 'breezy.plugins.demo_module')
500
        sys.modules['breezy.plugins.demo_module'] = demo_module
2457.1.1 by Robert Collins
(robertc) Fix bzr --no-plugins selftest which was broken by the help indices patch. (Robert Collins, Martin Pool)
501
        try:
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
502
            topics = index.get_topics('demo_module')
2457.1.1 by Robert Collins
(robertc) Fix bzr --no-plugins selftest which was broken by the help indices patch. (Robert Collins, Martin Pool)
503
            self.assertEqual(1, len(topics))
504
            self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
505
            self.assertEqual(demo_module, topics[0].module)
506
        finally:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
507
            del sys.modules['breezy.plugins.demo_module']
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
508
509
    def test_get_topics_no_topic(self):
510
        """Searching for something that is not a plugin returns []."""
511
        # test this by using a name that cannot be a plugin - its not
512
        # a valid python identifier.
513
        index = plugin.PluginsHelpIndex()
514
        self.assertEqual([], index.get_topics('nothing by this name'))
515
516
    def test_prefix(self):
517
        """PluginsHelpIndex has a prefix of 'plugins/'."""
518
        index = plugin.PluginsHelpIndex()
519
        self.assertEqual('plugins/', index.prefix)
520
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
521
    def test_get_plugin_topic_with_prefix(self):
522
        """Searching for plugins/demo_module returns help."""
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
523
        index = plugin.PluginsHelpIndex()
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
524
        self.assertFalse('breezy.plugins.demo_module' in sys.modules)
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
525
        demo_module = FakeModule('', 'breezy.plugins.demo_module')
526
        sys.modules['breezy.plugins.demo_module'] = demo_module
2457.1.1 by Robert Collins
(robertc) Fix bzr --no-plugins selftest which was broken by the help indices patch. (Robert Collins, Martin Pool)
527
        try:
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
528
            topics = index.get_topics('plugins/demo_module')
2457.1.1 by Robert Collins
(robertc) Fix bzr --no-plugins selftest which was broken by the help indices patch. (Robert Collins, Martin Pool)
529
            self.assertEqual(1, len(topics))
530
            self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
531
            self.assertEqual(demo_module, topics[0].module)
532
        finally:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
533
            del sys.modules['breezy.plugins.demo_module']
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
534
535
536
class FakeModule(object):
537
    """A fake module to test with."""
538
539
    def __init__(self, doc, name):
540
        self.__doc__ = doc
541
        self.__name__ = name
542
543
544
class TestModuleHelpTopic(tests.TestCase):
545
    """Tests for the ModuleHelpTopic class."""
546
547
    def test_contruct(self):
548
        """Construction takes the module to document."""
549
        mod = FakeModule('foo', 'foo')
550
        topic = plugin.ModuleHelpTopic(mod)
551
        self.assertEqual(mod, topic.module)
552
553
    def test_get_help_text_None(self):
554
        """A ModuleHelpTopic returns the docstring for get_help_text."""
555
        mod = FakeModule(None, 'demo')
556
        topic = plugin.ModuleHelpTopic(mod)
557
        self.assertEqual("Plugin 'demo' has no docstring.\n",
7143.15.2 by Jelmer Vernooij
Run autopep8.
558
                         topic.get_help_text())
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
559
560
    def test_get_help_text_no_carriage_return(self):
561
        """ModuleHelpTopic.get_help_text adds a \n if needed."""
562
        mod = FakeModule('one line of help', 'demo')
563
        topic = plugin.ModuleHelpTopic(mod)
564
        self.assertEqual("one line of help\n",
7143.15.2 by Jelmer Vernooij
Run autopep8.
565
                         topic.get_help_text())
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
566
567
    def test_get_help_text_carriage_return(self):
568
        """ModuleHelpTopic.get_help_text adds a \n if needed."""
569
        mod = FakeModule('two lines of help\nand more\n', 'demo')
570
        topic = plugin.ModuleHelpTopic(mod)
571
        self.assertEqual("two lines of help\nand more\n",
7143.15.2 by Jelmer Vernooij
Run autopep8.
572
                         topic.get_help_text())
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
573
574
    def test_get_help_text_with_additional_see_also(self):
575
        mod = FakeModule('two lines of help\nand more', 'demo')
576
        topic = plugin.ModuleHelpTopic(mod)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
577
        self.assertEqual(
578
            "two lines of help\nand more\n\n:See also: bar, foo\n",
579
            topic.get_help_text(['foo', 'bar']))
2432.1.29 by Robert Collins
Add get_help_topic to ModuleHelpTopic.
580
581
    def test_get_help_topic(self):
582
        """The help topic for a plugin is its module name."""
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
583
        mod = FakeModule('two lines of help\nand more', 'breezy.plugins.demo')
2432.1.29 by Robert Collins
Add get_help_topic to ModuleHelpTopic.
584
        topic = plugin.ModuleHelpTopic(mod)
585
        self.assertEqual('demo', topic.get_help_topic())
6059.3.6 by Vincent Ladeuil
Fix tests failing on pqm.
586
        mod = FakeModule('two lines of help\nand more',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
587
                         'breezy.plugins.foo_bar')
2432.1.29 by Robert Collins
Add get_help_topic to ModuleHelpTopic.
588
        topic = plugin.ModuleHelpTopic(mod)
589
        self.assertEqual('foo_bar', topic.get_help_topic())
3835.2.7 by Aaron Bentley
Add tests for plugins
590
591
5086.1.2 by Vincent Ladeuil
Cosmetic changes.
592
class TestEnvPluginPath(tests.TestCase):
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
593
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
594
    user = "USER"
595
    core = "CORE"
596
    site = "SITE"
7236.3.2 by Jelmer Vernooij
Fix tests.
597
    entrypoints = "ENTRYPOINTS"
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
598
599
    def check_path(self, expected_dirs, setting_dirs):
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
600
        if setting_dirs is None:
601
            del os.environ['BRZ_PLUGIN_PATH']
602
        else:
603
            os.environ['BRZ_PLUGIN_PATH'] = os.pathsep.join(setting_dirs)
604
        actual = [(p if t == 'path' else t.upper())
7143.15.2 by Jelmer Vernooij
Run autopep8.
605
                  for p, t in plugin._env_plugin_path()]
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
606
        self.assertEqual(expected_dirs, actual)
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
607
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
608
    def test_default(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
609
        self.check_path([self.user, self.core, self.entrypoints, self.site],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
610
                        None)
611
612
    def test_adhoc_policy(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
613
        self.check_path([self.user, self.core, self.site, self.entrypoints],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
614
                        ['+user', '+core', '+site'])
615
616
    def test_fallback_policy(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
617
        self.check_path([self.core, self.site, self.user, self.entrypoints],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
618
                        ['+core', '+site', '+user'])
619
620
    def test_override_policy(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
621
        self.check_path([self.user, self.site, self.core, self.entrypoints],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
622
                        ['+user', '+site', '+core'])
623
624
    def test_disable_user(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
625
        self.check_path([self.core, self.entrypoints, self.site], ['-user'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
626
627
    def test_disable_user_twice(self):
628
        # Ensures multiple removals don't left cruft
7236.3.2 by Jelmer Vernooij
Fix tests.
629
        self.check_path([self.core, self.entrypoints, self.site], ['-user', '-user'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
630
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
631
    def test_duplicates_are_removed(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
632
        self.check_path([self.user, self.core, self.entrypoints, self.site],
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
633
                        ['+user', '+user'])
634
        # And only the first reference is kept (since the later references will
5086.1.2 by Vincent Ladeuil
Cosmetic changes.
635
        # only produce '<plugin> already loaded' mutters)
7236.3.2 by Jelmer Vernooij
Fix tests.
636
        self.check_path([self.user, self.core, self.site, self.entrypoints],
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
637
                        ['+user', '+user', '+core',
638
                         '+user', '+site', '+site',
639
                         '+core'])
640
5086.1.5 by Vincent Ladeuil
Fix typo in test name.
641
    def test_disable_overrides_enable(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
642
        self.check_path([self.core, self.entrypoints, self.site], ['-user', '+user'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
643
644
    def test_disable_core(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
645
        self.check_path([self.entrypoints, self.site], ['-core'])
646
        self.check_path([self.user, self.entrypoints, self.site], ['+user', '-core'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
647
648
    def test_disable_site(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
649
        self.check_path([self.core, self.entrypoints], ['-site'])
650
        self.check_path([self.user, self.core, self.entrypoints], ['-site', '+user'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
651
652
    def test_override_site(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
653
        self.check_path(['mysite', self.user, self.core, self.entrypoints],
4628.2.3 by Vincent Ladeuil
Update doc and add NEWS entry.
654
                        ['mysite', '-site', '+user'])
7236.3.2 by Jelmer Vernooij
Fix tests.
655
        self.check_path(['mysite', self.core, self.entrypoints],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
656
                        ['mysite', '-site'])
657
658
    def test_override_core(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
659
        self.check_path(['mycore', self.user, self.site, self.entrypoints],
4628.2.3 by Vincent Ladeuil
Update doc and add NEWS entry.
660
                        ['mycore', '-core', '+user', '+site'])
7236.3.2 by Jelmer Vernooij
Fix tests.
661
        self.check_path(['mycore', self.entrypoints, self.site],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
662
                        ['mycore', '-core'])
663
664
    def test_my_plugin_only(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
665
        self.check_path(
666
            ['myplugin'],
667
            ['myplugin', '-user', '-core', '-site', '-entrypoints'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
668
669
    def test_my_plugin_first(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
670
        self.check_path(['myplugin', self.core, self.site, self.user, self.entrypoints],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
671
                        ['myplugin', '+core', '+site', '+user'])
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
672
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
673
    def test_bogus_references(self):
7236.3.2 by Jelmer Vernooij
Fix tests.
674
        self.check_path(['+foo', '-bar', self.core, self.entrypoints, self.site],
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
675
                        ['+foo', '-bar'])
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
676
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
677
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
678
class TestDisablePlugin(BaseTestPlugins):
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
679
5086.1.8 by Vincent Ladeuil
Fix warnings during autoload, add doc and a NEWS entry.
680
    def test_cannot_import(self):
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
681
        self.create_plugin_package('works')
682
        self.create_plugin_package('fails')
683
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'fails')
684
        self.update_module_paths(["."])
685
        import breezy.testingplugins.works as works
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
686
        try:
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
687
            import breezy.testingplugins.fails as fails
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
688
        except ImportError:
689
            pass
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
690
        else:
691
            self.fail("Loaded blocked plugin: " + repr(fails))
692
        self.assertPluginModules({'fails': None, 'works': works})
693
694
    def test_partial_imports(self):
695
        self.create_plugin('good')
696
        self.create_plugin('bad')
697
        self.create_plugin_package('ugly')
698
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'bad:ugly')
699
        self.load_with_paths(['.'])
700
        self.assertEqual({'good'}, viewkeys(self.plugins))
701
        self.assertPluginModules({
702
            'good': self.plugins['good'].module,
703
            'bad': None,
704
            'ugly': None,
705
        })
706
        # Ensure there are no warnings about plugins not being imported as
707
        # the user has explictly requested they be disabled.
708
        self.assertNotContainsRe(self.get_log(), r"Unable to load plugin")
709
710
711
class TestEnvDisablePlugins(tests.TestCase):
712
713
    def _get_names(self, env_value):
714
        os.environ['BRZ_DISABLE_PLUGINS'] = env_value
715
        return plugin._env_disable_plugins()
716
717
    def test_unset(self):
718
        self.assertEqual([], plugin._env_disable_plugins())
719
720
    def test_empty(self):
721
        self.assertEqual([], self._get_names(''))
722
723
    def test_single(self):
724
        self.assertEqual(['single'], self._get_names('single'))
725
726
    def test_multi(self):
727
        expected = ['one', 'two']
728
        self.assertEqual(expected, self._get_names(os.pathsep.join(expected)))
729
730
    def test_mixed(self):
731
        value = os.pathsep.join(['valid', 'in-valid'])
732
        self.assertEqual(['valid'], self._get_names(value))
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
733
        self.assertContainsRe(
734
            self.get_log(),
735
            r"Invalid name 'in-valid' in BRZ_DISABLE_PLUGINS=" + repr(value))
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
736
737
738
class TestEnvPluginsAt(tests.TestCase):
739
740
    def _get_paths(self, env_value):
741
        os.environ['BRZ_PLUGINS_AT'] = env_value
742
        return plugin._env_plugins_at()
743
744
    def test_empty(self):
745
        self.assertEqual([], plugin._env_plugins_at())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
746
        self.assertEqual([], self._get_paths(''))
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
747
748
    def test_one_path(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
749
        self.assertEqual([('b', 'man')], self._get_paths('b@man'))
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
750
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
751
    def test_multiple(self):
752
        self.assertEqual(
753
            [('tools', 'bzr-tools'), ('p', 'play.py')],
754
            self._get_paths(os.pathsep.join(('tools@bzr-tools', 'p@play.py'))))
755
756
    def test_many_at(self):
757
        self.assertEqual(
758
            [('church', 'StMichael@Plea@Norwich')],
759
            self._get_paths('church@StMichael@Plea@Norwich'))
760
761
    def test_only_py(self):
762
        self.assertEqual([('test', './test.py')], self._get_paths('./test.py'))
763
764
    def test_only_package(self):
765
        self.assertEqual([('py', '/opt/b/py')], self._get_paths('/opt/b/py'))
766
767
    def test_bad_name(self):
768
        self.assertEqual([], self._get_paths('/usr/local/bzr-git'))
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
769
        self.assertContainsRe(
770
            self.get_log(),
771
            r"Invalid name 'bzr-git' in BRZ_PLUGINS_AT='/usr/local/bzr-git'")
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
772
773
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
774
class TestLoadPluginAt(BaseTestPlugins):
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
775
776
    def setUp(self):
777
        super(TestLoadPluginAt, self).setUp()
778
        # Create the same plugin in two directories
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
779
        self.create_plugin_package('test_foo', dir='non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
780
        # The "normal" directory, we use 'standard' instead of 'plugins' to
781
        # avoid depending on the precise naming.
782
        self.create_plugin_package('test_foo', dir='standard/test_foo')
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
783
5086.5.14 by Vincent Ladeuil
Fix bug #552922 by controlling which files can be used to load a plugin.
784
    def assertTestFooLoadedFrom(self, path):
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
785
        self.assertPluginKnown('test_foo')
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
786
        self.assertDocstring('This is the doc for test_foo',
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
787
                             self.module.test_foo)
788
        self.assertEqual(path, self.module.test_foo.dir_source)
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
789
790
    def test_regular_load(self):
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
791
        self.load_with_paths(['standard'])
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
792
        self.assertTestFooLoadedFrom('standard/test_foo')
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
793
794
    def test_import(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
795
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
796
        self.update_module_paths(['standard'])
797
        import breezy.testingplugins.test_foo
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
798
        self.assertTestFooLoadedFrom('non-standard-dir')
799
800
    def test_loading(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
801
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
802
        self.load_with_paths(['standard'])
803
        self.assertTestFooLoadedFrom('non-standard-dir')
804
805
    def test_loading_other_name(self):
806
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
807
        os.rename('standard/test_foo', 'standard/test_bar')
808
        self.load_with_paths(['standard'])
5086.5.9 by Vincent Ladeuil
More tests.
809
        self.assertTestFooLoadedFrom('non-standard-dir')
810
811
    def test_compiled_loaded(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
812
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
813
        self.load_with_paths(['standard'])
5086.5.9 by Vincent Ladeuil
More tests.
814
        self.assertTestFooLoadedFrom('non-standard-dir')
5235.1.1 by Martin
Make BZR_PLUGINS_AT tests that check filenames use a path-based assertion method rather than just string comparison
815
        self.assertIsSameRealPath('non-standard-dir/__init__.py',
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
816
                                  self.module.test_foo.__file__)
5086.5.9 by Vincent Ladeuil
More tests.
817
818
        # Try importing again now that the source has been compiled
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
819
        os.remove('non-standard-dir/__init__.py')
820
        self.promote_cache('non-standard-dir')
821
        self.reset()
822
        self.load_with_paths(['standard'])
5086.5.9 by Vincent Ladeuil
More tests.
823
        self.assertTestFooLoadedFrom('non-standard-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
824
        suffix = plugin.COMPILED_EXT
825
        self.assertIsSameRealPath('non-standard-dir/__init__' + suffix,
826
                                  self.module.test_foo.__file__)
5086.5.9 by Vincent Ladeuil
More tests.
827
828
    def test_submodule_loading(self):
829
        # We create an additional directory under the one for test_foo
830
        self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
831
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
832
        self.update_module_paths(['standard'])
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
833
        import breezy.testingplugins.test_foo  # noqa: F401
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
834
        self.assertEqual(self.module_prefix + 'test_foo',
835
                         self.module.test_foo.__package__)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
836
        import breezy.testingplugins.test_foo.test_bar  # noqa: F401
5235.1.1 by Martin
Make BZR_PLUGINS_AT tests that check filenames use a path-based assertion method rather than just string comparison
837
        self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
838
                                  self.module.test_foo.test_bar.__file__)
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
839
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
840
    def test_relative_submodule_loading(self):
841
        self.create_plugin_package('test_foo', dir='another-dir', source='''
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
842
from . import test_bar
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
843
''')
844
        # We create an additional directory under the one for test_foo
845
        self.create_plugin_package('test_bar', dir='another-dir/test_bar')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
846
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@another-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
847
        self.update_module_paths(['standard'])
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
848
        import breezy.testingplugins.test_foo  # noqa: F401
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
849
        self.assertEqual(self.module_prefix + 'test_foo',
850
                         self.module.test_foo.__package__)
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
851
        self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
852
                                  self.module.test_foo.test_bar.__file__)
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
853
5086.5.15 by Vincent Ladeuil
Fixed as per Ian's review.
854
    def test_loading_from___init__only(self):
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
855
        # We rename the existing __init__.py file to ensure that we don't load
856
        # a random file
857
        init = 'non-standard-dir/__init__.py'
858
        random = 'non-standard-dir/setup.py'
859
        os.rename(init, random)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
860
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
861
        self.load_with_paths(['standard'])
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
862
        self.assertPluginUnknown('test_foo')
5086.5.14 by Vincent Ladeuil
Fix bug #552922 by controlling which files can be used to load a plugin.
863
864
    def test_loading_from_specific_file(self):
865
        plugin_dir = 'non-standard-dir'
866
        plugin_file_name = 'iamtestfoo.py'
867
        plugin_path = osutils.pathjoin(plugin_dir, plugin_file_name)
868
        source = '''\
869
"""This is the doc for %s"""
870
dir_source = '%s'
871
''' % ('test_foo', plugin_path)
872
        self.create_plugin('test_foo', source=source,
873
                           dir=plugin_dir, file_name=plugin_file_name)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
874
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@%s' % plugin_path)
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
875
        self.load_with_paths(['standard'])
5086.5.14 by Vincent Ladeuil
Fix bug #552922 by controlling which files can be used to load a plugin.
876
        self.assertTestFooLoadedFrom(plugin_path)
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
877
878
879
class TestDescribePlugins(BaseTestPlugins):
880
881
    def test_describe_plugins(self):
5616.7.11 by Martin Pool
Additional tests and fixes for refactored describe_plugins.
882
        class DummyModule(object):
883
            __doc__ = 'Hi there'
7143.15.2 by Jelmer Vernooij
Run autopep8.
884
5616.7.11 by Martin Pool
Additional tests and fixes for refactored describe_plugins.
885
        class DummyPlugin(object):
886
            __version__ = '0.1.0'
887
            module = DummyModule()
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
888
        self.plugin_warnings = {'bad': ['Failed to load (just testing)']}
889
        self.plugins = {'good': DummyPlugin()}
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
890
        self.assertEqual("""\
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
891
bad (failed to load)
892
  ** Failed to load (just testing)
893
5616.7.11 by Martin Pool
Additional tests and fixes for refactored describe_plugins.
894
good 0.1.0
895
  Hi there
896
6651.4.1 by Martin
Rewrite of the plugin module for Python 3 compat and general sanity
897
""", ''.join(plugin.describe_plugins(state=self)))
7236.3.4 by Jelmer Vernooij
Add tests.
898
899
900
class DummyPlugin(object):
901
    """Plugin."""
902
903
904
class TestLoadEnvPlugin(BaseTestPlugins):
905
906
    _test_needs_features = [pkg_resources_feature]
907
908
    def setup_plugin(self, source=""):
909
        # This test tests a new plugin appears in breezy.plugin.plugins().
910
        # check the plugin is not loaded already
911
        self.assertPluginUnknown('plugin')
912
        # write a plugin that _cannot_ fail to load.
913
        import pkg_resources
914
        d = pkg_resources.Distribution(__file__)
915
        ep = pkg_resources.EntryPoint.parse(
916
            'plugin = ' + __name__ + ':DummyPlugin', dist=d)
917
        d._ep_map = {'breezy.plugin': {'plugin': ep}}
7236.3.7 by Jelmer Vernooij
Fix tests.
918
        pkg_resources.working_set.add(d, 'plugin', replace=True)
919
        eps = list(pkg_resources.iter_entry_points('breezy.plugin'))
920
        self.assertEqual(['plugin'], [ep.name for ep in eps])
7236.3.4 by Jelmer Vernooij
Add tests.
921
        self.load_with_paths(['.'])
922
        self.addCleanup(d._ep_map.clear)
923
924
    def test_plugin_loaded(self):
925
        self.assertPluginUnknown('plugin')
926
        self.setup_plugin()
927
        p = self.plugins['plugin']
928
        self.assertIsInstance(p, breezy.plugin.PlugIn)
929
        self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
930
931
    def test_plugin_loaded_disabled(self):
932
        self.assertPluginUnknown('plugin')
933
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'plugin')
934
        self.setup_plugin()
935
        self.assertNotIn('plugin', self.plugins)