This prevent `keyword` valued runtime scripts from emitting too many values or values that take up too much space. Without this you can put allocate a ton of memory with the script by sticking it into a tight loop. Painless has some protections against this but: 1. I don't want to rely on them out of sheer paranoia 2. They don't really kick in when the script uses callbacks like we do anyway. Relates to #59332
This commit is contained in:
parent
1eb4595a29
commit
6d2cab9437
|
@ -19,8 +19,8 @@ public abstract class AbstractLongScriptFieldScript extends AbstractScriptFieldS
|
|||
private long[] values = new long[1];
|
||||
private int count;
|
||||
|
||||
public AbstractLongScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public AbstractLongScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,6 +50,7 @@ public abstract class AbstractLongScriptFieldScript extends AbstractScriptFieldS
|
|||
}
|
||||
|
||||
protected final void emitValue(long v) {
|
||||
checkMaxSize(count);
|
||||
if (values.length < count + 1) {
|
||||
values = ArrayUtil.grow(values, count + 1);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.search.lookup.SearchLookup;
|
|||
import org.elasticsearch.search.lookup.SourceLookup;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -27,6 +28,11 @@ import static org.elasticsearch.common.unit.TimeValue.timeValueMillis;
|
|||
* {@link AggregationScript} but hopefully with less historical baggage.
|
||||
*/
|
||||
public abstract class AbstractScriptFieldScript {
|
||||
/**
|
||||
* The maximum number of values a script should be allowed to emit.
|
||||
*/
|
||||
static final int MAX_VALUES = 100;
|
||||
|
||||
public static <F> ScriptContext<F> newContext(String name, Class<F> factoryClass) {
|
||||
return new ScriptContext<F>(
|
||||
name + "_script_field",
|
||||
|
@ -54,10 +60,12 @@ public abstract class AbstractScriptFieldScript {
|
|||
value -> ((SourceLookup) value).loadSourceIfNeeded()
|
||||
);
|
||||
|
||||
protected final String fieldName;
|
||||
private final Map<String, Object> params;
|
||||
private final LeafSearchLookup leafSearchLookup;
|
||||
|
||||
public AbstractScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
public AbstractScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
this.fieldName = fieldName;
|
||||
this.leafSearchLookup = searchLookup.getLeafSearchLookup(ctx);
|
||||
params = new HashMap<>(params);
|
||||
params.put("_source", leafSearchLookup.source());
|
||||
|
@ -94,5 +102,23 @@ public abstract class AbstractScriptFieldScript {
|
|||
return leafSearchLookup.doc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the we can add another value to the list of values.
|
||||
* @param currentSize the current size of the list
|
||||
*/
|
||||
protected final void checkMaxSize(int currentSize) {
|
||||
if (currentSize >= MAX_VALUES) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Runtime field [%s] is emitting [%s] values while the maximum number of values allowed is [%s]",
|
||||
fieldName,
|
||||
currentSize + 1,
|
||||
MAX_VALUES
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void execute();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public abstract class BooleanScriptFieldScript extends AbstractScriptFieldScript
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -41,8 +41,8 @@ public abstract class BooleanScriptFieldScript extends AbstractScriptFieldScript
|
|||
private int trues;
|
||||
private int falses;
|
||||
|
||||
public BooleanScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public BooleanScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,7 +31,7 @@ public abstract class DateScriptFieldScript extends AbstractLongScriptFieldScrip
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup, DateFormatter formatter);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, DateFormatter formatter);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -40,8 +40,14 @@ public abstract class DateScriptFieldScript extends AbstractLongScriptFieldScrip
|
|||
|
||||
private final DateFormatter formatter;
|
||||
|
||||
public DateScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, DateFormatter formatter, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public DateScriptFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
DateFormatter formatter,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public abstract class DoubleScriptFieldScript extends AbstractScriptFieldScript
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -41,8 +41,8 @@ public abstract class DoubleScriptFieldScript extends AbstractScriptFieldScript
|
|||
private double[] values = new double[1];
|
||||
private int count;
|
||||
|
||||
public DoubleScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public DoubleScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,6 +72,7 @@ public abstract class DoubleScriptFieldScript extends AbstractScriptFieldScript
|
|||
}
|
||||
|
||||
protected final void emitValue(double v) {
|
||||
checkMaxSize(count);
|
||||
if (values.length < count + 1) {
|
||||
values = ArrayUtil.grow(values, count + 1);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public abstract class IpScriptFieldScript extends AbstractScriptFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -60,8 +60,8 @@ public abstract class IpScriptFieldScript extends AbstractScriptFieldScript {
|
|||
private BytesRef[] values = new BytesRef[1];
|
||||
private int count;
|
||||
|
||||
public IpScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public IpScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,6 +94,7 @@ public abstract class IpScriptFieldScript extends AbstractScriptFieldScript {
|
|||
}
|
||||
|
||||
protected final void emitValue(String v) {
|
||||
checkMaxSize(count);
|
||||
if (values.length < count + 1) {
|
||||
values = ArrayUtil.grow(values, count + 1);
|
||||
}
|
||||
|
|
|
@ -28,15 +28,15 @@ public abstract class LongScriptFieldScript extends AbstractLongScriptFieldScrip
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
LongScriptFieldScript newInstance(LeafReaderContext ctx) throws IOException;
|
||||
}
|
||||
|
||||
public LongScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public LongScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
}
|
||||
|
||||
public static class EmitValue {
|
||||
|
|
|
@ -17,9 +17,15 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class StringScriptFieldScript extends AbstractScriptFieldScript {
|
||||
/**
|
||||
* The maximum number of chars a script should be allowed to emit.
|
||||
*/
|
||||
public static final long MAX_CHARS = 1024 * 1024;
|
||||
|
||||
public static final ScriptContext<Factory> CONTEXT = newContext("string_script_field", Factory.class);
|
||||
|
||||
static List<Whitelist> whitelist() {
|
||||
|
@ -31,7 +37,7 @@ public abstract class StringScriptFieldScript extends AbstractScriptFieldScript
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -39,9 +45,10 @@ public abstract class StringScriptFieldScript extends AbstractScriptFieldScript
|
|||
}
|
||||
|
||||
private final List<String> results = new ArrayList<>();
|
||||
private long chars;
|
||||
|
||||
public StringScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(params, searchLookup, ctx);
|
||||
public StringScriptFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,12 +59,26 @@ public abstract class StringScriptFieldScript extends AbstractScriptFieldScript
|
|||
*/
|
||||
public final List<String> resultsForDoc(int docId) {
|
||||
results.clear();
|
||||
chars = 0;
|
||||
setDocument(docId);
|
||||
execute();
|
||||
return results;
|
||||
}
|
||||
|
||||
protected final void emitValue(String v) {
|
||||
checkMaxSize(results.size());
|
||||
chars += v.length();
|
||||
if (chars > MAX_CHARS) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Runtime field [%s] is emitting [%s] characters while the maximum number of values allowed is [%s]",
|
||||
fieldName,
|
||||
chars,
|
||||
MAX_CHARS
|
||||
)
|
||||
);
|
||||
}
|
||||
results.add(v);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public class ScriptBooleanMappedFieldType extends AbstractScriptMappedFieldType
|
|||
}
|
||||
|
||||
private BooleanScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) {
|
||||
return scriptFactory.newFactory(script.getParams(), searchLookup);
|
||||
return scriptFactory.newFactory(name(), script.getParams(), searchLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -85,7 +85,7 @@ public class ScriptDateMappedFieldType extends AbstractScriptMappedFieldType {
|
|||
}
|
||||
|
||||
private DateScriptFieldScript.LeafFactory leafFactory(SearchLookup lookup) {
|
||||
return scriptFactory.newFactory(script.getParams(), lookup, dateTimeFormatter);
|
||||
return scriptFactory.newFactory(name(), script.getParams(), lookup, dateTimeFormatter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -64,7 +64,7 @@ public class ScriptDoubleMappedFieldType extends AbstractScriptMappedFieldType {
|
|||
}
|
||||
|
||||
private DoubleScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) {
|
||||
return scriptFactory.newFactory(script.getParams(), searchLookup);
|
||||
return scriptFactory.newFactory(name(), script.getParams(), searchLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -80,7 +80,7 @@ public final class ScriptIpMappedFieldType extends AbstractScriptMappedFieldType
|
|||
}
|
||||
|
||||
private IpScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) {
|
||||
return scriptFactory.newFactory(script.getParams(), searchLookup);
|
||||
return scriptFactory.newFactory(name(), script.getParams(), searchLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -68,7 +68,7 @@ public final class ScriptKeywordMappedFieldType extends AbstractScriptMappedFiel
|
|||
}
|
||||
|
||||
private StringScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) {
|
||||
return scriptFactory.newFactory(script.getParams(), searchLookup);
|
||||
return scriptFactory.newFactory(name(), script.getParams(), searchLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -64,7 +64,7 @@ public class ScriptLongMappedFieldType extends AbstractScriptMappedFieldType {
|
|||
}
|
||||
|
||||
private LongScriptFieldScript.LeafFactory leafFactory(SearchLookup searchLookup) {
|
||||
return scriptFactory.newFactory(script.getParams(), searchLookup);
|
||||
return scriptFactory.newFactory(name(), script.getParams(), searchLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,10 +6,22 @@
|
|||
|
||||
package org.elasticsearch.xpack.runtimefields;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class BooleanScriptFieldScriptTests extends ScriptFieldScriptTestCase<BooleanScriptFieldScript.Factory> {
|
||||
public static final BooleanScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new BooleanScriptFieldScript(
|
||||
public static final BooleanScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new BooleanScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
|
@ -29,4 +41,27 @@ public class BooleanScriptFieldScriptTests extends ScriptFieldScriptTestCase<Boo
|
|||
protected BooleanScriptFieldScript.Factory dummyScript() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
public void testTooManyValues() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
BooleanScriptFieldScript script = new BooleanScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES * 1000; i++) {
|
||||
emitValue(i % 2 == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
// There isn't a limit to the number of values so this won't throw
|
||||
script.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,24 @@
|
|||
|
||||
package org.elasticsearch.xpack.runtimefields;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.time.DateFormatter;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class DateScriptFieldScriptTests extends ScriptFieldScriptTestCase<DateScriptFieldScript.Factory> {
|
||||
public static final DateScriptFieldScript.Factory DUMMY = (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(
|
||||
public static final DateScriptFieldScript.Factory DUMMY = (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
|
@ -30,4 +44,31 @@ public class DateScriptFieldScriptTests extends ScriptFieldScriptTestCase<DateSc
|
|||
protected DateScriptFieldScript.Factory dummyScript() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
public void testTooManyValues() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
DateScriptFieldScript script = new DateScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
DateFormatter.forPattern(randomDateFormatterPattern()).withLocale(randomLocale(random())),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) {
|
||||
emitValue(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
Exception e = expectThrows(IllegalArgumentException.class, script::execute);
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,23 @@
|
|||
|
||||
package org.elasticsearch.xpack.runtimefields;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class DoubleScriptFieldScriptTests extends ScriptFieldScriptTestCase<DoubleScriptFieldScript.Factory> {
|
||||
public static final DoubleScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new DoubleScriptFieldScript(
|
||||
public static final DoubleScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new DoubleScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
|
@ -29,4 +42,30 @@ public class DoubleScriptFieldScriptTests extends ScriptFieldScriptTestCase<Doub
|
|||
protected DoubleScriptFieldScript.Factory dummyScript() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
public void testTooManyValues() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
DoubleScriptFieldScript script = new DoubleScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) {
|
||||
emitValue(1.0);
|
||||
}
|
||||
}
|
||||
};
|
||||
Exception e = expectThrows(IllegalArgumentException.class, script::execute);
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,27 @@
|
|||
|
||||
package org.elasticsearch.xpack.runtimefields;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class IpScriptFieldScriptTests extends ScriptFieldScriptTestCase<IpScriptFieldScript.Factory> {
|
||||
public static final IpScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new IpScriptFieldScript(params, lookup, ctx) {
|
||||
public static final IpScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new IpScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitValue("192.168.0.1");
|
||||
|
@ -25,4 +42,30 @@ public class IpScriptFieldScriptTests extends ScriptFieldScriptTestCase<IpScript
|
|||
protected IpScriptFieldScript.Factory dummyScript() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
public void testTooManyValues() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IpScriptFieldScript script = new IpScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) {
|
||||
emitValue("192.168.0.1");
|
||||
}
|
||||
}
|
||||
};
|
||||
Exception e = expectThrows(IllegalArgumentException.class, script::execute);
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,27 @@
|
|||
|
||||
package org.elasticsearch.xpack.runtimefields;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class LongScriptFieldScriptTests extends ScriptFieldScriptTestCase<LongScriptFieldScript.Factory> {
|
||||
public static final LongScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new LongScriptFieldScript(params, lookup, ctx) {
|
||||
public static final LongScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new LongScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitValue(1);
|
||||
|
@ -25,4 +42,30 @@ public class LongScriptFieldScriptTests extends ScriptFieldScriptTestCase<LongSc
|
|||
protected LongScriptFieldScript.Factory dummyScript() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
public void testTooManyValues() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
LongScriptFieldScript script = new LongScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) {
|
||||
emitValue(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
Exception e = expectThrows(IllegalArgumentException.class, script::execute);
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,23 @@
|
|||
|
||||
package org.elasticsearch.xpack.runtimefields;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class StringScriptFieldScriptTests extends ScriptFieldScriptTestCase<StringScriptFieldScript.Factory> {
|
||||
public static final StringScriptFieldScript.Factory DUMMY = (params, lookup) -> ctx -> new StringScriptFieldScript(
|
||||
public static final StringScriptFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new StringScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
|
@ -29,4 +42,61 @@ public class StringScriptFieldScriptTests extends ScriptFieldScriptTestCase<Stri
|
|||
protected StringScriptFieldScript.Factory dummyScript() {
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
public void testTooManyValues() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
StringScriptFieldScript script = new StringScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (int i = 0; i <= AbstractScriptFieldScript.MAX_VALUES; i++) {
|
||||
emitValue("test");
|
||||
}
|
||||
}
|
||||
};
|
||||
Exception e = expectThrows(IllegalArgumentException.class, script::execute);
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
equalTo("Runtime field [test] is emitting [101] values while the maximum number of values allowed is [100]")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testTooManyChars() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
StringScriptFieldScript script = new StringScriptFieldScript(
|
||||
"test",
|
||||
org.elasticsearch.common.collect.Map.of(),
|
||||
new SearchLookup(mock(MapperService.class), (ft, lookup) -> null, null),
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
StringBuilder big = new StringBuilder();
|
||||
while (big.length() < StringScriptFieldScript.MAX_CHARS / 4) {
|
||||
big.append("test");
|
||||
}
|
||||
String bigString = big.toString();
|
||||
for (int i = 0; i <= 4; i++) {
|
||||
emitValue(bigString);
|
||||
}
|
||||
}
|
||||
};
|
||||
Exception e = expectThrows(IllegalArgumentException.class, script::execute);
|
||||
assertThat(
|
||||
e.getMessage(),
|
||||
equalTo("Runtime field [test] is emitting [1310720] characters while the maximum number of values allowed is [1048576]")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -458,7 +458,12 @@ public class ScriptBooleanMappedFieldTypeTests extends AbstractNonTextScriptMapp
|
|||
private BooleanScriptFieldScript.Factory factory(String code) {
|
||||
switch (code) {
|
||||
case "read_foo":
|
||||
return (params, lookup) -> (ctx) -> new BooleanScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new BooleanScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
@ -467,7 +472,12 @@ public class ScriptBooleanMappedFieldTypeTests extends AbstractNonTextScriptMapp
|
|||
}
|
||||
};
|
||||
case "xor_param":
|
||||
return (params, lookup) -> (ctx) -> new BooleanScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new BooleanScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
|
|
@ -504,7 +504,13 @@ public class ScriptDateMappedFieldTypeTests extends AbstractNonTextScriptMappedF
|
|||
private DateScriptFieldScript.Factory factory(String code) {
|
||||
switch (code) {
|
||||
case "read_timestamp":
|
||||
return (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(params, lookup, formatter, ctx) {
|
||||
return (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object timestamp : (List<?>) getSource().get("timestamp")) {
|
||||
|
@ -514,7 +520,13 @@ public class ScriptDateMappedFieldTypeTests extends AbstractNonTextScriptMappedF
|
|||
}
|
||||
};
|
||||
case "add_days":
|
||||
return (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(params, lookup, formatter, ctx) {
|
||||
return (fieldName, params, lookup, formatter) -> ctx -> new DateScriptFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object timestamp : (List<?>) getSource().get("timestamp")) {
|
||||
|
|
|
@ -295,7 +295,7 @@ public class ScriptDoubleMappedFieldTypeTests extends AbstractNonTextScriptMappe
|
|||
private DoubleScriptFieldScript.Factory factory(String code) {
|
||||
switch (code) {
|
||||
case "read_foo":
|
||||
return (params, lookup) -> (ctx) -> new DoubleScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new DoubleScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
@ -304,7 +304,7 @@ public class ScriptDoubleMappedFieldTypeTests extends AbstractNonTextScriptMappe
|
|||
}
|
||||
};
|
||||
case "add_param":
|
||||
return (params, lookup) -> (ctx) -> new DoubleScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new DoubleScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
|
|
@ -338,7 +338,7 @@ public class ScriptIpMappedFieldTypeTests extends AbstractScriptMappedFieldTypeT
|
|||
private IpScriptFieldScript.Factory factory(String code) {
|
||||
switch (code) {
|
||||
case "read_foo":
|
||||
return (params, lookup) -> (ctx) -> new IpScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new IpScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
@ -347,7 +347,7 @@ public class ScriptIpMappedFieldTypeTests extends AbstractScriptMappedFieldTypeT
|
|||
}
|
||||
};
|
||||
case "append_param":
|
||||
return (params, lookup) -> (ctx) -> new IpScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new IpScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
|
|
@ -379,7 +379,7 @@ public class ScriptKeywordMappedFieldTypeTests extends AbstractScriptMappedField
|
|||
private StringScriptFieldScript.Factory factory(String code) {
|
||||
switch (code) {
|
||||
case "read_foo":
|
||||
return (params, lookup) -> (ctx) -> new StringScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> ctx -> new StringScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
@ -388,7 +388,7 @@ public class ScriptKeywordMappedFieldTypeTests extends AbstractScriptMappedField
|
|||
}
|
||||
};
|
||||
case "append_param":
|
||||
return (params, lookup) -> (ctx) -> new StringScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> ctx -> new StringScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
|
|
@ -324,7 +324,7 @@ public class ScriptLongMappedFieldTypeTests extends AbstractNonTextScriptMappedF
|
|||
private LongScriptFieldScript.Factory factory(String code) {
|
||||
switch (code) {
|
||||
case "read_foo":
|
||||
return (params, lookup) -> (ctx) -> new LongScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new LongScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
@ -333,7 +333,7 @@ public class ScriptLongMappedFieldTypeTests extends AbstractNonTextScriptMappedF
|
|||
}
|
||||
};
|
||||
case "add_param":
|
||||
return (params, lookup) -> (ctx) -> new LongScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new LongScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) getSource().get("foo")) {
|
||||
|
@ -344,7 +344,7 @@ public class ScriptLongMappedFieldTypeTests extends AbstractNonTextScriptMappedF
|
|||
case "millis_ago":
|
||||
// Painless actually call System.currentTimeMillis. We could mock the time but this works fine too.
|
||||
long now = System.currentTimeMillis();
|
||||
return (params, lookup) -> (ctx) -> new LongScriptFieldScript(params, lookup, ctx) {
|
||||
return (fieldName, params, lookup) -> (ctx) -> new LongScriptFieldScript(fieldName, params, lookup, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object timestamp : (List<?>) getSource().get("timestamp")) {
|
||||
|
|
|
@ -91,7 +91,7 @@ public class LongScriptFieldDistanceFeatureQueryTests extends AbstractScriptFiel
|
|||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
CheckedFunction<LeafReaderContext, AbstractLongScriptFieldScript, IOException> leafFactory =
|
||||
ctx -> new DateScriptFieldScript(Collections.emptyMap(), new SearchLookup(null, null, null), null, ctx) {
|
||||
ctx -> new DateScriptFieldScript("test", Collections.emptyMap(), new SearchLookup(null, null, null), null, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object timestamp : (List<?>) getSource().get("timestamp")) {
|
||||
|
|
Loading…
Reference in New Issue