QtTest regression tests
For instrumented builds, LCOV HTML reports, and Qt Creator coverage configuration,
see Measuring code coverage.
For the complete IDE build/run configuration set, see
Configure all build variants in Qt Creator.
The Coverage configuration uses coverage_report.sh after its instrumented
build; the script takes the source and build directories as its two arguments.
Open the repository's root dbc.pro in Qt Creator. It contains core (a static
C++17 library) and tests (the dbc_tests QtTest executable). Core is built first;
tests link its archive rather than compiling its implementation again.
Qt Core and Qt Test development packages are required for tests only.
The optional model tests also link QtGui, which is provided by Qt base development
packages. The adapter library itself still links only QtCore.
Build from the repository root with the installed Qt 6.8.2:
mkdir build
cd build
qmake6 ../dbc.pro
make -j
make check
Or run ./tests/dbc_tests directly. Parser, decoder, pipeline, lifetime, validation, and additional coverage
suites run, and the executable returns nonzero when any suite fails. Decoder cases appear as
individual QtTest data rows; parser checks are grouped into named test slots.
Checks also run in release builds.
To build tests separately against an existing core build:
mkdir /tmp/dbc-tests-build
cd /tmp/dbc-tests-build
qmake6 /absolute/path/to/dbc/tests/tests.pro \
DBC_CORE_BUILD_DIR=/absolute/path/to/build/core
make
make check
parser_tests.pri includes dbc_parser_test.cpp and dbc_statement_test.cpp;
decoder_tests.pri includes the decoder test source;
tests.pro also includes dbc_coverage_test.cpp, dbc_lifetime_test.cpp,
dbc_validation_test.cpp, and dbc_pipeline_test.cpp.
../core/core.pri supplies the library include path and linkage.
Local regression checks
run_core_ci.sh builds the core archive, runs all seven QtTest suites and the
qmake tree target with make check, then compiles and runs the standalone C++17
tree/builder test without Qt. A failed command returns a nonzero status. The
sanitize mode applies ASan/UBSan flags to core, tests, and the standalone
executable, with leak detection enabled by default and sanitizer errors fatal.
The optional adapter is not built. No automatic CI workflow is configured.
From the repository root, with Qt 6.8.2 available:
bash tests/run_core_ci.sh release
bash tests/run_core_ci.sh sanitize
Build directories default to build-ci/release and build-ci/sanitize; an
optional second argument selects another directory. Always use separate build
directories for the two modes. QMAKE, CXX, and JOBS override the qmake
executable, standalone compiler, and build parallelism (default 4). Generate the
locale as described below and set LOCPATH locally to run without locale skips.
On hosts where LeakSanitizer cannot work under a tracer, run with
ASAN_OPTIONS=detect_leaks=0:halt_on_error=1; this disables local leak checking
only. Test output is written to the terminal.
Validation of this script used clean builds in /tmp/dbc-ci-release
and /tmp/dbc-ci-sanitize with Qt 6.8.2 and the generated German locale. Each
mode passed 2,397 QtTest checks with no failures or skips, the qmake tree test,
and the standalone tree test. The sanitizer run used detect_leaks=0 because
an explicit leak-enabled run failed with LeakSanitizer's ptrace restriction.
Shell syntax, invalid-mode handling, and nonzero propagation of a failed qmake
command were also checked.
Decoder coverage
Coverage includes Motorola bit numbering within and across bytes, unaligned
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; frame status reports unknown frames, short payloads, and signal errors.
Tests exercise empty/short/exact/long payloads, ignored trailing bytes, signals
outside declared DLC, invalid enum metadata and overflowing start bits rejected
at construction, and preservation of successful signals on partial payloads.
Physical conversion checks cover NaN/Inf parameters rejected at construction,
multiplication/addition overflow, finite limits, signed/unsigned raw retention,
and raw selector activation after physical conversion failure.
Parser coverage
Structured diagnostic tests cover severity, code, supplied path, and physical
line numbers for skipped syntax and immediate/deferred errors; warnings preceding
an error are retained, and failed parses return an empty database. Common headers
and namespace symbol lists stay quiet. Tests also check file-open errors, fresh
parse sessions, and compatibility with the legacy throwing API.
The diagnostic audit also covers 11 unsupported-statement variants, all namespace
termination forms, CRLF and missing final newlines, relative paths with spaces,
first-error stopping, deferred diagnostic ordering, duplicate definitions/values,
selector ranges, overlaps, and preservation of supported decoding and metadata.
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.
Signal tests cover complete syntax and numeric validation, scientific notation,
finite physical parameters and ordered ranges, spaces and tabs, receiver lists,
invalid 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:
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,
raw lookup with scaling, unknown/invalid values, and both database builders.
Temporary DBC fixtures are created in the system temporary directory and removed
automatically.
Dispatch tests also verify exact keyword matching, handler construction and reuse, unknown statements, and independent parsing sessions, including recovery after errors.
Tree and optional model tests
tree_node_test.cpp is a standalone C++17 executable without Qt; see the root
README for its compiler command. It is also built as dbc_tree_tests and run by
qmake's make check, without Qt linkage. It checks empty trees, parent/child
round trips, sibling positions, const/mutable bounds, null children, vector growth,
and unique_ptr transfer. Compile-time checks reject node copying and movement.
Self/ancestor insertion must throw without consuming ownership or changing links.
Key tests cover frame/signal identity, standard/extended separation, repeated
signal names across frames, missing keys, source replacement, and row-independent
identity.
Enable CONFIG+=dbc_qt in the root qmake invocation to build dbc_qt and
dbc_model_tests alongside existing tests. Qt 6.8.2 is required.
make check runs all suites. Model tests parse a temporary DBC fixture and use
QAbstractItemModelTester, verify navigation across columns, invalid/foreign
indexes, metadata and exact VAL_ integers, and persistent-index invalidation
when reloading or clearing the tree. Their QGuiApplication registers graphical
metatypes used by QAbstractItemModelTester, avoiding the invalid QPixmap type
warning in Qt 6.8.2. The test executable defaults to QT_QPA_PLATFORM=offscreen
when the variable is unset or empty, so no display server is needed. An explicit
platform setting is preserved.
Basic multiplexing coverage includes selector declarations after branches, Intel/Motorola branch overlap, signed active values and VAL_ lookup, unconditional signals, inactive branches, missing selector/branch payloads, exact UINT64_MAX selector matching, malformed runtime selectors, source locations, and rejection of invalid markers, selector references/ranges, and overlaps.
Extended and nested multiplexing coverage includes deferred SG_MUL_VAL_
references, inclusive and separated ranges, repeated range statements, explicit
range precedence over markers, mNM fallback, independent selectors, nested
siblings sharing Intel/Motorola payload bits, raw selection with scaling, and
64-bit boundaries. Tests verify metadata through tree/runtime builders, selective
decoding with ancestor dependencies, inactive paths with missing bytes, missing
selectors versus leaf payload, malformed ranges, unknown targets, cycles,
conflicting parents, and invalid manually constructed runtime graphs.
The extended multiplexing change was verified with the root qmake build,
make -j4, make check (2,398 passed, no failures, one existing named C-locale
check skipped because the locale is unavailable), and the standalone tree test.
Additional regression coverage
dbc_coverage_test.cpp runs as part of dbc_tests. It covers signed boundaries
below 64 bits, deterministic extraction comparisons for both byte orders across
lengths 1–64, frame lookup failures, exact decode statuses, construction rejection
of malformed runtime multiplexing, PGN boundaries, comment handling, file
formatting, metadata copying
and source lifetime, physical conversion, and TypeFactory registration/creation.
Direct resolver tests construct ambiguous databases through the public metadata
API, verify source locations, and check that ambiguous targets receive no values.
J1939 regressions in dbc_coverage_test.cpp verify explicit parser opt-in and
ordinary extended CAN defaults, PF 239/240 and all data-page combinations, PGN
zero, PDU1 destination exclusion, PDU2 group-extension matching, changed source
and priority, standard/invalid-ID exclusion, and inconsistent manual metadata.
They also cover exact-ID precedence, order-independent ambiguous PGNs for both
PDU formats, mixed ordinary/J1939 definitions, selected-signal definition keys,
raw/physical values, and owning PGN handles across snapshot replacement.
The pipeline fixture explicitly enables J1939 through the diagnostic parser API.
Verified in build/ with qmake6 ../dbc.pro, make -j4, and make check:
all six QtTest suites and the Qt-free tree target passed. The existing named
comma-decimal C locale regression skipped because that locale is not installed.
All QtTest targets use Qt 6.8.2 and QVERIFY_THROWS_EXCEPTION. Exception tests
explicitly discard nodiscard results when only the exception is being checked.
The standalone tree test requires only a C++17 compiler.
Definition lifetime and reload coverage
dbc_lifetime_test.cpp checks retained definitions and value-description strings
across reload, clear, and destruction; independently saved signal results;
copied/moved results and database copies; owning lookup handles; and release of
the old snapshot after its final owner is removed. Compile-time checks enforce
const access to runtime metadata. Reload fixtures change ordering, frame names,
scaling, units, and descriptions, remove definitions, and rename signals.
Key tests check equality and hashing, standard/extended separation, the same signal name in different frames, and missing lookups. Constructor tests reject duplicate runtime keys, including manually supplied parsed metadata. Failed reload leaves the active database intact; empty reload clears it. Invalid/unknown results and insufficient payloads retain their documented ownership and status behavior. Inactive branches and unavailable selectors also retain definitions across reload.
Database validation coverage
dbc_validation_test.cpp checks direct construction and manually assembled
DbcDatabase input to DbcDecodeBuilder: standard/extended CAN ID limits,
encoded/reserved ID bits, duplicate keys, lengths 0/1–64/65/UINT32_MAX,
Intel/Motorola payload boundaries and overflowing start bits, invalid enums,
NaN and both infinities in every numeric parameter, and reversed physical ranges.
Selector tests include missing, duplicate, and signed selectors, branch ranges,
UINT64_MAX selection, mixed-order overlaps, and exclusive branches sharing bits.
Valid definitions cover the full byte-count storage range, including zero-byte
frames without signals and 255-byte frames. Existing extraction tests cover
lengths 1–64. Snapshot tests mutate retained frame, signal, and description aliases
after rvalue construction, and verify unchanged lookups and metadata. Failed
constructor/builder replacement preserves the active snapshot; clear removes its
index while saved handles remain alive.
Layout validation is also compared with independent DBC bit traversal for every start position through one byte beyond payload sizes 0, 1, 8, 64, and 255, and all lengths 1–64, for both byte orders. Zero/65-bit lengths and uint32 maximum inputs are rejected. Builder snapshots survive input mutation and destruction; failed replacement with duplicate frame or signal keys preserves the existing frame and signal lookups.
End-to-end pipeline coverage
dbc_pipeline_test.cpp parses temporary DBC files and checks independent expected
metadata against the parser, runtime builder, and tree builder. It exercises
standard and extended frames with the same numeric ID and signal name, Intel
and signed Motorola decoding, scaling, raw value descriptions, basic and extended multiplexing,
PGN metadata, receivers, units, ranges, and frame/signal comments. Tree checks
include node types, payloads, parents, rows, names, and child counts.
Empty and headers-only fixtures produce an empty runtime database and a valid empty tree root. Replacement fixtures change definitions, metadata and decoded values, remove old lookup keys, and then clear both outputs through an empty fixture. Saved decoded results and trees retain their original metadata.
Attribute coverage
multilineAttributes checks multiline definitions, defaults and assignments,
deferred cycle times, frame format overrides, quoted newlines/semicolons and
escapes, CRLF input, and warning locations for defaults and explicit values.
invalidMultilineAttributes checks malformed ENUM lists/ranges, missing
terminators, unterminated strings, undefined names, trailing fields, and error
locations at the first physical line through both parser APIs.
The multiline changes passed a clean qmake build and make check in
/tmp/dbc-attributes-build with Qt 6.8.2: 2,396 QtTest cases and the qmake
tree target passed. The standalone C++17 tree test also passed. One existing
C locale test skipped because no named comma-decimal locale is installed.
Parser slots attributes, invalidAttributes, and attributeWarnings cover
all five scopes and types, deferred definitions/defaults/targets, explicit
values overriding defaults, repeated assignments, escaped strings, typed
range/scope errors, duplicate definitions/defaults, unknown attributes and
missing targets. They check source diagnostics and the throwing API, distinct
standard/extended targets, frame cycle times and enum labels, unsupported
formats and ID conflicts, unchanged J1939 opt-in, and runtime/tree propagation.
Existing unsupported-statement checks now use relation forms, which remain
unsupported, instead of supported attribute forms.
Attribute changes were verified with qmake6 ../dbc.pro, make -j4, and
make check in build/: all six QtTest suites and the qmake tree target
passed. The standalone C++17 tree test also passed. The existing named
comma-decimal C locale test skipped because the locale is not installed.
Long value descriptions and multiplex ranges
dbc_statement_test.cpp adds a separate StatementParserTest suite to the
existing parser qmake source list and the main test runner. Both parser APIs are
checked with 50,000-character descriptions (including quotes, backslashes,
semicolons, and spaces), 10,000 VAL_ pairs, 10,000 multiplex ranges, and long
numeric bounds and whitespace. Valid metadata must survive parsing without
truncation, support value-description lookup after decoding, and activate or
skip multiplex branches correctly. Statements may precede or follow definitions.
Malformed long statements cover incomplete quotes/escapes, invalid escapes, missing separators and semicolons, duplicate keys, numeric overflow, empty and reversed ranges, trailing text, and unresolved long names. The diagnostic API must return an empty database with the correct category, path, and source line; the throwing API must report that same location.
Verified with Qt 6.8.2 in separate Release and ASan/UBSan builds with
CONFIG+=dbc_qt: each passed 2,449 core QtTest checks (including 29 checks in the
new suite), seven model checks, and the qmake tree test. One named-locale case
skipped because the locale is unavailable. Sanitizer errors were fatal; local
leak checking used detect_leaks=0 because of the documented ptrace restriction.
Unsupported signal value types
unsupportedSignalValueTypes verifies that both parser APIs reject SIG_VALTYPE_
declarations with UnsupportedSignalType, the original file path and physical
line, and an empty database. Cases include float32/float64, declarations before
signal definitions, extended IDs, tabs/CRLF, no final newline, type 0, unknown
types, and malformed declarations. Prior warnings are retained; SIG_VALTYPE_
symbols inside NS_ lists remain quiet.
The pipeline suite checks the IEEE 754 bytes for float32 and float64 1.0.
Adding a type declaration must prevent publication of an integer definition,
so building from the error result cannot produce a valid decoded signal. The
same payloads still decode to exact integers when defined only by supported
SG_ statements. New cases are included in the existing qmake targets.
Verified with Qt 6.8.2 in separate Release and ASan/UBSan builds with
CONFIG+=dbc_qt: each passed 2,420 core QtTest checks, seven model checks, and
the qmake tree test. One named-locale case skipped because its locale is
unavailable. ASan/UBSan used fatal errors and detect_leaks=0 because of the
previously documented ptrace restriction. The separately built demo was checked
with float32 and float64 declarations (exit 2, source-located error, no decode
output), a supported integer definition (exit 0), and an unknown extension
(exit 0 with a visible warning).
Long signal definitions
longSignalDefinitions reproduces the former stack overflow with a 50,000-character
unit string. Both parser APIs are exercised with long units, signal names,
receivers, decimal numbers, and a list of 10,001 receivers. Valid input must parse
without truncating units; malformed input (including missing quotes, delimiters,
receiver separators, numeric suffixes, overflow, and trailing receiver commas)
must return an empty database and an InvalidStatement diagnostic at the signal's
source line, or throw a source-located error through ParseFile().
These cases run as part of the existing parser target and sanitizer builds.
Verified with Qt 6.8.2 in separate Release and ASan/UBSan builds, both with
CONFIG+=dbc_qt: make check passed 2,409 core QtTest checks, seven model checks,
and the qmake tree test in each build. The named comma-decimal C locale test
skipped because the required locale is not installed. The sanitizer run used
ASAN_OPTIONS=detect_leaks=0:halt_on_error=1 and UBSAN_OPTIONS=halt_on_error=1;
address and undefined-behavior checks passed, while leak checking was disabled
because of the environment's previously documented ptrace restriction.
Extended validation
attributeNumbers checks signed 64-bit limits, leading plus signs, decimal HEX
values, FLOAT fractions/exponents, and default overrides under a comma-decimal
C++ locale. Node/environment defaults remain on definitions without becoming
database attributes. invalidAttributeNumbers supplies 39 data rows, each checked
in both definition bounds, a default, and an explicit assignment. The throwing
and diagnostic APIs must reject malformed signs, trailing text, hexadecimal
notation, non-finite values, overflow, and underflow with the correct error line.
Additional malformed-attribute cases cover token separators, scope/type names,
reversed FLOAT bounds, value types/ranges, and invalid CAN references.
Run AddressSanitizer and UndefinedBehaviorSanitizer in a separate directory:
mkdir -p build-sanitize
cd build-sanitize
qmake6 ../dbc.pro CONFIG+=dbc_qt CONFIG+=debug CONFIG-=release \
'QMAKE_CXXFLAGS+=-fsanitize=address,undefined -fno-omit-frame-pointer' \
'QMAKE_LFLAGS+=-fsanitize=address,undefined'
make -j4
ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=halt_on_error=1 \
QT_FATAL_WARNINGS=1 LOCPATH=/tmp/dbc-test-locales make check
Generate the optional German locale as described above before setting LOCPATH.
LeakSanitizer cannot run under this environment's tracer: detect_leaks=1
completes the core QtTest suites but fails during leak checking with the message
that LeakSanitizer does not work under ptrace. Disabling leak checking retains
AddressSanitizer and UndefinedBehaviorSanitizer checks; it does not verify leaks.