~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_plugins.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for plugins"""
18
18
 
20
20
# affects the global state of the process.  See bzrlib/plugins.py for more
21
21
# comments.
22
22
 
 
23
import logging
23
24
import os
24
25
from StringIO import StringIO
25
26
import sys
30
31
import bzrlib.plugins
31
32
import bzrlib.commands
32
33
import bzrlib.help
33
 
from bzrlib.tests import TestCase, TestCaseInTempDir
34
 
from bzrlib.osutils import pathjoin, abspath
 
34
from bzrlib.tests import (
 
35
    TestCase,
 
36
    TestCaseInTempDir,
 
37
    TestUtil,
 
38
    )
 
39
from bzrlib.osutils import pathjoin, abspath, normpath
35
40
 
36
41
 
37
42
PLUGIN_TEXT = """\
65
70
        # create two plugin directories
66
71
        os.mkdir('first')
67
72
        os.mkdir('second')
68
 
        # write a plugin that will record when its loaded in the 
 
73
        # write a plugin that will record when its loaded in the
69
74
        # tempattribute list.
70
75
        template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
71
76
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
72
 
        print >> file(os.path.join('first', 'plugin.py'), 'w'), template % (tempattribute, 'first')
73
 
        print >> file(os.path.join('second', 'plugin.py'), 'w'), template % (tempattribute, 'second')
 
77
 
 
78
        outfile = open(os.path.join('first', 'plugin.py'), 'w')
 
79
        try:
 
80
            outfile.write(template % (tempattribute, 'first'))
 
81
            outfile.write('\n')
 
82
        finally:
 
83
            outfile.close()
 
84
 
 
85
        outfile = open(os.path.join('second', 'plugin.py'), 'w')
 
86
        try:
 
87
            outfile.write(template % (tempattribute, 'second'))
 
88
            outfile.write('\n')
 
89
        finally:
 
90
            outfile.close()
 
91
 
74
92
        try:
75
93
            bzrlib.plugin.load_from_path(['first', 'second'])
76
94
            self.assertEqual(['first'], self.activeattributes[tempattribute])
77
95
        finally:
78
96
            # remove the plugin 'plugin'
79
97
            del self.activeattributes[tempattribute]
 
98
            if 'bzrlib.plugins.plugin' in sys.modules:
 
99
                del sys.modules['bzrlib.plugins.plugin']
80
100
            if getattr(bzrlib.plugins, 'plugin', None):
81
101
                del bzrlib.plugins.plugin
82
102
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
98
118
        # create two plugin directories
99
119
        os.mkdir('first')
100
120
        os.mkdir('second')
101
 
        # write plugins that will record when they are loaded in the 
 
121
        # write plugins that will record when they are loaded in the
102
122
        # tempattribute list.
103
123
        template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
104
124
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
105
 
        print >> file(os.path.join('first', 'pluginone.py'), 'w'), template % (tempattribute, 'first')
106
 
        print >> file(os.path.join('second', 'plugintwo.py'), 'w'), template % (tempattribute, 'second')
 
125
 
 
126
        outfile = open(os.path.join('first', 'pluginone.py'), 'w')
 
127
        try:
 
128
            outfile.write(template % (tempattribute, 'first'))
 
129
            outfile.write('\n')
 
130
        finally:
 
131
            outfile.close()
 
132
 
 
133
        outfile = open(os.path.join('second', 'plugintwo.py'), 'w')
 
134
        try:
 
135
            outfile.write(template % (tempattribute, 'second'))
 
136
            outfile.write('\n')
 
137
        finally:
 
138
            outfile.close()
 
139
 
107
140
        oldpath = bzrlib.plugins.__path__
108
141
        try:
109
142
            bzrlib.plugins.__path__ = ['first', 'second']
115
148
        finally:
116
149
            # remove the plugin 'plugin'
117
150
            del self.activeattributes[tempattribute]
118
 
            if getattr(bzrlib.plugins, 'plugin', None):
119
 
                del bzrlib.plugins.plugin
120
 
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
121
 
 
122
 
 
123
 
class TestAllPlugins(TestCaseInTempDir):
124
 
 
125
 
    def test_plugin_appears_in_all_plugins(self):
126
 
        # This test tests a new plugin appears in bzrlib.plugin.all_plugins().
 
151
            if getattr(bzrlib.plugins, 'pluginone', None):
 
152
                del bzrlib.plugins.pluginone
 
153
            if getattr(bzrlib.plugins, 'plugintwo', None):
 
