1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.*;
  25 import java.nio.*;
  26 import java.util.*;
  27 import java.util.stream.*;
  28 import static java.nio.charset.StandardCharsets.*;
  29 import static java.util.HexFormat.*;
  30 
  31 /**
  32  * @test
  33  * @bug 8170769
  34  * @summary test hexadecimal conversions to/from binary data.
  35  */
  36 
  37 public class HexdumpTest {
  38     private static final String LINE_SEPARATOR = String.format("%n");
  39 
  40     /**
  41      * Formatter that generates a custom hexdump format (8-byte chunks).
  42      */
  43     public static final HexFormat.Formatter CUSTOM_8_HEXDUMP_FORMATTER = new HexFormat.Formatter() {
  44         public String format(long offset, byte[] chunk, int fromIndex, int toIndex) {
  45             return String.format("%04d %-16s %s",
  46                 offset,
  47                 HexFormat.toString(chunk, fromIndex, toIndex),
  48                 HexFormat.toPrintableString(chunk, fromIndex, toIndex));
  49         }
  50     };
  51 
  52     /**
  53      * Formatter that generates a custom hexdump format (32-byte chunks).
  54      */
  55     public static final HexFormat.Formatter CUSTOM_32_HEXDUMP_FORMATTER = new HexFormat.Formatter() {
  56         public String format(long offset, byte[] chunk, int fromIndex, int toIndex) {
  57             return String.format("%04d %-64s %s",
  58                 offset,
  59                 HexFormat.toString(chunk, fromIndex, toIndex),
  60                 HexFormat.toPrintableString(chunk, fromIndex, toIndex));
  61         }
  62     };
  63 
  64     /**
  65      * Formatter that generates a custom hexdump format (supports Latin-1).
  66      */
  67     public static final HexFormat.Formatter CUSTOM_LATIN1_HEXDUMP_FORMATTER = new HexFormat.Formatter() {
  68 
  69         public String format(long offset, byte[] chunk, int fromIndex, int toIndex) {
  70             return String.format("%04d %s %s",
  71                 offset,
  72                 HexFormat.toFormattedString(chunk, fromIndex, toIndex),
  73                 new String(chunk, fromIndex, toIndex - fromIndex, ISO_8859_1).replaceAll("[\\x00-\\x1F\\x7F]", "."));
  74         }
  75     };
  76 
  77     public static final void main(String[] args) throws Exception {
  78 
  79         // Test data for byte array
  80         List<byte[]> byteArrayData = new ArrayList<>() {{
  81             add(new byte[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 });
  82             add(new byte[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 });
  83             add(new byte[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 });
  84             add(new byte[]{ (byte)0, (byte)0, (byte)134, (byte)0, (byte)61 });
  85             add(new byte[]{ (byte)0x00, (byte)0x01, (byte)0x02 });
  86             add(new byte[]{ (byte)0x00, (byte)0x01 });
  87             add(new byte[]{ (byte)0x00 });
  88             add(new byte[0]);
  89             add(new byte[]{ 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
  90                 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,
  91                 70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,
  92                 91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,
  93                 109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,
  94                 125,126,127 });
  95         }};
  96 
  97         // Test data for byte array (Latin1)
  98         List<byte[]> latin1ByteArrayData = new ArrayList<>() {{
  99             add(new byte[]{ (byte)192, (byte)193, (byte)194, (byte)195, (byte)196, (byte)197, (byte)198, (byte)199,
 100                             (byte)200, (byte)201, (byte)202, (byte)203, (byte)204, (byte)205, (byte)206, (byte)207 });
 101             add(new byte[]{ (byte)192, 1, (byte)193, 2, (byte)194, 3, (byte)195, 4, (byte)196, 5, (byte)197, 6 });
 102             add(new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
 103                             16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 104                             32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 105                             48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 106                             64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 107                             80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
 108                             96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
 109                             112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
 110                             (byte)127, (byte)128, (byte)129, (byte)130, (byte)131, (byte)132, (byte)133, (byte)134,
 111                             (byte)135, (byte)136, (byte)137, (byte)138, (byte)139, (byte)140, (byte)141, (byte)142,
 112                             (byte)143, (byte)144, (byte)145, (byte)146, (byte)147, (byte)148, (byte)149, (byte)150,
 113                             (byte)151, (byte)152, (byte)153, (byte)154, (byte)155, (byte)156, (byte)157, (byte)158,
 114                             (byte)159, (byte)160, (byte)161, (byte)162, (byte)163, (byte)164, (byte)165, (byte)166,
 115                             (byte)167, (byte)168, (byte)169, (byte)170, (byte)171, (byte)172, (byte)173, (byte)174,
 116                             (byte)175, (byte)176, (byte)177, (byte)178, (byte)179, (byte)180, (byte)181, (byte)182,
 117                             (byte)183, (byte)184, (byte)185, (byte)186, (byte)187, (byte)188, (byte)189, (byte)190,
 118                             (byte)191, (byte)192, (byte)193, (byte)194, (byte)195, (byte)196, (byte)197, (byte)198,
 119                             (byte)199, (byte)200, (byte)201, (byte)202, (byte)203, (byte)204, (byte)205, (byte)206,
 120                             (byte)207, (byte)208, (byte)209, (byte)210, (byte)211, (byte)212, (byte)213, (byte)214,
 121                             (byte)215, (byte)216, (byte)217, (byte)218, (byte)219, (byte)220, (byte)221, (byte)222,
 122                             (byte)223, (byte)224, (byte)225, (byte)226, (byte)227, (byte)228, (byte)229, (byte)230,
 123                             (byte)231, (byte)232, (byte)233, (byte)234, (byte)235, (byte)236, (byte)237, (byte)238,
 124                             (byte)239, (byte)240, (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246,
 125                             (byte)247, (byte)248, (byte)249, (byte)250, (byte)251, (byte)252, (byte)253, (byte)254,
 126                             (byte)255 });
 127         }};
 128 
 129         // Test data for String
 130         List<String> stringData = new ArrayList<>() {{
 131             add("000102030405060708090a0b0c0d0e0f101112");
 132             add("000102030405060708090a0b0c0d0e0f");
 133             add("000102030405060708090a0b0c0d0e");
 134             add("000086003d");
 135             add("000102");
 136             add("0001");
 137             add("00");
 138             add("");
 139             add("202122232425262728292a2b2c2d2e2f" +
 140                 "303132333435363738393a3b3c3d3e3f" +
 141                 "404142434445464748494a4b4c4d4e4f" +
 142                 "505152535455565758595a5b5c5d5e5f" +
 143                 "606162636465666768696a6b6c6d6e6f" +
 144                 "707172737475767778797a7b7c7d7e7f");
 145         }};
 146 
 147         // Test data for Stream of String
 148         List<List<String>> streamData = new ArrayList<>() {{
 149             add(List.of(
 150                 "00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|",
 151                 "00000010  10 11 12                                          |...|"));
 152             add(List.of(
 153                 "00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|"
 154                 ));
 155             add(List.of(
 156                 "00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e     |...............|"
 157                 ));
 158             add(List.of(
 159                 "00000000  00 00 86 00 3d                                    |....=|"));
 160             add(List.of(
 161                 "00000000  00 01 02                                          |...|"));
 162             add(List.of(
 163                 "00000000  00 01                                             |..|"));
 164             add(List.of(
 165                 "00000000  00                                                |.|"));
 166             add(Collections.emptyList());
 167             add(List.of(
 168                 "00000000  20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f  | !\"#$%&'()*+,-./|",
 169                 "00000010  30 31 32 33 34 35 36 37  38 39 3a 3b 3c 3d 3e 3f  |0123456789:;<=>?|",
 170                 "00000020  40 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f  |@ABCDEFGHIJKLMNO|",
 171                 "00000030  50 51 52 53 54 55 56 57  58 59 5a 5b 5c 5d 5e 5f  |PQRSTUVWXYZ[\\]^_|",
 172                 "00000040  60 61 62 63 64 65 66 67  68 69 6a 6b 6c 6d 6e 6f  |`abcdefghijklmno|",
 173                 "00000050  70 71 72 73 74 75 76 77  78 79 7a 7b 7c 7d 7e 7f  |pqrstuvwxyz{|}~.|"
 174                 ));
 175         }};
 176 
 177         // Test data for Stream of String (subarray)
 178         List<List<String>> subarrayStreamData = new ArrayList<>() {{
 179             add(List.of(
 180                 "00000000  01 02 03 04 05 06 07 08  09 0a 0b 0c 0d 0e 0f 10  |................|",
 181                 "00000010  11                                                |.|"));
 182             add(List.of(
 183                 "00000000  01 02 03 04 05 06 07 08  09 0a 0b 0c 0d 0e        |..............|"
 184                 ));
 185             add(List.of(
 186                 "00000000  01 02 03 04 05 06 07 08  09 0a 0b 0c 0d           |.............|"
 187                 ));
 188             add(List.of(
 189                 "00000000  00 86 00                                          |...|"));
 190             add(List.of(
 191                 "00000000  01                                                |.|"));
 192             add(Collections.emptyList()); // skipped, too short
 193             add(Collections.emptyList()); // skipped, too short
 194             add(Collections.emptyList()); // skipped, too short
 195             add(List.of(
 196                 "00000000  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!\"#$%&'()*+,-./0|",
 197                 "00000010  31 32 33 34 35 36 37 38  39 3a 3b 3c 3d 3e 3f 40  |123456789:;<=>?@|",
 198                 "00000020  41 42 43 44 45 46 47 48  49 4a 4b 4c 4d 4e 4f 50  |ABCDEFGHIJKLMNOP|",
 199                 "00000030  51 52 53 54 55 56 57 58  59 5a 5b 5c 5d 5e 5f 60  |QRSTUVWXYZ[\\]^_`|",
 200                 "00000040  61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  |abcdefghijklmnop|",
 201                 "00000050  71 72 73 74 75 76 77 78  79 7a 7b 7c 7d 7e        |qrstuvwxyz{|}~|"
 202                 ));
 203         }};
 204 
 205         // Test data for Stream of custom String
 206         List<List<String>> customStreamData = new ArrayList<>() {{
 207             add(List.of(
 208                 "0000 000102030405060708090a0b0c0d0e0f101112                           ..................."));
 209             add(List.of(
 210                 "0000 000102030405060708090a0b0c0d0e0f                                 ................"));
 211             add(List.of(
 212                 "0000 000102030405060708090a0b0c0d0e                                   ..............."));
 213             add(List.of(
 214                 "0000 000086003d                                                       ....="));
 215             add(List.of(
 216                 "0000 000102                                                           ..."));
 217             add(List.of(
 218                 "0000 0001                                                             .."));
 219             add(List.of(
 220                 "0000 00                                                               ."));
 221             add(Collections.emptyList());
 222             add(List.of(
 223                 "0000 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f  !\"#$%&'()*+,-./0123456789:;<=>?",
 224                 "0032 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_",
 225                 "0064 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f `abcdefghijklmnopqrstuvwxyz{|}~."
 226                 ));
 227         }};
 228 
 229         // Test data for Stream of Latin-1 String
 230         List<List<String>> customLatin1StreamData = new ArrayList<>() {{
 231             add(List.of(
 232                 "00000000  c0 c1 c2 c3 c4 c5 c6 c7  c8 c9 ca cb cc cd ce cf  |ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ|"
 233                 ));
 234             add(List.of(
 235                 "00000000  c0 01 c1 02 c2 03 c3 04  c4 05 c5 06              |À.Á.Â.Ã.Ä.Å.|"
 236                 ));
 237             add(List.of(
 238                 "00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|",
 239                 "00000010  10 11 12 13 14 15 16 17  18 19 1a 1b 1c 1d 1e 1f  |................|",
 240                 "00000020  20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f  | !\"#$%&'()*+,-./|",
 241                 "00000030  30 31 32 33 34 35 36 37  38 39 3a 3b 3c 3d 3e 3f  |0123456789:;<=>?|",
 242                 "00000040  40 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f  |@ABCDEFGHIJKLMNO|",
 243                 "00000050  50 51 52 53 54 55 56 57  58 59 5a 5b 5c 5d 5e 5f  |PQRSTUVWXYZ[\\]^_|",
 244                 "00000060  60 61 62 63 64 65 66 67  68 69 6a 6b 6c 6d 6e 6f  |`abcdefghijklmno|",
 245                 "00000070  70 71 72 73 74 75 76 77  78 79 7a 7b 7c 7d 7e 7f  |pqrstuvwxyz{|}~.|",
 246                 "00000080  80 81 82 83 84 85 86 87  88 89 8a 8b 8c 8d 8e 8f  |................|",
 247                 "00000090  90 91 92 93 94 95 96 97  98 99 9a 9b 9c 9d 9e 9f  |................|",
 248                 "000000a0  a0 a1 a2 a3 a4 a5 a6 a7  a8 a9 aa ab ac ad ae af  |\u00A0¡¢£¤¥¦§¨©ª«¬­®¯|",
 249                 "000000b0  b0 b1 b2 b3 b4 b5 b6 b7  b8 b9 ba bb bc bd be bf  |°±²³´µ¶·¸¹º»¼½¾¿|",
 250                 "000000c0  c0 c1 c2 c3 c4 c5 c6 c7  c8 c9 ca cb cc cd ce cf  |ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ|",
 251                 "000000d0  d0 d1 d2 d3 d4 d5 d6 d7  d8 d9 da db dc dd de df  |ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß|",
 252                 "000000e0  e0 e1 e2 e3 e4 e5 e6 e7  e8 e9 ea eb ec ed ee ef  |àáâãäåæçèéêëìíîï|",
 253                 "000000f0  f0 f1 f2 f3 f4 f5 f6 f7  f8 f9 fa fb fc fd fe ff  |ðñòóôõö÷øùúûüýþÿ|"
 254                ));
 255         }};
 256 
 257         // Test data for Stream of custom String (byteBuffer)
 258         List<List<String>> byteBufferStreamData = new ArrayList<>() {{
 259             add(List.of(
 260                 "0000 0001020304050607 ........",
 261                 "0008 08090a0b0c0d0e0f ........",
 262                 "0016 101112           ..."
 263                 ));
 264             add(List.of(
 265                 "0000 0001020304050607 ........",
 266                 "0008 08090a0b0c0d0e0f ........"
 267                 ));
 268             add(List.of(
 269                 "0000 0001020304050607 ........",
 270                 "0008 08090a0b0c0d0e   ......."
 271                 ));
 272             add(List.of(
 273                 "0000 000086003d       ....="
 274                 ));
 275             add(List.of(
 276                 "0000 000102           ..."
 277                 ));
 278             add(List.of(
 279                 "0000 0001             .."
 280                 ));
 281             add(List.of(
 282                 "0000 00               ."
 283                 ));
 284             add(Collections.emptyList());
 285             add(List.of(
 286                 "0000 2021222324252627  !\"#$%&'",
 287                 "0008 28292a2b2c2d2e2f ()*+,-./",
 288                 "0016 3031323334353637 01234567",
 289                 "0024 38393a3b3c3d3e3f 89:;<=>?",
 290                 "0032 4041424344454647 @ABCDEFG",
 291                 "0040 48494a4b4c4d4e4f HIJKLMNO",
 292                 "0048 5051525354555657 PQRSTUVW",
 293                 "0056 58595a5b5c5d5e5f XYZ[\\]^_",
 294                 "0064 6061626364656667 `abcdefg",
 295                 "0072 68696a6b6c6d6e6f hijklmno",
 296                 "0080 7071727374757677 pqrstuvw",
 297                 "0088 78797a7b7c7d7e7f xyz{|}~."
 298                 ));
 299         }};
 300 
 301         // Testing byte array conversions to hex string
 302         System.out.println("----------");
 303         for (int i = 0; i < byteArrayData.size(); i++) {
 304             byte[] input = byteArrayData.get(i);
 305             String expected = stringData.get(i);
 306             String output = HexFormat.toString(input);
 307             if (expected.equals(output)) {
 308                 System.out.println((i + 1) + ") Generated hex string: \"" + output + "\"");
 309             } else {
 310                 throw new Exception("ERROR: expected: \"" + expected +
 311                     "\" but received: \"" + output + "\"");
 312             }
 313         }
 314 
 315         // Testing subarray conversions to hex string
 316         System.out.println("----------");
 317         for (int i = 0; i < byteArrayData.size(); i++) {
 318             byte[] input = byteArrayData.get(i);
 319             if (input.length < 2) {
 320                 System.out.println((i + 1) + ") Input too short - skipping...");
 321                 continue;
 322             }
 323             String expected = stringData.get(i).toLowerCase();
 324             expected = expected.substring(2, expected.length() - 2);
 325             String output = HexFormat.toString(input, 1, input.length - 1);
 326             if (expected.equals(output)) {
 327                 System.out.println((i + 1) +
 328                     ") Generated subarray hex string: \"" + output + "\"");
 329             } else {
 330                 throw new Exception("ERROR: expected: \"" + expected +
 331                     "\" but received: \"" + output + "\"");
 332             }
 333         }
 334 
 335         // Testing conversions from hex string
 336         System.out.println("----------");
 337         for (int i = 0; i < stringData.size(); i++) {
 338             String input = stringData.get(i);
 339             byte[] expected = byteArrayData.get(i);
 340             byte[] output = HexFormat.fromString(input);
 341             if (Arrays.equals(expected, output)) {
 342                 System.out.println((i + 1) + ") Parsed hex string: \"" + input + "\"");
 343             } else {
 344                 throw new Exception("ERROR: expected: " +
 345                     Arrays.toString(expected) + " but received: " +
 346                     Arrays.toString(output));
 347             }
 348         }
 349 
 350         // Testing conversions to stream of hexdump string
 351         System.out.println("----------");
 352         for (int i = 0; i < byteArrayData.size(); i++) {
 353             byte[] input = byteArrayData.get(i);
 354             Stream<String> expected =
 355                 Stream.of(streamData.get(i).toArray(new String[0]));
 356             Stream<String> output = HexFormat.dumpAsStream(input);
 357             Object[] expectedArray = expected.toArray();
 358             System.out.println((i + 1) + ") Generating stream of hexdump string: (from byte array)");
 359             if (Arrays.equals(expectedArray, output.toArray())) {
 360                 HexFormat.dumpAsStream(input).forEach(System.out::println);
 361             } else {
 362                 throw new Exception(
 363                     "ERROR: expected this stream of hexdump string: " +
 364                     Arrays.toString(expectedArray) + " but received: " +
 365                     Arrays.toString(HexFormat.dumpAsStream(input).toArray()));
 366             }
 367         }
 368 
 369         // Testing subarray conversions to stream of hexdump string
 370         System.out.println("----------");
 371         for (int i = 0; i < byteArrayData.size(); i++) {
 372             byte[] input = byteArrayData.get(i);
 373             if (input.length < 2) {
 374                 System.out.println((i + 1) + ") Input too short - skipping...");
 375                 continue;
 376             }
 377             Stream<String> expected =
 378                 Stream.of(subarrayStreamData.get(i).toArray(new String[0]));
 379             Stream<String> output =
 380                 HexFormat.dumpAsStream(input, 1, input.length - 1, 16, null);
 381             Object[] expectedArray = expected.toArray();
 382             System.out.println((i + 1) + ") Generating stream of hexdump string: (from byte subarray)");
 383             if (Arrays.equals(expectedArray, output.toArray())) {
 384                 HexFormat.dumpAsStream(input, 1, input.length - 1, 16, null)
 385                     .forEach(System.out::println);
 386             } else {
 387                 throw new Exception(
 388                     "ERROR: expected this stream of hexdump string: " +
 389                     Arrays.toString(expectedArray) + " but received: " +
 390                     Arrays.toString(
 391                         HexFormat.dumpAsStream(input, 1, input.length - 1, 16, null)
 392                             .toArray()));
 393             }
 394         }
 395 
 396         // Testing subarray conversions to stream of hexdump string
 397         System.out.println("----------");
 398         for (int i = 0; i < byteArrayData.size(); i++) {
 399             byte[] input = byteArrayData.get(i);
 400             if (input.length < 2) {
 401                 System.out.println((i + 1) + ") Input too short - skipping...");
 402                 continue;
 403             }
 404             Stream<String> expected =
 405                 Stream.of(subarrayStreamData.get(i).toArray(new String[0]));
 406             Stream<String> output =
 407                 HexFormat.dumpAsStream(Arrays.copyOfRange(input, 1, input.length - 1));
 408             Object[] expectedArray = expected.toArray();
 409             System.out.println((i + 1) + ") Generating stream of hexdump string: (from byte subarray)");
 410             if (Arrays.equals(expectedArray, output.toArray())) {
 411                 HexFormat.dumpAsStream(Arrays.copyOfRange(input, 1, input.length - 1))
 412                     .forEach(System.out::println);
 413             } else {
 414                 throw new Exception(
 415                     "ERROR: expected this stream of hexdump string: " +
 416                     Arrays.toString(expectedArray) + " but received: " +
 417                     Arrays.toString(
 418                         HexFormat.dumpAsStream(Arrays.copyOfRange(input, 1, input.length - 1))
 419                             .toArray()));
 420             }
 421         }
 422 
 423         // Testing conversions to stream of custom hexdump string using 32-byte chunks
 424         System.out.println("----------");
 425         for (int i = 0; i < byteArrayData.size(); i++) {
 426             byte[] input = byteArrayData.get(i);
 427             Stream<String> expected =
 428                 Stream.of(customStreamData.get(i).toArray(new String[0]));
 429             Stream<String> output = HexFormat.dumpAsStream(input, 0, input.length, 32, CUSTOM_32_HEXDUMP_FORMATTER);
 430             Object[] expectedArray = expected.toArray();
 431             System.out.println((i + 1) + ") Generating stream of custom hexdump string: (from byte array)");
 432             if (Arrays.equals(expectedArray, output.toArray())) {
 433                 HexFormat.dumpAsStream(input, 0, input.length, 32, CUSTOM_32_HEXDUMP_FORMATTER)
 434                     .forEach(System.out::println);
 435             } else {
 436                 throw new Exception(
 437                     "ERROR: expected this stream of hexdump string: " +
 438                     Arrays.toString(expectedArray) + " but received: " +
 439                     Arrays.toString(HexFormat.dumpAsStream(input, 0, input.length, 32, CUSTOM_32_HEXDUMP_FORMATTER)
 440                         .toArray()));
 441             }
 442         }
 443 
 444         // Testing conversions to stream of custom hexdump string using Latin-1
 445         System.out.println("----------");
 446         for (int i = 0; i < latin1ByteArrayData.size(); i++) {
 447             byte[] input = latin1ByteArrayData.get(i);
 448             Stream<String> expected =
 449                 Stream.of(customLatin1StreamData.get(i).toArray(new String[0]));
 450             //VR Stream<String> output = HexFormat.dumpAsStream(input, 0, input.length, 16, CUSTOM_LATIN1_HEXDUMP_FORMATTER);
 451             Stream<String> output = HexFormat.dumpAsStream(input, 0, input.length, 16, null);
 452             Object[] expectedArray = expected.toArray();
 453             System.out.println((i + 1) + ") Generating stream of custom Latin-1 hexdump string: (from byte array)");
 454             if (Arrays.equals(expectedArray, output.toArray())) {
 455                 //VR HexFormat.dumpAsStream(input, 0, input.length, 16, CUSTOM_LATIN1_HEXDUMP_FORMATTER)
 456                 HexFormat.dumpAsStream(input, 0, input.length, 16, null)
 457                     .forEach(System.out::println);
 458             } else {
 459                  System.out.println("VR: error at byte["+i+"]");
 460                 throw new Exception(
 461                     "ERROR: expected this stream of hexdump string: " +
 462                     Arrays.toString(expectedArray) + " but received: " +
 463                     //VR Arrays.toString(HexFormat.dumpAsStream(input, 0, input.length, 16, CUSTOM_LATIN1_HEXDUMP_FORMATTER)
 464                     Arrays.toString(HexFormat.dumpAsStream(input, 0, input.length, 16, null)
 465                         .toArray()));
 466             }
 467         }
 468 
 469         // Testing ByteBuffer conversions to stream of custom hexdump string using 8-byte chunks
 470         System.out.println("----------");
 471         for (int i = 0; i < byteArrayData.size(); i++) {
 472             byte[] input = byteArrayData.get(i);
 473             Stream<String> expected =
 474                 Stream.of(byteBufferStreamData.get(i).toArray(new String[0]));
 475             Stream<String> output =
 476                 HexFormat.dumpAsStream(ByteBuffer.wrap(input), 0, input.length, 8, CUSTOM_8_HEXDUMP_FORMATTER);
 477             Object[] expectedArray = expected.toArray();
 478             System.out.println((i + 1) + ") Generating stream of custom hexdump string: (from ByteBuffer)");
 479             if (Arrays.equals(expectedArray, output.toArray())) {
 480                 HexFormat.dumpAsStream(ByteBuffer.wrap(input), 0, input.length, 8, CUSTOM_8_HEXDUMP_FORMATTER)
 481                     .forEach(System.out::println);
 482             } else {
 483                 throw new Exception(
 484                     "ERROR: expected this stream of custom hexdump string: " +
 485                     Arrays.toString(expectedArray) + " but received: " +
 486                     Arrays.toString(
 487                         HexFormat.dumpAsStream(ByteBuffer.wrap(input), 0, input.length, 8, CUSTOM_8_HEXDUMP_FORMATTER).toArray()));
 488             }
 489         }
 490     }
 491 }