• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.io;
18 
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertThrows;
21 
22 import java.io.IOException;
23 
24 import org.apache.commons.io.output.ByteArrayOutputStream;
25 import org.apache.commons.io.test.ThrowOnCloseOutputStream;
26 import org.junit.jupiter.api.Test;
27 
28 
29 /**
30  *
31  */
32 public class HexDumpTest {
33 
34     @Test
testDumpAppendable()35     public void testDumpAppendable() throws IOException {
36         final byte[] testArray = new byte[256];
37 
38         for (int j = 0; j < 256; j++) {
39             testArray[j] = (byte) j;
40         }
41 
42         // verify proper behavior dumping the entire array
43         StringBuilder out = new StringBuilder();
44         HexDump.dump(testArray, out);
45         assertEquals(
46             "00000000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................" + System.lineSeparator() +
47             "00000010 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ................" + System.lineSeparator() +
48             "00000020 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F  !\"#$%&'()*+,-./" + System.lineSeparator() +
49             "00000030 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 0123456789:;<=>?" + System.lineSeparator() +
50             "00000040 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F @ABCDEFGHIJKLMNO" + System.lineSeparator() +
51             "00000050 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F PQRSTUVWXYZ[\\]^_" + System.lineSeparator() +
52             "00000060 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F `abcdefghijklmno" + System.lineSeparator() +
53             "00000070 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F pqrstuvwxyz{|}~." + System.lineSeparator() +
54             "00000080 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F ................" + System.lineSeparator() +
55             "00000090 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F ................" + System.lineSeparator() +
56             "000000A0 A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF ................" + System.lineSeparator() +
57             "000000B0 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF ................" + System.lineSeparator() +
58             "000000C0 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF ................" + System.lineSeparator() +
59             "000000D0 D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF ................" + System.lineSeparator() +
60             "000000E0 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF ................" + System.lineSeparator() +
61             "000000F0 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF ................" + System.lineSeparator(),
62             out.toString());
63 
64         // verify proper behavior with non-zero offset, non-zero index and length shorter than array size
65         out = new StringBuilder();
66         HexDump.dump(testArray, 0x10000000, out, 0x28, 32);
67         assertEquals(
68             "10000028 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 ()*+,-./01234567" + System.lineSeparator() +
69             "10000038 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 89:;<=>?@ABCDEFG" + System.lineSeparator(),
70             out.toString());
71 
72         // verify proper behavior with non-zero index and length shorter than array size
73         out = new StringBuilder();
74         HexDump.dump(testArray, 0, out, 0x40, 24);
75         assertEquals(
76             "00000040 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F @ABCDEFGHIJKLMNO" + System.lineSeparator() +
77             "00000050 50 51 52 53 54 55 56 57                         PQRSTUVW" + System.lineSeparator(),
78             out.toString());
79 
80         // verify proper behavior with negative index
81         assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new StringBuilder(), -1, testArray.length));
82 
83         // verify proper behavior with index that is too large
84         assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new StringBuilder(), testArray.length, testArray.length));
85 
86         // verify proper behavior with length that is negative
87         assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0, new StringBuilder(), 0, -1));
88 
89         // verify proper behavior with length that is too large
90         final Exception exception = assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0, new StringBuilder(), 1,
91             testArray.length));
92         assertEquals("Range [1, 1 + 256) out of bounds for length 256", exception.getMessage());
93 
94         // verify proper behavior with null appendable
95         assertThrows(NullPointerException.class, () -> HexDump.dump(testArray, 0x10000000, null, 0, testArray.length));
96     }
97 
98     @Test
testDumpOutputStream()99     public void testDumpOutputStream() throws IOException {
100         final byte[] testArray = new byte[256];
101 
102         for (int j = 0; j < 256; j++) {
103             testArray[j] = (byte) j;
104         }
105         ByteArrayOutputStream stream = new ByteArrayOutputStream();
106 
107         HexDump.dump(testArray, 0, stream, 0);
108         byte[] outputArray = new byte[16 * (73 + System.lineSeparator().length())];
109 
110         for (int j = 0; j < 16; j++) {
111             int offset = (73 + System.lineSeparator().length()) * j;
112 
113             outputArray[offset++] = (byte) '0';
114             outputArray[offset++] = (byte) '0';
115             outputArray[offset++] = (byte) '0';
116             outputArray[offset++] = (byte) '0';
117             outputArray[offset++] = (byte) '0';
118             outputArray[offset++] = (byte) '0';
119             outputArray[offset++] = (byte) toHex(j);
120             outputArray[offset++] = (byte) '0';
121             outputArray[offset++] = (byte) ' ';
122             for (int k = 0; k < 16; k++) {
123                 outputArray[offset++] = (byte) toHex(j);
124                 outputArray[offset++] = (byte) toHex(k);
125                 outputArray[offset++] = (byte) ' ';
126             }
127             for (int k = 0; k < 16; k++) {
128                 outputArray[offset++] = (byte) toAscii(j * 16 + k);
129             }
130             System.arraycopy(System.lineSeparator().getBytes(), 0, outputArray, offset, System.lineSeparator().getBytes().length);
131         }
132         byte[] actualOutput = stream.toByteArray();
133 
134         assertEquals(outputArray.length, actualOutput.length, "array size mismatch");
135         for (int j = 0; j < outputArray.length; j++) {
136             assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch");
137         }
138 
139         // verify proper behavior with non-zero offset
140         stream = new ByteArrayOutputStream();
141         HexDump.dump(testArray, 0x10000000, stream, 0);
142         outputArray = new byte[16 * (73 + System.lineSeparator().length())];
143         for (int j = 0; j < 16; j++) {
144             int offset = (73 + System.lineSeparator().length()) * j;
145 
146             outputArray[offset++] = (byte) '1';
147             outputArray[offset++] = (byte) '0';
148             outputArray[offset++] = (byte) '0';
149             outputArray[offset++] = (byte) '0';
150             outputArray[offset++] = (byte) '0';
151             outputArray[offset++] = (byte) '0';
152             outputArray[offset++] = (byte) toHex(j);
153             outputArray[offset++] = (byte) '0';
154             outputArray[offset++] = (byte) ' ';
155             for (int k = 0; k < 16; k++) {
156                 outputArray[offset++] = (byte) toHex(j);
157                 outputArray[offset++] = (byte) toHex(k);
158                 outputArray[offset++] = (byte) ' ';
159             }
160             for (int k = 0; k < 16; k++) {
161                 outputArray[offset++] = (byte) toAscii(j * 16 + k);
162             }
163             System.arraycopy(System.lineSeparator().getBytes(), 0, outputArray, offset,
164                     System.lineSeparator().getBytes().length);
165         }
166         actualOutput = stream.toByteArray();
167         assertEquals(outputArray.length, actualOutput.length, "array size mismatch");
168         for (int j = 0; j < outputArray.length; j++) {
169             assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch");
170         }
171 
172         // verify proper behavior with negative offset
173         stream = new ByteArrayOutputStream();
174         HexDump.dump(testArray, 0xFF000000, stream, 0);
175         outputArray = new byte[16 * (73 + System.lineSeparator().length())];
176         for (int j = 0; j < 16; j++) {
177             int offset = (73 + System.lineSeparator().length()) * j;
178 
179             outputArray[offset++] = (byte) 'F';
180             outputArray[offset++] = (byte) 'F';
181             outputArray[offset++] = (byte) '0';
182             outputArray[offset++] = (byte) '0';
183             outputArray[offset++] = (byte) '0';
184             outputArray[offset++] = (byte) '0';
185             outputArray[offset++] = (byte) toHex(j);
186             outputArray[offset++] = (byte) '0';
187             outputArray[offset++] = (byte) ' ';
188             for (int k = 0; k < 16; k++) {
189                 outputArray[offset++] = (byte) toHex(j);
190                 outputArray[offset++] = (byte) toHex(k);
191                 outputArray[offset++] = (byte) ' ';
192             }
193             for (int k = 0; k < 16; k++) {
194                 outputArray[offset++] = (byte) toAscii(j * 16 + k);
195             }
196             System.arraycopy(System.lineSeparator().getBytes(), 0, outputArray, offset,
197                     System.lineSeparator().getBytes().length);
198         }
199         actualOutput = stream.toByteArray();
200         assertEquals(outputArray.length, actualOutput.length, "array size mismatch");
201         for (int j = 0; j < outputArray.length; j++) {
202             assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch");
203         }
204 
205         // verify proper behavior with non-zero index
206         stream = new ByteArrayOutputStream();
207         HexDump.dump(testArray, 0x10000000, stream, 0x81);
208         outputArray = new byte[8 * (73 + System.lineSeparator().length()) - 1];
209         for (int j = 0; j < 8; j++) {
210             int offset = (73 + System.lineSeparator().length()) * j;
211 
212             outputArray[offset++] = (byte) '1';
213             outputArray[offset++] = (byte) '0';
214             outputArray[offset++] = (byte) '0';
215             outputArray[offset++] = (byte) '0';
216             outputArray[offset++] = (byte) '0';
217             outputArray[offset++] = (byte) '0';
218             outputArray[offset++] = (byte) toHex(j + 8);
219             outputArray[offset++] = (byte) '1';
220             outputArray[offset++] = (byte) ' ';
221             for (int k = 0; k < 16; k++) {
222                 final int index = 0x81 + j * 16 + k;
223 
224                 if (index < 0x100) {
225                     outputArray[offset++] = (byte) toHex(index / 16);
226                     outputArray[offset++] = (byte) toHex(index);
227                 } else {
228                     outputArray[offset++] = (byte) ' ';
229                     outputArray[offset++] = (byte) ' ';
230                 }
231                 outputArray[offset++] = (byte) ' ';
232             }
233             for (int k = 0; k < 16; k++) {
234                 final int index = 0x81 + j * 16 + k;
235 
236                 if (index < 0x100) {
237                     outputArray[offset++] = (byte) toAscii(index);
238                 }
239             }
240             System.arraycopy(System.lineSeparator().getBytes(), 0, outputArray, offset,
241                     System.lineSeparator().getBytes().length);
242         }
243         actualOutput = stream.toByteArray();
244         assertEquals(outputArray.length, actualOutput.length, "array size mismatch");
245         for (int j = 0; j < outputArray.length; j++) {
246             assertEquals(outputArray[j], actualOutput[j], "array[ " + j + "] mismatch");
247         }
248 
249         // verify proper behavior with negative index
250         assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new ByteArrayOutputStream(), -1));
251 
252         // verify proper behavior with index that is too large
253         assertThrows(ArrayIndexOutOfBoundsException.class, () -> HexDump.dump(testArray, 0x10000000, new ByteArrayOutputStream(), testArray.length));
254 
255         // verify proper behavior with null stream
256         assertThrows(NullPointerException.class, () -> HexDump.dump(testArray, 0x10000000, null, 0));
257 
258         // verify output stream is not closed by the dump method
259         HexDump.dump(testArray, 0, new ThrowOnCloseOutputStream(new ByteArrayOutputStream()), 0);
260     }
261 
toAscii(final int c)262     private char toAscii(final int c) {
263         char rval = '.';
264 
265         if (c >= 32 && c <= 126) {
266             rval = (char) c;
267         }
268         return rval;
269     }
270 
toHex(final int n)271     private char toHex(final int n) {
272         final char[] hexChars =
273                 {
274                     '0', '1', '2', '3', '4', '5', '6', '7',
275                     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
276                 };
277 
278         return hexChars[n % 16];
279     }
280 }
281