View Javadoc
1   /*
2    * Copyright 2016-2024 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.util;
6   
7   import static org.hamcrest.MatcherAssert.assertThat;
8   import static org.hamcrest.Matchers.anEmptyMap;
9   import static org.hamcrest.Matchers.closeTo;
10  import static org.hamcrest.Matchers.contains;
11  import static org.hamcrest.Matchers.containsInAnyOrder;
12  import static org.hamcrest.Matchers.empty;
13  import static org.hamcrest.Matchers.emptyString;
14  import static org.hamcrest.Matchers.hasItems;
15  import static org.hamcrest.Matchers.is;
16  import static org.hamcrest.Matchers.not;
17  import static org.hamcrest.Matchers.notNullValue;
18  import static org.hamcrest.Matchers.nullValue;
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  
23  import java.nio.charset.StandardCharsets;
24  import java.time.Instant;
25  import java.time.OffsetDateTime;
26  import java.util.Arrays;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Locale;
30  import java.util.Map;
31  
32  import org.junit.jupiter.api.Test;
33  
34  import oshi.util.tuples.Pair;
35  import oshi.util.tuples.Triplet;
36  
37  /**
38   * The Class ParseUtilTest.
39   */
40  class ParseUtilTest {
41  
42      private static final double EPSILON = Double.MIN_VALUE;
43  
44      private enum TestEnum {
45          FOO, BAR, BAZ;
46      }
47  
48      /**
49       * Test parse hertz.
50       */
51      @Test
52      void testParseHertz() {
53          assertThat("parse OneHz", ParseUtil.parseHertz("OneHz"), is(-1L));
54          assertThat("parse NotEvenAHertz", ParseUtil.parseHertz("NotEvenAHertz"), is(-1L));
55          assertThat("parse 10000000000000000000 Hz", ParseUtil.parseHertz("10000000000000000000 Hz"),
56                  is(Long.MAX_VALUE));
57          assertThat("parse 1Hz", ParseUtil.parseHertz("1Hz"), is(1L));
58          assertThat("parse 500 Hz", ParseUtil.parseHertz("500 Hz"), is(500L));
59          assertThat("parse 1kHz", ParseUtil.parseHertz("1kHz"), is(1_000L));
60          assertThat("parse 1MHz", ParseUtil.parseHertz("1MHz"), is(1_000_000L));
61          assertThat("parse 1GHz", ParseUtil.parseHertz("1GHz"), is(1_000_000_000L));
62          assertThat("parse 1.5GHz", ParseUtil.parseHertz("1.5GHz"), is(1_500_000_000L));
63          assertThat("parse 1THz", ParseUtil.parseHertz("1THz"), is(1_000_000_000_000L));
64          // GHz exceeds max double
65      }
66  
67      /**
68       * Test parse string.
69       */
70      @Test
71      void testParseLastInt() {
72          assertThat("parse def -1", ParseUtil.parseLastInt("foo : bar", -1), is(-1));
73          assertThat("parse 1", ParseUtil.parseLastInt("foo : 1", 0), is(1));
74          assertThat("parse def 2", ParseUtil.parseLastInt("foo", 2), is(2));
75          assertThat("parse maxInt+1", ParseUtil.parseLastInt("max_int plus one is 2147483648", 3), is(3));
76          assertThat("parse 0xff", ParseUtil.parseLastInt("0xff", 4), is(255));
77  
78          assertThat("parse def -1 as long", ParseUtil.parseLastLong("foo : bar", -1L), is(-1L));
79          assertThat("parse 1 as long", ParseUtil.parseLastLong("foo : 1", 0L), is(1L));
80          assertThat("parse def 2 as long", ParseUtil.parseLastLong("foo", 2L), is(2L));
81          assertThat("parse maxInt+1 as long", ParseUtil.parseLastLong("max_int plus one is" + " 2147483648", 3L),
82                  is(2147483648L));
83          assertThat("parse 0xff as long", ParseUtil.parseLastLong("0xff", 0L), is(255L));
84  
85          assertThat("parse def -1 as double", ParseUtil.parseLastDouble("foo : bar", -1d), is(closeTo(-1d, EPSILON)));
86          assertThat("parse 1.0 as double", ParseUtil.parseLastDouble("foo : 1.0", 0d), is(closeTo(1d, EPSILON)));
87          assertThat("parse def 2 as double", ParseUtil.parseLastDouble("foo", 2d), is(closeTo(2d, EPSILON)));
88      }
89  
90      /**
91       * Test parse string.
92       */
93      @Test
94      void testParseLastString() {
95          assertThat("parse bar", ParseUtil.parseLastString("foo : bar"), is("bar"));
96          assertThat("parse foo", ParseUtil.parseLastString("foo"), is("foo"));
97          assertThat("parse \"\"", ParseUtil.parseLastString(""), is(emptyString()));
98      }
99  
100     /**
101      * Test hex string to byte array (and back).
102      */
103     @Test
104     void testHexStringToByteArray() {
105         byte[] temp = { (byte) 0x12, (byte) 0xaf };
106         assertThat(Arrays.equals(temp, ParseUtil.hexStringToByteArray("12af")), is(true));
107         assertThat("parse 12AF", ParseUtil.byteArrayToHexString(temp), is("12AF"));
108         temp = new byte[0];
109         assertThat(Arrays.equals(temp, ParseUtil.hexStringToByteArray("expected error abcde")), is(true));
110         assertThat(Arrays.equals(temp, ParseUtil.hexStringToByteArray("abcde")), is(true));
111     }
112 
113     /**
114      * Test string to byte array.
115      */
116     @Test
117     void testStringToByteArray() {
118         byte[] temp = { (byte) '1', (byte) '2', (byte) 'a', (byte) 'f', (byte) 0 };
119         assertThat(Arrays.equals(temp, ParseUtil.asciiStringToByteArray("12af", 5)), is(true));
120     }
121 
122     /**
123      * Test long to byte array.
124      */
125     @Test
126     void testLongToByteArray() {
127         byte[] temp = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0 };
128         assertThat(Arrays.equals(temp, ParseUtil.longToByteArray(0x12345678, 4, 5)), is(true));
129     }
130 
131     /**
132      * Test string and byte array to long.
133      */
134     @Test
135     void testStringAndByteArrayToLong() {
136         byte[] temp = { (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e' };
137         long abcde = (long) temp[0] << 32 | temp[1] << 24 | temp[2] << 16 | temp[3] << 8 | temp[4];
138         long edcba = (long) temp[4] << 32 | temp[3] << 24 | temp[2] << 16 | temp[1] << 8 | temp[0];
139         // Test string
140         assertThat("parse \"abcde\"", ParseUtil.strToLong("abcde", 5), is(abcde));
141         // Test byte array
142         assertThat("Incorrect parsing of " + abcde, ParseUtil.byteArrayToLong(temp, 5), is(abcde));
143         assertThat("Incorrect parsing of " + abcde + " BE", ParseUtil.byteArrayToLong(temp, 5, true), is(abcde));
144         assertThat("Incorrect parsing of " + edcba + " LE", ParseUtil.byteArrayToLong(temp, 5, false), is(edcba));
145     }
146 
147     @Test
148     void testByteArrayToLongSizeTooBig() {
149         assertThrows(IllegalArgumentException.class, () -> {
150             ParseUtil.byteArrayToLong(new byte[10], 9);
151         });
152     }
153 
154     @Test
155     void testByteArrayToLongSizeBigger() {
156         assertThrows(IllegalArgumentException.class, () -> {
157             ParseUtil.byteArrayToLong(new byte[7], 8);
158         });
159     }
160 
161     /**
162      * Test byte array to float
163      */
164     @Test
165     void testByteArrayToFloat() {
166         byte[] temp = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a };
167         float f = (temp[0] << 22 | temp[1] << 14 | temp[2] << 6 | temp[3] >>> 2) + (float) (temp[3] & 0x3) / 0x4;
168         assertEquals(f, ParseUtil.byteArrayToFloat(temp, 4, 2), Float.MIN_VALUE);
169         f = 0x12345 + (float) 0x6 / 0x10;
170         assertEquals(f, ParseUtil.byteArrayToFloat(temp, 3, 4), Float.MIN_VALUE);
171         f = 0x123 + (float) 0x4 / 0x10;
172         assertEquals(f, ParseUtil.byteArrayToFloat(temp, 2, 4), Float.MIN_VALUE);
173     }
174 
175     /**
176      * Test unsigned int to long
177      */
178     @Test
179     void testUnsignedIntToLong() {
180         assertThat("parse 0 as long", ParseUtil.unsignedIntToLong(0), is(0L));
181         assertThat("parse 123 as long", ParseUtil.unsignedIntToLong(123), is(123L));
182         assertThat("parse 4294967295L as long", ParseUtil.unsignedIntToLong(0xffffffff), is(4294967295L));
183     }
184 
185     /**
186      * Test unsigned long to signed long
187      */
188     @Test
189     void testUnsignedLongToSignedLong() {
190         assertThat("parse 1 as signed long", ParseUtil.unsignedLongToSignedLong(Long.MAX_VALUE + 2), is(1L));
191         assertThat("parse 123 as signed long", ParseUtil.unsignedLongToSignedLong(123), is(123L));
192         assertThat("parse 9223372036854775807 as signed long", ParseUtil.unsignedLongToSignedLong(9223372036854775807L),
193                 is(9223372036854775807L));
194     }
195 
196     /**
197      * Test hex string to string
198      */
199     @Test
200     void testHexStringToString() {
201         assertThat("parse ABC as string", ParseUtil.hexStringToString("414243"), is("ABC"));
202         assertThat("parse ab00cd as string", ParseUtil.hexStringToString("ab00cd"), is("ab00cd"));
203         assertThat("parse ab88cd as string", ParseUtil.hexStringToString("ab88cd"), is("ab88cd"));
204         assertThat("parse notHex as string", ParseUtil.hexStringToString("notHex"), is("notHex"));
205         assertThat("parse 320 as string", ParseUtil.hexStringToString("320"), is("320"));
206         assertThat("parse 0 as string", ParseUtil.hexStringToString("0"), is("0"));
207     }
208 
209     /**
210      * Test parse int
211      */
212     @Test
213     void testParseIntOrDefault() {
214         assertThat("parse 123", ParseUtil.parseIntOrDefault("123", 45), is(123));
215         assertThat("parse 45", ParseUtil.parseIntOrDefault("123X", 45), is(45));
216     }
217 
218     /**
219      * Test parse long
220      */
221     @Test
222     void testParseLongOrDefault() {
223         assertThat("parse 123", ParseUtil.parseLongOrDefault("123", 45L), is(123L));
224         assertThat("parse 45", ParseUtil.parseLongOrDefault("123L", 45L), is(45L));
225     }
226 
227     /**
228      * Test parse long
229      */
230     @Test
231     void testParseUnsignedLongOrDefault() {
232         assertThat("parse 9223372036854775807L", ParseUtil.parseUnsignedLongOrDefault("9223372036854775807", 123L),
233                 is(9223372036854775807L));
234         assertThat("parse 9223372036854775808L", ParseUtil.parseUnsignedLongOrDefault("9223372036854775808", 45L),
235                 is(-9223372036854775808L));
236         assertThat("parse 1L", ParseUtil.parseUnsignedLongOrDefault("18446744073709551615", 123L), is(-1L));
237         assertThat("parse 0L", ParseUtil.parseUnsignedLongOrDefault("18446744073709551616", 45L), is(0L));
238         assertThat("parse 123L", ParseUtil.parseUnsignedLongOrDefault("9223372036854775808L", 123L), is(123L));
239     }
240 
241     /**
242      * Test parse double
243      */
244     @Test
245     void testParseDoubleOrDefault() {
246         assertThat("parse 1.23d", ParseUtil.parseDoubleOrDefault("1.23", 4.5d), is(closeTo(1.23d, EPSILON)));
247         assertThat("parse 4.5d", ParseUtil.parseDoubleOrDefault("one.twentythree", 4.5d), is(closeTo(4.5d, EPSILON)));
248     }
249 
250     /**
251      * Test parse DHMS
252      */
253     @Test
254     void testParseDHMSOrDefault() {
255         assertThat("parse 93784050L", ParseUtil.parseDHMSOrDefault("1-02:03:04.05", 0L), is(93784050L));
256         assertThat("parse 93784000L", ParseUtil.parseDHMSOrDefault("1-02:03:04", 0L), is(93784000L));
257         assertThat("parse 7384000L", ParseUtil.parseDHMSOrDefault("02:03:04", 0L), is(7384000L));
258         assertThat("parse 184050L", ParseUtil.parseDHMSOrDefault("03:04.05", 0L), is(184050L));
259         assertThat("parse 184000L", ParseUtil.parseDHMSOrDefault("03:04", 0L), is(184000L));
260         assertThat("parse 4000L", ParseUtil.parseDHMSOrDefault("04", 0L), is(4000L));
261         assertThat("parse 0L", ParseUtil.parseDHMSOrDefault("04:05-06", 0L), is(0L));
262     }
263 
264     /**
265      * Test parse UUID
266      */
267     @Test
268     void testParseUuidOrDefault() {
269         assertThat("parse uuid", ParseUtil.parseUuidOrDefault("123e4567-e89b-12d3-a456-426655440000", "default"),
270                 is("123e4567-e89b-12d3-a456-426655440000"));
271         assertThat("parse uuid in string",
272                 ParseUtil.parseUuidOrDefault("The UUID is 123E4567-E89B-12D3-A456-426655440000!", "default"),
273                 is("123e4567-e89b-12d3-a456-426655440000"));
274         assertThat("parse foo or default", ParseUtil.parseUuidOrDefault("foo", "default"), is("default"));
275     }
276 
277     /**
278      * Test parse SingleQuoteString
279      */
280     @Test
281     void testGetSingleQuoteStringValue() {
282         assertThat("parse bar", ParseUtil.getSingleQuoteStringValue("foo = 'bar' (string)"), is("bar"));
283         assertThat("parse empty string", ParseUtil.getSingleQuoteStringValue("foo = bar (string)"), is(""));
284     }
285 
286     @Test
287     void testGetDoubleQuoteStringValue() {
288         assertThat("parse bar", ParseUtil.getDoubleQuoteStringValue("foo = \"bar\" (string)"), is("bar"));
289         assertThat("parse empty string", ParseUtil.getDoubleQuoteStringValue("hello"), is(""));
290     }
291 
292     /**
293      * Test parse SingleQuoteBetweenMultipleQuotes
294      */
295     @Test
296     void testGetStringBetweenMultipleQuotes() {
297         assertThat("parse Single quotes between Multiple quotes",
298                 ParseUtil.getStringBetween("hello = $hello $ is $", '$'), is("hello $ is"));
299         assertThat("parse Single quotes between Multiple quotes",
300                 ParseUtil.getStringBetween("pci.device = 'Realtek AC'97 Audio'", '\''), is("Realtek AC'97 Audio"));
301     }
302 
303     /**
304      * Test parse FirstIntValue
305      */
306     @Test
307     void testGetFirstIntValue() {
308         assertThat("parse FirstIntValue", ParseUtil.getFirstIntValue("foo = 42 (0x2a) (int)"), is(42));
309         assertThat("parse FirstIntValue", ParseUtil.getFirstIntValue("foo = 0x2a (int)"), is(0));
310         assertThat("parse FirstIntValue", ParseUtil.getFirstIntValue("42"), is(42));
311         assertThat("parse FirstIntValue", ParseUtil.getFirstIntValue("10.12.2"), is(10));
312     }
313 
314     /**
315      * Test parse NthIntValue
316      */
317     @Test
318     void testGetNthIntValue() {
319         assertThat("parse NthIntValue", ParseUtil.getNthIntValue("foo = 42 (0x2a) (int)", 3), is(2));
320         assertThat("parse NthIntValue", ParseUtil.getNthIntValue("foo = 0x2a (int)", 3), is(0));
321         assertThat("parse NthIntValue", ParseUtil.getNthIntValue("10.12.2", 2), is(12));
322     }
323 
324     /**
325      * Test parse removeMatchingString
326      */
327     @Test
328     void testRemoveMatchingString() {
329         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString("foo = 42 (0x2a) (int)", "0x2a"),
330                 is("foo = 42 () (int)"));
331         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString("foo = 0x2a (int)", "qqq"),
332                 is("foo = 0x2a (int)"));
333         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString("10.12.2", "2"), is("10.1."));
334         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString("10.12.2", "10.12.2"),
335                 is(emptyString()));
336         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString("", "10.12.2"), is(emptyString()));
337         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString(null, "10.12.2"), is(nullValue()));
338         assertThat("parse removeMatchingString", ParseUtil.removeMatchingString("10.12.2", "10.12."), is("2"));
339     }
340 
341     /**
342      * Test parse string to array
343      */
344     @Test
345     void testParseStringToLongArray() {
346         int[] indices = { 1, 3 };
347         long now = System.currentTimeMillis();
348 
349         String foo = String.format(Locale.ROOT, "The numbers are %d %d %d %d", 123, 456, 789, now);
350         int count = ParseUtil.countStringToLongArray(foo, ' ');
351         assertThat("countStringToLongArray should return 4 for \"" + foo + "\"", count, is(4));
352         long[] result = ParseUtil.parseStringToLongArray(foo, indices, 4, ' ');
353         assertThat("result[0] should be 456 using parseStringToLongArray on \"" + foo + "\"", result[0], is(456L));
354         assertThat("result[1] should be " + now + " using parseStringToLongArray on \"" + foo + "\"", result[1],
355                 is(now));
356 
357         foo = String.format(Locale.ROOT, "The numbers are %d %d %d %d %s", 123, 456, 789, now,
358                 "709af748-5f8e-41b3-b73a-b440ef4406c8");
359         count = ParseUtil.countStringToLongArray(foo, ' ');
360         assertThat("countStringToLongArray should return 4 for \"" + foo + "\"", count, is(4));
361         result = ParseUtil.parseStringToLongArray(foo, indices, 4, ' ');
362         assertThat("result[0] should be 456 using parseStringToLongArray on \"" + foo + "\"", result[0], is(456L));
363         assertThat("result[1] should be " + now + " using parseStringToLongArray on \"" + foo + "\"", result[1],
364                 is(now));
365 
366         foo = String.format(Locale.ROOT, "The numbers are %d -%d %d +%d", 123, 456, 789, now);
367         count = ParseUtil.countStringToLongArray(foo, ' ');
368         assertThat("countStringToLongArray should return 4 for \"" + foo + "\"", count, is(4));
369         result = ParseUtil.parseStringToLongArray(foo, indices, 4, ' ');
370         assertThat("result[0] should be -4456 using parseStringToLongArray on \"" + foo + "\"", result[0], is(-456L));
371         assertThat("result[1] index should be 456 using parseStringToLongArray on \"" + foo + "\"", result[1], is(now));
372 
373         foo = String.format(Locale.ROOT, "NOLOG: Invalid character %d %s %d %d", 123, "4v6", 789, now);
374         count = ParseUtil.countStringToLongArray(foo, ' ');
375         assertThat("countStringToLongArray should return 2 for \"" + foo + "\"", count, is(2));
376         result = ParseUtil.parseStringToLongArray(foo, indices, 4, ' ');
377         assertThat("result[1] index should be 0 using parseStringToLongArray on \"" + foo + "\"", result[1], is(0L));
378 
379         foo = String.format(Locale.ROOT, "Exceeds max long %d %d %d 1%d", 123, 456, 789, Long.MAX_VALUE);
380         result = ParseUtil.parseStringToLongArray(foo, indices, 4, ' ');
381         assertThat("result[1] index should be " + Long.MAX_VALUE
382                 + " (Long.MAX_VALUE) using parseStringToLongArray on \"" + foo + "\"", result[1], is(Long.MAX_VALUE));
383 
384         foo = String.format(Locale.ROOT, "NOLOG: String too short %d %d %d %d", 123, 456, 789, now);
385         result = ParseUtil.parseStringToLongArray(foo, indices, 9, ' ');
386         assertThat("result[1] index should be 0 using parseStringToLongArray on \"" + foo + "\"", result[1], is(0L));
387 
388         foo = String.format(Locale.ROOT, "NOLOG: Array too short %d %d %d %d", 123, 456, 789, now);
389         result = ParseUtil.parseStringToLongArray(foo, indices, 2, ' ');
390         assertThat("result[1] index should be 0 using parseStringToLongArray on \"" + foo + "\"", result[1], is(0L));
391 
392         foo = String.format(Locale.ROOT, "%d %d %d %d", 123, 456, 789, now);
393         count = ParseUtil.countStringToLongArray(foo, ' ');
394         assertThat("countStringToLongArray should return 4 for \"" + foo + "\"", count, is(4));
395 
396         foo = String.format(Locale.ROOT, "%d %d %d %d nonNumeric", 123, 456, 789, now);
397         count = ParseUtil.countStringToLongArray(foo, ' ');
398         assertThat("countStringToLongArray should return 4 for \"" + foo + "\"", count, is(4));
399 
400         foo = String.format(Locale.ROOT, "%d %d %d %d 123-456", 123, 456, 789, now);
401         count = ParseUtil.countStringToLongArray(foo, ' ');
402         assertThat("countStringToLongArray should return 4 for \"" + foo + "\"", count, is(4));
403 
404         foo = String.format(Locale.ROOT, "%d %d %d %d", 123, 456, 789, now);
405         indices = new int[] { 0 };
406         result = ParseUtil.parseStringToLongArray(foo, indices, 4, ' ');
407         assertThat("result[0] should be 123 using parseStringToLongArray on \"" + foo + "\"", result[0], is(123L));
408     }
409 
410     @Test
411     void testTextBetween() {
412         String text = "foo bar baz";
413         String before = "foo";
414         String after = "baz";
415         assertThat(ParseUtil.getTextBetweenStrings(text, before, after), is(" bar "));
416 
417         before = "";
418         assertThat(ParseUtil.getTextBetweenStrings(text, before, after), is("foo bar "));
419 
420         before = "food";
421         assertThat(ParseUtil.getTextBetweenStrings(text, before, after), is(emptyString()));
422 
423         before = "foo";
424         after = "qux";
425         assertThat(ParseUtil.getTextBetweenStrings(text, before, after), is(emptyString()));
426     }
427 
428     @Test
429     void testFiletimeToMs() {
430         assertThat(ParseUtil.filetimeToUtcMs(128166372003061629L, false), is(1172163600306L));
431     }
432 
433     @Test
434     void testParseCimDateTimeToOffset() {
435         String cimDateTime = "20160513072950.782000-420";
436         OffsetDateTime parsedTime = ParseUtil.parseCimDateTimeToOffset(cimDateTime);
437         assertNotNull(parsedTime);
438         // 2016-05-13T07:29:50 == 1463124590
439         // Add 420 minutes to get unix seconds
440         Instant timeInst = Instant.ofEpochMilli(1463124590_782L + 60 * 420_000L);
441         assertThat(parsedTime.toInstant(), is(timeInst));
442         OffsetDateTime badParsingTime = ParseUtil.parseCimDateTimeToOffset("Not a datetime");
443         assertNotNull(badParsingTime);
444         assertThat(badParsingTime.toInstant(), is(Instant.EPOCH));
445     }
446 
447     @Test
448     void testFilePathStartsWith() {
449         List<String> prefixList = Arrays.asList("/foo", "/bar");
450         assertThat(ParseUtil.filePathStartsWith(prefixList, "/foo"), is(true));
451         assertThat(ParseUtil.filePathStartsWith(prefixList, "/foo/bar"), is(true));
452         assertThat(ParseUtil.filePathStartsWith(prefixList, "/foobar"), is(false));
453         assertThat(ParseUtil.filePathStartsWith(prefixList, "/foo/baz"), is(true));
454         assertThat(ParseUtil.filePathStartsWith(prefixList, "/baz/foo"), is(false));
455     }
456 
457     @Test
458     void testParseDecimalMemorySizeToBinary() {
459         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("Not a number"), is(0L));
460         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1"), is(1L));
461         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1 kB"), is(1024L));
462         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1 KB"), is(1024L));
463         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1 MB"), is(1_048_576L));
464         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1MB"), is(1_048_576L));
465         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1 GB"), is(1_073_741_824L));
466         assertThat(ParseUtil.parseDecimalMemorySizeToBinary("1 TB"), is(1_099_511_627_776L));
467     }
468 
469     @Test
470     void testParseDeviceIdToVendorProductSerial() {
471         Triplet<String, String, String> idsAndSerial = ParseUtil
472                 .parseDeviceIdToVendorProductSerial("PCI\\VEN_10DE&DEV_134B&SUBSYS_00081414&REV_A2\\4&25BACB6&0&00E0");
473         assertThat("VEN_ DEV_ deviceID failed to parse", idsAndSerial, is(notNullValue()));
474         assertThat("Vendor ID failed to parse", idsAndSerial.getA(), is("0x10de"));
475         assertThat("Product ID failed to parse", idsAndSerial.getB(), is("0x134b"));
476         assertThat("SerialNumber should not have parsed", idsAndSerial.getC(), is(emptyString()));
477 
478         idsAndSerial = ParseUtil.parseDeviceIdToVendorProductSerial("USB\\VID_045E&PID_07C6\\000001000000");
479         assertThat("VID_ PID_ serial deviceID failed to parse", idsAndSerial, is(notNullValue()));
480         assertThat("Vendor ID failed to parse", idsAndSerial.getA(), is("0x045e"));
481         assertThat("Product ID failed to parse", idsAndSerial.getB(), is("0x07c6"));
482         assertThat("SerialNumber failed to parse", idsAndSerial.getC(), is("000001000000"));
483 
484         idsAndSerial = ParseUtil.parseDeviceIdToVendorProductSerial("USB\\VID_045E&PID_07C6\\5&000001000000");
485         assertThat("VID_ PID_ nonserial deviceID failed to parse", idsAndSerial, is(notNullValue()));
486         assertThat("Vendor ID failed to parse", idsAndSerial.getA(), is("0x045e"));
487         assertThat("Product ID failed to parse", idsAndSerial.getB(), is("0x07c6"));
488         assertThat("SerialNumber should not have parsed", idsAndSerial.getC(), is(emptyString()));
489 
490         idsAndSerial = ParseUtil
491                 .parseDeviceIdToVendorProductSerial("PCI\\VEN_80286&DEV_19116&SUBSYS_00141414&REV_07\\3&11583659&0&10");
492         assertThat("Vender and Product IDs should not have parsed", idsAndSerial, is(nullValue()));
493     }
494 
495     @Test
496     void testParseLshwResourceString() {
497         assertThat(
498                 ParseUtil.parseLshwResourceString(
499                         "irq:46 ioport:6000(size=32) memory:b0000000-bfffffff memory:e2000000-e200ffff"),
500                 is(268_435_456L + 65_536L));
501         assertThat(
502                 ParseUtil.parseLshwResourceString(
503                         "irq:46 ioport:6000(size=32) memory:b0000000-bfffffff memory:x2000000-e200ffff"),
504                 is(268_435_456L));
505         assertThat(ParseUtil.parseLshwResourceString(
506                 "irq:46 ioport:6000(size=32) memory:x0000000-bfffffff memory:e2000000-e200ffff"), is(65_536L));
507         assertThat(ParseUtil.parseLshwResourceString("some random string"), is(0L));
508     }
509 
510     @Test
511     void testParseLspciMachineReadable() {
512         Pair<String, String> pair = ParseUtil.parseLspciMachineReadable("foo [bar]");
513         assertThat("First element of pair mismatch.", pair.getA(), is("foo"));
514         assertThat("Second element of pair mismatch.", pair.getB(), is("bar"));
515         assertThat(ParseUtil.parseLspciMachineReadable("Bad format"), is(nullValue()));
516     }
517 
518     @Test
519     void testParseLspciMemorySize() {
520         assertThat(ParseUtil.parseLspciMemorySize("Doesn't parse"), is(0L));
521         assertThat(ParseUtil.parseLspciMemorySize("Foo [size=64K]"), is(64L * 1024L));
522         assertThat(ParseUtil.parseLspciMemorySize("Foo [size=256M]"), is(256L * 1024L * 1024L));
523     }
524 
525     @Test
526     void testParseHyphenatedIntList() {
527         String s = "1";
528         List<Integer> parsed = ParseUtil.parseHyphenatedIntList(s);
529         assertThat(parsed, not(hasItems(0)));
530         assertThat(parsed, contains(1));
531 
532         s = "0 2-5 7";
533         parsed = ParseUtil.parseHyphenatedIntList(s);
534         assertThat(parsed, contains(0, 2, 3, 4, 5, 7));
535         assertThat(parsed, not(hasItems(1)));
536         assertThat(parsed, not(hasItems(6)));
537 
538         s = "0, 2-5, 7-8, 9";
539         parsed = ParseUtil.parseHyphenatedIntList(s);
540         assertThat(parsed, contains(0, 2, 3, 4, 5, 7, 8, 9));
541         assertThat(parsed, not(hasItems(1)));
542         assertThat(parsed, not(hasItems(6)));
543     }
544 
545     @Test
546     void testParseMmDdYyyyToYyyyMmDD() {
547         assertThat("Unable to parse MM-DD-YYYY date string into YYYY-MM-DD date string",
548                 ParseUtil.parseMmDdYyyyToYyyyMmDD("00-11-2222"), is("2222-00-11"));
549         assertThat("Date string should not be parsed", ParseUtil.parseMmDdYyyyToYyyyMmDD("badstr"), is("badstr"));
550     }
551 
552     @Test
553     void testParseIntToIP() {
554         // IP addresses are big endian
555         int ip = 1 | 2 << 8 | 3 << 16 | 4 << 24;
556         byte[] ipb = { (byte) 1, (byte) 2, (byte) 3, (byte) 4 };
557         assertThat("IP did not parse properly", ParseUtil.parseIntToIP(ip), is(ipb));
558     }
559 
560     @Test
561     void testParseIntArrayToIP() {
562         // IP addresses are big endian
563         int[] ip = new int[4];
564         ip[0] = 1 | 2 << 8 | 3 << 16 | 4 << 24;
565         ip[1] = 5 | 6 << 8 | 7 << 16 | 8 << 24;
566         ip[2] = 9 | 10 << 8 | 11 << 16 | 12 << 24;
567         ip[3] = 13 | 14 << 8 | 15 << 16 | 16 << 24;
568         byte[] ipb = { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 9,
569                 (byte) 10, (byte) 11, (byte) 12, (byte) 13, (byte) 14, (byte) 15, (byte) 16 };
570         assertThat("IP array did not parse properly", ParseUtil.parseIntArrayToIP(ip), is(ipb));
571     }
572 
573     @Test
574     void testBigEndian16ToLittleEndian() {
575         assertThat("Port 80 did not convert properly", ParseUtil.bigEndian16ToLittleEndian(0x5000), is(80));
576         assertThat("Port 443 did not convert properly", ParseUtil.bigEndian16ToLittleEndian(0xBB01), is(443));
577     }
578 
579     @Test
580     void testParseUtAddrV6toIP() {
581         int[] zero = { 0, 0, 0, 0 };
582         int[] loopback = { 0, 0, 0, 1 };
583         String v6test = "2001:db8:85a3::8a2e:370:7334";
584         int[] v6 = new int[4];
585         v6[0] = Integer.parseUnsignedInt("20010db8", 16);
586         v6[1] = Integer.parseUnsignedInt("85a30000", 16);
587         v6[2] = Integer.parseUnsignedInt("00008a2e", 16);
588         v6[3] = Integer.parseUnsignedInt("03707334", 16);
589         String v4test = "127.0.0.1";
590         int[] v4 = new int[4];
591         v4[0] = (127 << 24) + 1;
592         int[] invalid = { 0, 0, 0 };
593 
594         assertThat("Unspecified address failed", ParseUtil.parseUtAddrV6toIP(zero), is("::"));
595         assertThat("Loopback address failed", ParseUtil.parseUtAddrV6toIP(loopback), is("::1"));
596         assertThat("V6 parsing failed", ParseUtil.parseUtAddrV6toIP(v6), is(v6test));
597         assertThat("V4 parsing failed", ParseUtil.parseUtAddrV6toIP(v4), is(v4test));
598         assertThrows(IllegalArgumentException.class, () -> {
599             ParseUtil.parseUtAddrV6toIP(invalid);
600         });
601     }
602 
603     @Test
604     void testHexStringToInt() {
605         assertThat("Parsing ff failed", ParseUtil.hexStringToInt("ff", 0), is(255));
606         assertThat("Parsing 830f53a0 failed", ParseUtil.hexStringToInt("830f53a0", 0), is(-2096147552));
607         assertThat("Parsing pqwe failed", ParseUtil.hexStringToInt("pqwe", 0), is(0));
608         assertThat("Parsing 0xff failed", ParseUtil.hexStringToInt("0xff", 0), is(255));
609         assertThat("Parsing 0x830f53a0 failed", ParseUtil.hexStringToInt("0x830f53a0", 0), is(-2096147552));
610         assertThat("Parsing 0xpqwe failed", ParseUtil.hexStringToInt("0xpqwe", 0), is(0));
611     }
612 
613     @Test
614     void testHexStringToLong() {
615         assertThat("Parsing ff failed", ParseUtil.hexStringToLong("ff", 0L), is(255L));
616         assertThat("Parsing 830f53a0 failed", ParseUtil.hexStringToLong("ffffffff830f53a0", 0L), is(-2096147552L));
617         assertThat("Parsing pqwe failed", ParseUtil.hexStringToLong("pqwe", 0L), is(0L));
618         assertThat("Parsing 0xff failed", ParseUtil.hexStringToLong("0xff", 0L), is(255L));
619         assertThat("Parsing 0x830f53a0 failed", ParseUtil.hexStringToLong("0xffffffff830f53a0", 0L), is(-2096147552L));
620         assertThat("Parsing 0xpqwe failed", ParseUtil.hexStringToLong("0xpqwe", 0L), is(0L));
621     }
622 
623     @Test
624     void testRemoveLeadingDots() {
625         assertThat(ParseUtil.removeLeadingDots("foo"), is("foo"));
626         assertThat(ParseUtil.removeLeadingDots("...bar"), is("bar"));
627         assertThat(ParseUtil.removeLeadingDots("..."), is(""));
628     }
629 
630     @Test
631     void testParseMultipliedToLongs() {
632         assertThat(ParseUtil.parseMultipliedToLongs("Not a number"), is(0L));
633         assertThat(ParseUtil.parseMultipliedToLongs("1"), is(1L));
634         assertThat(ParseUtil.parseMultipliedToLongs("1.2"), is(1L));
635         assertThat(ParseUtil.parseMultipliedToLongs("1 k"), is(1_000L));
636         assertThat(ParseUtil.parseMultipliedToLongs("1 M"), is(1_000_000L));
637         assertThat(ParseUtil.parseMultipliedToLongs("1MB"), is(1_000_000L));
638         assertThat(ParseUtil.parseMultipliedToLongs("1MC"), is(1_000_000L));
639         assertThat(ParseUtil.parseMultipliedToLongs("1 T"), is(1_000_000_000_000L));
640         assertThat(ParseUtil.parseMultipliedToLongs("1073M"), is(1073000000L));
641         assertThat(ParseUtil.parseMultipliedToLongs("1073 G"), is(1073000000000L));
642         assertThat(ParseUtil.parseMultipliedToLongs("12K"), is(12000L));
643     }
644 
645     @Test
646     void parseByteArrayToStrings() {
647         byte[] bytes = "foo bar".getBytes(StandardCharsets.US_ASCII);
648         bytes[3] = 0;
649         List<String> list = ParseUtil.parseByteArrayToStrings(bytes);
650         assertThat(list, contains("foo", "bar"));
651 
652         bytes[4] = 0;
653         list = ParseUtil.parseByteArrayToStrings(bytes);
654         assertThat(list, contains("foo"));
655 
656         bytes[0] = 0;
657         list = ParseUtil.parseByteArrayToStrings(bytes);
658         assertThat(list, empty());
659 
660         bytes = new byte[0];
661         list = ParseUtil.parseByteArrayToStrings(bytes);
662         assertThat(list, empty());
663     }
664 
665     @Test
666     void parseByteArrayToStringMap() {
667         byte[] bytes = "foo=1 bar=2".getBytes(StandardCharsets.US_ASCII);
668         bytes[5] = 0;
669         Map<String, String> map = ParseUtil.parseByteArrayToStringMap(bytes);
670         assertThat(map.keySet(), containsInAnyOrder("foo", "bar"));
671         assertThat(map.values(), containsInAnyOrder("1", "2"));
672         assertThat(map.get("foo"), is("1"));
673         assertThat(map.get("bar"), is("2"));
674 
675         bytes[10] = 0;
676         map = ParseUtil.parseByteArrayToStringMap(bytes);
677         assertThat(map.keySet(), containsInAnyOrder("foo", "bar"));
678         assertThat(map.values(), containsInAnyOrder("1", ""));
679         assertThat(map.get("foo"), is("1"));
680         assertThat(map.get("bar"), is(""));
681 
682         bytes = "foo=1 bar=2".getBytes(StandardCharsets.US_ASCII);
683         bytes[5] = 0;
684         bytes[6] = 0;
685         map = ParseUtil.parseByteArrayToStringMap(bytes);
686         assertThat(map.keySet(), contains("foo"));
687         assertThat(map.values(), contains("1"));
688         assertThat(map.get("foo"), is("1"));
689 
690         bytes[0] = 0;
691         map = ParseUtil.parseByteArrayToStringMap(bytes);
692         assertThat(map, anEmptyMap());
693 
694         bytes = new byte[0];
695         map = ParseUtil.parseByteArrayToStringMap(bytes);
696         assertThat(map, anEmptyMap());
697     }
698 
699     @Test
700     void parseCharArrayToStringMap() {
701         char[] chars = "foo=1 bar=2".toCharArray();
702         chars[5] = 0;
703         Map<String, String> map = ParseUtil.parseCharArrayToStringMap(chars);
704         assertThat(map.keySet(), containsInAnyOrder("foo", "bar"));
705         assertThat(map.values(), containsInAnyOrder("1", "2"));
706         assertThat(map.get("foo"), is("1"));
707         assertThat(map.get("bar"), is("2"));
708 
709         chars[10] = 0;
710         map = ParseUtil.parseCharArrayToStringMap(chars);
711         assertThat(map.keySet(), containsInAnyOrder("foo", "bar"));
712         assertThat(map.values(), containsInAnyOrder("1", ""));
713         assertThat(map.get("foo"), is("1"));
714         assertThat(map.get("bar"), is(""));
715 
716         chars = "foo=1 bar=2".toCharArray();
717         chars[5] = 0;
718         chars[6] = 0;
719         map = ParseUtil.parseCharArrayToStringMap(chars);
720         assertThat(map.keySet(), contains("foo"));
721         assertThat(map.values(), contains("1"));
722         assertThat(map.get("foo"), is("1"));
723 
724         chars[0] = 0;
725         map = ParseUtil.parseCharArrayToStringMap(chars);
726         assertThat(map, anEmptyMap());
727 
728         chars = new char[0];
729         map = ParseUtil.parseCharArrayToStringMap(chars);
730         assertThat(map, anEmptyMap());
731     }
732 
733     @Test
734     void teststringToEnumMap() {
735         String two = "one,two";
736         Map<TestEnum, String> map = ParseUtil.stringToEnumMap(TestEnum.class, two, ',');
737         assertThat(map.get(TestEnum.FOO), is("one"));
738         assertThat(map.get(TestEnum.BAR), is("two"));
739         assertThat(map.containsKey(TestEnum.BAZ), is(false));
740 
741         String three = "one,,two,three";
742         map = ParseUtil.stringToEnumMap(TestEnum.class, three, ',');
743         assertThat(map.get(TestEnum.FOO), is("one"));
744         assertThat(map.get(TestEnum.BAR), is("two"));
745         assertThat(map.get(TestEnum.BAZ), is("three"));
746 
747         String four = "one,two,three,four";
748         map = ParseUtil.stringToEnumMap(TestEnum.class, four, ',');
749         assertThat(map.get(TestEnum.FOO), is("one"));
750         assertThat(map.get(TestEnum.BAR), is("two"));
751         assertThat(map.get(TestEnum.BAZ), is("three,four"));
752 
753         String empty = "";
754         map = ParseUtil.stringToEnumMap(TestEnum.class, empty, ',');
755         assertThat(map.get(TestEnum.FOO), is(""));
756     }
757 
758     @Test
759     void testgetValueOrUnknown() {
760         String key = "key";
761         Map<String, String> map = new HashMap<>();
762         assertThat(ParseUtil.getValueOrUnknown(map, key), is(Constants.UNKNOWN));
763 
764         map.put("key", "value");
765         assertThat(ParseUtil.getValueOrUnknown(map, key), is("value"));
766     }
767 }