|
33 | 33 | package org.opensearch.search.aggregations.bucket.histogram;
|
34 | 34 |
|
35 | 35 | import org.apache.lucene.tests.util.TestUtil;
|
| 36 | +import org.opensearch.core.common.breaker.CircuitBreaker; |
| 37 | +import org.opensearch.core.common.breaker.CircuitBreakingException; |
36 | 38 | import org.opensearch.search.DocValueFormat;
|
37 | 39 | import org.opensearch.search.aggregations.BucketOrder;
|
| 40 | +import org.opensearch.search.aggregations.InternalAggregation; |
38 | 41 | import org.opensearch.search.aggregations.InternalAggregations;
|
| 42 | +import org.opensearch.search.aggregations.MultiBucketConsumerService; |
39 | 43 | import org.opensearch.search.aggregations.ParsedMultiBucketAggregation;
|
| 44 | +import org.opensearch.search.aggregations.pipeline.PipelineAggregator; |
40 | 45 | import org.opensearch.test.InternalAggregationTestCase;
|
41 | 46 | import org.opensearch.test.InternalMultiBucketAggregationTestCase;
|
42 | 47 |
|
|
47 | 52 | import java.util.Map;
|
48 | 53 | import java.util.TreeMap;
|
49 | 54 |
|
| 55 | +import org.mockito.Mockito; |
| 56 | + |
50 | 57 | public class InternalHistogramTests extends InternalMultiBucketAggregationTestCase<InternalHistogram> {
|
51 | 58 |
|
52 | 59 | private boolean keyed;
|
@@ -123,6 +130,42 @@ public void testHandlesNaN() {
|
123 | 130 | );
|
124 | 131 | }
|
125 | 132 |
|
| 133 | + public void testCircuitBreakerWhenAddEmptyBuckets() { |
| 134 | + String name = randomAlphaOfLength(5); |
| 135 | + double interval = 1; |
| 136 | + double lowerBound = 1; |
| 137 | + double upperBound = 1026; |
| 138 | + List<InternalHistogram.Bucket> bucket1 = List.of( |
| 139 | + new InternalHistogram.Bucket(lowerBound, 1, false, format, InternalAggregations.EMPTY) |
| 140 | + ); |
| 141 | + List<InternalHistogram.Bucket> bucket2 = List.of( |
| 142 | + new InternalHistogram.Bucket(upperBound, 1, false, format, InternalAggregations.EMPTY) |
| 143 | + ); |
| 144 | + BucketOrder order = BucketOrder.key(true); |
| 145 | + InternalHistogram.EmptyBucketInfo emptyBucketInfo = new InternalHistogram.EmptyBucketInfo( |
| 146 | + interval, |
| 147 | + 0, |
| 148 | + lowerBound, |
| 149 | + upperBound, |
| 150 | + InternalAggregations.EMPTY |
| 151 | + ); |
| 152 | + InternalHistogram histogram1 = new InternalHistogram(name, bucket1, order, 0, emptyBucketInfo, format, false, null); |
| 153 | + InternalHistogram histogram2 = new InternalHistogram(name, bucket2, order, 0, emptyBucketInfo, format, false, null); |
| 154 | + |
| 155 | + CircuitBreaker breaker = Mockito.mock(CircuitBreaker.class); |
| 156 | + Mockito.when(breaker.addEstimateBytesAndMaybeBreak(0, "allocated_buckets")).thenThrow(CircuitBreakingException.class); |
| 157 | + |
| 158 | + MultiBucketConsumerService.MultiBucketConsumer bucketConsumer = new MultiBucketConsumerService.MultiBucketConsumer(0, breaker); |
| 159 | + InternalAggregation.ReduceContext reduceContext = InternalAggregation.ReduceContext.forFinalReduction( |
| 160 | + null, |
| 161 | + null, |
| 162 | + bucketConsumer, |
| 163 | + PipelineAggregator.PipelineTree.EMPTY |
| 164 | + ); |
| 165 | + expectThrows(CircuitBreakingException.class, () -> histogram1.reduce(List.of(histogram1, histogram2), reduceContext)); |
| 166 | + Mockito.verify(breaker, Mockito.times(1)).addEstimateBytesAndMaybeBreak(0, "allocated_buckets"); |
| 167 | + } |
| 168 | + |
126 | 169 | @Override
|
127 | 170 | protected void assertReduced(InternalHistogram reduced, List<InternalHistogram> inputs) {
|
128 | 171 | TreeMap<Double, Long> expectedCounts = new TreeMap<>();
|
|
0 commit comments