Home | History | Annotate | Download | only in functional-tests
      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 {
     58     AllParamsPF() : ParameterFramework{getConfig()} { REQUIRE_NOTHROW(start()); }
     59 
     60     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 
     97     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 
    110     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      */
    118     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 
    153     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 
    182     static void checkXMLEq(const string &result, const string &expected)
    183     {
    184         checkEq(canonicalizeXML(result), canonicalizeXML(expected));
    185     }
    186 
    187     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      */
    197     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 
    207     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 {
    272     static string parameterBlockNode(string name, string settings)
    273     {
    274         return node("ParameterBlock", name, settings);
    275     };
    276     static string mkBasicSettings(string settings, string name)
    277     {
    278         return rootNode("ParameterBlock", "Name='" + name + "'", settings);
    279     }
    280 
    281     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 
    295     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. */
    307     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 
    318     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 
    333     static void checkBytesEq(const Bytes &result, const string &expect)
    334     {
    335         checkEq(showBytes(result), expect);
    336     }
    337     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") {
    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 
    415     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 {
    548     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 
    575     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