Testing¶
The test suite lives under src/test/java/ru/icc/regtab/ and is split into two complementary
parts that exercise the same benchmark tasks through both pattern
representations: the ATP fluent API and the RTL DSL.
ATP benchmark tests¶
The primary benchmark tests are in the atp package. Each class AtpTask{NN}Test implements one
task as an ATP pattern using the formal ru.icc.regtab.atp.spec API:
src/test/java/ru/icc/regtab/atp/
AtpTaskBase.java # parameterised base: loads CSV, runs matcher, asserts output
AtpTask001Test.java # Foofah benchmark tasks 001–050
AtpTask002Test.java
...
AtpTask050Test.java
AtpTask051Test.java # RegTab benchmark tasks 051–110
...
AtpTask110Test.java
AtpTask111Test.java # Baikal benchmark tasks 111–150
...
AtpTask150Test.java
Each test class overrides two methods:
taskId()— returns the three-digit task number (e.g."001")buildPattern()— constructs and returns theTablePatternfor that task
AtpTaskBase runs five JUnit parameterized test variants (@ValueSource(ints = {1,2,3,4,5})),
one per source table. For each variant it:
- Loads
src/test/resources/tasks/task_{NN}/input_{V}.csvinto aTableSyntax - Calls
AtpMatcher.match(pattern, syntax)to populate the semantic layer - Interprets the enriched
InterpretableTablewithTableInterpreter - Applies optional post-processing (e.g.
WhitespaceNormalization) - Asserts the result against
src/test/resources/tasks/task_{NN}/expected_{V}.csv
Example — Task 001 (subtables with a rec action using the sameSubtable predicate):
import ru.icc.regtab.atp.spec.*;
@Override
protected TablePattern buildPattern() {
var sameSubtable = ItemFilterConditionSpec.sameSubtable();
return TablePattern.of(
SubtablePattern.of(Quantifier.oneOrMore(),
RowPattern.of(
CellPattern.of(AtomicContentSpec.val(
ActionSpec.rec(ProviderSpec.val(ProviderSpec.UNBOUNDED, sameSubtable))
)),
CellPattern.of(Quantifier.exactly(2), AtomicContentSpec.val()),
CellPattern.skip(Quantifier.oneOrMore())
),
RowPattern.of(
CellPattern.skip(),
CellPattern.of(Quantifier.exactly(4), AtomicContentSpec.val()),
CellPattern.skip(Quantifier.oneOrMore())
)
)
);
}
RTL benchmark tests¶
The rtl package mirrors the ATP benchmark: each RtlTask{NN}Test implements the same task as a
compact RTL string. These tests verify that the RTL compiler produces an ATP pattern equivalent
to the hand-crafted ATP counterpart.
src/test/java/ru/icc/regtab/rtl/
RtlTaskBase.java # loads CSV, compiles RTL → ATP, runs matcher, asserts output
RtlTask001Test.java # Foofah benchmark tasks 001–050
...
RtlTask110Test.java # RegTab benchmark tasks 051–110
RtlTask111Test.java # Baikal benchmark tasks 111–150
...
RtlTask150Test.java
Each test class overrides two methods:
taskId()— returns the three-digit task number (e.g."001")buildRtl()— returns the RTL string for that task
Example — Task 01:
@Override
protected String buildRtl() {
return """
{ [ [VAL : ST*->REC] [VAL]{2} []+ ]
[ [] [VAL]{4} []+ ] }+
""";
}
Fixture data¶
Source and expected tables are stored as CSV files (UTF-8 without BOM):
src/test/resources/tasks/
task_001/
input_1.csv … input_5.csv
expected_1.csv … expected_5.csv
task_002/
...
task_150/
...
When a pattern produces named schema attributes (via AVP actions), the expected_{V}.csv
files carry a header row; this is declared per task in
src/test/resources/tasks/task_match_options.json.
Running the tests¶
Run the entire test suite with Maven:
To run only the ATP benchmark tests:
To run only the RTL benchmark tests:
To run a single task (ATP and RTL counterparts):
The illustrative example from the paper has its own pair of tests:
RTL conformance corpus¶
The directory conformance/ at the repository root is the normative test corpus of the
RTL language (see conformance/README.md for the full contract). It contains:
positive/<id>.rtl+<id>.expected.rtl— every task's RTL string paired with its canonical formserialize(compile(rtl)); any RTL implementation must reproduce the canonical form byte-for-byte, and the canonical form must be a fixed point;negative/*.rtl— inputs that must be rejected with a compile error, one per error category (lexer, parser, fragments,EXTbindings, settings, conflicting inline params).
Two test classes execute the contract in this repository:
RtlConformanceTest checks the contract itself; ConformanceCorpusFreshnessTest
regenerates the positive corpus in memory from the task tests and fails if the committed
files are stale (fix: rerun ConformanceCorpusGenerator, commit the diff).
Both jobs run in CI (.github/workflows/ci.yml): test runs the full suite, the fast
conformance job gives downstream RTL implementations (pyRegTab) a named status to pin.