|  | @@ -20,13 +20,18 @@
 | 
	
		
			
				|  |  |  package org.elasticsearch.ingest;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.settings.Settings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.script.IngestConditionalScript;
 | 
	
		
			
				|  |  |  import org.elasticsearch.script.MockScriptEngine;
 | 
	
		
			
				|  |  | +import org.elasticsearch.script.MockScriptService;
 | 
	
		
			
				|  |  |  import org.elasticsearch.script.Script;
 | 
	
		
			
				|  |  | +import org.elasticsearch.script.ScriptException;
 | 
	
		
			
				|  |  |  import org.elasticsearch.script.ScriptModule;
 | 
	
		
			
				|  |  |  import org.elasticsearch.script.ScriptService;
 | 
	
		
			
				|  |  |  import org.elasticsearch.script.ScriptType;
 | 
	
		
			
				|  |  | +import org.elasticsearch.script.StoredScriptSource;
 | 
	
		
			
				|  |  |  import org.elasticsearch.test.ESTestCase;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import java.text.ParseException;
 | 
	
		
			
				|  |  |  import java.util.ArrayList;
 | 
	
		
			
				|  |  |  import java.util.Collections;
 | 
	
		
			
				|  |  |  import java.util.HashMap;
 | 
	
	
		
			
				|  | @@ -34,6 +39,7 @@ import java.util.List;
 | 
	
		
			
				|  |  |  import java.util.Map;
 | 
	
		
			
				|  |  |  import java.util.concurrent.CompletableFuture;
 | 
	
		
			
				|  |  |  import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  | +import java.util.concurrent.atomic.AtomicBoolean;
 | 
	
		
			
				|  |  |  import java.util.function.Consumer;
 | 
	
		
			
				|  |  |  import java.util.function.LongSupplier;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -195,6 +201,59 @@ public class ConditionalProcessorTests extends ESTestCase {
 | 
	
		
			
				|  |  |          assertWarnings("[types removal] Looking up doc types [_type] in scripts is deprecated.");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    public void testPrecompiledError() {
 | 
	
		
			
				|  |  | +        ScriptService scriptService = MockScriptService.singleContext(IngestConditionalScript.CONTEXT, code -> {
 | 
	
		
			
				|  |  | +            throw new ScriptException("bad script", new ParseException("error", 0), List.of(), "", "lang", null);
 | 
	
		
			
				|  |  | +        }, Map.of());
 | 
	
		
			
				|  |  | +        Script script = new Script(ScriptType.INLINE, "lang", "foo", Map.of());
 | 
	
		
			
				|  |  | +        ScriptException e = expectThrows(ScriptException.class, () ->
 | 
	
		
			
				|  |  | +            new ConditionalProcessor(null, null, script, scriptService, null));
 | 
	
		
			
				|  |  | +        assertThat(e.getMessage(), equalTo("bad script"));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testRuntimeCompileError() {
 | 
	
		
			
				|  |  | +        AtomicBoolean fail = new AtomicBoolean(false);
 | 
	
		
			
				|  |  | +        Map<String, StoredScriptSource> storedScripts = new HashMap<>();
 | 
	
		
			
				|  |  | +        storedScripts.put("foo", new StoredScriptSource("lang", "", Map.of()));
 | 
	
		
			
				|  |  | +        ScriptService scriptService = MockScriptService.singleContext(IngestConditionalScript.CONTEXT, code -> {
 | 
	
		
			
				|  |  | +            if (fail.get()) {
 | 
	
		
			
				|  |  | +                throw new ScriptException("bad script", new ParseException("error", 0), List.of(), "", "lang", null);
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                return params -> new IngestConditionalScript(params) {
 | 
	
		
			
				|  |  | +                    @Override
 | 
	
		
			
				|  |  | +                    public boolean execute(Map<String, Object> ctx) {
 | 
	
		
			
				|  |  | +                        return false;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }, storedScripts);
 | 
	
		
			
				|  |  | +        Script script = new Script(ScriptType.STORED, null, "foo", Map.of());
 | 
	
		
			
				|  |  | +        var processor = new ConditionalProcessor(null, null, script, scriptService, null);
 | 
	
		
			
				|  |  | +        fail.set(true);
 | 
	
		
			
				|  |  | +        // must change the script source or the cached version will be used
 | 
	
		
			
				|  |  | +        storedScripts.put("foo", new StoredScriptSource("lang", "changed", Map.of()));
 | 
	
		
			
				|  |  | +        IngestDocument ingestDoc = new IngestDocument(Map.of(), Map.of());
 | 
	
		
			
				|  |  | +        processor.execute(ingestDoc, (doc, e) -> {
 | 
	
		
			
				|  |  | +            assertThat(e.getMessage(), equalTo("bad script"));
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testRuntimeError() {
 | 
	
		
			
				|  |  | +        ScriptService scriptService = MockScriptService.singleContext(IngestConditionalScript.CONTEXT,
 | 
	
		
			
				|  |  | +            code -> params -> new IngestConditionalScript(params) {
 | 
	
		
			
				|  |  | +                @Override
 | 
	
		
			
				|  |  | +                public boolean execute(Map<String, Object> ctx) {
 | 
	
		
			
				|  |  | +                    throw new IllegalArgumentException("runtime problem");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }, Map.of());
 | 
	
		
			
				|  |  | +        Script script = new Script(ScriptType.INLINE, "lang", "foo", Map.of());
 | 
	
		
			
				|  |  | +        var processor = new ConditionalProcessor(null, null, script, scriptService, null);
 | 
	
		
			
				|  |  | +        IngestDocument ingestDoc = new IngestDocument(Map.of(), Map.of());
 | 
	
		
			
				|  |  | +        processor.execute(ingestDoc, (doc, e) -> {
 | 
	
		
			
				|  |  | +            assertThat(e.getMessage(), equalTo("runtime problem"));
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private static void assertMutatingCtxThrows(Consumer<Map<String, Object>> mutation) throws Exception {
 | 
	
		
			
				|  |  |          String scriptName = "conditionalScript";
 | 
	
		
			
				|  |  |          CompletableFuture<Exception> expectedException = new CompletableFuture<>();
 |