56ebf997230e2f7eddc62b2fe4f11cdc2b69d5ac
[policy/apex-pdp.git] / plugins / plugins-executor / plugins-executor-javascript / src / test / java / org / onap / policy / apex / plugins / executor / javascript / JavascriptExecutorTest.java
1 /*-
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.plugins.executor.javascript;
22
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;
28
29 import java.io.IOException;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicBoolean;
32
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;
39
40 public class JavascriptExecutorTest {
41     private static final XLogger LOGGER = XLoggerFactory.getXLogger(JavascriptExecutorTest.class);
42
43     private AtomicBoolean concurrentResult = new AtomicBoolean();
44
45     @Before
46     public void beforeSetTimeouts() {
47         JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
48         JavascriptExecutor.setIntializationLatchTimeout(60);
49         JavascriptExecutor.setCleanupLatchTimeout(10);
50     }
51
52     @Test
53     public void testJavescriptExecutorConcurrencyNormal() throws StateMachineException, IOException {
54         JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
55         JavascriptExecutor.setIntializationLatchTimeout(60);
56         JavascriptExecutor.setCleanupLatchTimeout(10);
57
58         JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
59
60         assertThatThrownBy(() -> {
61             executor.init(null);
62         }).hasMessageMatching("^javascriptCode is marked .*on.*ull but is null$");
63
64         assertThatThrownBy(() -> {
65             executor.init("   ");
66         }).hasMessage("initiation failed, no logic specified for executor executor:0.0.1");
67
68         assertThatCode(() -> {
69             executor.init("var x = 1;");
70         }).doesNotThrowAnyException();
71
72         assertThatThrownBy(() -> {
73             executor.init("var x = 1;");
74         }).hasMessage("initiation failed, executor executor:0.0.1 already initialized, run cleanUp to clear executor");
75
76         assertThatCode(() -> {
77             executor.cleanUp();
78         }).doesNotThrowAnyException();
79
80         assertThatThrownBy(() -> {
81             executor.cleanUp();
82         }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
83
84         assertThatThrownBy(() -> {
85             executor.execute("Hello");
86         }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
87
88         assertThatCode(() -> {
89             executor.init("var x = 1;");
90         }).doesNotThrowAnyException();
91
92         assertThatThrownBy(() -> {
93             executor.execute("Hello");
94         }).hasMessage(
95             "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
96
97         assertThatThrownBy(() -> {
98             executor.execute("Hello");
99         }).hasMessage(
100             "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
101
102         assertThatThrownBy(() -> {
103             executor.execute("Hello");
104         }).hasMessage(
105             "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
106
107         assertThatThrownBy(() -> {
108             executor.execute("Hello");
109         }).hasMessage(
110             "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0");
111
112         assertThatCode(() -> {
113             executor.cleanUp();
114         }).doesNotThrowAnyException();
115
116         assertThatThrownBy(() -> {
117             executor.cleanUp();
118         }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
119
120         assertThatThrownBy(() -> {
121             executor.execute("hello");
122         }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
123     }
124
125     @Test
126     public void testJavescriptExecutorConcurrencyLatchTimeout() throws StateMachineException, IOException {
127         JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS);
128         JavascriptExecutor.setIntializationLatchTimeout(1);
129         JavascriptExecutor.setCleanupLatchTimeout(10000000);
130
131         JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
132
133         assertThatThrownBy(() -> {
134             executor.init("var x = 1;");
135         }).hasMessage("JavascriptExecutor executor:0.0.1 initiation timed out after 1 MICROSECONDS");
136
137         assertThatCode(() -> {
138             executor.cleanUp();
139         }).doesNotThrowAnyException();
140
141         JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS);
142         JavascriptExecutor.setIntializationLatchTimeout(60);
143
144         assertThatCode(() -> {
145             executor.init("var x = 1;");
146         }).doesNotThrowAnyException();
147
148         assertThatCode(() -> {
149             executor.cleanUp();
150         }).doesNotThrowAnyException();
151
152         JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS);
153         JavascriptExecutor.setIntializationLatchTimeout(60000000);
154         JavascriptExecutor.setCleanupLatchTimeout(1);
155
156         assertThatCode(() -> {
157             executor.init("var x = 1;");
158         }).doesNotThrowAnyException();
159
160         assertThatThrownBy(() -> {
161             executor.cleanUp();
162         }).hasMessage("JavascriptExecutor executor:0.0.1 cleanup timed out after 1 MICROSECONDS");
163
164         JavascriptExecutor.setCleanupLatchTimeout(10000000);
165         assertThatThrownBy(() -> {
166             executor.cleanUp();
167         }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
168
169         assertThatCode(() -> {
170             executor.init("var x = 1;");
171         }).doesNotThrowAnyException();
172
173         assertThatCode(() -> {
174             executor.cleanUp();
175         }).doesNotThrowAnyException();
176     }
177
178     @Test
179     public void testJavescriptExecutorBadStates() throws StateMachineException, IOException {
180         JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
181
182         assertThatThrownBy(() -> {
183             executor.execute("hello");
184         }).hasMessage("execution failed, executor executor:0.0.1 is not initialized");
185
186         assertThatThrownBy(() -> {
187             executor.cleanUp();
188         }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized");
189
190         assertThatCode(() -> {
191             executor.init("var x = 1;");
192         }).doesNotThrowAnyException();
193
194         executor.getExecutorThread().interrupt();
195         await().atMost(10, TimeUnit.SECONDS).until(() -> !executor.getExecutorThread().isAlive());
196
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");
201
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");
206
207         assertThatCode(() -> {
208             executor.cleanUp();
209         }).doesNotThrowAnyException();
210     }
211
212     @Test
213     public void testJavescriptExecutorExecution() throws StateMachineException, IOException {
214         JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1"));
215
216         assertThatCode(() -> {
217             executor.init("true;");
218         }).doesNotThrowAnyException();
219
220         assertThatCode(() -> {
221             assertTrue(executor.execute("hello"));
222         }).doesNotThrowAnyException();
223
224         assertThatCode(() -> {
225             executor.cleanUp();
226         }).doesNotThrowAnyException();
227
228         assertThatCode(() -> {
229             executor.init("false;");
230         }).doesNotThrowAnyException();
231
232         assertThatCode(() -> {
233             assertFalse(executor.execute("hello"));
234         }).doesNotThrowAnyException();
235
236         assertThatCode(() -> {
237             executor.cleanUp();
238         }).doesNotThrowAnyException();
239
240         assertThatThrownBy(() -> {
241             executor.init("aaaaa = \"sss");
242         }).hasMessage(
243             "logic failed to compile for executor:0.0.1 with message: unterminated string literal (executor:0.0.1#1)");
244
245         assertThatCode(() -> {
246             executor.cleanUp();
247         }).doesNotThrowAnyException();
248
249         assertThatCode(() -> {
250             executor.init("true;");
251         }).doesNotThrowAnyException();
252
253         assertThatCode(() -> {
254             assertTrue(executor.execute("hello"));
255         }).doesNotThrowAnyException();
256
257         assertThatCode(() -> {
258             executor.cleanUp();
259         }).doesNotThrowAnyException();
260
261         assertThatCode(() -> {
262             executor.init("throw \"this is an error\";");
263         }).doesNotThrowAnyException();
264
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)");
268
269         assertThatCode(() -> {
270             executor.cleanUp();
271         }).doesNotThrowAnyException();
272
273         assertThatCode(() -> {
274             executor.init("var x = 0; while (x < 100) { x++; }; true;");
275         }).doesNotThrowAnyException();
276
277         concurrentResult.set(true);
278
279         // Execute an infinite loop in Javascript
280         (new Thread() {
281             public void run() {
282                 try {
283                     while (executor.execute("hello")) {
284                         LOGGER.debug("test thread running . . .");
285                         // Loop until interrupted
286                     }
287                 } catch (StateMachineException e) {
288                     LOGGER.debug("test thread caught exception", e);
289                 }
290                 concurrentResult.set(false);
291                 LOGGER.debug("test thread exited");
292             }
293         }).start();
294
295         await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> executor.getExecutorThread().isAlive());
296
297         executor.getExecutorThread().interrupt();
298
299         await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> !concurrentResult.get());
300
301         assertThatCode(() -> {
302             executor.cleanUp();
303         }).doesNotThrowAnyException();
304
305         assertThatCode(() -> {
306             executor.init("true;");
307         }).doesNotThrowAnyException();
308
309         assertThatCode(() -> {
310             assertTrue(executor.execute("hello"));
311         }).doesNotThrowAnyException();
312
313         assertThatCode(() -> {
314             executor.cleanUp();
315         }).doesNotThrowAnyException();
316
317         assertThatCode(() -> {
318             executor.init("x = 1; true;");
319         }).doesNotThrowAnyException();
320
321         concurrentResult.set(true);
322
323         // Execute an infinite loop in Javascript
324         Thread executionThread = new Thread() {
325             public void run() {
326                 try {
327                     while (executor.execute("hello")) {
328                         ;
329                     }
330                 } catch (StateMachineException e) {
331                     ;
332                 }
333             }
334         };
335         executionThread.start();
336
337         executionThread.interrupt();
338
339         await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executionThread.isAlive());
340         await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executor.getExecutorThread().isAlive());
341
342         assertThatCode(() -> {
343             executor.cleanUp();
344         }).doesNotThrowAnyException();
345     }
346 }