From db73a6835f176150be8c770f1342d7426a6169fc Mon Sep 17 00:00:00 2001 From: huaxing Date: Wed, 17 Jun 2020 13:34:10 +0800 Subject: Remove thread in JavascriptExecutor This change is basically a rollback of https://gerrit.onap.org/r/c/policy/apex-pdp/+/104230, with minor refactoring. The problem that 104230 tried to address was supposed to be caused by https://jira.onap.org/browse/POLICY-2463. With this rollback, apex-pdp increases performance and reduces memory usage. Issue-ID: POLICY-2572 Signed-off-by: huaxing Change-Id: I3a52d0ead0c1e530d218f9e3aba8b3eb5558abaf --- .../executor/javascript/JavascriptExecutor.java | 262 ++--------------- .../JavascriptStateFinalizerExecutor.java | 23 +- .../javascript/JavascriptTaskExecutor.java | 28 +- .../javascript/JavascriptTaskSelectExecutor.java | 25 +- .../javascript/JavascriptExecutorFullApexTest.java | 4 +- .../javascript/JavascriptExecutorTest.java | 321 ++------------------- .../JavascriptStateFinalizerExecutorTest.java | 59 +--- .../javascript/JavascriptTaskExecutorTest.java | 40 +-- .../JavascriptTaskSelectExecutorTest.java | 45 +-- 9 files changed, 103 insertions(+), 704 deletions(-) diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java index 0eecd5d4b..344f8c5ae 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java @@ -20,288 +20,88 @@ package org.onap.policy.apex.plugins.executor.javascript; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.mozilla.javascript.Context; import org.mozilla.javascript.Script; import org.mozilla.javascript.Scriptable; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; import org.onap.policy.apex.model.basicmodel.concepts.AxKey; -import org.slf4j.ext.XLogger; -import org.slf4j.ext.XLoggerFactory; /** * The Class JavascriptExecutor is the executor for task logic written in Javascript. * * @author Liam Fallon (liam.fallon@ericsson.com) */ -public class JavascriptExecutor implements Runnable { - private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptExecutor.class); - +public class JavascriptExecutor { public static final int DEFAULT_OPTIMIZATION_LEVEL = 9; - // Token passed to executor thread to stop execution - private static final Object STOP_EXECUTION_TOKEN = "*** STOP EXECUTION ***"; - // Recurring string constants private static final String WITH_MESSAGE = " with message: "; - private static final String JAVASCRIPT_EXECUTOR = "JavascriptExecutor "; - private static final String EXECUTION_FAILED_EXECUTOR = "execution failed, executor "; - - @Setter(AccessLevel.PROTECTED) - private static TimeUnit timeunit4Latches = TimeUnit.SECONDS; - @Setter(AccessLevel.PROTECTED) - private static int intializationLatchTimeout = 60; - @Setter(AccessLevel.PROTECTED) - private static int cleanupLatchTimeout = 60; // The key of the subject that wants to execute Javascript code - final AxKey subjectKey; + private final AxKey subjectKey; - private String javascriptCode; - private Context javascriptContext; - private Script script; - - private final BlockingQueue executionQueue = new LinkedBlockingQueue<>(); - private final BlockingQueue resultQueue = new LinkedBlockingQueue<>(); - - @Getter(AccessLevel.PROTECTED) - private Thread executorThread; - private CountDownLatch intializationLatch; - private CountDownLatch cleanupLatch; - private AtomicReference executorException = new AtomicReference<>(null); + private final Script script; /** * Initializes the Javascript executor. * * @param subjectKey the key of the subject that is requesting Javascript execution - */ - public JavascriptExecutor(final AxKey subjectKey) { - this.subjectKey = subjectKey; - } - - /** - * Prepares the executor for processing and compiles the Javascript code. - * * @param javascriptCode the Javascript code to execute - * @throws StateMachineException thrown when instantiation of the executor fails */ - public synchronized void init(@NonNull final String javascriptCode) throws StateMachineException { - LOGGER.debug("JavascriptExecutor {} starting ... ", subjectKey.getId()); - - if (executorThread != null) { - throw new StateMachineException("initiation failed, executor " + subjectKey.getId() - + " already initialized, run cleanUp to clear executor"); - } - + public JavascriptExecutor(final AxKey subjectKey, String javascriptCode) throws StateMachineException { if (StringUtils.isBlank(javascriptCode)) { - throw new StateMachineException("initiation failed, no logic specified for executor " + subjectKey.getId()); - } - - this.javascriptCode = javascriptCode; - - executorThread = new Thread(this); - executorThread.setName(this.getClass().getSimpleName() + ":" + subjectKey.getId()); - intializationLatch = new CountDownLatch(1); - cleanupLatch = new CountDownLatch(1); - - try { - executorThread.start(); - } catch (IllegalThreadStateException e) { - throw new StateMachineException("initiation failed, executor " + subjectKey.getId() + " failed to start", - e); - } - - try { - if (!intializationLatch.await(intializationLatchTimeout, timeunit4Latches)) { - executorThread.interrupt(); - throw new StateMachineException(JAVASCRIPT_EXECUTOR + subjectKey.getId() - + " initiation timed out after " + intializationLatchTimeout + " " + timeunit4Latches); - } - } catch (InterruptedException e) { - LOGGER.debug("JavascriptExecutor {} interrupted on execution thread startup", subjectKey.getId(), e); - Thread.currentThread().interrupt(); - } - - if (executorException.get() != null) { - executorThread.interrupt(); - checkAndThrowExecutorException(); - } - - checkAndThrowExecutorException(); - - LOGGER.debug("JavascriptExecutor {} started ... ", subjectKey.getId()); - } - - /** - * Execute a Javascript script. - * - * @param executionContext the execution context to use for script execution - * @return true if execution was successful, false otherwise - * @throws StateMachineException on execution errors - */ - public synchronized boolean execute(final Object executionContext) throws StateMachineException { - if (executorThread == null) { - throw new StateMachineException(EXECUTION_FAILED_EXECUTOR + subjectKey.getId() + " is not initialized"); + throw new StateMachineException("no logic specified for " + subjectKey.getId()); } - - if (!executorThread.isAlive() || executorThread.isInterrupted()) { - throw new StateMachineException(EXECUTION_FAILED_EXECUTOR + subjectKey.getId() - + " is not running, run cleanUp to clear executor and init to restart executor"); - } - - executionQueue.add(executionContext); - - boolean result = false; - - try { - result = resultQueue.take(); - } catch (final InterruptedException e) { - executorThread.interrupt(); - Thread.currentThread().interrupt(); - throw new StateMachineException( - JAVASCRIPT_EXECUTOR + subjectKey.getId() + "interrupted on execution result wait", e); - } - - checkAndThrowExecutorException(); - - return result; + this.subjectKey = subjectKey; + this.script = compile(subjectKey.getId(), javascriptCode); } /** - * Cleans up the executor after processing. + * Executes the Javascript code. * - * @throws StateMachineException thrown when cleanup of the executor fails + * @param executionContext the execution context of the subject to be passed to the Javascript context + * @return true if the Javascript executed properly + * @throws StateMachineException thrown when Javascript execution fails */ - public synchronized void cleanUp() throws StateMachineException { - if (executorThread == null) { - throw new StateMachineException("cleanup failed, executor " + subjectKey.getId() + " is not initialized"); - } - - if (executorThread.isAlive()) { - executionQueue.add(STOP_EXECUTION_TOKEN); - - try { - if (!cleanupLatch.await(cleanupLatchTimeout, timeunit4Latches)) { - executorException.set(new StateMachineException(JAVASCRIPT_EXECUTOR + subjectKey.getId() - + " cleanup timed out after " + cleanupLatchTimeout + " " + timeunit4Latches)); - } - } catch (InterruptedException e) { - LOGGER.debug("JavascriptExecutor {} interrupted on execution cleanup wait", subjectKey.getId(), e); - Thread.currentThread().interrupt(); - } - } - - executorThread = null; - executionQueue.clear(); - resultQueue.clear(); - - checkAndThrowExecutorException(); - } - - @Override - public void run() { - LOGGER.debug("JavascriptExecutor {} initializing ... ", subjectKey.getId()); - - try { - initExecutor(); - } catch (StateMachineException sme) { - LOGGER.warn("JavascriptExecutor {} initialization failed", subjectKey.getId(), sme); - executorException.set(sme); - intializationLatch.countDown(); - cleanupLatch.countDown(); - return; - } - - intializationLatch.countDown(); - - LOGGER.debug("JavascriptExecutor {} executing ... ", subjectKey.getId()); - - // Take jobs from the execution queue of the worker and execute them - while (!Thread.currentThread().isInterrupted()) { - try { - Object contextObject = executionQueue.take(); - if (STOP_EXECUTION_TOKEN.equals(contextObject)) { - LOGGER.debug("execution close was ordered for " + subjectKey.getId()); - break; - } - resultQueue.add(executeScript(contextObject)); - } catch (final InterruptedException e) { - LOGGER.debug("execution was interruped for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e); - executionQueue.add(STOP_EXECUTION_TOKEN); - Thread.currentThread().interrupt(); - } catch (StateMachineException sme) { - executorException.set(sme); - resultQueue.add(false); - } - } - - resultQueue.add(false); - - try { - Context.exit(); - } catch (final Exception e) { - executorException.set(new StateMachineException( - "executor close failed to close for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e)); - } - - cleanupLatch.countDown(); - - LOGGER.debug("JavascriptExecutor {} completed processing", subjectKey.getId()); - } - - private void initExecutor() throws StateMachineException { - try { - // Create a Javascript context for this thread - javascriptContext = Context.enter(); - - // Set up the default values of the context - javascriptContext.setOptimizationLevel(DEFAULT_OPTIMIZATION_LEVEL); - javascriptContext.setLanguageVersion(Context.VERSION_1_8); - - script = javascriptContext.compileString(javascriptCode, subjectKey.getId(), 1, null); - } catch (Exception e) { - Context.exit(); - throw new StateMachineException( - "logic failed to compile for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e); - } - } - - private boolean executeScript(final Object executionContext) throws StateMachineException { + public boolean execute(final Object executionContext) throws StateMachineException { Object returnObject = null; + Context context = Context.enter(); try { // Pass the subject context to the Javascript engine - Scriptable javascriptScope = javascriptContext.initStandardObjects(); + Scriptable javascriptScope = context.initStandardObjects(); javascriptScope.put("executor", javascriptScope, executionContext); // Run the script - returnObject = script.exec(javascriptContext, javascriptScope); + returnObject = script.exec(context, javascriptScope); } catch (final Exception e) { throw new StateMachineException( - "logic failed to run for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e); + "logic failed to run for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e); + } finally { + Context.exit(); } if (!(returnObject instanceof Boolean)) { throw new StateMachineException( - "execute: logic for " + subjectKey.getId() + " returned a non-boolean value " + returnObject); + "execute: logic for " + subjectKey.getId() + " returned a non-boolean value " + returnObject); } return (boolean) returnObject; } - private void checkAndThrowExecutorException() throws StateMachineException { - StateMachineException exceptionToThrow = executorException.getAndSet(null); - if (exceptionToThrow != null) { - throw exceptionToThrow; + private Script compile(String id, String javascriptCode) throws StateMachineException { + Context context = Context.enter(); + try { + // Set up the default values of the context + context.setOptimizationLevel(DEFAULT_OPTIMIZATION_LEVEL); + context.setLanguageVersion(Context.VERSION_1_8); + return context.compileString(javascriptCode, id, 1, null); + } catch (Exception e) { + throw new StateMachineException( + "logic failed to compile for " + id + WITH_MESSAGE + e.getMessage(), e); + } finally { + Context.exit(); } } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java index ffd09259b..24c6b768a 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java @@ -52,12 +52,7 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor { super.prepare(); // Create the executor - if (javascriptExecutor == null) { - javascriptExecutor = new JavascriptExecutor(getSubject().getKey()); - } - - // Initialize and cleanup the executor to check the Javascript code - javascriptExecutor.init(getSubject().getLogic()); + javascriptExecutor = new JavascriptExecutor(getSubject().getKey(), getSubject().getLogic()); } /** @@ -72,16 +67,10 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor { */ @Override public String execute(final long executionId, final Properties executionProperties, - final Map incomingFields) throws StateMachineException, ContextException { - // Do execution pre work + final Map incomingFields) throws StateMachineException, ContextException { executePre(executionId, executionProperties, incomingFields); - - // Execute the Javascript executor boolean result = javascriptExecutor.execute(getExecutionContext()); - - // Execute the Javascript executePost(result); - return getOutgoing(); } @@ -92,9 +81,9 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor { */ @Override public void cleanUp() throws StateMachineException { - LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getLogicFlavour() + "," - + getSubject().getLogic()); - - javascriptExecutor.cleanUp(); + LOGGER.debug("cleanUp:{},{},{}", + getSubject().getKey().getId(), + getSubject().getLogicFlavour(), + getSubject().getLogic()); } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java index 9f30f839f..a25dca0c6 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java @@ -52,12 +52,7 @@ public class JavascriptTaskExecutor extends TaskExecutor { super.prepare(); // Create the executor - if (javascriptExecutor == null) { - javascriptExecutor = new JavascriptExecutor(getSubject().getKey()); - } - - // Initialize and cleanup the executor to check the Javascript code - javascriptExecutor.init(getSubject().getTaskLogic().getLogic()); + javascriptExecutor = new JavascriptExecutor(getSubject().getKey(), getSubject().getTaskLogic().getLogic()); } /** @@ -72,17 +67,10 @@ public class JavascriptTaskExecutor extends TaskExecutor { */ @Override public Map execute(final long executionId, final Properties executionProperties, - final Map incomingFields) throws StateMachineException, ContextException { - - // Do execution pre work + final Map incomingFields) throws StateMachineException, ContextException { executePre(executionId, executionProperties, incomingFields); - - // Execute the Javascript executor boolean result = javascriptExecutor.execute(getExecutionContext()); - - // Execute the Javascript executePost(result); - return getOutgoing(); } @@ -93,13 +81,9 @@ public class JavascriptTaskExecutor extends TaskExecutor { */ @Override public void cleanUp() throws StateMachineException { - LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogicFlavour() - + "," + getSubject().getTaskLogic().getLogic()); - - if (javascriptExecutor != null) { - javascriptExecutor.cleanUp(); - } - - javascriptExecutor = null; + LOGGER.debug("cleanUp:{},{},{}", + getSubject().getKey().getId(), + getSubject().getTaskLogic().getLogicFlavour(), + getSubject().getTaskLogic().getLogic()); } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java index d7b137f2e..5c28999b5 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java @@ -53,12 +53,8 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor { super.prepare(); // Create the executor - if (javascriptExecutor == null) { - javascriptExecutor = new JavascriptExecutor(getSubject().getKey()); - } - - // Initialize and cleanup the executor to check the Javascript code - javascriptExecutor.init(getSubject().getTaskSelectionLogic().getLogic()); + javascriptExecutor = new JavascriptExecutor(getSubject().getKey(), + getSubject().getTaskSelectionLogic().getLogic()); } /** @@ -73,16 +69,10 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor { */ @Override public AxArtifactKey execute(final long executionId, final Properties executionProperties, - final EnEvent incomingEvent) throws StateMachineException, ContextException { - // Do execution pre work + final EnEvent incomingEvent) throws StateMachineException, ContextException { executePre(executionId, executionProperties, incomingEvent); - - // Execute the Javascript executor boolean result = javascriptExecutor.execute(getExecutionContext()); - - // Execute the Javascript executePost(result); - return getOutgoing(); } @@ -93,10 +83,9 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor { */ @Override public void cleanUp() throws StateMachineException { - LOGGER.debug( - "cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getTaskSelectionLogic().getLogicFlavour() - + "," + getSubject().getTaskSelectionLogic().getLogic()); - - javascriptExecutor.cleanUp(); + LOGGER.debug("cleanUp:{},{},{}", + getSubject().getKey().getId(), + getSubject().getTaskSelectionLogic().getLogicFlavour(), + getSubject().getTaskSelectionLogic().getLogic()); } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java index 2b1c92fd3..394126bc4 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java @@ -56,9 +56,9 @@ public class JavascriptExecutorFullApexTest { } private boolean fileHasOccurencesOf(final File file, final String token, final int occurenceCount) - throws IOException { + throws IOException { return occurenceCount == StringUtils.countMatches(TextFileUtils.getTextFileAsString(file.getAbsolutePath()), - token); + token); } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java index e45f35cf0..948fc02ed 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. + * Copyright (C) 2020 Nordix Foundation. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,324 +22,39 @@ package org.onap.policy.apex.plugins.executor.javascript; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.awaitility.Awaitility.await; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import org.junit.Before; import org.junit.Test; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; -import org.slf4j.ext.XLogger; -import org.slf4j.ext.XLoggerFactory; public class JavascriptExecutorTest { - private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptExecutorTest.class); - - private AtomicBoolean concurrentResult = new AtomicBoolean(); - - @Before - public void beforeSetTimeouts() { - JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS); - JavascriptExecutor.setIntializationLatchTimeout(60); - JavascriptExecutor.setCleanupLatchTimeout(10); - } @Test - public void testJavescriptExecutorConcurrencyNormal() throws StateMachineException, IOException { - JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS); - JavascriptExecutor.setIntializationLatchTimeout(60); - JavascriptExecutor.setCleanupLatchTimeout(10); - - JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); - - assertThatThrownBy(() -> { - executor.init(null); - }).hasMessageMatching("^javascriptCode is marked .*on.*ull but is null$"); - - assertThatThrownBy(() -> { - executor.init(" "); - }).hasMessage("initiation failed, no logic specified for executor executor:0.0.1"); - - assertThatCode(() -> { - executor.init("var x = 1;"); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - executor.init("var x = 1;"); - }).hasMessage("initiation failed, executor executor:0.0.1 already initialized, run cleanUp to clear executor"); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - executor.cleanUp(); - }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); - - assertThatThrownBy(() -> { - executor.execute("Hello"); - }).hasMessage("execution failed, executor executor:0.0.1 is not initialized"); - - assertThatCode(() -> { - executor.init("var x = 1;"); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - executor.execute("Hello"); - }).hasMessage( - "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); - - assertThatThrownBy(() -> { - executor.execute("Hello"); - }).hasMessage( - "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); - - assertThatThrownBy(() -> { - executor.execute("Hello"); - }).hasMessage( - "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); - - assertThatThrownBy(() -> { - executor.execute("Hello"); - }).hasMessage( - "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - executor.cleanUp(); - }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); - - assertThatThrownBy(() -> { - executor.execute("hello"); - }).hasMessage("execution failed, executor executor:0.0.1 is not initialized"); + public void testReturnOK() throws StateMachineException { + JavascriptExecutor executor = new JavascriptExecutor( + new AxArtifactKey("TestTask:0.0.1"), "true;"); + assertThatCode(() -> executor.execute(new Object())); } @Test - public void testJavescriptExecutorConcurrencyLatchTimeout() throws StateMachineException, IOException { - JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS); - JavascriptExecutor.setIntializationLatchTimeout(1); - JavascriptExecutor.setCleanupLatchTimeout(10000000); - - JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); - - assertThatThrownBy(() -> { - executor.init("var x = 1;"); - }).hasMessage("JavascriptExecutor executor:0.0.1 initiation timed out after 1 MICROSECONDS"); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS); - JavascriptExecutor.setIntializationLatchTimeout(60); - - assertThatCode(() -> { - executor.init("var x = 1;"); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS); - JavascriptExecutor.setIntializationLatchTimeout(60000000); - JavascriptExecutor.setCleanupLatchTimeout(1); - - assertThatCode(() -> { - executor.init("var x = 1;"); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - executor.cleanUp(); - }).hasMessage("JavascriptExecutor executor:0.0.1 cleanup timed out after 1 MICROSECONDS"); - - JavascriptExecutor.setCleanupLatchTimeout(10000000); - assertThatThrownBy(() -> { - executor.cleanUp(); - }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); - - assertThatCode(() -> { - executor.init("var x = 1;"); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); + public void testReturnNonBoolean() throws StateMachineException { + JavascriptExecutor executor = new JavascriptExecutor( + new AxArtifactKey("TestTask:0.0.1"), "var a = 1; a;"); + assertThatThrownBy(() -> executor.execute(new Object())) + .hasMessageContaining("logic for TestTask:0.0.1 returned a non-boolean value"); } @Test - public void testJavescriptExecutorBadStates() throws StateMachineException, IOException { - JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); - - assertThatThrownBy(() -> { - executor.execute("hello"); - }).hasMessage("execution failed, executor executor:0.0.1 is not initialized"); - - assertThatThrownBy(() -> { - executor.cleanUp(); - }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); - - assertThatCode(() -> { - executor.init("var x = 1;"); - }).doesNotThrowAnyException(); - - executor.getExecutorThread().interrupt(); - await().atMost(10, TimeUnit.SECONDS).until(() -> !executor.getExecutorThread().isAlive()); - - assertThatThrownBy(() -> { - executor.execute("hello"); - }).hasMessage("execution failed, executor executor:0.0.1 is not running, " - + "run cleanUp to clear executor and init to restart executor"); - - assertThatThrownBy(() -> { - executor.execute("hello"); - }).hasMessage("execution failed, executor executor:0.0.1 is not running, " - + "run cleanUp to clear executor and init to restart executor"); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); + public void testBlankLogic() { + assertThatThrownBy(() -> new JavascriptExecutor( + new AxArtifactKey("TestTask:0.0.1"), " ")) + .hasMessageContaining("no logic specified for TestTask:0.0.1"); } @Test - public void testJavescriptExecutorExecution() throws StateMachineException, IOException { - JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); - - assertThatCode(() -> { - executor.init("true;"); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - assertTrue(executor.execute("hello")); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.init("false;"); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - assertFalse(executor.execute("hello")); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - executor.init("aaaaa = \"sss"); - }).hasMessage( - "logic failed to compile for executor:0.0.1 with message: unterminated string literal (executor:0.0.1#1)"); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.init("true;"); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - assertTrue(executor.execute("hello")); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.init("throw \"this is an error\";"); - }).doesNotThrowAnyException(); - - assertThatThrownBy(() -> { - assertTrue(executor.execute("hello")); - }).hasMessage("logic failed to run for executor:0.0.1 with message: this is an error (executor:0.0.1#1)"); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.init("var x = 0; while (x < 100) { x++; }; true;"); - }).doesNotThrowAnyException(); - - concurrentResult.set(true); - - // Execute an infinite loop in Javascript - (new Thread() { - public void run() { - try { - while (executor.execute("hello")) { - LOGGER.debug("test thread running . . ."); - // Loop until interrupted - } - } catch (StateMachineException e) { - LOGGER.debug("test thread caught exception", e); - } - concurrentResult.set(false); - LOGGER.debug("test thread exited"); - } - }).start(); - - await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> executor.getExecutorThread().isAlive()); - - executor.getExecutorThread().interrupt(); - - await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> !concurrentResult.get()); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.init("true;"); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - assertTrue(executor.execute("hello")); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); - - assertThatCode(() -> { - executor.init("x = 1; true;"); - }).doesNotThrowAnyException(); - - concurrentResult.set(true); - - // Execute an infinite loop in Javascript - Thread executionThread = new Thread() { - public void run() { - try { - while (executor.execute("hello")) { - ; - } - } catch (StateMachineException e) { - ; - } - } - }; - executionThread.start(); - - executionThread.interrupt(); - - await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executionThread.isAlive()); - await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executor.getExecutorThread().isAlive()); - - assertThatCode(() -> { - executor.cleanUp(); - }).doesNotThrowAnyException(); + public void testCompileFailed() { + assertThatThrownBy(() -> new JavascriptExecutor( + new AxArtifactKey("TestTask:0.0.1"), "return boolean;")) + .hasMessageContaining("logic failed to compile for TestTask:0.0.1"); } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java index f54e21ec4..2da6a5c73 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java @@ -20,7 +20,6 @@ package org.onap.policy.apex.plugins.executor.javascript; -import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -78,7 +77,6 @@ public class JavascriptStateFinalizerExecutorTest { @Test public void testJavaStateFinalizerExecutor() throws Exception { JavascriptStateFinalizerExecutor jsfe = new JavascriptStateFinalizerExecutor(); - assertNotNull(jsfe); assertThatThrownBy(() -> { jsfe.prepare(); @@ -96,61 +94,30 @@ public class JavascriptStateFinalizerExecutorTest { assertThatThrownBy(() -> { jsfe.prepare(); }).hasMessage("logic failed to compile for NULL:0.0.0:NULL:NULL " - + "with message: invalid return (NULL:0.0.0:NULL:NULL#1)"); + + "with message: invalid return (NULL:0.0.0:NULL:NULL#1)"); - Map incomingParameters1 = new HashMap<>(); - assertThatThrownBy(() -> { - jsfe.execute(-1, new Properties(), incomingParameters1); - }).hasMessage("execution failed, executor NULL:0.0.0:NULL:NULL is not running, " - + "run cleanUp to clear executor and init to restart executor"); - - assertThatThrownBy(() -> { - jsfe.prepare(); - }).hasMessage( - "initiation failed, executor NULL:0.0.0:NULL:NULL already initialized, run cleanUp to clear executor"); - - assertThatCode(() -> { - jsfe.cleanUp(); - }).doesNotThrowAnyException(); - - JavascriptStateFinalizerExecutor jsfe1 = new JavascriptStateFinalizerExecutor(); stateFinalizerLogic.setLogic("java.lang.String"); - jsfe1.setContext(parentStateExcutor, stateFinalizerLogic, internalContext); - jsfe1.prepare(); + jsfe.prepare(); AxEvent axEvent = new AxEvent(new AxArtifactKey("Event", "0.0.1")); EnEvent event = new EnEvent(axEvent); + stateFinalizerLogic.setLogic("if(executor.executionId==-1)" + "{\r\n" + + "var returnValueType = java.lang.Boolean;" + "var returnValue = new returnValueType(false); }\n" + + "else{\n" + "executor.setSelectedStateOutputName(\"SelectedOutputIsMe\");\n" + + "var returnValueType = java.lang.Boolean;\n" + "\n" + + "var returnValue = new returnValueType(true);} true;"); assertThatThrownBy(() -> { - jsfe1.execute(-1, new Properties(), event); - }).hasMessage( - "execute: logic for NULL:0.0.0:NULL:NULL returned a non-boolean value [JavaClass java.lang.String]"); - - assertThatThrownBy(() -> { - jsfe1.execute(-1, new Properties(), event); - }).hasMessage( - "execute: logic for NULL:0.0.0:NULL:NULL returned a non-boolean value [JavaClass java.lang.String]"); - - assertThatCode(() -> { - jsfe1.cleanUp(); - }).doesNotThrowAnyException(); - - JavascriptStateFinalizerExecutor jsfe2 = new JavascriptStateFinalizerExecutor(); - - stateFinalizerLogic.setLogic("executor.setSelectedStateOutputName(\"SelectedOutputIsMe\");\n true;"); - - jsfe2.setContext(parentStateExcutor, stateFinalizerLogic, internalContext); - assertThatCode(() -> { - jsfe2.prepare(); - }).doesNotThrowAnyException(); + jsfe.prepare(); + jsfe.execute(-1, new Properties(), event); + }).hasMessage("execute-post: state finalizer logic \"NULL:0.0.0:NULL:NULL\" did not select an output state"); state.getStateOutputs().put("SelectedOutputIsMe", null); - String stateOutput = jsfe2.execute(0, new Properties(), event); + jsfe.prepare(); + String stateOutput = jsfe.execute(0, new Properties(), event); assertEquals("SelectedOutputIsMe", stateOutput); - assertThatCode(() -> { - jsfe2.cleanUp(); - }).doesNotThrowAnyException(); + jsfe.cleanUp(); } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java index 435397bae..031d605e1 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java @@ -20,7 +20,6 @@ package org.onap.policy.apex.plugins.executor.javascript; -import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -64,7 +63,7 @@ public class JavascriptTaskExecutorTest { public static void prepareForTest() { final ContextParameters contextParameters = new ContextParameters(); contextParameters.getLockManagerParameters() - .setPluginClass("org.onap.policy.apex.context.impl.locking.jvmlocal.JvmLocalLockManager"); + .setPluginClass("org.onap.policy.apex.context.impl.locking.jvmlocal.JvmLocalLockManager"); contextParameters.setName(ContextParameterConstants.MAIN_GROUP_NAME); contextParameters.getDistributorParameters().setName(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME); @@ -98,47 +97,30 @@ public class JavascriptTaskExecutorTest { @Test public void testJavascriptTaskExecutor() throws Exception { + JavascriptTaskExecutor jte = new JavascriptTaskExecutor(); + assertThatThrownBy(() -> { - JavascriptTaskExecutor jteBadPrep = new JavascriptTaskExecutor(); - jteBadPrep.prepare(); + jte.prepare(); }).isInstanceOf(NullPointerException.class); AxTask task = new AxTask(new AxArtifactKey("TestTask:0.0.1")); final ApexInternalContext internalContext = new ApexInternalContext(new AxPolicyModel()); - JavascriptTaskExecutor jteBadLogic = new JavascriptTaskExecutor(); - assertNotNull(jteBadLogic); - - jteBadLogic.setContext(null, task, internalContext); + jte.setContext(null, task, internalContext); task.getTaskLogic().setLogic("return boolean;"); assertThatThrownBy(() -> { - jteBadLogic.prepare(); + jte.prepare(); }).hasMessage("logic failed to compile for TestTask:0.0.1 with message: invalid return (TestTask:0.0.1#1)"); task.getTaskLogic().setLogic("var x = 5;"); - JavascriptTaskExecutor jte = new JavascriptTaskExecutor(); - jte.setContext(null, task, internalContext); - jte.prepare(); - - assertThatThrownBy(() -> { - jte.prepare(); - }).hasMessage("initiation failed, executor TestTask:0.0.1 already initialized, run cleanUp to clear executor"); - - assertThatThrownBy(() -> { - jte.execute(-1, new Properties(), null); - }).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> { jte.execute(-1, new Properties(), null); }).isInstanceOf(NullPointerException.class); - - assertThatCode(() -> { - jte.cleanUp(); - }).doesNotThrowAnyException(); + jte.cleanUp(); task.getTaskLogic().setLogic("var returnValue = false;\nreturnValue;"); @@ -157,10 +139,6 @@ public class JavascriptTaskExecutorTest { Map returnMap = jte.execute(0, new Properties(), incomingParameters); assertEquals(0, returnMap.size()); jte.cleanUp(); - - assertThatCode(() -> { - jte.cleanUp(); - }).doesNotThrowAnyException(); } @Test @@ -207,12 +185,12 @@ public class JavascriptTaskExecutorTest { private ContextAlbum createTestContextAlbum() throws ContextException { AxContextSchemas schemas = new AxContextSchemas(); AxContextSchema simpleStringSchema = - new AxContextSchema(new AxArtifactKey("SimpleStringSchema", "0.0.1"), "JAVA", "java.lang.String"); + new AxContextSchema(new AxArtifactKey("SimpleStringSchema", "0.0.1"), "JAVA", "java.lang.String"); schemas.getSchemasMap().put(simpleStringSchema.getKey(), simpleStringSchema); ModelService.registerModel(AxContextSchemas.class, schemas); AxContextAlbum axContextAlbum = new AxContextAlbum(new AxArtifactKey("TestContextAlbum", "0.0.1"), "Policy", - true, AxArtifactKey.getNullKey()); + true, AxArtifactKey.getNullKey()); axContextAlbum.setItemSchema(simpleStringSchema.getKey()); Distributor distributor = new JvmLocalDistributor(); diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java index 23b3afe9e..a6e410cd0 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java @@ -20,7 +20,6 @@ package org.onap.policy.apex.plugins.executor.javascript; -import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -70,7 +69,6 @@ public class JavascriptTaskSelectExecutorTest { @Test public void testJavascriptTaskSelectExecutor() throws Exception { JavascriptTaskSelectExecutor jtse = new JavascriptTaskSelectExecutor(); - assertNotNull(jtse); assertThatThrownBy(() -> { jtse.prepare(); @@ -83,19 +81,11 @@ public class JavascriptTaskSelectExecutorTest { assertThatThrownBy(() -> { jtse.prepare(); - }).hasMessage("initiation failed, no logic specified for executor NULL:0.0.0:NULL:NULL"); + }).hasMessage("no logic specified for NULL:0.0.0:NULL:NULL"); AxEvent axEvent1 = new AxEvent(new AxArtifactKey("Event", "0.0.1")); EnEvent event1 = new EnEvent(axEvent1); - assertThatThrownBy(() -> { - jtse.execute(-1, new Properties(), event1); - }).hasMessage("execution failed, executor NULL:0.0.0:NULL:NULL is not initialized"); - - assertThatThrownBy(() -> { - jtse.cleanUp(); - }).hasMessage("cleanup failed, executor NULL:0.0.0:NULL:NULL is not initialized"); - state.getTaskSelectionLogic().setLogic("java.lang.String"); jtse.prepare(); @@ -109,33 +99,20 @@ public class JavascriptTaskSelectExecutorTest { assertThatThrownBy(() -> { jtse.execute(-1, new Properties(), event); }).hasMessage( - "execute: logic for NULL:0.0.0:NULL:NULL returned a non-boolean value [JavaClass java.lang.String]"); + "execute: logic for NULL:0.0.0:NULL:NULL returned a non-boolean value [JavaClass java.lang.String]"); - state.getTaskSelectionLogic().setLogic("var x=1;\n" + "false;"); + state.getTaskSelectionLogic().setLogic("var x=1;\n" + "false; "); assertThatThrownBy(() -> { + jtse.prepare(); jtse.execute(-1, new Properties(), event); - }).hasMessage( - "execute: logic for NULL:0.0.0:NULL:NULL returned a non-boolean value [JavaClass java.lang.String]"); + }).hasMessage("execute-post: task selection logic failed on state \"NULL:0.0.0:NULL:NULL\""); - assertThatThrownBy(() -> { - jtse.prepare(); - }).hasMessage( - "initiation failed, executor NULL:0.0.0:NULL:NULL already initialized, run cleanUp to clear executor"); - - assertThatCode(() -> { - jtse.cleanUp(); - }).doesNotThrowAnyException(); - - JavascriptTaskSelectExecutor jtse1 = new JavascriptTaskSelectExecutor(); - jtse1.setContext(null, state, internalContext); - state.getTaskSelectionLogic().setLogic("var x = 1\n" + "true;"); - - assertThatCode(() -> { - jtse1.prepare(); - AxArtifactKey taskKey = jtse1.execute(0, new Properties(), event); - assertEquals("NULL:0.0.0", taskKey.getId()); - jtse1.cleanUp(); - }).doesNotThrowAnyException(); + state.getTaskSelectionLogic().setLogic("var x = 1\n" + "true; "); + + jtse.prepare(); + AxArtifactKey taskKey = jtse.execute(0, new Properties(), event); + assertEquals("NULL:0.0.0", taskKey.getId()); + jtse.cleanUp(); } } -- cgit 1.2.3-korg