Skip to content

test(integ-test): add explicit ordering to order-dependent integration tests - #5723

Merged
mengweieric merged 7 commits into
opensearch-project:mainfrom
mengweieric:fix/order-dependent-tests
Aug 26, 2026
Merged

test(integ-test): add explicit ordering to order-dependent integration tests#5723
mengweieric merged 7 commits into
opensearch-project:mainfrom
mengweieric:fix/order-dependent-tests

Conversation

@mengweieric

@mengweieric mengweieric commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Description

Seven integration-test classes assert exact values or exact output over a query whose row order was never defined. All are test-side: every changed file is under src/test, no production code is touched, and no expected value changes — each fix adds an ordering that reproduces what the test already expects.

Why one shard passes and multiple shards fail: with a single shard there is one segment order, so an unordered scan returns rows in a stable incidental order and an assertion depending on it passes by luck. With multiple shards the coordinator merges per-shard results, that incidental order changes, and the assertion breaks.

Why these are test defects and not engine bugs: in each case the engine returns correct data for whichever rows it was given — what differs is which rows reach the assertion, or in what order they are printed, neither of which the query constrained.

1. CalciteMultiValueStatsIThead N with no sort

Seven tests run head N over an unordered scan and then assert exact values. head selects an undefined set of rows, so a 5-shard index feeds stats a different set:

source=<calcs> | head 5 | stats values(num0) as num_values by str0

1 shard : FURNITURE, FURNITURE, OFFICE SUPPLIES, OFFICE SUPPLIES, OFFICE SUPPLIES
5 shards: OFFICE SUPPLIES, OFFICE SUPPLIES, TECHNOLOGY, OFFICE SUPPLIES, TECHNOLOGY

Real failures:

testValuesFunctionGroupBy                AssertionError: expected:<2> but was:<3>
testListFunctionMultipleFields           expected: [[one, two, three], [5, -4, 5]]
                                         but was:  [["one","six"], ["5","-5","2"]]
testListFunctionWithTime                 expected: [[19:36:22]]  but was: [["22:50:16"]]
testListFunctionWithArithmeticExpression expected: [[9, 14, 3]]   but was: [["9","6","8"]]
testValuesFunctionWithNullValues         expected: [[1, 7]]       but was: [["1","3","4"]]

Note testValuesFunctionGroupBy: the group count differs, which normally suggests broken aggregation. It does not here — the input set differs, so a different number of str0 groups is present. Grouping itself is correct.

key is unique in the CALCS fixture (17 distinct over 17 documents), so sort key fixes the selection. Verified per test that 1-shard and 5-shard become identical and every existing expectation still holds:

1sh == 5sh expectation preserved
all 7 tests yes yes

Four other head tests in this class are deliberately left alone — they assert only schema and non-emptiness, so no exact value depends on the selection.

2. RawFormatIT — rendered table compared row by row

Two tests compare a fully rendered table against a query with no ORDER BY:

org.junit.ComparisonFailure:
expected:<... |lastname  [+Amber JOHnny|Duke Willmington+ -Hattie |Bond- =Nanette |Bates=] @Dale ...>

account_number is unique and ascends in exactly the order already asserted — 1, 6, 13, 18, 20 → Amber, Hattie, Nanette, Dale, Elinor — so ordering by it leaves the expected output byte for byte unchanged. All rows are retained.

3. StandaloneIT — whole response body compared

testSourceFieldQuery indexes two documents and compares the entire response body, datarows included, against a query with no sort:

org.junit.ComparisonFailure:
expected:<..."[hello" ], [ "world]" ]...>  but was:<..."[world" ], [ "hello]"...>

Sorting by name yields the same hello, world order the test already expects, so the expected body is unchanged.

4. CalciteConvertCommandIT, CalciteEvalCommandIT, CalciteMVAppendFunctionIThead N on BANK

Seven more tests share the same defect against the seven-row BANK fixture. Sorting by account_number selects accounts 1, 6, 13, whose values are exactly what the tests already assert:

account_number  1 ->  balance 39225  age 32  Amber JOHnny / Duke Willmington
account_number  6 ->  balance  5686  age 36  Hattie / Bond
account_number 13 ->  balance 32838  age 28  Nanette / Bates
  • CalciteConvertCommandIT: testConvertAutoFunction, testConvertNumFunction, testConvertWithAlias, testConvertMultipleFunctions, testConvertNoneFunction
  • CalciteEvalCommandIT: testEvalStringConcatenationWithExistingData
  • CalciteMVAppendFunctionIT: testMvappendWithFieldsAndLiterals — the neighbouring real-field tests in that class already sort by account_number, so this matches the existing local convention

5. CalciteBinCommandIThead N with exact bins

  • testBinValueFieldOnly: @timestamp is unique across all 100 time_test_data documents, and the three earliest values (8945, 7623, 9187) give exactly the asserted bins 8000-10000, 6000-8000, 8000-10000.
  • testBinSpanWithStartEndNeverShrinkRange: takes six of the seven BANK documents; sorting by account_number yields ages 32, 36, 28, 33, 36, 39 — the existing expectations.

testBinTimestampSpan6Days and testBinTimestampSpan7Days are deliberately left failing. They already sort, but they sort after bin has replaced @timestamp with the bin label, so every row shares one key and the sort is not a total order. Correcting them needs either a pipeline reorder or new expected values, neither of which belongs in this change.

Testing

integTestRemote against the same cluster at both shard counts, to confirm the changes did not trade one failure mode for another:

1 shard 5 shards
all seven classes 288 tests, 0 failures 288 tests, 2 failures — the two bin timestamp tests excluded above
CalciteMultiValueStatsIT 31/31 31/31 — both pushdown and no-pushdown routes

Deliberately not included, since each involves command semantics or engine behaviour rather than an undefined order: the two bin timestamp tests above, head | sort (testHeadThenSort is already annotated HEAD_WITHOUT_STABLE_SORT and branches its expectation per route, so moving the sort would change the operation under test), reverse, streamstats, FIRST/LAST, TAKE, and consecutive dedup. Nothing requiring an expected-value rewrite is included.

Check List

  • New functionality includes testing.
  • Commits are signed per the DCO using --signoff or -s.

Remaining items are not applicable: this changes integration-test queries only, and adds no functionality or user-facing behaviour.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@mengweieric mengweieric added the testing Related to improving software testing label Aug 25, 2026
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 1c85e22)

