1 /* 2 * Copyright (c) 2015, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software without 17 * specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "Config.hpp" 32 #include "Test.hpp" 33 #include "Exception.hpp" 34 #include "TmpFile.hpp" 35 36 #include "ParameterFramework.hpp" 37 #include "ElementHandle.hpp" 38 39 #include <catch.hpp> 40 41 #include <libxml/parser.h> 42 #include <libxml/tree.h> 43 44 #include <string> 45 #include <list> 46 47 #include <stdlib.h> 48 49 using std::string; 50 using std::list; 51 using Bytes = std::vector<uint8_t>; 52 53 namespace parameterFramework 54 { 55 56 struct AllParamsPF : public ParameterFramework 57 { AllParamsPFparameterFramework::AllParamsPF58 AllParamsPF() : ParameterFramework{getConfig()} { REQUIRE_NOTHROW(start()); } 59 getBasicParamsparameterFramework::AllParamsPF60 string getBasicParams() 61 { 62 string structure = R"( 63 <BooleanParameter Name="bool" Description="bool"/> 64 <BooleanParameter ArrayLength="2" Name="bool_array" Description="bool-array"/> 65 66 <IntegerParameter Signed="false" Min="33" Max="123" Size="16" Name="integer"/> 67 <IntegerParameter Signed="true" Min="-10" Max="10" Size="32" ArrayLength="4" Name="integer_array"/> 68 69 <FixedPointParameter Size="32" Integral="3" Fractional="4" Name="fix_point"/> 70 <FixedPointParameter Size="32" Integral="3" Fractional="4" ArrayLength="3" Name="fix_point_array"/> 71 72 <EnumParameter Size="8" Name="enum"> 73 <ValuePair Literal="min" Numerical="-128"/> 74 <ValuePair Literal="five" Numerical="5"/> 75 <ValuePair Literal="max" Numerical="127"/> 76 </EnumParameter> 77 <EnumParameter Size="16" ArrayLength="4" Name="enum_array"> 78 <ValuePair Literal="eight" Numerical="8"/> 79 <ValuePair Literal="min" Numerical="-32767"/> 80 </EnumParameter>)"; 81 82 // String and bit parameter arrays are not supported 83 structure += R"( 84 <StringParameter MaxLength="63" Name="string"/> 85 86 <BitParameterBlock Size="64" Name="bit_block"> 87 <BitParameter Pos="1" Size="1" Max="1" Name="one"/> 88 <BitParameter Pos="2" Size="2" Max="2" Name="two"/> 89 <BitParameter Pos="6" Size="6" Max="10" Name="six"/> 90 <BitParameter Pos="16" Size="16" Max="99" Name="sixteen"/> 91 <BitParameter Pos="32" Size="32" Max="4294967295" Name="thirty_two"/> 92 </BitParameterBlock> 93 )"; 94 return structure; 95 } 96 getConfigparameterFramework::AllParamsPF97 Config getConfig() 98 { 99 Config config; 100 config.components = nodeDesc("ComponentType", "component_type", getBasicParams()); 101 config.instances = 102 getBasicParams() + nodeDesc("ParameterBlock", "parameter_block", getBasicParams()) + 103 nodeDesc("ParameterBlock", "parameter_block_array", getBasicParams(), 104 "ArrayLength='2'") + 105 nodeDesc("Component", "component_scalar", "", "Type='component_type'") + 106 nodeDesc("Component", "component_array", "", "Type='component_type' ArrayLength='2'"); 107 return config; 108 } 109 checkStructureparameterFramework::AllParamsPF110 void checkStructure(const string &path, const string &expected) 111 { 112 CHECK_NOTHROW(checkXMLEq(ElementHandle{*this, path}.getStructureAsXML(), expected)); 113 } 114 115 /** Use libxml2 to pretty format xml. 116 * Equivalent of xmllint --format 117 */ canonicalizeXMLparameterFramework::AllParamsPF118 static string canonicalizeXML(const string &xml) 119 { 120 // Parse xml 121 // Might be better to specialize std::default_delete<xmlDoc>. 122 std::unique_ptr<xmlDoc, void (*)(xmlDoc *)> doc{ 123 xmlReadMemory(xml.c_str(), (int)xml.length(), "structure.xml", nullptr, 124 XML_PARSE_NOBLANKS), 125 xmlFreeDoc}; 126 if (doc == nullptr) { 127 throw Exception{"Failed to parse document: " + xml}; 128 } 129 130 // Dump it formated 131 int size; 132 133 // Need to use exception unsafe raw pointer as of libxml2 c api 134 xmlChar *unsafeFormated; 135 136 // TODO: Should use canonicalization (aka c14n). 137 // cf: http://xmlsoft.org/html/libxml-c14n.html 138 // https://en.wikipedia.org/wiki/Canonical_XML 139 // Additionally to what is listed on that page, 140 // attributes are also ordered deterministically. 141 // That would solve the workaround in the node function with pre/post attributes. 142 // Unfortunately c14n is not available in appveyor (Windows CI) libxml2 prebuild 143 xmlDocDumpFormatMemoryEnc(doc.get(), &unsafeFormated, &size, "UTF-8", 1); 144 std::unique_ptr<xmlChar, void (*)(void *)> formated{unsafeFormated, xmlFree}; 145 146 if (formated == nullptr) { 147 throw Exception{"Could not dump xml: " + xml}; 148 } 149 150 return string{(char *)formated.get()}; 151 } 152 checkEqparameterFramework::AllParamsPF153 static void checkEq(const string &result, const string &expected) 154 { 155 CHECK(result == expected); 156 157 // Pretty print the word differences with colors 158 // It does not matter if it fails as the test would still fail 159 // due to the above CHECK. 160 if (result != expected) { 161 utility::TmpFile resultFile(result); 162 utility::TmpFile expectedFile(expected); 163 string command = "git --no-pager diff --word-diff-regex='[^ <>]+'" 164 " --color --no-index --exit-code " + 165 resultFile.getPath() + ' ' + expectedFile.getPath(); 166 167 // `system` return -1 or 127 on failure, the command error code otherwise 168 // `git diff` return 1 if the files are the different (thanks to --exit-code) 169 auto status = system(command.c_str()); 170 #ifdef WIFEXITED // Posix platform 171 bool success = WIFEXITED(status) and WEXITSTATUS(status) == 1; 172 #else 173 bool success = status == 1; 174 #endif 175 if (not success) { 176 WARN("Warning: Failed to pretty-print the difference between " 177 "actual and expected results with `git diff'"); 178 } 179 } 180 } 181 checkXMLEqparameterFramework::AllParamsPF182 static void checkXMLEq(const string &result, const string &expected) 183 { 184 checkEq(canonicalizeXML(result), canonicalizeXML(expected)); 185 } 186 nodeparameterFramework::AllParamsPF187 static string node(string tag, string name, string content, string attributes = "", 188 string postAttributes = "") 189 { 190 return "<" + tag + " " + attributes + " Name='" + name + "' " + postAttributes + ">" + 191 content + "</" + tag + ">"; 192 } 193 /** Node with a description. 194 * @param[in] maybeDescription If nullptr, description will be generated from the name 195 * Otherwise, the description. 196 */ nodeDescparameterFramework::AllParamsPF197 static string nodeDesc(string tag, string name, string content, string attributes = "", 198 const char *maybeDescription = nullptr) 199 { 200 string description = "description_" + name; 201 if (maybeDescription != nullptr) { 202 description = maybeDescription; 203 } 204 return node(tag, name, content, attributes, "Description='" + description + "'"); 205 } 206 rootNodeparameterFramework::AllParamsPF207 static string rootNode(string name, string attributes, string content) 208 { 209 return '<' + name + ' ' + attributes + '>' + content + "</" + name + '>'; 210 } 211 }; 212 213 SCENARIO_METHOD(AllParamsPF, "Export boolean", "[handler][structure][xml]") 214 { 215 string expected = rootNode("BooleanParameter", "Name='bool' Description='bool'", ""); 216 checkStructure("/test/test/bool", expected); 217 } 218 219 SCENARIO_METHOD(AllParamsPF, "Export component", "[handler][structure][xml]") 220 { 221 string expected = rootNode("ParameterBlock", "Name='component_scalar' " 222 "Description='description_component_scalar'", 223 getBasicParams()); 224 checkStructure("/test/test/component_scalar", expected); 225 } 226 227 SCENARIO_METHOD(AllParamsPF, "Export component array", "[handler][structure][xml]") 228 { 229 string expected = rootNode( 230 "ParameterBlock", "Name='component_array' Description='description_component_array'", 231 nodeDesc("ParameterBlock", "0", getBasicParams(), "", "description_component_array") + 232 nodeDesc("ParameterBlock", "1", getBasicParams(), "", "description_component_array")); 233 checkStructure("/test/test/component_array", expected); 234 } 235 236 SCENARIO_METHOD(AllParamsPF, "Export all parameters", "[handler][structure][xml]") 237 { 238 string paramExpected = getBasicParams() + 239 nodeDesc("ParameterBlock", "parameter_block", getBasicParams()) + 240 nodeDesc("ParameterBlock", "parameter_block_array", 241 nodeDesc("ParameterBlock", "0", getBasicParams(), "", 242 // description is inherited from array 243 "description_parameter_block_array") + 244 nodeDesc("ParameterBlock", "1", getBasicParams(), "", 245 "description_parameter_block_array")) + 246 // Components should be exported as parameterBlock 247 nodeDesc("ParameterBlock", "component_scalar", getBasicParams()) + 248 nodeDesc("ParameterBlock", "component_array", 249 nodeDesc("ParameterBlock", "0", getBasicParams(), "", 250 // description is inherited from array 251 "description_component_array") + 252 nodeDesc("ParameterBlock", "1", getBasicParams(), "", 253 "description_component_array")); 254 255 WHEN ("Exporting subsystem") { 256 string expected = rootNode("Subsystem", "Name='test'", paramExpected); 257 checkStructure("/test/test", expected); 258 } 259 260 WHEN ("Exporting systemClass") { 261 string expected = rootNode("SystemClass", "Name='test'", 262 "<Subsystem Name='test'>" + paramExpected + "</Subsystem>"); 263 264 // Awkwardly, the root and its first child are the same element 265 checkStructure("/test", expected); 266 checkStructure("/", expected); 267 } 268 } 269 270 struct SettingsTestPF : public AllParamsPF 271 { parameterBlockNodeparameterFramework::SettingsTestPF272 static string parameterBlockNode(string name, string settings) 273 { 274 return node("ParameterBlock", name, settings); 275 }; mkBasicSettingsparameterFramework::SettingsTestPF276 static string mkBasicSettings(string settings, string name) 277 { 278 return rootNode("ParameterBlock", "Name='" + name + "'", settings); 279 } 280 fullXMLSettingsparameterFramework::SettingsTestPF281 static string fullXMLSettings(const string &basicSettings) 282 { 283 string settings = basicSettings; 284 settings += 285 parameterBlockNode("parameter_block", settings) + 286 parameterBlockNode("parameter_block_array", parameterBlockNode("0", settings) + 287 parameterBlockNode("1", settings)) + 288 parameterBlockNode("component_scalar", settings) + 289 parameterBlockNode("component_array", parameterBlockNode("0", settings) + 290 parameterBlockNode("1", settings)); 291 292 return rootNode("SystemClass", "Name='test'", node("Subsystem", "test", settings, "")); 293 } 294 fullBytesSettingsparameterFramework::SettingsTestPF295 static string fullBytesSettings(const string &basicSettings) 296 { 297 string fullSettings; 298 // We have the "basic params" repeated 7 times across the test 299 // structure 300 for (size_t i = 0; i < 7; ++i) { 301 fullSettings += basicSettings; 302 } 303 return fullSettings; 304 } 305 306 /** Print Bytes as string separated hexadecimal number. */ showBytesparameterFramework::SettingsTestPF307 static string showBytes(const Bytes &bytes) 308 { 309 using namespace std; 310 ostringstream ss; 311 ss.exceptions(ostream::badbit | ostream::failbit); 312 for (auto byte : bytes) { 313 ss << hex << setw(2) << setfill('0') << int{byte} << ' '; 314 } 315 return ss.str(); 316 } 317 readBytesparameterFramework::SettingsTestPF318 static Bytes readBytes(const string &strBytes) 319 { 320 using namespace std; 321 istringstream ss{strBytes}; 322 ss.exceptions(istream::badbit | istream::failbit); 323 Bytes bytes(strBytes.size() / 3); 324 325 for (auto &byte : bytes) { 326 uint16_t notCharByte; 327 ss >> hex >> setw(2) >> notCharByte; 328 byte = static_cast<char>(notCharByte); 329 } 330 return bytes; 331 } 332 checkBytesEqparameterFramework::SettingsTestPF333 static void checkBytesEq(const Bytes &result, const string &expect) 334 { 335 checkEq(showBytes(result), expect); 336 } checkBytesEqparameterFramework::SettingsTestPF337 static void checkBytesEq(const Bytes &result, const Bytes &expect) 338 { 339 checkEq(showBytes(result), showBytes(expect)); 340 } 341 }; 342 343 static const char *defaultBasicSettingsXML = R"( 344 <BooleanParameter Name="bool">0</BooleanParameter> 345 <BooleanParameter Name="bool_array">0 0</BooleanParameter> 346 <IntegerParameter Name="integer">33</IntegerParameter> 347 <IntegerParameter Name="integer_array">-10 -10 -10 -10</IntegerParameter> 348 <FixedPointParameter Name="fix_point">0.0000</FixedPointParameter> 349 <FixedPointParameter Name="fix_point_array">0.0000 0.0000 0.0000</FixedPointParameter> 350 <EnumParameter Name="enum">min</EnumParameter> 351 <EnumParameter Name="enum_array">eight eight eight eight</EnumParameter> 352 <StringParameter Name="string"></StringParameter> 353 <BitParameterBlock Name="bit_block"> 354 <BitParameter Name="one">0</BitParameter> 355 <BitParameter Name="two">0</BitParameter> 356 <BitParameter Name="six">0</BitParameter> 357 <BitParameter Name="sixteen">0</BitParameter> 358 <BitParameter Name="thirty_two">0</BitParameter> 359 </BitParameterBlock> 360 )"; 361 362 static const char *testBasicSettingsXML = R"( 363 <BooleanParameter Name="bool">1</BooleanParameter> 364 <BooleanParameter Name="bool_array">0 1</BooleanParameter> 365 <IntegerParameter Name="integer">100</IntegerParameter> 366 <IntegerParameter Name="integer_array">-10 0 8 10</IntegerParameter> 367 <FixedPointParameter Name="fix_point">2.2500</FixedPointParameter> 368 <FixedPointParameter Name="fix_point_array">7.1250 0.6875 -1.0000</FixedPointParameter> 369 <EnumParameter Name="enum">five</EnumParameter> 370 <EnumParameter Name="enum_array">eight min eight min</EnumParameter> 371 <StringParameter Name="string">A string of 32 character.@@@@@@@</StringParameter> 372 <BitParameterBlock Name="bit_block"> 373 <BitParameter Name="one">1</BitParameter> 374 <BitParameter Name="two">2</BitParameter> 375 <BitParameter Name="six">10</BitParameter> 376 <BitParameter Name="sixteen">72</BitParameter> 377 <BitParameter Name="thirty_two">4294967295</BitParameter> 378 </BitParameterBlock> 379 )"; 380 static const char *testRawHexBasicSettingsXML = R"( 381 <BooleanParameter Name="bool">0x1</BooleanParameter> 382 <BooleanParameter Name="bool_array">0x0 0x1</BooleanParameter> 383 <IntegerParameter Name="integer">0x0064</IntegerParameter> 384 <IntegerParameter Name="integer_array">0xFFFFFFF6 0x00000000 0x00000008 0x0000000A</IntegerParameter> 385 <FixedPointParameter ValueSpace="Raw" Name="fix_point">0x24000000</FixedPointParameter> 386 <FixedPointParameter ValueSpace="Raw" Name="fix_point_array">0x72000000 0x0B000000 0xF0000000</FixedPointParameter> 387 <EnumParameter Name="enum">five</EnumParameter> 388 <EnumParameter Name="enum_array">eight min eight min</EnumParameter> 389 <StringParameter Name="string">A string of 32 character.@@@@@@@</StringParameter> 390 <BitParameterBlock Name="bit_block"> 391 <BitParameter Name="one">0x1</BitParameter> 392 <BitParameter Name="two">0x2</BitParameter> 393 <BitParameter Name="six">0xA</BitParameter> 394 <BitParameter Name="sixteen">0x48</BitParameter> 395 <BitParameter Name="thirty_two">0xFFFFFFFF</BitParameter> 396 </BitParameterBlock> 397 )"; 398 399 SCENARIO_METHOD(SettingsTestPF, "Export and import XML settings", "[handler][settings][xml]") 400 { 401 WHEN ("Exporting root XML") { __anon46fdb7160102(string path) 402 auto getAsXML = [this](string path) { return ElementHandle(*this, path).getAsXML(); }; 403 CHECK(getAsXML("/") == getAsXML("/test")); 404 checkXMLEq(getAsXML("/"), fullXMLSettings(defaultBasicSettingsXML)); 405 } 406 407 ElementHandle basicParams(*this, "/test/test/parameter_block"); 408 WHEN ("Exporting basic parameter XML") { 409 checkXMLEq(basicParams.getAsXML(), 410 mkBasicSettings(defaultBasicSettingsXML, "parameter_block")); 411 } 412 string testSettings = mkBasicSettings(testBasicSettingsXML, "parameter_block"); 413 string rawTestSettings = mkBasicSettings(testRawHexBasicSettingsXML, "parameter_block"); 414 __anon46fdb7160202null415 auto checkExport = [&] { 416 THEN ("Exported settings should be the ones imported") { 417 checkXMLEq(basicParams.getAsXML(), testSettings); 418 } 419 THEN ("Exported raw settings should be the ones imported") { 420 setRawValueSpace(true); 421 setHexOutputFormat(true); 422 checkXMLEq(basicParams.getAsXML(), rawTestSettings); 423 } 424 }; 425 WHEN ("Importing basic parameter XML") { 426 CHECK_NOTHROW(basicParams.setAsXML(testSettings)); 427 checkExport(); 428 } 429 WHEN ("Importing raw basic parameter XML") { 430 CHECK_NOTHROW(basicParams.setAsXML(rawTestSettings)); 431 checkExport(); 432 } 433 } 434 435 static const string defaultBasicSettingsBytes = 436 "00 00 00 21 00 f6 ff ff ff f6 ff ff ff f6 ff ff ff f6 ff ff ff 00 00 00 00 " 437 "00 00 00 00 00 00 00 00 00 00 00 00 80 08 00 08 00 08 00 08 00 00 00 00 00 00 " 438 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 439 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 440 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "; 441 442 static const string testBasicSettingsBytes = 443 "01 00 01 64 00 f6 ff ff ff 00 00 00 00 08 00 00 00 0a 00 00 00 00 00 00 24 " 444 "00 00 00 72 00 00 00 0b 00 00 00 f0 05 08 00 01 80 08 00 01 80 41 20 73 74 72 " 445 "69 6e 67 20 6f 66 20 33 32 20 63 68 61 72 61 63 74 65 72 2e 40 40 40 40 40 40 " 446 "40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 447 "00 00 00 00 00 00 00 8a 02 48 00 ff ff ff ff "; 448 449 SCENARIO_METHOD(SettingsTestPF, "Bijection of binary show and read", "[identity][test]") 450 { 451 CHECK(showBytes(readBytes(testBasicSettingsBytes)) == testBasicSettingsBytes); 452 } 453 454 SCENARIO_METHOD(SettingsTestPF, "Export and import root binary settings", 455 "[handler][settings][bytes]") 456 { 457 ElementHandle root(*this, "/"); 458 ElementHandle systemClass(*this, "/"); 459 460 THEN ("Root and system class should export the same binary") { 461 checkBytesEq(root.getAsBytes(), systemClass.getAsBytes()); 462 } 463 WHEN ("Exporting root binary") { 464 checkBytesEq(root.getAsBytes(), fullBytesSettings(defaultBasicSettingsBytes)); 465 } 466 WHEN ("Importing root binary") { 467 string rootTestSettings = fullBytesSettings(testBasicSettingsBytes); 468 REQUIRE_NOTHROW(root.setAsBytes(readBytes(rootTestSettings))); 469 THEN ("Exported settings should be the ones imported") { 470 checkBytesEq(root.getAsBytes(), rootTestSettings); 471 } 472 } 473 } 474 475 SCENARIO_METHOD(SettingsTestPF, "Export and import basic binary settings", 476 "[handler][settings][bytes]") 477 { 478 ElementHandle basicParams(*this, "/test/test/parameter_block"); 479 WHEN ("Exporting basic parameter binary") { 480 checkBytesEq(basicParams.getAsBytes(), defaultBasicSettingsBytes); 481 } 482 WHEN ("Importing basic parameter binary") { 483 REQUIRE_NOTHROW(basicParams.setAsBytes(readBytes(testBasicSettingsBytes))); 484 THEN ("Exported settings should be the ones imported") { 485 checkBytesEq(basicParams.getAsBytes(), testBasicSettingsBytes); 486 } 487 } 488 } 489 490 SCENARIO_METHOD(SettingsTestPF, "Export and import array binary settings", 491 "[handler][settings][bytes]") 492 { 493 ElementHandle array(*this, "/test/test/parameter_block_array"); 494 ElementHandle elem0(*this, "/test/test/parameter_block_array/0"); 495 WHEN ("Importing one array element") { 496 REQUIRE_NOTHROW(elem0.setAsBytes(readBytes(testBasicSettingsBytes))); 497 THEN ("The other element should not have changed") { 498 checkBytesEq(array.getAsBytes(), testBasicSettingsBytes + defaultBasicSettingsBytes); 499 } 500 } 501 } 502 503 SCENARIO_METHOD(SettingsTestPF, "Import root in one format, export in an other", 504 "[handler][settings][bytes][xml]") 505 { 506 ElementHandle root(*this, "/test"); 507 string rootBytesSettings = fullBytesSettings(testBasicSettingsBytes); 508 string rootXMLSettings = fullXMLSettings(testBasicSettingsXML); 509 510 WHEN ("Importing root binary") { 511 REQUIRE_NOTHROW(root.setAsBytes(readBytes(rootBytesSettings))); 512 THEN ("Exported XML settings should be the ones imported") { 513 checkXMLEq(root.getAsXML(), rootXMLSettings); 514 } 515 } 516 517 WHEN ("Importing root XML") { 518 REQUIRE_NOTHROW(root.setAsXML(rootXMLSettings)); 519 THEN ("Exported bytes settings should be the ones imported") { 520 checkBytesEq(root.getAsBytes(), rootBytesSettings); 521 } 522 } 523 } 524 525 SCENARIO_METHOD(SettingsTestPF, "Import basic params in one format, export in an other", 526 "[handler][settings][bytes][xml]") 527 { 528 ElementHandle basicParams(*this, "/test/test/parameter_block_array/0"); 529 string basicXMLSettings = mkBasicSettings(testBasicSettingsXML, "0"); 530 531 WHEN ("Importing basic parameters binary") { 532 REQUIRE_NOTHROW(basicParams.setAsBytes(readBytes(testBasicSettingsBytes))); 533 THEN ("Exported XML settings should be the ones imported") { 534 checkXMLEq(basicParams.getAsXML(), basicXMLSettings); 535 } 536 } 537 538 WHEN ("Importing basic parameters XML") { 539 REQUIRE_NOTHROW(basicParams.setAsXML(basicXMLSettings)); 540 THEN ("Exported bytes settings should be the ones imported") { 541 checkBytesEq(basicParams.getAsBytes(), testBasicSettingsBytes); 542 } 543 } 544 } 545 546 struct MappingPF : public ParameterFramework 547 { MappingPFparameterFramework::MappingPF548 MappingPF() : ParameterFramework{getConfig()} { REQUIRE_NOTHROW(start()); } 549 550 struct TestVector 551 { 552 string path; 553 string humanReadable; 554 list<string> valid; 555 list<string> invalid; 556 }; 557 558 list<TestVector> testVectors = { 559 // clang-format off 560 {"/test/test", 561 {"rootK:rootV"}, 562 {"root"}, 563 {"param", "type", "instance", "derived"}}, 564 {"/test/test/param", 565 {"rootK:rootV, paramK:paramV"}, 566 {"root", "param"}, 567 {"type", "derived", "instance"}}, 568 {"/test/test/component", 569 {"rootK:rootV, typeK:typeV, derivedK:derivedV, instanceK:instanceV"}, 570 {"root", "type", "derived", "instance"}, 571 {"param"}} 572 // clang-format on 573 }; 574 getConfigparameterFramework::MappingPF575 Config getConfig() 576 { 577 Config config; 578 config.subsystemMapping = "rootK:rootV"; 579 config.components = "<ComponentType Name='componentType' Mapping='typeK:typeV' />" 580 "<ComponentType Extends='componentType' Name='derivedComponentType' " 581 "Mapping='derivedK:derivedV' />"; 582 config.instances = "<BooleanParameter Name='param' Mapping='paramK:paramV' />" 583 "<Component Name='component' Mapping='instanceK:instanceV' " 584 " Type='derivedComponentType' />"; 585 return config; 586 } 587 }; 588 589 SCENARIO_METHOD(MappingPF, "showMapping command", "[mapping]") 590 { 591 auto cmdHandler = std::unique_ptr<CommandHandlerInterface>(createCommandHandler()); 592 593 for (auto &testVector : testVectors) { 594 string output; 595 CHECK(cmdHandler->process("showMapping", {testVector.path}, output)); 596 CHECK(output == testVector.humanReadable); 597 } 598 } 599 600 SCENARIO_METHOD(MappingPF, "Mapping handle access", "[handler][mapping]") 601 { 602 GIVEN ("A PF with mappings") { 603 for (auto &test : testVectors) { 604 GIVEN ("An element handle of " + test.path) { 605 ElementHandle handle(*this, test.path); 606 607 for (auto &valid : test.valid) { 608 THEN ("The following mapping should exist: " + valid) { 609 CHECK(handle.getMappingData(valid + "K") == valid + "V"); 610 } 611 } 612 613 for (auto &invalid : test.invalid) { 614 THEN ("The following mapping should not exist: " + invalid) { 615 CHECK_THROWS_AS(handle.getMappingData(invalid + "K"), Exception); 616 } 617 } 618 } 619 } 620 } 621 } 622 623 SCENARIO_METHOD(SettingsTestPF, "Handle Get/Set as various kinds", "[handler][dynamic]") 624 { 625 ElementHandle intScalar(*this, "/test/test/parameter_block/integer"); 626 WHEN ("Setting a scalar integer") { 627 WHEN ("As an array") { 628 THEN ("It should fail") { 629 CHECK_THROWS(intScalar.setAsIntegerArray({0, 0})); 630 } 631 } 632 WHEN ("As a scalalar") { 633 THEN ("It should succeed") { 634 uint32_t expected = 111; 635 CHECK_NOTHROW(intScalar.setAsInteger(expected)); 636 AND_THEN ("Getting it back should give the same value") { 637 uint32_t back = 42; 638 CHECK_NOTHROW(intScalar.getAsInteger(back)); 639 CHECK(back == expected); 640 } 641 } 642 } 643 } 644 645 ElementHandle intArray(*this, "/test/test/parameter_block/integer_array"); 646 WHEN ("Setting a array integer") { 647 WHEN ("As a scalar") { 648 THEN ("It should fail") { 649 CHECK_THROWS(intArray.setAsSignedInteger(0)); 650 } 651 } 652 WHEN ("As a integer") { 653 THEN ("It should succeed") { 654 const std::vector<int32_t> expected = {-9, 8, -7, 6}; 655 CHECK_NOTHROW(intArray.setAsSignedIntegerArray(expected)); 656 AND_THEN ("Getting it back should give the same value") { 657 std::vector<int32_t> back = {-42, 42, 43, -43}; 658 CHECK_NOTHROW(intArray.getAsSignedIntegerArray(back)); 659 CHECK(back == expected); 660 } 661 } 662 } 663 } 664 } 665 } // namespace parameterFramework 666