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;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
36 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
37 import org.slf4j.ext.XLogger;
38 import org.slf4j.ext.XLoggerFactory;
40 public class JavascriptExecutorTest {
41 private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptExecutorTest.class);
43 private AtomicBoolean concurrentResult = new AtomicBoolean();
46 public void beforeSetTimeouts() {
47 JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
48 JavascriptExecutor.setIntializationLatchTimeout(60);
49 JavascriptExecutor.setCleanupLatchTimeout(10);
53 public void testJavescriptExecutorConcurrencyNormal() throws StateMachineException, IOException {
54 JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
55 JavascriptExecutor.setIntializationLatchTimeout(60);
56 JavascriptExecutor.setCleanupLatchTimeout(10);
58 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
60 assertThatThrownBy(() -> {
62 }).hasMessageMatching("^javascriptCode is marked .*on.*ull but is null$");
64 assertThatThrownBy(() -> {
66 }).hasMessage("initiation failed, no logic specified for executor executor:0.0.1");
68 assertThatCode(() -> {
69 executor.init("var x = 1;");
70 }).doesNotThrowAnyException();
72 assertThatThrownBy(() -> {
73 executor.init("var x = 1;");
74 }).hasMessage("initiation failed, executor executor:0.0.1 already initialized, run cleanUp to clear executor");
76 assertThatCode(() -> {
78 }).doesNotThrowAnyException();
80 assertThatThrownBy(() -> {
82 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
84 assertThatThrownBy(() -> {
85 executor.execute("Hello");
86 }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
88 assertThatCode(() -> {
89 executor.init("var x = 1;");
90 }).doesNotThrowAnyException();
92 assertThatThrownBy(() -> {
93 executor.execute("Hello");
95 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
97 assertThatThrownBy(() -> {
98 executor.execute("Hello");
100 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
102 assertThatThrownBy(() -> {
103 executor.execute("Hello");
105 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
107 assertThatThrownBy(() -> {
108 executor.execute("Hello");
110 "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
112 assertThatCode(() -> {
114 }).doesNotThrowAnyException();
116 assertThatThrownBy(() -> {
118 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
120 assertThatThrownBy(() -> {
121 executor.execute("hello");
122 }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
126 public void testJavescriptExecutorConcurrencyLatchTimeout() throws StateMachineException, IOException {
127 JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS);
128 JavascriptExecutor.setIntializationLatchTimeout(1);
129 JavascriptExecutor.setCleanupLatchTimeout(10000000);
131 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
133 assertThatThrownBy(() -> {
134 executor.init("var x = 1;");
135 }).hasMessage("JavascriptExecutor executor:0.0.1 initiation timed out after 1 MICROSECONDS");
137 assertThatCode(() -> {
139 }).doesNotThrowAnyException();
141 JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
142 JavascriptExecutor.setIntializationLatchTimeout(60);
144 assertThatCode(() -> {
145 executor.init("var x = 1;");
146 }).doesNotThrowAnyException();
148 assertThatCode(() -> {
150 }).doesNotThrowAnyException();
152 JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS);
153 JavascriptExecutor.setIntializationLatchTimeout(60000000);
154 JavascriptExecutor.setCleanupLatchTimeout(1);
156 assertThatCode(() -> {
157 executor.init("var x = 1;");
158 }).doesNotThrowAnyException();
160 assertThatThrownBy(() -> {
162 }).hasMessage("JavascriptExecutor executor:0.0.1 cleanup timed out after 1 MICROSECONDS");
164 JavascriptExecutor.setCleanupLatchTimeout(10000000);
165 assertThatThrownBy(() -> {
167 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
169 assertThatCode(() -> {
170 executor.init("var x = 1;");
171 }).doesNotThrowAnyException();
173 assertThatCode(() -> {
175 }).doesNotThrowAnyException();
179 public void testJavescriptExecutorBadStates() throws StateMachineException, IOException {
180 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
182 assertThatThrownBy(() -> {
183 executor.execute("hello");
184 }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
186 assertThatThrownBy(() -> {
188 }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
190 assertThatCode(() -> {
191 executor.init("var x = 1;");
192 }).doesNotThrowAnyException();
194 executor.getExecutorThread().interrupt();
195 await().atMost(10, TimeUnit.SECONDS).until(() -> !executor.getExecutorThread().isAlive());
197 assertThatThrownBy(() -> {
198 executor.execute("hello");
199 }).hasMessage("execution failed, executor executor:0.0.1 is not running, "
200 + "run cleanUp to clear executor and init to restart executor");
202 assertThatThrownBy(() -> {
203 executor.execute("hello");
204 }).hasMessage("execution failed, executor executor:0.0.1 is not running, "
205 + "run cleanUp to clear executor and init to restart executor");
207 assertThatCode(() -> {
209 }).doesNotThrowAnyException();
213 public void testJavescriptExecutorExecution() throws StateMachineException, IOException {
214 JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
216 assertThatCode(() -> {
217 executor.init("true;");
218 }).doesNotThrowAnyException();
220 assertThatCode(() -> {
221 assertTrue(executor.execute("hello"));
222 }).doesNotThrowAnyException();
224 assertThatCode(() -> {
226 }).doesNotThrowAnyException();
228 assertThatCode(() -> {
229 executor.init("false;");
230 }).doesNotThrowAnyException();
232 assertThatCode(() -> {
233 assertFalse(executor.execute("hello"));
234 }).doesNotThrowAnyException();
236 assertThatCode(() -> {
238 }).doesNotThrowAnyException();
240 assertThatThrownBy(() -> {
241 executor.init("aaaaa = \"sss");
243 "logic failed to compile for executor:0.0.1 with message: unterminated string literal (executor:0.0.1#1)");
245 assertThatCode(() -> {
247 }).doesNotThrowAnyException();
249 assertThatCode(() -> {
250 executor.init("true;");
251 }).doesNotThrowAnyException();
253 assertThatCode(() -> {
254 assertTrue(executor.execute("hello"));
255 }).doesNotThrowAnyException();
257 assertThatCode(() -> {
259 }).doesNotThrowAnyException();
261 assertThatCode(() -> {
262 executor.init("throw \"this is an error\";");
263 }).doesNotThrowAnyException();
265 assertThatThrownBy(() -> {
266 assertTrue(executor.execute("hello"));
267 }).hasMessage("logic failed to run for executor:0.0.1 with message: this is an error (executor:0.0.1#1)");
269 assertThatCode(() -> {
271 }).doesNotThrowAnyException();
273 assertThatCode(() -> {
274 executor.init("var x = 0; while (x < 100) { x++; }; true;");
275 }).doesNotThrowAnyException();
277 concurrentResult.set(true);
279 // Execute an infinite loop in Javascript
283 while (executor.execute("hello")) {
284 LOGGER.debug("test thread running . . .");
285 // Loop until interrupted
287 } catch (StateMachineException e) {
288 LOGGER.debug("test thread caught exception", e);
290 concurrentResult.set(false);
291 LOGGER.debug("test thread exited");
295 await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> executor.getExecutorThread().isAlive());
297 executor.getExecutorThread().interrupt();
299 await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> !concurrentResult.get());
301 assertThatCode(() -> {
303 }).doesNotThrowAnyException();
305 assertThatCode(() -> {
306 executor.init("true;");
307 }).doesNotThrowAnyException();
309 assertThatCode(() -> {
310 assertTrue(executor.execute("hello"));
311 }).doesNotThrowAnyException();
313 assertThatCode(() -> {
315 }).doesNotThrowAnyException();
317 assertThatCode(() -> {
318 executor.init("x = 1; true;");
319 }).doesNotThrowAnyException();
321 concurrentResult.set(true);
323 // Execute an infinite loop in Javascript
324 Thread executionThread = new Thread() {
327 while (executor.execute("hello")) {
330 } catch (StateMachineException e) {
335 executionThread.start();
337 executionThread.interrupt();
339 await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executionThread.isAlive());
340 await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executor.getExecutorThread().isAlive());
342 assertThatCode(() -> {
344 }).doesNotThrowAnyException();