2 * Copyright (c) 2010-2020 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.binding.tplinksmarthome.internal.device;
15 import static org.junit.Assert.assertEquals;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.*;
18 import static org.mockito.MockitoAnnotations.initMocks;
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.net.Socket;
24 import java.util.concurrent.atomic.AtomicInteger;
25 import java.util.function.Function;
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.junit.Before;
29 import org.mockito.Mock;
30 import org.openhab.binding.tplinksmarthome.internal.Connection;
31 import org.openhab.binding.tplinksmarthome.internal.CryptUtil;
32 import org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeConfiguration;
33 import org.openhab.binding.tplinksmarthome.internal.model.ModelTestUtil;
36 * Base class for tests that test classes extending {@link SmartHomeDevice} class.
38 * @author Hilbrand Bouwkamp - Initial contribution
41 public class DeviceTestBase<T extends SmartHomeDevice> {
43 protected final T device;
44 protected final Connection connection;
45 protected final TPLinkSmartHomeConfiguration configuration = new TPLinkSmartHomeConfiguration();
46 protected @NonNullByDefault({}) DeviceState deviceState;
48 private final String deviceStateFilename;
51 private @NonNullByDefault({}) Socket socket;
53 private @NonNullByDefault({}) OutputStream outputStream;
58 * @param device Device under test
59 * @param deviceStateFilename name of the file to read the device state json from to use in tests
61 * @throws IOException exception in case device not reachable
63 protected DeviceTestBase(T device, String deviceStateFilename) throws IOException {
65 this.deviceStateFilename = deviceStateFilename;
66 configuration.ipAddress = "localhost";
67 configuration.refresh = 30;
68 configuration.transitionPeriod = 10;
69 connection = new Connection(configuration.ipAddress) {
71 protected Socket createSocket() throws IOException {
75 device.initialize(connection, configuration);
79 public void setUp() throws IOException {
81 when(socket.getOutputStream()).thenReturn(outputStream);
82 deviceState = new DeviceState(ModelTestUtil.readJson(deviceStateFilename));
86 * Sets the answer to return when the socket.getInputStream() is requested. If multiple files are given they will
87 * returned in order each time a call to socket.getInputStream() is done.
89 * @param responseFilenames names of the files to read that contains the answer. It's the unencrypted json string
90 * @throws IOException exception in case device not reachable
92 protected void setSocketReturnAssert(String... responseFilenames) throws IOException {
93 AtomicInteger index = new AtomicInteger();
96 String stateResponse = ModelTestUtil.readJson(responseFilenames[index.getAndIncrement()]);
98 return new ByteArrayInputStream(CryptUtil.encryptWithLength(stateResponse));
99 }).when(socket).getInputStream();
103 * Asserts the value passed to outputstream.write, which is the call that would be made to the actual device. This
104 * checks if the value sent to the device is what is expected to be sent to the device. If multiple files are given
105 * they will be used to check in order each time a call outputstream.write is done.
107 * @param filenames names of the files containing the reference json
108 * @throws IOException exception in case device not reachable
110 protected void assertInput(String... filenames) throws IOException {
111 assertInput(Function.identity(), Function.identity(), filenames);
114 protected void assertInput(Function<String, String> jsonProcessor, Function<String, String> expectedProcessor,
115 String... filenames) throws IOException {
116 AtomicInteger index = new AtomicInteger();
119 String json = jsonProcessor.apply(ModelTestUtil.readJson(filenames[index.get()]));
121 byte[] input = (byte[]) arg.getArguments()[0];
122 try (ByteArrayInputStream inputStream = new ByteArrayInputStream(input)) {
123 String expectedString = expectedProcessor.apply(CryptUtil.decryptWithLength(inputStream));
124 assertEquals(filenames[index.get()], json, expectedString);
126 index.incrementAndGet();
128 }).when(outputStream).write(any());