1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.util;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.charset.StandardCharsets;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.Map.Entry;
28
29 import org.junit.Before;
30 import org.junit.BeforeClass;
31 import org.junit.Test;
32
33 import static org.eclipse.aether.internal.test.util.TestFileUtils.*;
34 import static org.junit.Assert.*;
35
36 public class ChecksumUtilTest {
37 private static final String EMPTY = "EMPTY";
38 private static final String PATTERN = "PATTERN";
39 private static final String TEXT = "TEXT";
40
41 private Map<String, File> files = new HashMap<>(3);
42
43 private Map<String, byte[]> bytes = new HashMap<>(3);
44
45 private static Map<String, String> emptyChecksums = new HashMap<>();
46
47 private static Map<String, String> patternChecksums = new HashMap<>();
48
49 private static Map<String, String> textChecksums = new HashMap<>();
50
51 private Map<String, Map<String, String>> sums = new HashMap<>();
52
53 @BeforeClass
54 public static void beforeClass() {
55 emptyChecksums.put("MD5", "d41d8cd98f00b204e9800998ecf8427e");
56 emptyChecksums.put("SHA-1", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
57 emptyChecksums.put("SHA-256", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
58 emptyChecksums.put(
59 "SHA-512",
60 "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
61 patternChecksums.put("MD5", "14f01d6c7de7d4cf0a4887baa3528b5a");
62 patternChecksums.put("SHA-1", "feeeda19f626f9b0ef6cbf5948c1ec9531694295");
63 patternChecksums.put("SHA-256", "81d480a714840ab206dc8de62ca6119036f65499ad9e2e227c2465551bed684d");
64 patternChecksums.put(
65 "SHA-512",
66 "931aa34118d9a85b9514e0224046d736a5bd7e2b2f366505fe1ad07ed85e1a4ac0cbc18e9b9a7fe36ce835be2a18cb571202a4975d182553faff336970eb0b7e");
67 textChecksums.put("MD5", "12582d1a662cefe3385f2113998e43ed");
68 textChecksums.put("SHA-1", "a8ae272db549850eef2ff54376f8cac2770745ee");
69 textChecksums.put("SHA-256", "35829adced2979761ba521dc2bb7d166e92ebed7342319d041398e509d481a46");
70 textChecksums.put(
71 "SHA-512",
72 "2d6d19570b26080fa88101af2256ce3dae63512b06864cd36a05371c81d6dbd0ec226dd75f22e8d46a9582e1fc40ee6e7a02d43c852f3c92255982b835db6e7c");
73 }
74
75 @Before
76 public void before() throws IOException {
77 sums.clear();
78
79 byte[] emptyBytes = new byte[0];
80 bytes.put(EMPTY, emptyBytes);
81 files.put(EMPTY, createTempFile(emptyBytes, 0));
82 sums.put(EMPTY, emptyChecksums);
83
84 byte[] patternBytes =
85 writeBytes(new byte[] {0, 1, 2, 4, 8, 16, 32, 64, 127, -1, -2, -4, -8, -16, -32, -64, -127}, 1000);
86 bytes.put(PATTERN, patternBytes);
87 files.put(PATTERN, createTempFile(patternBytes, 1));
88 sums.put(PATTERN, patternChecksums);
89
90 byte[] textBytes =
91 writeBytes("the quick brown fox jumps over the lazy dog\n".getBytes(StandardCharsets.UTF_8), 500);
92 bytes.put(TEXT, textBytes);
93 files.put(TEXT, createTempFile(textBytes, 1));
94 sums.put(TEXT, textChecksums);
95 }
96
97 @Test
98 public void testEquality() throws Throwable {
99 Map<String, Object> checksums = null;
100
101 for (Map.Entry<String, File> fileEntry : files.entrySet()) {
102
103 checksums = ChecksumUtils.calc(fileEntry.getValue(), Arrays.asList("SHA-512", "SHA-256", "SHA-1", "MD5"));
104
105 for (Entry<String, Object> entry : checksums.entrySet()) {
106 if (entry.getValue() instanceof Throwable) {
107 throw (Throwable) entry.getValue();
108 }
109 String actual = entry.getValue().toString();
110 String expected = sums.get(fileEntry.getKey()).get(entry.getKey());
111 assertEquals(
112 String.format(
113 "checksums do not match for '%s', algorithm '%s'",
114 fileEntry.getValue().getName(), entry.getKey()),
115 expected,
116 actual);
117 }
118 assertTrue("Could not delete file", fileEntry.getValue().delete());
119 }
120 }
121
122 @Test
123 public void testFileHandleLeakage() throws IOException {
124 for (File file : files.values()) {
125 for (int i = 0; i < 150; i++) {
126 ChecksumUtils.calc(file, Arrays.asList("SHA-512", "SHA-256", "SHA-1", "MD5"));
127 }
128 assertTrue("Could not delete file", file.delete());
129 }
130 }
131
132 @Test
133 public void testRead() throws IOException {
134 for (Map<String, String> checksums : sums.values()) {
135 String sha512 = checksums.get("SHA-512");
136 String sha256 = checksums.get("SHA-256");
137 String sha1 = checksums.get("SHA-1");
138 String md5 = checksums.get("MD5");
139
140 File sha512File = createTempFile(sha512);
141 File sha256File = createTempFile(sha256);
142 File sha1File = createTempFile(sha1);
143 File md5File = createTempFile(md5);
144
145 assertEquals(sha512, ChecksumUtils.read(sha512File));
146 assertEquals(sha256, ChecksumUtils.read(sha256File));
147 assertEquals(sha1, ChecksumUtils.read(sha1File));
148 assertEquals(md5, ChecksumUtils.read(md5File));
149
150 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.sha512)", sha512File.delete());
151 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.sha256)", sha256File.delete());
152 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.sha1)", sha1File.delete());
153 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.md5)", md5File.delete());
154 }
155 }
156
157 @Test
158 public void testReadSpaces() throws IOException {
159 for (Map<String, String> checksums : sums.values()) {
160 String sha512 = checksums.get("SHA-512");
161 String sha256 = checksums.get("SHA-256");
162 String sha1 = checksums.get("SHA-1");
163 String md5 = checksums.get("MD5");
164
165 File sha512File = createTempFile("sha512-checksum = " + sha512);
166 File sha256File = createTempFile("sha256-checksum = " + sha256);
167 File sha1File = createTempFile("sha1-checksum = " + sha1);
168 File md5File = createTempFile(md5 + " test");
169
170 assertEquals(sha512, ChecksumUtils.read(sha512File));
171 assertEquals(sha256, ChecksumUtils.read(sha256File));
172 assertEquals(sha1, ChecksumUtils.read(sha1File));
173 assertEquals(md5, ChecksumUtils.read(md5File));
174
175 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.sha512)", sha512File.delete());
176 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.sha256)", sha256File.delete());
177 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.sha1)", sha1File.delete());
178 assertTrue("ChecksumUtils leaks file handles (cannot delete checksums.md5)", md5File.delete());
179 }
180 }
181
182 @Test
183 public void testReadEmptyFile() throws IOException {
184 File file = createTempFile("");
185
186 assertEquals("", ChecksumUtils.read(file));
187
188 assertTrue("ChecksumUtils leaks file handles (cannot delete checksum.empty)", file.delete());
189 }
190
191 @Test
192 public void testToHexString() {
193 assertNull(ChecksumUtils.toHexString(null));
194 assertEquals("", ChecksumUtils.toHexString(new byte[] {}));
195 assertEquals("00", ChecksumUtils.toHexString(new byte[] {0}));
196 assertEquals("ff", ChecksumUtils.toHexString(new byte[] {-1}));
197 assertEquals("00017f", ChecksumUtils.toHexString(new byte[] {0, 1, 127}));
198 }
199
200 @Test
201 public void testFromHexString() {
202 assertNull(ChecksumUtils.toHexString(null));
203 assertArrayEquals(new byte[] {}, ChecksumUtils.fromHexString(""));
204 assertArrayEquals(new byte[] {0}, ChecksumUtils.fromHexString("00"));
205 assertArrayEquals(new byte[] {-1}, ChecksumUtils.fromHexString("ff"));
206 assertArrayEquals(new byte[] {0, 1, 127}, ChecksumUtils.fromHexString("00017f"));
207 }
208
209 @Test
210 public void testCalcWithByteArray() throws Throwable {
211 Map<String, Object> checksums = null;
212
213 for (Map.Entry<String, byte[]> bytesEntry : bytes.entrySet()) {
214 checksums = ChecksumUtils.calc(bytesEntry.getValue(), Arrays.asList("SHA-512", "SHA-256", "SHA-1", "MD5"));
215
216 for (Entry<String, Object> entry : checksums.entrySet()) {
217 if (entry.getValue() instanceof Throwable) {
218 throw (Throwable) entry.getValue();
219 }
220 String actual = entry.getValue().toString();
221 String expected = sums.get(bytesEntry.getKey()).get(entry.getKey());
222 assertEquals(
223 String.format(
224 "checksums do not match for '%s', algorithm '%s'", bytesEntry.getKey(), entry.getKey()),
225 expected,
226 actual);
227 }
228 }
229 }
230
231 private byte[] writeBytes(byte[] pattern, int repeat) {
232 byte[] result = new byte[pattern.length * repeat];
233 for (int i = 0; i < repeat; i++) {
234 System.arraycopy(pattern, 0, result, i * pattern.length, pattern.length);
235 }
236 return result;
237 }
238 }