-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[tests] Add unit tests for the
rootFolder
variables
- Loading branch information
Showing
2 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,281 @@ | ||
# coding:utf-8 | ||
|
||
from inspect import getfile | ||
import os | ||
from pathlib import Path | ||
import pytest | ||
from tempfile import mktemp, gettempdir | ||
|
||
from meshroom.core.exception import GraphCompatibilityError | ||
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 RelativePathsV2(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="relativePathInput2", | ||
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) | ||
|
||
|
||
def test_reloadGraphWithCompatibilityIssue(graphSavedOnDisk): | ||
registerNodeType(RelativePaths) | ||
|
||
graph: Graph = graphSavedOnDisk | ||
node = graph.addNewNode(RelativePaths.__name__) | ||
graph.save() | ||
|
||
# Replace saved node description by V2 | ||
meshroom.core.nodesDesc[RelativePaths.__name__] = RelativePathsV2 | ||
|
||
# Check that the compatibility issue is raised | ||
with pytest.raises(GraphCompatibilityError): | ||
loadGraph(graph.filepath, strictCompatibility=True) | ||
|
||
compatibilityGraph = loadGraph(graph.filepath) | ||
compatibilityNode = compatibilityGraph.node(node.name) | ||
assert compatibilityNode.isCompatibilityNode | ||
|
||
# Check that the rootFolder content for CompatibilityNodes checks out | ||
# rootFolder for CompatibilityNodes only contains "NODE_CACHE_FOLDER" | ||
assert len(compatibilityNode.rootFolder) != len(node.rootFolder) | ||
assert "NODE_CACHE_FOLDER" in compatibilityNode.rootFolder | ||
|
||
# Input values should be the same, but the evaluation should differ as rootFolder for | ||
# CompatibilityNodes do not include "NODE_SOURCECODE_FOLDER" | ||
assert compatibilityNode.attribute("relativePathInput").value == \ | ||
node.attribute("relativePathInput").value | ||
assert compatibilityNode.attribute("relativePathInput").getEvalValue() != \ | ||
node.attribute("relativePathInput").getEvalValue() | ||
|
||
# Output values are evaluated straight away: they should be the same since "NODE_CACHE_FOLDER" | ||
# is always available | ||
assert compatibilityNode.attribute("output").value == \ | ||
compatibilityNode.attribute("output").getEvalValue() == \ | ||
node.attribute("output").value | ||
|
||
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" |