Fix #2 Preserve unsigned 64-bit decoded values

This commit is contained in:
deeaitch committed 2026-10-01 13:09:57 -04:00
1 parent 2c057b631d
commit 69074e3321
6 files changed
+112 -15

No files matched your search

+2 -1
View File
@@ -22,6 +22,7 @@ The executable returns a nonzero exit code if any case fails. Checks remain
active in release builds and do not depend on `assert` or an external test framework.
Coverage includes Motorola bit numbering within and across bytes, unaligned
signals, signed values, scaling, 64-bit extraction, invalid lengths, insufficient
signals, signed values, scaling, 64-bit extraction, signed/unsigned boundary values
(including `INT64_MIN`, `INT64_MAX`, and `UINT64_MAX`), numeric output, invalid lengths, insufficient
payloads, and Intel regression cases. Frame validity means the definition was
found; insufficient payloads are checked through signal validity.
+59 -2
View File
@@ -2,6 +2,7 @@
#include <iostream>
#include <limits>
#include <sstream>
struct DecodeCase {
const char *name;
@@ -83,15 +84,71 @@ int main() {
(result.signals.size() == 1U) &&
(result.signals[0].definition == &database.frames[0].signals[0]) &&
(result.signals[0].valid == test.valid) &&
(!test.valid || ((result.signals[0].rawValue == test.rawValue) &&
(!test.valid || (((test.valueType == ValueType::Signed)
? (std::get_if<std::int64_t> (&result.signals[0].rawValue) &&
std::get<std::int64_t> (result.signals[0].rawValue) == test.rawValue)
: (std::get_if<std::uint64_t> (&result.signals[0].rawValue) &&
std::get<std::uint64_t> (result.signals[0].rawValue) ==
static_cast<std::uint64_t> (test.rawValue))) &&
(result.signals[0].physicalValue == test.physicalValue)));
if (!passed) {
std::cerr << "FAIL: " << test.name << '\n';
++failures;
}
}
std::size_t boundaryCases = 0U;
for (ByteOrder order : {ByteOrder::Intel, ByteOrder::Motorola}) {
for (ValueType type : {ValueType::Unsigned, ValueType::Signed}) {
for (std::uint64_t bits : {std::uint64_t (0U), std::uint64_t (0x7FFFFFFFFFFFFFFFULL),
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;
signal.length = 64U;
signal.byteOrder = order;
signal.valueType = type;
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);
RawCanFrame frame;
for (unsigned byte = 0U; byte < 8U; ++byte) {
const unsigned shift = (order == ByteOrder::Intel ? byte : 7U - byte) * 8U;
frame.data.push_back (static_cast<std::uint8_t> (bits >> shift));
}
const auto result = DbcDecoder().Decode (database, frame);
const std::int64_t signedExpected = bits <= 0x7FFFFFFFFFFFFFFFULL
? static_cast<std::int64_t> (bits)
: std::numeric_limits<std::int64_t>::min() +
static_cast<std::int64_t> (bits - 0x8000000000000000ULL);
const auto &decoded = result.signals.at (0U);
const auto expected = type == ValueType::Unsigned
? std::variant<std::int64_t, std::uint64_t> (bits)
: std::variant<std::int64_t, std::uint64_t> (signedExpected);
const double physical = (type == ValueType::Unsigned
? static_cast<double> (bits) : static_cast<double> (signedExpected)) * 0.5 + 10.0;
std::ostringstream actualText;
std::ostringstream expectedText;
std::visit ([&actualText] (auto raw) { actualText << raw; }, decoded.rawValue);
if (type == ValueType::Unsigned)
expectedText << bits;
else
expectedText << signedExpected;
if (!decoded.valid || decoded.rawValue != expected ||
decoded.physicalValue != physical || actualText.str() != expectedText.str()) {
std::cerr << "FAIL: 64-bit boundary " << bits << '\n';
++failures;
}
++boundaryCases;
}
}
}
if (failures != 0)
return 1;
std::cout << "All " << sizeof (cases) / sizeof (cases[0]) << " decoder cases passed.\n";
std::cout << "All " << sizeof (cases) / sizeof (cases[0]) + boundaryCases << " decoder cases passed.\n";
return 0;
}