Skip to content

Commit b28fd12

Browse files
committed
[tests] Add test node with GroupAttributes and unit test
The test ensures that if the attributes within `GroupAttributes` are connected to each other, the graph can be saved and reloaded without triggering compatibility issues for these nodes.
1 parent 4fc3d4a commit b28fd12

File tree

2 files changed

+253
-0
lines changed

2 files changed

+253
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
from meshroom.core import desc
2+
3+
class GroupAttributes(desc.Node):
4+
documentation = """ Test node to connect GroupAttributes to other GroupAttributes. """
5+
category = 'Test'
6+
7+
# Inputs to the node
8+
inputs = [
9+
desc.GroupAttribute(
10+
name="firstGroup",
11+
label="First Group",
12+
description="Group at the root level.",
13+
group=None,
14+
exposed=True,
15+
groupDesc=[
16+
desc.IntParam(
17+
name="firstGroupIntA",
18+
label="Integer A",
19+
description="First integer in group.",
20+
value=1024,
21+
range=(-1, 2000, 10),
22+
exposed=True,
23+
),
24+
desc.IntParam(
25+
name="firstGroupIntB",
26+
label="Integer B",
27+
description="Second integer in group.",
28+
value=1024,
29+
range=(-1, 2000, 10),
30+
exposed=True,
31+
),
32+
desc.IntParam(
33+
name="firstGroupIntC",
34+
label="Integer C",
35+
description="Third integer in group.",
36+
value=64,
37+
range=(0, 500, 1),
38+
exposed=True,
39+
),
40+
desc.BoolParam(
41+
name="firstGroupBool",
42+
label="Boolean",
43+
description="Boolean in group.",
44+
value=True,
45+
advanced=True,
46+
exposed=True,
47+
),
48+
desc.GroupAttribute(
49+
name="nestedGroup",
50+
label="Nested Group",
51+
description="A group within a group.",
52+
group=None,
53+
exposed=True,
54+
groupDesc=[
55+
desc.FloatParam(
56+
name="nestedGroupFloat",
57+
label="Floating Number",
58+
description="Floating number in group.",
59+
value=1.0,
60+
range=(0.0, 100.0, 0.01),
61+
exposed=True
62+
),
63+
],
64+
),
65+
desc.ListAttribute(
66+
name="groupedList",
67+
label="Grouped List",
68+
description="List of groups within a group.",
69+
advanced=True,
70+
exposed=True,
71+
elementDesc=desc.GroupAttribute(
72+
name="listedGroup",
73+
label="Listed Group",
74+
description="Group in a list within a group.",
75+
joinChar=":",
76+
group=None,
77+
groupDesc=[
78+
desc.IntParam(
79+
name="listedGroupInt",
80+
label="Integer 1",
81+
description="Integer in a group in a list within a group.",
82+
value=12,
83+
range=(3, 24, 1),
84+
exposed=True,
85+
),
86+
],
87+
),
88+
),
89+
desc.ListAttribute(
90+
name="singleGroupedList",
91+
label="Grouped List With Single Element",
92+
description="List of integers within a group.",
93+
advanced=True,
94+
exposed=True,
95+
elementDesc=desc.IntParam(
96+
name="listedInt",
97+
label="Integer In List",
98+
description="Integer in a list within a group.",
99+
value=40,
100+
),
101+
),
102+
],
103+
),
104+
desc.IntParam(
105+
name="exposedInt",
106+
label="Exposed Integer",
107+
description="Integer at the rool level, exposed.",
108+
value=1000,
109+
exposed=True,
110+
),
111+
desc.BoolParam(
112+
name="unexposedBool",
113+
label="Unexposed Boolean",
114+
description="Boolean at the root level, unexposed.",
115+
value=True,
116+
),
117+
desc.GroupAttribute(
118+
name="inputGroup",
119+
label="Input Group",
120+
description="A group set as an input.",
121+
group=None,
122+
groupDesc=[
123+
desc.BoolParam(
124+
name="inputBool",
125+
label="Input Bool",
126+
description="",
127+
value=False,
128+
),
129+
],
130+
),
131+
]
132+
133+
outputs = [
134+
desc.GroupAttribute(
135+
name="outputGroup",
136+
label="Output Group",
137+
description="A group set as an output.",
138+
group=None,
139+
exposed=True,
140+
groupDesc=[
141+
desc.BoolParam(
142+
name="outputBool",
143+
label="Output Bool",
144+
description="",
145+
value=False,
146+
exposed=True,
147+
),
148+
],
149+
),
150+
]

