[tests] Use the NodePluginManager instance in the unit tests

The plugin manager is now effectively used for all the operations that
involve registering or unregistering nodes.
This commit is contained in:
Candice Bentéjac 2025-05-12 17:33:02 +02:00
parent 28042dd2ad
commit 777ed4207e
8 changed files with 103 additions and 63 deletions

View file

@ -1,8 +1,13 @@
import os
from meshroom.core import loadAllNodes, initPipelines
from meshroom.core import loadAllNodes
from meshroom.core import pluginManager
plugins = loadAllNodes(os.path.join(os.path.dirname(__file__), "nodes"))
for plugin in plugins:
pluginManager.addPlugin(plugin)
pluginManager.registerPlugin(plugin.name)
loadAllNodes(os.path.join(os.path.dirname(__file__), "nodes"))
if os.getenv("MESHROOM_PIPELINE_TEMPLATES_PATH", False):
os.environ["MESHROOM_PIPELINE_TEMPLATES_PATH"] += os.pathsep + os.path.dirname(os.path.realpath(__file__))
else:

View file

@ -1,4 +1,5 @@
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core import desc, pluginManager
from meshroom.core.plugins import NodePlugin
from meshroom.core.graph import Graph, loadGraph
@ -52,13 +53,15 @@ class NodeWithChoiceParamsSavingValuesOverride(desc.Node):
class TestChoiceParam:
nodePlugin = NodePlugin(NodeWithChoiceParams)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithChoiceParams)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithChoiceParams)
pluginManager.unregisterNode(cls.nodePlugin)
def test_customValueIsSerialized(self, graphSavedOnDisk):
graph: Graph = graphSavedOnDisk
@ -117,13 +120,15 @@ class TestChoiceParam:
class TestChoiceParamSavingCustomValues:
nodePlugin = NodePlugin(NodeWithChoiceParamsSavingValuesOverride)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithChoiceParamsSavingValuesOverride)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithChoiceParamsSavingValuesOverride)
pluginManager.unregisterNode(cls.nodePlugin)
def test_customValueIsSerialized(self, graphSavedOnDisk):
graph: Graph = graphSavedOnDisk

View file

