Merge branch 'subtree'
[nikiroo-utils.git] / test / TestCase.java
1 package be.nikiroo.utils.test;
2
3 import java.io.File;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Map.Entry;
9
10 import be.nikiroo.utils.IOUtils;
11
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
27 public AssertException(String reason, Exception source) {
28 super(reason, source);
29 }
30
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
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
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
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
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
121 *
122 * @throws AssertException
123 * every time
124 */
125 public void fail(String reason) throws AssertException {
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 {
141 throw new AssertException("Failed!" + //
142 reason != null ? "\n" + reason : "", e);
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 *
164 * @param errorMessage
165 * the error message to display if they differ
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 {
176 if ((expected == null && actual != null)
177 || (expected != null && !expected.equals(actual))) {
178 if (errorMessage == null) {
179 throw new AssertException(generateAssertMessage(expected,
180 actual));
181 }
182
183 throw new AssertException(errorMessage, new AssertException(
184 generateAssertMessage(expected, actual)));
185 }
186 }
187
188 /**
189 * Check that 2 longs are equals.
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 {
200 assertEquals(Long.valueOf(expected), Long.valueOf(actual));
201 }
202
203 /**
204 * Check that 2 longs are equals.
205 *
206 * @param errorMessage
207 * the error message to display if they differ
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 {
218 assertEquals(errorMessage, Long.valueOf(expected), Long.valueOf(actual));
219 }
220
221 /**
222 * Check that 2 booleans are equals.
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 {
234 assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
235 }
236
237 /**
238 * Check that 2 booleans are equals.
239 *
240 * @param errorMessage
241 * the error message to display if they differ
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 {
252 assertEquals(errorMessage, Boolean.valueOf(expected),
253 Boolean.valueOf(actual));
254 }
255
256 /**
257 * Check that 2 doubles are equals.
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 {
269 assertEquals(Double.valueOf(expected), Double.valueOf(actual));
270 }
271
272 /**
273 * Check that 2 doubles are equals.
274 *
275 * @param errorMessage
276 * the error message to display if they differ
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 {
287 assertEquals(errorMessage, Double.valueOf(expected),
288 Double.valueOf(actual));
289 }
290
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 {
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
318 *
319 * @throws AssertException
320 * in case they differ
321 */
322 public void assertEquals(String errorMessage, List<?> expected,
323 List<?> actual) throws AssertException {
324
325 if (expected.size() != actual.size()) {
326 assertEquals(errorMessage + ": not same number of items",
327 list(expected), list(actual));
328 }
329
330 int size = expected.size();
331 for (int i = 0; i < size; i++) {
332 assertEquals(errorMessage + ": item " + i
333 + " (0-based) is not correct", expected.get(i),
334 actual.get(i));
335 }
336 }
337
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());
409 Collections.sort(expectedFiles);
410 List<String> actualFiles = Arrays.asList(actual.list());
411 Collections.sort(actualFiles);
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;
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 }
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
470 /**
471 * Check that given {@link Object} is not NULL.
472 *
473 * @param errorMessage
474 * the error message to display if it is NULL
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) {
484 String defaultReason = String.format("" //
485 + "Assertion failed!%n" //
486 + "Object should not have been NULL");
487
488 if (errorMessage == null) {
489 throw new AssertException(defaultReason);
490 }
491
492 throw new AssertException(errorMessage, new AssertException(
493 defaultReason));
494 }
495 }
496
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("" //
510 + "Assertion failed!%n" //
511 + "Expected value: [%s]%n" //
512 + "Actual value: [%s]", expected, actual);
513 }
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 }
535 }