]> git.basschouten.com Git - openhab-addons.git/blob
195c68c8ac752e892df8bb0212d778d59aed9fbf
[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.hamcrest.CoreMatchers.*;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.junit.jupiter.api.Assertions.assertThrows;
18
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.Optional;
22 import java.util.stream.Collectors;
23 import java.util.stream.Stream;
24
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.junit.jupiter.params.ParameterizedTest;
27 import org.junit.jupiter.params.provider.MethodSource;
28 import org.openhab.core.library.types.DecimalType;
29 import org.openhab.io.transport.modbus.ModbusBitUtilities;
30 import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
31 import org.openhab.io.transport.modbus.ModbusRegisterArray;
32
33 /**
34  * @author Sami Salonen - Initial contribution
35  */
36 public class BitUtilitiesExtractStateFromRegistersTest {
37
38     private static ModbusRegisterArray shortArrayToRegisterArray(int... arr) {
39         return new ModbusRegisterArray(arr);
40     }
41
42     public static Collection<Object[]> data() {
43         return Collections.unmodifiableList(Stream.of(
44                 //
45                 // BIT
46                 //
47                 new Object[] { new DecimalType("1.0"), ValueType.BIT,
48                         shortArrayToRegisterArray(1 << 5 | 1 << 4 | 1 << 15), 4 },
49                 new Object[] { new DecimalType("1.0"), ValueType.BIT,
50                         shortArrayToRegisterArray(1 << 5 | 1 << 4 | 1 << 15), 15 },
51                 new Object[] { new DecimalType("0.0"), ValueType.BIT, shortArrayToRegisterArray(1 << 5), 7 },
52                 new Object[] { new DecimalType("1.0"), ValueType.BIT, shortArrayToRegisterArray(1 << 5), 5 },
53                 new Object[] { new DecimalType("0.0"), ValueType.BIT, shortArrayToRegisterArray(1 << 5), 4 },
54                 new Object[] { new DecimalType("0.0"), ValueType.BIT, shortArrayToRegisterArray(1 << 5), 0 },
55                 new Object[] { new DecimalType("0.0"), ValueType.BIT, shortArrayToRegisterArray(0, 0), 15 },
56                 new Object[] { new DecimalType("1.0"), ValueType.BIT, shortArrayToRegisterArray(1 << 5, 1 << 4), 5 },
57                 new Object[] { new DecimalType("1.0"), ValueType.BIT, shortArrayToRegisterArray(1 << 5, 1 << 4), 20 },
58                 new Object[] { IllegalArgumentException.class, ValueType.BIT, shortArrayToRegisterArray(1 << 5), 16 },
59                 new Object[] { IllegalArgumentException.class, ValueType.BIT, shortArrayToRegisterArray(1 << 5), 200 },
60                 new Object[] { IllegalArgumentException.class, ValueType.BIT, shortArrayToRegisterArray(), 0 },
61                 new Object[] { IllegalArgumentException.class, ValueType.BIT, shortArrayToRegisterArray(0, 0), 32 },
62                 //
63                 // INT8
64                 //
65                 new Object[] { new DecimalType("5.0"), ValueType.INT8, shortArrayToRegisterArray(5), 0 },
66                 new Object[] { new DecimalType("-5.0"), ValueType.INT8, shortArrayToRegisterArray(-5), 0 },
67                 new Object[] { new DecimalType("3.0"), ValueType.INT8,
68                         shortArrayToRegisterArray(((byte) 6 << 8) | (byte) 3), 0 },
69                 new Object[] { new DecimalType("6.0"), ValueType.INT8,
70                         shortArrayToRegisterArray(((byte) 6 << 8) | (byte) 3), 1 },
71                 new Object[] { new DecimalType("4.0"), ValueType.INT8,
72                         shortArrayToRegisterArray(((byte) 6 << 8) | (byte) 3, 4), 2 },
73                 new Object[] { new DecimalType("6.0"), ValueType.INT8,
74                         shortArrayToRegisterArray(55, ((byte) 6 << 8) | (byte) 3), 3 },
75                 new Object[] { IllegalArgumentException.class, ValueType.INT8, shortArrayToRegisterArray(1), 2 },
76                 new Object[] { IllegalArgumentException.class, ValueType.INT8, shortArrayToRegisterArray(1, 2), 4 },
77                 //
78                 // UINT8
79                 //
80                 new Object[] { new DecimalType("5.0"), ValueType.UINT8, shortArrayToRegisterArray(5), 0 },
81                 new Object[] { new DecimalType("251.0"), ValueType.UINT8, shortArrayToRegisterArray(-5), 0 },
82                 new Object[] { new DecimalType("3.0"), ValueType.UINT8,
83                         shortArrayToRegisterArray(((byte) 6 << 8) | (byte) 3), 0 },
84                 new Object[] { new DecimalType("6.0"), ValueType.UINT8,
85                         shortArrayToRegisterArray(((byte) 6 << 8) | (byte) 3), 1 },
86                 new Object[] { new DecimalType("4.0"), ValueType.UINT8,
87                         shortArrayToRegisterArray(((byte) 6 << 8) | (byte) 3, 4), 2 },
88                 new Object[] { new DecimalType("6.0"), ValueType.UINT8,
89                         shortArrayToRegisterArray(55, ((byte) 6 << 8) | (byte) 3), 3 },
90                 new Object[] { IllegalArgumentException.class, ValueType.UINT8, shortArrayToRegisterArray(1), 2 },
91                 new Object[] { IllegalArgumentException.class, ValueType.UINT8, shortArrayToRegisterArray(1, 2), 4 },
92
93                 //
94                 // INT16
95                 //
96                 new Object[] { new DecimalType("1.0"), ValueType.INT16, shortArrayToRegisterArray(1), 0 },
97                 new Object[] { new DecimalType("2.0"), ValueType.INT16, shortArrayToRegisterArray(2), 0 },
98                 new Object[] { new DecimalType("-1004"), ValueType.INT16, shortArrayToRegisterArray(-1004), 0 },
99                 new Object[] { new DecimalType("-1536"), ValueType.INT16, shortArrayToRegisterArray(64000), 0 },
100                 new Object[] { new DecimalType("-1004"), ValueType.INT16, shortArrayToRegisterArray(4, -1004), 1 },
101                 new Object[] { new DecimalType("-1004"), ValueType.INT16, shortArrayToRegisterArray(-1004, 4), 0 },
102                 new Object[] { IllegalArgumentException.class, ValueType.INT16, shortArrayToRegisterArray(4, -1004),
103                         2 },
104                 //
105                 // UINT16
106                 //
107                 new Object[] { new DecimalType("1.0"), ValueType.UINT16, shortArrayToRegisterArray(1), 0 },
108                 new Object[] { new DecimalType("2.0"), ValueType.UINT16, shortArrayToRegisterArray(2), 0 },
109                 new Object[] { new DecimalType("64532"), ValueType.UINT16, shortArrayToRegisterArray(-1004), 0 },
110                 new Object[] { new DecimalType("64000"), ValueType.UINT16, shortArrayToRegisterArray(64000), 0 },
111                 new Object[] { new DecimalType("64532"), ValueType.UINT16, shortArrayToRegisterArray(4, -1004), 1 },
112                 new Object[] { new DecimalType("64532"), ValueType.UINT16, shortArrayToRegisterArray(-1004, 4), 0 },
113                 new Object[] { IllegalArgumentException.class, ValueType.UINT16, shortArrayToRegisterArray(4, -1004),
114                         2 },
115                 //
116                 // INT32
117                 //
118                 new Object[] { new DecimalType("1.0"), ValueType.INT32, shortArrayToRegisterArray(0, 1), 0 },
119                 new Object[] { new DecimalType("2.0"), ValueType.INT32, shortArrayToRegisterArray(0, 2), 0 },
120                 new Object[] { new DecimalType("-1004"), ValueType.INT32,
121                         // -1004 = 0xFFFFFC14 (32bit) =
122                         shortArrayToRegisterArray(0xFFFF, 0xFC14), 0 },
123                 new Object[] { new DecimalType("64000"), ValueType.INT32, shortArrayToRegisterArray(0, 64000), 0 },
124                 new Object[] { new DecimalType("-1004"), ValueType.INT32,
125                         // -1004 = 0xFFFFFC14 (32bit) =
126                         shortArrayToRegisterArray(0x4, 0xFFFF, 0xFC14), 1 },
127                 new Object[] { new DecimalType("-1004"), ValueType.INT32,
128                         // -1004 = 0xFFFFFC14 (32bit) =
129                         shortArrayToRegisterArray(0xFFFF, 0xFC14, 0x4), 0 },
130                 new Object[] { IllegalArgumentException.class, ValueType.INT32, shortArrayToRegisterArray(4, -1004),
131                         1 },
132                 new Object[] { IllegalArgumentException.class, ValueType.INT32, shortArrayToRegisterArray(4, -1004),
133                         2 },
134                 new Object[] { IllegalArgumentException.class, ValueType.INT32, shortArrayToRegisterArray(0, 0, 0), 2 },
135                 //
136                 // UINT32
137                 //
138                 new Object[] { new DecimalType("1.0"), ValueType.UINT32, shortArrayToRegisterArray(0, 1), 0 },
139                 new Object[] { new DecimalType("2.0"), ValueType.UINT32, shortArrayToRegisterArray(0, 2), 0 },
140                 new Object[] { new DecimalType("4294966292"), ValueType.UINT32,
141                         // 4294966292 = 0xFFFFFC14 (32bit) =
142                         shortArrayToRegisterArray(0xFFFF, 0xFC14), 0 },
143                 new Object[] { new DecimalType("64000"), ValueType.UINT32, shortArrayToRegisterArray(0, 64000), 0 },
144                 new Object[] {
145                         // out of bounds of unsigned 16bit (0 to 65,535)
146                         new DecimalType("70004"),
147                         // 70004 -> 0x00011174 (32bit) -> 0x1174 (16bit)
148                         ValueType.UINT32, shortArrayToRegisterArray(1, 4468), 0 },
149                 new Object[] { new DecimalType("4294966292"), ValueType.UINT32,
150                         // 4294966292 = 0xFFFFFC14 (32bit) =
151                         shortArrayToRegisterArray(0xFFFF, 0xFC14, 0x5), 0 },
152                 new Object[] { new DecimalType("4294966292"), ValueType.UINT32,
153                         // 4294966292 = 0xFFFFFC14 (32bit) =
154                         shortArrayToRegisterArray(0x5, 0xFFFF, 0xFC14), 1 },
155                 new Object[] { IllegalArgumentException.class, ValueType.UINT32, shortArrayToRegisterArray(4, -1004),
156                         1 },
157                 new Object[] { IllegalArgumentException.class, ValueType.UINT32, shortArrayToRegisterArray(4, -1004),
158                         2 },
159                 new Object[] { IllegalArgumentException.class, ValueType.UINT32, shortArrayToRegisterArray(0, 0, 0),
160                         2 },
161                 //
162                 // INT32_SWAP
163                 //
164                 new Object[] { new DecimalType("1.0"), ValueType.INT32_SWAP, shortArrayToRegisterArray(1, 0), 0 },
165                 new Object[] { new DecimalType("2.0"), ValueType.INT32_SWAP, shortArrayToRegisterArray(2, 0), 0 },
166                 new Object[] { new DecimalType("-1004"), ValueType.INT32_SWAP,
167                         // -1004 = 0xFFFFFC14 (32bit) =
168                         shortArrayToRegisterArray(0xFC14, 0xFFFF), 0 },
169                 new Object[] { new DecimalType("64000"), ValueType.INT32_SWAP, shortArrayToRegisterArray(64000, 0), 0 },
170                 new Object[] { new DecimalType("-1004"), ValueType.INT32_SWAP,
171                         // -1004 = 0xFFFFFC14 (32bit) =
172                         shortArrayToRegisterArray(0x4, 0xFC14, 0xFFFF), 1 },
173                 new Object[] { new DecimalType("-1004"), ValueType.INT32_SWAP,
174                         // -1004 = 0xFFFFFC14 (32bit) =
175                         shortArrayToRegisterArray(0xFC14, 0xFFFF, 0x4), 0 },
176                 new Object[] { IllegalArgumentException.class, ValueType.INT32_SWAP,
177                         shortArrayToRegisterArray(4, -1004), 1 },
178                 new Object[] { IllegalArgumentException.class, ValueType.INT32_SWAP,
179                         shortArrayToRegisterArray(4, -1004), 2 },
180                 new Object[] { IllegalArgumentException.class, ValueType.INT32_SWAP, shortArrayToRegisterArray(0, 0, 0),
181                         2 },
182                 //
183                 // UINT32_SWAP
184                 //
185                 new Object[] { new DecimalType("1.0"), ValueType.UINT32_SWAP, shortArrayToRegisterArray(1, 0), 0 },
186                 new Object[] { new DecimalType("2.0"), ValueType.UINT32_SWAP, shortArrayToRegisterArray(2, 0), 0 },
187                 new Object[] { new DecimalType("4294966292"), ValueType.UINT32_SWAP,
188                         // 4294966292 = 0xFFFFFC14 (32bit) =
189                         shortArrayToRegisterArray(0xFC14, 0xFFFF), 0 },
190                 new Object[] { new DecimalType("64000"), ValueType.UINT32_SWAP, shortArrayToRegisterArray(64000, 0),
191                         0 },
192                 new Object[] {
193                         // out of bounds of unsigned 16bit (0 to 65,535)
194                         new DecimalType("70004"),
195                         // 70004 -> 0x00011174 (32bit) -> 0x1174 (16bit)
196                         ValueType.UINT32_SWAP, shortArrayToRegisterArray(4468, 1), 0 },
197                 new Object[] { new DecimalType("4294966292"), ValueType.UINT32_SWAP,
198                         // 4294966292 = 0xFFFFFC14 (32bit) =
199                         shortArrayToRegisterArray(0xFC14, 0xFFFF, 0x5), 0 },
200                 new Object[] { new DecimalType("4294966292"), ValueType.UINT32_SWAP,
201                         // 4294966292 = 0xFFFFFC14 (32bit) =
202                         shortArrayToRegisterArray(0x5, 0xFC14, 0xFFFF), 1 },
203                 new Object[] { IllegalArgumentException.class, ValueType.UINT32_SWAP,
204                         shortArrayToRegisterArray(4, -1004), 1 },
205                 new Object[] { IllegalArgumentException.class, ValueType.UINT32_SWAP,
206                         shortArrayToRegisterArray(4, -1004), 2 },
207                 new Object[] { IllegalArgumentException.class, ValueType.UINT32_SWAP,
208                         shortArrayToRegisterArray(0, 0, 0), 2 },
209                 //
210                 // FLOAT32
211                 //
212                 new Object[] { new DecimalType("1.0"), ValueType.FLOAT32, shortArrayToRegisterArray(0x3F80, 0x0000),
213                         0 },
214                 new Object[] { new DecimalType(1.6f), ValueType.FLOAT32, shortArrayToRegisterArray(0x3FCC, 0xCCCD), 0 },
215                 new Object[] { new DecimalType(2.6f), ValueType.FLOAT32, shortArrayToRegisterArray(0x4026, 0x6666), 0 },
216                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32, shortArrayToRegisterArray(0xC47B, 0x199A),
217                         0 },
218                 new Object[] { new DecimalType("64000"), ValueType.FLOAT32, shortArrayToRegisterArray(0x477A, 0x0000),
219                         0 },
220                 new Object[] {
221                         // out of bounds of unsigned 16bit (0 to 65,535)
222                         new DecimalType(70004.4f), ValueType.FLOAT32, shortArrayToRegisterArray(0x4788, 0xBA33), 0 },
223                 new Object[] {
224                         // out of bounds of unsigned 32bit (0 to 4,294,967,295)
225                         new DecimalType("5000000000"), ValueType.FLOAT32, shortArrayToRegisterArray(0x4F95, 0x02F9),
226                         0 },
227                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32,
228                         shortArrayToRegisterArray(0x4, 0xC47B, 0x199A), 1 },
229                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32,
230                         shortArrayToRegisterArray(0xC47B, 0x199A, 0x4), 0 },
231                 new Object[] { // equivalent of NaN
232                         Optional.empty(), ValueType.FLOAT32, shortArrayToRegisterArray(0x7fc0, 0x0000), 0 },
233                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32,
234                         shortArrayToRegisterArray(0x4, 0x0, 0x0, 0x0, 0xC47B, 0x199A), 4 },
235                 new Object[] { IllegalArgumentException.class, ValueType.FLOAT32, shortArrayToRegisterArray(4, -1004),
236                         1 },
237                 new Object[] { IllegalArgumentException.class, ValueType.FLOAT32, shortArrayToRegisterArray(4, -1004),
238                         2 },
239                 new Object[] { IllegalArgumentException.class, ValueType.FLOAT32, shortArrayToRegisterArray(0, 0, 0),
240                         2 },
241                 //
242                 // FLOAT32_SWAP
243                 //
244                 new Object[] { new DecimalType("1.0"), ValueType.FLOAT32_SWAP,
245                         shortArrayToRegisterArray(0x0000, 0x3F80), 0 },
246                 new Object[] { new DecimalType(1.6f), ValueType.FLOAT32_SWAP, shortArrayToRegisterArray(0xCCCD, 0x3FCC),
247                         0 },
248                 new Object[] { new DecimalType(2.6f), ValueType.FLOAT32_SWAP, shortArrayToRegisterArray(0x6666, 0x4026),
249                         0 },
250                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32_SWAP,
251                         shortArrayToRegisterArray(0x199A, 0xC47B), 0 },
252                 new Object[] { new DecimalType("64000"), ValueType.FLOAT32_SWAP,
253                         shortArrayToRegisterArray(0x0000, 0x477A), 0 },
254                 new Object[] { // equivalent of NaN
255                         Optional.empty(), ValueType.FLOAT32_SWAP, shortArrayToRegisterArray(0x0000, 0x7fc0), 0 },
256                 new Object[] {
257                         // out of bounds of unsigned 16bit (0 to 65,535)
258                         new DecimalType(70004.4f), ValueType.FLOAT32_SWAP, shortArrayToRegisterArray(0xBA33, 0x4788),
259                         0 },
260                 new Object[] {
261                         // out of bounds of unsigned 32bit (0 to 4,294,967,295)
262                         new DecimalType("5000000000"), ValueType.FLOAT32_SWAP,
263                         shortArrayToRegisterArray(0x02F9, 0x4F95), 0 },
264                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32_SWAP,
265                         shortArrayToRegisterArray(0x4, 0x199A, 0xC47B), 1 },
266                 new Object[] { new DecimalType(-1004.4f), ValueType.FLOAT32_SWAP,
267                         shortArrayToRegisterArray(0x199A, 0xC47B, 0x4), 0 },
268                 new Object[] { IllegalArgumentException.class, ValueType.FLOAT32_SWAP,
269                         shortArrayToRegisterArray(4, -1004), 1 },
270                 new Object[] { IllegalArgumentException.class, ValueType.FLOAT32_SWAP,
271                         shortArrayToRegisterArray(4, -1004), 2 },
272                 new Object[] { IllegalArgumentException.class, ValueType.FLOAT32_SWAP,
273                         shortArrayToRegisterArray(0, 0, 0), 2 },
274
275                 //
276                 // INT64
277                 //
278                 new Object[] { new DecimalType("1.0"), ValueType.INT64, shortArrayToRegisterArray(0, 0, 0, 1), 0 },
279                 new Object[] { new DecimalType("2.0"), ValueType.INT64, shortArrayToRegisterArray(0, 0, 0, 2), 0 },
280                 new Object[] { new DecimalType("-1004"), ValueType.INT64,
281                         shortArrayToRegisterArray(0xFFFF, 0xFFFF, 0xFFFF, 0xFC14), 0 },
282                 new Object[] { new DecimalType("64000"), ValueType.INT64, shortArrayToRegisterArray(0, 0, 0, 64000),
283                         0 },
284                 new Object[] {
285                         // out of bounds of unsigned 32bit
286                         new DecimalType("34359738368"), ValueType.INT64, shortArrayToRegisterArray(0x0, 0x8, 0x0, 0x0),
287                         0 },
288                 new Object[] { new DecimalType("-2322243636186679031"), ValueType.INT64,
289                         shortArrayToRegisterArray(0xDFC5, 0xBBB7, 0x772E, 0x7909), 0 },
290                 // would read over the registers
291                 new Object[] { IllegalArgumentException.class, ValueType.INT64,
292                         shortArrayToRegisterArray(0xDFC5, 0xBBB7, 0x772E, 0x7909), 1 },
293                 // would read over the registers
294                 new Object[] { IllegalArgumentException.class, ValueType.INT64,
295                         shortArrayToRegisterArray(0xDFC5, 0xBBB7, 0x772E, 0x7909), 2 },
296                 // 4 registers expected, only 3 available
297                 new Object[] { IllegalArgumentException.class, ValueType.INT64,
298                         shortArrayToRegisterArray(0xDFC5, 0xBBB7, 0x772E), 0 },
299
300                 //
301                 // UINT64
302                 //
303                 new Object[] { new DecimalType("1.0"), ValueType.UINT64, shortArrayToRegisterArray(0, 0, 0, 1), 0 },
304                 new Object[] { new DecimalType("2.0"), ValueType.UINT64, shortArrayToRegisterArray(0, 0, 0, 2), 0 },
305                 new Object[] { new DecimalType("18446744073709550612"), ValueType.UINT64,
306                         shortArrayToRegisterArray(0xFFFF, 0xFFFF, 0xFFFF, 0xFC14), 0 },
307                 new Object[] { new DecimalType("64000"), ValueType.UINT64, shortArrayToRegisterArray(0, 0, 0, 64000),
308                         0 },
309                 new Object[] {
310                         // out of bounds of unsigned 32bit
311                         new DecimalType("34359738368"), ValueType.UINT64, shortArrayToRegisterArray(0x0, 0x8, 0x0, 0x0),
312                         0 },
313                 new Object[] { new DecimalType("16124500437522872585"), ValueType.UINT64,
314                         shortArrayToRegisterArray(0xDFC5, 0xBBB7, 0x772E, 0x7909), 0 },
315
316                 //
317                 // INT64_SWAP
318                 //
319                 new Object[] { new DecimalType("1.0"), ValueType.INT64_SWAP, shortArrayToRegisterArray(1, 0, 0, 0), 0 },
320                 new Object[] { new DecimalType("2.0"), ValueType.INT64_SWAP, shortArrayToRegisterArray(2, 0, 0, 0), 0 },
321                 new Object[] { new DecimalType("-1004"), ValueType.INT64_SWAP,
322                         shortArrayToRegisterArray(0xFC14, 0xFFFF, 0xFFFF, 0xFFFF), 0 },
323                 new Object[] { new DecimalType("64000"), ValueType.INT64_SWAP,
324                         shortArrayToRegisterArray(64000, 0, 0, 0), 0 },
325                 new Object[] {
326                         // out of bounds of unsigned 32bit
327                         new DecimalType("34359738368"),
328                         // 70004 -> 0x00011174 (32bit) -> 0x1174 (16bit)
329                         ValueType.INT64_SWAP, shortArrayToRegisterArray(0x0, 0x0, 0x8, 0x0), 0 },
330                 new Object[] { new DecimalType("-2322243636186679031"), ValueType.INT64_SWAP,
331
332                         shortArrayToRegisterArray(0x7909, 0x772E, 0xBBB7, 0xDFC5), 0 },
333
334                 //
335                 // UINT64_SWAP
336                 //
337                 new Object[] { new DecimalType("1.0"), ValueType.UINT64_SWAP, shortArrayToRegisterArray(1, 0, 0, 0),
338                         0 },
339                 new Object[] { new DecimalType("2.0"), ValueType.UINT64_SWAP, shortArrayToRegisterArray(2, 0, 0, 0),
340                         0 },
341                 new Object[] { new DecimalType("18446744073709550612"), ValueType.UINT64_SWAP,
342                         shortArrayToRegisterArray(0xFC14, 0xFFFF, 0xFFFF, 0xFFFF), 0 },
343                 new Object[] { new DecimalType("64000"), ValueType.UINT64_SWAP,
344                         shortArrayToRegisterArray(64000, 0, 0, 0), 0 },
345                 new Object[] {
346                         // out of bounds of unsigned 32bit
347                         new DecimalType("34359738368"), ValueType.UINT64_SWAP,
348                         shortArrayToRegisterArray(0x0, 0x0, 0x8, 0x0), 0 },
349                 new Object[] {
350                         // out of bounds of unsigned 64bit
351                         new DecimalType("16124500437522872585"), ValueType.UINT64_SWAP,
352                         shortArrayToRegisterArray(0x7909, 0x772E, 0xBBB7, 0xDFC5), 0 })
353                 .collect(Collectors.toList()));
354     }
355
356     @SuppressWarnings({ "unchecked", "rawtypes" })
357     @ParameterizedTest
358     @MethodSource("data")
359     public void testextractStateFromRegisters(Object expectedResult, ValueType type, ModbusRegisterArray registers,
360             int index) {
361         if (expectedResult instanceof Class && Exception.class.isAssignableFrom((Class) expectedResult)) {
362             assertThrows((Class) expectedResult,
363                     () -> ModbusBitUtilities.extractStateFromRegisters(registers, index, type));
364             return;
365         }
366
367         Optional<@NonNull DecimalType> actualState = ModbusBitUtilities.extractStateFromRegisters(registers, index,
368                 type);
369         // Wrap given expectedResult to Optional, if necessary
370         Optional<@NonNull DecimalType> expectedStateWrapped = expectedResult instanceof DecimalType
371                 ? Optional.of((DecimalType) expectedResult)
372                 : (Optional<@NonNull DecimalType>) expectedResult;
373         assertThat(String.format("registers=%s, index=%d, type=%s", registers, index, type), actualState,
374                 is(equalTo(expectedStateWrapped)));
375     }
376 }