154
                del bzrlib.plugins.plugintwo
 
155
        self.failIf(getattr(bzrlib.plugins, 'pluginone', None))
 
156
        self.failIf(getattr(bzrlib.plugins, 'plugintwo', None))
 
157
 
 
158
    def test_plugins_can_load_from_directory_with_trailing_slash(self):
 
159
        # This test tests that a plugin can load from a directory when the
 
160
        # directory in the path has a trailing slash.
 
161
        # check the plugin is not loaded already
 
162
        self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
 
163
        tempattribute = "trailing-slash"
 
164
        self.failIf(tempattribute in self.activeattributes)
 
165
        # set a place for the plugin to record its loading, and at the same
 
166
        # time validate that the location the plugin should record to is
 
167
        # valid and correct.
 
168
        bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
 
169
            [tempattribute] = []
 
170
        self.failUnless(tempattribute in self.activeattributes)
 
171
        # create a directory for the plugin
 
172
        os.mkdir('plugin_test')
 
173
        # write a plugin that will record when its loaded in the
 
174
        # tempattribute list.
 
175
        template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
 
176
                    "TestLoadingPlugins.activeattributes[%r].append('%s')\n")
 
177
 
 
178
        outfile = open(os.path.join('plugin_test', 'ts_plugin.py'), 'w')
 
179
        try:
 
180
            outfile.write(template % (tempattribute, 'plugin'))
 
181
            outfile.write('\n')
 
182
        finally:
 
183
            outfile.close()
 
184
 
 
185
        try:
 
186
            bzrlib.plugin.load_from_path(['plugin_test'+os.sep])
 
187
            self.assertEqual(['plugin'], self.activeattributes[tempattribute])
 
188
        finally:
 
189
            # remove the plugin 'plugin'
 
190
            del self.activeattributes[tempattribute]
 
191
            if getattr(bzrlib.plugins, 'ts_plugin', None):
 
192
                del bzrlib.plugins.ts_plugin
 
193
        self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
 
194
 
 
195
    def load_and_capture(self, name):
 
196
        """Load plugins from '.' capturing the output.
 
197
 
 
198
        :param name: The name of the plugin.
 
199
        :return: A string with the log from the plugin loading call.
 
200
        """
 
201
        # Capture output
 
202
        stream = StringIO()
 
203
        try:
 
204
            handler = logging.StreamHandler(stream)
 
205
            log = logging.getLogger('bzr')
 
206
            log.addHandler(handler)
 
207
            try:
 
208
                try:
 
209
                    bzrlib.plugin.load_from_path(['.'])
 
210
                finally:
 
211
                    if 'bzrlib.plugins.%s' % name in sys.modules:
 
212
                        del sys.modules['bzrlib.plugins.%s' % name]
 
213
                    if getattr(bzrlib.plugins, name, None):
 
214
                        delattr(bzrlib.plugins, name)
 
215
            finally:
 
216
                # Stop capturing output
 
217
                handler.flush()
 
218
                handler.close()
 
219
                log.removeHandler(handler)
 
220
            return stream.getvalue()
 
221
        finally:
 
222
            stream.close()
 
223
 
 
224
    def test_plugin_with_bad_api_version_reports(self):
 
225
        # This plugin asks for bzrlib api version 1.0.0, which is not supported
 
226
        # anymore.
 
227
        name = 'wants100.py'
 
228
        f = file(name, 'w')
 
229
        try:
 
230
            f.write("import bzrlib.api\n"
 
231
                "bzrlib.api.require_any_api(bzrlib, [(1, 0, 0)])\n")
 
232
        finally:
 
233
            f.close()
 
234
 
 
235
        log = self.load_and_capture(name)
 
236
        self.assertContainsRe(log,
 
237
            r"It requested API version")
 
238
 
 
239
    def test_plugin_with_bad_name_does_not_load(self):
 
240
        # The file name here invalid for a python module.
 
241
        name = 'bzr-bad plugin-name..py'
 
242
        file(name, 'w').close()
 
243
        log = self.load_and_capture(name)
 
244
        self.assertContainsRe(log,
 
245
            r"Unable to load 'bzr-bad plugin-name\.' in '\.' as a plugin "
 
246
            "because the file path isn't a valid module name; try renaming "
 
247
            "it to 'bad_plugin_name_'\.")
 
248
 
 
249
 
 
250
class TestPlugins(TestCaseInTempDir):
 
