Skip to content

Commit 4735e0a

Browse files
committed
Throw exception when maxBounds greater than minBounds
The recent changes to the Histogram Aggregator introduced a bug where an exception would not be thrown if the maxBound of the extended bounds is less that the minBound. This change fixes that bug. Closes #19833
1 parent 920a21e commit 4735e0a

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

core/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramAggregationBuilder.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public class HistogramAggregationBuilder
4747

4848
private double interval;
4949
private double offset = 0;
50-
private double minBound = Double.MAX_VALUE;
51-
private double maxBound = Double.MIN_VALUE;
50+
private double minBound = Double.POSITIVE_INFINITY;
51+
private double maxBound = Double.NEGATIVE_INFINITY;
5252
private InternalOrder order = (InternalOrder) Histogram.Order.KEY_ASC;
5353
private boolean keyed = false;
5454
private long minDocCount = 0;
@@ -122,17 +122,24 @@ public double maxBound() {
122122
return maxBound;
123123
}
124124

125-
/** Set extended bounds on this builder: buckets between {@code minBound}
126-
* and {@code maxBound} will be created even if no documents fell into
127-
* these buckets. It is possible to create half-open bounds by providing
128-
* {@link Double#POSITIVE_INFINITY} as a {@code minBound} or
129-
* {@link Double#NEGATIVE_INFINITY} as a {@code maxBound}. */
125+
/**
126+
* Set extended bounds on this builder: buckets between {@code minBound} and
127+
* {@code maxBound} will be created even if no documents fell into these
128+
* buckets.
129+
*
130+
* @throws IllegalArgumentException
131+
* if maxBound is less that minBound, or if either of the bounds
132+
* are not finite.
133+
*/
130134
public HistogramAggregationBuilder extendedBounds(double minBound, double maxBound) {
131-
if (minBound == Double.NEGATIVE_INFINITY) {
132-
throw new IllegalArgumentException("minBound must not be -Infinity, got: " + minBound);
135+
if (Double.isFinite(minBound) == false) {
136+
throw new IllegalArgumentException("minBound must be finite, got: " + minBound);
133137
}
134-
if (maxBound == Double.POSITIVE_INFINITY) {
135-
throw new IllegalArgumentException("maxBound must not be +Infinity, got: " + maxBound);
138+
if (Double.isFinite(maxBound) == false) {
139+
throw new IllegalArgumentException("maxBound must be finite, got: " + maxBound);
140+
}
141+
if (maxBound < minBound) {
142+
throw new IllegalArgumentException("maxBound [" + maxBound + "] must be greater than minBound [" + minBound + "]");
136143
}
137144
this.minBound = minBound;
138145
this.maxBound = maxBound;

core/src/test/java/org/elasticsearch/search/aggregations/bucket/HistogramIT.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ public void testSingleValuedFieldWithExtendedBounds() throws Exception {
860860
return;
861861
}
862862

863-
} catch (Exception e) {
863+
} catch (IllegalArgumentException e) {
864864
if (invalidBoundsError) {
865865
// expected
866866
return;
@@ -886,7 +886,6 @@ public void testSingleValuedFieldWithExtendedBounds() throws Exception {
886886
}
887887
}
888888

889-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/19833")
890889
public void testEmptyWithExtendedBounds() throws Exception {
891890
int lastDataBucketKey = (numValueBuckets - 1) * interval;
892891

@@ -938,7 +937,7 @@ public void testEmptyWithExtendedBounds() throws Exception {
938937
return;
939938
}
940939

941-
} catch (Exception e) {
940+
} catch (IllegalArgumentException e) {
942941
if (invalidBoundsError) {
943942
// expected
944943
return;

core/src/test/java/org/elasticsearch/search/aggregations/bucket/HistogramTests.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregationBuilder;
2424
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram.Order;
2525

26+
import static org.hamcrest.Matchers.equalTo;
27+
import static org.hamcrest.Matchers.startsWith;
28+
2629
public class HistogramTests extends BaseAggregationTestCase<HistogramAggregationBuilder> {
2730

2831
@Override
@@ -31,7 +34,9 @@ protected HistogramAggregationBuilder createTestAggregatorBuilder() {
3134
factory.field(INT_FIELD_NAME);
3235
factory.interval(randomDouble() * 1000);
3336
if (randomBoolean()) {
34-
factory.extendedBounds(randomDouble(), randomDouble());
37+
double minBound = randomDouble();
38+
double maxBound = randomDoubleBetween(minBound, 1, true);
39+
factory.extendedBounds(minBound, maxBound);
3540
}
3641
if (randomBoolean()) {
3742
factory.format("###.##");
@@ -74,4 +79,27 @@ protected HistogramAggregationBuilder createTestAggregatorBuilder() {
7479
return factory;
7580
}
7681

82+
public void testInvalidBounds() {
83+
HistogramAggregationBuilder factory = new HistogramAggregationBuilder("foo");
84+
factory.field(INT_FIELD_NAME);
85+
factory.interval(randomDouble() * 1000);
86+
87+
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(Double.NaN, 1.0); });
88+
assertThat(ex.getMessage(), startsWith("minBound must be finite, got: "));
89+
ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(Double.POSITIVE_INFINITY, 1.0); });
90+
assertThat(ex.getMessage(), startsWith("minBound must be finite, got: "));
91+
ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(Double.NEGATIVE_INFINITY, 1.0); });
92+
assertThat(ex.getMessage(), startsWith("minBound must be finite, got: "));
93+
94+
ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(0.0, Double.NaN); });
95+
assertThat(ex.getMessage(), startsWith("maxBound must be finite, got: "));
96+
ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(0.0, Double.POSITIVE_INFINITY); });
97+
assertThat(ex.getMessage(), startsWith("maxBound must be finite, got: "));
98+
ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(0.0, Double.NEGATIVE_INFINITY); });
99+
assertThat(ex.getMessage(), startsWith("maxBound must be finite, got: "));
100+
101+
ex = expectThrows(IllegalArgumentException.class, () -> { factory.extendedBounds(0.5, 0.4); });
102+
assertThat(ex.getMessage(), equalTo("maxBound [0.4] must be greater than minBound [0.5]"));
103+
}
104+
77105
}

0 commit comments

Comments
 (0)