]> git.basschouten.com Git - openhab-addons.git/blob
e153d3ac981eb9bf5d8c7ef3e355e25afa473fcf
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.transform.javascript.internal;
14
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.junit.jupiter.api.Assumptions.assumeTrue;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.nio.file.Files;
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.util.Comparator;
24 import java.util.stream.Stream;
25
26 import org.junit.jupiter.api.AfterEach;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.junit.jupiter.api.extension.ExtendWith;
30 import org.mockito.Mock;
31 import org.mockito.junit.jupiter.MockitoExtension;
32 import org.mockito.junit.jupiter.MockitoSettings;
33 import org.mockito.quality.Strictness;
34 import org.openhab.core.transform.TransformationException;
35 import org.osgi.framework.BundleContext;
36
37 /**
38  * @author Pauli Anttila - Initial contribution
39  */
40 @ExtendWith(MockitoExtension.class)
41 @MockitoSettings(strictness = Strictness.LENIENT)
42 public class JavaScriptTransformationServiceTest {
43
44     private static final boolean NASHORN_AVAILABLE = isNashornAvailable();
45
46     private static final String BASE_FOLDER = "target";
47     private static final String SRC_FOLDER = "conf";
48     private static final String CONFIG_FOLDER = BASE_FOLDER + File.separator + SRC_FOLDER;
49
50     private @Mock BundleContext bundleContext;
51
52     private TestableJavaScriptTransformationService processor;
53
54     private class TestableJavaScriptTransformationService extends JavaScriptTransformationService {
55         public TestableJavaScriptTransformationService(JavaScriptEngineManager manager) {
56             super(manager);
57         }
58     };
59
60     /**
61      * Returns if the Nashorn JavaScript engine is available based on the Java specification version property.
62      * Nashorn has been removed from JDK 15 and onwards.
63      *
64      * @return {@code true} if Nashorn is available, {@code false} otherwise
65      */
66     private static boolean isNashornAvailable() {
67         try {
68             String javaVersion = System.getProperty("java.specification.version");
69             return javaVersion == null ? false : Long.parseLong(javaVersion) < 15;
70         } catch (NumberFormatException e) {
71             return false;
72         }
73     }
74
75     @BeforeEach
76     public void setUp() throws IOException {
77         assumeTrue(NASHORN_AVAILABLE);
78
79         JavaScriptEngineManager manager = new JavaScriptEngineManager();
80         processor = new TestableJavaScriptTransformationService(manager);
81         copyDirectory(SRC_FOLDER, CONFIG_FOLDER);
82     }
83
84     @AfterEach
85     public void tearDown() throws IOException {
86         Path path = Path.of(CONFIG_FOLDER);
87         if (Files.exists(path)) {
88             try (Stream<Path> walk = Files.walk(path)) {
89                 walk.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
90             }
91         }
92     }
93
94     private void copyDirectory(String from, String to) throws IOException {
95         Files.walk(Paths.get(from)).forEach(fromPath -> {
96             Path toPath = Paths.get(to, fromPath.toString().substring(from.length()));
97             try {
98                 Files.copy(fromPath, toPath);
99             } catch (IOException e) {
100             }
101         });
102     }
103
104     @Test
105     public void testInlineScript() throws Exception {
106         final String DATA = "100";
107         final String SCRIPT = "| input / 10";
108
109         String transformedResponse = processor.transform(SCRIPT, DATA);
110         assertEquals("10.0", transformedResponse);
111     }
112
113     @Test
114     public void testInlineScriptIncludingPipe() throws Exception {
115         final String DATA = "1";
116         final String SCRIPT = "| false || (input == '1')";
117
118         String transformedResponse = processor.transform(SCRIPT, DATA);
119         assertEquals("true", transformedResponse);
120     }
121
122     @Test
123     public void testReadmeExampleWithoutSubFolder() throws Exception {
124         final String DATA = "foo bar baz";
125         final String SCRIPT = "readme.js";
126
127         String transformedResponse = processor.transform(SCRIPT, DATA);
128         assertEquals("3", transformedResponse);
129     }
130
131     @Test
132     public void testReadmeExampleWithSubFolders() throws Exception {
133         final String DATA = "foo bar baz";
134         final String SCRIPT = "js/readme/readme.js";
135
136         String transformedResponse = processor.transform(SCRIPT, DATA);
137         assertEquals("3", transformedResponse);
138     }
139
140     @Test
141     public void testReadmeScaleExample() throws Exception {
142         final String DATA = "214";
143         final String SCRIPT = "scale.js?correctionFactor=1.1&divider=10.js";
144
145         String transformedResponse = processor.transform(SCRIPT, DATA);
146         assertEquals("23.54", transformedResponse);
147     }
148
149     @Test
150     public void testAdditionalVariables() throws Exception {
151         final String DATA = "100";
152         final String SCRIPT = "sum.js?a=10&b=1";
153
154         String transformedResponse = processor.transform(SCRIPT, DATA);
155         assertEquals("111", transformedResponse);
156     }
157
158     @Test
159     public void testIllegalVariableName() throws Exception {
160         final String DATA = "100";
161         final String SCRIPT = "sum.js?a=10&input=fail&b=1";
162
163         Exception exception = assertThrows(TransformationException.class, () -> processor.transform(SCRIPT, DATA));
164         assertEquals("'input' word is reserved and can't be used in additional parameters", exception.getMessage());
165     }
166
167     @Test
168     public void testIllegalQuestionmarkSequence() throws Exception {
169         final String DATA = "100";
170         final String SCRIPT = "sum.js?a=1&test=ab?d&b=2";
171
172         Exception exception = assertThrows(TransformationException.class, () -> processor.transform(SCRIPT, DATA));
173         assertEquals("Questionmark should be defined only once in the filename", exception.getMessage());
174     }
175
176     @Test
177     public void testIllegalAmbersandSequence() throws Exception {
178         final String DATA = "foo";
179         final String SCRIPT = "returntest.js?a=1&test=ab&d&b=2";
180
181         Exception exception = assertThrows(TransformationException.class, () -> processor.transform(SCRIPT, DATA));
182         assertEquals("Illegal filename syntax", exception.getMessage());
183     }
184
185     @Test
186     public void testEncodedSpecialCharacters() throws Exception {
187         final String DATA = "100";
188         final String SCRIPT = "returntest.js?a=1&test=ab%3Fd%26f&b=2";
189
190         String transformedResponse = processor.transform(SCRIPT, DATA);
191         assertEquals("ab?d&f", transformedResponse);
192     }
193 }