From d40d862094c58c4e4ed145ce3fa5be2f98418359 Mon Sep 17 00:00:00 2001 From: Jason Wells Date: Thu, 10 Aug 2023 15:38:11 -0700 Subject: [PATCH] script runner tests and ability to capture implicit value of last statement --- .../enginewrapper/RubyScriptRunner.java | 28 +++++++++-- Nx/src/test/java/RubyScriptRunnerTests.java | 48 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 Nx/src/test/java/RubyScriptRunnerTests.java diff --git a/Nx/src/main/java/com/nuix/innovation/enginewrapper/RubyScriptRunner.java b/Nx/src/main/java/com/nuix/innovation/enginewrapper/RubyScriptRunner.java index f8e5db4..2d5badd 100644 --- a/Nx/src/main/java/com/nuix/innovation/enginewrapper/RubyScriptRunner.java +++ b/Nx/src/main/java/com/nuix/innovation/enginewrapper/RubyScriptRunner.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jruby.embed.LocalVariableBehavior; import org.jruby.embed.ScriptingContainer; +import org.jruby.embed.internal.BiVariableMap; import javax.swing.*; import java.io.File; @@ -14,6 +15,7 @@ import java.io.InputStream; import java.io.Writer; import java.util.Map; +import java.util.function.BiConsumer; import java.util.function.Consumer; /*** @@ -40,9 +42,7 @@ public void write(@NotNull char[] cbuf, int off, int len) throws IOException { char[] subchars = new char[len]; System.arraycopy(cbuf, off, subchars, 0, len); String value = new String(subchars); - SwingUtilities.invokeLater(() -> { - consumer.accept(value); - }); + consumer.accept(value); } } } @@ -61,10 +61,20 @@ public void close() throws IOException { protected Thread scriptThread; protected Consumer standardOutput; protected Consumer errorOutput; + protected Consumer completedCallback; public RubyScriptRunner() { } + /*** + * Allows you to provide a callback to be invoked when script finishes. + * @param completedCallback A {@link BiConsumer} that accepts an Object (the final returned value) and + * a Map containing all the variables in the scripting container upon completion. + */ + public void whenScriptCompletes(Consumer completedCallback) { + this.completedCallback = completedCallback; + } + /*** * Interrupts running script thread if there is one running. See also {@link #isAlive()}. */ @@ -138,7 +148,8 @@ public void runScriptAsync(String script, String nuixVersion, Map { - scriptingContainer.runScriptlet(script); + Object returnedValue = scriptingContainer.runScriptlet(script); + fireCompletedCallback(returnedValue); }); scriptThread.start(); @@ -156,7 +167,8 @@ public void runFileAsync(File scriptFile, String nuixVersion, Map { try (InputStream scriptFileInputStream = FileUtils.openInputStream(scriptFile)) { - scriptingContainer.runScriptlet(scriptFileInputStream, scriptFile.getAbsolutePath()); + Object returnedValue = scriptingContainer.runScriptlet(scriptFileInputStream, scriptFile.getAbsolutePath()); + fireCompletedCallback(returnedValue); } catch (Exception exc) { errorOutput.accept(ExceptionUtils.getMessage(exc) + "\n" + ExceptionUtils.getStackTrace(exc)); } @@ -194,4 +206,10 @@ private void initialize(String nuixVersion, Map variablesToSet) scriptingContainer.put(variableToSet.getKey(), variableToSet.getValue()); } } + + private void fireCompletedCallback(Object returnedValue) { + if(completedCallback != null) { + completedCallback.accept(returnedValue); + } + } } diff --git a/Nx/src/test/java/RubyScriptRunnerTests.java b/Nx/src/test/java/RubyScriptRunnerTests.java new file mode 100644 index 0000000..5c8802f --- /dev/null +++ b/Nx/src/test/java/RubyScriptRunnerTests.java @@ -0,0 +1,48 @@ +import com.nuix.innovation.enginewrapper.RubyScriptRunner; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class RubyScriptRunnerTests { + @Test + public void RunScript() throws Exception { + // Validate that script runs and output is captured + String script = "puts 'hello'"; + List output = new ArrayList<>(); + RubyScriptRunner rubyScriptRunner = new RubyScriptRunner(); + rubyScriptRunner.setStandardOutputConsumer(output::add); + rubyScriptRunner.setErrorOutputConsumer(output::add); + rubyScriptRunner.runScriptAsync(script, "0.0.0.0", Map.of()); + rubyScriptRunner.join(); + assertTrue(output.size() > 0); + } + + @Test + public void ReturnedValue() throws Exception { + // Test that returned value from last statement is captured + String script = "response['sum'] = 10 + 15 + 15 + 2"; + List output = new ArrayList<>(); + RubyScriptRunner rubyScriptRunner = new RubyScriptRunner(); + + rubyScriptRunner.whenScriptCompletes((ret) -> { + assertEquals(42L, ret); + }); + + Map varContainer = new HashMap<>(); + Map response = new HashMap<>(); + varContainer.put("response", response); + + rubyScriptRunner.setStandardOutputConsumer(output::add); + rubyScriptRunner.setErrorOutputConsumer(output::add); + rubyScriptRunner.runScriptAsync(script, "0.0.0.0", varContainer); + rubyScriptRunner.join(); + + assertEquals(42L, response.get("sum")); + } +}