251
 
 
252
    def setup_plugin(self, source=""):
 
253
        # This test tests a new plugin appears in bzrlib.plugin.plugins().
127
254
        # check the plugin is not loaded already
128
255
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
129
256
        # write a plugin that _cannot_ fail to load.
130
 
        print >> file('plugin.py', 'w'), ""
131
 
        try:
132
 
            bzrlib.plugin.load_from_path(['.'])
133
 
            self.failUnless('plugin' in bzrlib.plugin.all_plugins())
134
 
            self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
135
 
            self.assertEqual(bzrlib.plugin.all_plugins()['plugin'],
136
 
                             bzrlib.plugins.plugin)
137
 
        finally:
138
 
            # remove the plugin 'plugin'
139
 
            if 'bzrlib.plugins.plugin' in sys.modules:
140
 
                del sys.modules['bzrlib.plugins.plugin']
141
 
            if getattr(bzrlib.plugins, 'plugin', None):
142
 
                del bzrlib.plugins.plugin
 
257
        file('plugin.py', 'w').write(source + '\n')
 
258
        self.addCleanup(self.teardown_plugin)
 
259
        bzrlib.plugin.load_from_path(['.'])
 
260
 
 
261
    def teardown_plugin(self):
 
262
        # remove the plugin 'plugin'
 
263
        if 'bzrlib.plugins.plugin' in sys.modules:
 
264
            del sys.modules['bzrlib.plugins.plugin']
 
265
        if getattr(bzrlib.plugins, 'plugin', None):
 
266
            del bzrlib.plugins.plugin
143
267
        self.failIf(getattr(bzrlib.plugins, 'plugin', None))
144
268
 
 
269
    def test_plugin_appears_in_plugins(self):
 
270
        self.setup_plugin()
 
271
        self.failUnless('plugin' in bzrlib.plugin.plugins())
 
272
        self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
 
273
        plugins = bzrlib.plugin.plugins()
 
274
        plugin = plugins['plugin']
 
275
        self.assertIsInstance(plugin, bzrlib.plugin.PlugIn)
 
276
        self.assertEqual(bzrlib.plugins.plugin, plugin.module)
 
277
 
 
278
    def test_trivial_plugin_get_path(self):
 
279
        self.setup_plugin()
 
280
        plugins = bzrlib.plugin.plugins()
 
281
        plugin = plugins['plugin']
 
282
        plugin_path = self.test_dir + '/plugin.py'
 
283
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
 
284
 
 
285
    def test_plugin_get_path_py_not_pyc(self):
 
286
        self.setup_plugin()         # after first import there will be plugin.pyc
 
287
        self.teardown_plugin()
 
288
        bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
 
289
        plugins = bzrlib.plugin.plugins()
 
290
        plugin = plugins['plugin']
 
291
        plugin_path = self.test_dir + '/plugin.py'
 
292
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
 
293
 
 
294
    def test_plugin_get_path_pyc_only(self):
 
295
        self.setup_plugin()         # after first import there will be plugin.pyc
 
296
        self.teardown_plugin()
 
297
        os.unlink(self.test_dir + '/plugin.py')
 
298
        bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
 
299
        plugins = bzrlib.plugin.plugins()
 
300
        plugin = plugins['plugin']
 
301
        if __debug__:
 
302
            plugin_path = self.test_dir + '/plugin.pyc'
 
303
        else:
 
304
            plugin_path = self.test_dir + '/plugin.pyo'
 
305
        self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
 
306
 
 
307
    def test_no_test_suite_gives_None_for_test_suite(self):
 
308
        self.setup_plugin()
 
309
        plugin = bzrlib.plugin.plugins()['plugin']
 
310
        self.assertEqual(None, plugin.test_suite())
 
311
 
 
312
    def test_test_suite_gives_test_suite_result(self):
 
313
        source = """def test_suite(): return 'foo'"""
 
314
        self.setup_plugin(source)
 
315
        plugin = bzrlib.plugin.plugins()['plugin']
 
316
        self.assertEqual('foo', plugin.test_suite())
 
317
 
 
318
    def test_no_load_plugin_tests_gives_None_for_load_plugin_tests(self):
 
319
        self.setup_plugin()
 
320
        loader = TestUtil.TestLoader()
 
321
        plugin = bzrlib.plugin.plugins()['plugin']
 
322
        self.assertEqual(None, plugin.load_plugin_tests(loader))
 
323
 
 
324
    def test_load_plugin_tests_gives_load_plugin_tests_result(self):
 
