Skip to content

Commit 4c46059

Browse files
committed
Add block loader tests for aggregate_metric_double
1 parent cf600e5 commit 4c46059

File tree

8 files changed

+204
-6
lines changed

8 files changed

+204
-6
lines changed

test/framework/src/main/java/org/elasticsearch/index/mapper/TestBlock.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.io.IOException;
1717
import java.io.UncheckedIOException;
1818
import java.util.ArrayList;
19+
import java.util.HashMap;
1920
import java.util.List;
2021

2122
import static org.junit.Assert.assertNotNull;
@@ -292,12 +293,29 @@ public BlockLoader.IntBuilder count() {
292293

293294
@Override
294295
public BlockLoader.Block build() {
295-
var minBlock = max.build();
296+
var minBlock = min.build();
296297
var maxBlock = max.build();
297-
var sumBlock = max.build();
298-
var countBlock = max.build();
298+
var sumBlock = sum.build();
299+
var countBlock = count.build();
299300

300-
return new TestBlock(null);
301+
assert minBlock.size() == maxBlock.size();
302+
assert maxBlock.size() == sumBlock.size();
303+
assert sumBlock.size() == countBlock.size();
304+
305+
var values = new ArrayList<>(minBlock.size());
306+
307+
for (int i = 0; i < minBlock.size(); i++) {
308+
// we need to represent this complex block somehow
309+
var value = new HashMap<String, Object>();
310+
value.put("min", minBlock.values.get(i));
311+
value.put("max", maxBlock.values.get(i));
312+
value.put("sum", sumBlock.values.get(i));
313+
value.put("value_count", countBlock.values.get(i));
314+
315+
values.add(value);
316+
}
317+
318+
return new TestBlock(values);
301319
}
302320

303321
@Override

test/framework/src/main/java/org/elasticsearch/logsdb/datageneration/datasource/DataSourceHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ default DataSourceResponse.VersionStringGenerator handle(DataSourceRequest.Versi
8282
return null;
8383
}
8484

85+
default DataSourceResponse.AggregateMetricDoubleGenerator handle(DataSourceRequest.AggregateMetricDoubleGenerator request) {
86+
return null;
87+
}
88+
8589
default DataSourceResponse.NullWrapper handle(DataSourceRequest.NullWrapper request) {
8690
return null;
8791
}

test/framework/src/main/java/org/elasticsearch/logsdb/datageneration/datasource/DataSourceRequest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ public DataSourceResponse.VersionStringGenerator accept(DataSourceHandler handle
132132
}
133133
}
134134

