You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							120 lines
						
					
					
						
							5.0 KiB
						
					
					
				
			
		
		
	
	
							120 lines
						
					
					
						
							5.0 KiB
						
					
					
				| # pylint: disable=redefined-outer-name
 | |
| from pathlib import Path
 | |
| 
 | |
| import pytest
 | |
| 
 | |
| from shepherd.agent import plugin
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def simple_plugin(request):
 | |
|     # Load a simple plugin as a custom plugin, using `./assets` as the plugin dir
 | |
|     interface = plugin.load_plugin("simpletestplugin", Path(request.fspath.dirname)/'assets')
 | |
|     return interface
 | |
| 
 | |
| 
 | |
| def test_simple_plugin_load(simple_plugin: plugin.PluginInterface):
 | |
|     assert simple_plugin._plugin_name == "simpletestplugin"
 | |
| 
 | |
| 
 | |
| def test_simple_interface_function_load(simple_plugin: plugin.PluginInterface):
 | |
| 
 | |
|     # Check register_function()
 | |
|     assert "my_interface_function" in simple_plugin._functions
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def simple_initialised_plugin(request):
 | |
|     plugin.unload_plugin("simpletestplugin")
 | |
|     interface = plugin.load_plugin("simpletestplugin", Path(request.fspath.dirname)/'assets')
 | |
|     # The plugin system is _not_ responsible for making sure the config passed to it is valid. It
 | |
|     # stores and provides the conf-spec, but it's up to Core.Agent to actually validate the
 | |
|     # config - otherwise we wouldn't be able to do the whole multiple-layer-fallback thing before
 | |
|     # actually initialising the plugin.
 | |
|     # Therefore, part of the promise we make with the plugin interface is that the config we pass
 | |
|     # in _will_ fit the config-spec
 | |
|     template_config = interface.confspec.get_template()
 | |
|     plugin.init_plugins({"simpletestplugin": template_config})
 | |
|     return interface
 | |
| 
 | |
| 
 | |
| def test_simple_plugin_init(simple_initialised_plugin):
 | |
|     assert simple_initialised_plugin._plugin_name == "simpletestplugin"
 | |
|     # Check registered init function has run
 | |
|     assert simple_initialised_plugin.init_func_called is True
 | |
| 
 | |
| 
 | |
| def test_simple_interface_functions(simple_initialised_plugin):
 | |
| 
 | |
|     # Check module level function dict
 | |
|     assert simple_initialised_plugin._functions["my_interface_function"]() == 42
 | |
| 
 | |
|     # Check functions handed back to plugin
 | |
|     assert simple_initialised_plugin.plugins["simpletestplugin"].my_interface_function() == 42
 | |
| 
 | |
| 
 | |
| def test_simple_hook_attachments(simple_initialised_plugin):
 | |
|     assert "basic_hook" in simple_initialised_plugin._hooks
 | |
|     assert simple_initialised_plugin._hooks['basic_hook'](
 | |
|     ) == {'simpletestplugin': "basic attachment"}
 | |
|     assert simple_initialised_plugin.hooks.hook_with_args(
 | |
|         3, 7) == {'simpletestplugin': "attachment with args: 3, 7"}
 | |
|     assert simple_initialised_plugin.hooks.hook_with_fancy_args(
 | |
|         2, 4) == {'simpletestplugin': "attachment with fancy args: 2, 4, True"}
 | |
| 
 | |
|     with pytest.raises(TypeError, match="takes 2 positional arguments but 3 were"):
 | |
|         simple_initialised_plugin.hooks.hook_with_args(3, 7, 5)
 | |
| 
 | |
| 
 | |
| def test_dirty_plugin_load(request):
 | |
|     """
 | |
|     Corner cases in plugin load
 | |
|     """
 | |
|     interface = plugin.load_plugin("dirtytestplugin", Path(request.fspath.dirname)/'assets')
 | |
| 
 | |
|     # Should prefer the confspec actually registered, even if declared after
 | |
|     assert "spec2" in interface.confspec.spec_dict
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def running_class_plugin(request):
 | |
|     plugin.unload_plugin("classtestplugin")
 | |
|     interface = plugin.load_plugin("classtestplugin", Path(request.fspath.dirname)/'assets')
 | |
|     template_config = interface.confspec.get_template()
 | |
|     plugin.init_plugins({"classtestplugin": template_config})
 | |
|     return interface
 | |
| 
 | |
| 
 | |
| def test_class_plugin_init(running_class_plugin):
 | |
|     assert running_class_plugin._plugin_name == "classtestplugin"
 | |
|     # Check plugin object init method has run
 | |
|     assert running_class_plugin.init_method_called is True
 | |
|     # Check registered init method has run
 | |
|     assert running_class_plugin.init2_method_called is True
 | |
| 
 | |
| 
 | |
| def test_class_interface_functions(running_class_plugin):
 | |
|     ifuncs = running_class_plugin.plugins["classtestplugin"]
 | |
|     assert ifuncs.module_function(1) == "module func 1"
 | |
|     assert ifuncs.instance_method(2) == "instance method 2"
 | |
|     assert ifuncs.class_method(3) == "class method 3"
 | |
|     assert ifuncs.static_method(4) == "static method 4"
 | |
| 
 | |
| 
 | |
| def test_class_hook_attachments(running_class_plugin):
 | |
|     assert running_class_plugin._hooks.keys() == {"module_hook", "instance_hook",
 | |
|                                                   "static_hook", "static_hook2"}
 | |
|     # Internal hooks dict
 | |
|     assert running_class_plugin._hooks['module_hook'](1, 2) == {'classtestplugin':
 | |
|                                                                 "module attachment 1 2"}
 | |
|     # Interface hooks namespace
 | |
|     assert running_class_plugin.hooks.instance_hook(3, 4) == {'classtestplugin':
 | |
|                                                               "instance attachment 3 4"}
 | |
|     # Replaced attr in plugin object
 | |
|     assert running_class_plugin._plugin_obj.static_hook(5, 6) == {'classtestplugin':
 | |
|                                                                   "static attachment 5 6"}
 | |
|     assert running_class_plugin.hooks.static_hook2(7, 8) == {'classtestplugin':
 | |
|                                                              "class attachment 7 8"}
 | |
|     with pytest.raises(TypeError, match="takes 2 positional arguments but 3 were"):
 | |
|         running_class_plugin.hooks.static_hook(3, 7, 5)
 |