This commit is contained in:
deeaitch committed 2026-10-05 18:33:19 -04:00
1 parent 88b5883dda
commit 8d82b13dad
5 files changed
+227 -94

No files matched your search

+3
View File
@@ -43,6 +43,9 @@ following the decoder instructions above, then run `./dbc_parser_test`.
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.
Signal tests cover complete syntax and numeric validation, scientific notation,
finite physical parameters and ordered ranges, spaces and tabs, receiver lists,
unsupported multiplexing, and Intel/Motorola declared-payload boundaries.
Temporary DBC fixtures are created in the system temporary directory and removed
automatically.
+97
View File
@@ -100,6 +100,103 @@ int main() {
check (std::string (error.what()).find (fixture.path.string() + ":2: ") == 0U,
"Signal error location");
}
const DbcParser signalParser;
const auto signalLine = [] (const std::string &start, const std::string &length,
const std::string &order, const std::string &factor,
const std::string &offset, const std::string &minimum,
const std::string &maximum) {
return "SG_ Value : " + start + "|" + length + "@" + order +
" (" + factor + "," + offset + ") [" + minimum + "|" + maximum + "] \"\" ECU";
};
const auto rejectSignal = [&] (const std::string &line, unsigned payload = 8U) {
fixture.Write ("BO_ 1 Frame: " + std::to_string (payload) + " ECU\n\n" + line + "\n");
try {
signalParser.ParseFile (fixture.path.string());
check (false, "Reject " + line);
} catch (const std::runtime_error &error) {
const std::string prefix = fixture.path.string() + ":3: ";
check (std::string (error.what()).find (prefix) == 0U &&
std::string (error.what()).size() > prefix.size(), "Reject " + line);
}
};
const std::string ordinary = signalLine ("0", "8", "1+", "1", "0", "0", "255");
for (const std::string value : {"-1", "+1", "0junk", "0x10", "1.5",
"4294967296", "999999999999999999999"}) {
rejectSignal (signalLine (value, "8", "1+", "1", "0", "0", "255"));
rejectSignal (signalLine ("0", value, "1+", "1", "0", "0", "255"));
}
for (const std::string length : {"0", "65"})
rejectSignal (signalLine ("0", length, "1+", "1", "0", "0", "255"));
for (const std::string order : {"2+", "9-", "1", "1x", "1++", "01+"})
rejectSignal (signalLine ("0", "8", order, "1", "0", "0", "255"));
for (const std::string value : {"1junk", "nan", "NaN", "inf", "-inf", "1e999", "1e-999", "0x1p2", "", "1e", "1.2.3"}) {
rejectSignal (signalLine ("0", "8", "1+", value, "0", "0", "255"));
rejectSignal (signalLine ("0", "8", "1+", "1", value, "0", "255"));
rejectSignal (signalLine ("0", "8", "1+", "1", "0", value, "255"));
rejectSignal (signalLine ("0", "8", "1+", "1", "0", "0", value));
}
rejectSignal (signalLine ("0", "8", "1+", "1", "0", "2", "1"));
for (const std::string name : {"", "Two Names", "Value M", "Value m1", "Value m1M"}) {
std::string line = ordinary;
line.replace (4U, 5U, name);
rejectSignal (line);
}
for (const std::string broken : {
"SG_", "SG_ Value", "SG_ Value : 0|8@1+ (1,0) [0|255] ECU",
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\"",
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU,",
"SG_ Value : 0|8@1+ (1,0) [0|255] \"\" ECU extra"})
rejectSignal (broken);
rejectSignal (signalLine ("64", "1", "1+", "1", "0", "0", "1"));
rejectSignal (signalLine ("63", "2", "1+", "1", "0", "0", "3"));
rejectSignal (signalLine ("56", "2", "0+", "1", "0", "0", "3"));
rejectSignal (signalLine ("4294967295", "64", "1+", "1", "0", "0", "1"));
rejectSignal (ordinary, 0U);
for (const char delimiter : {'|', '@', '(', ')', '[', ']', '"'}) {
std::string line = ordinary;
line.erase (line.find (delimiter), 1U);
rejectSignal (line);
}
fixture.Write ("BO_ 1 Frame: 8 ECU\n" +
signalLine ("0", "8", "1+", "0", "0", "0", "0") + "\n" +
signalLine ("8", "8", "1-", "-1", "0", "-255", "0") + "\n");
const auto factors = signalParser.ParseFile (fixture.path.string());
check (factors.frames[0].signals.size() == 2U &&
factors.frames[0].signals[0].factor == 0.0 &&
factors.frames[0].signals[1].factor == -1.0,
"Zero and negative factors and equal range boundaries");
struct SignalCase { const char *start; const char *length; const char *order; unsigned payload; };
const SignalCase validSignals[] = {
{"0", "1", "1+", 1U}, {"7", "1", "0-", 1U},
{"0", "64", "1+", 8U}, {"7", "64", "0-", 8U},
{"63", "1", "1+", 8U}, {"56", "1", "0+", 8U},
{"3", "12", "0+", 2U}, {"2039", "1", "1+", 255U}
};
for (const auto &test : validSignals) {
fixture.Write ("BO_ 1 Frame: " + std::to_string (test.payload) + " ECU\n" +
signalLine (test.start, test.length, test.order, ".5e+1", "-2.5E-1", "-1.", "+2e2") + "\n");
try {
const auto parsed = signalParser.ParseFile (fixture.path.string());
const auto &signal = parsed.frames.at (0).signals.at (0);
check (signal.startBit == std::stoul (test.start) &&
signal.length == std::stoul (test.length) &&
signal.isLittleEndian == (test.order[0] == '1') &&
signal.isSigned == (test.order[1] == '-') &&
signal.factor == 5.0 && signal.offset == -0.25 &&
signal.minimum == -1.0 && signal.maximum == 200.0,
"Valid signal boundary and numeric metadata");
} catch (const std::exception &error) { check (false, error.what()); }
}
fixture.Write ("BO_ 1 Frame: 8 ECU\n"
"SG_\tValue\t:\t0 | 8 @1+ ( 1 , 0 ) [ 0 | 255 ] \"rpm\" ECU1,\tECU2\n");
try {
const auto parsed = signalParser.ParseFile (fixture.path.string());
const auto &signal = parsed.frames.at (0).signals.at (0);
check (signal.name == "Value" && signal.unit == "rpm" &&
signal.receivers == std::vector<std::string> ({"ECU1", "ECU2"}),
"Signal tabs, spaces, and receiver list");
} catch (const std::exception &error) { check (false, error.what()); }
DbcDatabase dispatchDatabase;
DbcParseContext context {dispatchDatabase, nullptr};
DbcStatementDispatcher dispatcher;