This commit is contained in:
deeaitch committed 2026-10-11 06:30:18 -04:00
1 parent 51fcdb88ac
commit 0708316a37
155 files changed
+5190 -2691

No files matched your search

+18 -2
View File
@@ -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
View File
@@ -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);
+4 -8
View File
@@ -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;
+242
View File
@@ -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(), &copy.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"
+10 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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