2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.apex.plugins.executor.javascript;
23 import static org.assertj.core.api.Assertions.assertThatCode;
24 import static org.assertj.core.api.Assertions.assertThatThrownBy;
25 import static org.awaitility.Awaitility.await;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertTrue;
29 import java.io.IOException;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
35 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
36 import org.slf4j.ext.XLogger;
37 import org.slf4j.ext.XLoggerFactory;
39 public class JavascriptExecutorTest {
40 private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptExecutorTest.class);
42 private AtomicBoolean concurrentResult = new AtomicBoolean();
45 public void beforeSetTimeouts() {
46 JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
47 JavascriptExecutor.setIntializationLatchTimeout(60);
48 JavascriptExecutor.setCleanupLatchTimeout(10);
52 public void testJavescriptExecutorConcurrencyNormal() throws StateMachineException, IOException {
53 JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
54 JavascriptExecutor.setIntializationLatchTimeout(60);
55 JavascriptExecutor.setCleanupLatchTimeout(10);
57 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
59 assertThatThrownBy(() -> {
61 }).hasMessageMatching("^javascriptCode is marked .*on.*ull but is null$");
63 assertThatThrownBy(() -> {
65 }).hasMessage("initiation failed, no logic specified for executor executor:0.0.1");
67 assertThatCode(() -> {
68 executor.init("var x = 1;");
69 }).doesNotThrowAnyException();
71 assertThatThrownBy(() -> {
72 executor.init("var x = 1;");
73 }).hasMessage("initiation failed, executor executor:0.0.1 already initialized, run cleanUp to clear executor");
75 assertThatCode(() -> {
77 }).doesNotThrowAnyException();
79 assertThatThrownBy(() -> {
81 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
83 assertThatThrownBy(() -> {
84 executor.execute("Hello");
85 }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
87 assertThatCode(() -> {
88 executor.init("var x = 1;");
89 }).doesNotThrowAnyException();
91 assertThatThrownBy(() -> {
92 executor.execute("Hello");
94 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
96 assertThatThrownBy(() -> {
97 executor.execute("Hello");
99 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
101 assertThatThrownBy(() -> {
102 executor.execute("Hello");
104 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
106 assertThatThrownBy(() -> {
107 executor.execute("Hello");
109 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
111 assertThatCode(() -> {
113 }).doesNotThrowAnyException();
115 assertThatThrownBy(() -> {
117 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
119 assertThatThrownBy(() -> {
120 executor.execute("hello");
121 }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
125 public void testJavescriptExecutorConcurrencyLatchTimeout() throws StateMachineException, IOException {
126 JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS);
127 JavascriptExecutor.setIntializationLatchTimeout(1);
128 JavascriptExecutor.setCleanupLatchTimeout(10000000);
130 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
132 assertThatThrownBy(() -> {
133 executor.init("var x = 1;");
134 }).hasMessage("JavascriptExecutor executor:0.0.1 initiation timed out after 1 MICROSECONDS");
136 assertThatCode(() -> {
138 }).doesNotThrowAnyException();
140 JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
141 JavascriptExecutor.setIntializationLatchTimeout(60);
143 assertThatCode(() -> {
144 executor.init("var x = 1;");
145 }).doesNotThrowAnyException();
147 assertThatCode(() -> {
149 }).doesNotThrowAnyException();
151 JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS);
152 JavascriptExecutor.setIntializationLatchTimeout(60000000);
153 JavascriptExecutor.setCleanupLatchTimeout(1);
155 assertThatCode(() -> {
156 executor.init("var x = 1;");
157 }).doesNotThrowAnyException();
159 assertThatThrownBy(() -> {
161 }).hasMessage("JavascriptExecutor executor:0.0.1 cleanup timed out after 1 MICROSECONDS");
163 JavascriptExecutor.setCleanupLatchTimeout(10000000);
164 assertThatThrownBy(() -> {
166 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
168 assertThatCode(() -> {
169 executor.init("var x = 1;");
170 }).doesNotThrowAnyException();
172 assertThatCode(() -> {
174 }).doesNotThrowAnyException();
178 public void testJavescriptExecutorBadStates() throws StateMachineException, IOException {
179 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
181 assertThatThrownBy(() -> {
182 executor.execute("hello");
183 }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
185 assertThatThrownBy(() -> {
187 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
189 assertThatCode(() -> {
190 executor.init("var x = 1;");
191 }).doesNotThrowAnyException();
193 executor.getExecutorThread().interrupt();
194 await().atMost(10, TimeUnit.SECONDS).until(() -> !executor.getExecutorThread().isAlive());
196 assertThatThrownBy(() -> {
197 executor.execute("hello");
198 }).hasMessage("execution failed, executor executor:0.0.1 is not running, "
199 + "run cleanUp to clear executor and init to restart executor");
201 assertThatThrownBy(() -> {
202 executor.execute("hello");
203 }).hasMessage("execution failed, executor executor:0.0.1 is not running, "
204 + "run cleanUp to clear executor and init to restart executor");
206 assertThatCode(() -> {
208 }).doesNotThrowAnyException();
212 public void testJavescriptExecutorExecution() throws StateMachineException, IOException {
213 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
215 assertThatCode(() -> {
216 executor.init("true;");
217 }).doesNotThrowAnyException();
219 assertThatCode(() -> {
220 assertTrue(executor.execute("hello"));
221 }).doesNotThrowAnyException();
223 assertThatCode(() -> {
225 }).doesNotThrowAnyException();
227 assertThatCode(() -> {
228 executor.init("false;");
229 }).doesNotThrowAnyException();
231 assertThatCode(() -> {
232 assertFalse(executor.execute("hello"));
233 }).doesNotThrowAnyException();
235 assertThatCode(() -> {
237 }).doesNotThrowAnyException();
239 assertThatThrownBy(() -> {
240 executor.init("aaaaa = \"sss");
242 "logic failed to compile for executor:0.0.1 with message: unterminated string literal (executor:0.0.1#1)");
244 assertThatCode(() -> {
246 }).doesNotThrowAnyException();
248 assertThatCode(() -> {
249 executor.init("true;");
250 }).doesNotThrowAnyException();
252 assertThatCode(() -> {
253 assertTrue(executor.execute("hello"));
254 }).doesNotThrowAnyException();
256 assertThatCode(() -> {
258 }).doesNotThrowAnyException();
260 assertThatCode(() -> {
261 executor.init("throw \"this is an error\";");
262 }).doesNotThrowAnyException();
264 assertThatThrownBy(() -> {
265 assertTrue(executor.execute("hello"));
266 }).hasMessage("logic failed to run for executor:0.0.1 with message: this is an error (executor:0.0.1#1)");
268 assertThatCode(() -> {
270 }).doesNotThrowAnyException();
272 assertThatCode(() -> {
273 executor.init("var x = 0; while (x < 100) { x++; }; true;");
274 }).doesNotThrowAnyException();
276 concurrentResult.set(true);
278 // Execute an infinite loop in Javascript
282 while (executor.execute("hello")) {
283 LOGGER.debug("test thread running . . .");
284 // Loop until interrupted
286 } catch (StateMachineException e) {
287 LOGGER.debug("test thread caught exception", e);
289 concurrentResult.set(false);
290 LOGGER.debug("test thread exited");
294 await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> executor.getExecutorThread().isAlive());
296 executor.getExecutorThread().interrupt();
298 await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> !concurrentResult.get());
300 assertThatCode(() -> {
302 }).doesNotThrowAnyException();
304 assertThatCode(() -> {
305 executor.init("true;");
306 }).doesNotThrowAnyException();
308 assertThatCode(() -> {
309 assertTrue(executor.execute("hello"));
310 }).doesNotThrowAnyException();
312 assertThatCode(() -> {
314 }).doesNotThrowAnyException();
316 assertThatCode(() -> {
317 executor.init("x = 1; true;");
318 }).doesNotThrowAnyException();
320 concurrentResult.set(true);
322 // Execute an infinite loop in Javascript
323 Thread executionThread = new Thread() {
326 while (executor.execute("hello")) {
329 } catch (StateMachineException e) {
334 executionThread.start();
336 executionThread.interrupt();
338 await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executionThread.isAlive());
339 await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executor.getExecutorThread().isAlive());
341 assertThatCode(() -> {
343 }).doesNotThrowAnyException();