Closes #14
This commit is contained in:
1 parent
51fcdb88ac
commit
0708316a37
155 files changed
+5190
-2691
No files matched your search
+18
-2
@@ -24,7 +24,7 @@ make -j
|
||||
make check
|
||||
```
|
||||
|
||||
Or run `./tests/dbc_tests` directly. Parser, decoder, and additional coverage
|
||||
Or run `./tests/dbc_tests` directly. Parser, decoder, lifetime, and additional coverage
|
||||
suites run, and the executable returns nonzero when any suite fails. Decoder cases appear as
|
||||
individual QtTest data rows; parser checks are grouped into named test slots.
|
||||
Checks also run in release builds.
|
||||
@@ -41,7 +41,7 @@ make check
|
||||
```
|
||||
|
||||
`parser_tests.pri` and `decoder_tests.pri` include the original test sources;
|
||||
`tests.pro` also includes `dbc_coverage_test.cpp`.
|
||||
`tests.pro` also includes `dbc_coverage_test.cpp` and `dbc_lifetime_test.cpp`.
|
||||
`../core/core.pri` supplies the library include path and linkage.
|
||||
|
||||
## Decoder coverage
|
||||
@@ -120,3 +120,19 @@ API, verify source locations, and check that ambiguous targets receive no values
|
||||
All QtTest targets use Qt 6.8.2 and `QVERIFY_THROWS_EXCEPTION`. Exception tests
|
||||
explicitly discard `nodiscard` results when only the exception is being checked.
|
||||
The standalone tree test requires only a C++17 compiler.
|
||||
|
||||
## Definition lifetime and reload coverage
|
||||
|
||||
`dbc_lifetime_test.cpp` checks retained definitions and value-description strings
|
||||
across reload, clear, and destruction; independently saved signal results;
|
||||
copied/moved results and database copies; owning lookup handles; and release of
|
||||
the old snapshot after its final owner is removed. Compile-time checks enforce
|
||||
const access to runtime metadata. Reload fixtures change ordering, frame names,
|
||||
scaling, units, and descriptions, remove definitions, and rename signals.
|
||||
|
||||
Key tests check equality and hashing, standard/extended separation, the same
|
||||
signal name in different frames, and missing lookups. Constructor tests reject
|
||||
duplicate runtime keys, including manually supplied parsed metadata. Failed reload
|
||||
leaves the active database intact; empty reload clears it. Invalid/unknown results
|
||||
and insufficient payloads retain their documented ownership and status behavior.
|
||||
Inactive branches and unavailable selectors also retain definitions across reload.
|
||||
+24
-23
@@ -21,13 +21,10 @@ namespace {
|
||||
}
|
||||
|
||||
DecodeDatabase SingleSignal(const DecodeSignal &signal) {
|
||||
DecodeDatabase database;
|
||||
DecodeFrame frame;
|
||||
frame.canId = 17U;
|
||||
frame.signals.push_back(signal);
|
||||
database.frames.push_back(frame);
|
||||
database.frameIndexByKey.emplace(FrameKey(17U, false), 0U);
|
||||
return database;
|
||||
return DecodeDatabase({frame});
|
||||
}
|
||||
|
||||
// Independent reference: collect the visited bits first, then weight them.
|
||||
@@ -115,14 +112,12 @@ void CoverageTest::frameLookup() {
|
||||
raw.canId = 18U;
|
||||
QVERIFY(!decoder.Decode(database, raw).valid);
|
||||
raw.canId = 17U;
|
||||
database.frameIndexByKey.at(FrameKey(17U, false)) = database.frames.size();
|
||||
QVERIFY(decoder.FindFrame(database, 17U, false) == nullptr);
|
||||
QVERIFY(!decoder.Decode(database, raw).valid);
|
||||
database.frameIndexByKey.at(FrameKey(17U, false)) = 0U;
|
||||
database.frames[0].signals.clear();
|
||||
DecodeFrame noSignals;
|
||||
noSignals.canId = 17U;
|
||||
database = DecodeDatabase({noSignals});
|
||||
const DecodedFrameValue matched = decoder.Decode(database, raw);
|
||||
QVERIFY(matched.valid);
|
||||
QCOMPARE(matched.definition, &database.frames[0]);
|
||||
QCOMPARE(matched.definition.get(), &database.GetFrames()[0]);
|
||||
QVERIFY(matched.signals.empty());
|
||||
}
|
||||
|
||||
@@ -255,21 +250,28 @@ void CoverageTest::malformedRuntimeMultiplexing() {
|
||||
DecodeSignal selector;
|
||||
selector.length = 1U;
|
||||
selector.multiplexing.role = MultiplexRole::Selector;
|
||||
DecodeDatabase database = SingleSignal(selector);
|
||||
selector.name = "Selector";
|
||||
std::vector<DecodeFrame> definitions = SingleSignal(selector).GetFrames();
|
||||
DecodeSignal branch;
|
||||
branch.name = "Branch";
|
||||
branch.startBit = 8U;
|
||||
branch.length = 8U;
|
||||
branch.multiplexing.role = MultiplexRole::Branch;
|
||||
branch.multiplexing.value = 1U;
|
||||
database.frames[0].signals.push_back(branch);
|
||||
definitions[0].signals.push_back(branch);
|
||||
DecodeSignal ordinary;
|
||||
ordinary.name = "Ordinary";
|
||||
ordinary.startBit = 16U;
|
||||
ordinary.length = 8U;
|
||||
database.frames[0].signals.push_back(ordinary);
|
||||
if (kind == 0) database.frames[0].signals.push_back(selector);
|
||||
if (kind == 1) database.frames[0].signals[0].valueType = ValueType::Signed;
|
||||
if (kind == 2) database.frames[0].signals[0].length = 65U;
|
||||
if (kind == 3) database.frames[0].signals[1].multiplexing.value = 2U;
|
||||
definitions[0].signals.push_back(ordinary);
|
||||
if (kind == 0) {
|
||||
selector.name = "SecondSelector";
|
||||
definitions[0].signals.push_back(selector);
|
||||
}
|
||||
if (kind == 1) definitions[0].signals[0].valueType = ValueType::Signed;
|
||||
if (kind == 2) definitions[0].signals[0].length = 65U;
|
||||
if (kind == 3) definitions[0].signals[1].multiplexing.value = 2U;
|
||||
const DecodeDatabase database(std::move(definitions));
|
||||
RawCanFrame raw;
|
||||
raw.canId = 17U;
|
||||
raw.data = {1U, 42U, 99U};
|
||||
@@ -491,8 +493,8 @@ void CoverageTest::missingFile() {
|
||||
|
||||
void CoverageTest::builders() {
|
||||
const DecodeDatabase emptyRuntime = DbcDecodeBuilder().Build(DbcDatabase());
|
||||
QVERIFY(emptyRuntime.frames.empty());
|
||||
QVERIFY(emptyRuntime.frameIndexByKey.empty());
|
||||
QVERIFY(emptyRuntime.GetFrames().empty());
|
||||
QVERIFY(!emptyRuntime.FindFrame(FrameKey(0U, false)));
|
||||
const std::unique_ptr<TreeNode> emptyTree = DbcTreeBuilder().Build(DbcDatabase());
|
||||
QCOMPARE(emptyTree->GetType(), NodeType::Root);
|
||||
QCOMPARE(emptyTree->GetName(), std::string("dbc"));
|
||||
@@ -517,18 +519,17 @@ void CoverageTest::builders() {
|
||||
source.frames[0].signals[1].valueDescriptions.clear();
|
||||
source.frames.clear();
|
||||
}
|
||||
QCOMPARE(runtime.frames.size(), expected.frames.size());
|
||||
QCOMPARE(runtime.GetFrames().size(), expected.frames.size());
|
||||
QCOMPARE(tree->GetChildCount(), expected.frames.size());
|
||||
QCOMPARE(runtime.frameIndexByKey.size(), expected.frames.size());
|
||||
for (std::size_t i = 0; i < expected.frames.size(); ++i) {
|
||||
const FrameInfo &frame = expected.frames[i];
|
||||
const DecodeFrame &decodedFrame = runtime.frames[i];
|
||||
const DecodeFrame &decodedFrame = runtime.GetFrames()[i];
|
||||
const TreeNode *node = tree->GetChild(i);
|
||||
QVERIFY(node && node->GetFrame());
|
||||
QCOMPARE(node->GetType(), NodeType::Frame);
|
||||
QCOMPARE(node->GetName(), frame.name);
|
||||
QVERIFY(node->GetSignal() == nullptr);
|
||||
QCOMPARE(runtime.frameIndexByKey.at(FrameKey(frame.canId, frame.isExtended)), i);
|
||||
QCOMPARE(runtime.FindFrame(FrameKey(frame.canId, frame.isExtended)).get(), &decodedFrame);
|
||||
const FrameInfo &copied = *node->GetFrame();
|
||||
QCOMPARE(copied.name, frame.name);
|
||||
QCOMPARE(decodedFrame.name, frame.name);
|
||||
|
||||
@@ -68,19 +68,17 @@ void DbcDecoderTest::decode() {
|
||||
definition.canId = 0x123U;
|
||||
definition.dlc = static_cast<std::uint8_t>(test.data.size());
|
||||
definition.signals.push_back(signal);
|
||||
DecodeDatabase database;
|
||||
database.frames.push_back(definition);
|
||||
database.frameIndexByKey.emplace(FrameKey(definition.canId, false), 0U);
|
||||
const DecodeDatabase database({definition});
|
||||
|
||||
RawCanFrame frame;
|
||||
frame.canId = definition.canId;
|
||||
frame.data = test.data;
|
||||
const DecodedFrameValue result = DbcDecoder().Decode(database, frame);
|
||||
QVERIFY2(result.valid, test.name);
|
||||
QCOMPARE(result.definition, &database.frames[0]);
|
||||
QCOMPARE(result.definition.get(), &database.GetFrames()[0]);
|
||||
QCOMPARE(result.signals.size(), std::size_t(1U));
|
||||
const DecodedSignalValue &decoded = result.signals[0];
|
||||
QCOMPARE(decoded.definition, &database.frames[0].signals[0]);
|
||||
QCOMPARE(decoded.definition.get(), &database.GetFrames()[0].signals[0]);
|
||||
QCOMPARE(decoded.valid, test.valid);
|
||||
if (!test.valid)
|
||||
return;
|
||||
@@ -104,7 +102,6 @@ void DbcDecoderTest::boundaries() {
|
||||
std::uint64_t(0x8000000000000000ULL),
|
||||
std::uint64_t(0x8000000000000001ULL),
|
||||
std::uint64_t(0xFFFFFFFFFFFFFFFFULL)}) {
|
||||
DecodeDatabase database;
|
||||
DecodeFrame definition;
|
||||
DecodeSignal signal;
|
||||
signal.startBit = order == ByteOrder::Intel ? 0U : 7U;
|
||||
@@ -114,8 +111,7 @@ void DbcDecoderTest::boundaries() {
|
||||
signal.factor = 0.5;
|
||||
signal.offset = 10.0;
|
||||
definition.signals.push_back(signal);
|
||||
database.frames.push_back(definition);
|
||||
database.frameIndexByKey.emplace(FrameKey(0U, false), 0U);
|
||||
const DecodeDatabase database({definition});
|
||||
RawCanFrame frame;
|
||||
for (unsigned byte = 0U; byte < 8U; ++byte) {
|
||||
const unsigned shift = (order == ByteOrder::Intel ? byte : 7U - byte) * 8U;
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2026 Dim Himro
|
||||
|
||||
#include "dbc_decode_builder.h"
|
||||
#include "dbc_decoder.h"
|
||||
#include "dbc_parser.h"
|
||||
#include <QTemporaryFile>
|
||||
#include <QtTest>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
static_assert(std::is_same_v<decltype(std::declval<const DecodeDatabase &>().GetFrames()),
|
||||
const std::vector<DecodeFrame> &>);
|
||||
static_assert(std::is_same_v<decltype(DecodedFrameValue::definition), std::shared_ptr<const DecodeFrame>>);
|
||||
static_assert(std::is_same_v<decltype(DecodedSignalValue::definition), std::shared_ptr<const DecodeSignal>>);
|
||||
|
||||
namespace {
|
||||
DecodeDatabase BuildText(const std::string &text) {
|
||||
QTemporaryFile file;
|
||||
if (!file.open() ||
|
||||
file.write(text.data(), static_cast<qint64>(text.size())) != static_cast<qint64>(text.size()) ||
|
||||
!file.flush())
|
||||
throw std::runtime_error("Cannot write reload fixture");
|
||||
return DbcDecodeBuilder().Build(DbcParser().ParseFile(file.fileName().toStdString()));
|
||||
}
|
||||
|
||||
const std::string firstDbc =
|
||||
"BO_ 17 OldFrame: 2 ECU\n"
|
||||
"SG_ State : 0|8@1+ (2,1) [1|511] \"old\" ECU\n"
|
||||
"SG_ Removed : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
|
||||
"VAL_ 17 State 1 \"Old label\";\n"
|
||||
"BO_ 18 Deleted: 1 ECU\n"
|
||||
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n";
|
||||
const std::string secondDbc =
|
||||
"BO_ 2147483665 Extended: 1 ECU\n"
|
||||
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
|
||||
"BO_ 17 NewFrame: 2 ECU\n"
|
||||
"SG_ Renamed : 8|8@1+ (1,0) [0|255] \"\" ECU\n"
|
||||
"SG_ State : 0|8@1+ (4,0) [0|1020] \"new\" ECU\n"
|
||||
"VAL_ 17 State 1 \"New label\";\n";
|
||||
}// namespace
|
||||
|
||||
class DbcLifetimeTest : public QObject {
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void reload();
|
||||
void independentSignalLifetime();
|
||||
void lookupLifetime();
|
||||
void keys();
|
||||
void duplicateKeys();
|
||||
void failedReload();
|
||||
void invalidResults();
|
||||
void retainedMultiplexStatuses();
|
||||
};
|
||||
|
||||
void DbcLifetimeTest::reload() {
|
||||
DecodeDatabase database = BuildText(firstDbc);
|
||||
RawCanFrame raw;
|
||||
raw.canId = 17U;
|
||||
raw.data = {1U, 42U};
|
||||
DecodedFrameValue oldResult = DbcDecoder().Decode(database, raw);
|
||||
const DecodedFrameValue copied = oldResult;
|
||||
DecodedFrameValue moved = std::move(oldResult);
|
||||
std::weak_ptr<const DecodeFrame> oldDefinition = moved.definition;
|
||||
database = BuildText(secondDbc);
|
||||
const DecodedFrameValue current = DbcDecoder().Decode(database, raw);
|
||||
QVERIFY(current.valid && moved.valid && copied.valid);
|
||||
QVERIFY(current.definition != moved.definition);
|
||||
QVERIFY(current.key == moved.key);
|
||||
QVERIFY(current.signals[1].key == moved.signals[0].key);
|
||||
QCOMPARE(moved.definition->name, std::string("OldFrame"));
|
||||
QCOMPARE(copied.definition, moved.definition);
|
||||
QCOMPARE(moved.signals[0].physicalValue, 3.0);
|
||||
QCOMPARE(current.signals[1].physicalValue, 4.0);
|
||||
QCOMPARE(moved.signals[0].definition->unit, std::string("old"));
|
||||
QCOMPARE(current.signals[1].definition->unit, std::string("new"));
|
||||
QCOMPARE(*moved.signals[0].GetValueDescription(), std::string("Old label"));
|
||||
QCOMPARE(*current.signals[1].GetValueDescription(), std::string("New label"));
|
||||
QCOMPARE(moved.signals[1].definition->name, std::string("Removed"));
|
||||
QVERIFY(!database.FindSignal(moved.signals[1].key));
|
||||
database = DecodeDatabase();
|
||||
QVERIFY(!oldDefinition.expired());
|
||||
QCOMPARE(current.definition->name, std::string("NewFrame"));
|
||||
QCOMPARE(*current.signals[1].GetValueDescription(), std::string("New label"));
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::independentSignalLifetime() {
|
||||
DecodedSignalValue saved;
|
||||
std::weak_ptr<const DecodeSignal> definition;
|
||||
const std::string *label = nullptr;
|
||||
{
|
||||
DecodeDatabase database = BuildText(firstDbc);
|
||||
RawCanFrame raw;
|
||||
raw.canId = 17U;
|
||||
raw.data = {1U, 0U};
|
||||
DecodedFrameValue result = DbcDecoder().Decode(database, raw);
|
||||
saved = result.signals[0];
|
||||
definition = saved.definition;
|
||||
label = saved.GetValueDescription();
|
||||
result = DecodedFrameValue();
|
||||
database = BuildText(secondDbc);
|
||||
}
|
||||
QVERIFY(!definition.expired());
|
||||
QVERIFY(label != nullptr);
|
||||
QCOMPARE(*label, std::string("Old label"));
|
||||
QCOMPARE(saved.definition->factor, 2.0);
|
||||
DecodedSignalValue copied = saved;
|
||||
DecodedSignalValue moved = std::move(saved);
|
||||
QCOMPARE(moved.definition, copied.definition);
|
||||
saved = DecodedSignalValue();
|
||||
moved = DecodedSignalValue();
|
||||
QVERIFY(!definition.expired());
|
||||
copied = DecodedSignalValue();
|
||||
QVERIFY(definition.expired());
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::lookupLifetime() {
|
||||
std::shared_ptr<const DecodeFrame> frame;
|
||||
std::shared_ptr<const DecodeSignal> signal;
|
||||
std::weak_ptr<const DecodeFrame> released;
|
||||
{
|
||||
DecodeDatabase database = BuildText(firstDbc);
|
||||
DecodeDatabase copy = database;
|
||||
frame = DbcDecoder().FindFrame(database, 17U, false);
|
||||
signal = copy.FindSignal(SignalKey(FrameKey(17U, false), "State"));
|
||||
QVERIFY(frame && signal);
|
||||
QCOMPARE(frame.get(), ©.GetFrames()[0]);
|
||||
QCOMPARE(signal.get(), &frame->signals[0]);
|
||||
released = frame;
|
||||
database = BuildText(secondDbc);
|
||||
DecodeDatabase moved = std::move(copy);
|
||||
QVERIFY(copy.GetFrames().empty());
|
||||
QVERIFY(!copy.FindFrame(FrameKey(17U, false)));
|
||||
QCOMPARE(moved.FindFrame(FrameKey(17U, false)), frame);
|
||||
}
|
||||
QCOMPARE(frame->name, std::string("OldFrame"));
|
||||
frame.reset();
|
||||
QVERIFY(!released.expired());
|
||||
QCOMPARE(signal->name, std::string("State"));
|
||||
signal.reset();
|
||||
QVERIFY(released.expired());
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::keys() {
|
||||
const FrameKey frame(17U, false);
|
||||
const SignalKey state(frame, "State");
|
||||
const DecodeDatabase first = BuildText(firstDbc);
|
||||
const DecodeDatabase second = BuildText(secondDbc);
|
||||
QVERIFY(first.FindFrame(frame)->GetKey() == second.FindFrame(frame)->GetKey());
|
||||
QVERIFY(first.FindSignal(state) && second.FindSignal(state));
|
||||
QVERIFY(!second.FindFrame(FrameKey(18U, false)));
|
||||
QVERIFY(!second.FindSignal(SignalKey(frame, "Removed")));
|
||||
QVERIFY(second.FindSignal(SignalKey(frame, "Renamed")));
|
||||
QVERIFY(second.FindSignal(SignalKey(FrameKey(17U, true), "State")));
|
||||
QVERIFY(!second.FindSignal(SignalKey(FrameKey(999U, false), "State")));
|
||||
QVERIFY(first.FindSignal(SignalKey(FrameKey(18U, false), "State")));
|
||||
std::unordered_map<FrameKey, int, FrameKeyHasher> frames;
|
||||
frames.emplace(frame, 1);
|
||||
frames.emplace(FrameKey(17U, true), 2);
|
||||
QCOMPARE(frames.size(), std::size_t(2U));
|
||||
std::unordered_map<SignalKey, int, SignalKeyHasher> signals;
|
||||
signals.emplace(state, 1);
|
||||
signals.emplace(SignalKey(FrameKey(17U, true), "State"), 2);
|
||||
signals.emplace(SignalKey(frame, "Renamed"), 3);
|
||||
signals.emplace(SignalKey(FrameKey(18U, false), "State"), 4);
|
||||
QCOMPARE(signals.at(SignalKey(FrameKey(17U, false), "State")), 1);
|
||||
QCOMPARE(signals.size(), std::size_t(4U));
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::duplicateKeys() {
|
||||
DecodeFrame frame;
|
||||
frame.canId = 17U;
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame, frame}));
|
||||
DecodeSignal signal;
|
||||
signal.name = "State";
|
||||
frame.signals = {signal, signal};
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DecodeDatabase({frame}));
|
||||
DbcDatabase parsed;
|
||||
FrameInfo source;
|
||||
source.canId = 17U;
|
||||
parsed.frames = {source, source};
|
||||
QVERIFY_THROWS_EXCEPTION(std::invalid_argument, (void) DbcDecodeBuilder().Build(parsed));
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::failedReload() {
|
||||
DecodeDatabase database = BuildText(firstDbc);
|
||||
const std::shared_ptr<const DecodeFrame> original = database.FindFrame(FrameKey(17U, false));
|
||||
QVERIFY_THROWS_EXCEPTION(std::runtime_error, database = BuildText("BO_ invalid\n"));
|
||||
QCOMPARE(database.FindFrame(FrameKey(17U, false)), original);
|
||||
database = BuildText("");
|
||||
QVERIFY(database.GetFrames().empty());
|
||||
QVERIFY(!database.FindFrame(FrameKey(17U, false)));
|
||||
QCOMPARE(original->name, std::string("OldFrame"));
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::invalidResults() {
|
||||
RawCanFrame raw;
|
||||
raw.canId = 17U;
|
||||
DecodedFrameValue result = DbcDecoder().Decode(BuildText(firstDbc), raw);
|
||||
QVERIFY(result.valid);
|
||||
QVERIFY(!result.signals[0].valid);
|
||||
QCOMPARE(result.signals[0].status, SignalDecodeStatus::InsufficientPayload);
|
||||
QVERIFY(!result.signals[0].GetValueDescription());
|
||||
QCOMPARE(result.signals[0].definition->name, std::string("State"));
|
||||
result = DbcDecoder().Decode(DecodeDatabase(), raw);
|
||||
QVERIFY(!result.valid && !result.definition && result.signals.empty());
|
||||
QVERIFY(result.key == FrameKey(17U, false));
|
||||
QVERIFY(!DecodedSignalValue().GetValueDescription());
|
||||
QVERIFY(!DecodeDatabase().FindSignal(SignalKey(FrameKey(17U, false), "State")));
|
||||
}
|
||||
|
||||
void DbcLifetimeTest::retainedMultiplexStatuses() {
|
||||
const std::string text =
|
||||
"BO_ 17 Frame: 2 ECU\n"
|
||||
"SG_ Mode M : 0|1@1+ (1,0) [0|1] \"\" ECU\n"
|
||||
"SG_ State m1 : 8|8@1+ (1,0) [0|255] \"\" ECU\n";
|
||||
const std::vector<std::vector<std::uint8_t>> payloads = {{0U}, {}, {1U}};
|
||||
const SignalDecodeStatus statuses[] = {SignalDecodeStatus::Inactive,
|
||||
SignalDecodeStatus::SelectorUnavailable,
|
||||
SignalDecodeStatus::InsufficientPayload};
|
||||
for (std::size_t index = 0U; index < payloads.size(); ++index) {
|
||||
DecodeDatabase database = BuildText(text);
|
||||
RawCanFrame raw;
|
||||
raw.canId = 17U;
|
||||
raw.data = payloads[index];
|
||||
const DecodedSignalValue saved = DbcDecoder().Decode(database, raw).signals[1];
|
||||
database = BuildText(secondDbc);
|
||||
QCOMPARE(saved.status, statuses[index]);
|
||||
QVERIFY(!saved.valid && !saved.GetValueDescription());
|
||||
QCOMPARE(saved.definition->multiplexing.role, MultiplexRole::Branch);
|
||||
QVERIFY(saved.key == SignalKey(FrameKey(17U, false), "State"));
|
||||
}
|
||||
}
|
||||
|
||||
int RunLifetimeTests(int argc, char **argv) {
|
||||
DbcLifetimeTest test;
|
||||
return QTest::qExec(&test, argc, argv);
|
||||
}
|
||||
|
||||
#include "dbc_lifetime_test.moc"
|
||||
@@ -270,7 +270,7 @@ void DbcParserTest::diagnosticUnsupportedStatements() {
|
||||
CHECK(decoded.signals[0].GetValueDescription() &&
|
||||
*decoded.signals[0].GetValueDescription() == "On",
|
||||
"Warnings preserve VAL_ descriptions");
|
||||
QCOMPARE(runtime.frames[0].signals[0].comment, std::string("Signal comment"));
|
||||
QCOMPARE(runtime.GetFrames()[0].signals[0].comment, std::string("Signal comment"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ void DbcParserTest::multiplexingBoundaries() {
|
||||
"SG_ Mode M : 7|64@0+ (0,5) [0|1] \"\" ECU\n");
|
||||
const DbcDatabase parsed = DbcParser().ParseFile(fixture.path.string());
|
||||
DecodeDatabase runtime = DbcDecodeBuilder().Build(parsed);
|
||||
CHECK(runtime.frames[0].signals[0].multiplexing.value == std::numeric_limits<std::uint64_t>::max(),
|
||||
CHECK(runtime.GetFrames()[0].signals[0].multiplexing.value == std::numeric_limits<std::uint64_t>::max(),
|
||||
"Exact uint64 branch metadata");
|
||||
RawCanFrame raw;
|
||||
raw.canId = 1U;
|
||||
@@ -601,12 +601,15 @@ void DbcParserTest::multiplexingBoundaries() {
|
||||
result = DbcDecoder().Decode(runtime, raw);
|
||||
CHECK(result.signals[0].status == SignalDecodeStatus::Inactive,
|
||||
"Adjacent large integers remain distinct");
|
||||
runtime.frames[0].signals[1].length = 0U;
|
||||
std::vector<DecodeFrame> definitions = runtime.GetFrames();
|
||||
definitions[0].signals[1].length = 0U;
|
||||
runtime = DecodeDatabase(definitions);
|
||||
result = DbcDecoder().Decode(runtime, raw);
|
||||
CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition &&
|
||||
result.signals[1].status == SignalDecodeStatus::InvalidDefinition,
|
||||
"Malformed runtime selector distinguished from payload errors");
|
||||
runtime.frames[0].signals.pop_back();
|
||||
definitions[0].signals.pop_back();
|
||||
runtime = DecodeDatabase(definitions);
|
||||
result = DbcDecoder().Decode(runtime, raw);
|
||||
CHECK(result.signals[0].status == SignalDecodeStatus::InvalidDefinition,
|
||||
"Missing runtime selector");
|
||||
@@ -788,12 +791,12 @@ void DbcParserTest::valueDescriptions() {
|
||||
for (std::size_t index = 0; index < parsed.frames.size(); ++index) {
|
||||
CHECK(tree->GetChild(index)->GetChild(0)->GetSignal()->valueDescriptions ==
|
||||
parsed.frames[index].signals[0].valueDescriptions &&
|
||||
runtime.frames[index].signals[0].valueDescriptions ==
|
||||
runtime.GetFrames()[index].signals[0].valueDescriptions ==
|
||||
parsed.frames[index].signals[0].valueDescriptions,
|
||||
"All mappings survive both builders");
|
||||
}
|
||||
CHECK(tree->GetChild(0)->GetChild(0)->GetSignal()->valueDescriptions ==
|
||||
runtime.frames[0].signals[0].valueDescriptions,
|
||||
runtime.GetFrames()[0].signals[0].valueDescriptions,
|
||||
"Both builders preserve descriptions");
|
||||
RawCanFrame frame;
|
||||
frame.canId = 256;
|
||||
@@ -830,7 +833,7 @@ void DbcParserTest::valueDescriptions() {
|
||||
CHECK(decoded.GetValueDescription() && *decoded.GetValueDescription() == test.description,
|
||||
"Unsigned boundaries");
|
||||
}
|
||||
CHECK(FindValueDescription(runtime.frames[0].signals[0].valueDescriptions, std::int64_t(1)) != nullptr,
|
||||
CHECK(FindValueDescription(runtime.GetFrames()[0].signals[0].valueDescriptions, std::int64_t(1)) != nullptr,
|
||||
"Nonnegative signed lookup matches unsigned key");
|
||||
frame.data.clear();
|
||||
CHECK(!DbcDecoder().Decode(runtime, frame).signals[0].GetValueDescription(), "Invalid decode has no description");
|
||||
|
||||
+4
-1
@@ -5,10 +5,13 @@ int RunParserTests(int argc, char **argv);
|
||||
int RunDecoderTests(int argc, char **argv);
|
||||
int RunCoverageTests(int argc, char **argv);
|
||||
|
||||
int RunLifetimeTests(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
QCoreApplication application(argc, argv);
|
||||
const int parserResult = RunParserTests(argc, argv);
|
||||
const int decoderResult = RunDecoderTests(argc, argv);
|
||||
const int coverageResult = RunCoverageTests(argc, argv);
|
||||
return parserResult | decoderResult | coverageResult;
|
||||
const int lifetimeResult = RunLifetimeTests(argc, argv);
|
||||
return parserResult | decoderResult | coverageResult | lifetimeResult;
|
||||
}
|
||||
+1
-1
@@ -8,5 +8,5 @@ CONFIG -= app_bundle
|
||||
include(../core/core.pri)
|
||||
include(parser_tests.pri)
|
||||
include(decoder_tests.pri)
|
||||
SOURCES += main.cpp dbc_coverage_test.cpp
|
||||
SOURCES += main.cpp dbc_coverage_test.cpp dbc_lifetime_test.cpp
|
||||
CONFIG -= debug_and_release debug_and_release_target
|
||||
Reference in new issue
Block a user