summaryrefslogtreecommitdiff
path: root/tests/internals/pluginfactory.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/internals/pluginfactory.py')
-rw-r--r--tests/internals/pluginfactory.py300
1 files changed, 300 insertions, 0 deletions
diff --git a/tests/internals/pluginfactory.py b/tests/internals/pluginfactory.py
new file mode 100644
index 000000000..28ab039bd
--- /dev/null
+++ b/tests/internals/pluginfactory.py
@@ -0,0 +1,300 @@
+import os
+import pytest
+
+from pluginbase import PluginBase
+from buildstream._elementfactory import ElementFactory
+from buildstream._sourcefactory import SourceFactory
+from buildstream._exceptions import PluginError
+
+DATA_DIR = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ 'pluginfactory',
+)
+
+
+# Simple fixture to create a PluginBase object that
+# we use for loading plugins.
+@pytest.fixture()
+def plugin_fixture():
+ return {
+ 'base': PluginBase(package='buildstream.plugins')
+ }
+
+
+##############################################################
+# Basics: test the fixture, test we can create the factories #
+##############################################################
+def test_fixture(plugin_fixture):
+ assert(isinstance(plugin_fixture['base'], PluginBase))
+
+
+def test_source_factory(plugin_fixture):
+ factory = SourceFactory(plugin_fixture['base'])
+ assert(isinstance(factory, SourceFactory))
+
+
+def test_element_factory(plugin_fixture):
+ factory = ElementFactory(plugin_fixture['base'])
+ assert(isinstance(factory, ElementFactory))
+
+
+##############################################################
+# Check that we can load custom sources & elements #
+##############################################################
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'customsource'))
+def test_custom_source(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
+ assert(isinstance(factory, SourceFactory))
+
+ foo_type, _ = factory.lookup('foo')
+ assert(foo_type.__name__ == 'FooSource')
+
+
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'customelement'))
+def test_custom_element(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
+ assert(isinstance(factory, ElementFactory))
+
+ foo_type, _ = factory.lookup('foo')
+ assert(foo_type.__name__ == 'FooElement')
+
+
+##############################################################
+# Check plugin loading failure modes #
+##############################################################
+def test_missing_source(plugin_fixture):
+ factory = SourceFactory(plugin_fixture['base'])
+ assert(isinstance(factory, SourceFactory))
+
+ # Test fails if PluginError is not raised
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+def test_missing_element(plugin_fixture):
+ factory = ElementFactory(plugin_fixture['base'])
+ assert(isinstance(factory, ElementFactory))
+
+ # Test fails if PluginError is not raised
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin that returns a value instead of Source subclass
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'notatype'))
+def test_source_notatype(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin that returns a value instead of Element subclass
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'notatype'))
+def test_element_notatype(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin that returns a type
+# which is not a Source subclass
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'wrongtype'))
+def test_source_wrongtype(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin that returns a type
+# which is not a Element subclass
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'wrongtype'))
+def test_element_wrongtype(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin which fails to provide a setup() function
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'nosetup'))
+def test_source_missing_setup(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin which fails to provide a setup() function
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'nosetup'))
+def test_element_missing_setup(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin which provides a setup symbol
+# that is not a function
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'badsetup'))
+def test_source_bad_setup(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin which provides a setup symbol
+# that is not a function
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'badsetup'))
+def test_element_bad_setup(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin which requires an absurdly
+# high version of buildstream
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'badversionsource'))
+def test_source_badversion(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = SourceFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+# Load a factory with a plugin which requires an absurdly
+# high version of buildstream
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'badversionelement'))
+def test_element_badversion(plugin_fixture, datafiles):
+ plugins = [{
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename),
+ 'plugins': {'foo': 0}
+ }]
+ factory = ElementFactory(plugin_fixture['base'], plugin_origins=plugins)
+ with pytest.raises(PluginError) as exc:
+ foo_type = factory.lookup('foo')
+
+
+##############################################################
+# Check we can load different contexts of plugin #
+##############################################################
+
+# Load two factories, both of which define a different 'foo' plugin
+@pytest.mark.datafiles(DATA_DIR)
+def test_source_multicontext(plugin_fixture, datafiles):
+ plugins1 = {
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename,
+ 'customsource'),
+ 'plugins': {'foo': 0}
+ }
+ plugins2 = {
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename,
+ 'anothersource'),
+ 'plugins': {'foo': 0}
+ }
+
+ factory1 = SourceFactory(plugin_fixture['base'], plugin_origins=[plugins1])
+ factory2 = SourceFactory(plugin_fixture['base'], plugin_origins=[plugins2])
+ assert(isinstance(factory1, SourceFactory))
+ assert(isinstance(factory2, SourceFactory))
+
+ foo_type1, _ = factory1.lookup('foo')
+ foo_type2, _ = factory2.lookup('foo')
+ assert(foo_type1.__name__ == 'FooSource')
+ assert(foo_type2.__name__ == 'AnotherFooSource')
+
+
+# Load two factories, both of which define a different 'foo' plugin
+@pytest.mark.datafiles(DATA_DIR)
+def test_element_multicontext(plugin_fixture, datafiles):
+ plugins1 = {
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename,
+ 'customelement'),
+ 'plugins': {'foo': 0}
+ }
+ plugins2 = {
+ 'origin': 'local',
+ 'path': os.path.join(datafiles.dirname,
+ datafiles.basename,
+ 'anotherelement'),
+ 'plugins': {'foo': 0}
+ }
+
+ factory1 = ElementFactory(plugin_fixture['base'], plugin_origins=[plugins1])
+ factory2 = ElementFactory(plugin_fixture['base'], plugin_origins=[plugins2])
+ assert(isinstance(factory1, ElementFactory))
+ assert(isinstance(factory2, ElementFactory))
+
+ foo_type1, _ = factory1.lookup('foo')
+ foo_type2, _ = factory2.lookup('foo')
+ assert(foo_type1.__name__ == 'FooElement')
+ assert(foo_type2.__name__ == 'AnotherFooElement')