Remove thread in JavascriptExecutor 42/109242/5
authorhuaxing <huaxing.jin@est.tech>
Wed, 17 Jun 2020 05:34:10 +0000 (13:34 +0800)
committerLiam Fallon <liam.fallon@est.tech>
Tue, 23 Jun 2020 13:23:02 +0000 (13:23 +0000)
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 <huaxing.jin@est.tech>
Change-Id: I3a52d0ead0c1e530d218f9e3aba8b3eb5558abaf

plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java
plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java
plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java
plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java
plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java

index 0eecd5d..344f8c5 100644 (file)
 
 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<Object> executionQueue = new LinkedBlockingQueue<>();
-    private final BlockingQueue<Boolean> resultQueue = new LinkedBlockingQueue<>();
-
-    @Getter(AccessLevel.PROTECTED)
-    private Thread executorThread;
-    private CountDownLatch intializationLatch;
-    private CountDownLatch cleanupLatch;
-    private AtomicReference<StateMachineException> 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();
         }
     }
 }
index ffd0925..24c6b76 100644 (file)
@@ -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<String, Object> incomingFields) throws StateMachineException, ContextException {
-        // Do execution pre work
+            final Map<String, Object> 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());
     }
 }
index 9f30f83..a25dca0 100644 (file)
@@ -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<String, Object> execute(final long executionId, final Properties executionProperties,
-        final Map<String, Object> incomingFields) throws StateMachineException, ContextException {
-
-        // Do execution pre work
+            final Map<String, Object> 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());
     }
 }
index d7b137f..5c28999 100644 (file)
@@ -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());
     }
 }
index 2b1c92f..394126b 100644 (file)
@@ -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);
     }
 }
index e45f35c..948fc02 100644 (file)
@@ -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");
     }
 }
index f54e21e..2da6a5c 100644 (file)
@@ -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<String, Object> 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();
     }
 }
index 435397b..031d605 100644 (file)
@@ -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<String, Object> 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();
index 23b3afe..a6e410c 100644 (file)
@@ -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();
     }
 }