/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2005-2012, 2016 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
750 by Martin Pool
- stubbed-out tests for python plugins
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
750 by Martin Pool
- stubbed-out tests for python plugins
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.
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
12
#
750 by Martin Pool
- stubbed-out tests for python plugins
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
750 by Martin Pool
- stubbed-out tests for python plugins
16
17
"""Tests for plugins"""
18
1185.16.83 by mbp at sourcefrog
- notes on testability of plugins
19
# XXX: There are no plugin tests at the moment because the plugin module
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
20
# affects the global state of the process.  See breezy/plugins.py for more
1185.16.83 by mbp at sourcefrog
- notes on testability of plugins
21
# comments.
22
2967.4.5 by Daniel Watkins
Added test for badly-named plugins.
23
import logging
1185.16.83 by mbp at sourcefrog
- notes on testability of plugins
24
import os
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
25
import sys
750 by Martin Pool
- stubbed-out tests for python plugins
26
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
27
import breezy
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
28
from .. import (
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
29
    errors,
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
30
    osutils,
31
    plugin,
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
32
    plugins,
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
33
    tests,
5086.1.8 by Vincent Ladeuil
Fix warnings during autoload, add doc and a NEWS entry.
34
    trace,
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
35
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
36
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
37
    BytesIO,
38
    )
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
39
1185.16.83 by mbp at sourcefrog
- notes on testability of plugins
40
1492 by Robert Collins
Support decoration of commands.
41
# 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
42
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
43
class BaseTestPlugins(tests.TestCaseInTempDir):
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
44
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
45
    def create_plugin(self, name, source=None, dir='.', file_name=None):
46
        if source is None:
47
            source = '''\
48
"""This is the doc for %s"""
49
''' % (name)
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
50
        if file_name is None:
51
            file_name = name + '.py'
52
        # 'source' must not fail to load
5086.1.7 by Vincent Ladeuil
Cleaner fix for bug #411413.
53
        path = osutils.pathjoin(dir, file_name)
54
        f = open(path, 'w')
55
        self.addCleanup(os.unlink, path)
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
56
        try:
57
            f.write(source + '\n')
58
        finally:
59
            f.close()
60
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
61
    def create_plugin_package(self, name, dir=None, source=None):
62
        if dir is None:
63
            dir = name
64
        if source is None:
65
            source = '''\
66
"""This is the doc for %s"""
67
dir_source = '%s'
68
''' % (name, dir)
69
        os.makedirs(dir)
5086.5.9 by Vincent Ladeuil
More tests.
70
        def cleanup():
71
            # Workaround lazy import random? madness
72
            osutils.rmtree(dir)
73
        self.addCleanup(cleanup)
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
74
        self.create_plugin(name, source, dir,
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
75
                           file_name='__init__.py')
76
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
77
    def _unregister_plugin(self, name):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
78
        """Remove the plugin from sys.modules and the breezy namespace."""
79
        py_name = 'breezy.plugins.%s' % name
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
80
        if py_name in sys.modules:
81
            del sys.modules[py_name]
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
82
        if getattr(breezy.plugins, name, None) is not None:
83
            delattr(breezy.plugins, name)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
84
5268.6.1 by Vincent Ladeuil
Drive-by fix of the submodule leak.
85
    def _unregister_plugin_submodule(self, plugin_name, submodule_name):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
86
        """Remove the submodule from sys.modules and the breezy namespace."""
87
        py_name = 'breezy.plugins.%s.%s' % (plugin_name, submodule_name)
5268.6.1 by Vincent Ladeuil
Drive-by fix of the submodule leak.
88
        if py_name in sys.modules:
89
            del sys.modules[py_name]
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
90
        plugin = getattr(breezy.plugins, plugin_name, None)
5268.6.3 by Vincent Ladeuil
BZR_PLUGINS_AT should use packages properly to handle relative imports.
91
        if plugin is not None:
92
            if getattr(plugin, submodule_name, None) is not None:
93
                delattr(plugin, submodule_name)
5268.6.1 by Vincent Ladeuil
Drive-by fix of the submodule leak.
94
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
95
    def assertPluginUnknown(self, name):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
96
        self.assertFalse(getattr(breezy.plugins, name, None) is not None)
97
        self.assertFalse('breezy.plugins.%s' % name in sys.modules)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
98
99
    def assertPluginKnown(self, name):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
100
        self.assertTrue(getattr(breezy.plugins, name, None) is not None)
101
        self.assertTrue('breezy.plugins.%s' % name in sys.modules)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
102
103
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
104
class TestLoadingPlugins(BaseTestPlugins):
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
105
106
    activeattributes = {}
107
108
    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
109
        # This test tests that having two plugins in different directories does
110
        # not result in both being loaded when they have the same name.  get a
111
        # file name we can use which is also a valid attribute for accessing in
112
        # activeattributes. - we cannot give import parameters.
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
113
        tempattribute = "0"
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
114
        self.assertFalse(tempattribute in self.activeattributes)
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
115
        # set a place for the plugins to record their loading, and at the same
116
        # time validate that the location the plugins should record to is
117
        # valid and correct.
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
118
        self.__class__.activeattributes [tempattribute] = []
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
119
        self.assertTrue(tempattribute in self.activeattributes)
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
120
        # create two plugin directories
121
        os.mkdir('first')
122
        os.mkdir('second')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
123
        # 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
124
        # tempattribute list.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
125
        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
126
                    "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.
127
128
        outfile = open(os.path.join('first', 'plugin.py'), 'w')
129
        try:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
130
            outfile.write(template % (tempattribute, 'first'))
131
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
132
        finally:
133
            outfile.close()
134
135
        outfile = open(os.path.join('second', 'plugin.py'), 'w')
136
        try:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
137
            outfile.write(template % (tempattribute, 'second'))
138
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
139
        finally:
140
            outfile.close()
141
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
142
        try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
143
            breezy.plugin.load_from_path(['first', 'second'])
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
144
            self.assertEqual(['first'], self.activeattributes[tempattribute])
145
        finally:
146
            # remove the plugin 'plugin'
147
            del self.activeattributes[tempattribute]
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
148
            self._unregister_plugin('plugin')
