1
# Copyright (C) 2005 by Canonical Ltd
1
# Copyright (C) 2005 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
17
"""Tests for plugins"""
28
from bzrlib.selftest import InTempDir
31
def PluginTest(InTempDir):
32
"""Create an external plugin and test loading."""
36
orig_help = self.backtick('bzr help commands') # No plugins yet
37
os.mkdir('plugin_test')
38
f = open(os.path.join('plugin_test', 'myplug.py'), 'wt')
42
newhelp = backtick('bzr help commands')
43
assert newhelp.startswith('You have been overridden\n')
44
# We added a line, but the rest should work
45
assert newhelp[25:] == help
47
assert backtick('bzr commit -m test') == "I'm sorry dave, you can't do that\n"
49
shutil.rmtree('plugin_test')
55
"""import bzrlib, bzrlib.commands
19
# XXX: There are no plugin tests at the moment because the plugin module
20
# affects the global state of the process. See bzrlib/plugins.py for more
24
from StringIO import StringIO
30
import bzrlib.commands
32
from bzrlib.tests import TestCase, TestCaseInTempDir
33
from bzrlib.osutils import pathjoin, abspath
37
import bzrlib.commands
56
38
class cmd_myplug(bzrlib.commands.Command):
57
39
'''Just a simple test plugin.'''
60
42
print 'Hello from my plugin'
64
os.environ['BZRPLUGINPATH'] = os.path.abspath('plugin_test')
65
help = backtick('bzr help commands')
66
assert help.find('myplug') != -1
67
assert help.find('Just a simple test plugin.') != -1
70
assert backtick('bzr myplug') == 'Hello from my plugin\n'
71
assert backtick('bzr mplg') == 'Hello from my plugin\n'
73
f = open(os.path.join('plugin_test', 'override.py'), 'wb')
74
f.write("""import bzrlib, bzrlib.commands
75
class cmd_commit(bzrlib.commands.cmd_commit):
76
'''Commit changes into a new revision.'''
77
def run(self, *args, **kwargs):
78
print "I'm sorry dave, you can't do that"
80
class cmd_help(bzrlib.commands.cmd_help):
81
'''Show help on a command or other topic.'''
82
def run(self, *args, **kwargs):
83
print "You have been overridden"
84
bzrlib.commands.cmd_help.run(self, *args, **kwargs)
45
# TODO: Write a test for plugin decoration of commands.
47
class TestLoadingPlugins(TestCaseInTempDir):
51
def test_plugins_with_the_same_name_are_not_loaded(self):
52
# This test tests that having two plugins in different directories does
53
# not result in both being loaded when they have the same name. get a
54
# file name we can use which is also a valid attribute for accessing in
55
# activeattributes. - we cannot give import parameters.
57
self.failIf(tempattribute in self.activeattributes)
58
# set a place for the plugins to record their loading, and at the same
59
# time validate that the location the plugins should record to is
61
bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
63
self.failUnless(tempattribute in self.activeattributes)
64
# create two plugin directories
67
# write a plugin that will record when its loaded in the
69
template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
70
"TestLoadingPlugins.activeattributes[%r].append('%s')\n")
71
print >> file(os.path.join('first', 'plugin.py'), 'w'), template % (tempattribute, 'first')
72
print >> file(os.path.join('second', 'plugin.py'), 'w'), template % (tempattribute, 'second')
74
bzrlib.plugin.load_from_path(['first', 'second'])
75
self.assertEqual(['first'], self.activeattributes[tempattribute])
77
# remove the plugin 'plugin'
78
del self.activeattributes[tempattribute]
79
if getattr(bzrlib.plugins, 'plugin', None):
80
del bzrlib.plugins.plugin
81
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
83
def test_plugins_from_different_dirs_can_demand_load(self):
84
# This test tests that having two plugins in different
85
# directories with different names allows them both to be loaded, when
86
# we do a direct import statement.
87
# Determine a file name we can use which is also a valid attribute
88
# for accessing in activeattributes. - we cannot give import parameters.
89
tempattribute = "different-dirs"
90
self.failIf(tempattribute in self.activeattributes)
91
# set a place for the plugins to record their loading, and at the same
92
# time validate that the location the plugins should record to is
94
bzrlib.tests.test_plugins.TestLoadingPlugins.activeattributes \
96
self.failUnless(tempattribute in self.activeattributes)
97
# create two plugin directories
100
# write plugins that will record when they are loaded in the
101
# tempattribute list.
102
template = ("from bzrlib.tests.test_plugins import TestLoadingPlugins\n"
103
"TestLoadingPlugins.activeattributes[%r].append('%s')\n")
104
print >> file(os.path.join('first', 'pluginone.py'), 'w'), template % (tempattribute, 'first')
105
print >> file(os.path.join('second', 'plugintwo.py'), 'w'), template % (tempattribute, 'second')
106
oldpath = bzrlib.plugins.__path__
108
bzrlib.plugins.__path__ = ['first', 'second']
109
exec "import bzrlib.plugins.pluginone"
110
self.assertEqual(['first'], self.activeattributes[tempattribute])
111
exec "import bzrlib.plugins.plugintwo"
112
self.assertEqual(['first', 'second'],
113
self.activeattributes[tempattribute])
115
# remove the plugin 'plugin'
116
del self.activeattributes[tempattribute]
117
if getattr(bzrlib.plugins, 'plugin', None):
118
del bzrlib.plugins.plugin
119
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
122
class TestAllPlugins(TestCaseInTempDir):
124
def test_plugin_appears_in_all_plugins(self):
125
# This test tests a new plugin appears in bzrlib.plugin.all_plugins().
126
# check the plugin is not loaded already
127
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
128
# write a plugin that _cannot_ fail to load.
129
print >> file('plugin.py', 'w'), ""
131
bzrlib.plugin.load_from_path(['.'])
132
self.failUnless('plugin' in bzrlib.plugin.all_plugins())
133
self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
134
self.assertEqual(bzrlib.plugin.all_plugins()['plugin'],
135
bzrlib.plugins.plugin)
137
# remove the plugin 'plugin'
138
if 'bzrlib.plugins.plugin' in sys.modules:
139
del sys.modules['bzrlib.plugins.plugin']
140
if getattr(bzrlib.plugins, 'plugin', None):
141
del bzrlib.plugins.plugin
142
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
145
class TestPluginHelp(TestCaseInTempDir):
147
def split_help_commands(self):
150
for line in self.capture('help commands').splitlines():
151
if not line.startswith(' '):
152
current = line.split()[0]
153
help[current] = help.get(current, '') + line
157
def test_plugin_help_builtins_unaffected(self):
158
# Check we don't get false positives
159
help_commands = self.split_help_commands()
160
for cmd_name in bzrlib.commands.builtin_command_names():
161
if cmd_name in bzrlib.commands.plugin_command_names():
165
bzrlib.help.help_on_command(cmd_name, help)
166
except NotImplementedError:
167
# some commands have no help
171
self.assertNotContainsRe(help.read(), 'From plugin "[^"]*"')
173
if help in help_commands.keys():
174
# some commands are hidden
175
help = help_commands[cmd_name]
176
self.assertNotContainsRe(help, 'From plugin "[^"]*"')
178
def test_plugin_help_shows_plugin(self):
179
# Create a test plugin
180
os.mkdir('plugin_test')
181
f = open(pathjoin('plugin_test', 'myplug.py'), 'w')
187
bzrlib.plugin.load_from_path(['plugin_test'])
188
bzrlib.commands.register_command( bzrlib.plugins.myplug.cmd_myplug)
189
help = self.capture('help myplug')
190
self.assertContainsRe(help, 'From plugin "myplug"')
191
help = self.split_help_commands()['myplug']
192
self.assertContainsRe(help, '\[myplug\]')
195
if bzrlib.commands.plugin_cmds.get('myplug', None):
196
del bzrlib.commands.plugin_cmds['myplug']
197
# remove the plugin 'myplug'
198
if getattr(bzrlib.plugins, 'myplug', None):
199
delattr(bzrlib.plugins, 'myplug')
202
class TestPluginFromZip(TestCaseInTempDir):
204
def make_zipped_plugin(self, zip_name, filename):
205
z = zipfile.ZipFile(zip_name, 'w')
206
z.writestr(filename, PLUGIN_TEXT)
209
def check_plugin_load(self, zip_name, plugin_name):
210
self.assertFalse(plugin_name in dir(bzrlib.plugins),
211
'Plugin already loaded')
213
bzrlib.plugin.load_from_zip(zip_name)
214
self.assertTrue(plugin_name in dir(bzrlib.plugins),
215
'Plugin is not loaded')
218
if getattr(bzrlib.plugins, plugin_name, None):
219
delattr(bzrlib.plugins, plugin_name)
221
def test_load_module(self):
222
self.make_zipped_plugin('./test.zip', 'ziplug.py')
223
self.check_plugin_load('./test.zip', 'ziplug')
225
def test_load_package(self):
226
self.make_zipped_plugin('./test.zip', 'ziplug/__init__.py')
227
self.check_plugin_load('./test.zip', 'ziplug')
230
class TestSetPluginsPath(TestCase):
232
def test_set_plugins_path(self):
233
"""set_plugins_path should set the module __path__ correctly."""
234
old_path = bzrlib.plugins.__path__
236
bzrlib.plugins.__path__ = []
237
expected_path = bzrlib.plugin.set_plugins_path()
238
self.assertEqual(expected_path, bzrlib.plugins.__path__)
240
bzrlib.plugins.__path__ = old_path