Skip to content

Commit 8c37fd0

Browse files
committed
[tests] Add unit tests for the rootFolder variables
1 parent ac2502f commit 8c37fd0

File tree

2 files changed

+305
-0
lines changed

2 files changed

+305
-0
lines changed

tests/nodes/test/RelativePaths.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from meshroom.core import desc
2+
3+
class RelativePaths(desc.Node):
4+
documentation = "Test node with filepaths that are set relatively to some variables."
5+
inputs = [
6+
desc.File(
7+
name="relativePathInput",
8+
label="Relative Input File",
9+
description="Relative path to the input file.",
10+
value="${NODE_SOURCECODE_FOLDER}" + "/input.txt",
11+
),
12+
]
13+
14+
outputs = [
15+
desc.File(
16+
name="output",
17+
label="Output",
18+
description="Path to the output file.",
19+
value="${NODE_CACHE_FOLDER}" + "file.out",
20+
),
21+
]
22+
23+
def processChunk(self, chunk):
24+
pass

tests/test_nodeRootFolders.py

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
# coding:utf-8
2+
3+
from inspect import getfile
4+
import os
5+
from pathlib import Path
6+
import pytest
7+
from tempfile import gettempdir
8+
9+
from meshroom.core.exception import GraphCompatibilityError
10+
from meshroom.core.graph import Graph, loadGraph
11+
from meshroom.core import desc, loadAllNodes, registerNodeType, unregisterNodeType
12+
from meshroom.core.node import Node
13+
import meshroom.core
14+
15+
16+
class RelativePaths(desc.Node):
17+
"""
18+
Local "RelativePaths" node, with a different source code folder as the one in nodes/test.
19+
"""
20+
documentation = "Test node with filepaths that are set relatively to some variables."
21+
inputs = [
22+
desc.File(
23+
name="relativePathInput",
24+
label="Relative Input File",
25+
description="Relative path to the input file.",
26+
value="${NODE_SOURCECODE_FOLDER}" + "/input.txt",
27+
),
28+
]
29+
30+
outputs = [
31+
desc.File(
32+
name="output",
33+
label="Output",
34+
description="Path to the output file.",
35+
value="${NODE_CACHE_FOLDER}" + "file.out",
36+
),
37+
]
38+
39+
def processChunk(self, chunk):
40+
pass
41+
42+
43+
class RelativePathsV2(desc.Node):
44+
"""
45+
Local "RelativePaths" node, with a different source code folder as the one in nodes/test.
46+
"""
47+
documentation = "Test node with filepaths that are set relatively to some variables."
48+
inputs = [
49+
desc.File(
50+
name="relativePathInput2",
51+
label="Relative Input File",
52+
description="Relative path to the input file.",
53+
value="${NODE_SOURCECODE_FOLDER}" + "/input.txt",
54+
),
55+
]
56+
57+
outputs = [
58+
desc.File(
59+
name="output",
60+
label="Output",
61+
description="Path to the output file.",
62+
value="${NODE_CACHE_FOLDER}" + "file.out",
63+
),
64+
]
65+
66+
def processChunk(self, chunk):
67+
pass
68+
69+
70+
class FakeRelativePaths(desc.Node):
71+
documentation = """
72+
Test node with filepaths that are set relatively to some variables that do not exist.
73+
"""
74+
inputs = [
75+
desc.File(
76+
name="relativePathInput",
77+
label="Relative Input File",
78+
description="Relative path to the input file.",
79+
value="${NODE_UNEXISTING_FOLDER}" + "/input.txt",
80+
),
81+
]
82+
83+
outputs = [
84+
desc.File(
85+
name="output",
86+
label="Output",
87+
description="Path to the output file.",
88+
value="${NODE_RANDOM_FOLDER}" + "file.out",
89+
)
90+
]
91+
92+
def processChunk(self, chunk):
93+
pass
94+
95+
96+
def test_registerSameNodeWithDifferentLocations():
97+
"""
98+
Check that the nodes with the same description but registered at different locations
99+
have different evaluations for the NODE_SOURCECODE_FOLDER value.
100+
"""
101+
loadAllNodes(os.path.join(os.path.dirname(__file__), "nodes"))
102+
assert "RelativePaths" in meshroom.core.nodesDesc
103+
104+
# Node loaded from "nodes/test"
105+
n1 = Node("RelativePaths")
106+
sourceFolderNode1 = n1.attribute("relativePathInput").getEvalValue()
107+
assert sourceFolderNode1 == \
108+
Path(getfile(meshroom.core.nodesDesc["RelativePaths"])).parent.resolve().as_posix() + \
109+
"/input.txt"
110+
assert sourceFolderNode1 == n1.sourceCodeFolder + "/input.txt"
111+
assert Path(sourceFolderNode1).parent.resolve().as_posix() == \
112+
n1.rootFolder["NODE_SOURCECODE_FOLDER"]
113+
114+
# Unregister that node and replace it with the one from this file
115+
unregisterNodeType(RelativePaths)
116+
assert "RelativePaths" not in meshroom.core.nodesDesc
117+
118+
registerNodeType(RelativePaths)
119+
assert "RelativePaths" in meshroom.core.nodesDesc
120+
121+
n2 = Node("RelativePaths")
122+
sourceFolderNode2 = n2.attribute("relativePathInput").getEvalValue()
123+
assert sourceFolderNode2 == \
124+
Path(getfile(meshroom.core.nodesDesc["RelativePaths"])).parent.resolve().as_posix() + \
125+
"/input.txt"
126+
assert sourceFolderNode2 == n2.sourceCodeFolder + "/input.txt"
127+
assert Path(sourceFolderNode2).parent.resolve().as_posix() == \
128+
n2.rootFolder["NODE_SOURCECODE_FOLDER"]
129+
130+
assert sourceFolderNode1 is not sourceFolderNode2
131+
unregisterNodeType(RelativePaths)
132+
133+
134+
def test_reloadGraphWithDifferentNodeLocations(graphSavedOnDisk):
135+
"""
136+
Save a Graph with a node description registered at a specific location, unregister that node
137+
type, and register the same description from a different location.
138+
"""
139+
loadAllNodes(os.path.join(os.path.dirname(__file__), "nodes"))
140+
assert "RelativePaths" in meshroom.core.nodesDesc
141+
142+
graph: Graph = graphSavedOnDisk
143+
node = graph.addNewNode("RelativePaths")
144+
name = node.name
145+
filename = graph.filepath
146+
147+
# Save graph in a file
148+
graph.save()
149+
150+
sourceCodeFolderNode = node.attribute("relativePathInput").getEvalValue()
151+
assert sourceCodeFolderNode == node.rootFolder["NODE_SOURCECODE_FOLDER"] + "/input.txt"
152+
153+
# Output attribute, already evaluated upon the node's creation
154+
cacheFolderNode = node.attribute("output").value
155+
156+
node._buildCmdVars()
157+
assert desc.Node.internalFolder == node.rootFolder["NODE_CACHE_FOLDER"]
158+
assert cacheFolderNode == desc.Node.internalFolder.format(**node._cmdVars) + "file.out"
159+
160+
# Delete the current graph
161+
del graph
162+
163+
# Unregister that node and replace it with the one from this file
164+
unregisterNodeType(meshroom.core.nodesDesc["RelativePaths"])
165+
assert "RelativePaths" not in meshroom.core.nodesDesc
166+
167+
registerNodeType(RelativePaths)
168+
assert "RelativePaths" in meshroom.core.nodesDesc
169+
170+
# Reload the graph
171+
graph = loadGraph(filename)
172+
assert graph
173+
node = graph.node(name)
174+
assert node.nodeType == "RelativePaths"
175+
176+
# Check that the relative path is different for the input
177+
assert node.attribute("relativePathInput").getEvalValue() != sourceCodeFolderNode
178+
179+
# Check that it is the same for the cache
180+
assert node.attribute("output").value == cacheFolderNode
181+
182+
os.remove(filename)
183+
unregisterNodeType(RelativePaths)
184+
185+
186+
def test_reloadGraphWithCompatibilityIssue(graphSavedOnDisk):
187+
registerNodeType(RelativePaths)
188+
189+
graph: Graph = graphSavedOnDisk
190+
node = graph.addNewNode(RelativePaths.__name__)
191+
graph.save()
192+
193+
# Replace saved node description by V2
194+
meshroom.core.nodesDesc[RelativePaths.__name__] = RelativePathsV2
195+
196+
# Check that the compatibility issue is raised
197+
with pytest.raises(GraphCompatibilityError):
198+
loadGraph(graph.filepath, strictCompatibility=True)
199+
200+
compatibilityGraph = loadGraph(graph.filepath)
201+
compatibilityNode = compatibilityGraph.node(node.name)
202+
assert compatibilityNode.isCompatibilityNode
203+
204+
# Check that the rootFolder content for CompatibilityNodes checks out
205+
# rootFolder for CompatibilityNodes only contains "NODE_CACHE_FOLDER"
206+
assert len(compatibilityNode.rootFolder) != len(node.rootFolder)
207+
assert "NODE_CACHE_FOLDER" in compatibilityNode.rootFolder
208+
209+
# Input values should be the same, but the evaluation should differ as rootFolder for
210+
# CompatibilityNodes do not include "NODE_SOURCECODE_FOLDER"
211+
assert compatibilityNode.attribute("relativePathInput").value == \
212+
node.attribute("relativePathInput").value
213+
assert compatibilityNode.attribute("relativePathInput").getEvalValue() != \
214+
node.attribute("relativePathInput").getEvalValue()
215+
216+
# Output values are evaluated straight away: they should be the same since "NODE_CACHE_FOLDER"
217+
# is always available
218+
assert compatibilityNode.attribute("output").value == \
219+
compatibilityNode.attribute("output").getEvalValue() == \
220+
node.attribute("output").value
221+
222+
unregisterNodeType(RelativePaths)
223+
224+
225+
class TestRootFolderContent():
226+
""" Class to test changes on the root folders' values. """
227+
@classmethod
228+
def setup_class(cls):
229+
""" Register nodes upon class' creation. """
230+
registerNodeType(RelativePaths)
231+
registerNodeType(FakeRelativePaths)
232+
233+
@classmethod
234+
def teardown_class(cls):
235+
""" Unregister nodes upon class' destruction. """
236+
unregisterNodeType(RelativePaths)
237+
unregisterNodeType(FakeRelativePaths)
238+
239+
def test_updateRootFolders(self):
240+
"""
241+
Check that root folder variables can be added and removed.
242+
"""
243+
assert "RelativePaths" in meshroom.core.nodesDesc
244+
245+
node = Node("RelativePaths")
246+
assert len(node.rootFolder) == 2
247+
248+
# Add a new element in the list of root folders
249+
node.rootFolder.update({"NODE_TEST_FOLDER": gettempdir()})
250+
assert len(node.rootFolder) == 3
251+
252+
attr = node.attribute("relativePathInput")
253+
254+
sourceCodeFolder = attr.getEvalValue()
255+
attr.value = "${NODE_TEST_FOLDER}" + "/input.txt"
256+
assert attr.getEvalValue() == gettempdir() + "/input.txt"
257+
assert attr.getEvalValue() != sourceCodeFolder
258+
259+
# Remove the extra element in the list of root folders
260+
node.rootFolder.pop("NODE_TEST_FOLDER", None)
261+
assert len(node.rootFolder) == 2
262+
263+
assert attr.getEvalValue() != gettempdir() + "/input.txt"
264+
# Unevaluated value as the variable does not exist
265+
assert attr.getEvalValue() == attr.value
266+
267+
attr.value = attr.defaultValue()
268+
assert attr.getEvalValue() == sourceCodeFolder
269+
270+
271+
def test_nonExistingRootFolder(self):
272+
"""
273+
Check that a variable that does not correspond to any root folder is not evaluated.
274+
"""
275+
node = Node("FakeRelativePaths")
276+
277+
# The root folder variable cannot be evaluated as it does not exist: it is not substituted
278+
assert node.attribute("relativePathInput").getEvalValue() == \
279+
node.attribute("relativePathInput").value
280+
assert node.attribute("output").getEvalValue() == \
281+
node.attribute("output").value == "${NODE_RANDOM_FOLDER}file.out"

0 commit comments

Comments
 (0)