/*
* 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">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">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