25
25
import org .elasticsearch .search .aggregations .BucketOrder ;
26
26
import org .elasticsearch .search .aggregations .InternalAggregation ;
27
27
import org .elasticsearch .search .aggregations .InternalAggregations ;
28
- import org .elasticsearch .test .InternalMultiBucketAggregationTestCase ;
29
28
import org .elasticsearch .search .aggregations .ParsedMultiBucketAggregation ;
30
29
import org .elasticsearch .search .aggregations .pipeline .PipelineAggregator ;
30
+ import org .elasticsearch .test .InternalMultiBucketAggregationTestCase ;
31
31
32
32
import java .util .ArrayList ;
33
33
import java .util .Arrays ;
@@ -40,29 +40,52 @@ public class InternalHistogramTests extends InternalMultiBucketAggregationTestCa
40
40
41
41
private boolean keyed ;
42
42
private DocValueFormat format ;
43
+ private int interval ;
44
+ private int minDocCount ;
45
+ private InternalHistogram .EmptyBucketInfo emptyBucketInfo ;
46
+ private int offset ;
43
47
44
48
@ Override
45
- public void setUp () throws Exception {
49
+ public void setUp () throws Exception {
46
50
super .setUp ();
47
51
keyed = randomBoolean ();
48
52
format = randomNumericDocValueFormat ();
53
+ interval = randomIntBetween (1 , 3 );
54
+ offset = randomIntBetween (0 , 3 );
55
+ if (randomBoolean ()) {
56
+ minDocCount = randomIntBetween (1 , 10 );
57
+ emptyBucketInfo = null ;
58
+ } else {
59
+ minDocCount = 0 ;
60
+ //it's ok if minBound and maxBound are outside the range of the generated buckets, that will just mean that
61
+ //empty buckets won't be added before the first bucket and/or after the last one
62
+ int minBound = randomInt (50 ) - 30 ;
63
+ int maxBound = randomNumberOfBuckets () * interval + randomIntBetween (0 , 10 );
64
+ emptyBucketInfo = new InternalHistogram .EmptyBucketInfo (interval , offset , minBound , maxBound , InternalAggregations .EMPTY );
65
+ }
66
+ }
67
+
68
+ private double round (double key ) {
69
+ return Math .floor ((key - offset ) / interval ) * interval + offset ;
49
70
}
50
71
51
72
@ Override
52
73
protected InternalHistogram createTestInstance (String name ,
53
74
List <PipelineAggregator > pipelineAggregators ,
54
75
Map <String , Object > metaData ,
55
76
InternalAggregations aggregations ) {
56
- final int base = randomInt (50 ) - 30 ;
77
+ final double base = round ( randomInt (50 ) - 30 ) ;
57
78
final int numBuckets = randomNumberOfBuckets ();
58
- final int interval = randomIntBetween (1 , 3 );
59
79
List <InternalHistogram .Bucket > buckets = new ArrayList <>();
60
80
for (int i = 0 ; i < numBuckets ; ++i ) {
61
- final int docCount = TestUtil .nextInt (random (), 1 , 50 );
62
- buckets .add (new InternalHistogram .Bucket (base + i * interval , docCount , keyed , format , aggregations ));
81
+ //rarely leave some holes to be filled up with empty buckets in case minDocCount is set to 0
82
+ if (frequently ()) {
83
+ final int docCount = TestUtil .nextInt (random (), 1 , 50 );
84
+ buckets .add (new InternalHistogram .Bucket (base + i * interval , docCount , keyed , format , aggregations ));
85
+ }
63
86
}
64
87
BucketOrder order = BucketOrder .key (randomBoolean ());
65
- return new InternalHistogram (name , buckets , order , 1 , null , format , keyed , pipelineAggregators , metaData );
88
+ return new InternalHistogram (name , buckets , order , minDocCount , emptyBucketInfo , format , keyed , pipelineAggregators , metaData );
66
89
}
67
90
68
91
// issue 26787
@@ -88,13 +111,36 @@ public void testHandlesNaN() {
88
111
89
112
@ Override
90
113
protected void assertReduced (InternalHistogram reduced , List <InternalHistogram > inputs ) {
91
- Map <Double , Long > expectedCounts = new TreeMap <>();
114
+ TreeMap <Double , Long > expectedCounts = new TreeMap <>();
92
115
for (Histogram histogram : inputs ) {
93
116
for (Histogram .Bucket bucket : histogram .getBuckets ()) {
94
117
expectedCounts .compute ((Double ) bucket .getKey (),
95
118
(key , oldValue ) -> (oldValue == null ? 0 : oldValue ) + bucket .getDocCount ());
96
119
}
97
120
}
121
+ if (minDocCount == 0 ) {
122
+ double minBound = round (emptyBucketInfo .minBound );
123
+ if (expectedCounts .isEmpty () && emptyBucketInfo .minBound < emptyBucketInfo .maxBound ) {
124
+ expectedCounts .put (minBound , 0L );
125
+ }
126
+ if (expectedCounts .isEmpty () == false ) {
127
+ Double nextKey = expectedCounts .firstKey ();
128
+ while (nextKey < expectedCounts .lastKey ()) {
129
+ expectedCounts .putIfAbsent (nextKey , 0L );
130
+ nextKey += interval ;
131
+ }
132
+ while (minBound < expectedCounts .firstKey ()) {
133
+ expectedCounts .put (expectedCounts .firstKey () - interval , 0L );
134
+ }
135
+ double maxBound = round (emptyBucketInfo .maxBound );
136
+ while (expectedCounts .lastKey () < maxBound ) {
137
+ expectedCounts .put (expectedCounts .lastKey () + interval , 0L );
138
+ }
139
+ }
140
+ }
141
+
142
+ expectedCounts .entrySet ().removeIf (doubleLongEntry -> doubleLongEntry .getValue () < minDocCount );
143
+
98
144
Map <Double , Long > actualCounts = new TreeMap <>();
99
145
for (Histogram .Bucket bucket : reduced .getBuckets ()) {
100
146
actualCounts .compute ((Double ) bucket .getKey (),
@@ -121,6 +167,7 @@ protected InternalHistogram mutateInstance(InternalHistogram instance) {
121
167
long minDocCount = instance .getMinDocCount ();
122
168
List <PipelineAggregator > pipelineAggregators = instance .pipelineAggregators ();
123
169
Map <String , Object > metaData = instance .getMetaData ();
170
+ InternalHistogram .EmptyBucketInfo emptyBucketInfo = instance .emptyBucketInfo ;
124
171
switch (between (0 , 4 )) {
125
172
case 0 :
126
173
name += randomAlphaOfLength (5 );
@@ -135,6 +182,7 @@ protected InternalHistogram mutateInstance(InternalHistogram instance) {
135
182
break ;
136
183
case 3 :
137
184
minDocCount += between (1 , 10 );
185
+ emptyBucketInfo = null ;
138
186
break ;
139
187
case 4 :
140
188
if (metaData == null ) {
@@ -147,6 +195,6 @@ protected InternalHistogram mutateInstance(InternalHistogram instance) {
147
195
default :
148
196
throw new AssertionError ("Illegal randomisation branch" );
149
197
}
150
- return new InternalHistogram (name , buckets , order , minDocCount , null , format , keyed , pipelineAggregators , metaData );
198
+ return new InternalHistogram (name , buckets , order , minDocCount , emptyBucketInfo , format , keyed , pipelineAggregators , metaData );
151
199
}
152
200
}
0 commit comments