@ -7,8 +7,8 @@ import copy
from typing import Type
import pytest
import meshroom.core
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core import desc, pluginManager
from meshroom.core.plugins import NodePlugin
from meshroom.core.exception import GraphCompatibilityError, NodeUpgradeError
from meshroom.core.graph import Graph, loadGraph
from meshroom.core.node import CompatibilityNode, CompatibilityIssue, Node
@ -170,21 +170,22 @@ class SampleInputNodeV2(desc.InputNode):
def replaceNodeTypeDesc(nodeType: str, nodeDesc: Type[desc.Node]):
"""Change the `nodeDesc` associated to `nodeType`."""
meshroom.core.nodesDesc[nodeType] = nodeDesc
pluginManager.getNodePlugins()[nodeType] = NodePlugin(nodeDesc)
def test_unknown_node_type():
"""
Test compatibility behavior for unknown node type.
"""
registerNodeType(SampleNodeV1)
nodePlugin = NodePlugin(SampleNodeV1)
pluginManager.registerNode(nodePlugin)
g = Graph("")
n = g.addNewNode("SampleNodeV1", input="/dev/null", paramA="foo")
graphFile = os.path.join(tempfile.mkdtemp(), "test_unknown_node_type.mg")
g.save(graphFile)
internalFolder = n.internalFolder
nodeName = n.name
unregisterNodeType(SampleNodeV1)
pluginManager.unregisterNode(nodePlugin)
# Reload file
@ -328,14 +329,18 @@ def test_description_conflict():
raise ValueError("Unexpected node type: " + srcNode.nodeType)
# Restore original node types
meshroom.core.nodesDesc = originalNodeTypes
pluginManager._nodePlugins = originalNodeTypes
def test_upgradeAllNodes():
registerNodeType(SampleNodeV1)
registerNodeType(SampleNodeV2)
registerNodeType(SampleInputNodeV1)
registerNodeType(SampleInputNodeV2)
nodePluginSampleV1 = NodePlugin(SampleNodeV1)
nodePluginSampleV2 = NodePlugin(SampleNodeV2)
nodePluginSampleInputV1 = NodePlugin(SampleInputNodeV1)
nodePluginSampleInputV2 = NodePlugin(SampleInputNodeV2)
pluginManager.registerNode(nodePluginSampleV1)
pluginManager.registerNode(nodePluginSampleV2)
pluginManager.registerNode(nodePluginSampleInputV1)
pluginManager.registerNode(nodePluginSampleInputV2)
g = Graph("")
n1 = g.addNewNode("SampleNodeV1")
@ -350,11 +355,13 @@ def test_upgradeAllNodes():
g.save(graphFile)
# Make SampleNodeV2 and SampleInputNodeV2 an unknown type
unregisterNodeType(SampleNodeV2)
unregisterNodeType(SampleInputNodeV2)
meshroom.core.nodesDesc[SampleNodeV1.__name__] = SampleNodeV2
meshroom.core.nodesDesc[SampleInputNodeV1.__name__] = SampleInputNodeV2
pluginManager.unregisterNode(nodePluginSampleV2)
pluginManager.unregisterNode(nodePluginSampleInputV2)
# Replace SampleNodeV1 by SampleNodeV2 and SampleInputNodeV1 by SampleInputNodeV2
pluginManager.getNodePlugins()[nodePluginSampleV1.nodeDescriptor.__name__] = nodePluginSampleV2
pluginManager.getNodePlugins()[nodePluginSampleInputV1.nodeDescriptor.__name__] = \
nodePluginSampleInputV2
# Reload file
g = loadGraph(graphFile)
@ -375,13 +382,15 @@ def test_upgradeAllNodes():
assert n2Name in g.compatibilityNodes.keys()
assert n4Name in g.compatibilityNodes.keys()
unregisterNodeType(SampleNodeV1)
unregisterNodeType(SampleInputNodeV1)
pluginManager.unregisterNode(nodePluginSampleV1)
pluginManager.unregisterNode(nodePluginSampleInputV1)
def test_conformUpgrade():
registerNodeType(SampleNodeV5)
registerNodeType(SampleNodeV6)
nodePluginSampleV5 = NodePlugin(SampleNodeV5)
nodePluginSampleV6 = NodePlugin(SampleNodeV6)
pluginManager.registerNode(nodePluginSampleV5)
pluginManager.registerNode(nodePluginSampleV6)
g = Graph("")
n1 = g.addNewNode("SampleNodeV5")
@ -391,7 +400,7 @@ def test_conformUpgrade():
g.save(graphFile)
# Replace SampleNodeV5 by SampleNodeV6
meshroom.core.nodesDesc[SampleNodeV5.__name__] = SampleNodeV6
pluginManager.getNodePlugins()[nodePluginSampleV5.nodeDescriptor.__name__] = nodePluginSampleV6
# Reload file
g = loadGraph(graphFile)
@ -415,8 +424,8 @@ def test_conformUpgrade():
# Check conformation
assert len(upgradedNode.paramA.value) == 1
unregisterNodeType(SampleNodeV5)
unregisterNodeType(SampleNodeV6)
pluginManager.unregisterNode(nodePluginSampleV5)
pluginManager.unregisterNode(nodePluginSampleV6)
class TestGraphLoadingWithStrictCompatibility:

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python
# coding:utf-8
from meshroom.core.graph import Graph
from meshroom.core import desc, registerNodeType
from meshroom.core import desc, pluginManager
from meshroom.core.plugins import NodePlugin
class SampleNode(desc.Node):
@ -16,9 +17,8 @@ class SampleNode(desc.Node):
desc.File(name='output', label='Output', description='', value="{nodeCacheFolder}")
]
registerNodeType(SampleNode)
nodePlugin = NodePlugin(SampleNode)
pluginManager.registerNode(nodePlugin) # register standalone NodePlugin
def test_output_invalidation():
graph = Graph("")

View file

