666 lines
27 KiB
C++
666 lines
27 KiB
C++
/*
|
|
* 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
|