diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java b/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java index c7f84fe6577..465cef30877 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/Aggregations.java @@ -128,7 +128,6 @@ public class Aggregations implements Iterable, ToXContent { return builder; } - //TODO add tests for this method public static Aggregations fromXContent(XContentParser parser) throws IOException { final List aggregations = new ArrayList<>(); XContentParser.Token token; diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java new file mode 100644 index 00000000000..84d11db3dbe --- /dev/null +++ b/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java @@ -0,0 +1,156 @@ +/* + * 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; + +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.rest.action.search.RestSearchAction; +import org.elasticsearch.search.aggregations.bucket.InternalSingleBucketAggregationTestCase; +import org.elasticsearch.search.aggregations.bucket.histogram.InternalDateHistogramTests; +import org.elasticsearch.search.aggregations.bucket.histogram.InternalHistogramTests; +import org.elasticsearch.search.aggregations.metrics.InternalExtendedStatsTests; +import org.elasticsearch.search.aggregations.metrics.InternalMaxTests; +import org.elasticsearch.search.aggregations.metrics.InternalStatsBucketTests; +import org.elasticsearch.search.aggregations.metrics.InternalStatsTests; +import org.elasticsearch.search.aggregations.metrics.avg.InternalAvgTests; +import org.elasticsearch.search.aggregations.metrics.cardinality.InternalCardinalityTests; +import org.elasticsearch.search.aggregations.metrics.geobounds.InternalGeoBoundsTests; +import org.elasticsearch.search.aggregations.metrics.geocentroid.InternalGeoCentroidTests; +import org.elasticsearch.search.aggregations.metrics.min.InternalMinTests; +import org.elasticsearch.search.aggregations.metrics.percentiles.hdr.InternalHDRPercentilesRanksTests; +import org.elasticsearch.search.aggregations.metrics.percentiles.hdr.InternalHDRPercentilesTests; +import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.InternalTDigestPercentilesRanksTests; +import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.InternalTDigestPercentilesTests; +import org.elasticsearch.search.aggregations.metrics.sum.InternalSumTests; +import org.elasticsearch.search.aggregations.metrics.valuecount.InternalValueCountTests; +import org.elasticsearch.search.aggregations.pipeline.InternalSimpleValueTests; +import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.InternalBucketMetricValueTests; +import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.percentile.InternalPercentilesBucketTests; +import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.stats.extended.InternalExtendedStatsBucketTests; +import org.elasticsearch.search.aggregations.pipeline.derivative.InternalDerivativeTests; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.hamcrest.ElasticsearchAssertions; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static java.util.Collections.singletonMap; + +/** + * This class tests that aggregations parsing works properly. It checks that we can parse + * different aggregations and adds sub-aggregations where applicable. + * + */ +public class AggregationsTests extends ESTestCase { + + private static final List aggsTests = getAggsTests(); + + private static List getAggsTests() { + List aggsTests = new ArrayList<>(); + aggsTests.add(new InternalCardinalityTests()); + aggsTests.add(new InternalTDigestPercentilesTests()); + aggsTests.add(new InternalTDigestPercentilesRanksTests()); + aggsTests.add(new InternalHDRPercentilesTests()); + aggsTests.add(new InternalHDRPercentilesRanksTests()); + aggsTests.add(new InternalPercentilesBucketTests()); + aggsTests.add(new InternalMinTests()); + aggsTests.add(new InternalMaxTests()); + aggsTests.add(new InternalAvgTests()); + aggsTests.add(new InternalSumTests()); + aggsTests.add(new InternalValueCountTests()); + aggsTests.add(new InternalSimpleValueTests()); + aggsTests.add(new InternalDerivativeTests()); + aggsTests.add(new InternalBucketMetricValueTests()); + aggsTests.add(new InternalStatsTests()); + aggsTests.add(new InternalStatsBucketTests()); + aggsTests.add(new InternalExtendedStatsTests()); + aggsTests.add(new InternalExtendedStatsBucketTests()); + aggsTests.add(new InternalGeoBoundsTests()); + aggsTests.add(new InternalGeoCentroidTests()); + aggsTests.add(new InternalHistogramTests()); + aggsTests.add(new InternalDateHistogramTests()); + return Collections.unmodifiableList(aggsTests); + } + + @Override + protected NamedXContentRegistry xContentRegistry() { + return new NamedXContentRegistry(InternalAggregationTestCase.getNamedXContents()); + } + + @Before + public void init() throws Exception { + for (InternalAggregationTestCase aggsTest : aggsTests) { + aggsTest.setUp(); + } + } + + @After + public void cleanUp() throws Exception { + for (InternalAggregationTestCase aggsTest : aggsTests) { + aggsTest.tearDown(); + } + } + + public void testFromXContent() throws IOException { + XContentType xContentType = randomFrom(XContentType.values()); + final ToXContent.Params params = new ToXContent.MapParams(singletonMap(RestSearchAction.TYPED_KEYS_PARAM, "true")); + Aggregations aggregations = createTestInstance(); + BytesReference originalBytes = toShuffledXContent(aggregations, xContentType, params, randomBoolean()); + try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) { + assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken()); + assertEquals(XContentParser.Token.FIELD_NAME, parser.nextToken()); + assertEquals(Aggregations.AGGREGATIONS_FIELD, parser.currentName()); + assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken()); + Aggregations parsedAggregations = Aggregations.fromXContent(parser); + BytesReference parsedBytes = XContentHelper.toXContent(parsedAggregations, xContentType, randomBoolean()); + ElasticsearchAssertions.assertToXContentEquivalent(originalBytes, parsedBytes, xContentType); + } + } + + private static InternalAggregations createTestInstance() { + return createTestInstance(0, 5); + } + + private static InternalAggregations createTestInstance(final int currentDepth, final int maxDepth) { + int numAggs = randomIntBetween(1, 5); + List aggs = new ArrayList<>(numAggs); + for (int i = 0; i < numAggs; i++) { + InternalAggregationTestCase testCase = randomFrom(aggsTests); + if (testCase instanceof InternalMultiBucketAggregationTestCase && currentDepth < maxDepth) { + InternalMultiBucketAggregationTestCase multiBucketAggTestCase = (InternalMultiBucketAggregationTestCase) testCase; + multiBucketAggTestCase.subAggregationsSupplier = () -> createTestInstance(currentDepth + 1, maxDepth); + } + if (testCase instanceof InternalSingleBucketAggregationTestCase && currentDepth < maxDepth) { + InternalSingleBucketAggregationTestCase singleBucketAggTestCase = (InternalSingleBucketAggregationTestCase) testCase; + singleBucketAggTestCase.subAggregationsSupplier = () -> createTestInstance(currentDepth + 1, maxDepth); + } + aggs.add(testCase.createTestInstance()); + } + return new InternalAggregations(aggs); + } +} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java index ae293d5ac31..64eee02dcb6 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java @@ -21,36 +21,42 @@ package org.elasticsearch.search.aggregations; import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; -import org.junit.Before; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Supplier; +import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; public abstract class InternalMultiBucketAggregationTestCase extends InternalAggregationTestCase { - private boolean hasSubAggregations; + Supplier subAggregationsSupplier; - @Before - public void initHasSubAggregations() { - hasSubAggregations = randomBoolean(); + @Override + public void setUp() throws Exception { + super.setUp(); + if (randomBoolean()) { + subAggregationsSupplier = () -> InternalAggregations.EMPTY; + } else { + subAggregationsSupplier = () -> { + final int numAggregations = randomIntBetween(1, 3); + List aggs = new ArrayList<>(); + for (int i = 0; i < numAggregations; i++) { + aggs.add(createTestInstance(randomAlphaOfLength(5), emptyList(), emptyMap(), InternalAggregations.EMPTY)); + } + return new InternalAggregations(aggs); + }; + } } @Override protected final T createTestInstance(String name, List pipelineAggregators, Map metaData) { - List internal = new ArrayList<>(); - if (hasSubAggregations) { - final int numAggregations = randomIntBetween(1, 3); - for (int i = 0; i pipelineAggregators, diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java index 5d2e8affe78..a31b28e7fdb 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregationTestCase.java @@ -29,31 +29,43 @@ import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; public abstract class InternalSingleBucketAggregationTestCase extends InternalAggregationTestCase { + private final boolean hasInternalMax = randomBoolean(); private final boolean hasInternalMin = randomBoolean(); + public Supplier subAggregationsSupplier; + + @Override + public void setUp() throws Exception { + super.setUp(); + subAggregationsSupplier = () -> { + List aggs = new ArrayList<>(); + if (hasInternalMax) { + aggs.add(new InternalMax("max", randomDouble(), randomNumericDocValueFormat(), emptyList(), emptyMap())); + } + if (hasInternalMin) { + aggs.add(new InternalMin("min", randomDouble(), randomNumericDocValueFormat(), emptyList(), emptyMap())); + } + return new InternalAggregations(aggs); + }; + } + protected abstract T createTestInstance(String name, long docCount, InternalAggregations aggregations, List pipelineAggregators, Map metaData); protected abstract void extraAssertReduced(T reduced, List inputs); @Override protected final T createTestInstance(String name, List pipelineAggregators, Map metaData) { - List 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); + return createTestInstance(name, docCount, subAggregationsSupplier.get(), pipelineAggregators, metaData); } @Override diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalDateHistogramTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalDateHistogramTests.java index c4410713ac8..0b71d138a57 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalDateHistogramTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalDateHistogramTests.java @@ -26,7 +26,6 @@ import org.elasticsearch.search.aggregations.InternalMultiBucketAggregationTestC import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.joda.time.DateTime; -import org.junit.Before; import java.util.ArrayList; import java.util.List; @@ -42,8 +41,9 @@ public class InternalDateHistogramTests extends InternalMultiBucketAggregationTe private boolean keyed; private DocValueFormat format; - @Before - public void init() { + @Override + public void setUp() throws Exception { + super.setUp(); keyed = randomBoolean(); format = randomNumericDocValueFormat(); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalHistogramTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalHistogramTests.java index bfcfe78ff7d..4f0fea87d63 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalHistogramTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalHistogramTests.java @@ -22,12 +22,10 @@ package org.elasticsearch.search.aggregations.bucket.histogram; import org.apache.lucene.util.TestUtil; import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.search.DocValueFormat; -import org.elasticsearch.search.aggregations.InternalAggregationTestCase; import org.elasticsearch.search.aggregations.InternalAggregations; import org.elasticsearch.search.aggregations.InternalMultiBucketAggregationTestCase; import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; -import org.junit.Before; import java.util.ArrayList; import java.util.List; @@ -39,8 +37,9 @@ public class InternalHistogramTests extends InternalMultiBucketAggregationTestCa private boolean keyed; private DocValueFormat format; - @Before - public void init() { + @Override + public void setUp() throws Exception{ + super.setUp(); keyed = randomBoolean(); format = randomNumericDocValueFormat(); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalMaxTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalMaxTests.java index 53483be55c0..1d3a8b45a11 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalMaxTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/InternalMaxTests.java @@ -34,7 +34,7 @@ public class InternalMaxTests extends InternalAggregationTestCase { @Override protected InternalMax createTestInstance(String name, List pipelineAggregators, Map metaData) { - double value = frequently() ? randomDouble() : randomFrom(new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY }); + double value = frequently() ? randomDouble() : randomFrom(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); DocValueFormat formatter = randomNumericDocValueFormat(); return new InternalMax(name, value, formatter, pipelineAggregators, metaData); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/cardinality/InternalCardinalityTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/cardinality/InternalCardinalityTests.java index efa5438ae3c..60f0179d9a1 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/cardinality/InternalCardinalityTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/cardinality/InternalCardinalityTests.java @@ -28,7 +28,6 @@ import org.elasticsearch.search.aggregations.InternalAggregationTestCase; import org.elasticsearch.search.aggregations.ParsedAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.junit.After; -import org.junit.Before; import java.util.ArrayList; import java.util.List; @@ -38,12 +37,22 @@ public class InternalCardinalityTests extends InternalAggregationTestCase algos; private static int p; - @Before - public void setup() { + @Override + public void setUp() throws Exception { + super.setUp(); algos = new ArrayList<>(); p = randomIntBetween(HyperLogLogPlusPlus.MIN_PRECISION, HyperLogLogPlusPlus.MAX_PRECISION); } + @After //we force @After to have it run before ESTestCase#after otherwise it fails + @Override + public void tearDown() throws Exception { + super.tearDown(); + Releasables.close(algos); + algos.clear(); + algos = null; + } + @Override protected InternalCardinality createTestInstance(String name, List pipelineAggregators, Map metaData) { @@ -82,11 +91,4 @@ public class InternalCardinalityTests extends InternalAggregationTestCase