Closes #7
This commit is contained in:
1 parent
8d82b13dad
commit
b91cf4aae5
21 files changed
+1165
-1146
No files matched your search
+123
-138
@@ -5,150 +5,135 @@
|
||||
#include <sstream>
|
||||
|
||||
struct DecodeCase {
|
||||
const char *name;
|
||||
ByteOrder byteOrder;
|
||||
std::uint32_t startBit;
|
||||
std::uint32_t length;
|
||||
ValueType valueType;
|
||||
std::vector<std::uint8_t> data;
|
||||
bool valid;
|
||||
std::int64_t rawValue;
|
||||
double factor;
|
||||
double offset;
|
||||
double physicalValue;
|
||||
const char *name;
|
||||
ByteOrder byteOrder;
|
||||
std::uint32_t startBit;
|
||||
std::uint32_t length;
|
||||
ValueType valueType;
|
||||
std::vector<std::uint8_t> data;
|
||||
bool valid;
|
||||
std::int64_t rawValue;
|
||||
double factor;
|
||||
double offset;
|
||||
double physicalValue;
|
||||
};
|
||||
|
||||
int main() {
|
||||
const DecodeCase cases[] = {
|
||||
{"Motorola reproduction", ByteOrder::Motorola, 7U, 16U, ValueType::Unsigned,
|
||||
{0x12, 0x34}, true, 0x1234, 1.0, 0.0, 4660.0},
|
||||
{"Motorola within byte", ByteOrder::Motorola, 5U, 4U, ValueType::Unsigned,
|
||||
{0xAC}, true, 11, 1.0, 0.0, 11.0},
|
||||
{"Motorola unaligned crossing", ByteOrder::Motorola, 3U, 12U, ValueType::Unsigned,
|
||||
{0xAB, 0xCD}, true, 0xBCD, 1.0, 0.0, 3021.0},
|
||||
{"Motorola starts at bit zero", ByteOrder::Motorola, 0U, 2U, ValueType::Unsigned,
|
||||
{0x01, 0x80}, true, 3, 1.0, 0.0, 3.0},
|
||||
{"Motorola second byte", ByteOrder::Motorola, 15U, 16U, ValueType::Unsigned,
|
||||
{0xFF, 0x12, 0x34}, true, 0x1234, 1.0, 0.0, 4660.0},
|
||||
{"Motorola signed scaled", ByteOrder::Motorola, 7U, 16U, ValueType::Signed,
|
||||
{0xFF, 0xFE}, true, -2, 0.5, 10.0, 9.0},
|
||||
{"Motorola 64 bits", ByteOrder::Motorola, 7U, 64U, ValueType::Unsigned,
|
||||
{0, 0, 0, 0, 0, 0, 0x12, 0x34}, true, 0x1234, 1.0, 0.0, 4660.0},
|
||||
{"Motorola 64 bits high bit", ByteOrder::Motorola, 7U, 64U, ValueType::Unsigned,
|
||||
{0x40, 0, 0, 0, 0, 0, 0, 0}, true, 0x4000000000000000LL,
|
||||
1.0, 0.0, 4611686018427387904.0},
|
||||
{"Motorola short payload", ByteOrder::Motorola, 7U, 16U, ValueType::Unsigned,
|
||||
{0x12}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola empty payload", ByteOrder::Motorola, 7U, 8U, ValueType::Unsigned,
|
||||
{}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola large start", ByteOrder::Motorola,
|
||||
std::numeric_limits<std::uint32_t>::max(), 8U, ValueType::Unsigned,
|
||||
{0xFF}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola zero length", ByteOrder::Motorola, 7U, 0U, ValueType::Unsigned,
|
||||
{0xFF}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola excessive length", ByteOrder::Motorola, 7U, 65U, ValueType::Unsigned,
|
||||
std::vector<std::uint8_t> (9U, 0xFF), false, 0, 1.0, 0.0, 0.0},
|
||||
{"Intel regression", ByteOrder::Intel, 0U, 16U, ValueType::Unsigned,
|
||||
{0x12, 0x34}, true, 0x3412, 1.0, 0.0, 13330.0},
|
||||
{"Intel signed regression", ByteOrder::Intel, 0U, 16U, ValueType::Signed,
|
||||
{0xFE, 0xFF}, true, -2, 0.5, 10.0, 9.0},
|
||||
{"Intel short payload", ByteOrder::Intel, 0U, 16U, ValueType::Unsigned,
|
||||
{0x12}, false, 0, 1.0, 0.0, 0.0}
|
||||
};
|
||||
const DecodeCase cases[] = {
|
||||
{"Motorola reproduction", ByteOrder::Motorola, 7U, 16U, ValueType::Unsigned, {0x12, 0x34}, true, 0x1234, 1.0, 0.0, 4660.0},
|
||||
{"Motorola within byte", ByteOrder::Motorola, 5U, 4U, ValueType::Unsigned, {0xAC}, true, 11, 1.0, 0.0, 11.0},
|
||||
{"Motorola unaligned crossing", ByteOrder::Motorola, 3U, 12U, ValueType::Unsigned, {0xAB, 0xCD}, true, 0xBCD, 1.0, 0.0, 3021.0},
|
||||
{"Motorola starts at bit zero", ByteOrder::Motorola, 0U, 2U, ValueType::Unsigned, {0x01, 0x80}, true, 3, 1.0, 0.0, 3.0},
|
||||
{"Motorola second byte", ByteOrder::Motorola, 15U, 16U, ValueType::Unsigned, {0xFF, 0x12, 0x34}, true, 0x1234, 1.0, 0.0, 4660.0},
|
||||
{"Motorola signed scaled", ByteOrder::Motorola, 7U, 16U, ValueType::Signed, {0xFF, 0xFE}, true, -2, 0.5, 10.0, 9.0},
|
||||
{"Motorola 64 bits", ByteOrder::Motorola, 7U, 64U, ValueType::Unsigned, {0, 0, 0, 0, 0, 0, 0x12, 0x34}, true, 0x1234, 1.0, 0.0, 4660.0},
|
||||
{"Motorola 64 bits high bit", ByteOrder::Motorola, 7U, 64U, ValueType::Unsigned, {0x40, 0, 0, 0, 0, 0, 0, 0}, true, 0x4000000000000000LL, 1.0, 0.0, 4611686018427387904.0},
|
||||
{"Motorola short payload", ByteOrder::Motorola, 7U, 16U, ValueType::Unsigned, {0x12}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola empty payload", ByteOrder::Motorola, 7U, 8U, ValueType::Unsigned, {}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola large start", ByteOrder::Motorola, std::numeric_limits<std::uint32_t>::max(), 8U, ValueType::Unsigned, {0xFF}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola zero length", ByteOrder::Motorola, 7U, 0U, ValueType::Unsigned, {0xFF}, false, 0, 1.0, 0.0, 0.0},
|
||||
{"Motorola excessive length", ByteOrder::Motorola, 7U, 65U, ValueType::Unsigned,
|
||||
std::vector<std::uint8_t>(9U, 0xFF), false, 0, 1.0, 0.0, 0.0},
|
||||
{"Intel regression", ByteOrder::Intel, 0U, 16U, ValueType::Unsigned, {0x12, 0x34}, true, 0x3412, 1.0, 0.0, 13330.0},
|
||||
{"Intel signed regression", ByteOrder::Intel, 0U, 16U, ValueType::Signed, {0xFE, 0xFF}, true, -2, 0.5, 10.0, 9.0},
|
||||
{"Intel short payload", ByteOrder::Intel, 0U, 16U, ValueType::Unsigned, {0x12}, false, 0, 1.0, 0.0, 0.0}};
|
||||
|
||||
int failures = 0;
|
||||
for (const DecodeCase &test : cases) {
|
||||
DecodeSignal signal;
|
||||
signal.name = test.name;
|
||||
signal.byteOrder = test.byteOrder;
|
||||
signal.startBit = test.startBit;
|
||||
signal.length = test.length;
|
||||
signal.valueType = test.valueType;
|
||||
signal.factor = test.factor;
|
||||
signal.offset = test.offset;
|
||||
|
||||
DecodeFrame definition;
|
||||
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);
|
||||
|
||||
RawCanFrame frame;
|
||||
frame.canId = definition.canId;
|
||||
frame.data = test.data;
|
||||
const DecodedFrameValue result = DbcDecoder().Decode (database, frame);
|
||||
const bool passed = result.valid &&
|
||||
(result.definition == &database.frames[0]) &&
|
||||
(result.signals.size() == 1U) &&
|
||||
(result.signals[0].definition == &database.frames[0].signals[0]) &&
|
||||
(result.signals[0].valid == test.valid) &&
|
||||
(!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;
|
||||
int failures = 0;
|
||||
for (const DecodeCase &test: cases) {
|
||||
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);
|
||||
signal.name = test.name;
|
||||
signal.byteOrder = test.byteOrder;
|
||||
signal.startBit = test.startBit;
|
||||
signal.length = test.length;
|
||||
signal.valueType = test.valueType;
|
||||
signal.factor = test.factor;
|
||||
signal.offset = test.offset;
|
||||
|
||||
DecodeFrame definition;
|
||||
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);
|
||||
|
||||
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));
|
||||
frame.canId = definition.canId;
|
||||
frame.data = test.data;
|
||||
const DecodedFrameValue result = DbcDecoder().Decode(database, frame);
|
||||
const bool passed = result.valid &&
|
||||
(result.definition == &database.frames[0]) &&
|
||||
(result.signals.size() == 1U) &&
|
||||
(result.signals[0].definition == &database.frames[0].signals[0]) &&
|
||||
(result.signals[0].valid == test.valid) &&
|
||||
(!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;
|
||||
}
|
||||
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]) + boundaryCases << " decoder cases passed.\n";
|
||||
return 0;
|
||||
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]) + boundaryCases << " decoder cases passed.\n";
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user