Skip to content

Commit

Permalink
[tests] Add unit tests for the rootFolder variables
Browse files Browse the repository at this point in the history
  • Loading branch information
cbentejac committed Dec 27, 2024
1 parent ac2502f commit beb7938
Show file tree
Hide file tree
Showing 2 changed files with 305 additions and 0 deletions.
24 changes: 24 additions & 0 deletions tests/nodes/test/RelativePaths.py
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

Check warning on line 24 in tests/nodes/test/RelativePaths.py

View check run for this annotation

Codecov / codecov/patch

tests/nodes/test/RelativePaths.py#L24

Added line #L24 was not covered by tests
281 changes: 281 additions & 0 deletions tests/test_nodeRootFolders.py
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

Check warning on line 40 in tests/test_nodeRootFolders.py

View check run for this annotation

Codecov / codecov/patch

tests/test_nodeRootFolders.py#L40

Added line #L40 was not covered by tests


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

Check warning on line 67 in tests/test_nodeRootFolders.py

View check run for this annotation

Codecov / codecov/patch

tests/test_nodeRootFolders.py#L67

Added line #L67 was not covered by tests


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

Check warning on line 93 in tests/test_nodeRootFolders.py

View check run for this annotation

Codecov / codecov/patch

tests/test_nodeRootFolders.py#L93

Added line #L93 was not covered by tests


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()

Check warning on line 147 in tests/test_nodeRootFolders.py

View check run for this annotation

codefactor.io / CodeFactor

tests/test_nodeRootFolders.py#L147

Use of insecure and deprecated function (mktemp). (B306)
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"

0 comments on commit beb7938

Please sign in to comment.