Skip to content

Commit 11d9b40

Browse files
committed
[tests] Add unit tests for the dynamicEnvVars variables
1 parent fd6607f commit 11d9b40

File tree

2 files changed

+309
-0
lines changed

2 files changed

+309
-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_nodeDynamicEnvVars.py

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
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.dynamicEnvVars["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.dynamicEnvVars["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.dynamicEnvVars["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.dynamicEnvVars["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 dynamicEnvVars content for CompatibilityNodes checks out:
205+
# dynamicEnvVars for CompatibilityNodes only contains a set "NODE_CACHE_FOLDER" and
206+
# a "NODE_SOURCECODE_FOLDER" that is set to "UndefinedPath"
207+
assert len(compatibilityNode.dynamicEnvVars) == len(node.dynamicEnvVars)
208+
assert "NODE_CACHE_FOLDER" in compatibilityNode.dynamicEnvVars
209+
assert "NODE_SOURCECODE_FOLDER" in compatibilityNode.dynamicEnvVars
210+
assert compatibilityNode.dynamicEnvVars["NODE_SOURCECODE_FOLDER"] == "UndefinedPath"
211+
212+
# Input values should be the same, but the evaluation should differ as dynamicEnvVars
213+
# for CompatibilityNodes do not include the same value for "NODE_SOURCECODE_FOLDER"
214+
assert compatibilityNode.attribute("relativePathInput").value == \
215+
node.attribute("relativePathInput").value
216+
assert compatibilityNode.attribute("relativePathInput").getEvalValue() != \
217+
node.attribute("relativePathInput").getEvalValue()
218+
219+
# Output values are evaluated straight away: they should be the same since "NODE_CACHE_FOLDER"
220+
# is always available
221+
assert compatibilityNode.attribute("output").value == \
222+
compatibilityNode.attribute("output").getEvalValue() == \
223+
node.attribute("output").value
224+
225+
unregisterNodeType(RelativePaths)
226+
227+
228+
class TestDynamicEnvVarsContent():
229+
""" Class to test changes on the dynamic environment variables' values. """
230+
@classmethod
231+
def setup_class(cls):
232+
""" Register nodes upon class' creation. """
233+
registerNodeType(RelativePaths)
234+
registerNodeType(FakeRelativePaths)
235+
236+
@classmethod
237+
def teardown_class(cls):
238+
""" Unregister nodes upon class' destruction. """
239+
unregisterNodeType(RelativePaths)
240+
unregisterNodeType(FakeRelativePaths)
241+
242+
def test_updateDynamicEnvVars(self):
243+
"""
244+
Check that dynamic environment variables can be added and removed.
245+
"""
246+
assert "RelativePaths" in meshroom.core.nodesDesc
247+
248+
node = Node("RelativePaths")
249+
assert len(node.dynamicEnvVars) == 2
250+
251+
# Add a new element in the list of dynamic environment variables
252+
node.dynamicEnvVars.update({"NODE_TEST_FOLDER": gettempdir()})
253+
assert len(node.dynamicEnvVars) == 3
254+
255+
attr = node.attribute("relativePathInput")
256+
257+
sourceCodeFolder = attr.getEvalValue()
258+
attr.value = "${NODE_TEST_FOLDER}" + "/input.txt"
259+
assert attr.getEvalValue() == gettempdir() + "/input.txt"
260+
assert attr.getEvalValue() != sourceCodeFolder
261+
262+
# Remove the extra element in the list of dynamic environment variables
263+
node.dynamicEnvVars.pop("NODE_TEST_FOLDER", None)
264+
assert len(node.dynamicEnvVars) == 2
265+
266+
assert attr.getEvalValue() != gettempdir() + "/input.txt"
267+
# Unevaluated value as the variable does not exist
268+
assert attr.getEvalValue() == attr.value
269+
270+
attr.value = attr.defaultValue()
271+
assert attr.getEvalValue() == sourceCodeFolder
272+
273+
274+
def test_nonExistingDynamicEnvVars(self):
275+
"""
276+
Check that a variable that does not correspond to any dynamic environment variable
277+
is not evaluated.
278+
"""
279+
node = Node("FakeRelativePaths")
280+
281+
# The dynamic environment variable cannot be evaluated as it does not exist: it is not substituted
282+
assert node.attribute("relativePathInput").getEvalValue() == \
283+
node.attribute("relativePathInput").value
284+
assert node.attribute("output").getEvalValue() == \
285+
node.attribute("output").value == "${NODE_RANDOM_FOLDER}file.out"

0 commit comments

Comments
 (0)