tests/test_groupAttributes.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env python
2+
# coding:utf-8
3+
4+
import os
5+
import tempfile
6+
7+
from meshroom.core.graph import Graph, loadGraph
8+
from meshroom.core.node import CompatibilityNode
9+
from meshroom.core.attribute import GroupAttribute
10+
11+
GROUPATTRIBUTES_FIRSTGROUP_NB_CHILDREN = 8 # 3 ints, 1 bool, 1 group, 1 float nested in the group, 2 lists
12+
GROUPATTRIBUTES_FIRSTGROUP_NESTED_NB_CHILDREN = 1 # 1 float
13+
GROUPATTRIBUTES_OUTPUTGROUP_NB_CHILDREN = 1 # 1 bool
14+
GROUPATTRIBUTES_FIRSTGROUP_DEPTHS = [1, 1, 1, 1, 1, 2, 1, 1]
15+
16+
def test_saveLoadGroupConnections():
17+
"""
18+
Ensure that connecting attributes that are part of GroupAttributes does not cause
19+
their nodes to have CompatibilityIssues when re-opening them.
20+
"""
21+
graph = Graph("Connections between GroupAttributes")
22+
23+
# Create two "GroupAttributes" nodes with their default parameters
24+
nodeA = graph.addNewNode("GroupAttributes")
25+
nodeB = graph.addNewNode("GroupAttributes")
26+
27+
# Connect attributes within groups at different depth levels
28+
graph.addEdges(
29+
(nodeA.firstGroup.firstGroupIntA, nodeB.firstGroup.firstGroupIntA),
30+
(nodeA.firstGroup.nestedGroup.nestedGroupFloat, nodeB.firstGroup.nestedGroup.nestedGroupFloat)
31+
)
32+
33+
# Save the graph in a file
34+
graphFile = os.path.join(tempfile.mkdtemp(), "test_io_group_connections.mg")
35+
graph.save(graphFile)
36+
37+
# Reload the graph
38+
graph = loadGraph(graphFile)
39+
40+
# Ensure the nodes are not CompatibilityNodes
41+
for node in graph.nodes:
42+
assert not isinstance(node, CompatibilityNode)
43+
44+
45+
def test_groupAttributesFlatChildren():
46+
"""
47+
Check that the list of static flat children is correct, even with list elements.
48+
"""
49+
graph = Graph("Children of GroupAttributes")
50+
51+
# Create two "GroupAttributes" nodes with their default parameters
52+
node = graph.addNewNode("GroupAttributes")
53+
54+
intAttr = node.attribute("exposedInt")
55+
assert not isinstance(intAttr, GroupAttribute)
56+
assert len(intAttr.flatStaticChildren) == 0 # Not a Group, cannot have any child
57+
58+
inputGroup = node.attribute("firstGroup")
59+
assert isinstance(inputGroup, GroupAttribute)
60+
assert len(inputGroup.flatStaticChildren) == GROUPATTRIBUTES_FIRSTGROUP_NB_CHILDREN
61+
62+
# Add an element to a list within the group and check the number of children hasn't changed
63+
groupedList = node.attribute("firstGroup.singleGroupedList")
64+
groupedList.insert(0, 30)
65+
assert len(groupedList.flatStaticChildren) == 0 # Not a Group, elements are not counted as children
66+
assert len(inputGroup.flatStaticChildren) == GROUPATTRIBUTES_FIRSTGROUP_NB_CHILDREN
67+
68+
nestedGroup = node.attribute("firstGroup.nestedGroup")
69+
assert isinstance(nestedGroup, GroupAttribute)
70+
assert len(nestedGroup.flatStaticChildren) == GROUPATTRIBUTES_FIRSTGROUP_NESTED_NB_CHILDREN
71+
72+
outputGroup = node.attribute("outputGroup")
73+
assert isinstance(outputGroup, GroupAttribute)
74+
assert len(outputGroup.flatStaticChildren) == GROUPATTRIBUTES_OUTPUTGROUP_NB_CHILDREN
75+
76+
77+
def test_groupAttributesDepthLevels():
78+
"""
79+
Check that the depth level of children attributes is correctly set.
80+
"""
81+
graph = Graph("Children of GroupAttributes")
82+
83+
# Create two "GroupAttributes" nodes with their default parameters
84+
node = graph.addNewNode("GroupAttributes")
85+
inputGroup = node.attribute("firstGroup")
86+
assert isinstance(inputGroup, GroupAttribute)
87+
assert inputGroup.depth == 0 # Root level
88+
89+
cnt = 0
90+
for child in inputGroup.flatStaticChildren:
91+
assert child.depth == GROUPATTRIBUTES_FIRSTGROUP_DEPTHS[cnt]
92+
cnt = cnt + 1
93+
94+
outputGroup = node.attribute("outputGroup")
95+
assert isinstance(outputGroup, GroupAttribute)
96+
assert outputGroup.depth == 0
97+
for child in outputGroup.flatStaticChildren: # Single element in the group
98+
assert child.depth == 1
99+
100+
101+
intAttr = node.attribute("exposedInt")
102+
assert not isinstance(intAttr, GroupAttribute)
103+
assert intAttr.depth == 0

0 commit comments

Comments
 (0)