| 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__)), |
| 'basics', |
| ) |
| |
| |
| # 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'], 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'], 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'], 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'], 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'], 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'], 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'], 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'], 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'], 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'], 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'], 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'], 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'], [plugins1]) |
| factory2 = SourceFactory(plugin_fixture['base'], [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'], [plugins1]) |
| factory2 = ElementFactory(plugin_fixture['base'], [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') |