]> git.basschouten.com Git - openhab-addons.git/blob
bd762862f815d1c4043f7b97db6b93b606a5e33e
[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.io.transport.modbus.test;
14
15 import static org.junit.jupiter.api.Assertions.*;
16
17 import java.nio.charset.Charset;
18 import java.nio.charset.StandardCharsets;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.stream.Collectors;
22 import java.util.stream.Stream;
23 import java.util.stream.Stream.Builder;
24
25 import org.junit.jupiter.params.ParameterizedTest;
26 import org.junit.jupiter.params.provider.MethodSource;
27 import org.openhab.io.transport.modbus.ModbusBitUtilities;
28 import org.openhab.io.transport.modbus.ModbusRegisterArray;
29
30 /**
31  * @author Sami Salonen - Initial contribution
32  */
33 public class BitUtilitiesExtractStringTest {
34
35     private static ModbusRegisterArray shortArrayToRegisterArray(int... arr) {
36         return new ModbusRegisterArray(arr);
37     }
38
39     public static Collection<Object[]> data() {
40         return Collections.unmodifiableList(Stream.of(
41                 new Object[] { "", shortArrayToRegisterArray(0), 0, 0, StandardCharsets.UTF_8 },
42                 new Object[] { "hello", shortArrayToRegisterArray(0x6865, 0x6c6c, 0x6f00), 0, 5,
43                         StandardCharsets.UTF_8 },
44                 new Object[] { "he", shortArrayToRegisterArray(0x6865, 0x6c6c, 0x6f00), 0, 2, StandardCharsets.UTF_8 }, // limited
45                                                                                                                         // by
46                                                                                                                         // count=2
47                 new Object[] { "hello ", shortArrayToRegisterArray(0, 0, 0x6865, 0x6c6c, 0x6f20, 0, 0), 2, 6,
48                         StandardCharsets.UTF_8 },
49                 new Object[] { "hello", shortArrayToRegisterArray(0x6865, 0x6c6c, 0x6f00, 0x0000, 0x0000), 0, 10,
50                         StandardCharsets.UTF_8 },
51                 new Object[] { "árvíztűrő tükörfúrógép",
52                         shortArrayToRegisterArray(0xc3a1, 0x7276, 0xc3ad, 0x7a74, 0xc5b1, 0x72c5, 0x9120, 0x74c3,
53                                 0xbc6b, 0xc3b6, 0x7266, 0xc3ba, 0x72c3, 0xb367, 0xc3a9, 0x7000),
54                         0, 32, StandardCharsets.UTF_8 },
55                 new Object[] { "你好,世界",
56                         shortArrayToRegisterArray(0xe4bd, 0xa0e5, 0xa5bd, 0xefbc, 0x8ce4, 0xb896, 0xe795, 0x8c00), 0,
57                         16, StandardCharsets.UTF_8 },
58                 new Object[] { "árvíztűrő tükörfúrógép",
59                         shortArrayToRegisterArray(0xe172, 0x76ed, 0x7a74, 0xfb72, 0xf520, 0x74fc, 0x6bf6, 0x7266,
60                                 0xfa72, 0xf367, 0xe970),
61                         0, 22, Charset.forName("ISO-8859-2") },
62                 // Example where registers contain 0 byte in between -- only the data preceding zero byte is parsed
63                 new Object[] { "hello", shortArrayToRegisterArray(0x6865, 0x6c6c, 0x6f00, 0x776f, 0x726c, 0x64), 0, 10,
64                         StandardCharsets.UTF_8 },
65
66                 // Invalid values
67                 // 0xe4 = "ä" in extended ascii but not covered by US_ASCII. Will be replaced by �
68                 new Object[] { "�", shortArrayToRegisterArray(0xe400), 0, 2, StandardCharsets.US_ASCII },
69                 // out of bounds
70                 new Object[] { IllegalArgumentException.class, shortArrayToRegisterArray(0, 0), 2, 4,
71                         StandardCharsets.UTF_8 },
72                 // negative index
73                 new Object[] { IllegalArgumentException.class, shortArrayToRegisterArray(0, 0), 0, -1,
74                         StandardCharsets.UTF_8 },
75                 // out of bounds
76                 new Object[] { IllegalArgumentException.class, shortArrayToRegisterArray(0, 0), 0, 5,
77                         StandardCharsets.UTF_8 })
78                 .collect(Collectors.toList()));
79     }
80
81     public static Stream<Object[]> dataWithByteVariations() {
82         return data().stream().flatMap(vals -> {
83             Object expected = vals[0];
84             ModbusRegisterArray registers = (ModbusRegisterArray) vals[1];
85             int index = (int) vals[2];
86             int length = (int) vals[3];
87             Charset charset = (Charset) vals[4];
88
89             byte[] origBytes = registers.getBytes();
90             int origRegisterIndex = index;
91             int origByteIndex = origRegisterIndex * 2;
92
93             Builder<Object[]> streamBuilder = Stream.builder();
94             for (int offset = 0; offset < 5; offset++) {
95                 byte[] bytesOffsetted = new byte[origBytes.length + offset];
96                 System.arraycopy(origBytes, 0, bytesOffsetted, offset, origBytes.length);
97                 streamBuilder.add(
98                         new Object[] { expected, offset, bytesOffsetted, origByteIndex + offset, length, charset });
99             }
100             Stream<Object[]> variations = streamBuilder.build();
101             return variations;
102         });
103     }
104
105     @SuppressWarnings({ "unchecked", "rawtypes" })
106     @ParameterizedTest
107     @MethodSource("data")
108     public void testExtractStringFromRegisters(Object expectedResult, ModbusRegisterArray registers, int index,
109             int length, Charset charset) {
110         if (expectedResult instanceof Class && Exception.class.isAssignableFrom((Class) expectedResult)) {
111             assertThrows((Class) expectedResult,
112                     () -> ModbusBitUtilities.extractStringFromRegisters(registers, index, length, charset));
113             return;
114         } else {
115             String actualState = ModbusBitUtilities.extractStringFromRegisters(registers, index, length, charset);
116             assertEquals(actualState, expectedResult,
117                     String.format("registers=%s, index=%d, length=%d", registers, index, length));
118         }
119     }
120
121     @SuppressWarnings({ "unchecked", "rawtypes" })
122     @ParameterizedTest
123     @MethodSource("dataWithByteVariations")
124     public void testExtractStringFromBytes(Object expectedResult, int byteOffset, byte[] bytes, int byteIndex,
125             int length, Charset charset) {
126         if (expectedResult instanceof Class && Exception.class.isAssignableFrom((Class) expectedResult)) {
127             assertThrows((Class) expectedResult,
128                     () -> ModbusBitUtilities.extractStringFromBytes(bytes, byteIndex, length, charset));
129             return;
130         } else {
131             String actualState = ModbusBitUtilities.extractStringFromBytes(bytes, byteIndex, length, charset);
132             assertEquals(actualState, expectedResult, String.format("registers=%s, index=%d, length=%d, byteIndex=%d",
133                     bytes, byteIndex, length, byteIndex));
134         }
135     }
136 }