This commit is contained in:
1 parent
0b05152bcf
commit
d87c100398
9 files changed
+265
-65
No files matched your search
@@ -75,6 +75,11 @@ On Linux, reading a directory exercises the distinct `FileReadError` path.
|
||||
Parser tests cover standard and extended CAN IDs, whitespace, payload storage
|
||||
boundaries, missing fields, malformed and overflowing numbers, reserved ID bits,
|
||||
error paths and line numbers, and integration with signals and comments.
|
||||
Comment regressions cover tabs, escaped quotes/backslashes, multiline text with
|
||||
blank lines and indentation, CRLF, missing final newlines, comments preceding
|
||||
frame/signal definitions, last-wins and empty overwrites, normalized ID boundaries,
|
||||
standard/extended separation, malformed syntax/IDs, and missing targets. Errors
|
||||
verify both structured diagnostics and the throwing API at the starting line.
|
||||
Duplicate definitions are rejected at their source lines, including equivalent
|
||||
extended ID encodings and repeated signal names within a frame. Standard and
|
||||
extended frames may share a numeric ID, and separate frames may reuse signal names.
|
||||
|
||||
@@ -312,10 +312,7 @@ void CoverageTest::comments_data() {
|
||||
QTest::newRow("tabs") << QString::fromUtf8("") << QString::fromUtf8("CM_\tBO_ 1 \"Frame\";\nCM_\tSG_ 1 State \"Signal\";\n") << QString::fromUtf8("Frame") << QString::fromUtf8("Signal");
|
||||
QTest::newRow("empty-overwrite") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 \"Old\";\nCM_ BO_ 1 \"\";\nCM_ SG_ 1 State \"Old\";\nCM_ SG_ 1 State \"\";\n") << QString::fromUtf8("") << QString::fromUtf8("");
|
||||
QTest::newRow("last-wins") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 \"First\";\nCM_ BO_ 1 \"Last\";\nCM_ SG_ 1 State \"First\";\nCM_ SG_ 1 State \"Last\";\n") << QString::fromUtf8("Last") << QString::fromUtf8("Last");
|
||||
QTest::newRow("missing-targets") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 2 \"Unknown\";\nCM_ SG_ 2 State \"Unknown\";\nCM_ SG_ 1 Missing \"Unknown\";\n") << QString::fromUtf8("") << QString::fromUtf8("");
|
||||
// Current documented limitation: comments resolve only already parsed targets.
|
||||
QTest::newRow("before-definitions") << QString::fromUtf8("CM_ BO_ 1 \"Early\";\nCM_ SG_ 1 State \"Early\";\n") << QString::fromUtf8("") << QString::fromUtf8("") << QString::fromUtf8("");
|
||||
QTest::newRow("missing-quotes") << QString::fromUtf8("") << QString::fromUtf8("CM_ BO_ 1 Missing;\nCM_ SG_ 1 State \"Unclosed;\n") << QString::fromUtf8("") << QString::fromUtf8("");
|
||||
QTest::newRow("before-definitions") << QString::fromUtf8("CM_ BO_ 1 \"Early\";\nCM_ SG_ 1 State \"Early\";\n") << QString::fromUtf8("") << QString::fromUtf8("Early") << QString::fromUtf8("Early");
|
||||
}
|
||||
|
||||
void CoverageTest::comments() {
|
||||
|
||||
@@ -75,6 +75,9 @@ private Q_SLOTS:
|
||||
void duplicateFrames();
|
||||
void duplicateSignals();
|
||||
void distinctDefinitions();
|
||||
void comments();
|
||||
void invalidComments_data();
|
||||
void invalidComments();
|
||||
void integration();
|
||||
void invalidSignals();
|
||||
void validSignals();
|
||||
@@ -489,6 +492,103 @@ void DbcParserTest::distinctDefinitions() {
|
||||
QCOMPARE(extended.definition->comment, std::string("Extended"));
|
||||
}
|
||||
|
||||
void DbcParserTest::comments() {
|
||||
Fixture fixture;
|
||||
fixture.Write(
|
||||
"CM_\tBO_\t1\t\"First\";\r\n"
|
||||
"CM_\tSG_\t1\tState\t\" Line one \r\n"
|
||||
"\r\n"
|
||||
"\tBO_ is text; \\\"quoted\\\" and \\\\slash\"\t;\r\n"
|
||||
"CM_ BO_ 2147483649 \"Extended\";\r\n"
|
||||
"CM_ SG_ 2147483649 State \"Extended signal\";\r\n"
|
||||
"BO_ 1 Standard: 1 ECU\r\n"
|
||||
"CM_ BO_ 1 \"Last\";\r\n"
|
||||
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\r\n"
|
||||
"BO_ 2147483649 Extended: 1 ECU\r\n"
|
||||
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU");
|
||||
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
|
||||
QVERIFY(!result.HasErrors());
|
||||
QVERIFY(result.diagnostics.empty());
|
||||
QCOMPARE(result.database.frames.size(), std::size_t(2));
|
||||
QCOMPARE(result.database.frames[0].comment, std::string("Last"));
|
||||
QCOMPARE(result.database.frames[0].signals[0].comment,
|
||||
std::string(" Line one \n\n\tBO_ is text; \"quoted\" and \\slash"));
|
||||
QCOMPARE(result.database.frames[1].comment, std::string("Extended"));
|
||||
QCOMPARE(result.database.frames[1].signals[0].comment, std::string("Extended signal"));
|
||||
|
||||
const std::string ids[][2] = {
|
||||
{"0", "0"},
|
||||
{"2047", "2047"},
|
||||
{"2048", "2147485696"},
|
||||
{"536870911", "2684354559"},
|
||||
{"2684354559", "536870911"}};
|
||||
for (const std::string(&id)[2]: ids) {
|
||||
fixture.Write("CM_ BO_ " + id[0] + " \"Frame\";\nCM_ SG_ " + id[0] +
|
||||
" State \"Signal\";\nBO_ " + id[1] + " Frame: 1 ECU\n"
|
||||
"SG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n");
|
||||
const DbcDatabase database = DbcParser().ParseFile(fixture.path.string());
|
||||
QCOMPARE(database.frames[0].comment, std::string("Frame"));
|
||||
QCOMPARE(database.frames[0].signals[0].comment, std::string("Signal"));
|
||||
}
|
||||
fixture.Write("CM_ BO_ 1 \"Line one\nLine two\";\n"
|
||||
"BO_ 1 Frame: 0 ECU\nUNKNOWN_ value\nBO_ bad Frame: 0 ECU\n");
|
||||
const DbcParseResult following = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
|
||||
QVERIFY(following.HasErrors());
|
||||
QCOMPARE(following.diagnostics.size(), std::size_t(2));
|
||||
QCOMPARE(following.diagnostics[0].lineNumber, std::size_t(4));
|
||||
QCOMPARE(following.diagnostics[1].lineNumber, std::size_t(5));
|
||||
}
|
||||
|
||||
void DbcParserTest::invalidComments_data() {
|
||||
QTest::addColumn<QString>("statement");
|
||||
const char *ids[] = {"-1", "+1", "1x", "0x1", "4294967296", "536870912",
|
||||
"1073741824", "2684354560", "4294967295"};
|
||||
for (const char *id: ids) {
|
||||
const std::string frameRow = std::string("frame-id-") + id;
|
||||
const std::string signalRow = std::string("signal-id-") + id;
|
||||
QTest::newRow(frameRow.c_str()) << QString::fromStdString("CM_ BO_ " + std::string(id) + " \"Text\";");
|
||||
QTest::newRow(signalRow.c_str()) << QString::fromStdString("CM_ SG_ " + std::string(id) + " State \"Text\";");
|
||||
}
|
||||
QTest::newRow("missing-id") << QStringLiteral("CM_ BO_");
|
||||
QTest::newRow("missing-signal") << QStringLiteral("CM_ SG_ 1 \"Text\";");
|
||||
QTest::newRow("missing-quote") << QStringLiteral("CM_ BO_ 1 Text;");
|
||||
QTest::newRow("unclosed") << QStringLiteral("CM_ SG_ 1 State \"Text\n More");
|
||||
QTest::newRow("invalid-escape") << QStringLiteral("CM_ BO_ 1 \"bad\\q\";");
|
||||
QTest::newRow("dangling-escape") << QStringLiteral("CM_ BO_ 1 \"bad\\");
|
||||
QTest::newRow("missing-semicolon") << QStringLiteral("CM_ SG_ 1 State \"Text\"");
|
||||
QTest::newRow("trailing-text") << QStringLiteral("CM_ BO_ 1 \"Text\"; garbage");
|
||||
QTest::newRow("extra-header") << QStringLiteral("CM_ BO_ 1 extra \"Text\";");
|
||||
QTest::newRow("extra-string") << QStringLiteral("CM_ BO_ 1 \"Text\" \"More\";");
|
||||
QTest::newRow("missing-frame") << QStringLiteral("CM_ BO_ 2 \"Text\";");
|
||||
QTest::newRow("missing-signal-frame") << QStringLiteral("CM_ SG_ 2 State \"Text\";");
|
||||
QTest::newRow("missing-signal-reference") << QStringLiteral("CM_ SG_ 1 Missing \"Text\";");
|
||||
QTest::newRow("different-frame-type") << QStringLiteral("CM_ BO_ 2147483649 \"Text\";");
|
||||
QTest::newRow("missing-multiline-reference") << QStringLiteral("CM_ SG_ 1 Missing \"Text\nMore\";");
|
||||
}
|
||||
|
||||
void DbcParserTest::invalidComments() {
|
||||
QFETCH(QString, statement);
|
||||
Fixture fixture;
|
||||
fixture.Write("BO_ 1 Frame: 1 ECU\nSG_ State : 0|8@1+ (1,0) [0|255] \"\" ECU\n\n" +
|
||||
statement.toStdString());
|
||||
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
|
||||
QVERIFY(result.HasErrors());
|
||||
QVERIFY(result.database.frames.empty());
|
||||
QCOMPARE(result.diagnostics.size(), std::size_t(1));
|
||||
const DbcDiagnostic &error = result.diagnostics[0];
|
||||
QCOMPARE(error.severity, DbcDiagnosticSeverity::Error);
|
||||
QCOMPARE(error.code, DbcDiagnosticCode::InvalidStatement);
|
||||
QCOMPARE(error.filePath, fixture.path.string());
|
||||
QCOMPARE(error.lineNumber, std::size_t(4));
|
||||
QVERIFY(!error.message.empty());
|
||||
try {
|
||||
DbcParser().ParseFile(fixture.path.string());
|
||||
QFAIL("Malformed or unresolved comment must throw.");
|
||||
} catch (const std::runtime_error &exception) {
|
||||
QVERIFY(std::string(exception.what()).find(fixture.path.string() + ":4: ") == 0U);
|
||||
}
|
||||
}
|
||||
|
||||
void DbcParserTest::integration() {
|
||||
Fixture fixture;
|
||||
fixture.Write(
|
||||
|
||||
Reference in new issue
Block a user