2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.transform.map.internal;
15 import static org.junit.jupiter.api.Assertions.*;
18 import java.io.FileReader;
19 import java.io.FileWriter;
20 import java.io.IOException;
21 import java.io.PrintStream;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.nio.file.Paths;
25 import java.util.Comparator;
26 import java.util.Locale;
27 import java.util.Properties;
28 import java.util.concurrent.Callable;
29 import java.util.stream.Stream;
31 import org.junit.jupiter.api.AfterEach;
32 import org.junit.jupiter.api.BeforeEach;
33 import org.junit.jupiter.api.Test;
34 import org.junit.jupiter.api.extension.ExtendWith;
35 import org.mockito.Mock;
36 import org.mockito.junit.jupiter.MockitoExtension;
37 import org.mockito.junit.jupiter.MockitoSettings;
38 import org.mockito.quality.Strictness;
39 import org.osgi.framework.BundleContext;
42 * @author Gaƫl L'hopital - Initial contribution
44 @ExtendWith(MockitoExtension.class)
45 @MockitoSettings(strictness = Strictness.WARN)
46 public class MapTransformationServiceTest {
48 private static final String SOURCE_CLOSED = "CLOSED";
49 private static final String SOURCE_UNKNOWN = "UNKNOWN";
50 private static final String EXISTING_FILENAME_DE = "map/doorstatus_de.map";
51 private static final String SHOULD_BE_LOCALIZED_FILENAME = "map/doorstatus.map";
52 private static final String DEFAULTED_FILENAME = "map/doorstatus_defaulted.map";
53 private static final String INEXISTING_FILENAME = "map/de.map";
54 private static final String BASE_FOLDER = "target";
55 private static final String SRC_FOLDER = "conf";
56 private static final String CONFIG_FOLDER = BASE_FOLDER + File.separator + SRC_FOLDER;
57 private static final String USED_FILENAME = CONFIG_FOLDER + File.separator + "transform/" + EXISTING_FILENAME_DE;
59 private @Mock BundleContext bundleContext;
61 private TestableMapTransformationService processor;
63 private class TestableMapTransformationService extends MapTransformationService {
65 protected String getSourcePath() {
66 return BASE_FOLDER + File.separator + super.getSourcePath();
70 protected Locale getLocale() {
75 public void activate(BundleContext context) {
76 super.activate(context);
80 public void deactivate() {
86 public void setUp() throws IOException {
87 processor = new TestableMapTransformationService();
88 processor.activate(bundleContext);
89 copyDirectory(SRC_FOLDER, CONFIG_FOLDER);
93 public void tearDown() throws IOException {
94 processor.deactivate();
96 try (Stream<Path> walk = Files.walk(Path.of(CONFIG_FOLDER))) {
97 walk.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
101 private void copyDirectory(String from, String to) throws IOException {
102 Files.walk(Paths.get(from)).forEach(fromPath -> {
103 Path toPath = Paths.get(to, fromPath.toString().substring(from.length()));
105 Files.copy(fromPath, toPath);
106 } catch (IOException e) {
112 public void testTransformByMap() throws Exception {
113 // Test that we find a translation in an existing file
114 String transformedResponse = processor.transform(EXISTING_FILENAME_DE, SOURCE_CLOSED);
115 assertEquals("zu", transformedResponse);
117 Properties properties = new Properties();
118 try (FileReader reader = new FileReader(USED_FILENAME); FileWriter writer = new FileWriter(USED_FILENAME)) {
119 properties.load(reader);
120 properties.setProperty(SOURCE_CLOSED, "changevalue");
121 properties.store(writer, "");
123 // This tests that the requested transformation file has been removed from
125 waitForAssert(new Callable<Void>() {
127 public Void call() throws Exception {
128 final String transformedResponse = processor.transform(EXISTING_FILENAME_DE, SOURCE_CLOSED);
129 assertEquals("changevalue", transformedResponse);
134 properties.setProperty(SOURCE_CLOSED, "zu");
135 properties.store(writer, "");
137 waitForAssert(new Callable<Void>() {
139 public Void call() throws Exception {
140 final String transformedResponse = processor.transform(EXISTING_FILENAME_DE, SOURCE_CLOSED);
141 assertEquals("zu", transformedResponse);
145 } catch (IOException e1) {
146 PrintStream err = System.err;
148 e1.printStackTrace(err);
152 // Checks that an unknown input in an existing file give the expected
153 // transformed response that shall be empty string (Issue #1107) if not found in the file
154 transformedResponse = processor.transform(EXISTING_FILENAME_DE, SOURCE_UNKNOWN);
155 assertEquals("", transformedResponse);
157 // Test that an inexisting file raises correct exception as expected
159 transformedResponse = processor.transform(INEXISTING_FILENAME, SOURCE_CLOSED);
161 } catch (Exception e) {
162 // That's what we expect.
165 // Test that we find a localized version of desired file
166 transformedResponse = processor.transform(SHOULD_BE_LOCALIZED_FILENAME, SOURCE_CLOSED);
167 // as we don't know the real locale at the moment the
168 // test is run, we test that the string has actually been transformed
169 assertNotEquals(SOURCE_CLOSED, transformedResponse);
170 transformedResponse = processor.transform(SHOULD_BE_LOCALIZED_FILENAME, SOURCE_CLOSED);
171 assertNotEquals(SOURCE_CLOSED, transformedResponse);
175 public void testTransformByMapWithDefault() throws Exception {
176 // Standard behaviour with no default value
177 String transformedResponse = processor.transform(SHOULD_BE_LOCALIZED_FILENAME, "toBeDefaulted");
178 assertEquals("", transformedResponse);
179 // Modified behaviour with a file containing default value definition
180 transformedResponse = processor.transform(DEFAULTED_FILENAME, "toBeDefaulted");
181 assertEquals("Default Value", transformedResponse);
184 protected void waitForAssert(Callable<Void> assertion, int timeout, int sleepTime) throws Exception {
186 while (waitingTime < timeout) {
190 } catch (AssertionError error) {
191 waitingTime += sleepTime;
193 Thread.sleep(sleepTime);
194 } catch (InterruptedException e) {
195 throw new RuntimeException(e);