Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/FirmwarePlugin/ParameterMetaData.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,14 @@ void ParameterMetaData::setEnumFromPairs(FactMetaData *metaData, const QList<Val
QStringList enumStrings;
QVariantList enumValues;

// Validate against storage type only: firmware often declares sentinel enum
// values (e.g. 0 = Disabled) outside the operating min/max range.
FactMetaData typeMetaData(metaData->type());

for (const auto &[code, description] : pairs) {
QVariant enumValue;
QString errorString;
if (metaData->convertAndValidateRaw(code, false, enumValue, errorString)) {
if (typeMetaData.convertAndValidateRaw(code, false, enumValue, errorString)) {
enumValues << enumValue;
enumStrings << description;
} else {
Expand Down
53 changes: 53 additions & 0 deletions test/FactSystem/APMParameterMetaDataTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -425,4 +425,57 @@ void APMParameterMetaDataTest::_outOfRangeBitmaskIndexSkipped()
QCOMPARE(fact->bitmaskStrings()[1], "Second");
}

void APMParameterMetaDataTest::_parseEnumSentinelOutsideRange()
{
static const char *json = R"({
"TEST_": {
"TEST_SENTINEL": {
"DisplayName": "Sentinel enum",
"Description": "Enum with sentinel value outside operating range",
"Range": {"low": "0.5", "high": "10"},
"Values": {"0": "Disabled", "1": "Enabled"}
}
}
})";

QScopedPointer<APMParameterMetaData> meta(_loadFromJson(json, nullptr));
QVERIFY(meta);

FactMetaData *fact = meta->getMetaDataForFact("TEST_SENTINEL", FactMetaData::valueTypeFloat);
QVERIFY(fact);
QCOMPARE(fact->rawMin().toFloat(), 0.5f);
QCOMPARE(fact->rawMax().toFloat(), 10.0f);
QCOMPARE(fact->enumStrings(), QStringList({"Disabled", "Enabled"}));
QCOMPARE(fact->enumValues().size(), 2);
QCOMPARE(fact->enumValues()[0].toFloat(), 0.0f);
QCOMPARE(fact->enumValues()[1].toFloat(), 1.0f);
}

void APMParameterMetaDataTest::_parseEnumNegativeSentinelIntType()
{
static const char *json = R"({
"TEST_": {
"TEST_SENTINEL_INT": {
"DisplayName": "Int sentinel enum",
"Description": "Negative sentinel below integer operating range",
"Range": {"low": "0", "high": "100"},
"Values": {"-1": "Disabled", "0": "First", "1": "Second"}
}
}
})";

QScopedPointer<APMParameterMetaData> meta(_loadFromJson(json, nullptr));
QVERIFY(meta);

FactMetaData *fact = meta->getMetaDataForFact("TEST_SENTINEL_INT", FactMetaData::valueTypeInt32);
QVERIFY(fact);
QCOMPARE(fact->rawMin().toInt(), 0);
QCOMPARE(fact->rawMax().toInt(), 100);
QCOMPARE(fact->enumStrings(), QStringList({"Disabled", "First", "Second"}));
QCOMPARE(fact->enumValues().size(), 3);
QCOMPARE(fact->enumValues()[0].toInt(), -1);
QCOMPARE(fact->enumValues()[1].toInt(), 0);
QCOMPARE(fact->enumValues()[2].toInt(), 1);
}

UT_REGISTER_TEST(APMParameterMetaDataTest, TestLabel::Unit)
2 changes: 2 additions & 0 deletions test/FactSystem/APMParameterMetaDataTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ private slots:
void _invalidEnumKeySkipped();
void _invalidBitmaskIndexSkipped();
void _outOfRangeBitmaskIndexSkipped();
void _parseEnumSentinelOutsideRange();
void _parseEnumNegativeSentinelIntType();
};
Loading