Skip to content

Commit

Permalink
[Test] Use appropriate DocValueFormats in Aggregations tests (elastic…
Browse files Browse the repository at this point in the history
…#24155)

Some aggregations (like Min, Max etc) use a wrong DocValueFormat in
tests (like IP or GeoHash). We should not test aggregations that expect
a numeric value with a DocValueFormat like IP. Such wrong DocValueFormat
can also prevent the aggregation to be rendered as ToXContent, and this
will be an issue for the High Level Rest Client tests which expect to be
able to parse back aggregations.
  • Loading branch information
tlrx authored and javanna committed May 23, 2017
1 parent a36967a commit 0910ebe
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 10 deletions.
17 changes: 17 additions & 0 deletions core/src/main/java/org/elasticsearch/search/DocValueFormat.java
Expand Up @@ -393,5 +393,22 @@ public double parseDouble(String value, boolean roundUp, LongSupplier now) {
public BytesRef parseBytesRef(String value) {
throw new UnsupportedOperationException();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Decimal that = (Decimal) o;
return Objects.equals(pattern, that.pattern);
}

@Override
public int hashCode() {
return Objects.hash(pattern);
}
}
}
Expand Up @@ -19,9 +19,6 @@

package org.elasticsearch.search;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.InetAddressPoint;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
Expand All @@ -34,6 +31,9 @@
import org.elasticsearch.test.ESTestCase;
import org.joda.time.DateTimeZone;

import java.util.ArrayList;
import java.util.List;

