]> git.basschouten.com Git - openhab-addons.git/blob
02a080dc27bc2ac4ddb8164e4d1fb409975297bb
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.binding.tplinksmarthome.internal.device;
14
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;
19
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;
26
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;
34
35 /**
36  * Base class for tests that test classes extending {@link SmartHomeDevice} class.
37  *
38  * @author Hilbrand Bouwkamp - Initial contribution
39  */
40 @NonNullByDefault
41 public class DeviceTestBase<T extends SmartHomeDevice> {
42
43     protected final T device;
44     protected final Connection connection;
45     protected final TPLinkSmartHomeConfiguration configuration = new TPLinkSmartHomeConfiguration();
46     protected @NonNullByDefault({}) DeviceState deviceState;
47
48     private final String deviceStateFilename;
49
50     @Mock
51     private @NonNullByDefault({}) Socket socket;
52     @Mock
53     private @NonNullByDefault({}) OutputStream outputStream;
54
55     /**
56      * Constructor.
57      *
58      * @param device Device under test
59      * @param deviceStateFilename name of the file to read the device state json from to use in tests
60      *
61      * @throws IOException exception in case device not reachable
62      */
63     protected DeviceTestBase(T device, String deviceStateFilename) throws IOException {
64         this.device = device;
65         this.deviceStateFilename = deviceStateFilename;
66         configuration.ipAddress = "localhost";
67         configuration.refresh = 30;
68         configuration.transitionPeriod = 10;
69         connection = new Connection(configuration.ipAddress) {
70             @Override
71             protected Socket createSocket() throws IOException {
72                 return socket;
73             }
74         };
75         device.initialize(connection, configuration);
76     }
77
78     @Before
79     public void setUp() throws IOException {
80         initMocks(this);
81         when(socket.getOutputStream()).thenReturn(outputStream);
82         deviceState = new DeviceState(ModelTestUtil.readJson(deviceStateFilename));
83     }
84
85     /**
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.
88      *
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
91      */
92     protected void setSocketReturnAssert(String... responseFilenames) throws IOException {
93         AtomicInteger index = new AtomicInteger();
94
95         doAnswer(i -> {
96             String stateResponse = ModelTestUtil.readJson(responseFilenames[index.getAndIncrement()]);
97
98             return new ByteArrayInputStream(CryptUtil.encryptWithLength(stateResponse));
99         }).when(socket).getInputStream();
100     }
101
102     /**
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.
106      *
107      * @param filenames names of the files containing the reference json
108      * @throws IOException exception in case device not reachable
109      */
110     protected void assertInput(String... filenames) throws IOException {
111         assertInput(Function.identity(), Function.identity(), filenames);
112     }
113
114     protected void assertInput(Function<String, String> jsonProcessor, Function<String, String> expectedProcessor,
115             String... filenames) throws IOException {
116         AtomicInteger index = new AtomicInteger();
117
118         doAnswer(arg -> {
119             String json = jsonProcessor.apply(ModelTestUtil.readJson(filenames[index.get()]));
120
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);
125             }
126             index.incrementAndGet();
127             return null;
128         }).when(outputStream).write(any());
129     }
130 }