20
20
# affects the global state of the process. See bzrlib/plugins.py for more
23
from cStringIO import StringIO
25
from StringIO import StringIO
29
29
from bzrlib import (
36
import bzrlib.commands
38
from bzrlib.tests import (
43
from bzrlib.osutils import pathjoin, abspath, normpath
47
import bzrlib.commands
48
class cmd_myplug(bzrlib.commands.Command):
49
'''Just a simple test plugin.'''
52
print 'Hello from my plugin'
55
38
# TODO: Write a test for plugin decoration of commands.
57
class TestLoadingPlugins(TestCaseInTempDir):
40
class TestPluginMixin(object):
42
def create_plugin(self, name, source='', dir='.', file_name=None):
44
file_name = name + '.py'
45
# 'source' must not fail to load
46
path = osutils.pathjoin(dir, file_name)
48
self.addCleanup(os.unlink, path)
50
f.write(source + '\n')
54
def create_plugin_package(self, name, source='', dir='.'):
55
plugin_dir = osutils.pathjoin(dir, name)
57
self.addCleanup(osutils.rmtree, plugin_dir)
58
self.create_plugin(name, source, dir=plugin_dir,
59
file_name='__init__.py')
61
def _unregister_plugin(self, name):
62
"""Remove the plugin from sys.modules and the bzrlib namespace."""
63
py_name = 'bzrlib.plugins.%s' % name
64
if py_name in sys.modules:
65
del sys.modules[py_name]
66
if getattr(bzrlib.plugins, name, None) is not None:
67
delattr(bzrlib.plugins, name)
69
def assertPluginUnknown(self, name):
70
self.failIf(getattr(bzrlib.plugins, name, None) is not None)
71
self.failIf('bzrlib.plugins.%s' % name in sys.modules)
73
def assertPluginKnown(self, name):
74
self.failUnless(getattr(bzrlib.plugins, name, None) is not None)
75
self.failUnless('bzrlib.plugins.%s' % name in sys.modules)
78
class TestLoadingPlugins(tests.TestCaseInTempDir, TestPluginMixin):
59
80
activeattributes = {}
251
268
"it to 'bad_plugin_name_'\.")
254
class TestPlugins(TestCaseInTempDir):
271
class TestPlugins(tests.TestCaseInTempDir, TestPluginMixin):
256
273
def setup_plugin(self, source=""):
257
274
# This test tests a new plugin appears in bzrlib.plugin.plugins().
258
275
# check the plugin is not loaded already
259
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
276
self.assertPluginUnknown('plugin')
260
277
# write a plugin that _cannot_ fail to load.
261
278
file('plugin.py', 'w').write(source + '\n')
262
279
self.addCleanup(self.teardown_plugin)
263
bzrlib.plugin.load_from_path(['.'])
280
plugin.load_from_path(['.'])
265
282
def teardown_plugin(self):
266
# remove the plugin 'plugin'
267
if 'bzrlib.plugins.plugin' in sys.modules:
268
del sys.modules['bzrlib.plugins.plugin']
269
if getattr(bzrlib.plugins, 'plugin', None):
270
del bzrlib.plugins.plugin
271
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
283
self._unregister_plugin('plugin')
284
self.assertPluginUnknown('plugin')
273
286
def test_plugin_appears_in_plugins(self):
274
287
self.setup_plugin()
275
self.failUnless('plugin' in bzrlib.plugin.plugins())
276
self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
277
plugins = bzrlib.plugin.plugins()
278
plugin = plugins['plugin']
279
self.assertIsInstance(plugin, bzrlib.plugin.PlugIn)
280
self.assertEqual(bzrlib.plugins.plugin, plugin.module)
288
self.assertPluginKnown('plugin')
289
p = plugin.plugins()['plugin']
290
self.assertIsInstance(p, bzrlib.plugin.PlugIn)
291
self.assertEqual(p.module, plugins.plugin)
282
293
def test_trivial_plugin_get_path(self):
283
294
self.setup_plugin()
284
plugins = bzrlib.plugin.plugins()
285
plugin = plugins['plugin']
295
p = plugin.plugins()['plugin']
286
296
plugin_path = self.test_dir + '/plugin.py'
287
self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
297
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
289
299
def test_plugin_get_path_py_not_pyc(self):
290
self.setup_plugin() # after first import there will be plugin.pyc
300
# first import creates plugin.pyc
291
302
self.teardown_plugin()
292
bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
293
plugins = bzrlib.plugin.plugins()
294
plugin = plugins['plugin']
303
plugin.load_from_path(['.']) # import plugin.pyc
304
p = plugin.plugins()['plugin']
295
305
plugin_path = self.test_dir + '/plugin.py'
296
self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
306
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
298
308
def test_plugin_get_path_pyc_only(self):
299
self.setup_plugin() # after first import there will be plugin.pyc
309
# first import creates plugin.pyc (or plugin.pyo depending on __debug__)
300
311
self.teardown_plugin()
301
312
os.unlink(self.test_dir + '/plugin.py')
302
bzrlib.plugin.load_from_path(['.']) # import plugin.pyc
303
plugins = bzrlib.plugin.plugins()
304
plugin = plugins['plugin']
313
plugin.load_from_path(['.']) # import plugin.pyc (or .pyo)
314
p = plugin.plugins()['plugin']
306
316
plugin_path = self.test_dir + '/plugin.pyc'
308
318
plugin_path = self.test_dir + '/plugin.pyo'
309
self.assertIsSameRealPath(plugin_path, normpath(plugin.path()))
319
self.assertIsSameRealPath(plugin_path, osutils.normpath(p.path()))
311
321
def test_no_test_suite_gives_None_for_test_suite(self):
312
322
self.setup_plugin()
313
plugin = bzrlib.plugin.plugins()['plugin']
314
self.assertEqual(None, plugin.test_suite())
323
p = plugin.plugins()['plugin']
324
self.assertEqual(None, p.test_suite())
316
326
def test_test_suite_gives_test_suite_result(self):
317
327
source = """def test_suite(): return 'foo'"""
318
328
self.setup_plugin(source)
319
plugin = bzrlib.plugin.plugins()['plugin']
320
self.assertEqual('foo', plugin.test_suite())
329
p = plugin.plugins()['plugin']
330
self.assertEqual('foo', p.test_suite())
322
332
def test_no_load_plugin_tests_gives_None_for_load_plugin_tests(self):
323
333
self.setup_plugin()
324
loader = TestUtil.TestLoader()
325
plugin = bzrlib.plugin.plugins()['plugin']
326
self.assertEqual(None, plugin.load_plugin_tests(loader))
334
loader = tests.TestUtil.TestLoader()
335
p = plugin.plugins()['plugin']
336
self.assertEqual(None, p.load_plugin_tests(loader))
328
338
def test_load_plugin_tests_gives_load_plugin_tests_result(self):
330
340
def load_tests(standard_tests, module, loader):
332
342
self.setup_plugin(source)
333
loader = TestUtil.TestLoader()
334
plugin = bzrlib.plugin.plugins()['plugin']
335
self.assertEqual('foo', plugin.load_plugin_tests(loader))
343
loader = tests.TestUtil.TestLoader()
344
p = plugin.plugins()['plugin']
345
self.assertEqual('foo', p.load_plugin_tests(loader))
347
def check_version_info(self, expected, source='', name='plugin'):
348
self.setup_plugin(source)
349
self.assertEqual(expected, plugin.plugins()[name].version_info())
337
351
def test_no_version_info(self):
339
plugin = bzrlib.plugin.plugins()['plugin']
340
self.assertEqual(None, plugin.version_info())
352
self.check_version_info(None)
342
354
def test_with_version_info(self):
343
self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
344
plugin = bzrlib.plugin.plugins()['plugin']
345
self.assertEqual((1, 2, 3, 'dev', 4), plugin.version_info())
355
self.check_version_info((1, 2, 3, 'dev', 4),
356
"version_info = (1, 2, 3, 'dev', 4)")
347
358
def test_short_version_info_gets_padded(self):
348
359
# the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
350
self.setup_plugin("version_info = (1, 2, 3)")
351
plugin = bzrlib.plugin.plugins()['plugin']
352
self.assertEqual((1, 2, 3, 'final', 0), plugin.version_info())
361
self.check_version_info((1, 2, 3, 'final', 0),
362
"version_info = (1, 2, 3)")
364
def check_version(self, expected, source=None, name='plugin'):
365
self.setup_plugin(source)
366
self.assertEqual(expected, plugins[name].__version__)
354
368
def test_no_version_info___version__(self):
355
369
self.setup_plugin()
740
742
def test_bogus_references(self):
741
743
self.check_path(['+foo', '-bar', self.core, self.site],
742
744
['+foo', '-bar'])
747
class TestDisablePlugin(tests.TestCaseInTempDir, TestPluginMixin):
750
super(TestDisablePlugin, self).setUp()
751
self.create_plugin_package('test_foo')
752
# Make sure we don't pollute the plugins namespace
753
self.overrideAttr(plugins, '__path__')
754
# Be paranoid in case a test fail
755
self.addCleanup(self._unregister_plugin, 'test_foo')
757
def test_cannot_import(self):
758
osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
759
plugin.set_plugins_path(['.'])
761
import bzrlib.plugins.test_foo
764
self.assertPluginUnknown('test_foo')
766
def test_regular_load(self):
767
self.overrideAttr(plugin, '_loaded', False)
768
plugin.load_plugins(['.'])
769
self.assertPluginKnown('test_foo')
771
def test_not_loaded(self):
773
def captured_warning(*args, **kwargs):
774
self.warnings.append((args, kwargs))
775
self.overrideAttr(trace, 'warning', captured_warning)
776
self.overrideAttr(plugin, '_loaded', False)
777
osutils.set_or_unset_env('BZR_DISABLE_PLUGINS', 'test_foo')
778
plugin.load_plugins(plugin.set_plugins_path(['.']))
779
self.assertPluginUnknown('test_foo')
780
# Make sure we don't warn about the plugin ImportError since this has
781
# been *requested* by the user.
782
self.assertLength(0, self.warnings)