Skip to content

Commit 437273f

Browse files
authored
Add supported type tests for Percentiles/Ranks (#52597)
Also makes some tweaks to the test itself: - Makes it final so tests can't accidentally override - Adds specific example docs for the floating points, since they are encoded and some aggs (HDR histo) cannot use negative numbers, so blindly using a random long can encode to a negative - Some reformatting to make it more readable
1 parent 9b48d6f commit 437273f

File tree

5 files changed

+97
-27
lines changed

5 files changed

+97
-27
lines changed

server/src/test/java/org/elasticsearch/search/aggregations/metrics/HDRPercentileRanksAggregatorTests.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,32 @@
3030
import org.apache.lucene.util.NumericUtils;
3131
import org.elasticsearch.index.mapper.MappedFieldType;
3232
import org.elasticsearch.index.mapper.NumberFieldMapper;
33+
import org.elasticsearch.search.aggregations.AggregationBuilder;
3334
import org.elasticsearch.search.aggregations.AggregatorTestCase;
34-
import org.elasticsearch.search.aggregations.metrics.Percentile;
35-
import org.elasticsearch.search.aggregations.metrics.PercentileRanks;
36-
import org.elasticsearch.search.aggregations.metrics.PercentileRanksAggregationBuilder;
37-
import org.elasticsearch.search.aggregations.metrics.PercentilesMethod;
3835
import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper;
36+
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
37+
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
3938
import org.hamcrest.Matchers;
4039

4140
import java.io.IOException;
4241
import java.util.Iterator;
42+
import java.util.List;
4343

4444

4545
public class HDRPercentileRanksAggregatorTests extends AggregatorTestCase {
4646

47+
@Override
48+
protected AggregationBuilder createAggBuilderForTypeTest(MappedFieldType fieldType, String fieldName) {
49+
return new PercentileRanksAggregationBuilder("hdr_ranks", new double[]{0.1, 0.5, 12})
50+
.field(fieldName)
51+
.percentilesConfig(new PercentilesConfig.Hdr());
52+
}
53+
54+
@Override
55+
protected List<ValuesSourceType> getSupportedValuesSourceTypes() {
56+
return List.of(CoreValuesSourceType.NUMERIC);
57+
}
58+
4759
public void testEmpty() throws IOException {
4860
PercentileRanksAggregationBuilder aggBuilder = new PercentileRanksAggregationBuilder("my_agg", new double[]{0.5})
4961
.field("field")

server/src/test/java/org/elasticsearch/search/aggregations/metrics/HDRPercentilesAggregatorTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@
3333
import org.elasticsearch.common.CheckedConsumer;
3434
import org.elasticsearch.index.mapper.MappedFieldType;
3535
import org.elasticsearch.index.mapper.NumberFieldMapper;
36+
import org.elasticsearch.search.aggregations.AggregationBuilder;
3637
import org.elasticsearch.search.aggregations.AggregatorTestCase;
3738
import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper;
39+
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
40+
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
3841

3942
import java.io.IOException;
43+
import java.util.List;
4044
import java.util.function.Consumer;
4145

4246
import static java.util.Arrays.asList;
@@ -46,6 +50,18 @@
4650

4751
public class HDRPercentilesAggregatorTests extends AggregatorTestCase {
4852

53+
@Override
54+
protected AggregationBuilder createAggBuilderForTypeTest(MappedFieldType fieldType, String fieldName) {
55+
return new PercentilesAggregationBuilder("hdr_percentiles")
56+
.field(fieldName)
57+
.percentilesConfig(new PercentilesConfig.Hdr());
58+
}
59+
60+
@Override
61+
protected List<ValuesSourceType> getSupportedValuesSourceTypes() {
62+
return List.of(CoreValuesSourceType.NUMERIC);
63+
}
64+
4965
public void testNoDocs() throws IOException {
5066
testCase(new MatchAllDocsQuery(), iw -> {
5167
// Intentionally not writing any docs

server/src/test/java/org/elasticsearch/search/aggregations/metrics/TDigestPercentileRanksAggregatorTests.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,32 @@
3030
import org.apache.lucene.util.NumericUtils;
3131
import org.elasticsearch.index.mapper.MappedFieldType;
3232
import org.elasticsearch.index.mapper.NumberFieldMapper;
33+
import org.elasticsearch.search.aggregations.AggregationBuilder;
3334
import org.elasticsearch.search.aggregations.AggregatorTestCase;
34-
import org.elasticsearch.search.aggregations.metrics.Percentile;
35-
import org.elasticsearch.search.aggregations.metrics.PercentileRanks;
36-
import org.elasticsearch.search.aggregations.metrics.PercentileRanksAggregationBuilder;
37-
import org.elasticsearch.search.aggregations.metrics.PercentilesMethod;
3835
import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper;
36+
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
37+
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
3938
import org.hamcrest.Matchers;
4039

4140
import java.io.IOException;
4241
import java.util.Iterator;
42+
import java.util.List;
4343

4444

4545
public class TDigestPercentileRanksAggregatorTests extends AggregatorTestCase {
4646

47+
@Override
48+
protected AggregationBuilder createAggBuilderForTypeTest(MappedFieldType fieldType, String fieldName) {
49+
return new PercentileRanksAggregationBuilder("tdigest_ranks", new double[]{0.1, 0.5, 12})
50+
.field(fieldName)
51+
.percentilesConfig(new PercentilesConfig.TDigest());
52+
}
53+
54+
@Override
55+
protected List<ValuesSourceType> getSupportedValuesSourceTypes() {
56+
return List.of(CoreValuesSourceType.NUMERIC);
57+
}
58+
4759
public void testEmpty() throws IOException {
4860
PercentileRanksAggregationBuilder aggBuilder = new PercentileRanksAggregationBuilder("my_agg", new double[]{0.5})
4961
.field("field")

server/src/test/java/org/elasticsearch/search/aggregations/metrics/TDigestPercentilesAggregatorTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@
3333
import org.elasticsearch.common.CheckedConsumer;
3434
import org.elasticsearch.index.mapper.MappedFieldType;
3535
import org.elasticsearch.index.mapper.NumberFieldMapper;
36+
import org.elasticsearch.search.aggregations.AggregationBuilder;
3637
import org.elasticsearch.search.aggregations.AggregatorTestCase;
3738
import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper;
39+
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
40+
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
3841

3942
import java.io.IOException;
43+
import java.util.List;
4044
import java.util.function.Consumer;
4145

4246
import static java.util.Arrays.asList;
@@ -46,6 +50,18 @@
4650

4751
public class TDigestPercentilesAggregatorTests extends AggregatorTestCase {
4852

53+
@Override
54+
protected AggregationBuilder createAggBuilderForTypeTest(MappedFieldType fieldType, String fieldName) {
55+
return new PercentilesAggregationBuilder("tdist_percentiles")
56+
.field(fieldName)
57+
.percentilesConfig(new PercentilesConfig.TDigest());
58+
}
59+
60+
@Override
61+
protected List<ValuesSourceType> getSupportedValuesSourceTypes() {
62+
return List.of(CoreValuesSourceType.NUMERIC);
63+
}
64+
4965
public void testNoDocs() throws IOException {
5066
testCase(new MatchAllDocsQuery(), iw -> {
5167
// Intentionally not writing any docs

test/framework/src/main/java/org/elasticsearch/search/aggregations/AggregatorTestCase.java

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.elasticsearch.search.aggregations;
2020

2121
import org.apache.lucene.document.BinaryDocValuesField;
22+
import org.apache.lucene.document.HalfFloatPoint;
2223
import org.apache.lucene.document.InetAddressPoint;
2324
import org.apache.lucene.document.LatLonDocValuesField;
2425
import org.apache.lucene.document.SortedNumericDocValuesField;
@@ -41,6 +42,7 @@
4142
import org.apache.lucene.search.Weight;
4243
import org.apache.lucene.store.Directory;
4344
import org.apache.lucene.util.BytesRef;
45+
import org.apache.lucene.util.NumericUtils;
4446
import org.elasticsearch.Version;
4547
import org.elasticsearch.cluster.metadata.IndexMetaData;
4648
import org.elasticsearch.common.breaker.CircuitBreaker;
@@ -74,6 +76,7 @@
7476
import org.elasticsearch.index.mapper.Mapper;
7577
import org.elasticsearch.index.mapper.Mapper.BuilderContext;
7678
import org.elasticsearch.index.mapper.MapperService;
79+
import org.elasticsearch.index.mapper.NumberFieldMapper;
7780
import org.elasticsearch.index.mapper.ObjectMapper;
7881
import org.elasticsearch.index.mapper.ObjectMapper.Nested;
7982
import org.elasticsearch.index.mapper.RangeFieldMapper;
@@ -605,7 +608,7 @@ protected AggregationBuilder createAggBuilderForTypeTest(MappedFieldType fieldTy
605608
*
606609
* Exception types/messages are not currently checked, just presence/absence of an exception.
607610
*/
608-
public void testSupportedFieldTypes() throws IOException {
611+
public final void testSupportedFieldTypes() throws IOException {
609612
MapperRegistry mapperRegistry = new IndicesModule(Collections.emptyList()).getMapperRegistry();
610613
Settings settings = Settings.builder().put("index.version.created", Version.CURRENT.id).build();
611614
String fieldName = "typeTestFieldName";
@@ -675,67 +678,78 @@ public void testSupportedFieldTypes() throws IOException {
675678
*/
676679
private void writeTestDoc(MappedFieldType fieldType, String fieldName, RandomIndexWriter iw) throws IOException {
677680

678-
if (fieldType.getValuesSourceType().equals(CoreValuesSourceType.NUMERIC)) {
681+
String typeName = fieldType.typeName();
682+
ValuesSourceType vst = fieldType.getValuesSourceType();
683+
684+
if (vst.equals(CoreValuesSourceType.NUMERIC)) {
679685
// TODO note: once VS refactor adds DATE/BOOLEAN, this conditional will go away
680-
if (fieldType.typeName().equals(DateFieldMapper.CONTENT_TYPE)
681-
|| fieldType.typeName().equals(DateFieldMapper.DATE_NANOS_CONTENT_TYPE)) {
686+
if (typeName.equals(DateFieldMapper.CONTENT_TYPE) || typeName.equals(DateFieldMapper.DATE_NANOS_CONTENT_TYPE)) {
682687
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, randomNonNegativeLong())));
683-
} else if (fieldType.typeName().equals(BooleanFieldMapper.CONTENT_TYPE)) {
688+
} else if (typeName.equals(BooleanFieldMapper.CONTENT_TYPE)) {
684689
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, randomBoolean() ? 0 : 1)));
690+
} else if (typeName.equals(NumberFieldMapper.NumberType.DOUBLE.typeName())) {
691+
long encoded = NumericUtils.doubleToSortableLong(Math.abs(randomDouble()));
692+
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, encoded)));
693+
} else if (typeName.equals(NumberFieldMapper.NumberType.FLOAT.typeName())) {
694+
long encoded = NumericUtils.floatToSortableInt(Math.abs(randomFloat()));
695+
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, encoded)));
696+
} else if (typeName.equals(NumberFieldMapper.NumberType.HALF_FLOAT.typeName())) {
697+
long encoded = HalfFloatPoint.halfFloatToSortableShort(Math.abs(randomFloat()));
698+
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, encoded)));
685699
} else {
686-
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, randomLong())));
700+
iw.addDocument(singleton(new SortedNumericDocValuesField(fieldName, randomNonNegativeLong())));
687701
}
688-
} else if (fieldType.getValuesSourceType().equals(CoreValuesSourceType.BYTES)) {
689-
if (fieldType.typeName().equals(BinaryFieldMapper.CONTENT_TYPE)) {
702+
} else if (vst.equals(CoreValuesSourceType.BYTES)) {
703+
if (typeName.equals(BinaryFieldMapper.CONTENT_TYPE)) {
690704
iw.addDocument(singleton(new BinaryFieldMapper.CustomBinaryDocValuesField(fieldName, new BytesRef("a").bytes)));
691-
} else if (fieldType.typeName().equals(IpFieldMapper.CONTENT_TYPE)) {
705+
} else if (typeName.equals(IpFieldMapper.CONTENT_TYPE)) {
692706
// TODO note: once VS refactor adds IP, this conditional will go away
693707
boolean v4 = randomBoolean();
694708
iw.addDocument(singleton(new SortedSetDocValuesField(fieldName, new BytesRef(InetAddressPoint.encode(randomIp(v4))))));
695709
} else {
696710
iw.addDocument(singleton(new SortedSetDocValuesField(fieldName, new BytesRef("a"))));
697711
}
698-
} else if (fieldType.getValuesSourceType().equals(CoreValuesSourceType.RANGE)) {
712+
} else if (vst.equals(CoreValuesSourceType.RANGE)) {
699713
Object start;
700714
Object end;
701715
RangeType rangeType;
702716

703-
if (fieldType.typeName().equals(RangeType.DOUBLE.typeName())) {
717+
if (typeName.equals(RangeType.DOUBLE.typeName())) {
704718
start = randomDouble();
705719
end = RangeType.DOUBLE.nextUp(start);
706720
rangeType = RangeType.DOUBLE;
707-
} else if (fieldType.typeName().equals(RangeType.FLOAT.typeName())) {
721+
} else if (typeName.equals(RangeType.FLOAT.typeName())) {
708722
start = randomFloat();
709723
end = RangeType.FLOAT.nextUp(start);
710724
rangeType = RangeType.DOUBLE;
711-
} else if (fieldType.typeName().equals(RangeType.IP.typeName())) {
725+
} else if (typeName.equals(RangeType.IP.typeName())) {
712726
boolean v4 = randomBoolean();
713727
start = randomIp(v4);
714728
end = RangeType.IP.nextUp(start);
715729
rangeType = RangeType.IP;
716-
} else if (fieldType.typeName().equals(RangeType.LONG.typeName())) {
730+
} else if (typeName.equals(RangeType.LONG.typeName())) {
717731
start = randomLong();
718732
end = RangeType.LONG.nextUp(start);
719733
rangeType = RangeType.LONG;
720-
} else if (fieldType.typeName().equals(RangeType.INTEGER.typeName())) {
734+
} else if (typeName.equals(RangeType.INTEGER.typeName())) {
721735
start = randomInt();
722736
end = RangeType.INTEGER.nextUp(start);
723737
rangeType = RangeType.INTEGER;
724-
} else if (fieldType.typeName().equals(RangeType.DATE.typeName())) {
738+
} else if (typeName.equals(RangeType.DATE.typeName())) {
725739
start = randomNonNegativeLong();
726740
end = RangeType.DATE.nextUp(start);
727741
rangeType = RangeType.DATE;
728742
} else {
729-
throw new IllegalStateException("Unknown type of range [" + fieldType.typeName() + "]");
743+
throw new IllegalStateException("Unknown type of range [" + typeName + "]");
730744
}
731745

732746
final RangeFieldMapper.Range range = new RangeFieldMapper.Range(rangeType, start, end, true, true);
733747
iw.addDocument(singleton(new BinaryDocValuesField(fieldName, rangeType.encodeRanges(Collections.singleton(range)))));
734748

735-
} else if (fieldType.getValuesSourceType().equals(CoreValuesSourceType.GEOPOINT)) {
749+
} else if (vst.equals(CoreValuesSourceType.GEOPOINT)) {
736750
iw.addDocument(singleton(new LatLonDocValuesField(fieldName, randomDouble(), randomDouble())));
737751
} else {
738-
throw new IllegalStateException("Unknown field type [" + fieldType.typeName() + "]");
752+
throw new IllegalStateException("Unknown field type [" + typeName + "]");
739753
}
740754
}
741755

0 commit comments

Comments
 (0)