|
@@ -19,6 +19,7 @@
|
|
|
|
|
|
package org.elasticsearch.search.aggregations.metrics;
|
|
|
|
|
|
+import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.common.geo.GeoPoint;
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
import org.elasticsearch.script.MockScriptEngine;
|
|
@@ -28,8 +29,12 @@ import org.elasticsearch.script.ScriptModule;
|
|
|
import org.elasticsearch.script.ScriptService;
|
|
|
import org.elasticsearch.script.ScriptType;
|
|
|
import org.elasticsearch.search.aggregations.Aggregation.CommonFields;
|
|
|
+import org.elasticsearch.search.aggregations.InternalAggregation;
|
|
|
+import org.elasticsearch.search.aggregations.InternalAggregation.ReduceContext;
|
|
|
import org.elasticsearch.search.aggregations.ParsedAggregation;
|
|
|
+import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator.PipelineTree;
|
|
|
import org.elasticsearch.test.InternalAggregationTestCase;
|
|
|
+import org.elasticsearch.test.VersionUtils;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
@@ -41,6 +46,9 @@ import java.util.Map;
|
|
|
import java.util.function.Predicate;
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
+import static java.util.Collections.singletonList;
|
|
|
+import static org.hamcrest.Matchers.equalTo;
|
|
|
+
|
|
|
public class InternalScriptedMetricTests extends InternalAggregationTestCase<InternalScriptedMetric> {
|
|
|
|
|
|
private static final String REDUCE_SCRIPT_NAME = "reduceScript";
|
|
@@ -79,8 +87,27 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
|
|
|
if (hasReduceScript) {
|
|
|
reduceScript = new Script(ScriptType.INLINE, MockScriptEngine.NAME, REDUCE_SCRIPT_NAME, params);
|
|
|
}
|
|
|
- Object randomValue = randomValue(valueTypes, 0);
|
|
|
- return new InternalScriptedMetric(name, randomValue, reduceScript, metadata);
|
|
|
+ return new InternalScriptedMetric(name, randomAggregations(), reduceScript, metadata);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Object> randomAggregations() {
|
|
|
+ return randomList(randomBoolean() ? 1 : 5, this::randomAggregation);
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
|
+ private Object randomAggregation() {
|
|
|
+ int levels = randomIntBetween(1, 3);
|
|
|
+ Supplier[] valueTypes = new Supplier[levels];
|
|
|
+ for (int l = 0; l < levels; l++) {
|
|
|
+ if (l < levels - 1) {
|
|
|
+ valueTypes[l] = randomFrom(nestedValueSuppliers);
|
|
|
+ } else {
|
|
|
+ // the last one needs to be a leaf value, not map or
|
|
|
+ // list
|
|
|
+ valueTypes[l] = randomFrom(leafValueSuppliers);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return randomValue(valueTypes, 0);
|
|
|
}
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@@ -124,13 +151,23 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
|
|
|
InternalScriptedMetric firstAgg = inputs.get(0);
|
|
|
assertEquals(firstAgg.getName(), reduced.getName());
|
|
|
assertEquals(firstAgg.getMetadata(), reduced.getMetadata());
|
|
|
+ int size = (int) inputs.stream().mapToLong(i -> i.aggregationsList().size()).sum();
|
|
|
if (hasReduceScript) {
|
|
|
- assertEquals(inputs.size(), reduced.aggregation());
|
|
|
+ assertEquals(size, reduced.aggregation());
|
|
|
} else {
|
|
|
- assertEquals(inputs.size(), ((List<?>) reduced.aggregation()).size());
|
|
|
+ assertEquals(size, ((List<?>) reduced.aggregation()).size());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ protected InternalScriptedMetric createTestInstanceForXContent() {
|
|
|
+ InternalScriptedMetric aggregation = createTestInstance();
|
|
|
+ return (InternalScriptedMetric) aggregation.reduce(
|
|
|
+ singletonList(aggregation),
|
|
|
+ ReduceContext.forFinalReduction(null, mockScriptService(), null, PipelineTree.EMPTY)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
protected void assertFromXContent(InternalScriptedMetric aggregation, ParsedAggregation parsedAggregation) {
|
|
|
assertTrue(parsedAggregation instanceof ParsedScriptedMetric);
|
|
@@ -188,7 +225,7 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
|
|
|
@Override
|
|
|
protected InternalScriptedMetric mutateInstance(InternalScriptedMetric instance) throws IOException {
|
|
|
String name = instance.getName();
|
|
|
- Object value = instance.aggregation();
|
|
|
+ List<Object> aggregationsList = instance.aggregationsList();
|
|
|
Script reduceScript = instance.reduceScript;
|
|
|
Map<String, Object> metadata = instance.getMetadata();
|
|
|
switch (between(0, 3)) {
|
|
@@ -196,22 +233,7 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
|
|
|
name += randomAlphaOfLength(5);
|
|
|
break;
|
|
|
case 1:
|
|
|
- Object newValue = randomValue(valueTypes, 0);
|
|
|
- while ((newValue == null && value == null) || (newValue != null && newValue.equals(value))) {
|
|
|
- int levels = randomIntBetween(1, 3);
|
|
|
- Supplier[] valueTypes = new Supplier[levels];
|
|
|
- for (int i = 0; i < levels; i++) {
|
|
|
- if (i < levels - 1) {
|
|
|
- valueTypes[i] = randomFrom(nestedValueSuppliers);
|
|
|
- } else {
|
|
|
- // the last one needs to be a leaf value, not map or
|
|
|
- // list
|
|
|
- valueTypes[i] = randomFrom(leafValueSuppliers);
|
|
|
- }
|
|
|
- }
|
|
|
- newValue = randomValue(valueTypes, 0);
|
|
|
- }
|
|
|
- value = newValue;
|
|
|
+ aggregationsList = randomValueOtherThan(aggregationsList, this::randomAggregations);
|
|
|
break;
|
|
|
case 2:
|
|
|
reduceScript = new Script(ScriptType.INLINE, MockScriptEngine.NAME, REDUCE_SCRIPT_NAME + "-mutated", Collections.emptyMap());
|
|
@@ -227,6 +249,28 @@ public class InternalScriptedMetricTests extends InternalAggregationTestCase<Int
|
|
|
default:
|
|
|
throw new AssertionError("Illegal randomisation branch");
|
|
|
}
|
|
|
- return new InternalScriptedMetric(name, value, reduceScript, metadata);
|
|
|
+ return new InternalScriptedMetric(name, aggregationsList, reduceScript, metadata);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testOldSerialization() throws IOException {
|
|
|
+ // A single element list looks like a fully reduced agg
|
|
|
+ InternalScriptedMetric original = new InternalScriptedMetric("test", List.of("foo"), new Script("test"), null);
|
|
|
+ InternalScriptedMetric roundTripped = (InternalScriptedMetric) copyNamedWriteable(
|
|
|
+ original,
|
|
|
+ getNamedWriteableRegistry(),
|
|
|
+ InternalAggregation.class,
|
|
|
+ VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, VersionUtils.getPreviousVersion(Version.V_7_8_0))
|
|
|
+ );
|
|
|
+ assertThat(roundTripped, equalTo(original));
|
|
|
+
|
|
|
+ // A multi-element list looks like a non-reduced agg
|
|
|
+ InternalScriptedMetric unreduced = new InternalScriptedMetric("test", List.of("foo", "bar"), new Script("test"), null);
|
|
|
+ Exception e = expectThrows(IllegalArgumentException.class, () -> copyNamedWriteable(
|
|
|
+ unreduced,
|
|
|
+ getNamedWriteableRegistry(),
|
|
|
+ InternalAggregation.class,
|
|
|
+ VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, VersionUtils.getPreviousVersion(Version.V_7_8_0))
|
|
|
+ ));
|
|
|
+ assertThat(e.getMessage(), equalTo("scripted_metric doesn't support cross cluster search until 7.8.0"));
|
|
|
}
|
|
|
}
|