Commit | Line | Data |
---|---|---|
80383c14 NR |
1 | package be.nikiroo.utils.test; |
2 | ||
d62784c7 NR |
3 | import java.io.File; |
4 | import java.util.Arrays; | |
50f31077 | 5 | import java.util.Collections; |
620f7329 | 6 | import java.util.List; |
d62784c7 NR |
7 | import java.util.Map; |
8 | import java.util.Map.Entry; | |
9 | ||
10 | import be.nikiroo.utils.IOUtils; | |
620f7329 | 11 | |
80383c14 NR |
12 | /** |
13 | * A {@link TestCase} that can be run with {@link TestLauncher}. | |
14 | * | |
15 | * @author niki | |
16 | */ | |
17 | abstract public class TestCase { | |
18 | /** | |
19 | * The type of {@link Exception} used to signal a failed assertion or a | |
20 | * force-fail. | |
21 | * | |
22 | * @author niki | |
23 | */ | |
24 | class AssertException extends Exception { | |
25 | private static final long serialVersionUID = 1L; | |
26 | ||
c37cc690 NR |
27 | public AssertException(String reason, Exception source) { |
28 | super(reason, source); | |
29 | } | |
30 | ||
80383c14 NR |
31 | public AssertException(String reason) { |
32 | super(reason); | |
33 | } | |
34 | } | |
35 | ||
36 | private String name; | |
37 | ||
38 | /** | |
39 | * Create a new {@link TestCase}. | |
40 | * | |
41 | * @param name | |
42 | * the test name | |
43 | */ | |
44 | public TestCase(String name) { | |
45 | this.name = name; | |
46 | } | |
47 | ||
72648e75 NR |
48 | /** |
49 | * This constructor can be used if you require a no-param constructor. In | |
50 | * this case, you are allowed to set the name manually via | |
51 | * {@link TestCase#setName}. | |
52 | */ | |
53 | protected TestCase() { | |
54 | this("no name"); | |
55 | } | |
56 | ||
80383c14 NR |
57 | /** |
58 | * Setup the test (called before the test is run). | |
59 | * | |
60 | * @throws Exception | |
61 | * in case of error | |
62 | */ | |
63 | public void setUp() throws Exception { | |
64 | } | |
65 | ||
66 | /** | |
67 | * Tear-down the test (called when the test has been ran). | |
68 | * | |
69 | * @throws Exception | |
70 | * in case of error | |
71 | */ | |
72 | public void tearDown() throws Exception { | |
73 | } | |
74 | ||
75 | /** | |
76 | * The test name. | |
77 | * | |
78 | * @return the name | |
79 | */ | |
80 | public String getName() { | |
81 | return name; | |
82 | } | |
83 | ||
72648e75 NR |
84 | /** |
85 | * The test name. | |
86 | * | |
87 | * @param name | |
88 | * the new name (internal use only) | |
89 | * | |
90 | * @return this (so we can chain and so we can initialize it in a member | |
91 | * variable if this is an anonymous inner class) | |
92 | */ | |
93 | protected TestCase setName(String name) { | |
94 | this.name = name; | |
95 | return this; | |
96 | } | |
97 | ||
80383c14 NR |
98 | /** |
99 | * Actually do the test. | |
100 | * | |
101 | * @throws Exception | |
102 | * in case of error | |
103 | */ | |
104 | abstract public void test() throws Exception; | |
105 | ||
106 | /** | |
107 | * Force a failure. | |
108 | * | |
109 | * @throws AssertException | |
110 | * every time | |
111 | */ | |
112 | public void fail() throws AssertException { | |
113 | fail(null); | |
114 | } | |
115 | ||
116 | /** | |
117 | * Force a failure. | |
118 | * | |
119 | * @param reason | |
120 | * the failure reason | |
edeff2ab | 121 | * |
80383c14 NR |
122 | * @throws AssertException |
123 | * every time | |
124 | */ | |
125 | public void fail(String reason) throws AssertException { | |
edeff2ab NR |
126 | fail(reason, null); |
127 | } | |
128 | ||
129 | /** | |
130 | * Force a failure. | |
131 | * | |
132 | * @param reason | |
133 | * the failure reason | |
134 | * @param e | |
135 | * the exception that caused the failure (can be NULL) | |
136 | * | |
137 | * @throws AssertException | |
138 | * every time | |
139 | */ | |
140 | public void fail(String reason, Exception e) throws AssertException { | |
80383c14 | 141 | throw new AssertException("Failed!" + // |
edeff2ab | 142 | reason != null ? "\n" + reason : "", e); |
80383c14 NR |
143 | } |
144 | ||
145 | /** | |
146 | * Check that 2 {@link Object}s are equals. | |
147 | * | |
148 | * @param expected | |
149 | * the expected value | |
150 | * @param actual | |
151 | * the actual value | |
152 | * | |
153 | * @throws AssertException | |
154 | * in case they differ | |
155 | */ | |
156 | public void assertEquals(Object expected, Object actual) | |
157 | throws AssertException { | |
158 | assertEquals(null, expected, actual); | |
159 | } | |
160 | ||
161 | /** | |
162 | * Check that 2 {@link Object}s are equals. | |
163 | * | |
db31c358 NR |
164 | * @param errorMessage |
165 | * the error message to display if they differ | |
80383c14 NR |
166 | * @param expected |
167 | * the expected value | |
168 | * @param actual | |
169 | * the actual value | |
170 | * | |
171 | * @throws AssertException | |
172 | * in case they differ | |
173 | */ | |
174 | public void assertEquals(String errorMessage, Object expected, Object actual) | |
175 | throws AssertException { | |
80383c14 NR |
176 | if ((expected == null && actual != null) |
177 | || (expected != null && !expected.equals(actual))) { | |
c37cc690 NR |
178 | if (errorMessage == null) { |
179 | throw new AssertException(generateAssertMessage(expected, | |
180 | actual)); | |
c37cc690 | 181 | } |
cd0c27d2 NR |
182 | |
183 | throw new AssertException(errorMessage, new AssertException( | |
184 | generateAssertMessage(expected, actual))); | |
80383c14 NR |
185 | } |
186 | } | |
187 | ||
188 | /** | |
620f7329 | 189 | * Check that 2 longs are equals. |
80383c14 NR |
190 | * |
191 | * @param expected | |
192 | * the expected value | |
193 | * @param actual | |
194 | * the actual value | |
195 | * | |
196 | * @throws AssertException | |
197 | * in case they differ | |
198 | */ | |
199 | public void assertEquals(long expected, long actual) throws AssertException { | |
0988831f | 200 | assertEquals(Long.valueOf(expected), Long.valueOf(actual)); |
80383c14 NR |
201 | } |
202 | ||
203 | /** | |
620f7329 | 204 | * Check that 2 longs are equals. |
80383c14 | 205 | * |
db31c358 NR |
206 | * @param errorMessage |
207 | * the error message to display if they differ | |
80383c14 NR |
208 | * @param expected |
209 | * the expected value | |
210 | * @param actual | |
211 | * the actual value | |
212 | * | |
213 | * @throws AssertException | |
214 | * in case they differ | |
215 | */ | |
216 | public void assertEquals(String errorMessage, long expected, long actual) | |
217 | throws AssertException { | |
0988831f | 218 | assertEquals(errorMessage, Long.valueOf(expected), Long.valueOf(actual)); |
80383c14 NR |
219 | } |
220 | ||
221 | /** | |
620f7329 | 222 | * Check that 2 booleans are equals. |
80383c14 NR |
223 | * |
224 | * @param expected | |
225 | * the expected value | |
226 | * @param actual | |
227 | * the actual value | |
228 | * | |
229 | * @throws AssertException | |
230 | * in case they differ | |
231 | */ | |
232 | public void assertEquals(boolean expected, boolean actual) | |
233 | throws AssertException { | |
0988831f | 234 | assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual)); |
80383c14 NR |
235 | } |
236 | ||
237 | /** | |
620f7329 | 238 | * Check that 2 booleans are equals. |
80383c14 | 239 | * |
db31c358 NR |
240 | * @param errorMessage |
241 | * the error message to display if they differ | |
80383c14 NR |
242 | * @param expected |
243 | * the expected value | |
244 | * @param actual | |
245 | * the actual value | |
246 | * | |
247 | * @throws AssertException | |
248 | * in case they differ | |
249 | */ | |
250 | public void assertEquals(String errorMessage, boolean expected, | |
251 | boolean actual) throws AssertException { | |
0988831f NR |
252 | assertEquals(errorMessage, Boolean.valueOf(expected), |
253 | Boolean.valueOf(actual)); | |
80383c14 NR |
254 | } |
255 | ||
256 | /** | |
620f7329 | 257 | * Check that 2 doubles are equals. |
80383c14 NR |
258 | * |
259 | * @param expected | |
260 | * the expected value | |
261 | * @param actual | |
262 | * the actual value | |
263 | * | |
264 | * @throws AssertException | |
265 | * in case they differ | |
266 | */ | |
267 | public void assertEquals(double expected, double actual) | |
268 | throws AssertException { | |
0988831f | 269 | assertEquals(Double.valueOf(expected), Double.valueOf(actual)); |
80383c14 NR |
270 | } |
271 | ||
272 | /** | |
620f7329 | 273 | * Check that 2 doubles are equals. |
80383c14 | 274 | * |
db31c358 NR |
275 | * @param errorMessage |
276 | * the error message to display if they differ | |
80383c14 NR |
277 | * @param expected |
278 | * the expected value | |
279 | * @param actual | |
280 | * the actual value | |
281 | * | |
282 | * @throws AssertException | |
283 | * in case they differ | |
284 | */ | |
285 | public void assertEquals(String errorMessage, double expected, double actual) | |
286 | throws AssertException { | |
0988831f NR |
287 | assertEquals(errorMessage, Double.valueOf(expected), |
288 | Double.valueOf(actual)); | |
80383c14 | 289 | } |
86057589 | 290 | |
620f7329 NR |
291 | /** |
292 | * Check that 2 {@link List}s are equals. | |
293 | * | |
294 | * @param errorMessage | |
295 | * the error message to display if they differ | |
296 | * @param expected | |
297 | * the expected value | |
298 | * @param actual | |
299 | * the actual value | |
300 | * | |
301 | * @throws AssertException | |
302 | * in case they differ | |
303 | */ | |
304 | public void assertEquals(List<?> expected, List<?> actual) | |
305 | throws AssertException { | |
534332ff NR |
306 | assertEquals("Assertion failed", expected, actual); |
307 | } | |
308 | ||
309 | /** | |
310 | * Check that 2 {@link List}s are equals. | |
311 | * | |
312 | * @param errorMessage | |
313 | * the error message to display if they differ | |
314 | * @param expected | |
315 | * the expected value | |
316 | * @param actual | |
317 | * the actual value | |
534332ff NR |
318 | * |
319 | * @throws AssertException | |
320 | * in case they differ | |
321 | */ | |
322 | public void assertEquals(String errorMessage, List<?> expected, | |
323 | List<?> actual) throws AssertException { | |
620f7329 | 324 | |
534332ff NR |
325 | if (expected.size() != actual.size()) { |
326 | assertEquals(errorMessage + ": not same number of items", | |
327 | list(expected), list(actual)); | |
328 | } | |
620f7329 NR |
329 | |
330 | int size = expected.size(); | |
331 | for (int i = 0; i < size; i++) { | |
534332ff NR |
332 | assertEquals(errorMessage + ": item " + i |
333 | + " (0-based) is not correct", expected.get(i), | |
334 | actual.get(i)); | |
620f7329 NR |
335 | } |
336 | } | |
337 | ||
d62784c7 NR |
338 | /** |
339 | * Check that 2 {@link File}s are equals, by doing a line-by-line | |
340 | * comparison. | |
341 | * | |
342 | * @param expected | |
343 | * the expected value | |
344 | * @param actual | |
345 | * the actual value | |
346 | * @param errorMessage | |
347 | * the error message to display if they differ | |
348 | * | |
349 | * @throws AssertException | |
350 | * in case they differ | |
351 | */ | |
352 | public void assertEquals(File expected, File actual) throws AssertException { | |
353 | assertEquals(generateAssertMessage(expected, actual), expected, actual); | |
354 | } | |
355 | ||
356 | /** | |
357 | * Check that 2 {@link File}s are equals, by doing a line-by-line | |
358 | * comparison. | |
359 | * | |
360 | * @param errorMessage | |
361 | * the error message to display if they differ | |
362 | * @param expected | |
363 | * the expected value | |
364 | * @param actual | |
365 | * the actual value | |
366 | * | |
367 | * @throws AssertException | |
368 | * in case they differ | |
369 | */ | |
370 | public void assertEquals(String errorMessage, File expected, File actual) | |
371 | throws AssertException { | |
372 | assertEquals(errorMessage, expected, actual, null); | |
373 | } | |
374 | ||
375 | /** | |
376 | * Check that 2 {@link File}s are equals, by doing a line-by-line | |
377 | * comparison. | |
378 | * | |
379 | * @param errorMessage | |
380 | * the error message to display if they differ | |
381 | * @param expected | |
382 | * the expected value | |
383 | * @param actual | |
384 | * the actual value | |
385 | * @param skipCompare | |
386 | * skip the lines starting with some values for the given files | |
387 | * (relative path from base directory in recursive mode) | |
388 | * | |
389 | * @throws AssertException | |
390 | * in case they differ | |
391 | */ | |
392 | public void assertEquals(String errorMessage, File expected, File actual, | |
393 | Map<String, List<String>> skipCompare) throws AssertException { | |
394 | assertEquals(errorMessage, expected, actual, skipCompare, null); | |
395 | } | |
396 | ||
397 | private void assertEquals(String errorMessage, File expected, File actual, | |
398 | Map<String, List<String>> skipCompare, String removeFromName) | |
399 | throws AssertException { | |
400 | ||
401 | if (expected.isDirectory() || actual.isDirectory()) { | |
402 | assertEquals(errorMessage + ": type mismatch: expected a " | |
403 | + (expected.isDirectory() ? "directory" : "file") | |
404 | + ", received a " | |
405 | + (actual.isDirectory() ? "directory" : "file"), | |
406 | expected.isDirectory(), actual.isDirectory()); | |
407 | ||
408 | List<String> expectedFiles = Arrays.asList(expected.list()); | |
50f31077 | 409 | Collections.sort(expectedFiles); |
d62784c7 | 410 | List<String> actualFiles = Arrays.asList(actual.list()); |
50f31077 | 411 | Collections.sort(actualFiles); |
d62784c7 NR |
412 | |
413 | assertEquals(errorMessage, expectedFiles, actualFiles); | |
414 | for (int i = 0; i < actualFiles.size(); i++) { | |
415 | File expectedFile = new File(expected, expectedFiles.get(i)); | |
416 | File actualFile = new File(actual, actualFiles.get(i)); | |
417 | ||
418 | assertEquals(errorMessage, expectedFile, actualFile, | |
419 | skipCompare, expected.getAbsolutePath()); | |
420 | } | |
421 | } else { | |
422 | try { | |
423 | List<String> expectedLines = Arrays.asList(IOUtils | |
424 | .readSmallFile(expected).split("\n")); | |
425 | List<String> resultLines = Arrays.asList(IOUtils.readSmallFile( | |
426 | actual).split("\n")); | |
427 | ||
428 | String name = expected.getAbsolutePath(); | |
429 | if (removeFromName != null && name.startsWith(removeFromName)) { | |
430 | name = expected.getName() | |
431 | + name.substring(removeFromName.length()); | |
432 | } | |
433 | ||
434 | assertEquals(errorMessage + ": " + name | |
435 | + ": the number of lines is not the same", | |
436 | expectedLines.size(), resultLines.size()); | |
437 | ||
438 | for (int j = 0; j < expectedLines.size(); j++) { | |
439 | String expectedLine = expectedLines.get(j); | |
440 | String resultLine = resultLines.get(j); | |
441 | ||
442 | boolean skip = false; | |
3232fdd1 NR |
443 | if (skipCompare != null) { |
444 | for (Entry<String, List<String>> skipThose : skipCompare | |
445 | .entrySet()) { | |
446 | for (String skipStart : skipThose.getValue()) { | |
447 | if (name.endsWith(skipThose.getKey()) | |
448 | && expectedLine.startsWith(skipStart) | |
449 | && resultLine.startsWith(skipStart)) { | |
450 | skip = true; | |
451 | } | |
d62784c7 NR |
452 | } |
453 | } | |
454 | } | |
455 | ||
456 | if (skip) { | |
457 | continue; | |
458 | } | |
459 | ||
460 | assertEquals(errorMessage + ": line " + (j + 1) | |
461 | + " is not the same in file " + name, expectedLine, | |
462 | resultLine); | |
463 | } | |
464 | } catch (Exception e) { | |
465 | throw new AssertException(errorMessage, e); | |
466 | } | |
467 | } | |
468 | } | |
469 | ||
16d59378 NR |
470 | /** |
471 | * Check that given {@link Object} is not NULL. | |
472 | * | |
db31c358 NR |
473 | * @param errorMessage |
474 | * the error message to display if it is NULL | |
16d59378 NR |
475 | * @param actual |
476 | * the actual value | |
477 | * | |
478 | * @throws AssertException | |
479 | * in case they differ | |
480 | */ | |
481 | public void assertNotNull(String errorMessage, Object actual) | |
482 | throws AssertException { | |
483 | if (actual == null) { | |
c37cc690 | 484 | String defaultReason = String.format("" // |
0988831f NR |
485 | + "Assertion failed!%n" // |
486 | + "Object should not have been NULL"); | |
c37cc690 | 487 | |
16d59378 | 488 | if (errorMessage == null) { |
c37cc690 | 489 | throw new AssertException(defaultReason); |
16d59378 | 490 | } |
cd0c27d2 NR |
491 | |
492 | throw new AssertException(errorMessage, new AssertException( | |
493 | defaultReason)); | |
16d59378 NR |
494 | } |
495 | } | |
496 | ||
86057589 NR |
497 | /** |
498 | * Generate the default assert message for 2 different values that were | |
499 | * supposed to be equals. | |
500 | * | |
501 | * @param expected | |
502 | * the expected value | |
503 | * @param actual | |
504 | * the actual value | |
505 | * | |
506 | * @return the message | |
507 | */ | |
508 | public static String generateAssertMessage(Object expected, Object actual) { | |
509 | return String.format("" // | |
0988831f NR |
510 | + "Assertion failed!%n" // |
511 | + "Expected value: [%s]%n" // | |
3f277541 | 512 | + "Actual value: [%s]", expected, actual); |
86057589 | 513 | } |
534332ff NR |
514 | |
515 | private static String list(List<?> items) { | |
516 | StringBuilder builder = new StringBuilder(); | |
517 | for (Object item : items) { | |
518 | if (builder.length() == 0) { | |
519 | builder.append(items.size() + " item(s): "); | |
520 | } else { | |
521 | builder.append(", "); | |
522 | } | |
523 | ||
524 | builder.append("" + item); | |
525 | ||
526 | if (builder.length() > 60) { | |
527 | builder.setLength(57); | |
528 | builder.append("..."); | |
529 | break; | |
530 | } | |
531 | } | |
532 | ||
533 | return builder.toString(); | |
534 | } | |
80383c14 | 535 | } |