6.3 KiB
test_regress/ -- regression tests
Covers .v/.sv sources, .py drivers, and .out golden files under
test_regress/. Read the repository-root AGENTS.md first. This
file has two parts: Orientation explains how the harness runs a test;
Before you open a PR is the test-authoring checklist.
Orientation: how the harness works
- A test is a
.v/.svsource plus a matching.pydriver int/. The driver callstest.compile(),test.execute(), and/ortest.lint(). Without a.pythe source never runs and is dead code giving false coverage confidence. - Golden output lives in
.outfiles, compared viaexpect_filename. Generate them withHARNESS_UPDATE_GOLDEN=1 python3 t/<name>.py-- never hand-write them; the harness normalizes paths, version markers, and line numbers that hand edits get wrong. - Run one test from the repository root:
test_regress/t/t_<name>.py. When running from a checkout, setVERILATOR_ROOTto the checkout root first so the harness compiles the generated C++ against the right headers. test.compile()defaults are richer than they look: the vlt driver auto-injects--exeand a generated main, andassert propertyfires its action blocks without--assert-- try the simple form before adding flags.- The
t_dist_*tests enforce repository conventions (file headers, sorted lists, warning documentation, ASCII-only) -- run the relevant ones before submitting.
Before you open a PR
Naming
- Name tests
t_{category}_{description}in snake_case; the first word groups the category (t_lint_unused_func_bad, nott_unused_func_lint_bad) so related tests are findable and runnable together. - Use
_badwhen the code is illegal SystemVerilog,_unsupwhen it is legal but unsupported,_offfor disabled-behavior tests -- never_fail. - Keep filenames under roughly 30-35 characters.
Files and drivers
- Every
.vneeds a matching.pydriver that actually callstest.compile()andtest.execute()(ortest.lint()for static-analysis-only tests) -- a driver that sets up but never runs hides coverage gaps silently. - Copy the license header from an existing file:
.vtests carry the CC0 notice,.pydrivers carry the standard driver header -- distribution tests check headers on every committed file. - Use
--binaryinstead of--exe --main --timing-- it implies the others. - Error tests use
test.compile(fails=True, expect_filename=test.golden_filename)(ortest.lint(...)) and must not calltest.execute(). - Use
.outgolden files withexpect_filenameinstead of inlineexpectregex strings -- goldens are diffable and maintainable. - Use
test.glob_one()/test.glob_some()andtest.timeout()instead of rawglob.glob()and manualtime.time()measurements. - Coverage tests run
verilator_coverageand verify individual bins and points, not just aggregate percentages. - Assert optimization stats with exact expected counts:
test.file_grep(test.stats, r'Optimizations, ...\s+(\d+)', N). - Add a
_protect_idsvariant when a feature emits user identifiers or filenames; use conservative thread counts (2 or fewer) in multithreaded tests. - Extend existing test files with related cases instead of creating many
single-purpose files; keep drivers minimal -- test logic belongs in the
.v.
Golden .out files
- Never hand-write or hand-edit
.outgoldens -- regenerate withHARNESS_UPDATE_GOLDEN=1. - When a feature lands, remove its now-supported entries from
t_*_unsup.v/t_*_bad.vin the same change and regenerate the goldens -- stale entries no longer error and reviewers will flag them.
Verilog style
-
2-space indentation, no tabs.
-
Declarations are flush-left with a single space between type and name; never column-align:
// WRONG: column-aligned bit [63:0] crc = 64'h5aef0c8d_d70a4497; int cyc = 0; // RIGHT: flush-left bit [63:0] crc = 64'h5aef0c8d_d70a4497; int cyc = 0; -
Run
nodist/verilog_formaton new.vfiles; wrap macro definitions in// verilog_format: off/onso the formatter does not split them. -
Use
$display("%0d", ...)not%d-- avoids leading-space padding. -
Wrap Verilator-specific test code (e.g.
$c) in`ifdef VERILATOR. -
Use inline
// verilator lint_off WARNCODEonly when that warning is itself under test -- fix root causes otherwise. -
Use only IEEE 1800-compliant constructs other simulators also accept -- tests validate standard behavior, not Verilator's parser leniency.
-
Omit optional end labels on
endmodule/endclass/endtask/endfunction.
Self-checking
- Use the
checkh/checkd/checksassertion macros, not manualif/$display/$stopsequences. Notecheckhprints with%p, which renders integers as hex -- usecheckdfor integer comparisons. - Use the
`stopmacro rather than direct$stop. - Drive logic with runtime-varying inputs (counters, CRC/LFSR registers) so constant folding cannot pre-evaluate the logic under test; check behavior across multiple clock cycles, not just initial values.
- For a test whose pass/fail depends on varying or random values, loop enough iterations that the values demonstrably differ and size the value space so a failure is probable per run, then confirm the test fails on an un-fixed tree before submitting.
Test design
- Use non-power-of-2, non-word-aligned widths (7, 15, 31, 33, 63, 65, 95) -- exposes masking and word-boundary bugs that 32/64/128 hide.
- Test both
[high:low]and[low:high]orderings plus non-zero bounds like[3:1]; use different ranges for each axis of multidimensional arrays. - When adding type support, test all basic types (chandle, string, real) and typedef-wrapped variants.
- Include the issue's own reproducer as a committed test, and verify it fails without the fix.
- Assert non-blocking-assignment results in the cycle immediately after they take effect, before later overwrites, using indices that change post-NBA.