Closes #24
This commit is contained in:
1 parent
fc97682b37
commit
e555ebb571
16 files changed
+337
-52
No files matched your search
+161
-4
@@ -12,12 +12,12 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
DbcDatabase ParseText(const std::string &text) {
|
||||
DbcDatabase ParseText(const std::string &text, bool enableJ1939 = false) {
|
||||
QTemporaryFile file;
|
||||
if (!file.open()) throw std::runtime_error("Cannot create DBC fixture");
|
||||
if (file.write(text.data(), static_cast<qint64>(text.size())) != static_cast<qint64>(text.size()) || !file.flush())
|
||||
throw std::runtime_error("Cannot write DBC fixture");
|
||||
return DbcParser().ParseFile(file.fileName().toStdString());
|
||||
return DbcParser(DbcParserOptions{enableJ1939}).ParseFile(file.fileName().toStdString());
|
||||
}
|
||||
|
||||
DecodeDatabase SingleSignal(const DecodeSignal &signal) {
|
||||
@@ -73,6 +73,11 @@ private Q_SLOTS:
|
||||
void malformedRuntimeMultiplexing();
|
||||
void pgn_data();
|
||||
void pgn();
|
||||
void j1939Lookup_data();
|
||||
void j1939Lookup();
|
||||
void j1939Ambiguity_data();
|
||||
void j1939Ambiguity();
|
||||
void j1939MetadataValidation();
|
||||
void comments_data();
|
||||
void comments();
|
||||
void ignoredCommentStatements_data();
|
||||
@@ -285,7 +290,7 @@ void CoverageTest::pgn_data() {
|
||||
QTest::addColumn<unsigned>("expected");
|
||||
QTest::addColumn<bool>("hasPgn");
|
||||
QTest::newRow("standard") << 0x7FFU << 0U << false;
|
||||
for (unsigned dp: {0U, 1U})
|
||||
for (unsigned dp: {0U, 1U, 2U, 3U})
|
||||
for (unsigned pf: {239U, 240U})
|
||||
for (unsigned ps: {0U, 0xABU}) {
|
||||
const unsigned id = 0x80000000U | (dp << 24U) | (pf << 16U) | (ps << 8U) | 0x42U;
|
||||
@@ -299,11 +304,163 @@ void CoverageTest::pgn() {
|
||||
QFETCH(unsigned, id);
|
||||
QFETCH(unsigned, expected);
|
||||
QFETCH(bool, hasPgn);
|
||||
const DbcDatabase parsed = ParseText("BO_ " + std::to_string(id) + " Frame: 8 ECU\n");
|
||||
const std::string text = "BO_ " + std::to_string(id) + " Frame: 8 ECU\n";
|
||||
const DbcDatabase generic = ParseText(text);
|
||||
QVERIFY(!generic.frames[0].hasPgn);
|
||||
QCOMPARE(generic.frames[0].pgn, 0U);
|
||||
const DbcDatabase parsed = ParseText(text, true);
|
||||
QCOMPARE(parsed.frames[0].hasPgn, hasPgn);
|
||||
QCOMPARE(parsed.frames[0].pgn, expected);
|
||||
}
|
||||
|
||||
void CoverageTest::j1939Lookup_data() {
|
||||
QTest::addColumn<unsigned>("definitionId");
|
||||
QTest::addColumn<unsigned>("receivedId");
|
||||
QTest::addColumn<unsigned>("pgn");
|
||||
QTest::addColumn<bool>("matches");
|
||||
QTest::newRow("pdu1-source") << 0x18EF1242U << 0x18EF1299U << 0xEF00U << true;
|
||||
QTest::newRow("pdu1-destination-priority") << 0x18EF1242U << 0x0CEF3499U << 0xEF00U << true;
|
||||
QTest::newRow("pdu2-source-priority") << 0x18F00442U << 0x0CF00499U << 0xF004U << true;
|
||||
QTest::newRow("pdu2-group-extension") << 0x18F00442U << 0x18F00599U << 0xF004U << false;
|
||||
QTest::newRow("data-page") << 0x18F00442U << 0x19F00499U << 0xF004U << false;
|
||||
QTest::newRow("extended-data-page") << 0x18F00442U << 0x1AF00499U << 0xF004U << false;
|
||||
QTest::newRow("pgn-zero") << 0x80000123U << 0x00000456U << 0U << true;
|
||||
}
|
||||
|
||||
void CoverageTest::j1939Lookup() {
|
||||
QFETCH(unsigned, definitionId);
|
||||
QFETCH(unsigned, receivedId);
|
||||
QFETCH(unsigned, pgn);
|
||||
QFETCH(bool, matches);
|
||||
const std::string text = "BO_ " + std::to_string(definitionId) + " Frame: 1 ECU\n"
|
||||
"SG_ Value : 0|8@1+ (2,1) [0|511] \"\" ECU\n";
|
||||
const DbcDecoder decoder;
|
||||
RawCanFrame raw;
|
||||
raw.canId = receivedId;
|
||||
raw.isExtended = true;
|
||||
raw.data = {7U};
|
||||
const DecodeDatabase generic = DbcDecodeBuilder().Build(ParseText(text));
|
||||
QVERIFY(!decoder.FindFrame(generic, receivedId, true));
|
||||
QCOMPARE(decoder.Decode(generic, raw).status, FrameDecodeStatus::UnknownFrame);
|
||||
QVERIFY(!generic.FindFrameByPgn(pgn).definition);
|
||||
|
||||
DecodeDatabase database = DbcDecodeBuilder().Build(ParseText(text, true));
|
||||
const FrameKey key(definitionId & 0x1FFFFFFFU, true);
|
||||
const PgnLookupResult lookup = database.FindFrameByPgn(pgn);
|
||||
QVERIFY(!lookup.ambiguous);
|
||||
QVERIFY(lookup.definition != nullptr);
|
||||
QCOMPARE(lookup.definition.get(), database.FindFrame(key).get());
|
||||
const DecodedFrameValue result = decoder.Decode(database, raw);
|
||||
QCOMPARE(result.valid, matches);
|
||||
QCOMPARE(result.status, matches ? FrameDecodeStatus::Valid : FrameDecodeStatus::UnknownFrame);
|
||||
QCOMPARE(bool(decoder.FindFrame(database, receivedId, true)), matches);
|
||||
if (matches) {
|
||||
QVERIFY(result.key == key);
|
||||
QCOMPARE(result.definition.get(), lookup.definition.get());
|
||||
QCOMPARE(result.signals.size(), std::size_t(1));
|
||||
QVERIFY(result.signals[0].key == SignalKey(key, "Value"));
|
||||
QCOMPARE(std::get<std::uint64_t>(result.signals[0].rawValue), std::uint64_t(7));
|
||||
QCOMPARE(result.signals[0].physicalValue, 15.0);
|
||||
const DecodedFrameValue selected = decoder.Decode(database, raw, {SignalKey(key, "Value")});
|
||||
QCOMPARE(selected.status, FrameDecodeStatus::Valid);
|
||||
QVERIFY(selected.signals[0].key == result.signals[0].key);
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument,
|
||||
decoder.Decode(database, raw, {SignalKey(FrameKey(receivedId, true), "Value")}));
|
||||
} else {
|
||||
QVERIFY(result.key == FrameKey(receivedId, true));
|
||||
QVERIFY(!result.definition);
|
||||
QVERIFY(result.signals.empty());
|
||||
}
|
||||
raw.isExtended = false;
|
||||
QCOMPARE(decoder.Decode(database, raw).status, FrameDecodeStatus::UnknownFrame);
|
||||
raw.isExtended = true;
|
||||
raw.canId = receivedId | 0x80000000U;
|
||||
QCOMPARE(decoder.Decode(database, raw).status, FrameDecodeStatus::UnknownFrame);
|
||||
|
||||
database = DecodeDatabase();
|
||||
QCOMPARE(lookup.definition->pgn, pgn); // PGN handles own the old snapshot.
|
||||
QVERIFY(!database.FindFrameByPgn(pgn).definition);
|
||||
QVERIFY(!database.FindFrameByPgn(pgn).ambiguous);
|
||||
}
|
||||
|
||||
void CoverageTest::j1939Ambiguity_data() {
|
||||
QTest::addColumn<unsigned>("firstId");
|
||||
QTest::addColumn<unsigned>("secondId");
|
||||
QTest::addColumn<unsigned>("receivedId");
|
||||
QTest::addColumn<unsigned>("pgn");
|
||||
QTest::newRow("pdu1") << 0x18EF1242U << 0x18EF3443U << 0x18EF5699U << 0xEF00U;
|
||||
QTest::newRow("pdu2") << 0x18F00442U << 0x0CF00443U << 0x18F00499U << 0xF004U;
|
||||
}
|
||||
|
||||
void CoverageTest::j1939Ambiguity() {
|
||||
QFETCH(unsigned, firstId);
|
||||
QFETCH(unsigned, secondId);
|
||||
QFETCH(unsigned, receivedId);
|
||||
QFETCH(unsigned, pgn);
|
||||
DecodeFrame first;
|
||||
first.canId = firstId;
|
||||
first.isExtended = true;
|
||||
first.hasPgn = true;
|
||||
first.pgn = pgn;
|
||||
DecodeFrame second = first;
|
||||
second.canId = secondId;
|
||||
RawCanFrame raw;
|
||||
raw.canId = receivedId;
|
||||
raw.isExtended = true;
|
||||
const DbcDecoder decoder;
|
||||
for (const std::vector<DecodeFrame> &frames: {std::vector<DecodeFrame>{first, second},
|
||||
std::vector<DecodeFrame>{second, first}}) {
|
||||
const DecodeDatabase database(frames);
|
||||
const PgnLookupResult lookup = database.FindFrameByPgn(pgn);
|
||||
QVERIFY(lookup.ambiguous);
|
||||
QVERIFY(!lookup.definition);
|
||||
QVERIFY(!decoder.FindFrame(database, receivedId, true));
|
||||
const DecodedFrameValue result = decoder.Decode(database, raw);
|
||||
QCOMPARE(result.status, FrameDecodeStatus::AmbiguousFrame);
|
||||
QVERIFY(!result.valid);
|
||||
QVERIFY(!result.definition);
|
||||
QVERIFY(result.signals.empty());
|
||||
QVERIFY(result.key == FrameKey(receivedId, true));
|
||||
QCOMPARE(decoder.Decode(database, raw, {SignalKey(first.GetKey(), "Missing")}).status,
|
||||
FrameDecodeStatus::AmbiguousFrame);
|
||||
raw.canId = firstId;
|
||||
const DecodedFrameValue exact = decoder.Decode(database, raw);
|
||||
QCOMPARE(exact.status, FrameDecodeStatus::Valid);
|
||||
QVERIFY(exact.key == first.GetKey());
|
||||
raw.canId = receivedId;
|
||||
}
|
||||
// A generic extended definition neither creates ambiguity nor loses exact-ID precedence.
|
||||
second.hasPgn = false;
|
||||
second.canId = receivedId;
|
||||
const DecodeDatabase mixed({first, second});
|
||||
QVERIFY(!mixed.FindFrameByPgn(pgn).ambiguous);
|
||||
QCOMPARE(mixed.FindFrameByPgn(pgn).definition->canId, firstId);
|
||||
QCOMPARE(decoder.Decode(mixed, raw).definition->canId, receivedId);
|
||||
raw.canId = receivedId ^ 1U;
|
||||
QCOMPARE(decoder.Decode(mixed, raw).definition->canId, firstId);
|
||||
}
|
||||
|
||||
void CoverageTest::j1939MetadataValidation() {
|
||||
DecodeFrame frame;
|
||||
frame.canId = 0x18F00442U;
|
||||
frame.isExtended = true;
|
||||
frame.hasPgn = true;
|
||||
frame.pgn = 0xF005U;
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame}));
|
||||
DbcDatabase source;
|
||||
FrameInfo metadata;
|
||||
metadata.canId = frame.canId;
|
||||
metadata.isExtended = true;
|
||||
metadata.hasPgn = true;
|
||||
metadata.pgn = frame.pgn;
|
||||
source.frames.push_back(metadata);
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument, DbcDecodeBuilder().Build(source));
|
||||
frame.canId = 1U;
|
||||
frame.isExtended = false;
|
||||
frame.pgn = 0U;
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame}));
|
||||
}
|
||||
|
||||
void CoverageTest::comments_data() {
|
||||
QTest::addColumn<QString>("before");
|
||||
QTest::addColumn<QString>("after");
|
||||
|
||||
Reference in new issue
Block a user