From add926dc8cb42a2908079385bcf7221c6b17f5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Fri, 27 Dec 2024 11:17:43 +0100 Subject: [PATCH] [tests] Add unit tests for the `rootFolder` variables --- tests/nodes/test/RelativePaths.py | 24 ++++ tests/test_nodeRootFolders.py | 214 ++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 tests/nodes/test/RelativePaths.py create mode 100644 tests/test_nodeRootFolders.py diff --git a/tests/nodes/test/RelativePaths.py b/tests/nodes/test/RelativePaths.py new file mode 100644 index 0000000000..e5dd701120 --- /dev/null +++ b/tests/nodes/test/RelativePaths.py @@ -0,0 +1,24 @@ +from meshroom.core import desc + +class RelativePaths(desc.Node): + documentation = "Test node with filepaths that are set relatively to some variables." + inputs = [ + desc.File( + name="relativePathInput", + label="Relative Input File", + description="Relative path to the input file.", + value="${NODE_SOURCECODE_FOLDER}" + "/input.txt", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Output", + description="Path to the output file.", + value="${NODE_CACHE_FOLDER}" + "file.out", + ), + ] + + def processChunk(self, chunk): + pass diff --git a/tests/test_nodeRootFolders.py b/tests/test_nodeRootFolders.py new file mode 100644 index 0000000000..e505c030d6 --- /dev/null +++ b/tests/test_nodeRootFolders.py @@ -0,0 +1,214 @@ +# coding:utf-8 + +from inspect import getfile +import os +from pathlib import Path +from tempfile import mktemp, gettempdir + +from meshroom.core.graph import Graph, loadGraph +from meshroom.core import desc, loadAllNodes, registerNodeType, unregisterNodeType +from meshroom.core.node import Node +import meshroom.core + + +class RelativePaths(desc.Node): + """ + Local "RelativePaths" node, with a different source code folder as the one in nodes/test. + """ + + documentation = "Test node with filepaths that are set relatively to some variables." + inputs = [ + desc.File( + name="relativePathInput", + label="Relative Input File", + description="Relative path to the input file.", + value="${NODE_SOURCECODE_FOLDER}" + "/input.txt", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Output", + description="Path to the output file.", + value="${NODE_CACHE_FOLDER}" + "file.out", + ), + ] + + def processChunk(self, chunk): + pass + + +class FakeRelativePaths(desc.Node): + documentation = """ + Test node with filepaths that are set relatively to some variables that do not exist. + """ + inputs = [ + desc.File( + name="relativePathInput", + label="Relative Input File", + description="Relative path to the input file.", + value="${NODE_UNEXISTING_FOLDER}" + "/input.txt", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Output", + description="Path to the output file.", + value="${NODE_RANDOM_FOLDER}" + "file.out", + ) + ] + + def processChunk(self, chunk): + pass + + +def test_registerSameNodeWithDifferentLocations(): + """ + Check that the nodes with the same description but registered at different locations + have different evaluations for the NODE_SOURCECODE_FOLDER value. + """ + loadAllNodes(os.path.join(os.path.dirname(__file__), "nodes")) + assert "RelativePaths" in meshroom.core.nodesDesc + + # Node loaded from "nodes/test" + n1 = Node("RelativePaths") + sourceFolderNode1 = n1.attribute("relativePathInput").getEvalValue() + assert sourceFolderNode1 == \ + Path(getfile(meshroom.core.nodesDesc["RelativePaths"])).parent.resolve().as_posix() + \ + "/input.txt" + assert sourceFolderNode1 == n1.sourceCodeFolder + "/input.txt" + assert Path(sourceFolderNode1).parent.resolve().as_posix() == \ + n1.rootFolder["NODE_SOURCECODE_FOLDER"] + + # Unregister that node and replace it with the one from this file + unregisterNodeType(RelativePaths) + assert "RelativePaths" not in meshroom.core.nodesDesc + + registerNodeType(RelativePaths) + assert "RelativePaths" in meshroom.core.nodesDesc + + n2 = Node("RelativePaths") + sourceFolderNode2 = n2.attribute("relativePathInput").getEvalValue() + assert sourceFolderNode2 == \ + Path(getfile(meshroom.core.nodesDesc["RelativePaths"])).parent.resolve().as_posix() + \ + "/input.txt" + assert sourceFolderNode2 == n2.sourceCodeFolder + "/input.txt" + assert Path(sourceFolderNode2).parent.resolve().as_posix() == \ + n2.rootFolder["NODE_SOURCECODE_FOLDER"] + + assert sourceFolderNode1 is not sourceFolderNode2 + unregisterNodeType(RelativePaths) + + +def test_reloadGraphWithDifferentNodeLocations(): + """ + Save a Graph with a node description registered at a specific location, unregister that node + type, and register the same description from a different location. + """ + loadAllNodes(os.path.join(os.path.dirname(__file__), "nodes")) + assert "RelativePaths" in meshroom.core.nodesDesc + + graph = Graph('') + node = graph.addNewNode("RelativePaths") + name = node.name + + # Save graph in a file + filename = mktemp() + graph.save(filename) + + sourceCodeFolderNode = node.attribute("relativePathInput").getEvalValue() + assert sourceCodeFolderNode == node.rootFolder["NODE_SOURCECODE_FOLDER"] + "/input.txt" + + # Output attribute, already evaluated upon the node's creation + cacheFolderNode = node.attribute("output").value + + node._buildCmdVars() + assert desc.Node.internalFolder == node.rootFolder["NODE_CACHE_FOLDER"] + assert cacheFolderNode == desc.Node.internalFolder.format(**node._cmdVars) + "file.out" + + # Delete the current graph + del graph + + # Unregister that node and replace it with the one from this file + unregisterNodeType(meshroom.core.nodesDesc["RelativePaths"]) + assert "RelativePaths" not in meshroom.core.nodesDesc + + registerNodeType(RelativePaths) + assert "RelativePaths" in meshroom.core.nodesDesc + + # Reload the graph + graph = loadGraph(filename) + assert graph + node = graph.node(name) + assert node.nodeType == "RelativePaths" + + # Check that the relative path is different for the input + assert node.attribute("relativePathInput").getEvalValue() != sourceCodeFolderNode + + # Check that it is the same for the cache + assert node.attribute("output").value == cacheFolderNode + + os.remove(filename) + unregisterNodeType(RelativePaths) + + +class TestRootFolderContent(): + """ Class to test changes on the root folders' values. """ + @classmethod + def setup_class(cls): + """ Register nodes upon class' creation. """ + registerNodeType(RelativePaths) + registerNodeType(FakeRelativePaths) + + @classmethod + def teardown_class(cls): + """ Unregister nodes upon class' destruction. """ + unregisterNodeType(RelativePaths) + unregisterNodeType(FakeRelativePaths) + + def test_updateRootFolders(self): + """ + Check that root folder variables can be added and removed. + """ + assert "RelativePaths" in meshroom.core.nodesDesc + + node = Node("RelativePaths") + assert len(node.rootFolder) == 2 + + # Add a new element in the list of root folders + node.rootFolder.update({"NODE_TEST_FOLDER": gettempdir()}) + assert len(node.rootFolder) == 3 + + attr = node.attribute("relativePathInput") + + sourceCodeFolder = attr.getEvalValue() + attr.value = "${NODE_TEST_FOLDER}" + "/input.txt" + assert attr.getEvalValue() == gettempdir() + "/input.txt" + assert attr.getEvalValue() != sourceCodeFolder + + # Remove the extra element in the list of root folders + node.rootFolder.pop("NODE_TEST_FOLDER", None) + assert len(node.rootFolder) == 2 + + assert attr.getEvalValue() != gettempdir() + "/input.txt" + # Unevaluated value as the variable does not exist + assert attr.getEvalValue() == attr.value + + attr.value = attr.defaultValue() + assert attr.getEvalValue() == sourceCodeFolder + + + def test_nonExistingRootFolder(self): + """ + Check that a variable that does not correspond to any root folder is not evaluated. + """ + node = Node("FakeRelativePaths") + + # The root folder variable cannot be evaluated as it does not exist: it is not substituted + assert node.attribute("relativePathInput").getEvalValue() == \ + node.attribute("relativePathInput").value + assert node.attribute("output").getEvalValue() == \ + node.attribute("output").value == "${NODE_RANDOM_FOLDER}file.out"