Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit cccb2c0

Browse files
committed
xml generation: check for conflicting elements in user-provided input
Conflicting elements are elements belonging to more than one domain. The behaviour in such a case is unspecified. In the context of XML generation from user input, this denotes a mistake from the user. We now warn him and fail the generation. This commit includes testing. Signed-off-by: David Wagner <[email protected]>
1 parent 18a2753 commit cccb2c0

File tree

6 files changed

+64
-22
lines changed

6 files changed

+64
-22
lines changed

test/xml-generator/PFConfig/structure.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
<InstanceDefinition>
1111

1212
<Component Name="included" Type="Included"/>
13+
<ParameterBlock Name="inline">
14+
<BooleanParameter Name="bool"/>
15+
</ParameterBlock>
1316

1417
<ParameterBlock Name="block" ArrayLength="5">
1518
<FixedPointParameter Name="q2.5" Size="8" Integral="2" Fractional="5"/>

test/xml-generator/test.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,27 +90,33 @@ def check(self, reference=None, expectedErrors=0):
9090
config_dir = os.path.join(basedir, "PFConfig")
9191
vector_dir = os.path.join(basedir, "testVector")
9292
class TestCase(unittest.TestCase):
93-
nominal_reference = open(os.path.join(vector_dir, "reference.xml")).read().splitlines()
94-
nominal_pfconfig = PfConfig(os.path.join(config_dir, "configuration.xml"),
95-
os.path.join(config_dir, "criteria.txt"),
96-
os.path.join(basedir, "../../schemas"))
97-
nominal_vector = TestVector(os.path.join(vector_dir, "initialSettings.xml"),
98-
[os.path.join(vector_dir, "first.pfw"),
99-
os.path.join(vector_dir, "second.pfw"),
100-
os.path.join(vector_dir, "complex.pfw")],
101-
[os.path.join(vector_dir, "third.xml"),
102-
os.path.join(vector_dir, "fourth.xml")])
93+
def setUp(self):
94+
self.nominal_reference = open(os.path.join(vector_dir, "reference.xml")).read().splitlines()
95+
self.nominal_pfconfig = PfConfig(os.path.join(config_dir, "configuration.xml"),
96+
os.path.join(config_dir, "criteria.txt"),
97+
os.path.join(basedir, "../../schemas"))
98+
self.nominal_vector = TestVector(os.path.join(vector_dir, "initialSettings.xml"),
99+
[os.path.join(vector_dir, "first.pfw"),
100+
os.path.join(vector_dir, "second.pfw"),
101+
os.path.join(vector_dir, "complex.pfw")],
102+
[os.path.join(vector_dir, "third.xml"),
103+
os.path.join(vector_dir, "fourth.xml")])
103104

104105
def test_nominal(self):
105106
tester = Tester(self.nominal_pfconfig, self.nominal_vector)
106107
tester.check(self.nominal_reference)
107108

108109
def test_nonfatalError(self):
109-
vector = copy.copy(self.nominal_vector)
110-
vector.edds.append(os.path.join(vector_dir, "duplicate.pfw"))
110+
self.nominal_vector.edds.append(os.path.join(vector_dir, "duplicate.pfw"))
111111

112-
tester = Tester(self.nominal_pfconfig, vector)
112+
tester = Tester(self.nominal_pfconfig, self.nominal_vector)
113113
tester.check(self.nominal_reference, expectedErrors=1)
114114

115+
def test_conflicting(self):
116+
vector = TestVector(edds=[os.path.join(vector_dir, "conflicting.pfw")])
117+
118+
tester = Tester(self.nominal_pfconfig, vector)
119+
tester.check(expectedErrors=1)
120+
115121
if __name__ == "__main__":
116122
unittest.main()

test/xml-generator/testVector/complex.pfw

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ domainGroup: Red sequenceAware
3333
Colors Includes Blue
3434

3535
component: /Test/test
36-
component: block/3
36+
component: block/0
3737
q2.5 = 1.18750
3838
string = 12 ab @ <![CDATA[ < > \n \0 ✔ "'\
39-
component: included
39+
component: inline
4040
bool = 1
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Causes a conflicting-element error
2+
domain: First
3+
conf: Default
4+
/Test/test/included/bool = 1
5+
domain: Second
6+
conf: Default
7+
/Test/test/included/bool = 0

test/xml-generator/testVector/reference.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,19 +200,19 @@
200200
</Configuration>
201201
</Configurations>
202202
<ConfigurableElements>
203-
<ConfigurableElement Path="/Test/test/block/3/q2.5"/>
204-
<ConfigurableElement Path="/Test/test/block/3/string"/>
205-
<ConfigurableElement Path="/Test/test/included/bool"/>
203+
<ConfigurableElement Path="/Test/test/block/0/q2.5"/>
204+
<ConfigurableElement Path="/Test/test/block/0/string"/>
205+
<ConfigurableElement Path="/Test/test/inline/bool"/>
206206
</ConfigurableElements>
207207
<Settings>
208208
<Configuration Name="green.confGroup..On.Blue.dot">
209-
<ConfigurableElement Path="/Test/test/block/3/q2.5">
209+
<ConfigurableElement Path="/Test/test/block/0/q2.5">
210210
<FixedPointParameter Name="q2.5">1.18750</FixedPointParameter>
211211
</ConfigurableElement>
212-
<ConfigurableElement Path="/Test/test/block/3/string">
212+
<ConfigurableElement Path="/Test/test/block/0/string">
213213
<StringParameter Name="string">12 ab @ &lt;![CDATA[ &lt; &gt; \n \0 ✔ "'\</StringParameter>
214214
</ConfigurableElement>
215-
<ConfigurableElement Path="/Test/test/included/bool">
215+
<ConfigurableElement Path="/Test/test/inline/bool">
216216
<BooleanParameter Name="bool">1</BooleanParameter>
217217
</ConfigurableElement>
218218
</Configuration>

tools/xmlGenerator/domainGeneratorConnector.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ class XmlGenerator
9292
*/
9393
size_t parse(std::istream &input);
9494

95+
/** Check for elements belonging to several domains
96+
*
97+
* Prints conflicting elements, if any, on the error output.
98+
*
99+
* @returns true if there are conflicting elements, false otherwise
100+
*/
101+
bool conflictingElements();
102+
95103
/** Prints the Parameter Framework's instance configuration
96104
*
97105
* @param[out] output The stream to which output the configuration
@@ -182,6 +190,22 @@ size_t XmlGenerator::parse(std::istream &input)
182190
return errorNb;
183191
}
184192

193+
bool XmlGenerator::conflictingElements()
194+
{
195+
string conflicting;
196+
if (not mCommandHandler->process("listConflictingElements", {}, conflicting)) {
197+
// Should not happen
198+
throw Exception("Failed to list conflicting elements");
199+
}
200+
201+
if (not conflicting.empty()) {
202+
std::cerr << "There are conflicting elements:" << std::endl << conflicting;
203+
return true;
204+
}
205+
206+
return false;
207+
}
208+
185209
void XmlGenerator::start()
186210
{
187211
string error;
@@ -257,7 +281,9 @@ int main(int argc, char *argv[])
257281
try {
258282
XmlGenerator xmlGenerator(toplevelConfig, validate, verbose, schemasDir);
259283
auto errorNb = xmlGenerator.parse(std::cin);
260-
// TODO: add a check for conflicting elements
284+
if (xmlGenerator.conflictingElements()) {
285+
errorNb++;
286+
}
261287
xmlGenerator.exportDomains(std::cout);
262288

263289
return normalizeExitCode(errorNb);

0 commit comments

Comments
 (0)