@ -1,8 +1,9 @@
# coding:utf-8
from meshroom.core.graph import Graph, loadGraph, executeGraph
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core import desc, pluginManager
from meshroom.core.node import Node
from meshroom.core.plugins import NodePlugin
class NodeWithAttributeChangedCallback(desc.BaseNode):
@ -37,13 +38,15 @@ class NodeWithAttributeChangedCallback(desc.BaseNode):
class TestNodeWithAttributeChangedCallback:
nodePlugin = NodePlugin(NodeWithAttributeChangedCallback)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithAttributeChangedCallback)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithAttributeChangedCallback)
pluginManager.unregisterNode(cls.nodePlugin)
def test_assignValueTriggersCallback(self):
node = Node(NodeWithAttributeChangedCallback.__name__)
@ -68,13 +71,15 @@ class TestNodeWithAttributeChangedCallback:
class TestAttributeCallbackTriggerInGraph:
nodePlugin = NodePlugin(NodeWithAttributeChangedCallback)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithAttributeChangedCallback)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithAttributeChangedCallback)
pluginManager.unregisterNode(cls.nodePlugin)
def test_connectionTriggersCallback(self):
graph = Graph("")
@ -241,15 +246,18 @@ class NodeWithCompoundAttributes(desc.BaseNode):
class TestAttributeCallbackBehaviorWithUpstreamCompoundAttributes:
nodePluginAttributeChangedCallback = NodePlugin(NodeWithAttributeChangedCallback)
nodePluginCompoundAttributes = NodePlugin(NodeWithCompoundAttributes)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithAttributeChangedCallback)
registerNodeType(NodeWithCompoundAttributes)
pluginManager.registerNode(cls.nodePluginAttributeChangedCallback)
pluginManager.registerNode(cls.nodePluginCompoundAttributes)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithAttributeChangedCallback)
unregisterNodeType(NodeWithCompoundAttributes)
pluginManager.unregisterNode(cls.nodePluginAttributeChangedCallback)
pluginManager.unregisterNode(cls.nodePluginCompoundAttributes)
def test_connectionToListElement(self):
graph = Graph("")
@ -341,15 +349,18 @@ class NodeWithDynamicOutputValue(desc.BaseNode):
class TestAttributeCallbackBehaviorWithUpstreamDynamicOutputs:
nodePluginAttributeChangedCallback = NodePlugin(NodeWithAttributeChangedCallback)
nodePluginDynamicOutputValue = NodePlugin(NodeWithDynamicOutputValue)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithAttributeChangedCallback)
registerNodeType(NodeWithDynamicOutputValue)
pluginManager.registerNode(cls.nodePluginAttributeChangedCallback)
pluginManager.registerNode(cls.nodePluginDynamicOutputValue)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithAttributeChangedCallback)
unregisterNodeType(NodeWithDynamicOutputValue)
pluginManager.unregisterNode(cls.nodePluginAttributeChangedCallback)
pluginManager.unregisterNode(cls.nodePluginDynamicOutputValue)
def test_connectingUncomputedDynamicOutputDoesNotTriggerDownstreamAttributeChangedCallback(
self,
@ -432,13 +443,15 @@ class TestAttributeCallbackBehaviorWithUpstreamDynamicOutputs:
class TestAttributeCallbackBehaviorOnGraphImport:
nodePlugin = NodePlugin(NodeWithAttributeChangedCallback)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithAttributeChangedCallback)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithAttributeChangedCallback)
pluginManager.unregisterNode(cls.nodePlugin)
def test_importingGraphDoesNotTriggerAttributeChangedCallbacks(self):
graph = Graph("")

View file

@ -1,6 +1,7 @@
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core import desc, pluginManager
from meshroom.core.node import Node
from meshroom.core.graph import Graph, loadGraph
from meshroom.core.plugins import NodePlugin
class NodeWithCreationCallback(desc.InputNode):
@ -22,13 +23,15 @@ class NodeWithCreationCallback(desc.InputNode):
class TestNodeCreationCallback:
nodePlugin = NodePlugin(NodeWithCreationCallback)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithCreationCallback)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithCreationCallback)
pluginManager.unregisterNode(cls.nodePlugin)
def test_notTriggeredOnNodeInstantiation(self):
node = Node(NodeWithCreationCallback.__name__)

View file

@ -2,8 +2,9 @@
# coding:utf-8
from meshroom.core.graph import Graph, loadGraph, executeGraph
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core import desc, pluginManager
from meshroom.core.node import Node
from meshroom.core.plugins import NodePlugin
class NodeWithAttributesNeedingFormatting(desc.Node):
@ -100,13 +101,15 @@ class NodeWithAttributesNeedingFormatting(desc.Node):
]
class TestCommandLineFormatting:
nodePlugin = NodePlugin(NodeWithAttributesNeedingFormatting)
@classmethod
def setup_class(cls):
registerNodeType(NodeWithAttributesNeedingFormatting)
pluginManager.registerNode(cls.nodePlugin)
@classmethod
def teardown_class(cls):
unregisterNodeType(NodeWithAttributesNeedingFormatting)
pluginManager.unregisterNode(cls.nodePlugin)
def test_formatting_listOfFiles(self):
inputImages = ["/non/existing/fileA", "/non/existing/with space/fileB"]

View file

@ -1,23 +1,25 @@
from contextlib import contextmanager
from unittest.mock import patch
from typing import Type
import meshroom
from meshroom.core import registerNodeType, unregisterNodeType
from meshroom.core import desc
from meshroom.core import desc, pluginManager
from meshroom.core.plugins import NodePlugin
@contextmanager
def registeredNodeTypes(nodeTypes: list[Type[desc.Node]]):
def registeredNodeTypes(nodeTypes: list[desc.Node]):
nodePluginsList = {}
for nodeType in nodeTypes:
registerNodeType(nodeType)
nodePlugin = NodePlugin(nodeType)
pluginManager.registerNode(nodePlugin)
nodePluginsList[nodeType] = nodePlugin
yield
for nodeType in nodeTypes:
unregisterNodeType(nodeType)
pluginManager.unregisterNode(nodePluginsList[nodeType])
@contextmanager
def overrideNodeTypeVersion(nodeType: Type[desc.Node], version: str):
def overrideNodeTypeVersion(nodeType: desc.Node, version: str):
""" Helper context manager to override the version of a given node type. """
unpatchedFunc = meshroom.core.nodeVersion
with patch.object(