325
        source = """
 
326
def load_tests(standard_tests, module, loader):
 
327
    return 'foo'"""
 
328
        self.setup_plugin(source)
 
329
        loader = TestUtil.TestLoader()
 
330
        plugin = bzrlib.plugin.plugins()['plugin']
 
331
        self.assertEqual('foo', plugin.load_plugin_tests(loader))
 
332
 
 
333
    def test_no_version_info(self):
 
334
        self.setup_plugin()
 
335
        plugin = bzrlib.plugin.plugins()['plugin']
 
336
        self.assertEqual(None, plugin.version_info())
 
337
 
 
338
    def test_with_version_info(self):
 
339
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
 
340
        plugin = bzrlib.plugin.plugins()['plugin']
 
341
        self.assertEqual((1, 2, 3, 'dev', 4), plugin.version_info())
 
342
 
 
343
    def test_short_version_info_gets_padded(self):
 
344
        # the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
 
345
        # so we adapt it
 
346
        self.setup_plugin("version_info = (1, 2, 3)")
 
347
        plugin = bzrlib.plugin.plugins()['plugin']
 
348
        self.assertEqual((1, 2, 3, 'final', 0), plugin.version_info())
 
349
 
 
350
    def test_no_version_info___version__(self):
 
351
        self.setup_plugin()
 
352
        plugin = bzrlib.plugin.plugins()['plugin']
 
353
        self.assertEqual("unknown", plugin.__version__)
 
354
 
 
355
    def test_str__version__with_version_info(self):
 
356
        self.setup_plugin("version_info = '1.2.3'")
 
357
        plugin = bzrlib.plugin.plugins()['plugin']
 
358
        self.assertEqual("1.2.3", plugin.__version__)
 
359
 
 
360
    def test_noniterable__version__with_version_info(self):
 
361
        self.setup_plugin("version_info = (1)")
 
362
        plugin = bzrlib.plugin.plugins()['plugin']
 
363
        self.assertEqual("1", plugin.__version__)
 
364
 
 
365
    def test_1__version__with_version_info(self):
 
366
        self.setup_plugin("version_info = (1,)")
 
367
        plugin = bzrlib.plugin.plugins()['plugin']
 
368
        self.assertEqual("1", plugin.__version__)
 
369
 
 
370
    def test_1_2__version__with_version_info(self):
 
371
        self.setup_plugin("version_info = (1, 2)")
 
372
        plugin = bzrlib.plugin.plugins()['plugin']
 
373
        self.assertEqual("1.2", plugin.__version__)
 
374
 
 
375
    def test_1_2_3__version__with_version_info(self):
 
376
        self.setup_plugin("version_info = (1, 2, 3)")
 
377
        plugin = bzrlib.plugin.plugins()['plugin']
 
378
        self.assertEqual("1.2.3", plugin.__version__)
 
379
 
 
380
    def test_candidate__version__with_version_info(self):
 
381
        self.setup_plugin("version_info = (1, 2, 3, 'candidate', 1)")
 
382
        plugin = bzrlib.plugin.plugins()['plugin']
 
383
        self.assertEqual("1.2.3rc1", plugin.__version__)
 
384
 
 
385
    def test_dev__version__with_version_info(self):
 
386
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 0)")
 
387
        plugin = bzrlib.plugin.plugins()['plugin']
 
388
        self.assertEqual("1.2.3dev", plugin.__version__)
 
389
 
 
390
    def test_dev_fallback__version__with_version_info(self):
 
391
        self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
 
392
        plugin = bzrlib.plugin.plugins()['plugin']
 
393
        self.assertEqual("1.2.3dev4", plugin.__version__)
 
394
 
 
395
    def test_final__version__with_version_info(self):
 
396
        self.setup_plugin("version_info = (1, 2, 3, 'final', 0)")
 
397
        plugin = bzrlib.plugin.plugins()['plugin']
 
398
        self.assertEqual("1.2.3", plugin.__version__)
 
399
 
 
400
    def test_final_fallback__version__with_version_info(self):
 
401
        self.setup_plugin("version_info = (1, 2, 3, 'final', 2)")
 
402
        plugin = bzrlib.plugin.plugins()['plugin']
 
403
        self.assertEqual("1.2.3.final.2", plugin.__version__)
 
404
 
145
405
 
146
406
class TestPluginHelp(TestCaseInTempDir):
147
407
 
148
408
    def split_help_commands(self):
