Files
salmanoff/commonLibs/attachmentSupport/tests/deviceAttachmentSpecParams_tests.cpp
T

414 lines
12 KiB
C++
Raw Normal View History

#include <array>
#include <gtest/gtest.h>
#include <support/exceptionAssertions.h>
#include <user/deviceAttachmentSpec.h>
#include <vector>
namespace smo {
namespace device {
namespace {
using ParamList = std::vector<std::pair<std::string, std::string>>;
ParamList makeParams(std::initializer_list<std::pair<const char*, const char*>> entries)
{
ParamList params;
for (const auto& entry : entries)
{
params.emplace_back(entry.first, entry.second);
}
return params;
}
TEST(DeviceAttachmentSpecNamesContainTest, MatchesVectorAndArraySynonyms)
{
const std::vector<std::string> widthSynonyms = {
"frame-width",
"dim-w",
};
EXPECT_TRUE(DeviceAttachmentSpec::namesContain(widthSynonyms, "dim-w"));
EXPECT_FALSE(DeviceAttachmentSpec::namesContain(widthSynonyms, "dim-h"));
const std::array<std::string_view, 2> heightSynonyms = {
"frame-height",
"dim-h",
};
EXPECT_TRUE(DeviceAttachmentSpec::namesContain(heightSynonyms, "frame-height"));
EXPECT_FALSE(DeviceAttachmentSpec::namesContain(heightSynonyms, "frame-width"));
}
TEST(DeviceAttachmentSpecParamsContainTest, DetectsExactParamName)
{
const ParamList params = makeParams({
{"display", "0"},
{"screen", "1"},
});
EXPECT_TRUE(DeviceAttachmentSpec::paramsContain(params, "display"));
EXPECT_TRUE(DeviceAttachmentSpec::paramsContain(params, "screen"));
EXPECT_FALSE(DeviceAttachmentSpec::paramsContain(params, "width"));
}
TEST(DeviceAttachmentSpecParamNameMatchesAnySynonymGroupTest, MatchesAcrossGroups)
{
const std::vector<std::string> widthSynonyms = {"dim-w", "frame-w"};
const std::vector<std::string> heightSynonyms = {"dim-h", "frame-h"};
EXPECT_TRUE(DeviceAttachmentSpec::paramNameMatchesAnySynonymGroup(
"dim-w", widthSynonyms, heightSynonyms));
EXPECT_TRUE(DeviceAttachmentSpec::paramNameMatchesAnySynonymGroup(
"frame-h", widthSynonyms, heightSynonyms));
EXPECT_FALSE(DeviceAttachmentSpec::paramNameMatchesAnySynonymGroup(
"colour-space", widthSynonyms, heightSynonyms));
}
TEST(DeviceAttachmentSpecNormalizeParamTokenTest, TrimsAndLowercases)
{
EXPECT_EQ(DeviceAttachmentSpec::normalizeParamToken(" TRUE "), "true");
EXPECT_EQ(DeviceAttachmentSpec::normalizeParamToken("YUV"), "yuv");
EXPECT_EQ(DeviceAttachmentSpec::normalizeParamToken("480p"), "480p");
EXPECT_EQ(DeviceAttachmentSpec::normalizeParamToken(""), "");
}
TEST(DeviceAttachmentSpecFindOptionalParamTest, LattermostExactNameWins)
{
const ParamList params = makeParams({
{"display", "0"},
{"other", "ignored"},
{"display", "2"},
});
const std::optional<std::pair<std::string, std::string>> matched =
DeviceAttachmentSpec::findOptionalParam(params, "display");
ASSERT_TRUE(matched.has_value());
EXPECT_EQ(matched->first, "display");
EXPECT_EQ(matched->second, "2");
}
TEST(DeviceAttachmentSpecFindOptionalParamWithSynonymsTest, LattermostSynonymWins)
{
const std::vector<std::string> synonyms = {
"cmd-timeout-ms",
"command-timeout-ms",
};
const ParamList params = makeParams({
{"cmd-timeout-ms", "5"},
{"command-timeout-ms", "25"},
});
const std::optional<std::pair<std::string, std::string>> matched =
DeviceAttachmentSpec::findOptionalParamWithSynonyms(params, synonyms);
ASSERT_TRUE(matched.has_value());
EXPECT_EQ(matched->first, "command-timeout-ms");
EXPECT_EQ(matched->second, "25");
}
TEST(DeviceAttachmentSpecFindOptionalParamWithSynonymsTest, AbsentReturnsNullopt)
{
const std::vector<std::string> synonyms = {"data-port"};
const ParamList params = makeParams({{"cmd-port", "56001"}});
EXPECT_FALSE(DeviceAttachmentSpec::findOptionalParamWithSynonyms(
params, synonyms).has_value());
}
TEST(DeviceAttachmentSpecParseParamValueAsIntTest, ParsesValidInteger)
{
EXPECT_EQ(
DeviceAttachmentSpec::parseParamValueAsInt("width", "1280"),
1280);
EXPECT_EQ(
DeviceAttachmentSpec::parseParamValueAsInt("width", "-42"),
-42);
}
TEST(DeviceAttachmentSpecParseParamValueAsIntTest, InvalidIntegerThrows)
{
try {
DeviceAttachmentSpec::parseParamValueAsInt("width", "not-a-number");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "Failed to parse 'width'");
}
}
TEST(DeviceAttachmentSpecParseParamValueAsIntTest, OutOfRangeThrows)
{
try {
DeviceAttachmentSpec::parseParamValueAsInt(
"width",
"999999999999999999999");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "out of range");
}
}
TEST(DeviceAttachmentSpecParseParamValueAsPositiveIntTest, RejectsNonPositive)
{
EXPECT_EQ(
DeviceAttachmentSpec::parseParamValueAsPositiveInt("width", "640"),
640);
try {
DeviceAttachmentSpec::parseParamValueAsPositiveInt("width", "0");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "must be positive");
}
try {
DeviceAttachmentSpec::parseParamValueAsPositiveInt("width", "-10");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "must be positive");
}
}
TEST(DeviceAttachmentSpecParseParamValueAsBoolTest, ParsesRecognizedValues)
{
EXPECT_TRUE(DeviceAttachmentSpec::parseParamValueAsBool(""));
EXPECT_TRUE(DeviceAttachmentSpec::parseParamValueAsBool("true"));
EXPECT_TRUE(DeviceAttachmentSpec::parseParamValueAsBool(" YES "));
EXPECT_TRUE(DeviceAttachmentSpec::parseParamValueAsBool("1"));
EXPECT_FALSE(DeviceAttachmentSpec::parseParamValueAsBool("false"));
EXPECT_FALSE(DeviceAttachmentSpec::parseParamValueAsBool("0"));
EXPECT_FALSE(DeviceAttachmentSpec::parseParamValueAsBool("no"));
EXPECT_FALSE(DeviceAttachmentSpec::parseParamValueAsBool(
"", /*emptyMeansTrue=*/false));
}
TEST(DeviceAttachmentSpecParseParamValueAsBoolTest, UnknownValueThrows)
{
EXPECT_THROW(
DeviceAttachmentSpec::parseParamValueAsBool("maybe"),
std::runtime_error);
}
TEST(DeviceAttachmentSpecParseRequiredParamAsIntTest, MissingParamThrows)
{
const ParamList params = makeParams({{"screen", "1"}});
try {
DeviceAttachmentSpec::parseRequiredParamAsInt(params, "display");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "No display specified in params");
}
}
TEST(DeviceAttachmentSpecParseRequiredParamAsIntTest, LattermostValueWins)
{
const ParamList params = makeParams({
{"display", "0"},
{"display", "3"},
});
EXPECT_EQ(
DeviceAttachmentSpec::parseRequiredParamAsInt(params, "display"),
3);
}
TEST(DeviceAttachmentSpecParseOptionalParamAsIntTest, ReturnsDefaultWhenAbsent)
{
const ParamList params = makeParams({{"screen", "1"}});
EXPECT_EQ(
DeviceAttachmentSpec::parseOptionalParamAsInt(params, "display", 42),
42);
}
TEST(DeviceAttachmentSpecParseOptionalParamAsIntWithSynonymsTest, SynonymLattermostWins)
{
const std::vector<std::string> synonyms = {
"n-dgrams-per-frame",
"num-dgrams-per-frame",
};
const ParamList params = makeParams({
{"n-dgrams-per-frame", "10"},
{"num-dgrams-per-frame", "99"},
});
EXPECT_EQ(
DeviceAttachmentSpec::parseOptionalParamAsIntWithSynonyms(
params, synonyms, 84),
99);
}
TEST(DeviceAttachmentSpecParseRequiredParamAsIntWithSynonymsTest, ParsesMatchedSynonym)
{
const std::vector<std::string> synonyms = {
"cmd-timeout-ms",
"command-timeout-ms",
};
const ParamList params = makeParams({
{"command-timeout-ms", "15"},
});
EXPECT_EQ(
DeviceAttachmentSpec::parseRequiredParamAsIntWithSynonyms(
params,
synonyms,
"missing timeout"),
15);
}
TEST(DeviceAttachmentSpecParseRequiredParamValueWithSynonymsTest, RequiresNonEmptyValue)
{
const std::vector<std::string> synonyms = {"colour-space"};
const ParamList missing = makeParams({{"width", "640"}});
try {
DeviceAttachmentSpec::parseRequiredParamValueWithSynonyms(
missing, synonyms, "colour-space required");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "colour-space required");
}
const ParamList emptyValue = makeParams({{"colour-space", ""}});
try {
DeviceAttachmentSpec::parseRequiredParamValueWithSynonyms(
emptyValue, synonyms, "colour-space required");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "colour-space required");
}
const ParamList present = makeParams({{"colour-space", "yuv"}});
EXPECT_EQ(
DeviceAttachmentSpec::parseRequiredParamValueWithSynonyms(
present, synonyms, "colour-space required"),
"yuv");
}
TEST(DeviceAttachmentSpecParseOptionalParamValueWithSynonymsTest, OptionalStringValue)
{
const std::vector<std::string> synonyms = {"colour-space"};
const ParamList absent = makeParams({{"width", "640"}});
EXPECT_FALSE(DeviceAttachmentSpec::parseOptionalParamValueWithSynonyms(
absent, synonyms, "empty colour-space").has_value());
const ParamList emptyValue = makeParams({{"colour-space", ""}});
try {
DeviceAttachmentSpec::parseOptionalParamValueWithSynonyms(
emptyValue, synonyms, "empty colour-space");
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "empty colour-space");
}
const ParamList present = makeParams({{"colour-space", "yuv"}});
const std::optional<std::string> parsed =
DeviceAttachmentSpec::parseOptionalParamValueWithSynonyms(
present, synonyms, "empty colour-space");
ASSERT_TRUE(parsed.has_value());
EXPECT_EQ(*parsed, "yuv");
}
TEST(DeviceAttachmentSpecParseOptionalParamAsBoolWithSynonymsTest, ParsesPresenceAndValues)
{
const std::vector<std::string> synonyms = {
"full-planar-is-optional",
"opt-planar",
};
const ParamList absent = makeParams({{"width", "640"}});
EXPECT_FALSE(DeviceAttachmentSpec::parseOptionalParamAsBoolWithSynonyms(
absent, synonyms, false));
const ParamList presentEmpty = makeParams({{"opt-planar", ""}});
EXPECT_TRUE(DeviceAttachmentSpec::parseOptionalParamAsBoolWithSynonyms(
presentEmpty, synonyms, false));
const ParamList presentFalse = makeParams({{"opt-planar", "false"}});
EXPECT_FALSE(DeviceAttachmentSpec::parseOptionalParamAsBoolWithSynonyms(
presentFalse, synonyms, true));
const ParamList lattermostWins = makeParams({
{"opt-planar", "true"},
{"full-planar-is-optional", "false"},
});
EXPECT_FALSE(DeviceAttachmentSpec::parseOptionalParamAsBoolWithSynonyms(
lattermostWins, synonyms, true));
}
TEST(DeviceAttachmentSpecRejectUnknownParamsTest, RejectsUnknownNames)
{
const std::vector<std::string> knownA = {"width", "dim-w"};
const std::vector<std::string> knownB = {"height", "dim-h"};
const ParamList params = makeParams({
{"dim-w", "640"},
{"unknown-param", "1"},
});
try {
DeviceAttachmentSpec::rejectUnknownParams(
params,
"unknown param '",
knownA,
knownB);
FAIL() << "Expected std::runtime_error";
}
catch (const std::runtime_error& exception)
{
sscl::tests::expectExceptionMessageContains(
exception, "unknown-param");
}
}
TEST(DeviceAttachmentSpecRejectUnknownParamsTest, AcceptsAllKnownNames)
{
const std::vector<std::string> knownA = {"width", "dim-w"};
const std::vector<std::string> knownB = {"height", "dim-h"};
const ParamList params = makeParams({
{"dim-w", "640"},
{"dim-h", "480"},
});
EXPECT_NO_THROW(DeviceAttachmentSpec::rejectUnknownParams(
params,
"unknown param '",
knownA,
knownB));
}
} // namespace
} // namespace device
} // namespace smo