1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.digest;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotSame;
23
24 import java.nio.charset.StandardCharsets;
25 import java.nio.file.Paths;
26 import java.util.function.Supplier;
27 import java.util.zip.Checksum;
28
29 import org.apache.commons.codec.binary.StringUtils;
30 import org.apache.commons.io.file.PathUtils;
31 import org.apache.commons.io.function.Uncheck;
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.params.ParameterizedTest;
34 import org.junit.jupiter.params.provider.MethodSource;
35
36
37
38
39 class Crc16Test {
40
41 private static final String BIG_TEXT = Uncheck.get(() -> PathUtils.readString(Paths.get("LICENSE.txt"), StandardCharsets.US_ASCII));
42 private static final byte[] TEST_BYTES = "123456789".getBytes(StandardCharsets.US_ASCII);
43 private static final int TEST_BYTES_LEN = TEST_BYTES.length;
44
45 static Object[][] testArcDefault() {
46
47 return new Object[][] {
48 { "", 0x0000 },
49 { "1", 0xD4C1 },
50 { "12", 0x4594 },
51 { "123", 0xBA04 },
52 { "1234", 0x14BA },
53 { "12345", 0xA455 },
54 { "123456", 0x29E4 },
55 { "1234567", 0x9D68 },
56 { "12345678", 0x3C9D },
57 { "123456789", 0xBB3D },
58 { BIG_TEXT, 0xD01C }
59 };
60
61 }
62
63 static Object[][] testCcittDefault() {
64
65 return new Object[][] {
66 { "", 0x0000 },
67 { "1", 0x200A },
68 { "12", 0xBDEB },
69 { "123", 0x5A78 },
70 { "1234", 0x8832 },
71 { "12345", 0x7437 },
72 { "123456", 0x11FD },
73 { "1234567", 0x6947 },
74 { "12345678", 0x8B19 },
75 { "123456789", 0x2189 },
76 { BIG_TEXT, 0xA912 }
77 };
78
79 }
80
81 static Object[][] testDnpDefault() {
82
83 return new Object[][] {
84 { "", 0xFFFF },
85 { "1", 0x5265 },
86 { "12", 0x8FC8 },
87 { "123", 0x26F7 },
88 { "1234", 0x4213 },
89 { "12345", 0x711C },
90 { "123456", 0x57DE },
91 { "1234567", 0xF8F8 },
92 { "12345678", 0x182F },
93 { "123456789", 0xEA82 },
94 { BIG_TEXT, 0x7E33 }
95 };
96
97 }
98
99 @SuppressWarnings("unchecked")
100 static Supplier<int[]>[] testGetTables() {
101
102 return new Supplier[] {
103 Crc16::getArcTable,
104 Crc16::getCcittTable,
105 Crc16::getDnpTable,
106 Crc16::getMcrf4xxTable,
107 Crc16::getMaximTable,
108 Crc16::getModbusTable,
109 Crc16::getNrsc5Table
110 };
111
112 }
113
114 static Object[][] testIbmSdlcDefault() {
115
116 return new Object[][] {
117 { "", 0x0000 },
118 { "1", 0xD072 },
119 { "12", 0xB2AC },
120 { "123", 0x9CB4 },
121 { "1234", 0x74EC },
122 { "12345", 0xBB40 },
123 { "123456", 0xE672 },
124 { "1234567", 0xE537 },
125 { "12345678", 0x086A },
126 { "123456789", 0x906E },
127 { BIG_TEXT, 0x6C3F }
128 };
129
130 }
131
132 static Object[][] testMaximDefault() {
133
134 return new Object[][] {
135 { "", 0xFFFF },
136 { "1", 0x2B3E },
137 { "12", 0xBA6B },
138 { "123", 0x45FB },
139 { "1234", 0xEB45 },
140 { "12345", 0x5BAA },
141 { "123456", 0xD61B },
142 { "1234567", 0x6297 },
143 { "12345678", 0xC362 },
144 { "123456789", 0x44C2 },
145 { BIG_TEXT, 0x2FE3 }
146 };
147
148 }
149
150 static Object[][] testMcrf4xxDefault() {
151
152 return new Object[][] {
153 { "", 0xFFFF },
154 { "1", 0x2F8D },
155 { "12", 0x4D53 },
156 { "123", 0x634B },
157 { "1234", 0x8B13 },
158 { "12345", 0x44BF },
159 { "123456", 0x198D },
160 { "1234567", 0x1AC8 },
161 { "12345678", 0xF795 },
162 { "123456789", 0x6F91 },
163 { BIG_TEXT, 0x93C0 }
164 };
165
166 }
167
168 static Object[][] testModbusDefault() {
169
170 return new Object[][] {
171 { "", 0xFFFF },
172 { "1", 0x947E },
173 { "12", 0xF595 },
174 { "123", 0x7A75 },
175 { "1234", 0x30BA },
176 { "12345", 0xA471 },
177 { "123456", 0x32E4 },
178 { "1234567", 0x9D73 },
179 { "12345678", 0x37DD },
180 { "123456789", 0x4B37 },
181 { BIG_TEXT, 0xEC67 }
182 };
183
184 }
185
186 static Object[][] testNrsc5Default() {
187
188 return new Object[][] {
189 { "", 0xFFFF },
190 { "1", 0x083E },
191 { "12", 0xDB99 },
192 { "123", 0x8286 },
193 { "1234", 0x95DC },
194 { "12345", 0xB42C },
195 { "123456", 0x7CFF },
196 { "1234567", 0xB565 },
197 { "12345678", 0x9C8A },
198 { "123456789", 0xA066 },
199 { BIG_TEXT, 0x2A84 }
200 };
201
202 }
203
204 static Object[][] testUsbDefault() {
205
206 return new Object[][] {
207 { "", 0x0000 },
208 { "1", 0x6B81 },
209 { "12", 0x0A6A },
210 { "123", 0x858A },
211 { "1234", 0xCF45 },
212 { "12345", 0x5B8E },
213 { "123456", 0xCD1B },
214 { "1234567", 0x628C },
215 { "12345678", 0xC822 },
216 { "123456789", 0xB4C8 },
217 { BIG_TEXT, 0x1398 }
218 };
219
220 }
221
222 private Supplier<String> messageSupplier(final Checksum crc16, final long expected) {
223 return () -> String.format("Expected %04X but was %s", expected, crc16);
224 }
225
226 void stdUpdate(final Checksum crc16) {
227 crc16.update(TEST_BYTES, 0, TEST_BYTES_LEN);
228 }
229
230 @ParameterizedTest
231 @MethodSource
232 void testArcDefault(final String source, final long expected) {
233 testUpdateReset(source, expected, Crc16.arc());
234 }
235
236 @ParameterizedTest
237 @MethodSource
238 void testCcittDefault(final String source, final long expected) {
239 testUpdateReset(source, expected, Crc16.ccitt());
240 }
241
242 @ParameterizedTest
243 @MethodSource
244 void testDnpDefault(final String source, final long expected) {
245 testUpdateReset(source, expected, Crc16.dnp());
246 }
247
248 @ParameterizedTest
249 @MethodSource
250 void testGetTables(final Supplier<int[]> supplier) {
251 final int[] value1 = supplier.get();
252 final int[] value2 = supplier.get();
253 assertNotSame(value1, value2);
254 assertArrayEquals(value1, value2);
255 }
256
257 @ParameterizedTest
258 @MethodSource
259 void testIbmSdlcDefault(final String source, final long expected) {
260 testUpdateReset(source, expected, Crc16.ibmSdlc());
261 }
262
263 @Test
264 void testInit() {
265 final Checksum crc16 = Crc16.builder().setTable(Crc16.getModbusTable()).setInit(0xFFFF).get();
266 stdUpdate(crc16);
267 assertEquals(0x4B37, crc16.getValue());
268 stdUpdate(crc16);
269 assertEquals(0x090A, crc16.getValue());
270 crc16.reset();
271 stdUpdate(crc16);
272 assertEquals(0x4B37, crc16.getValue());
273 }
274
275 @ParameterizedTest
276 @MethodSource
277 void testMaximDefault(final String source, final long expected) {
278 testUpdateReset(source, expected, Crc16.maxim());
279 }
280
281 @ParameterizedTest
282 @MethodSource
283 void testMcrf4xxDefault(final String source, final long expected) {
284 testUpdateReset(source, expected, Crc16.mcrf4xx());
285 }
286
287 @Test
288 void testModbusCustom() {
289 final Checksum crc16 = Crc16.builder().setTable(Crc16.getModbusTable()).setInit(0xFFFF).get();
290 stdUpdate(crc16);
291 assertEquals(0x4B37, crc16.getValue());
292 stdUpdate(crc16);
293 assertEquals(0x090A, crc16.getValue());
294 crc16.reset();
295 stdUpdate(crc16);
296 assertEquals(0x4B37, crc16.getValue());
297 }
298
299 @ParameterizedTest
300 @MethodSource
301 void testModbusDefault(final String source, final long expected) {
302 testUpdateReset(source, expected, Crc16.modbus());
303 }
304
305 @ParameterizedTest
306 @MethodSource
307 void testNrsc5Default(final String source, final long expected) {
308 testUpdateReset(source, expected, Crc16.nrsc5());
309 }
310
311 @Test
312 void testReset() {
313 final Checksum crc16 = Crc16.modbus();
314 stdUpdate(crc16);
315 assertEquals(0x4B37, crc16.getValue());
316 stdUpdate(crc16);
317 assertEquals(0x090A, crc16.getValue());
318 crc16.reset();
319 stdUpdate(crc16);
320 assertEquals(0x4B37, crc16.getValue());
321 }
322
323 @Test
324 void testResetCustomModbus() {
325 final Checksum crc16 = Crc16.builder().setTable(Crc16.getModbusTable()).setInit(0x0000).get();
326 stdUpdate(crc16);
327 assertEquals(0xBB3D, crc16.getValue());
328 stdUpdate(crc16);
329 assertEquals(0xED7B, crc16.getValue());
330 crc16.reset();
331 stdUpdate(crc16);
332 assertEquals(0xbb3d, crc16.getValue());
333 }
334
335 @Test
336 void testUpdateArray() {
337 final Checksum crc16 = Crc16.builder().setTable(Crc16.getModbusTable()).setInit(0x0000).get();
338 stdUpdate(crc16);
339 assertEquals(0xBB3D, crc16.getValue());
340 }
341
342 @Test
343 void testUpdateInt() {
344 final Checksum crc16 = Crc16.builder().setTable(Crc16.getModbusTable()).setInit(0x0000).get();
345 final byte[] bytes = TEST_BYTES;
346 for (final byte element : bytes) {
347 crc16.update(element);
348 }
349 assertEquals(0xBB3D, crc16.getValue());
350 }
351
352 void testUpdateReset(final String source, final long expected, final Checksum crc16) {
353 final byte[] bytes = StringUtils.getBytesUsAscii(source);
354 crc16.update(bytes, 0, bytes.length);
355 long actual = crc16.getValue();
356 assertEquals(expected, actual, messageSupplier(crc16, expected));
357 crc16.reset();
358 crc16.update(bytes, 0, bytes.length);
359 actual = crc16.getValue();
360 assertEquals(expected, actual, messageSupplier(crc16, expected));
361 }
362
363 @ParameterizedTest
364 @MethodSource
365 void testUsbDefault(final String source, final long expected) {
366 testUpdateReset(source, expected, Crc16.usb());
367 }
368
369 }