Skip to content

Commit 495bf67

Browse files
authored
For stability of DisjunctionIntervalsSource.toString(), sort subSources (#193)
Iterators over subSources of DisjunctionIntervalsSource may return elements in indeterminate order, requiring special handling to make toString() output stable across equivalent instances
1 parent 636d10b commit 495bf67

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

lucene/queries/src/java/org/apache/lucene/queries/intervals/DisjunctionIntervalsSource.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ public int hashCode() {
120120

121121
@Override
122122
public String toString() {
123-
return subSources.stream().map(Object::toString).collect(Collectors.joining(",", "or(", ")"));
123+
return subSources.stream()
124+
.map(Object::toString)
125+
.sorted()
126+
.collect(Collectors.joining(",", "or(", ")"));
124127
}
125128

126129
@Override

lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.io.IOException;
2121
import java.util.Arrays;
22+
import java.util.Collections;
2223
import java.util.HashSet;
2324
import java.util.Set;
2425
import java.util.stream.Collectors;
@@ -401,6 +402,35 @@ public void testUnorderedWithRepeatsAndMaxGaps() throws IOException {
401402
source, "field1", 3, new int[][] {{}, {0, 3, 2, 6}, {3, 6}, {}, {0, 3, 2, 6}, {}});
402403
}
403404

405+
public void testIntervalDisjunctionToStringStability() {
406+
/*
407+
Sanity check that the subclauses of a disjunction are presented in sorted order via the toString() method.
408+
The exact order is irrelevant, but ensuring stability of output makes the output more useful; e.g., for external
409+
comparison across different JVMs, etc...
410+
*/
411+
final int size =
412+
random().nextInt(22) + 4; // ensure a reasonably large minimum number of clauses
413+
final String[] terms = new String[size];
414+
for (int i = 0; i < size; i++) {
415+
terms[i] = Character.toString((char) ('a' + i));
416+
}
417+
final String expected = Arrays.stream(terms).collect(Collectors.joining(",", "or(", ")"));
418+
419+
/*
420+
NOTE: shuffling below shouldn't matter at the moment (because the disjunction subSources are destined for a
421+
HashMap, so will be reordered anyway); but it might matter if the internal implementation of
422+
DisjunctionIntervalsSource changes.
423+
*/
424+
Collections.shuffle(Arrays.asList(terms), random());
425+
426+
IntervalsSource source =
427+
Intervals.or(
428+
Arrays.stream(terms)
429+
.map((term) -> Intervals.term(term))
430+
.toArray((sz) -> new IntervalsSource[sz]));
431+
assertEquals(expected, source.toString());
432+
}
433+
404434
public void testIntervalDisjunction() throws IOException {
405435
IntervalsSource source =
406436
Intervals.or(Intervals.term("pease"), Intervals.term("hot"), Intervals.term("notMatching"));

0 commit comments

Comments
 (0)