Add khepri predicate conformance tests for rules-engine-internal#3574
Draft
ajpallares wants to merge 43 commits into
Draft
Add khepri predicate conformance tests for rules-engine-internal#3574ajpallares wants to merge 43 commits into
ajpallares wants to merge 43 commits into
Conversation
…e fixtures Adds per-operator JSON predicate fixtures (exact copies of the iOS #6885 corpus) under src/test/resources/predicate-fixtures, run by a shared parameterized runner. Deletes the migrated arithmetic/comparison/equality/ logic suites and trims the accessor/evaluator/string-array suites to the cases not expressible as predicate->boolean. Test-only change. Co-authored-by: Cursor <cursoragent@cursor.com>
Expresses the "empty-string key resolves to the whole scope and is not
missing" case as a `{"!!":{"missing":[""]}}` -> false fixture (the string
coercion the other missing fixtures use can't distinguish [] from [""]).
Removes the now-covered Kotlin test and bumps the fixture count to 237.
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds fixtures for the empty-segment dot-path splits, var default-vs-null-leaf behavior, and the non-numeric missing_some threshold (7 new cases), and drops the now-redundant Kotlin tests. AccessorOperatorsTest keeps only the cases that cannot be a predicate->boolean fixture (top-level array scope or a whole-object return). Fixture count is now 244. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Mirror the iOS rules-engine implementation: Kotlin some/all operators matching json-logic-js semantics, shared JSON predicate fixtures, and pinned fixture count bumped to 271. Co-authored-by: Cursor <cursoragent@cursor.com>
place operator docs on each op instead of duplicating at the type level; drop "not vacuous truth" wording Co-authored-by: Cursor <cursoragent@cursor.com>
…-logic-iteration-operators
Implement variadic min/max with JS Math.min/Math.max semantics: operands coerce via Number() (toNumberOrNull), empty input yields ±∞, and NaN operands poison the result. Wire into the operator dispatcher and add byte-identical min.json/max.json fixtures from purchases-ios, bumping the pinned fixture count to 305. Co-authored-by: Cursor <cursoragent@cursor.com>
Completes the json-logic-js iteration family on top of some/all.
none/map/filter rebind vars to the current item; reduce rebinds to
{current, accumulator}. Non-array sources: none -> true, map/filter
-> [], reduce -> seed unchanged. Coverage is the shared declarative
JSON fixtures (none/map/filter/reduce.json, byte-identical to iOS),
bumping the pinned fixture count to 345. Android counterpart of
RevenueCat/purchases-ios#6834.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Label each operator grouping in Operators.dispatch per PR review feedback. Co-authored-by: Cursor <cursoragent@cursor.com>
Move the string/array group after comparison so the Android dispatcher mirrors the iOS Operators.dispatch grouping order. Co-authored-by: Cursor <cursoragent@cursor.com>
Rename the all-match fixture and add cases where only the first or only the middle item matches, addressing PR review feedback that the existing some coverage was order dependent. Fixtures kept byte-identical with iOS. Co-authored-by: Cursor <cursoragent@cursor.com>
khepri guards all with notEmpty, so it returns false for an empty array like json-logic-js; drop the inaccurate claim that khepri returns true. Fixture kept byte-identical with iOS. Co-authored-by: Cursor <cursoragent@cursor.com>
…-logic-iteration-operators
…teration-operators Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # rules-engine-internal/src/test/kotlin/com/revenuecat/purchases/rules/PredicateFixtureLoaderTest.kt
…erators' into pallares/json-logic-min-max-operators Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # rules-engine-internal/src/main/kotlin/com/revenuecat/purchases/rules/operators/Operators.kt # rules-engine-internal/src/test/kotlin/com/revenuecat/purchases/rules/PredicateFixtureLoaderTest.kt
…in-max-operators Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # rules-engine-internal/src/main/kotlin/com/revenuecat/purchases/rules/operators/Operators.kt # rules-engine-internal/src/test/kotlin/com/revenuecat/purchases/rules/PredicateFixtureLoaderTest.kt
Add a dedicated "Min and max" grouping comment so the min/max cases are not lumped under arithmetic, matching the iOS dispatcher. Co-authored-by: Cursor <cursoragent@cursor.com>
…ators' into pallares/json-logic-iteration-mapping-operators Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # rules-engine-internal/src/test/kotlin/com/revenuecat/purchases/rules/PredicateFixtureLoaderTest.kt
Self-documenting replacement for the {"/": [-10,0]} workaround; constants
seeded only by the conformance harness (reservedConstants), engine untouched;
NaN still uses x != x; fixtures kept byte-identical with iOS.
Co-authored-by: Cursor <cursoragent@cursor.com>
substr.json and missing_some.json now use the seeded "+Infinity" and "-Infinity" variables instead of division-by-zero operands. NaN cases and evaluator.json are unchanged. Fixtures are byte-identical to iOS. Co-authored-by: Cursor <cursoragent@cursor.com>
Mirror iOS predicate fixture updates: remove the redundant "comes from the test-only" clause from 7 fixture descriptions across min, max, substr, and missing_some. Fixtures kept byte-identical with iOS. Co-authored-by: Cursor <cursoragent@cursor.com>
…nfinity-fixture-vars Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # rules-engine-internal/src/test/resources/predicate-fixtures/max.json # rules-engine-internal/src/test/resources/predicate-fixtures/min.json
…ture-vars' into pallares/json-logic-iteration-mapping-operators
Co-authored-by: Cursor <cursoragent@cursor.com>
…ument) Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Cover logging ±Infinity, NaN, empty object, and empty array. Empty array and empty args were indistinguishable under substring matching (they log "" and "null"), so `expectedLogs` now asserts the exact, ordered list of emitted messages. `expectedWarnings` is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
The tag was always the single `[RulesEngine]` constant and never varied at any call site, so it added interface surface without flexibility. For the `log` channel a prefix also defeats the verbatim passthrough. Hosts that bridge the logger prepend their own identifier when they need one. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Wrap NaN- and infinity-producing subexpressions in `log` and assert the exact emitted string via `expectedLogs`, so these fixtures verify the intermediate value, not just the final truthiness. Covers arithmetic, min, max, reduce, missing_some, and evaluator edge cases. Co-authored-by: Cursor <cursoragent@cursor.com>
Place a `log` in a branch that should be skipped and assert it never fires (`expectedLogs: []`), with positive controls that log when the branch is evaluated — verifying and/or/if laziness. Co-authored-by: Cursor <cursoragent@cursor.com>
Downloads khepri's predicate_conformance_v1.json and evaluates each fixture through the shared PredicateConformanceRunner, reusing the same in-repo fixture model and parameterized JUnit harness as the predicate fixtures. Adds the on-demand run-rules-engine-conformance-tests CircleCI job (triggered via the run_rules_engine_conformance_tests pipeline action) and a download script that fetches the fixtures from the private RevenueCat/khepri repo. Mirrors iOS PR #6822 (RevenueCat/purchases-ios). The conformance suite is kept out of the standard unit-test run because the fixture file is downloaded on demand and git-ignored (absent by default): the suite skips via a JUnit assumption when absent and is excluded from the default test task unless -PrunRulesEngineConformanceTests is set. No production changes. Co-authored-by: Cursor <cursoragent@cursor.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3574 +/- ##
=======================================
Coverage 80.30% 80.30%
=======================================
Files 377 377
Lines 15387 15387
Branches 2135 2135
=======================================
Hits 12356 12356
Misses 2174 2174
Partials 857 857 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Base automatically changed from
pallares/android-rules-fixture-log-assertions
to
main
June 9, 2026 15:35
…ri-predicate-conformance Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # rules-engine-internal/src/test/resources/predicate-fixtures/log.json
Mirror iOS' Xcode scheme pre-action: when `-PrunRulesEngineConformanceTests` is set, a Gradle task runs the download script before the suite and points the test JVM at the fetched file, so the conformance tests can be run locally with a single command. Default unit-test runs are unchanged (suite still excluded). Co-authored-by: Cursor <cursoragent@cursor.com>
Read and decode the downloaded conformance envelope once via a lazy, shared by the existence check and both accessors, mirroring the in-repo `allCases`. Avoids the few redundant reads/decodes per run. Test-only change. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves SDK-4334
Motivation
Run khepri's
predicate_conformance_v1.jsonagainstrules-engine-internalthrough the existing fixture runner, so the in-repo and khepri-downloaded fixtures share one harness. Android port of RevenueCat/purchases-ios#6822.Description
An on-demand
run-rules-engine-conformance-testsCI job downloads the fixtures (gitignored) and runs only the conformance suite; it is excluded from the default test task unless-PrunRulesEngineConformanceTestsis set.