This commit is contained in:
deeaitch committed 2026-10-20 13:21:43 -04:00
1 parent e555ebb571
commit 849ce31e2f
17 files changed
+675 -35

No files matched your search

+133 -4
View File
@@ -3,6 +3,7 @@
#include "dbc_parser.h"
#include "dbc_statement_handler.h"
#include "dbc_tree_builder.h"
#include <algorithm>
#include <clocale>
#include <limits>
#include <locale>
@@ -87,6 +88,9 @@ private:
}
}
private Q_SLOTS:
void attributes();
void invalidAttributes();
void attributeWarnings();
void diagnostics();
void diagnosticErrors();
void diagnosticUnsupportedStatements();
@@ -113,6 +117,133 @@ private Q_SLOTS:
void invalidValueDescriptions();
};
void DbcParserTest::attributes() {
Fixture fixture;
fixture.Write(
"BA_ \"GenMsgCycleTime\" BO_ 1 25;\n"
"BA_ \"VFrameFormat\" BO_ 2147483649 1;\n"
"BA_ \"Label\" SG_ 1 Value \"a\\\"b\\\\c\";\n"
"BA_ \"NodeLabel\" BU_ ECU \"node\";\n"
"BA_ \"Environment\" EV_ Env 2;\n"
"BA_DEF_DEF_ \"GenMsgCycleTime\" 100;\n"
"BA_DEF_DEF_ \"VFrameFormat\" \"StandardCAN\";\n"
"BA_DEF_DEF_ \"Label\" \"default\";\n"
"BA_DEF_DEF_ \"BusLabel\" \"CAN\";\n"
"BA_DEF_DEF_ \"Ratio\" 1.5e-1;\n"
"BA_DEF_ BO_ \"GenMsgCycleTime\" INT 0 10000;\n"
"BA_DEF_ BO_ \"VFrameFormat\" ENUM \"StandardCAN\",\"ExtendedCAN\",\"StandardCAN_FD\";\n"
"BA_DEF_ SG_ \"Label\" STRING;\n"
"BA_DEF_ \"BusLabel\" STRING;\n"
"BA_DEF_ BO_ \"Ratio\" FLOAT -1 1;\n"
"BA_DEF_ BU_ \"NodeLabel\" STRING;\n"
"BA_DEF_ EV_ \"Environment\" HEX 0 255;\n"
"BO_ 1 Standard: 1 ECU\n"
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
"BO_ 2147483649 Extended: 1 ECU\n"
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n");
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
QVERIFY(!result.HasErrors());
QVERIFY(result.diagnostics.empty());
const DbcDatabase &database = result.database;
QCOMPARE(database.attributeDefinitions.size(), std::size_t(7));
QCOMPARE(database.attributeAssignments.size(), std::size_t(5));
QCOMPARE(std::get<std::string>(database.attributes.at("BusLabel")), std::string("CAN"));
QCOMPARE(database.frames[0].cycleTimeMs.value(), 25U);
QCOMPARE(database.frames[1].cycleTimeMs.value(), 100U);
QCOMPARE(database.frames[1].frameFormat.value(), std::string("ExtendedCAN"));
QVERIFY(!database.frames[1].hasPgn);
QCOMPARE(std::get<double>(database.frames[0].attributes.at("Ratio")), 0.15);
QCOMPARE(std::get<std::string>(database.frames[0].signals[0].attributes.at("Label")), std::string("a\"b\\c"));
QCOMPARE(std::get<std::string>(database.frames[1].signals[0].attributes.at("Label")), std::string("default"));
const DecodeDatabase runtime = DbcDecodeBuilder().Build(database);
QCOMPARE(runtime.GetFrames()[0].cycleTimeMs.value(), 25U);
QCOMPARE(runtime.GetFrames()[1].frameFormat.value(), std::string("ExtendedCAN"));
QCOMPARE(runtime.GetFrames()[0].signals[0].attributes, database.frames[0].signals[0].attributes);
const std::unique_ptr<TreeNode> tree = DbcTreeBuilder().Build(database);
QCOMPARE(tree->GetChild(0)->GetFrame()->cycleTimeMs.value(), 25U);
QCOMPARE(tree->GetChild(0)->GetChild(0)->GetSignal()->attributes, database.frames[0].signals[0].attributes);
fixture.Write("BA_DEF_ BO_ \"Period\" INT 0 10;\nBA_DEF_DEF_ \"Period\" 1;\n"
"BA_ \"Period\" BO_ 1 2;\nBA_ \"Period\" BO_ 1 3;\nBO_ 1 F: 0 ECU\n");
const DbcDatabase repeated = DbcParser().ParseFile(fixture.path.string());
QCOMPARE(std::get<std::int64_t>(repeated.frames[0].attributes.at("Period")), std::int64_t(3));
fixture.Write("BA_DEF_ BO_ \"GenMsgCycleTime\" INT 0 4294967295;\n"
"BA_DEF_DEF_ \"GenMsgCycleTime\" 0;\n"
"BA_ \"GenMsgCycleTime\" BO_ 1 4294967295;\n"
"BA_DEF_ \"Wide\" INT -9223372036854775808 9223372036854775807;\n"
"BA_DEF_DEF_ \"Wide\" -9223372036854775808;\n"
"BA_DEF_ SG_ \"State\" ENUM \"off\",\"on\";\n"
"BA_DEF_DEF_ \"State\" 1;\n"
"BO_ 1 F: 0 ECU\nBO_ 2 Empty: 0 ECU\n");
const DbcDatabase boundaries = DbcParser().ParseFile(fixture.path.string());
QCOMPARE(boundaries.frames[0].cycleTimeMs.value(), std::numeric_limits<std::uint32_t>::max());
QCOMPARE(boundaries.frames[1].cycleTimeMs.value(), 0U);
QVERIFY(!boundaries.frames[0].frameFormat);
QCOMPARE(std::get<std::int64_t>(boundaries.attributes.at("Wide")), std::numeric_limits<std::int64_t>::min());
QCOMPARE(std::get<std::int64_t>(*boundaries.attributeDefinitions.at("State").defaultValue), std::int64_t(1));
}
void DbcParserTest::invalidAttributes() {
Fixture fixture;
const std::vector<std::string> invalid = {
"BA_DEF_ BO_ \"A\" INT 2 1;",
"BA_DEF_ BO_ \"A\" FLOAT nan 1;",
"BA_DEF_ BO_ \"A\" FLOAT 0 inf;",
"BA_DEF_ BO_ \"A\" INT 0 9223372036854775808;",
"BA_DEF_ BO_ \"A\" STRING; trailing",
"BA_DEF_ BO_ \"A\" ENUM;",
"BA_DEF_ BO_ \"A\" ENUM \"one\",;",
"BA_DEF_ BO_ \"A\" ENUM \"one\",\"one\";",
"BA_DEF_ BO_ \"VFrameFormat\" STRING;",
"BA_DEF_ SG_ \"GenMsgCycleTime\" INT 0 10;",
"BA_ \"Unknown\" BO_ 1 0;",
"BA_DEF_DEF_ \"Unknown\" 0;",
"BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 1 2;",
"BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 1 \"0\";",
"BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" SG_ 1 S 0;",
"BA_DEF_ BO_ \"A\" INT 0 1;\nBA_ \"A\" BO_ 2 0;",
"BA_DEF_ SG_ \"A\" INT 0 1;\nBA_ \"A\" SG_ 1 Missing 0;",
"BA_DEF_ BO_ \"A\" INT 0 1;\nBA_DEF_ BO_ \"A\" INT 0 1;",
"BA_DEF_ BO_ \"A\" INT 0 1;\nBA_DEF_DEF_ \"A\" 0;\nBA_DEF_DEF_ \"A\" 1;",
"BA_DEF_ BO_ \"A\" STRING;\nBA_ \"A\" BO_ 1 \"bad\\q\";",
"BA_DEF_ BO_ \"A\" STRING;\nBA_ \"A\" BO_ 1 \"unterminated;",
"BA_DEF_ BO_ \"A\" ENUM \"one\";\nBA_DEF_DEF_ \"A\" \"missing\";",
"BA_DEF_ BO_ \"A\" ENUM \"one\";\nBA_ \"A\" BO_ 1 1;",
"BA_DEF_ BO_ \"GenMsgCycleTime\" INT -1 4294967296;\nBA_DEF_DEF_ \"GenMsgCycleTime\" -1;",
"BA_DEF_ BO_ \"GenMsgCycleTime\" INT 0 4294967296;\nBA_ \"GenMsgCycleTime\" BO_ 1 4294967296;"};
for (const std::string &statement: invalid) {
fixture.Write("BO_ 1 F: 0 ECU\n" + statement + '\n');
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
QVERIFY2(result.HasErrors(), statement.c_str());
QVERIFY(result.database.frames.empty());
QCOMPARE(result.diagnostics.back().code, DbcDiagnosticCode::InvalidAttribute);
QCOMPARE(result.diagnostics.back().lineNumber, std::size_t(2 + std::count(statement.begin(), statement.end(), '\n')));
QVERIFY_THROWS_EXCEPTION(std::runtime_error, DbcParser().ParseFile(fixture.path.string()));
}
}
void DbcParserTest::attributeWarnings() {
Fixture fixture;
fixture.Write("BA_DEF_ BO_ \"VFrameFormat\" ENUM \"StandardCAN\",\"ExtendedCAN\",\"J1939PG\",\"StandardCAN_FD\";\n"
"BA_DEF_DEF_ \"VFrameFormat\" \"StandardCAN_FD\";\n"
"BA_ \"VFrameFormat\" BO_ 1 2;\n"
"BA_ \"VFrameFormat\" BO_ 2147483649 0;\n"
"BO_ 1 F: 0 ECU\nBO_ 2147483649 E: 0 ECU\nBO_ 2 Default: 0 ECU\n");
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
QVERIFY(!result.HasErrors());
QCOMPARE(result.diagnostics.size(), std::size_t(3));
const std::size_t lines[] = {3U, 4U, 2U};
for (std::size_t index = 0; index < 3U; ++index) {
QCOMPARE(result.diagnostics[index].code, DbcDiagnosticCode::UnsupportedAttribute);
QCOMPARE(result.diagnostics[index].severity, DbcDiagnosticSeverity::Warning);
QCOMPARE(result.diagnostics[index].lineNumber, lines[index]);
QCOMPARE(result.diagnostics[index].filePath, fixture.path.string());
}
QCOMPARE(result.database.frames[0].frameFormat.value(), std::string("J1939PG"));
QVERIFY(!result.database.frames[0].hasPgn);
QVERIFY(result.database.frames[1].isExtended);
}
void DbcParserTest::diagnostics() {
Fixture fixture;
fixture.Write("VERSION \"test\"\n"
@@ -126,7 +257,7 @@ void DbcParserTest::diagnostics() {
"BO_ 1 Frame: 1 ECU\n"
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU\n"
"SIG_VALTYPE_ 1 Value : 1;\n"
"BA_ \"SignalType\" SG_ 1 Value 1;\n"
"BA_REL_ \"SignalType\" SG_ 1 Value 1;\n"
"VENDOR_EXTENSION_ data;\n");
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
CHECK(!result.HasErrors() && result.database.frames.size() == 1U,
@@ -264,9 +395,7 @@ void DbcParserTest::diagnosticUnsupportedStatements() {
"CM_ SG_ 1 Value \"Signal comment\";\nVAL_ 1 Value 1 \"On\";\n";
const std::vector<std::string> statements = {
"SIG_VALTYPE_ 1 Value : 1;", "SIG_VALTYPE_ 1 Value : 2;",
"BA_ \"SignalType\" SG_ 1 Value 1;",
"BA_DEF_ SG_ \"SignalType\" INT 0 1;",
"BA_DEF_DEF_ \"SignalType\" 0;",
"BA_REL_ \"SignalType\" SG_ 1 Value 1;",
"BA_DEF_REL_ BU_SG_REL_ \"Relation\" INT 0 1;",
"BA_REL_ \"Relation\" BU_SG_REL_ ECU SG_ 1 Value 1;",
"SGTYPE_ Type : 8@1+ (1,0) [0|255] \"\" 0, Table;",