Skip to content

Add order-independent list equivalence tests (FHIR-59734) - #173

Open
bryantaustin13 wants to merge 1 commit into
cqframework:mainfrom
bryantaustin13:list-equivalent-order-independent
Open

bryantaustin13 wants to merge 1 commit into
cqframework:mainfrom
bryantaustin13:list-equivalent-order-independent

Conversation

@bryantaustin13

@bryantaustin13 bryantaustin13 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Test cases for FHIR-59734, which corrects CQL list equivalence (~) to match FHIRPath. The tests come from the Zulip thread ~ and duplicates. Paul Lynch's two cases are the first two rows of the Equivalent table below. They're meant to check that the corrected wording produces aligned engines before the tracker goes to the WG.

The change

CQL currently says list equivalence is ordered (Equivalent, and the list case in the general Equivalent): "for each element in the lists, in order, the elements are equivalent."

FHIRPath (§6.1.2 Equivalent) says: "Each item must be equivalent. Comparison is not order dependent. Note that this implies that if the collections have a different number of items to compare … the result will be false."

The Zulip discussion settled on a pairwise reading. Each item is matched one to one with an equivalent item on the other side, in any order, so duplicates count. Set-style comparison is still available with includes/included in.

Tests

All tests are in CqlListOperatorsTest.xml and use version="1.0", matching their groups.

Equivalent

Test Expression Expected What it checks
Equivalent12And21 { 1, 2 } ~ { 2, 1 } true Order doesn't matter (Paul's case 1)
Equivalent112And122 { 1, 1, 2 } ~ { 1, 2, 2 } false Duplicates pair one to one, ruling out a set-based reading (Paul's case 2)
Equivalent111And112 { 1, 1, 1 } ~ { 1, 1, 2 } false The one-directional case from the thread…
Equivalent112And111 { 1, 1, 2 } ~ { 1, 1, 1 } false …and its reverse: a ~ b must equal b ~ a
Equivalent122And212 { 1, 2, 2 } ~ { 2, 1, 2 } true Duplicates and reordering together
EquivalentOneNullAndNullOne { 1, null } ~ { null, 1 } true CQL lists can hold nulls, and null ~ null is true
EquivalentaBAndbA { 'a', 'B' } ~ { 'b', 'A' } true Reordering combined with case-insensitive string equivalence

Not Equivalent

Test Expression Expected
NotEquivalent12And21 { 1, 2 } !~ { 2, 1 } false

Equal (guard)

Test Expression Expected
Equal12And21 { 1, 2 } = { 2, 1 } false

List equality stays ordered in both CQL (Equal) and FHIRPath. FHIR-59734 changes only equivalence.

Equivalent112And122, Equivalent111And112, Equivalent112And111 and Equal12And21 hold under both the current and the corrected wording. They catch an engine fix that makes ~ order-independent by treating the lists as sets.

Current engines

Both reference engines implement the current, ordered wording:

  • the Java engine: listEquivalent in EquivalentEvaluator.kt walks both lists in step;
  • cql-execution: compareEveryItemInArrays compares item i with item i.

So Equivalent12And21, Equivalent122And212, EquivalentOneNullAndNullOne, EquivalentaBAndbA and NotEquivalent12And21 are expected to fail on both until they're updated.

Run through cql-tests-runner (main, $cql) against the Java engine on HAPI FHIR 8.12.0, the results match:

Test Result Engine returned
Equivalent12And21 fail false
Equivalent122And212 fail false
EquivalentOneNullAndNullOne fail false
EquivalentaBAndbA fail false
NotEquivalent12And21 fail true
Equivalent112And122, Equivalent111And112, Equivalent112And111 pass false
Equal12And21 pass false

I haven't run them against cql-execution; that expectation comes from reading compareEveryItemInArrays. The engine changes are tracked in cqframework/clinical_quality_language#1897 (Java) and cqframework/cql-execution#398.

None of the 13 existing list ~/!~ tests reorder items, so none of them change.

Not covered

  • Nested lists, such as { {1, 2} } ~ { {2, 1} }. Order-independence would apply recursively if element equivalence uses the same rule, but neither the tracker nor the thread says so.

CqlListOperatorsTest.xml validates against tests/testSchema.xsd.

🤖 Generated with Claude Code

FHIR-59734 corrects CQL list equivalence to match FHIRPath: items are
paired one to one, in any order. Adds seven Equivalent tests, one
NotEquivalent test, and an Equal guard showing equality stays ordered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant