| /* |
| * Copyright (c) 2015, Intel Corporation |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation and/or |
| * other materials provided with the distribution. |
| * |
| * 3. Neither the name of the copyright holder nor the names of its contributors |
| * may be used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "Config.hpp" |
| #include "Test.hpp" |
| #include "Exception.hpp" |
| #include "TmpFile.hpp" |
| |
| #include "ParameterFramework.hpp" |
| #include "ElementHandle.hpp" |
| |
| #include <catch.hpp> |
| |
| #include <libxml/parser.h> |
| #include <libxml/tree.h> |
| |
| #include <string> |
| #include <list> |
| |
| #include <stdlib.h> |
| |
| using std::string; |
| using std::list; |
| using Bytes = std::vector<uint8_t>; |
| |
| namespace parameterFramework |
| { |
| |
| struct AllParamsPF : public ParameterFramework |
| { |
| AllParamsPF() : ParameterFramework{getConfig()} { REQUIRE_NOTHROW(start()); } |
| |
| string getBasicParams() |
| { |
| string structure = R"( |
| <BooleanParameter Name="bool" Description="bool"/> |
| <BooleanParameter ArrayLength="2" Name="bool_array" Description="bool-array"/> |
| |
| <IntegerParameter Signed="false" Min="33" Max="123" Size="16" Name="integer"/> |
| <IntegerParameter Signed="true" Min="-10" Max="10" Size="32" ArrayLength="4" Name="integer_array"/> |
| |
| <FixedPointParameter Size="32" Integral="3" Fractional="4" Name="fix_point"/> |
| <FixedPointParameter Size="32" Integral="3" Fractional="4" ArrayLength="3" Name="fix_point_array"/> |
| |
| <EnumParameter Size="8" Name="enum"> |
| <ValuePair Literal="min" Numerical="-128"/> |
| <ValuePair Literal="five" Numerical="5"/> |
| <ValuePair Literal="max" Numerical="127"/> |
| </EnumParameter> |
| <EnumParameter Size="16" ArrayLength="4" Name="enum_array"> |
| <ValuePair Literal="eight" Numerical="8"/> |
| <ValuePair Literal="min" Numerical="-32767"/> |
| </EnumParameter>)"; |
| |
| // String and bit parameter arrays are not supported |
| structure += R"( |
| <StringParameter MaxLength="63" Name="string"/> |
| |
| <BitParameterBlock Size="64" Name="bit_block"> |
| <BitParameter Pos="1" Size="1" Max="1" Name="one"/> |
| <BitParameter Pos="2" Size="2" Max="2" Name="two"/> |
| <BitParameter Pos="6" Size="6" Max="10" Name="six"/> |
| <BitParameter Pos="16" Size="16" Max="99" Name="sixteen"/> |
| <BitParameter Pos="32" Size="32" Max="4294967295" Name="thirty_two"/> |
| </BitParameterBlock> |
| )"; |
| return structure; |
| } |
| |
| Config getConfig() |
| { |
| Config config; |
| config.components = nodeDesc("ComponentType", "component_type", getBasicParams()); |
| config.instances = |
| getBasicParams() + nodeDesc("ParameterBlock", "parameter_block", getBasicParams()) + |
| nodeDesc("ParameterBlock", "parameter_block_array", getBasicParams(), |
| "ArrayLength='2'") + |
| nodeDesc("Component", "component_scalar", "", "Type='component_type'") + |
| nodeDesc("Component", "component_array", "", "Type='component_type' ArrayLength='2'"); |
| return config; |
| } |
| |
| void checkStructure(const string &path, const string &expected) |
| { |
| CHECK_NOTHROW(checkXMLEq(ElementHandle{*this, path}.getStructureAsXML(), expected)); |
| } |
| |
| /** Use libxml2 to pretty format xml. |
| * Equivalent of xmllint --format |
| */ |
| static string canonicalizeXML(const string &xml) |
| { |
| // Parse xml |
| // Might be better to specialize std::default_delete<xmlDoc>. |
| std::unique_ptr<xmlDoc, void (*)(xmlDoc *)> doc{ |
| xmlReadMemory(xml.c_str(), (int)xml.length(), "structure.xml", nullptr, |
| XML_PARSE_NOBLANKS), |
| xmlFreeDoc}; |
| if (doc == nullptr) { |
| throw Exception{"Failed to parse document: " + xml}; |
| } |
| |
| // Dump it formated |
| int size; |
| |
| // Need to use exception unsafe raw pointer as of libxml2 c api |
| xmlChar *unsafeFormated; |
| |
| // TODO: Should use canonicalization (aka c14n). |
| // cf: http://xmlsoft.org/html/libxml-c14n.html |
| // https://en.wikipedia.org/wiki/Canonical_XML |
| // Additionally to what is listed on that page, |
| // attributes are also ordered deterministically. |
| // That would solve the workaround in the node function with pre/post attributes. |
| // Unfortunately c14n is not available in appveyor (Windows CI) libxml2 prebuild |
| xmlDocDumpFormatMemoryEnc(doc.get(), &unsafeFormated, &size, "UTF-8", 1); |
| std::unique_ptr<xmlChar, void (*)(void *)> formated{unsafeFormated, xmlFree}; |
| |
| if (formated == nullptr) { |
| throw Exception{"Could not dump xml: " + xml}; |
| } |
| |
| return string{(char *)formated.get()}; |
| } |
| |
| static void checkEq(const string &result, const string &expected) |
| { |
| CHECK(result == expected); |
| |
| // Pretty print the word differences with colors |
| // It does not matter if it fails as the test would still fail |
| // due to the above CHECK. |
| if (result != expected) { |
| utility::TmpFile resultFile(result); |
| utility::TmpFile expectedFile(expected); |
| string command = "git --no-pager diff --word-diff-regex='[^ <>]+'" |
| " --color --no-index --exit-code " + |
| resultFile.getPath() + ' ' + expectedFile.getPath(); |
| |
| // `system` return -1 or 127 on failure, the command error code otherwise |
| // `git diff` return 1 if the files are the different (thanks to --exit-code) |
| auto status = system(command.c_str()); |
| #ifdef WIFEXITED // Posix platform |
| bool success = WIFEXITED(status) and WEXITSTATUS(status) == 1; |
| #else |
| bool success = status == 1; |
| #endif |
| if (not success) { |
| WARN("Warning: Failed to pretty-print the difference between " |
| "actual and expected results with `git diff'"); |
| } |
| } |
| } |
| |
| static void checkXMLEq(const string &result, const string &expected) |
| { |
| checkEq(canonicalizeXML(result), canonicalizeXML(expected)); |
| } |
| |
| static string node(string tag, string name, string content, string attributes = "", |
| string postAttributes = "") |
| { |
| return "<" + tag + " " + attributes + " Name='" + name + "' " + postAttributes + ">" + |
| content + "</" + tag + ">"; |
| } |
| /** Node with a description. |
| * @param[in] maybeDescription If nullptr, description will be generated from the name |
| * Otherwise, the description. |
| */ |
| static string nodeDesc(string tag, string name, string content, string attributes = "", |
| const char *maybeDescription = nullptr) |
| { |
| string description = "description_" + name; |
| if (maybeDescription != nullptr) { |
| description = maybeDescription; |
| } |
| return node(tag, name, content, attributes, "Description='" + description + "'"); |
| } |
| |
| static string rootNode(string name, string attributes, string content) |
| { |
| return '<' + name + ' ' + attributes + '>' + content + "</" + name + '>'; |
| } |
| }; |
| |
| SCENARIO_METHOD(AllParamsPF, "Export boolean", "[handler][structure][xml]") |
| { |
| string expected = rootNode("BooleanParameter", "Name='bool' Description='bool'", ""); |
| checkStructure("/test/test/bool", expected); |
| } |
| |
| SCENARIO_METHOD(AllParamsPF, "Export component", "[handler][structure][xml]") |
| { |
| string expected = rootNode("ParameterBlock", "Name='component_scalar' " |
| "Description='description_component_scalar'", |
| getBasicParams()); |
| checkStructure("/test/test/component_scalar", expected); |
| } |
| |
| SCENARIO_METHOD(AllParamsPF, "Export component array", "[handler][structure][xml]") |
| { |
| string expected = rootNode( |
| "ParameterBlock", "Name='component_array' Description='description_component_array'", |
| nodeDesc("ParameterBlock", "0", getBasicParams(), "", "description_component_array") + |
| nodeDesc("ParameterBlock", "1", getBasicParams(), "", "description_component_array")); |
| checkStructure("/test/test/component_array", expected); |
| } |
| |
| SCENARIO_METHOD(AllParamsPF, "Export all parameters", "[handler][structure][xml]") |
| { |
| string paramExpected = getBasicParams() + |
| nodeDesc("ParameterBlock", "parameter_block", getBasicParams()) + |
| nodeDesc("ParameterBlock", "parameter_block_array", |
| nodeDesc("ParameterBlock", "0", getBasicParams(), "", |
| // description is inherited from array |
| "description_parameter_block_array") + |
| nodeDesc("ParameterBlock", "1", getBasicParams(), "", |
| "description_parameter_block_array")) + |
| // Components should be exported as parameterBlock |
| nodeDesc("ParameterBlock", "component_scalar", getBasicParams()) + |
| nodeDesc("ParameterBlock", "component_array", |
| nodeDesc("ParameterBlock", "0", getBasicParams(), "", |
| // description is inherited from array |
| "description_component_array") + |
| nodeDesc("ParameterBlock", "1", getBasicParams(), "", |
| "description_component_array")); |
| |
| WHEN ("Exporting subsystem") { |
| string expected = rootNode("Subsystem", "Name='test'", paramExpected); |
| checkStructure("/test/test", expected); |
| } |
| |
| WHEN ("Exporting systemClass") { |
| string expected = rootNode("SystemClass", "Name='test'", |
| "<Subsystem Name='test'>" + paramExpected + "</Subsystem>"); |
| |
| // Awkwardly, the root and its first child are the same element |
| checkStructure("/test", expected); |
| checkStructure("/", expected); |
| } |
| } |
| |
| struct SettingsTestPF : public AllParamsPF |
| { |
| static string parameterBlockNode(string name, string settings) |
| { |
| return node("ParameterBlock", name, settings); |
| }; |
| static string mkBasicSettings(string settings, string name) |
| { |
| return rootNode("ParameterBlock", "Name='" + name + "'", settings); |
| } |
| |
| static string fullXMLSettings(const string &basicSettings) |
| { |
| string settings = basicSettings; |
| settings += |
| parameterBlockNode("parameter_block", settings) + |
| parameterBlockNode("parameter_block_array", parameterBlockNode("0", settings) + |
| parameterBlockNode("1", settings)) + |
| parameterBlockNode("component_scalar", settings) + |
| parameterBlockNode("component_array", parameterBlockNode("0", settings) + |
| parameterBlockNode("1", settings)); |
| |
| return rootNode("SystemClass", "Name='test'", node("Subsystem", "test", settings, "")); |
| } |
| |
| static string fullBytesSettings(const string &basicSettings) |
| { |
| string fullSettings; |
| // We have the "basic params" repeated 7 times across the test |
| // structure |
| for (size_t i = 0; i < 7; ++i) { |
| fullSettings += basicSettings; |
| } |
| return fullSettings; |
| } |
| |
| /** Print Bytes as string separated hexadecimal number. */ |
| static string showBytes(const Bytes &bytes) |
| { |
| using namespace std; |
| ostringstream ss; |
| ss.exceptions(ostream::badbit | ostream::failbit); |
| for (auto byte : bytes) { |
| ss << hex << setw(2) << setfill('0') << int{byte} << ' '; |
| } |
| return ss.str(); |
| } |
| |
| static Bytes readBytes(const string &strBytes) |
| { |
| using namespace std; |
| istringstream ss{strBytes}; |
| ss.exceptions(istream::badbit | istream::failbit); |
| Bytes bytes(strBytes.size() / 3); |
| |
| for (auto &byte : bytes) { |
| uint16_t notCharByte; |
| ss >> hex >> setw(2) >> notCharByte; |
| byte = static_cast<char>(notCharByte); |
| } |
| return bytes; |
| } |
| |
| static void checkBytesEq(const Bytes &result, const string &expect) |
| { |
| checkEq(showBytes(result), expect); |
| } |
| static void checkBytesEq(const Bytes &result, const Bytes &expect) |
| { |
| checkEq(showBytes(result), showBytes(expect)); |
| } |
| }; |
| |
| static const char *defaultBasicSettingsXML = R"( |
| <BooleanParameter Name="bool">0</BooleanParameter> |
| <BooleanParameter Name="bool_array">0 0</BooleanParameter> |
| <IntegerParameter Name="integer">33</IntegerParameter> |
| <IntegerParameter Name="integer_array">-10 -10 -10 -10</IntegerParameter> |
| <FixedPointParameter Name="fix_point">0.0000</FixedPointParameter> |
| <FixedPointParameter Name="fix_point_array">0.0000 0.0000 0.0000</FixedPointParameter> |
| <EnumParameter Name="enum">min</EnumParameter> |
| <EnumParameter Name="enum_array">eight eight eight eight</EnumParameter> |
| <StringParameter Name="string"></StringParameter> |
| <BitParameterBlock Name="bit_block"> |
| <BitParameter Name="one">0</BitParameter> |
| <BitParameter Name="two">0</BitParameter> |
| <BitParameter Name="six">0</BitParameter> |
| <BitParameter Name="sixteen">0</BitParameter> |
| <BitParameter Name="thirty_two">0</BitParameter> |
| </BitParameterBlock> |
| )"; |
| |
| static const char *testBasicSettingsXML = R"( |
| <BooleanParameter Name="bool">1</BooleanParameter> |
| <BooleanParameter Name="bool_array">0 1</BooleanParameter> |
| <IntegerParameter Name="integer">100</IntegerParameter> |
| <IntegerParameter Name="integer_array">-10 0 8 10</IntegerParameter> |
| <FixedPointParameter Name="fix_point">2.2500</FixedPointParameter> |
| <FixedPointParameter Name="fix_point_array">7.1250 0.6875 -1.0000</FixedPointParameter> |
| <EnumParameter Name="enum">five</EnumParameter> |
| <EnumParameter Name="enum_array">eight min eight min</EnumParameter> |
| <StringParameter Name="string">A string of 32 character.@@@@@@@</StringParameter> |
| <BitParameterBlock Name="bit_block"> |
| <BitParameter Name="one">1</BitParameter> |
| <BitParameter Name="two">2</BitParameter> |
| <BitParameter Name="six">10</BitParameter> |
| <BitParameter Name="sixteen">72</BitParameter> |
| <BitParameter Name="thirty_two">4294967295</BitParameter> |
| </BitParameterBlock> |
| )"; |
| static const char *testRawHexBasicSettingsXML = R"( |
| <BooleanParameter Name="bool">0x1</BooleanParameter> |
| <BooleanParameter Name="bool_array">0x0 0x1</BooleanParameter> |
| <IntegerParameter Name="integer">0x0064</IntegerParameter> |
| <IntegerParameter Name="integer_array">0xFFFFFFF6 0x00000000 0x00000008 0x0000000A</IntegerParameter> |
| <FixedPointParameter ValueSpace="Raw" Name="fix_point">0x24000000</FixedPointParameter> |
| <FixedPointParameter ValueSpace="Raw" Name="fix_point_array">0x72000000 0x0B000000 0xF0000000</FixedPointParameter> |
| <EnumParameter Name="enum">0x05</EnumParameter> |
| <EnumParameter Name="enum_array">0x0008 0x8001 0x0008 0x8001</EnumParameter> |
| <StringParameter Name="string">A string of 32 character.@@@@@@@</StringParameter> |
| <BitParameterBlock Name="bit_block"> |
| <BitParameter Name="one">0x1</BitParameter> |
| <BitParameter Name="two">0x2</BitParameter> |
| <BitParameter Name="six">0xA</BitParameter> |
| <BitParameter Name="sixteen">0x48</BitParameter> |
| <BitParameter Name="thirty_two">0xFFFFFFFF</BitParameter> |
| </BitParameterBlock> |
| )"; |
| |
| SCENARIO_METHOD(SettingsTestPF, "Export and import XML settings", "[handler][settings][xml]") |
| { |
| WHEN ("Exporting root XML") { |
| auto getAsXML = [this](string path) { return ElementHandle(*this, path).getAsXML(); }; |
| CHECK(getAsXML("/") == getAsXML("/test")); |
| checkXMLEq(getAsXML("/"), fullXMLSettings(defaultBasicSettingsXML)); |
| } |
| |
| ElementHandle basicParams(*this, "/test/test/parameter_block"); |
| WHEN ("Exporting basic parameter XML") { |
| checkXMLEq(basicParams.getAsXML(), |
| mkBasicSettings(defaultBasicSettingsXML, "parameter_block")); |
| } |
| string testSettings = mkBasicSettings(testBasicSettingsXML, "parameter_block"); |
| string rawTestSettings = mkBasicSettings(testRawHexBasicSettingsXML, "parameter_block"); |
| |
| auto checkExport = [&] { |
| THEN ("Exported settings should be the ones imported") { |
| checkXMLEq(basicParams.getAsXML(), testSettings); |
| } |
| THEN ("Exported raw settings should be the ones imported") { |
| setRawValueSpace(true); |
| setHexOutputFormat(true); |
| checkXMLEq(basicParams.getAsXML(), rawTestSettings); |
| } |
| }; |
| WHEN ("Importing basic parameter XML") { |
| CHECK_NOTHROW(basicParams.setAsXML(testSettings)); |
| checkExport(); |
| } |
| WHEN ("Importing raw basic parameter XML") { |
| CHECK_NOTHROW(basicParams.setAsXML(rawTestSettings)); |
| checkExport(); |
| } |
| } |
| |
| static const string defaultBasicSettingsBytes = |
| "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 " |
| "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 " |
| "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 " |
| "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 " |
| "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "; |
| |
| static const string testBasicSettingsBytes = |
| "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 " |
| "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 " |
| "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 " |
| "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 " |
| "00 00 00 00 00 00 00 8a 02 48 00 ff ff ff ff "; |
| |
| SCENARIO_METHOD(SettingsTestPF, "Bijection of binary show and read", "[identity][test]") |
| { |
| CHECK(showBytes(readBytes(testBasicSettingsBytes)) == testBasicSettingsBytes); |
| } |
| |
| SCENARIO_METHOD(SettingsTestPF, "Export and import root binary settings", |
| "[handler][settings][bytes]") |
| { |
| ElementHandle root(*this, "/"); |
| ElementHandle systemClass(*this, "/"); |
| |
| THEN ("Root and system class should export the same binary") { |
| checkBytesEq(root.getAsBytes(), systemClass.getAsBytes()); |
| } |
| WHEN ("Exporting root binary") { |
| checkBytesEq(root.getAsBytes(), fullBytesSettings(defaultBasicSettingsBytes)); |
| } |
| WHEN ("Importing root binary") { |
| string rootTestSettings = fullBytesSettings(testBasicSettingsBytes); |
| REQUIRE_NOTHROW(root.setAsBytes(readBytes(rootTestSettings))); |
| THEN ("Exported settings should be the ones imported") { |
| checkBytesEq(root.getAsBytes(), rootTestSettings); |
| } |
| } |
| } |
| |
| SCENARIO_METHOD(SettingsTestPF, "Export and import basic binary settings", |
| "[handler][settings][bytes]") |
| { |
| ElementHandle basicParams(*this, "/test/test/parameter_block"); |
| WHEN ("Exporting basic parameter binary") { |
| checkBytesEq(basicParams.getAsBytes(), defaultBasicSettingsBytes); |
| } |
| WHEN ("Importing basic parameter binary") { |
| REQUIRE_NOTHROW(basicParams.setAsBytes(readBytes(testBasicSettingsBytes))); |
| THEN ("Exported settings should be the ones imported") { |
| checkBytesEq(basicParams.getAsBytes(), testBasicSettingsBytes); |
| } |
| } |
| } |
| |
| SCENARIO_METHOD(SettingsTestPF, "Export and import array binary settings", |
| "[handler][settings][bytes]") |
| { |
| ElementHandle array(*this, "/test/test/parameter_block_array"); |
| ElementHandle elem0(*this, "/test/test/parameter_block_array/0"); |
| WHEN ("Importing one array element") { |
| REQUIRE_NOTHROW(elem0.setAsBytes(readBytes(testBasicSettingsBytes))); |
| THEN ("The other element should not have changed") { |
| checkBytesEq(array.getAsBytes(), testBasicSettingsBytes + defaultBasicSettingsBytes); |
| } |
| } |
| } |
| |
| SCENARIO_METHOD(SettingsTestPF, "Import root in one format, export in an other", |
| "[handler][settings][bytes][xml]") |
| { |
| ElementHandle root(*this, "/test"); |
| string rootBytesSettings = fullBytesSettings(testBasicSettingsBytes); |
| string rootXMLSettings = fullXMLSettings(testBasicSettingsXML); |
| |
| WHEN ("Importing root binary") { |
| REQUIRE_NOTHROW(root.setAsBytes(readBytes(rootBytesSettings))); |
| THEN ("Exported XML settings should be the ones imported") { |
| checkXMLEq(root.getAsXML(), rootXMLSettings); |
| } |
| } |
| |
| WHEN ("Importing root XML") { |
| REQUIRE_NOTHROW(root.setAsXML(rootXMLSettings)); |
| THEN ("Exported bytes settings should be the ones imported") { |
| checkBytesEq(root.getAsBytes(), rootBytesSettings); |
| } |
| } |
| } |
| |
| SCENARIO_METHOD(SettingsTestPF, "Import basic params in one format, export in an other", |
| "[handler][settings][bytes][xml]") |
| { |
| ElementHandle basicParams(*this, "/test/test/parameter_block_array/0"); |
| string basicXMLSettings = mkBasicSettings(testBasicSettingsXML, "0"); |
| |
| WHEN ("Importing basic parameters binary") { |
| REQUIRE_NOTHROW(basicParams.setAsBytes(readBytes(testBasicSettingsBytes))); |
| THEN ("Exported XML settings should be the ones imported") { |
| checkXMLEq(basicParams.getAsXML(), basicXMLSettings); |
| } |
| } |
| |
| WHEN ("Importing basic parameters XML") { |
| REQUIRE_NOTHROW(basicParams.setAsXML(basicXMLSettings)); |
| THEN ("Exported bytes settings should be the ones imported") { |
| checkBytesEq(basicParams.getAsBytes(), testBasicSettingsBytes); |
| } |
| } |
| } |
| |
| struct MappingPF : public ParameterFramework |
| { |
| MappingPF() : ParameterFramework{getConfig()} { REQUIRE_NOTHROW(start()); } |
| |
| struct TestVector |
| { |
| string path; |
| string humanReadable; |
| list<string> valid; |
| list<string> invalid; |
| }; |
| |
| list<TestVector> testVectors = { |
| // clang-format off |
| {"/test/test", |
| {"rootK:rootV"}, |
| {"root"}, |
| {"param", "type", "instance", "derived"}}, |
| {"/test/test/param", |
| {"rootK:rootV, paramK:paramV"}, |
| {"root", "param"}, |
| {"type", "derived", "instance"}}, |
| {"/test/test/component", |
| {"rootK:rootV, typeK:typeV, derivedK:derivedV, instanceK:instanceV"}, |
| {"root", "type", "derived", "instance"}, |
| {"param"}} |
| // clang-format on |
| }; |
| |
| Config getConfig() |
| { |
| Config config; |
| config.subsystemMapping = "rootK:rootV"; |
| config.components = "<ComponentType Name='componentType' Mapping='typeK:typeV' />" |
| "<ComponentType Extends='componentType' Name='derivedComponentType' " |
| "Mapping='derivedK:derivedV' />"; |
| config.instances = "<BooleanParameter Name='param' Mapping='paramK:paramV' />" |
| "<Component Name='component' Mapping='instanceK:instanceV' " |
| " Type='derivedComponentType' />"; |
| return config; |
| } |
| }; |
| |
| SCENARIO_METHOD(MappingPF, "showMapping command", "[mapping]") |
| { |
| auto cmdHandler = std::unique_ptr<CommandHandlerInterface>(createCommandHandler()); |
| |
| for (auto &testVector : testVectors) { |
| string output; |
| CHECK(cmdHandler->process("showMapping", {testVector.path}, output)); |
| CHECK(output == testVector.humanReadable); |
| } |
| } |
| |
| SCENARIO_METHOD(MappingPF, "Mapping handle access", "[handler][mapping]") |
| { |
| GIVEN ("A PF with mappings") { |
| for (auto &test : testVectors) { |
| GIVEN ("An element handle of " + test.path) { |
| ElementHandle handle(*this, test.path); |
| |
| for (auto &valid : test.valid) { |
| THEN ("The following mapping should exist: " + valid) { |
| CHECK(handle.getMappingData(valid + "K") == valid + "V"); |
| } |
| } |
| |
| for (auto &invalid : test.invalid) { |
| THEN ("The following mapping should not exist: " + invalid) { |
| CHECK_THROWS_AS(handle.getMappingData(invalid + "K"), Exception); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| SCENARIO_METHOD(SettingsTestPF, "Handle Get/Set as various kinds", "[handler][dynamic]") |
| { |
| ElementHandle intScalar(*this, "/test/test/parameter_block/integer"); |
| WHEN ("Setting a scalar integer") { |
| WHEN ("As an array") { |
| THEN ("It should fail") { |
| CHECK_THROWS(intScalar.setAsIntegerArray({0, 0})); |
| } |
| } |
| WHEN ("As a scalalar") { |
| THEN ("It should succeed") { |
| uint32_t expected = 111; |
| CHECK_NOTHROW(intScalar.setAsInteger(expected)); |
| AND_THEN ("Getting it back should give the same value") { |
| uint32_t back = 42; |
| CHECK_NOTHROW(intScalar.getAsInteger(back)); |
| CHECK(back == expected); |
| } |
| } |
| } |
| } |
| |
| ElementHandle intArray(*this, "/test/test/parameter_block/integer_array"); |
| WHEN ("Setting a array integer") { |
| WHEN ("As a scalar") { |
| THEN ("It should fail") { |
| CHECK_THROWS(intArray.setAsSignedInteger(0)); |
| } |
| } |
| WHEN ("As a integer") { |
| THEN ("It should succeed") { |
| const std::vector<int32_t> expected = {-9, 8, -7, 6}; |
| CHECK_NOTHROW(intArray.setAsSignedIntegerArray(expected)); |
| AND_THEN ("Getting it back should give the same value") { |
| std::vector<int32_t> back = {-42, 42, 43, -43}; |
| CHECK_NOTHROW(intArray.getAsSignedIntegerArray(back)); |
| CHECK(back == expected); |
| } |
| } |
| } |
| } |
| } |
| } // namespace parameterFramework |