Here are some key observations to aid the review process:

🧪 No relevant tests
🔒 No security concerns identified
✅ No TODO sections
🔀 No multiple PR themes
⚡ No major issues detected

…tsIT

Seven tests run `head N` with no preceding sort and then assert exact values.
`head` over an unordered scan selects an undefined set of rows, so those values
hold only by accident of scan order, and a 5-shard index feeds `stats` a
different set:

  testValuesFunctionGroupBy   1 shard: FURNITURE, OFFICE SUPPLIES
                              5 shards: OFFICE SUPPLIES, TECHNOLOGY

The engine is not at fault -- what differs is which rows reach `stats`, not how
they are aggregated.

`key` is unique in the CALCS fixture (17 distinct over 17 documents), so sorting
on it fixes the selection. Verified per test that 1-shard and 5-shard results
become identical and every existing expectation still holds, so no expected value
changes.

Four other `head` tests in this class are left alone: they assert only schema and
non-emptiness, so no exact value depends on the selection.

Signed-off-by: Eric Wei <menwe@amazon.com>
Five tests run `head 3` with no preceding sort and assert the values of the first
three BANK documents. Sorting by account_number selects accounts 1, 6 and 13,
whose balances (39225, 5686, 32838) and ages (32, 36, 28) are exactly what the
tests already expect, so no expected value changes.

Signed-off-by: Eric Wei <menwe@amazon.com>
testEvalStringConcatenationWithExistingData runs `head 3` with no preceding sort
and asserts concatenated names from the first three BANK documents. Sorting by
account_number selects accounts 1, 6 and 13, matching the existing expectations.

Signed-off-by: Eric Wei <menwe@amazon.com>
…ionIT

testMvappendWithFieldsAndLiterals runs `head 1` with no preceding sort and
asserts age 32, which is the first BANK document only by accident of scan order.
Sort by account_number, matching the neighbouring real-field tests in this class
which already do so.

Signed-off-by: Eric Wei <menwe@amazon.com>
Two tests run `head N` with no preceding sort and assert exact bins.

testBinValueFieldOnly takes the first three time_test_data documents; @timestamp
is unique across all 100, and the three earliest values (8945, 7623, 9187) give
exactly the asserted bins.

testBinSpanWithStartEndNeverShrinkRange takes six of the seven BANK documents;
sorting by account_number yields ages 32, 36, 28, 33, 36, 39, matching the
existing expectations.

testBinTimestampSpan6Days and testBinTimestampSpan7Days are deliberately not
fixed here. They already sort, but they sort after `bin` has replaced @timestamp
with the bin label, so every row shares one key and the sort is not a total
order. Correcting them needs either a pipeline reorder or new expected values,
neither of which belongs in this change.

Signed-off-by: Eric Wei <menwe@amazon.com>
Two tests compare a fully rendered table, row for row, against a query with no
ORDER BY. Row order is unspecified, so the comparison holds only by accident of
scan order and breaks once the index has more than one shard.

account_number is unique in the fixture and ascends in the same order the tests
already expect (1, 6, 13, 18, 20 -> Amber, Hattie, Nanette, Dale, Elinor), so
ordering by it leaves the expected output byte for byte unchanged. All rows are
retained. contentHeaderTest shares the query but asserts only the response
content type, so it is left unordered.

Signed-off-by: Eric Wei <menwe@amazon.com>
testSourceFieldQuery indexes two documents and compares the whole response body,
including datarows, against a query with no sort. The expected order is hello
then world, which holds only by accident of scan order. Sorting by name yields
that same order, so the expected body is unchanged.

Signed-off-by: Eric Wei <menwe@amazon.com>
@mengweieric
mengweieric force-pushed the fix/order-dependent-tests branch from a2c4a6e to 1c85e22 Compare August 25, 2026 22:45
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 1c85e22

@mengweieric
mengweieric merged commit c64b06f into opensearch-project:main Aug 26, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

testing Related to improving software testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants