Skip to content

Add new-style block loader tests for constant_keyword, version, wildcard #126968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion test/framework/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ dependencies {

api "org.elasticsearch:mocksocket:${versions.mocksocket}"

testImplementation project(":modules:mapper-extras")
testImplementation project(':x-pack:plugin:core')
testImplementation project(':x-pack:plugin:mapper-unsigned-long')
testImplementation project(':x-pack:plugin:mapper-counted-keyword')
testImplementation project(":modules:mapper-extras")
testImplementation project(':x-pack:plugin:mapper-constant-keyword')
testImplementation project(':x-pack:plugin:wildcard')
}

sourceSets {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.elasticsearch.logsdb.datageneration.datasource.DataSource;
import org.elasticsearch.logsdb.datageneration.fields.leaf.BooleanFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.ByteFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.ConstantKeywordFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.CountedKeywordFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.DateFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.DoubleFieldDataGenerator;
Expand All @@ -26,6 +27,7 @@
import org.elasticsearch.logsdb.datageneration.fields.leaf.ShortFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.TextFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.UnsignedLongFieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.fields.leaf.WildcardFieldDataGenerator;

/**
* Lists all leaf field types that are supported for data generation by default.
Expand All @@ -46,7 +48,9 @@ public enum FieldType {
DATE("date"),
GEO_POINT("geo_point"),
TEXT("text"),
IP("ip");
IP("ip"),
CONSTANT_KEYWORD("constant_keyword"),
WILDCARD("wildcard");

private final String name;

Expand All @@ -56,7 +60,7 @@ public enum FieldType {

public FieldDataGenerator generator(String fieldName, DataSource dataSource) {
return switch (this) {
case KEYWORD -> new KeywordFieldDataGenerator(fieldName, dataSource);
case KEYWORD -> new KeywordFieldDataGenerator(dataSource);
case LONG -> new LongFieldDataGenerator(fieldName, dataSource);
case UNSIGNED_LONG -> new UnsignedLongFieldDataGenerator(fieldName, dataSource);
case INTEGER -> new IntegerFieldDataGenerator(fieldName, dataSource);
Expand All @@ -72,6 +76,8 @@ public FieldDataGenerator generator(String fieldName, DataSource dataSource) {
case GEO_POINT -> new GeoPointFieldDataGenerator(dataSource);
case TEXT -> new TextFieldDataGenerator(dataSource);
case IP -> new IpFieldDataGenerator(dataSource);
case CONSTANT_KEYWORD -> new ConstantKeywordFieldDataGenerator();
case WILDCARD -> new WildcardFieldDataGenerator(dataSource);
};
}

Expand All @@ -93,6 +99,8 @@ public static FieldType tryParse(String name) {
case "geo_point" -> FieldType.GEO_POINT;
case "text" -> FieldType.TEXT;
case "ip" -> FieldType.IP;
case "constant_keyword" -> FieldType.CONSTANT_KEYWORD;
case "wildcard" -> FieldType.WILDCARD;
default -> null;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ default DataSourceResponse.IpGenerator handle(DataSourceRequest.IpGenerator requ
return null;
}

default DataSourceResponse.VersionStringGenerator handle(DataSourceRequest.VersionStringGenerator request) {
return null;
}

default DataSourceResponse.NullWrapper handle(DataSourceRequest.NullWrapper request) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ public DataSourceResponse.IpGenerator accept(DataSourceHandler handler) {
}
}

record VersionStringGenerator() implements DataSourceRequest<DataSourceResponse.VersionStringGenerator> {
public DataSourceResponse.VersionStringGenerator accept(DataSourceHandler handler) {
return handler.handle(this);
}
}

record NullWrapper() implements DataSourceRequest<DataSourceResponse.NullWrapper> {
public DataSourceResponse.NullWrapper accept(DataSourceHandler handler) {
return handler.handle(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ record GeoPointGenerator(Supplier<Object> generator) implements DataSourceRespon

record IpGenerator(Supplier<InetAddress> generator) implements DataSourceResponse {}

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

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

record ArrayWrapper(Function<Supplier<Object>, Supplier<Object>> wrapper) implements DataSourceResponse {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public DataSourceResponse.LeafMappingParametersGenerator handle(DataSourceReques
case GEO_POINT -> geoPointMapping(map);
case TEXT -> textMapping(request, new HashMap<>());
case IP -> ipMapping(map);
case CONSTANT_KEYWORD -> constantKeywordMapping(new HashMap<>());
case WILDCARD -> wildcardMapping(new HashMap<>());
});
}

Expand Down Expand Up @@ -225,6 +227,29 @@ private Supplier<Map<String, Object>> ipMapping(Map<String, Object> injected) {
};
}

private Supplier<Map<String, Object>> constantKeywordMapping(Map<String, Object> injected) {
return () -> {
// value is optional and can be set from the first document
// we don't cover this case here
injected.put("value", ESTestCase.randomAlphaOfLengthBetween(0, 10));

return injected;
};
}

private Supplier<Map<String, Object>> wildcardMapping(Map<String, Object> injected) {
return () -> {
if (ESTestCase.randomDouble() <= 0.2) {
injected.put("ignore_above", ESTestCase.randomIntBetween(1, 100));
}
if (ESTestCase.randomDouble() <= 0.2) {
injected.put("null_value", ESTestCase.randomAlphaOfLengthBetween(0, 10));
}

return injected;
};
}

private static HashMap<String, Object> commonMappingParameters() {
var map = new HashMap<String, Object>();
map.put("store", ESTestCase.randomBoolean());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.logsdb.datageneration.fields.leaf;

import org.elasticsearch.logsdb.datageneration.FieldDataGenerator;

import java.util.Map;

public class ConstantKeywordFieldDataGenerator implements FieldDataGenerator {
@Override
public Object generateValue(Map<String, Object> fieldMapping) {
if (fieldMapping == null) {
// Dynamically mapped, skip it because it will be mapped as text, and we cover this case already
return null;
}

var value = fieldMapping.get("value");
assert value != null;

return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@
import org.elasticsearch.logsdb.datageneration.datasource.DataSource;
import org.elasticsearch.logsdb.datageneration.datasource.DataSourceRequest;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

public class CountedKeywordFieldDataGenerator implements FieldDataGenerator {
private final Supplier<Object> valueGenerator;
private final Set<String> previousStrings = new HashSet<>();

public CountedKeywordFieldDataGenerator(String fieldName, DataSource dataSource) {
var strings = dataSource.get(new DataSourceRequest.StringGenerator());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
public class KeywordFieldDataGenerator implements FieldDataGenerator {
private final Supplier<Object> valueGenerator;

public KeywordFieldDataGenerator(String fieldName, DataSource dataSource) {
public KeywordFieldDataGenerator(DataSource dataSource) {
var strings = dataSource.get(new DataSourceRequest.StringGenerator());
var nulls = dataSource.get(new DataSourceRequest.NullWrapper());
var arrays = dataSource.get(new DataSourceRequest.ArrayWrapper());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.logsdb.datageneration.fields.leaf;

import org.elasticsearch.logsdb.datageneration.FieldDataGenerator;
import org.elasticsearch.logsdb.datageneration.datasource.DataSource;

import java.util.Map;

public class WildcardFieldDataGenerator implements FieldDataGenerator {
private final FieldDataGenerator keywordGenerator;

public WildcardFieldDataGenerator(DataSource dataSource) {
this.keywordGenerator = new KeywordFieldDataGenerator(dataSource);
}

@Override
public Object generateValue(Map<String, Object> fieldMapping) {
return keywordGenerator.generateValue(fieldMapping);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ static Map<String, FieldSpecificMatcher> matchers(
return new HashMap<>() {
{
put("keyword", new KeywordMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("date", new DateMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("long", new NumberMatcher("long", actualMappings, actualSettings, expectedMappings, expectedSettings));
put("unsigned_long", new UnsignedLongMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("integer", new NumberMatcher("integer", actualMappings, actualSettings, expectedMappings, expectedSettings));
Expand All @@ -58,11 +57,14 @@ static Map<String, FieldSpecificMatcher> matchers(
put("scaled_float", new ScaledFloatMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("counted_keyword", new CountedKeywordMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("boolean", new BooleanMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("date", new DateMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("geo_shape", new ExactMatcher("geo_shape", actualMappings, actualSettings, expectedMappings, expectedSettings));
put("shape", new ExactMatcher("shape", actualMappings, actualSettings, expectedMappings, expectedSettings));
put("geo_point", new GeoPointMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("text", new TextMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("ip", new IpMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("constant_keyword", new ConstantKeywordMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
put("wildcard", new WildcardMatcher(actualMappings, actualSettings, expectedMappings, expectedSettings));
}
};
}
Expand Down Expand Up @@ -691,6 +693,46 @@ Object convert(Object value, Object nullValue) {
}
}

class ConstantKeywordMatcher extends GenericMappingAwareMatcher {
ConstantKeywordMatcher(
XContentBuilder actualMappings,
Settings.Builder actualSettings,
XContentBuilder expectedMappings,
Settings.Builder expectedSettings
) {
super("constant_keyword", actualMappings, actualSettings, expectedMappings, expectedSettings);
}

@Override
Object convert(Object value, Object nullValue) {
// We just need to get rid of literal `null`s which is done in the caller.
return value;
}
}

class WildcardMatcher extends GenericMappingAwareMatcher {
WildcardMatcher(
XContentBuilder actualMappings,
Settings.Builder actualSettings,
XContentBuilder expectedMappings,
Settings.Builder expectedSettings
) {
super("wildcard", actualMappings, actualSettings, expectedMappings, expectedSettings);
}

@Override
Object convert(Object value, Object nullValue) {
if (value == null) {
if (nullValue != null) {
return nullValue;
}
return null;
}

return value;
}
}

/**
* Generic matcher that supports common matching logic like null values.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xpack.constantkeyword.ConstantKeywordMapperPlugin;
import org.elasticsearch.xpack.countedkeyword.CountedKeywordMapperPlugin;
import org.elasticsearch.xpack.unsignedlong.UnsignedLongMapperPlugin;
import org.elasticsearch.xpack.wildcard.Wildcard;

import java.io.IOException;
import java.util.Collection;
Expand Down Expand Up @@ -111,7 +113,13 @@ public DataSourceResponse.FieldTypeGenerator handle(DataSourceRequest.FieldTypeG
var mappingService = new MapperServiceTestCase() {
@Override
protected Collection<? extends Plugin> getPlugins() {
return List.of(new UnsignedLongMapperPlugin(), new MapperExtrasPlugin(), new CountedKeywordMapperPlugin());
return List.of(
new UnsignedLongMapperPlugin(),
new MapperExtrasPlugin(),
new CountedKeywordMapperPlugin(),
new ConstantKeywordMapperPlugin(),
new Wildcard()
);
}
}.createMapperService(mappingXContent);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.constantkeyword.mapper;

import org.apache.lucene.util.BytesRef;
import org.elasticsearch.index.mapper.BlockLoaderTestCase;
import org.elasticsearch.logsdb.datageneration.FieldType;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.xpack.constantkeyword.ConstantKeywordMapperPlugin;

import java.util.Collection;
import java.util.List;
import java.util.Map;

public class ConstantKeywordFieldBlockLoaderTests extends BlockLoaderTestCase {
public ConstantKeywordFieldBlockLoaderTests(Params params) {
super(FieldType.CONSTANT_KEYWORD.toString(), params);
}

@Override
protected Object expected(Map<String, Object> fieldMapping, Object value, TestContext testContext) {
return new BytesRef((String) fieldMapping.get("value"));
}

@Override
protected Collection<Plugin> getPlugins() {
return List.of(new ConstantKeywordMapperPlugin());
}
}
Loading