Skip to content

Factor out comparison-based oracle reproducers to share common base - #1351

Merged
mrigger merged 2 commits into
mainfrom
refactor/reproducer
Jul 30, 2026
Merged

Factor out comparison-based oracle reproducers to share common base#1351
mrigger merged 2 commits into
mainfrom
refactor/reproducer

Conversation

@tlmorgan24

Copy link
Copy Markdown
Collaborator

Summary

The EET, TLP-WHERE and NoREC oracles all detect a bug the same way. Each evaluates two things that should agree and compares them. When they disagree (or when one triggers an unexpected database error), the oracle produces a Reproducer that re-runs the comparison against the reduced database during test case reduction.

The three Reproducer implementations had shared logic. Each decided whether a reduced database still shows the bug, took care to distinguish the original failure from an unrelated error introduced by the reduction itself, and formatted the failing queries into the reduced test case. This PR moves that shared logic into a new abstract class and rewrites the three reproducers on top of it. There is no change in behaviour.

Changes

New base class (common/oracle/AbstractComparisonReproducer.java)

Holds the bugStillTriggers control flow and the getBugInformation formatting that the three oracles previously duplicated. This covers re-evaluating both sides, treating an unexpected error as a reproduction only when it is the same error the original failure reported, and writing the header that introduces the failing queries.

A subclass supplies only the parts that differ between oracles. This includes how each side is evaluated against the database, how the two sides are compared, and how the failing queries are written out.

common/oracle/EETOracle.java

EETReproducer now extends the base class. A side is evaluated by reading the first column of a query's result set, and the two are compared with assumeResultSetsAreEqual.

common/oracle/TLPWhereOracle.java

TLPWhereReproducer now extends the base class. The original side is a plain result set and the transformed side is the combined result of the three partition queries. Because the comparison also needs the human-readable combined query strings that getCombinedResultSet fills in, a small value class carries them alongside the result set for the transformed side.

common/oracle/NoRECOracle.java

NoRECReproducer now extends the base class. The two sides are integer row counts compared for inequality, keeping the existing guard that treats a failed count (-1) on either side as no reproduction.

@tlmorgan24
tlmorgan24 requested a review from mrigger July 30, 2026 07:07
@mrigger

mrigger commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

I think this PR already improves on the current state, but I'm now wondering whether we can further improve it: conceptually, the individual logic bug test oracles are different from the unexpected error oracle. Thus, rather than instantiating specific reproducers for the logic bug oracles, can we have a separate UnexpectedErrorReproducer instead? Like this, the individual classes have a simpler logic and include only those fields that are absolutely necessary.

@tlmorgan24

tlmorgan24 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

Indeed, the above refactor ended up mainly factoring out the logic-bug aspect, but the unexpected-error aspect can be factored out better and would be applicable to essentially all oracles.

I have added a new commit. The unexpected-error reproduction now has its own class, and any oracle can implement it simply with a functional interface.

There are still specific reproducers for the logic bug oracles, but now these only contain the logic that's necessary for the logic-bug reproduction. I kept the AbstractComparisonReproducer as a base for them (many oracles involve comparing two executions), but it is now trimmed down as it does not have to think about unexpected errors at all. I wonder whether AbstractComparisonReproducer is an excessive abstraction though, please let me know if I should refactor back down to independent logic-bug reproducers for each oracle (given that we now at least have the common unexpected-error reproducer).

@mrigger mrigger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks!

@mrigger
mrigger merged commit 535eab9 into main Jul 30, 2026
23 of 25 checks passed
@mrigger
mrigger deleted the refactor/reproducer branch July 30, 2026 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants