Closes #19
This commit is contained in:
1 parent
d87c100398
commit
4ae4e527b8
5 files changed
+138
-10
No files matched your search
@@ -86,6 +86,22 @@ extended frames may share a numeric ID, and separate frames may reuse signal nam
|
||||
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.
|
||||
Physical-number tests apply a custom comma-decimal C++ locale and an available
|
||||
named comma-decimal C numeric locale. They check all four physical fields,
|
||||
leading signs, fractions, scientific notation, finite boundaries, zero, malformed
|
||||
numbers, comma/grouped numbers, overflow/underflow, and reversed ranges. Locale
|
||||
changes are restored after each test. The named C locale case skips if none of
|
||||
the supported locale names are installed; the custom C++ locale case always runs.
|
||||
On Linux with locale sources and `localedef`, run both cases without installing a
|
||||
system locale:
|
||||
|
||||
```sh
|
||||
mkdir -p /tmp/dbc-test-locales
|
||||
localedef --no-archive -i de_DE -f UTF-8 /tmp/dbc-test-locales/de_DE.UTF-8
|
||||
LOCPATH=/tmp/dbc-test-locales make check
|
||||
```
|
||||
|
||||
Run `make check` from the build directory as usual.
|
||||
Value-description tests cover full `VAL_` syntax, whitespace, escaped quotes,
|
||||
empty text, exact integer boundaries, duplicate keys within and across statements,
|
||||
deferred and normalized frame references, missing targets, error locations,
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include "dbc_parser.h"
|
||||
#include "dbc_statement_handler.h"
|
||||
#include "dbc_tree_builder.h"
|
||||
#include <clocale>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
|
||||
#include <QtTest>
|
||||
#include <chrono>
|
||||
@@ -28,6 +30,27 @@ struct Fixture {
|
||||
}
|
||||
};
|
||||
|
||||
class CommaDecimalPunctuation : public std::numpunct<char> {
|
||||
protected:
|
||||
char do_decimal_point() const override { return ','; }
|
||||
char do_thousands_sep() const override { return '.'; }
|
||||
std::string do_grouping() const override { return "\3"; }
|
||||
};
|
||||
|
||||
class ApplicationLocaleGuard {
|
||||
public:
|
||||
ApplicationLocaleGuard()
|
||||
: previousCppLocale(std::locale()), previousCLocale(std::setlocale(LC_ALL, nullptr)) {}
|
||||
~ApplicationLocaleGuard() {
|
||||
std::locale::global(previousCppLocale);
|
||||
std::setlocale(LC_ALL, previousCLocale.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
std::locale previousCppLocale;
|
||||
std::string previousCLocale;
|
||||
};
|
||||
|
||||
class CountingHandler : public DbcStatementHandler {
|
||||
public:
|
||||
inline static int instances = 0;
|
||||
@@ -50,6 +73,7 @@ std::string SignalLine(const std::string &start, const std::string &length,
|
||||
class DbcParserTest : public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
void CheckPhysicalNumbers();
|
||||
void RejectSignal(const Fixture &fixture, const std::string &line, unsigned payload = 8U) {
|
||||
fixture.Write("BO_ 1 Frame: " + std::to_string(payload) + " ECU\n\n" + line + "\n");
|
||||
try {
|
||||
@@ -81,6 +105,8 @@ private Q_SLOTS:
|
||||
void integration();
|
||||
void invalidSignals();
|
||||
void validSignals();
|
||||
void physicalNumbersCppLocale();
|
||||
void physicalNumbersCLocale();
|
||||
void dispatch();
|
||||
void independentSessions();
|
||||
void valueDescriptions();
|
||||
@@ -824,6 +850,75 @@ void DbcParserTest::validSignals() {
|
||||
} catch (const std::exception &error) { CHECK(false, error.what()); }
|
||||
}
|
||||
|
||||
void DbcParserTest::CheckPhysicalNumbers() {
|
||||
Fixture fixture;
|
||||
struct PhysicalCase {
|
||||
const char *factor;
|
||||
const char *offset;
|
||||
const char *minimum;
|
||||
const char *maximum;
|
||||
double expectedFactor;
|
||||
double expectedOffset;
|
||||
double expectedMinimum;
|
||||
double expectedMaximum;
|
||||
};
|
||||
const PhysicalCase valid[] = {
|
||||
{"+1.25", "-0.5", "-2.75", "255.5", 1.25, -0.5, -2.75, 255.5},
|
||||
{"+.5e+1", "-2.5E-1", "-1.", "+2e2", 5.0, -0.25, -1.0, 200.0},
|
||||
{"0e-999", "+0.", "-.0", ".0e+999", 0.0, 0.0, 0.0, 0.0},
|
||||
{"1.7976931348623157e308", "2.2250738585072014e-308", "-1e308", "+1e308",
|
||||
std::numeric_limits<double>::max(), std::numeric_limits<double>::min(), -1e308, 1e308}};
|
||||
for (const PhysicalCase &test: valid) {
|
||||
fixture.Write("BO_ 1 Frame: 1 ECU\n" +
|
||||
SignalLine("0", "8", "1+", test.factor, test.offset, test.minimum, test.maximum) + "\n");
|
||||
const DbcParseResult result = DbcParser().ParseFileWithDiagnostics(fixture.path.string());
|
||||
QVERIFY(!result.HasErrors());
|
||||
QVERIFY(result.diagnostics.empty());
|
||||
QCOMPARE(result.database.frames.size(), std::size_t(1));
|
||||
const SignalInfo &signal = result.database.frames[0].signals[0];
|
||||
QCOMPARE(signal.factor, test.expectedFactor);
|
||||
QCOMPARE(signal.offset, test.expectedOffset);
|
||||
QCOMPARE(signal.minimum, test.expectedMinimum);
|
||||
QCOMPARE(signal.maximum, test.expectedMaximum);
|
||||
}
|
||||
|
||||
const char *invalid[] = {"1,5", "1.234,5", "1,234.5", "1junk", "nan", "inf", "-inf",
|
||||
"1e999", "1e-999", "1e-320", "-1e-320", "0x1p2", "1e", "1.2.3"};
|
||||
for (const char *value: invalid) {
|
||||
RejectSignal(fixture, SignalLine("0", "8", "1+", value, "0", "0", "255"));
|
||||
RejectSignal(fixture, SignalLine("0", "8", "1+", "1", value, "0", "255"));
|
||||
RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", value, "255"));
|
||||
RejectSignal(fixture, SignalLine("0", "8", "1+", "1", "0", "0", value));
|
||||
}
|
||||
RejectSignal(fixture, SignalLine("0", "8", "1+", "1.25", "0", "2.5", "1.5"));
|
||||
}
|
||||
|
||||
void DbcParserTest::physicalNumbersCppLocale() {
|
||||
const ApplicationLocaleGuard guard;
|
||||
std::locale::global(std::locale(std::locale::classic(), new CommaDecimalPunctuation));
|
||||
QCOMPARE(std::use_facet<std::numpunct<char>>(std::locale()).decimal_point(), ',');
|
||||
CheckPhysicalNumbers();
|
||||
QCOMPARE(std::use_facet<std::numpunct<char>>(std::locale()).decimal_point(), ',');
|
||||
}
|
||||
|
||||
void DbcParserTest::physicalNumbersCLocale() {
|
||||
const ApplicationLocaleGuard guard;
|
||||
bool found = false;
|
||||
const char *names[] = {"de_DE.UTF-8", "de_DE.utf8", "fr_FR.UTF-8", "fr_FR.utf8",
|
||||
"German_Germany.1252", "French_France.1252"};
|
||||
for (const char *name: names) {
|
||||
if (std::setlocale(LC_NUMERIC, name) && std::string(std::localeconv()->decimal_point) == ",") {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
QSKIP("No named comma-decimal C locale is installed; generate de_DE.UTF-8 and set LOCPATH.");
|
||||
QCOMPARE(std::string(std::localeconv()->decimal_point), std::string(","));
|
||||
CheckPhysicalNumbers();
|
||||
QCOMPARE(std::string(std::localeconv()->decimal_point), std::string(","));
|
||||
}
|
||||
|
||||
void DbcParserTest::dispatch() {
|
||||
CountingHandler::instances = 0;
|
||||
CountingHandler::calls = 0;
|
||||
|
||||
Reference in new issue
Block a user