Meshroom/tests/test_plugins.py

217 lines
6.7 KiB
Python

#!/usr/bin/env python
# coding:utf-8
""" Test for Meshroom Plugins.
"""
# STD
import os
import shutil
import tempfile
# Internal
from meshroom.core import _plugins
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core.graph import Graph
from meshroom.core.node import Node, IncompatiblePluginNode
class SampleNode(desc.Node):
""" Sample Node for unit testing """
category = "Sample"
inputs = [
desc.File(name='input', label='Input', description='', value='',),
desc.StringParam(name='paramA', label='ParamA', description='', value='', invalidate=False) # No impact on UID
]
outputs = [
desc.File(name='output', label='Output', description='', value=desc.Node.internalFolder)
]
def test_plugin_management():
""" Tests the plugin manager for registering and unregistering node.
"""
# Sample Node name
name = SampleNode.__name__
# Register the node
registerNodeType(SampleNode)
# Since the Node Plugin Manager is a singleton instance
# We should still be able to instantiate and have a look at out registered plugins directly
pluginManager = _plugins.NodePluginManager()
# Assert that the plugin we have registered above is indeed registered
assert pluginManager.registered(name)
# Assert that the plugin can only be registered once
assert not pluginManager.registerNode(SampleNode)
# And once un-registered, it should no longer be present in the pluginManager
unregisterNodeType(SampleNode)
# Assert that the plugin we have registered above is indeed registered
assert not pluginManager.registered(name)
assert name not in pluginManager.descriptors
def test_descriptor():
""" Tests the Descriptor and NodeDescriptor instances.
"""
# Register the node
registerNodeType(SampleNode)
# Since the Node Plugin Manager is a singleton instance
# We should still be able to instantiate and have a look at out registered plugins directly
pluginManager = _plugins.NodePluginManager()
# Assert the descriptor is same as the Plugin NodeType
assert pluginManager.descriptor(SampleNode.__name__).__name__ == SampleNode.__name__
# Assert that the category of the NodeDescriptor is correct for the registered plugin
assert pluginManager.descriptors.get(SampleNode.__name__).category == "Sample"
# Finally unregister the plugin
unregisterNodeType(SampleNode)
def _setup_temp_package(directory, name):
""" Sets up a temporary meshroom package structure which can be loaded as plugins.
"""
package = os.path.join(directory, name)
# Create the base package in the directory
os.makedirs(package)
# The very first file that we need is probably empty __init__.py
init = os.path.join(package, "__init__.py")
# The second thing we need is a directory inside
packageDir = os.path.join(package, "TesingPackage")
# Third would be another init for the package
packinit = os.path.join(packageDir, "__init__.py")
# Then comes the main module which will hold the plugin
pluginMod = os.path.join(packageDir, "TestInput.py")
# Now start constructing stuff here
os.makedirs(packageDir)
with open(init, "w") as f:
f.write("__version__ =\"1.0\"")
with open(packinit, "w") as f:
f.write("__version__ =\"1.0\"")
contents = """
from meshroom.core import desc
class SampleTroubledNode(desc.Node):
\""" Sample Node for unit testing a reload process.
Defaults to having an invalid input param value. Which gets updated later on.
\"""
category = "Sample"
inputs = [
# A Float param having the value as a string will cause the plugin to be loaded in an Error state
desc.FloatParam(name='paramA', label='ParamA', description='', value='4.0')
]
outputs = [
desc.File(name='output', label='Output', description='', value=desc.Node.internalFolder)
]
"""
with open(pluginMod, "w") as f:
f.write(contents)
return package
def _correctify_plugin(pluginPath):
contents = """
from meshroom.core import desc
class SampleTroubledNode(desc.Node):
\""" Sample Node for unit testing a reload process.
Defaults to having an invalid input param value. Which gets updated later on.
\"""
category = "Sample"
inputs = [
# A Float param having the value as a string will cause the plugin to be loaded in an Error state
desc.FloatParam(name='paramA', label='ParamA', description='', value=4.0)
]
outputs = [
desc.File(name='output', label='Output', description='', value=desc.Node.internalFolder)
]
"""
with open(pluginPath, "w") as f:
f.write(contents)
def _cleaup_package(directory):
""" Cleans up the Package
"""
shutil.rmtree(directory)
def test_reload_with_graph():
""" Tests Reloading of a plugin and how does the change propagate to a graph.
"""
# Create a temp directory
directory = tempfile.mkdtemp()
package = _setup_temp_package(directory, "MTest")
# Since the Node Plugin Manager is a singleton instance
# We should still be able to instantiate and have a look at out registered plugins directly
pluginManager = _plugins.NodePluginManager()
pluginManager.load(package)
# Sample Node name
name = "SampleTroubledNode"
# Assert that the plugin we have registered above is indeed registered
assert pluginManager.registered(name)
# But the status of the plugin would be errored
assert pluginManager.status(name) == _plugins.Status.ERRORED
# Graph for usage
g = Graph("")
# Create Nodes in the Graph
n = g.addNewNode(name)
# Assert that the node is of an Incompatible Plugin type as the plugin had errors while loading
assert isinstance(n, IncompatiblePluginNode)
descriptor = pluginManager.descriptors.get(name)
# Test that the plugin would not get reloaded
# unless either the source has been modified or the plugin is forced to be loaded
assert not descriptor.reload()
# Modify the Source of the Troubled Node before we reload the plugin
# This updates the source of the plugin and ensures that the plugin can now be loaded as expected
_correctify_plugin(os.path.join(package, "TesingPackage", "TestInput.py"))
# Reload the plugin as the source has been modified
assert descriptor.reload()
# Now the plugin has been reloaded
assert pluginManager.status(name) == _plugins.Status.LOADED
# Now reload the nodes of the provided type in the graph
g.reloadNodes(name)
# Get all the nodes and assert that they have been upgraded to Standard Nodes
for node in g.nodesOfType(name):
assert isinstance(node, Node)
# Once the tests are concluded -> Cleanup
_cleaup_package(package)