149
409
        help = {}
150
410
        current = None
151
 
        for line in self.capture('help commands').splitlines():
 
411
        out, err = self.run_bzr('--no-plugins help commands')
 
412
        for line in out.splitlines():
152
413
            if not line.startswith(' '):
153
414
                current = line.split()[0]
154
415
            help[current] = help.get(current, '') + line
167
428
                # some commands have no help
168
429
                pass
169
430
            else:
170
 
                self.assertNotContainsRe(help, 'From plugin "[^"]*"')
 
431
                self.assertNotContainsRe(help, 'plugin "[^"]*"')
171
432
 
172
433
            if cmd_name in help_commands.keys():
173
434
                # some commands are hidden
174
435
                help = help_commands[cmd_name]
175
 
                self.assertNotContainsRe(help, 'From plugin "[^"]*"')
 
436
                self.assertNotContainsRe(help, 'plugin "[^"]*"')
176
437
 
177
438
    def test_plugin_help_shows_plugin(self):
178
439
        # Create a test plugin
185
446
            # Check its help
186
447
            bzrlib.plugin.load_from_path(['plugin_test'])
187
448
            bzrlib.commands.register_command( bzrlib.plugins.myplug.cmd_myplug)
188
 
            help = self.capture('help myplug')
189
 
            self.assertContainsRe(help, 'From plugin "myplug"')
 
449
            help = self.run_bzr('help myplug')[0]
 
450
            self.assertContainsRe(help, 'plugin "myplug"')
190
451
            help = self.split_help_commands()['myplug']
191
452
            self.assertContainsRe(help, '\[myplug\]')
192
453
        finally:
193
454
            # unregister command
194
 
            if bzrlib.commands.plugin_cmds.get('myplug', None):
195
 
                del bzrlib.commands.plugin_cmds['myplug']
 
455
            if 'myplug' in bzrlib.commands.plugin_cmds:
 
456
                bzrlib.commands.plugin_cmds.remove('myplug')
196
457
            # remove the plugin 'myplug'
197
458
            if getattr(bzrlib.plugins, 'myplug', None):
198
459
                delattr(bzrlib.plugins, 'myplug')
199
460
 
200
461
 
201
 
class TestPluginFromZip(TestCaseInTempDir):
202
 
 
203
 
    def make_zipped_plugin(self, zip_name, filename):
204
 
        z = zipfile.ZipFile(zip_name, 'w')
205
 
        z.writestr(filename, PLUGIN_TEXT)
206
 
        z.close()
207
 
 
208
 
    def check_plugin_load(self, zip_name, plugin_name):
209
 
        self.assertFalse(plugin_name in dir(bzrlib.plugins),
210
 
                         'Plugin already loaded')
211
 
        try:
212
 
            bzrlib.plugin.load_from_zip(zip_name)
213
 
            self.assertTrue(plugin_name in dir(bzrlib.plugins),
214
 
                            'Plugin is not loaded')
215
 
        finally:
216
 
            # unregister plugin
217
 
            if getattr(bzrlib.plugins, plugin_name, None):
218
 
                delattr(bzrlib.plugins, plugin_name)
219
 
 
220
 
    def test_load_module(self):
221
 
        self.make_zipped_plugin('./test.zip', 'ziplug.py')
222
 
        self.check_plugin_load('./test.zip', 'ziplug')
223
 
 
224
 
    def test_load_package(self):
225
 
        self.make_zipped_plugin('./test.zip', 'ziplug/__init__.py')
226
 
        self.check_plugin_load('./test.zip', 'ziplug')
227
 
 
228
 
 
229
462
class TestSetPluginsPath(TestCase):
230
 
    
 
463
 
231
464
    def test_set_plugins_path(self):
232
465
        """set_plugins_path should set the module __path__ correctly."""
233
466
        old_path = bzrlib.plugins.__path__
238
471
        finally:
239
472
            bzrlib.plugins.__path__ = old_path
240
473
 
 
474
    def test_set_plugins_path_with_trailing_slashes(self):
 
475
        """set_plugins_path should set the module __path__ based on
 
476
        BZR_PLUGIN_PATH after removing all trailing slashes."""
 
477
        old_path = bzrlib.plugins.__path__
 
478
        old_env = os.environ.get('BZR_PLUGIN_PATH')
 
479
        try:
 
480
            bzrlib.plugins.__path__ = []
 
481
            os.environ['BZR_PLUGIN_PATH'] = "first\\//\\" + os.pathsep + \
 