135+
record AggregateMetricDoubleGenerator() implements DataSourceRequest<DataSourceResponse.AggregateMetricDoubleGenerator> {
136+
public DataSourceResponse.AggregateMetricDoubleGenerator accept(DataSourceHandler handler) {
137+
return handler.handle(this);
138+
}
139+
}
140+
135141
record NullWrapper() implements DataSourceRequest<DataSourceResponse.NullWrapper> {
136142
public DataSourceResponse.NullWrapper accept(DataSourceHandler handler) {
137143
return handler.handle(this);

test/framework/src/main/java/org/elasticsearch/logsdb/datageneration/datasource/DataSourceResponse.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ record IpGenerator(Supplier<InetAddress> generator) implements DataSourceRespons
5555

5656
record VersionStringGenerator(Supplier<String> generator) implements DataSourceResponse {}
5757

58+
record AggregateMetricDoubleGenerator(Supplier<Map<String, Number>> generator) implements DataSourceResponse {}
59+
5860
record NullWrapper(Function<Supplier<Object>, Supplier<Object>> wrapper) implements DataSourceResponse {}
5961

6062
record ArrayWrapper(Function<Supplier<Object>, Supplier<Object>> wrapper) implements DataSourceResponse {}

x-pack/plugin/mapper-aggregate-metric/src/main/java/org/elasticsearch/xpack/aggregatemetric/mapper/AggregateMetricDoubleFieldMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,7 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
851851
// by its FieldMapper#parse()
852852
throw e;
853853
}
854+
854855
for (Map.Entry<Metric, Number> parsed : metricsParsed.entrySet()) {
855856
NumberFieldMapper delegateFieldMapper = metricFieldMappers.get(parsed.getKey());
856857
delegateFieldMapper.indexValue(context, parsed.getValue());

x-pack/plugin/mapper-aggregate-metric/src/test/java/org/elasticsearch/xpack/aggregatemetric/mapper/AggregateMetricDoubleFieldBlockLoaderTests.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,56 @@
88
package org.elasticsearch.xpack.aggregatemetric.mapper;
99

1010
import org.elasticsearch.index.mapper.BlockLoaderTestCase;
11+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceHandler;
12+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceRequest;
13+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceResponse;
1114
import org.elasticsearch.plugins.Plugin;
1215
import org.elasticsearch.xpack.aggregatemetric.AggregateMetricMapperPlugin;
16+
import org.elasticsearch.xpack.aggregatemetric.mapper.datageneration.AggregateMetricDoubleDataSourceHandler;
1317

18+
import java.util.Arrays;
1419
import java.util.Collection;
20+
import java.util.HashMap;
1521
import java.util.List;
1622
import java.util.Map;
23+
import java.util.Optional;
1724

1825
public class AggregateMetricDoubleFieldBlockLoaderTests extends BlockLoaderTestCase {
1926
public AggregateMetricDoubleFieldBlockLoaderTests(Params params) {
20-
super("aggregate_metric_double", params);
27+
super("aggregate_metric_double", List.of(new AggregateMetricDoubleDataSourceHandler(), new DataSourceHandler() {
28+
@Override
29+
public DataSourceResponse.ObjectArrayGenerator handle(DataSourceRequest.ObjectArrayGenerator request) {
30+
// aggregate_metric_double does not support multiple values in a document so we can't have object arrays
31+
return new DataSourceResponse.ObjectArrayGenerator(Optional::empty);
32+
}
33+
}), params);
2134
}
2235

2336
@Override
2437
protected Object expected(Map<String, Object> fieldMapping, Object value, TestContext testContext) {
25-
return null;
38+
if (value instanceof Map<?, ?> map) {
39+
var expected = new HashMap<String, Object>(map.size());
40+
41+
// put explicit `null` for metrics that are not present, this is how the block looks like
42+
Arrays.stream(AggregateMetricDoubleFieldMapper.Metric.values())
43+
.map(AggregateMetricDoubleFieldMapper.Metric::toString)
44+
.sorted()
45+
.forEach(m -> {
46+
expected.put(m, map.get(m));
47+
});
48+
49+
return expected;
50+
}
51+
52+
// malformed or null, return "empty row"
53+
return new HashMap<>() {
54+
{
55+
put("min", null);
56+
put("max", null);
57+
put("sum", null);
58+
put("value_count", null);
59+
}
60+
};
2661
}
2762

2863
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.aggregatemetric.mapper.datageneration;
9+
10+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceHandler;
11+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceRequest;
12+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceResponse;
13+
import org.elasticsearch.test.ESTestCase;
14+
import org.elasticsearch.xpack.aggregatemetric.mapper.AggregateMetricDoubleFieldMapper;
15+
16+
import java.util.Arrays;
17+
import java.util.HashMap;
18+
import java.util.List;
19+
20+
public class AggregateMetricDoubleDataSourceHandler implements DataSourceHandler {
21+
@Override
22+
public DataSourceResponse.AggregateMetricDoubleGenerator handle(DataSourceRequest.AggregateMetricDoubleGenerator request) {
23+
return new DataSourceResponse.AggregateMetricDoubleGenerator(() -> {
24+
var metricContainer = new HashMap<String, Number>();
25+
26+
// min and max must make sense - max has to be gte min
27+
double min = ESTestCase.randomDoubleBetween(-Double.MAX_VALUE, 1_000_000_000, false);
28+
double max = ESTestCase.randomDoubleBetween(min, Double.MAX_VALUE, true);
29+
30+
metricContainer.put("min", min);
31+
metricContainer.put("max", max);
32+
metricContainer.put("sum", ESTestCase.randomDouble());
33+
metricContainer.put("value_count", ESTestCase.randomIntBetween(1, Integer.MAX_VALUE));
34+
35+
return metricContainer;
36+
});
37+
}
38+
39+
@Override
40+
public DataSourceResponse.LeafMappingParametersGenerator handle(DataSourceRequest.LeafMappingParametersGenerator request) {
41+
if (request.fieldType().equals("aggregate_metric_double") == false) {
42+
return null;
43+
}
44+
45+
return new DataSourceResponse.LeafMappingParametersGenerator(() -> {
46+
var map = new HashMap<String, Object>();
47+
48+
List<AggregateMetricDoubleFieldMapper.Metric> metrics = ESTestCase.randomNonEmptySubsetOf(
49+
Arrays.asList(AggregateMetricDoubleFieldMapper.Metric.values())
50+
);
51+
52+
map.put("metrics", metrics.stream().map(Enum::toString).toList());
53+
map.put("default_metric", metrics.get(ESTestCase.randomIntBetween(0, metrics.size() - 1)));
54+
55+
if (ESTestCase.randomBoolean()) {
56+
map.put("ignore_malformed", ESTestCase.randomBoolean());
57+
}
58+
59+
return map;
60+
});
61+
}
62+
63+
@Override
64+
public DataSourceResponse.FieldDataGenerator handle(DataSourceRequest.FieldDataGenerator request) {
65+
if (request.fieldType().equals("aggregate_metric_double") == false) {
66+
return null;
67+
}
68+
69+
return new DataSourceResponse.FieldDataGenerator(new AggregateMetricDoubleFieldDataGenerator(request.dataSource()));
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.aggregatemetric.mapper.datageneration;
9+
10+
import org.elasticsearch.logsdb.datageneration.FieldDataGenerator;
11+
import org.elasticsearch.logsdb.datageneration.datasource.DataSource;
12+
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceRequest;
13+
14+
import java.util.HashMap;
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.function.Function;
18+
import java.util.function.Supplier;
19+
20+
public class AggregateMetricDoubleFieldDataGenerator implements FieldDataGenerator {
21+
private final Supplier<Map<String, Number>> metrics;
22+
private final Function<Supplier<Object>, Supplier<Object>> nullWrapper;
23+
private final Function<Supplier<Object>, Supplier<Object>> nullAndMalformedWrapper;
24+
25+
public AggregateMetricDoubleFieldDataGenerator(DataSource dataSource) {
26+
this.metrics = dataSource.get(new DataSourceRequest.AggregateMetricDoubleGenerator()).generator();
27+
28+
this.nullWrapper = dataSource.get(new DataSourceRequest.NullWrapper()).wrapper();
29+
30+
var strings = dataSource.get(new DataSourceRequest.StringGenerator()).generator();
31+
var malformed = dataSource.get(new DataSourceRequest.MalformedWrapper(strings::get)).wrapper();
32+
this.nullAndMalformedWrapper = malformed.andThen(nullWrapper);
33+
}
34+
35+
@Override
36+
@SuppressWarnings("unchecked")
37+
public Object generateValue(Map<String, Object> fieldMapping) {
38+
if (fieldMapping == null) {
39+
// this field can't be properly mapped with dynamic mapping
40+
return null;
41+
}
42+
43+
// metrics returned have all metric fields but we only need those that appear in the mapping
44+
Supplier<Object> metricsAdjustedForMapping = () -> {
45+
var metric = metrics.get();
46+
47+
var adjusted = new HashMap<String, Number>();
48+
for (var metricName : (List<String>) fieldMapping.get("metrics")) {
49+
adjusted.put(metricName, metric.get(metricName));
50+
}
51+
52+
return adjusted;
53+
};
54+
55+
if ((Boolean) fieldMapping.getOrDefault("ignore_malformed", false)) {
56+
return nullAndMalformedWrapper.apply(metricsAdjustedForMapping).get();
57+
}
58+
59+
return nullWrapper.apply(metricsAdjustedForMapping).get();
60+
}
61+
}

0 commit comments

Comments
 (0)