149
        self.assertPluginUnknown('plugin')
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
150
151
    def test_plugins_from_different_dirs_can_demand_load(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
152
        self.assertFalse('breezy.plugins.pluginone' in sys.modules)
153
        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
154
        # This test tests that having two plugins in different
155
        # directories with different names allows them both to be loaded, when
156
        # we do a direct import statement.
157
        # Determine a file name we can use which is also a valid attribute
158
        # for accessing in activeattributes. - we cannot give import parameters.
159
        tempattribute = "different-dirs"
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
160
        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
161
        # set a place for the plugins to record their loading, and at the same
162
        # time validate that the location the plugins should record to is
163
        # valid and correct.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
164
        breezy.tests.test_plugins.TestLoadingPlugins.activeattributes \
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
165
            [tempattribute] = []
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
166
        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
167
        # create two plugin directories
168
        os.mkdir('first')
169
        os.mkdir('second')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
170
        # 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
171
        # tempattribute list.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
172
        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
173
                    "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.
174
175
        outfile = open(os.path.join('first', 'pluginone.py'), 'w')
176
        try:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
177
            outfile.write(template % (tempattribute, 'first'))
178
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
179
        finally:
180
            outfile.close()
181
182
        outfile = open(os.path.join('second', 'plugintwo.py'), 'w')
183
        try:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
184
            outfile.write(template % (tempattribute, 'second'))
185
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
186
        finally:
187
            outfile.close()
188
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
189
        oldpath = breezy.plugins.__path__
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
190
        try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
191
            self.assertFalse('breezy.plugins.pluginone' in sys.modules)
192
            self.assertFalse('breezy.plugins.plugintwo' in sys.modules)
193
            breezy.plugins.__path__ = ['first', 'second']
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
194
            exec("import breezy.plugins.pluginone")
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
195
            self.assertEqual(['first'], self.activeattributes[tempattribute])
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
196
            exec("import breezy.plugins.plugintwo")
2256.2.2 by Robert Collins
Allow 'import bzrlib.plugins.NAME' to work when the plugin NAME has not
197
            self.assertEqual(['first', 'second'],
198
                self.activeattributes[tempattribute])
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
199
        finally:
200
            # remove the plugin 'plugin'
201
            del self.activeattributes[tempattribute]
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
202
            self._unregister_plugin('pluginone')
203
            self._unregister_plugin('plugintwo')
204
        self.assertPluginUnknown('pluginone')
205
        self.assertPluginUnknown('plugintwo')
1516 by Robert Collins
* bzrlib.plugin.all_plugins has been changed from an attribute to a
206
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.
207
    def test_plugins_can_load_from_directory_with_trailing_slash(self):
208
        # This test tests that a plugin can load from a directory when the
209
        # 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.
210
        # check the plugin is not loaded already
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
211
        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.
212
        tempattribute = "trailing-slash"
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
213
        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.
214
        # set a place for the plugin to record its loading, and at the same
215
        # 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.
216
        # valid and correct.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
217
        breezy.tests.test_plugins.TestLoadingPlugins.activeattributes \
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.
218
            [tempattribute] = []
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
219
        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.
220
        # create a directory for the plugin
221
        os.mkdir('plugin_test')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
222
        # 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.
223
        # tempattribute list.
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
224
        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.
225
                    "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.
226
227
        outfile = open(os.path.join('plugin_test', 'ts_plugin.py'), 'w')
228
        try:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
229
            outfile.write(template % (tempattribute, 'plugin'))
2911.6.4 by Blake Winton
Fix test failures
230
            outfile.write('\n')
2652.2.7 by Blake Winton
fix lines which were wider than 79 chars. Also handle files a little more safely.
231
        finally:
232
            outfile.close()
233
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.
234
        try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
235
            breezy.plugin.load_from_path(['plugin_test'+os.sep])
2652.2.3 by Blake Winton
Understand the code and comments of the test, instead of just cargo-culting them.
236
            self.assertEqual(['plugin'], self.activeattributes[tempattribute])
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.
237
        finally:
238
            del self.activeattributes[tempattribute]
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
239
            self._unregister_plugin('ts_plugin')
240
        self.assertPluginUnknown('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.
241
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
242
    def load_and_capture(self, name):
243
        """Load plugins from '.' capturing the output.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
244
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
245
        :param name: The name of the plugin.
246
        :return: A string with the log from the plugin loading call.
247
        """
2967.4.5 by Daniel Watkins
Added test for badly-named plugins.
248
        # Capture output
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
249
        stream = BytesIO()
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
250
        try:
251
            handler = logging.StreamHandler(stream)
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
252
            log = logging.getLogger('brz')
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
253
            log.addHandler(handler)
254
            try:
255
                try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
256
                    breezy.plugin.load_from_path(['.'])
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
257
                finally:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
258
                    if 'breezy.plugins.%s' % name in sys.modules:
259
                        del sys.modules['breezy.plugins.%s' % name]
260
                    if getattr(breezy.plugins, name, None):
261
                        delattr(breezy.plugins, name)
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
262
            finally:
263
                # Stop capturing output
264
                handler.flush()
265
                handler.close()
266
                log.removeHandler(handler)
267
            return stream.getvalue()
268
        finally:
269
            stream.close()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
270
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
271
    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
272
        """Try loading a plugin that requests an unsupported api.
273
        
5616.7.12 by Martin Pool
Comment correction
274
        Observe that it records the problem but doesn't complain on stderr.
5616.7.7 by Martin Pool
Paper over test global state dependency
275
276
        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
277
        """
5616.7.2 by Martin Pool
Include plugin warnings in apport crash
278
        self.overrideAttr(plugin, 'plugin_warnings', {})
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
279
        name = 'wants100.py'
280
        f = file(name, 'w')
281
        try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
282
            f.write("import breezy.api\n"
283
                "breezy.api.require_any_api(breezy, [(1, 0, 0)])\n")
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
284
        finally:
285
            f.close()
286
        log = self.load_and_capture(name)
5616.7.1 by Martin Pool
Record but don't show warnings about updated plugins
287
        self.assertNotContainsRe(log,
288
            r"It requested API version")
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
289
        self.assertEqual(
5616.7.1 by Martin Pool
Record but don't show warnings about updated plugins
290
            ['wants100'],
5616.7.2 by Martin Pool
Include plugin warnings in apport crash
291
            plugin.plugin_warnings.keys())
5616.7.1 by Martin Pool
Record but don't show warnings about updated plugins
292
        self.assertContainsRe(
5616.7.3 by Martin Pool
Put plugin warnings into both the apport and plain crash report
293
            plugin.plugin_warnings['wants100'][0],
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
294
            r"It requested API version")
295
296
    def test_plugin_with_bad_name_does_not_load(self):
297
        # The file name here invalid for a python module.
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
298
        name = 'brz-bad plugin-name..py'
3766.3.2 by Robert Collins
Fix reporting of incompatible api plugin load errors, fixing bug 279451.
299
        file(name, 'w').close()
300
        log = self.load_and_capture(name)
301
        self.assertContainsRe(log,
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
302
            r"Unable to load 'brz-bad plugin-name\.' in '\.' as a plugin "
3290.1.1 by James Westby
Strip "bzr_" from the start of the suggested plugin name.
303
            "because the file path isn't a valid module name; try renaming "
304
            "it to 'bad_plugin_name_'\.")
2967.4.5 by Daniel Watkins
Added test for badly-named plugins.
305
1516 by Robert Collins
* bzrlib.plugin.all_plugins has been changed from an attribute to a
306
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
307
class TestPlugins(BaseTestPlugins):
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
308
309
    def setup_plugin(self, source=""):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
310
        # 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
311
        # check the plugin is not loaded already
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
312
        self.assertPluginUnknown('plugin')
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
313
        # write a plugin that _cannot_ fail to load.
6437.20.1 by Wouter van Heyst
ensure files actually hit the disk under pypy
314
        with file('plugin.py', 'w') as f: f.write(source + '\n')
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
315
        self.addCleanup(self.teardown_plugin)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
316
        plugin.load_from_path(['.'])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
317
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
318
    def teardown_plugin(self):
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
319
        self._unregister_plugin('plugin')
320
        self.assertPluginUnknown('plugin')
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
321
322
    def test_plugin_appears_in_plugins(self):
323
        self.setup_plugin()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
324
        self.assertPluginKnown('plugin')
325
        p = plugin.plugins()['plugin']
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
326
        self.assertIsInstance(p, breezy.plugin.PlugIn)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
327
        self.assertEqual(p.module, plugins.plugin)
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
328
329
    def test_trivial_plugin_get_path(self):
330
        self.setup_plugin()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
331
        p = plugin.plugins()['plugin']
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
332
        plugin_path = self.test_dir + '/plugin.py'
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
333
        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
334
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
335
    def test_plugin_get_path_py_not_pyc(self):
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
336
        # first import creates plugin.pyc
337
        self.setup_plugin()
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
338
        self.teardown_plugin()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
339
        plugin.load_from_path(['.']) # import plugin.pyc
340
        p = plugin.plugins()['plugin']
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
341
        plugin_path = self.test_dir + '/plugin.py'
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
342
        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
343
344
    def test_plugin_get_path_pyc_only(self):
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
345
        # first import creates plugin.pyc (or plugin.pyo depending on __debug__)
346
        self.setup_plugin()
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
347
        self.teardown_plugin()
348
        os.unlink(self.test_dir + '/plugin.py')
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
349
        plugin.load_from_path(['.']) # import plugin.pyc (or .pyo)
350
        p = plugin.plugins()['plugin']
3193.2.1 by Alexander Belchenko
show path to plugin module as *.py instead of *.pyc if python source available
351
        if __debug__:
352
            plugin_path = self.test_dir + '/plugin.pyc'
353
        else:
354
            plugin_path = self.test_dir + '/plugin.pyo'
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
355
        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
356
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
357
    def test_no_test_suite_gives_None_for_test_suite(self):
358
        self.setup_plugin()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
359
        p = plugin.plugins()['plugin']
360
        self.assertEqual(None, p.test_suite())
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
361
362
    def test_test_suite_gives_test_suite_result(self):
363
        source = """def test_suite(): return 'foo'"""
364
        self.setup_plugin(source)
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
365
        p = plugin.plugins()['plugin']
366
        self.assertEqual('foo', p.test_suite())
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
367
3302.8.21 by Vincent Ladeuil
Fixed as per Robert's review.
368
    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.
369
        self.setup_plugin()
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
370
        loader = tests.TestUtil.TestLoader()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
371
        p = plugin.plugins()['plugin']
372
        self.assertEqual(None, p.load_plugin_tests(loader))
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
373
3302.8.21 by Vincent Ladeuil
Fixed as per Robert's review.
374
    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.
375
        source = """
6625.1.5 by Martin
Drop custom load_tests implementation and use unittest signature
376
def load_tests(loader, standard_tests, pattern):
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
377
    return 'foo'"""
378
        self.setup_plugin(source)
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
379
        loader = tests.TestUtil.TestLoader()
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
380
        p = plugin.plugins()['plugin']
381
        self.assertEqual('foo', p.load_plugin_tests(loader))
382
383
    def check_version_info(self, expected, source='', name='plugin'):
384
        self.setup_plugin(source)
385
        self.assertEqual(expected, plugin.plugins()[name].version_info())
3302.8.10 by Vincent Ladeuil
Prepare bzrlib.plugin to use the new test loader.
386
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
387
    def test_no_version_info(self):
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
388
        self.check_version_info(None)
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
389
390
    def test_with_version_info(self):
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
391
        self.check_version_info((1, 2, 3, 'dev', 4),
392
                                "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
393
394
    def test_short_version_info_gets_padded(self):
395
        # the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
396
        # so we adapt it
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
397
        self.check_version_info((1, 2, 3, 'final', 0),
398
                                "version_info = (1, 2, 3)")
399
400
    def check_version(self, expected, source=None, name='plugin'):
401
        self.setup_plugin(source)
402
        self.assertEqual(expected, plugins[name].__version__)
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
403
404
    def test_no_version_info___version__(self):
405
        self.setup_plugin()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
406
        plugin = breezy.plugin.plugins()['plugin']
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
407
        self.assertEqual("unknown", plugin.__version__)
408
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
409
    def test_str__version__with_version_info(self):
410
        self.setup_plugin("version_info = '1.2.3'")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
411
        plugin = breezy.plugin.plugins()['plugin']
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
412
        self.assertEqual("1.2.3", plugin.__version__)
413
414
    def test_noniterable__version__with_version_info(self):
415
        self.setup_plugin("version_info = (1)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
416
        plugin = breezy.plugin.plugins()['plugin']
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
417
        self.assertEqual("1", plugin.__version__)
418
419
    def test_1__version__with_version_info(self):
420
        self.setup_plugin("version_info = (1,)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
421
        plugin = breezy.plugin.plugins()['plugin']
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
422
        self.assertEqual("1", plugin.__version__)
423
424
    def test_1_2__version__with_version_info(self):
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
425
        self.setup_plugin("version_info = (1, 2)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
426
        plugin = breezy.plugin.plugins()['plugin']
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
427
        self.assertEqual("1.2", plugin.__version__)
428
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
429
    def test_1_2_3__version__with_version_info(self):
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
430
        self.setup_plugin("version_info = (1, 2, 3)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
431
        plugin = breezy.plugin.plugins()['plugin']
3777.6.5 by Marius Kruger
add 2 more tests for plugin version numbers
432
        self.assertEqual("1.2.3", plugin.__version__)
433
434
    def test_candidate__version__with_version_info(self):
3777.6.4 by Marius Kruger
fix tests
435
        self.setup_plugin("version_info = (1, 2, 3, 'candidate', 1)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
436
        plugin = breezy.plugin.plugins()['plugin']
3777.6.4 by Marius Kruger
fix tests
437
        self.assertEqual("1.2.3rc1", plugin.__version__)
438
439
    def test_dev__version__with_version_info(self):
440
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 0)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
441
        plugin = breezy.plugin.plugins()['plugin']
3777.6.4 by Marius Kruger
fix tests
442
        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
443
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
444
    def test_dev_fallback__version__with_version_info(self):
445
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
446
        plugin = breezy.plugin.plugins()['plugin']
4634.50.6 by John Arbash Meinel
Handle a plugin fallback versioning issue.
447
        self.assertEqual("1.2.3dev4", plugin.__version__)
3777.6.7 by Marius Kruger
* Can now also handle non-iteratable and string plugin versions.
448
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
449
    def test_final__version__with_version_info(self):
3777.6.4 by Marius Kruger
fix tests
450
        self.setup_plugin("version_info = (1, 2, 3, 'final', 0)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
451
        plugin = breezy.plugin.plugins()['plugin']
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
452
        self.assertEqual("1.2.3", plugin.__version__)
453
4634.50.6 by John Arbash Meinel
Handle a plugin fallback versioning issue.
454
    def test_final_fallback__version__with_version_info(self):
455
        self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
456
        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
457
        self.assertEqual("1.2.3.2", plugin.__version__)
4634.50.6 by John Arbash Meinel
Handle a plugin fallback versioning issue.
458
2762.2.1 by Robert Collins
* ``bzr plugins`` now lists the version number for each plugin in square
459
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
460
class TestPluginHelp(tests.TestCaseInTempDir):
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
461
462
    def split_help_commands(self):
463
        help = {}
464
        current = None
3908.1.1 by Andrew Bennetts
Try harder to avoid loading plugins during the test suite.
465
        out, err = self.run_bzr('--no-plugins help commands')
466
        for line in out.splitlines():
2034.1.2 by Aaron Bentley
Fix testcase
467
            if not line.startswith(' '):
468
                current = line.split()[0]
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
469
            help[current] = help.get(current, '') + line
470
471
        return help
472
473
    def test_plugin_help_builtins_unaffected(self):
474
        # Check we don't get false positives
475
        help_commands = self.split_help_commands()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
476
        for cmd_name in breezy.commands.builtin_command_names():
477
            if cmd_name in breezy.commands.plugin_command_names():
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
478
                continue
479
            try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
480
                help = breezy.commands.get_cmd_object(cmd_name).get_help_text()
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
481
            except NotImplementedError:
482
                # some commands have no help
483
                pass
484
            else:
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
485
                self.assertNotContainsRe(help, 'plugin "[^"]*"')
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
486
2432.1.12 by Robert Collins
Relocate command help onto Command.
487
            if cmd_name in help_commands.keys():
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
488
                # some commands are hidden
489
                help = help_commands[cmd_name]
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
490
                self.assertNotContainsRe(help, 'plugin "[^"]*"')
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
491
492
    def test_plugin_help_shows_plugin(self):
493
        # Create a test plugin
494
        os.mkdir('plugin_test')
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
495
        f = open(osutils.pathjoin('plugin_test', 'myplug.py'), 'w')
5086.1.2 by Vincent Ladeuil
Cosmetic changes.
496
        f.write("""\
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
497
from breezy import commands
5086.1.3 by Vincent Ladeuil
Fix imports in test_plugins.
498
class cmd_myplug(commands.Command):
5131.2.1 by Martin
Permit bzrlib to run under python -OO by explictly assigning to __doc__ for user-visible docstrings
499
    __doc__ = '''Just a simple test plugin.'''
5086.1.2 by Vincent Ladeuil
Cosmetic changes.
500
    aliases = ['mplg']
501
    def run(self):
502
        print 'Hello from my plugin'
503
504
"""
505
)
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
506
        f.close()
507
508
        try:
509
            # Check its help
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
510
            breezy.plugin.load_from_path(['plugin_test'])
511
            breezy.commands.register_command( breezy.plugins.myplug.cmd_myplug)
2530.3.4 by Martin Pool
Deprecate run_bzr_captured in favour of just run_bzr
512
            help = self.run_bzr('help myplug')[0]
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
513
            self.assertContainsRe(help, 'plugin "myplug"')
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
514
            help = self.split_help_commands()['myplug']
2034.1.4 by Aaron Bentley
Change angle brackets to square brackets
515
            self.assertContainsRe(help, '\[myplug\]')
1733.2.5 by Michael Ellerman
Show which plugin (if any) provides a command.
516
        finally:
2204.3.2 by Alexander Belchenko
cherrypicking: test_plugin_help_shows_plugin: fix cleanup after test
517
            # unregister command
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
518
            if 'myplug' in breezy.commands.plugin_cmds:
519
                breezy.commands.plugin_cmds.remove('myplug')
2204.3.2 by Alexander Belchenko
cherrypicking: test_plugin_help_shows_plugin: fix cleanup after test
520
            # remove the plugin 'myplug'
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
521
            if getattr(breezy.plugins, 'myplug', None):
522
                delattr(breezy.plugins, 'myplug')
2215.4.1 by Alexander Belchenko
Bugfix #68124: Allow plugins import from zip archives.
523
524
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
525
class TestHelpIndex(tests.TestCase):
526
    """Tests for the PluginsHelpIndex class."""
527
528
    def test_default_constructable(self):
529
        index = plugin.PluginsHelpIndex()
530
531
    def test_get_topics_None(self):
532
        """Searching for None returns an empty list."""
533
        index = plugin.PluginsHelpIndex()
534
        self.assertEqual([], index.get_topics(None))
535
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
536
    def test_get_topics_for_plugin(self):
537
        """Searching for plugin name gets its docstring."""
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
538
        index = plugin.PluginsHelpIndex()
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
539
        # make a new plugin here for this test, even if we're run with
540
        # --no-plugins
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
541
        self.assertFalse('breezy.plugins.demo_module' in sys.modules)
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
542
        demo_module = FakeModule('', 'breezy.plugins.demo_module')
543
        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)
544
        try:
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
545
            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)
546
            self.assertEqual(1, len(topics))
547
            self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
548
            self.assertEqual(demo_module, topics[0].module)
549
        finally:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
550
            del sys.modules['breezy.plugins.demo_module']
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
551
552
    def test_get_topics_no_topic(self):
553
        """Searching for something that is not a plugin returns []."""
554
        # test this by using a name that cannot be a plugin - its not
555
        # a valid python identifier.
556
        index = plugin.PluginsHelpIndex()
557
        self.assertEqual([], index.get_topics('nothing by this name'))
558
559
    def test_prefix(self):
560
        """PluginsHelpIndex has a prefix of 'plugins/'."""
561
        index = plugin.PluginsHelpIndex()
562
        self.assertEqual('plugins/', index.prefix)
563
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
564
    def test_get_plugin_topic_with_prefix(self):
565
        """Searching for plugins/demo_module returns help."""
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
566
        index = plugin.PluginsHelpIndex()
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
567
        self.assertFalse('breezy.plugins.demo_module' in sys.modules)
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
568
        demo_module = FakeModule('', 'breezy.plugins.demo_module')
569
        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)
570
        try:
2475.1.1 by Martin Pool
Rename test_plugin tests and the example module used there.
571
            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)
572
            self.assertEqual(1, len(topics))
573
            self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
574
            self.assertEqual(demo_module, topics[0].module)
575
        finally:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
576
            del sys.modules['breezy.plugins.demo_module']
2432.1.25 by Robert Collins
Return plugin module docstrings for 'bzr help plugin'.
577
578
579
class FakeModule(object):
580
    """A fake module to test with."""
581
582
    def __init__(self, doc, name):
583
        self.__doc__ = doc
584
        self.__name__ = name
585
586
587
class TestModuleHelpTopic(tests.TestCase):
588
    """Tests for the ModuleHelpTopic class."""
589
590
    def test_contruct(self):
591
        """Construction takes the module to document."""
592
        mod = FakeModule('foo', 'foo')
593
        topic = plugin.ModuleHelpTopic(mod)
594
        self.assertEqual(mod, topic.module)
595
596
    def test_get_help_text_None(self):
597
        """A ModuleHelpTopic returns the docstring for get_help_text."""
598
        mod = FakeModule(None, 'demo')
599
        topic = plugin.ModuleHelpTopic(mod)
600
        self.assertEqual("Plugin 'demo' has no docstring.\n",
601
            topic.get_help_text())
602
603
    def test_get_help_text_no_carriage_return(self):
604
        """ModuleHelpTopic.get_help_text adds a \n if needed."""
605
        mod = FakeModule('one line of help', 'demo')
606
        topic = plugin.ModuleHelpTopic(mod)
607
        self.assertEqual("one line of help\n",
608
            topic.get_help_text())
609
610
    def test_get_help_text_carriage_return(self):
611
        """ModuleHelpTopic.get_help_text adds a \n if needed."""
612
        mod = FakeModule('two lines of help\nand more\n', 'demo')
613
        topic = plugin.ModuleHelpTopic(mod)
614
        self.assertEqual("two lines of help\nand more\n",
615
            topic.get_help_text())
616
617
    def test_get_help_text_with_additional_see_also(self):
618
        mod = FakeModule('two lines of help\nand more', 'demo')
619
        topic = plugin.ModuleHelpTopic(mod)
6059.3.6 by Vincent Ladeuil
Fix tests failing on pqm.
620
        self.assertEqual("two lines of help\nand more\n\n:See also: bar, foo\n",
621
                         topic.get_help_text(['foo', 'bar']))
2432.1.29 by Robert Collins
Add get_help_topic to ModuleHelpTopic.
622
623
    def test_get_help_topic(self):
624
        """The help topic for a plugin is its module name."""
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
625
        mod = FakeModule('two lines of help\nand more', 'breezy.plugins.demo')
2432.1.29 by Robert Collins
Add get_help_topic to ModuleHelpTopic.
626
        topic = plugin.ModuleHelpTopic(mod)
627
        self.assertEqual('demo', topic.get_help_topic())
6059.3.6 by Vincent Ladeuil
Fix tests failing on pqm.
628
        mod = FakeModule('two lines of help\nand more',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
629
                         'breezy.plugins.foo_bar')
2432.1.29 by Robert Collins
Add get_help_topic to ModuleHelpTopic.
630
        topic = plugin.ModuleHelpTopic(mod)
631
        self.assertEqual('foo_bar', topic.get_help_topic())
3835.2.7 by Aaron Bentley
Add tests for plugins
632
633
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
634
class TestLoadFromPath(tests.TestCaseInTempDir):
635
636
    def setUp(self):
637
        super(TestLoadFromPath, self).setUp()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
638
        # Change breezy.plugin to think no plugins have been loaded yet.
639
        self.overrideAttr(breezy.plugins, '__path__', [])
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
640
        self.overrideAttr(plugin, '_loaded', False)
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
641
642
        # Monkey-patch load_from_path to stop it from actually loading anything.
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
643
        self.overrideAttr(plugin, 'load_from_path', lambda dirs: None)
3835.2.7 by Aaron Bentley
Add tests for plugins
644
645
    def test_set_plugins_path_with_args(self):
646
        plugin.set_plugins_path(['a', 'b'])
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
647
        self.assertEqual(['a', 'b'], breezy.plugins.__path__)
3835.2.7 by Aaron Bentley
Add tests for plugins
648
649
    def test_set_plugins_path_defaults(self):
650
        plugin.set_plugins_path()
651
        self.assertEqual(plugin.get_standard_plugins_path(),
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
652
                         breezy.plugins.__path__)
3835.2.7 by Aaron Bentley
Add tests for plugins
653
654
    def test_get_standard_plugins_path(self):
655
        path = plugin.get_standard_plugins_path()
656
        for directory in path:
4412.2.1 by Vincent Ladeuil
Fix some OSX test regressions (well actual test bugs indeed).
657
            self.assertNotContainsRe(directory, r'\\/$')
3835.2.7 by Aaron Bentley
Add tests for plugins
658
        try:
659
            from distutils.sysconfig import get_python_lib
660
        except ImportError:
661
            pass
662
        else:
663
            if sys.platform != 'win32':
664
                python_lib = get_python_lib()
665
                for directory in path:
666
                    if directory.startswith(python_lib):
667
                        break
668
                else:
669
                    self.fail('No path to global plugins')
670
671
    def test_get_standard_plugins_path_env(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
672
        self.overrideEnv('BRZ_PLUGIN_PATH', 'foo/')
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
673
        path = plugin.get_standard_plugins_path()
674
        for directory in path:
675
            self.assertNotContainsRe(directory, r'\\/$')
3835.2.7 by Aaron Bentley
Add tests for plugins
676
677
    def test_load_plugins(self):
678
        plugin.load_plugins(['.'])
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
679
        self.assertEqual(breezy.plugins.__path__, ['.'])
3835.2.7 by Aaron Bentley
Add tests for plugins
680
        # subsequent loads are no-ops
681
        plugin.load_plugins(['foo'])
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
682
        self.assertEqual(breezy.plugins.__path__, ['.'])
3835.2.7 by Aaron Bentley
Add tests for plugins
683
684
    def test_load_plugins_default(self):
685
        plugin.load_plugins()
686
        path = plugin.get_standard_plugins_path()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
687
        self.assertEqual(path, breezy.plugins.__path__)
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
688
689
5086.1.2 by Vincent Ladeuil
Cosmetic changes.
690
class TestEnvPluginPath(tests.TestCase):
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
691
692
    def setUp(self):
693
        super(TestEnvPluginPath, self).setUp()
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
694
        self.overrideAttr(plugin, 'DEFAULT_PLUGIN_PATH', None)
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
695
696
        self.user = plugin.get_user_plugin_path()
697
        self.site = plugin.get_site_plugin_path()
698
        self.core = plugin.get_core_plugin_path()
699
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
700
    def _list2paths(self, *args):
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
701
        paths = []
702
        for p in args:
703
            plugin._append_new_path(paths, p)
704
        return paths
705
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
706
    def _set_path(self, *args):
707
        path = os.pathsep.join(self._list2paths(*args))
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
708
        self.overrideEnv('BRZ_PLUGIN_PATH', path)
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
709
710
    def check_path(self, expected_dirs, setting_dirs):
711
        if setting_dirs:
712
            self._set_path(*setting_dirs)
713
        actual = plugin.get_standard_plugins_path()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
714
        self.assertEqual(self._list2paths(*expected_dirs), actual)
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
715
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
716
    def test_default(self):
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
717
        self.check_path([self.user, self.core, self.site],
718
                        None)
719
720
    def test_adhoc_policy(self):
721
        self.check_path([self.user, self.core, self.site],
722
                        ['+user', '+core', '+site'])
723
724
    def test_fallback_policy(self):
725
        self.check_path([self.core, self.site, self.user],
726
                        ['+core', '+site', '+user'])
727
728
    def test_override_policy(self):
729
        self.check_path([self.user, self.site, self.core],
730
                        ['+user', '+site', '+core'])
731
732
    def test_disable_user(self):
733
        self.check_path([self.core, self.site], ['-user'])
734
735
    def test_disable_user_twice(self):
736
        # Ensures multiple removals don't left cruft
737
        self.check_path([self.core, self.site], ['-user', '-user'])
738
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
739
    def test_duplicates_are_removed(self):
740
        self.check_path([self.user, self.core, self.site],
741
                        ['+user', '+user'])
742
        # And only the first reference is kept (since the later references will
5086.1.2 by Vincent Ladeuil
Cosmetic changes.
743
        # only produce '<plugin> already loaded' mutters)
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
744
        self.check_path([self.user, self.core, self.site],
745
                        ['+user', '+user', '+core',
746
                         '+user', '+site', '+site',
747
                         '+core'])
748
5086.1.5 by Vincent Ladeuil
Fix typo in test name.
749
    def test_disable_overrides_enable(self):
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
750
        self.check_path([self.core, self.site], ['-user', '+user'])
751
752
    def test_disable_core(self):
4628.2.3 by Vincent Ladeuil
Update doc and add NEWS entry.
753
        self.check_path([self.site], ['-core'])
754
        self.check_path([self.user, self.site], ['+user', '-core'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
755
756
    def test_disable_site(self):
4628.2.3 by Vincent Ladeuil
Update doc and add NEWS entry.
757
        self.check_path([self.core], ['-site'])
758
        self.check_path([self.user, self.core], ['-site', '+user'])
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
759
760
    def test_override_site(self):
4628.2.3 by Vincent Ladeuil
Update doc and add NEWS entry.
761
        self.check_path(['mysite', self.user, self.core],
762
                        ['mysite', '-site', '+user'])
763
        self.check_path(['mysite', self.core],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
764
                        ['mysite', '-site'])
765
766
    def test_override_core(self):
4628.2.3 by Vincent Ladeuil
Update doc and add NEWS entry.
767
        self.check_path(['mycore', self.user, self.site],
768
                        ['mycore', '-core', '+user', '+site'])
769
        self.check_path(['mycore', self.site],
4628.2.2 by Vincent Ladeuil
Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
770
                        ['mycore', '-core'])
771
772
    def test_my_plugin_only(self):
773
        self.check_path(['myplugin'], ['myplugin', '-user', '-core', '-site'])
774
775
    def test_my_plugin_first(self):
776
        self.check_path(['myplugin', self.core, self.site, self.user],
777
                        ['myplugin', '+core', '+site', '+user'])
4628.2.1 by Vincent Ladeuil
Start introducing accessors for plugin paths.
778
4628.2.5 by Vincent Ladeuil
Fixes prompted by review.
779
    def test_bogus_references(self):
780
        self.check_path(['+foo', '-bar', self.core, self.site],
781
                        ['+foo', '-bar'])
5086.1.4 by Vincent Ladeuil
Slight plugin tests rewriting.
782
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
783
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
784
class TestDisablePlugin(BaseTestPlugins):
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
785
5086.1.7 by Vincent Ladeuil
Cleaner fix for bug #411413.
786
    def setUp(self):
787
        super(TestDisablePlugin, self).setUp()
788
        self.create_plugin_package('test_foo')
789
        # Make sure we don't pollute the plugins namespace
790
        self.overrideAttr(plugins, '__path__')
791
        # Be paranoid in case a test fail
792
        self.addCleanup(self._unregister_plugin, 'test_foo')
5086.1.8 by Vincent Ladeuil
Fix warnings during autoload, add doc and a NEWS entry.
793
794
    def test_cannot_import(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
795
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'test_foo')
5086.1.10 by Vincent Ladeuil
Fixed as per review comments.
796
        plugin.set_plugins_path(['.'])
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
797
        try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
798
            import breezy.plugins.test_foo
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
799
        except ImportError:
800
            pass
5086.1.7 by Vincent Ladeuil
Cleaner fix for bug #411413.
801
        self.assertPluginUnknown('test_foo')
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
802
5086.1.9 by Vincent Ladeuil
Fix bogus helpers and add a test.
803
    def test_regular_load(self):
804
        self.overrideAttr(plugin, '_loaded', False)
805
        plugin.load_plugins(['.'])
806
        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
807
        self.assertDocstring("This is the doc for test_foo",
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
808
                             breezy.plugins.test_foo)
5086.1.9 by Vincent Ladeuil
Fix bogus helpers and add a test.
809
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
810
    def test_not_loaded(self):
5086.1.8 by Vincent Ladeuil
Fix warnings during autoload, add doc and a NEWS entry.
811
        self.warnings = []
812
        def captured_warning(*args, **kwargs):
813
            self.warnings.append((args, kwargs))
814
        self.overrideAttr(trace, 'warning', captured_warning)
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
815
        # Reset the flag that protect against double loading
5086.1.8 by Vincent Ladeuil
Fix warnings during autoload, add doc and a NEWS entry.
816
        self.overrideAttr(plugin, '_loaded', False)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
817
        self.overrideEnv('BRZ_DISABLE_PLUGINS', 'test_foo')
5086.5.4 by Vincent Ladeuil
Merge for fixes from 411413-plugin-path
818
        plugin.load_plugins(['.'])
5086.1.6 by Vincent Ladeuil
Crude fix for bug #411413.
819
        self.assertPluginUnknown('test_foo')
5086.1.8 by Vincent Ladeuil
Fix warnings during autoload, add doc and a NEWS entry.
820
        # Make sure we don't warn about the plugin ImportError since this has
821
        # been *requested* by the user.
822
        self.assertLength(0, self.warnings)
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
823
824
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
825
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
826
class TestLoadPluginAtSyntax(tests.TestCase):
827
828
    def _get_paths(self, paths):
829
        return plugin._get_specific_plugin_paths(paths)
830
831
    def test_empty(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
832
        self.assertEqual([], self._get_paths(None))
833
        self.assertEqual([], self._get_paths(''))
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
834
835
    def test_one_path(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
836
        self.assertEqual([('b', 'man')], self._get_paths('b@man'))
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
837
838
    def test_bogus_path(self):
5268.5.2 by Vincent Ladeuil
Catch the wrong path descriptions in BZR_PLUGINS_AT.
839
        # We need a '@'
840
        self.assertRaises(errors.BzrCommandError, self._get_paths, 'batman')
841
        # Too much '@' isn't good either
842
        self.assertRaises(errors.BzrCommandError, self._get_paths,
843
                          'batman@mobile@cave')
844
        # An empty description probably indicates a problem
845
        self.assertRaises(errors.BzrCommandError, self._get_paths,
846
                          os.pathsep.join(['batman@cave', '', 'robin@mobile']))
5268.5.1 by Vincent Ladeuil
Reproduce bug #591215.
847
848
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
849
class TestLoadPluginAt(BaseTestPlugins):
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
850
851
    def setUp(self):
852
        super(TestLoadPluginAt, self).setUp()
853
        # Make sure we don't pollute the plugins namespace
854
        self.overrideAttr(plugins, '__path__')
855
        # Reset the flag that protect against double loading
856
        self.overrideAttr(plugin, '_loaded', False)
857
        # Create the same plugin in two directories
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
858
        self.create_plugin_package('test_foo', dir='non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
859
        # The "normal" directory, we use 'standard' instead of 'plugins' to
860
        # avoid depending on the precise naming.
861
        self.create_plugin_package('test_foo', dir='standard/test_foo')
5268.6.1 by Vincent Ladeuil
Drive-by fix of the submodule leak.
862
        # All the tests will load the 'test_foo' plugin from various locations
863
        self.addCleanup(self._unregister_plugin, 'test_foo')
5616.7.7 by Martin Pool
Paper over test global state dependency
864
        # Unfortunately there's global cached state for the specific
865
        # registered paths.
866
        self.addCleanup(plugin.PluginImporter.reset)
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
867
5086.5.14 by Vincent Ladeuil
Fix bug #552922 by controlling which files can be used to load a plugin.
868
    def assertTestFooLoadedFrom(self, path):
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
869
        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
870
        self.assertDocstring('This is the doc for test_foo',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
871
                             breezy.plugins.test_foo)
872
        self.assertEqual(path, breezy.plugins.test_foo.dir_source)
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
873
874
    def test_regular_load(self):
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
875
        plugin.load_plugins(['standard'])
876
        self.assertTestFooLoadedFrom('standard/test_foo')
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
877
878
    def test_import(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
879
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
880
        plugin.set_plugins_path(['standard'])
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
881
        try:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
882
            import breezy.plugins.test_foo
5086.5.3 by Vincent Ladeuil
First shot at loading plugins from a specific directory.
883
        except ImportError:
884
            pass
5086.5.8 by Vincent Ladeuil
Make sure we can load from a non-standard directory name.
885
        self.assertTestFooLoadedFrom('non-standard-dir')
886
887
    def test_loading(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
888
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
889
        plugin.load_plugins(['standard'])
5086.5.9 by Vincent Ladeuil
More tests.
890
        self.assertTestFooLoadedFrom('non-standard-dir')
891
892
    def test_compiled_loaded(self):
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
893
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
894
        plugin.load_plugins(['standard'])
5086.5.9 by Vincent Ladeuil
More tests.
895
        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
896
        self.assertIsSameRealPath('non-standard-dir/__init__.py',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
897
                                  breezy.plugins.test_foo.__file__)
5086.5.9 by Vincent Ladeuil
More tests.
898
899
        # Try importing again now that the source has been compiled
900
        self._unregister_plugin('test_foo')
901
        plugin._loaded = False
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
902
        plugin.load_plugins(['standard'])
5086.5.9 by Vincent Ladeuil
More tests.
903
        self.assertTestFooLoadedFrom('non-standard-dir')
5086.5.11 by Vincent Ladeuil
Fix pqm failure.
904
        if __debug__:
905
            suffix = 'pyc'
906
        else:
907
            suffix = 'pyo'
5235.1.1 by Martin
Make BZR_PLUGINS_AT tests that check filenames use a path-based assertion method rather than just string comparison
908
        self.assertIsSameRealPath('non-standard-dir/__init__.%s' % suffix,
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
909
                                  breezy.plugins.test_foo.__file__)
5086.5.9 by Vincent Ladeuil
More tests.
910
911
    def test_submodule_loading(self):
912
        # We create an additional directory under the one for test_foo
913
        self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
5268.6.1 by Vincent Ladeuil
Drive-by fix of the submodule leak.
914
        self.addCleanup(self._unregister_plugin_submodule,
915
                        'test_foo', 'test_bar')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
916
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
917
        plugin.set_plugins_path(['standard'])
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
918
        import breezy.plugins.test_foo
919
        self.assertEqual('breezy.plugins.test_foo',
920
                         breezy.plugins.test_foo.__package__)
921
        import breezy.plugins.test_foo.test_bar
5235.1.1 by Martin
Make BZR_PLUGINS_AT tests that check filenames use a path-based assertion method rather than just string comparison
922
        self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
923
                                  breezy.plugins.test_foo.test_bar.__file__)
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
924
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
925
    def test_relative_submodule_loading(self):
926
        self.create_plugin_package('test_foo', dir='another-dir', source='''
927
import test_bar
928
''')
929
        # We create an additional directory under the one for test_foo
930
        self.create_plugin_package('test_bar', dir='another-dir/test_bar')
931
        self.addCleanup(self._unregister_plugin_submodule,
932
                        'test_foo', 'test_bar')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
933
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@another-dir')
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
934
        plugin.set_plugins_path(['standard'])
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
935
        import breezy.plugins.test_foo
936
        self.assertEqual('breezy.plugins.test_foo',
937
                         breezy.plugins.test_foo.__package__)
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
938
        self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
939
                                  breezy.plugins.test_foo.test_bar.__file__)
5268.6.2 by Vincent Ladeuil
Reproduce bug #588959.
940
5086.5.15 by Vincent Ladeuil
Fixed as per Ian's review.
941
    def test_loading_from___init__only(self):
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
942
        # We rename the existing __init__.py file to ensure that we don't load
943
        # a random file
944
        init = 'non-standard-dir/__init__.py'
945
        random = 'non-standard-dir/setup.py'
946
        os.rename(init, random)
947
        self.addCleanup(os.rename, random, init)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
948
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@non-standard-dir')
5086.5.13 by Vincent Ladeuil
Reproduce bug #552922.
949
        plugin.load_plugins(['standard'])
950
        self.assertPluginUnknown('test_foo')
5086.5.14 by Vincent Ladeuil
Fix bug #552922 by controlling which files can be used to load a plugin.
951
952
    def test_loading_from_specific_file(self):
953
        plugin_dir = 'non-standard-dir'
954
        plugin_file_name = 'iamtestfoo.py'
955
        plugin_path = osutils.pathjoin(plugin_dir, plugin_file_name)
956
        source = '''\
957
"""This is the doc for %s"""
958
dir_source = '%s'
959
''' % ('test_foo', plugin_path)
960
        self.create_plugin('test_foo', source=source,
961
                           dir=plugin_dir, file_name=plugin_file_name)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
962
        self.overrideEnv('BRZ_PLUGINS_AT', 'test_foo@%s' % plugin_path)
5086.5.14 by Vincent Ladeuil
Fix bug #552922 by controlling which files can be used to load a plugin.
963
        plugin.load_plugins(['standard'])
964
        self.assertTestFooLoadedFrom(plugin_path)
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
965
966
967
class TestDescribePlugins(BaseTestPlugins):
968
969
    def test_describe_plugins(self):
5616.7.11 by Martin Pool
Additional tests and fixes for refactored describe_plugins.
970
        class DummyModule(object):
971
            __doc__ = 'Hi there'
972
        class DummyPlugin(object):
973
            __version__ = '0.1.0'
974
            module = DummyModule()
975
        def dummy_plugins():
976
            return { 'good': DummyPlugin() }
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
977
        self.overrideAttr(plugin, 'plugin_warnings',
978
            {'bad': ['Failed to load (just testing)']})
5616.7.11 by Martin Pool
Additional tests and fixes for refactored describe_plugins.
979
        self.overrideAttr(plugin, 'plugins', dummy_plugins)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
980
        self.assertEqual("""\
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
981
bad (failed to load)
982
  ** Failed to load (just testing)
983
5616.7.11 by Martin Pool
Additional tests and fixes for refactored describe_plugins.
984
good 0.1.0
985
  Hi there
986
5616.7.10 by Martin Pool
Clean up describe_plugins to sort loaded and unloaded plugins together.
987
""", ''.join(plugin.describe_plugins()))