482
                "second/\\/\\/"
 
483
            bzrlib.plugin.set_plugins_path()
 
484
            # We expect our nominated paths to have all path-seps removed,
 
485
            # and this is testing only that.
 
486
            expected_path = ['first', 'second']
 
487
            self.assertEqual(expected_path,
 
488
                bzrlib.plugins.__path__[:len(expected_path)])
 
489
        finally:
 
490
            bzrlib.plugins.__path__ = old_path
 
491
            if old_env is not None:
 
492
                os.environ['BZR_PLUGIN_PATH'] = old_env
 
493
            else:
 
494
                del os.environ['BZR_PLUGIN_PATH']
 
495
 
241
496
 
242
497
class TestHelpIndex(tests.TestCase):
243
498
    """Tests for the PluginsHelpIndex class."""
345
600
        mod = FakeModule('two lines of help\nand more', 'bzrlib.plugins.foo_bar')
346
601
        topic = plugin.ModuleHelpTopic(mod)
347
602
        self.assertEqual('foo_bar', topic.get_help_topic())
 
603
 
 
604
 
 
605
def clear_plugins(test_case):
 
606
    # Save the attributes that we're about to monkey-patch.
 
607
    old_plugins_path = bzrlib.plugins.__path__
 
608
    old_loaded = plugin._loaded
 
609
    old_load_from_path = plugin.load_from_path
 
610
    # Change bzrlib.plugin to think no plugins have been loaded yet.
 
611
    bzrlib.plugins.__path__ = []
 
612
    plugin._loaded = False
 
613
    # Monkey-patch load_from_path to stop it from actually loading anything.
 
614
    def load_from_path(dirs):
 
615
        pass
 
616
    plugin.load_from_path = load_from_path
 
617
    def restore_plugins():
 
618
        bzrlib.plugins.__path__ = old_plugins_path
 
619
        plugin._loaded = old_loaded
 
620
        plugin.load_from_path = old_load_from_path
 
621
    test_case.addCleanup(restore_plugins)
 
622
 
 
623
 
 
624
class TestPluginPaths(tests.TestCase):
 
625
 
 
626
    def test_set_plugins_path_with_args(self):
 
627
        clear_plugins(self)
 
628
        plugin.set_plugins_path(['a', 'b'])
 
629
        self.assertEqual(['a', 'b'], bzrlib.plugins.__path__)
 
630
 
 
631
    def test_set_plugins_path_defaults(self):
 
632
        clear_plugins(self)
 
633
        plugin.set_plugins_path()
 
634
        self.assertEqual(plugin.get_standard_plugins_path(),
 
635
                         bzrlib.plugins.__path__)
 
636
 
 
637
    def test_get_standard_plugins_path(self):
 
638
        path = plugin.get_standard_plugins_path()
 
639
        self.assertEqual(plugin.get_default_plugin_path(), path[0])
 
640
        for directory in path:
 
641
            self.assertNotContainsRe(directory, r'\\/$')
 
642
        try:
 
643
            from distutils.sysconfig import get_python_lib
 
644
        except ImportError:
 
645
            pass
 
646
        else:
 
647
            if sys.platform != 'win32':
 
648
                python_lib = get_python_lib()
 
649
                for directory in path:
 
650
                    if directory.startswith(python_lib):
 
651
                        break
 
652
                else:
 
653
                    self.fail('No path to global plugins')
 
654
 
 
655
    def test_get_standard_plugins_path_env(self):
 
656
        os.environ['BZR_PLUGIN_PATH'] = 'foo/'
 
657
        self.assertEqual('foo', plugin.get_standard_plugins_path()[0])
 
658
 
 
659
 
 
660
class TestLoadPlugins(tests.TestCaseInTempDir):
 
661
 
 
662
    def test_load_plugins(self):
 
663
        clear_plugins(self)
 
664
        plugin.load_plugins(['.'])
 
665
        self.assertEqual(bzrlib.plugins.__path__, ['.'])
 
666
        # subsequent loads are no-ops
 
667
        plugin.load_plugins(['foo'])
 
668
        self.assertEqual(bzrlib.plugins.__path__, ['.'])
 
669
 
 
670
    def test_load_plugins_default(self):
 
671
        clear_plugins(self)
 
672
        plugin.load_plugins()
 
673
        path = plugin.get_standard_plugins_path()
 
674
        self.assertEqual(path, bzrlib.plugins.__path__)