public class DocValueFormatTests extends ESTestCase {

public void testSerialization() throws Exception {
Expand Down Expand Up @@ -108,6 +108,18 @@ public void testIpFormat() {
DocValueFormat.IP.format(new BytesRef(InetAddressPoint.encode(InetAddresses.forString("::1")))));
}

public void testDecimalFormat() {
DocValueFormat formatter = new DocValueFormat.Decimal("###.##");
assertEquals("0", formatter.format(0.0d));
assertEquals("1", formatter.format(1d));
formatter = new DocValueFormat.Decimal("000.000");
assertEquals("-000.500", formatter.format(-0.5));
formatter = new DocValueFormat.Decimal("###,###.###");
assertEquals("0.86", formatter.format(0.8598023539251286d));
formatter = new DocValueFormat.Decimal("###,###.###");
assertEquals("859,802.354", formatter.format(0.8598023539251286d * 1_000_000));
}

public void testRawParse() {
assertEquals(-1L, DocValueFormat.RAW.parseLong("-1", randomBoolean(), null));
assertEquals(1L, DocValueFormat.RAW.parseLong("1", randomBoolean(), null));
Expand Down Expand Up @@ -145,4 +157,16 @@ public void testIPParse() {
assertEquals(new BytesRef(InetAddressPoint.encode(InetAddresses.forString("::1"))),
DocValueFormat.IP.parseBytesRef("::1"));
}

public void testDecimalParse() {
DocValueFormat parser = new DocValueFormat.Decimal("###.##");
assertEquals(0.0d, parser.parseDouble(randomFrom("0.0", "0", ".0", ".0000"), true, null), 0.0d);
assertEquals(-1.0d, parser.parseDouble(randomFrom("-1.0", "-1", "-1.0", "-1.0000"), true, null), 0.0d);
assertEquals(0.0d, parser.parseLong("0", true, null), 0.0d);
assertEquals(1.0d, parser.parseLong("1", true, null), 0.0d);
parser = new DocValueFormat.Decimal("###,###.###");
assertEquals(859802.354d, parser.parseDouble("859,802.354", true, null), 0.0d);
assertEquals(0.859d, parser.parseDouble("0.859", true, null), 0.0d);
assertEquals(0.8598023539251286d, parser.parseDouble("0.8598023539251286", true, null), 0.0d);
}
}
Expand Up @@ -45,6 +45,7 @@
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCountAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.InternalSimpleValue;
import org.elasticsearch.search.aggregations.pipeline.ParsedSimpleValue;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.search.aggregations.pipeline.derivative.DerivativePipelineAggregationBuilder;
Expand All @@ -56,6 +57,7 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.function.Supplier;

import static java.util.Collections.*;
import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
Expand Down Expand Up @@ -149,4 +151,15 @@ public final void testFromXContent() throws IOException {
//norelease TODO make abstract
protected void assertFromXContent(T aggregation, ParsedAggregation parsedAggregation) {
}

/**
* @return a random {@link DocValueFormat} that can be used in aggregations which
* compute numbers.
*/
protected static DocValueFormat randomNumericDocValueFormat() {
final List<Supplier<DocValueFormat>> formats = new ArrayList<>(3);
formats.add(() -> DocValueFormat.RAW);
formats.add(() -> new DocValueFormat.Decimal(randomFrom("###.##", "###,###.##")));
return randomFrom(formats).get();
}
}
@@ -0,0 +1,57 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.search.aggregations.bucket;

import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.InternalAggregations;
import org.elasticsearch.search.aggregations.metrics.max.InternalMax;
import org.elasticsearch.search.aggregations.metrics.min.InternalMin;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;

public abstract class InternalSingleBucketAggregationTestCase<T extends InternalSingleBucketAggregation>
extends InternalAggregationTestCase<T> {
private final boolean hasInternalMax = randomBoolean();
private final boolean hasInternalMin = randomBoolean();

protected abstract T createTestInstance(String name, long docCount, InternalAggregations aggregations,
List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData);

@Override
protected final T createTestInstance(String name, List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
List<InternalAggregation> internal = new ArrayList<>();
if (hasInternalMax) {
internal.add(new InternalMax("max", randomDouble(), randomNumericDocValueFormat(), emptyList(), emptyMap()));
}
if (hasInternalMin) {
internal.add(new InternalMin("min", randomDouble(), randomNumericDocValueFormat(), emptyList(), emptyMap()));
}
// we shouldn't use the full long range here since we sum doc count on reduce, and don't want to overflow the long range there
long docCount = between(0, Integer.MAX_VALUE);
return createTestInstance(name, docCount, new InternalAggregations(internal), pipelineAggregators, metaData);
}
}
Expand Up @@ -19,12 +19,12 @@

package org.elasticsearch.search.aggregations.metrics;


import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.ParsedAggregation;
import org.elasticsearch.search.aggregations.metrics.max.InternalMax;
import org.elasticsearch.search.aggregations.metrics.max.ParsedMax;
import org.elasticsearch.search.aggregations.metrics.min.InternalMin;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;

import java.util.List;
Expand Down
Expand Up @@ -32,7 +32,7 @@ public class InternalAvgTests extends InternalAggregationTestCase<InternalAvg> {

@Override
protected InternalAvg createTestInstance(String name, List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
DocValueFormat formatter = randomFrom(new DocValueFormat.Decimal("###.##"), DocValueFormat.BOOLEAN, DocValueFormat.RAW);
DocValueFormat formatter = randomNumericDocValueFormat();
long count = frequently() ? randomNonNegativeLong() % 100000 : 0;
return new InternalAvg(name, randomDoubleBetween(0, 100000, true), count, formatter, pipelineAggregators, metaData);
}
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.elasticsearch.search.aggregations.metrics.min;

import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.ParsedAggregation;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
Expand All @@ -31,7 +32,7 @@ public class InternalMinTests extends InternalAggregationTestCase<InternalMin> {
@Override
protected InternalMin createTestInstance(String name, List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
double value = frequently() ? randomDouble() : randomFrom(new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY });
DocValueFormat formatter = randomFrom(new DocValueFormat.Decimal("###.##"), DocValueFormat.BOOLEAN, DocValueFormat.RAW);
DocValueFormat formatter = randomNumericDocValueFormat();
return new InternalMin(name, value, formatter, pipelineAggregators, metaData);
}

Expand Down
Expand Up @@ -19,12 +19,10 @@

package org.elasticsearch.search.aggregations.pipeline;

import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.ParsedAggregation;

import java.util.Collections;
import java.util.List;
import java.util.Map;

Expand Down
Expand Up @@ -19,13 +19,11 @@

package org.elasticsearch.search.aggregations.pipeline.derivative;

import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.ParsedAggregation;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;

import java.util.Collections;
import java.util.List;
import java.util.Map;

Expand Down

0 comments on commit 0910ebe

Please sign in to comment.