"Fossies" - the Fresh Open Source Software Archive 
Member "buildbot-2.5.1/buildbot/test/unit/test_plugins.py" (24 Nov 2019, 8780 Bytes) of package /linux/misc/buildbot-2.5.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1 # This file is part of Buildbot. Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
8 # details.
9 #
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 #
14 # Copyright Buildbot Team Members
15 """
16 Unit tests for the plugin framework
17 """
18
19 import mock
20
21 from twisted.trial import unittest
22 from zope.interface import implementer
23
24 import buildbot.plugins.db
25 from buildbot.errors import PluginDBError
26 from buildbot.interfaces import IPlugin
27
28 # buildbot.plugins.db needs to be imported for patching, however just 'db' is
29 # much shorter for using in tests
30 db = buildbot.plugins.db
31
32
33 class FakeEntry:
34
35 """
36 An entry suitable for unit tests
37 """
38
39 def __init__(self, name, project_name, version, fail_require, value):
40 self._name = name
41 self._dist = mock.Mock(spec_set=['project_name', 'version'])
42 self._dist.project_name = project_name
43 self._dist.version = version
44 self._fail_require = fail_require
45 self._value = value
46
47 @property
48 def name(self):
49 "entry name"
50 return self._name
51
52 @property
53 def dist(self):
54 "dist thingie"
55 return self._dist
56
57 def require(self):
58 """
59 handle external dependencies
60 """
61 if self._fail_require:
62 raise RuntimeError('Fail require as requested')
63
64 def load(self):
65 """
66 handle loading
67 """
68 return self._value
69
70
71 class ITestInterface(IPlugin):
72
73 """
74 test interface
75 """
76 def hello(name):
77 "Greets by :param:`name`"
78
79
80 @implementer(ITestInterface)
81 class ClassWithInterface:
82
83 """
84 a class to implement a simple interface
85 """
86
87 def __init__(self, name=None):
88 self._name = name
89
90 def hello(self, name=None):
91 'implement the required method'
92 return name or self._name
93
94
95 class ClassWithNoInterface:
96
97 """
98 just a class
99 """
100
101
102 # NOTE: buildbot.plugins.db prepends the group with common namespace --
103 # 'buildbot.'
104 _FAKE_ENTRIES = {
105 'buildbot.interface': [
106 FakeEntry('good', 'non-existent', 'irrelevant', False,
107 ClassWithInterface),
108 FakeEntry('deep.path', 'non-existent', 'irrelevant', False,
109 ClassWithInterface)
110 ],
111 'buildbot.interface_failed': [
112 FakeEntry('good', 'non-existent', 'irrelevant', True,
113 ClassWithInterface)
114 ],
115 'buildbot.no_interface': [
116 FakeEntry('good', 'non-existent', 'irrelevant', False,
117 ClassWithNoInterface)
118 ],
119 'buildbot.no_interface_again': [
120 FakeEntry('good', 'non-existent', 'irrelevant', False,
121 ClassWithNoInterface)
122 ],
123 'buildbot.no_interface_failed': [
124 FakeEntry('good', 'non-existent', 'irrelevant', True,
125 ClassWithNoInterface)
126 ],
127 'buildbot.duplicates': [
128 FakeEntry('good', 'non-existent', 'first', False,
129 ClassWithNoInterface),
130 FakeEntry('good', 'non-existent', 'second', False,
131 ClassWithNoInterface)
132 ]
133 }
134
135
136 def provide_fake_entries(group):
137 """
138 give a set of fake entries for known groups
139 """
140 return _FAKE_ENTRIES.get(group, [])
141
142
143 @mock.patch('buildbot.plugins.db.iter_entry_points', provide_fake_entries)
144 class TestBuildbotPlugins(unittest.TestCase):
145
146 def setUp(self):
147 buildbot.plugins.db._DB = buildbot.plugins.db._PluginDB()
148
149 def test_check_group_registration(self):
150 with mock.patch.object(buildbot.plugins.db, '_DB', db._PluginDB()):
151 # The groups will be prepended with namespace, so info() will
152 # return a dictionary with right keys, but no data
153 groups = set(_FAKE_ENTRIES.keys())
154 for group in groups:
155 db.get_plugins(group)
156
157 registered = set(db.info().keys())
158 self.assertEqual(registered, groups)
159 self.assertEqual(registered, set(db.namespaces()))
160
161 def test_interface_provided_simple(self):
162 # Basic check before the actual test
163 self.assertTrue(ITestInterface.implementedBy(ClassWithInterface))
164
165 plugins = db.get_plugins('interface', interface=ITestInterface)
166
167 self.assertTrue('good' in plugins.names)
168
169 result_get = plugins.get('good')
170 result_getattr = plugins.good
171 self.assertFalse(result_get is None)
172 self.assertTrue(result_get is result_getattr)
173
174 # Make sure we actually got our class
175 greeter = result_get('yes')
176 self.assertEqual('yes', greeter.hello())
177 self.assertEqual('no', greeter.hello('no'))
178
179 def test_missing_plugin(self):
180 plugins = db.get_plugins('interface', interface=ITestInterface)
181
182 with self.assertRaises(AttributeError):
183 getattr(plugins, 'bad')
184 with self.assertRaises(PluginDBError):
185 plugins.get('bad')
186 with self.assertRaises(PluginDBError):
187 plugins.get('good.extra')
188
189 def test_interface_provided_deep(self):
190 # Basic check before the actual test
191 self.assertTrue(ITestInterface.implementedBy(ClassWithInterface))
192
193 plugins = db.get_plugins('interface', interface=ITestInterface)
194
195 self.assertTrue('deep.path' in plugins.names)
196
197 self.assertTrue('deep.path' in plugins)
198 self.assertFalse('even.deeper.path' in plugins)
199
200 result_get = plugins.get('deep.path')
201 result_getattr = plugins.deep.path
202 self.assertFalse(result_get is None)
203 self.assertTrue(result_get is result_getattr)
204
205 # Make sure we actually got our class
206 greeter = result_get('yes')
207 self.assertEqual('yes', greeter.hello())
208 self.assertEqual('no', greeter.hello('no'))
209
210 def test_interface_provided_deps_failed(self):
211 plugins = db.get_plugins('interface_failed', interface=ITestInterface,
212 check_extras=True)
213 with self.assertRaises(PluginDBError):
214 plugins.get('good')
215
216 def test_required_interface_not_provided(self):
217 plugins = db.get_plugins('no_interface_again',
218 interface=ITestInterface)
219 self.assertTrue(plugins._interface is ITestInterface)
220 with self.assertRaises(PluginDBError):
221 plugins.get('good')
222
223 def test_no_interface_provided(self):
224 plugins = db.get_plugins('no_interface')
225 self.assertFalse(plugins.get('good') is None)
226
227 def test_no_interface_provided_deps_failed(self):
228 plugins = db.get_plugins('no_interface_failed', check_extras=True)
229 with self.assertRaises(PluginDBError):
230 plugins.get('good')
231
232 def test_failure_on_dups(self):
233 with self.assertRaises(PluginDBError):
234 db.get_plugins('duplicates', load_now=True)
235
236 def test_get_info_on_a_known_plugin(self):
237 plugins = db.get_plugins('interface')
238 self.assertEqual(('non-existent', 'irrelevant'), plugins.info('good'))
239
240 def test_failure_on_unknown_plugin_info(self):
241 plugins = db.get_plugins('interface')
242 with self.assertRaises(PluginDBError):
243 plugins.info('bad')
244
245 def test_failure_on_unknown_plugin_get(self):
246 plugins = db.get_plugins('interface')
247 with self.assertRaises(PluginDBError):
248 plugins.get('bad')
249
250
251 class SimpleFakeEntry(FakeEntry):
252
253 def __init__(self, name, value):
254 super().__init__(name, 'non-existent', 'irrelevant', False, value)
255
256
257 _WORKER_FAKE_ENTRIES = {
258 'buildbot.worker': [
259 SimpleFakeEntry('Worker', ClassWithInterface),
260 SimpleFakeEntry('EC2LatentWorker', ClassWithInterface),
261 SimpleFakeEntry('LibVirtWorker', ClassWithInterface),
262 SimpleFakeEntry('OpenStackLatentWorker', ClassWithInterface),
263 SimpleFakeEntry('newthirdparty', ClassWithInterface),
264 SimpleFakeEntry('deep.newthirdparty', ClassWithInterface),
265 ],
266 'buildbot.util': [
267 SimpleFakeEntry('WorkerLock', ClassWithInterface),
268 SimpleFakeEntry('enforceChosenWorker', ClassWithInterface),
269 SimpleFakeEntry('WorkerChoiceParameter', ClassWithInterface),
270 ],
271 }
272
273
274 def provide_worker_fake_entries(group):
275 """
276 give a set of fake entries for known groups
277 """
278 return _WORKER_FAKE_ENTRIES.get(group, [])