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