Improve conversion tests
[fanfix.git] / src / be / nikiroo / fanfix / test / ConversionTest.java
1 package be.nikiroo.fanfix.test;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FilenameFilter;
6 import java.io.IOException;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Map.Entry;
13 import java.util.zip.ZipEntry;
14 import java.util.zip.ZipInputStream;
15
16 import be.nikiroo.fanfix.Instance;
17 import be.nikiroo.fanfix.Main;
18 import be.nikiroo.fanfix.output.BasicOutput;
19 import be.nikiroo.utils.IOUtils;
20 import be.nikiroo.utils.TempFiles;
21 import be.nikiroo.utils.TraceHandler;
22 import be.nikiroo.utils.test.TestCase;
23 import be.nikiroo.utils.test.TestLauncher;
24
25 class ConversionTest extends TestLauncher {
26 private TempFiles tempFiles;
27 private File testFile;
28 private File expectedDir;
29 private File resultDir;
30 private List<BasicOutput.OutputType> realTypes;
31 private Map<String, List<String>> skipCompare;
32
33 public ConversionTest(String[] args) {
34 super("Conversion", args);
35
36 // Special mode SYSOUT is not a file type (System.out)
37 realTypes = new ArrayList<BasicOutput.OutputType>();
38 for (BasicOutput.OutputType type : BasicOutput.OutputType.values()) {
39 if (!BasicOutput.OutputType.SYSOUT.equals(type)) {
40 realTypes.add(type);
41 }
42 }
43
44 addTest(new TestCase("Read the test file") {
45 @Override
46 public void test() throws Exception {
47 assertEquals("The test file \"" + testFile
48 + "\" cannot be found", true, testFile.exists());
49 }
50 });
51
52 addTest(new TestCase("Assure directories exist") {
53 @Override
54 public void test() throws Exception {
55 expectedDir.mkdirs();
56 resultDir.mkdirs();
57 assertEquals("The Expected directory \"" + expectedDir
58 + "\" cannot be created", true, expectedDir.exists());
59 assertEquals("The Result directory \"" + resultDir
60 + "\" cannot be created", true, resultDir.exists());
61 }
62 });
63
64 for (BasicOutput.OutputType type : realTypes) {
65 addTest(getTestFor(type));
66 }
67 }
68
69 @Override
70 protected void start() throws Exception {
71 testFile = new File("test/test.story");
72 expectedDir = new File("test/expected/");
73 resultDir = new File("test/result/");
74
75 tempFiles = new TempFiles("Fanfix-ConversionTest");
76
77 skipCompare = new HashMap<String, List<String>>();
78 skipCompare.put("epb.ncx",
79 Arrays.asList(" <meta name=\"dtb:uid\" content="));
80 skipCompare.put("epb.opf", Arrays.asList(" <dc:subject>",
81 " <dc:identifier id=\"BookId\" opf:scheme=\"URI\">"));
82 skipCompare.put(".info",
83 Arrays.asList("CREATION_DATE=", "SUBJECT=", "URL=", "UUID="));
84 skipCompare.put("URL", Arrays.asList("file:/"));
85 }
86
87 @Override
88 protected void stop() throws Exception {
89 tempFiles.close();
90 }
91
92 private TestCase getTestFor(final BasicOutput.OutputType type) {
93 return new TestCase(type + " output mode") {
94 @Override
95 public void test() throws Exception {
96 File target = generate(this, testFile, resultDir, type);
97 target = new File(target.getAbsolutePath()
98 + type.getDefaultExtension(false));
99
100 // Check conversion:
101 compareFiles(this, expectedDir, resultDir, type, null);
102
103 // LATEX not supported as input
104 if (BasicOutput.OutputType.LATEX.equals(type)) {
105 return;
106 }
107
108 // Cross-checks:
109 for (BasicOutput.OutputType crossType : realTypes) {
110 File crossDir = tempFiles.createTempDir("cross-result");
111 generate(this, target, crossDir, crossType);
112 compareFiles(this, resultDir, crossDir, crossType,
113 crossType);
114 }
115 }
116 };
117 }
118
119 private File generate(TestCase testCase, File testFile, File resultDir,
120 BasicOutput.OutputType type) throws Exception {
121 final List<String> errors = new ArrayList<String>();
122
123 TraceHandler previousTraceHandler = Instance.getTraceHandler();
124 Instance.setTraceHandler(new TraceHandler(true, true, 0) {
125 @Override
126 public void error(String message) {
127 errors.add(message);
128 }
129
130 @Override
131 public void error(Exception e) {
132 error(" ");
133 for (Throwable t = e; t != null; t = t.getCause()) {
134 error(((t == e) ? "(" : "..caused by: (")
135 + t.getClass().getSimpleName() + ") "
136 + t.getMessage());
137 for (StackTraceElement s : t.getStackTrace()) {
138 error("\t" + s.toString());
139 }
140 }
141 }
142 });
143
144 try {
145 File target = new File(resultDir, type.toString());
146 int code = Main.convert(testFile.getAbsolutePath(),
147 type.toString(), target.getAbsolutePath(), false, null);
148
149 String error = "";
150 for (String err : errors) {
151 if (!error.isEmpty())
152 error += "\n";
153 error += err;
154 }
155 testCase.assertEquals("The conversion returned an error message: "
156 + error, 0, errors.size());
157 if (code != 0) {
158 testCase.fail("The conversion failed with return code: " + code);
159 }
160
161 return target;
162 } finally {
163 Instance.setTraceHandler(previousTraceHandler);
164 }
165 }
166
167 private void compareFiles(TestCase testCase, File expectedDir,
168 File resultDir, final BasicOutput.OutputType typeToCompare,
169 final BasicOutput.OutputType sourceType) throws Exception {
170
171 FilenameFilter filter = null;
172 if (typeToCompare != null) {
173 filter = new FilenameFilter() {
174 @Override
175 public boolean accept(File dir, String name) {
176 return name.startsWith(typeToCompare.toString());
177 }
178 };
179 }
180
181 List<String> resultFiles = Arrays.asList(resultDir.list(filter));
182 resultFiles.sort(null);
183 List<String> expectedFiles = Arrays.asList(expectedDir.list(filter));
184 expectedFiles.sort(null);
185
186 testCase.assertEquals("The resulting file names are not expected",
187 expectedFiles, resultFiles);
188
189 for (int i = 0; i < resultFiles.size(); i++) {
190 File expected = new File(expectedDir, expectedFiles.get(i));
191 File result = new File(resultDir, resultFiles.get(i));
192
193 testCase.assertEquals(
194 "Type mismatch: expected a "
195 + (expected.isDirectory() ? "directory" : "file")
196 + ", received a "
197 + (result.isDirectory() ? "directory" : "file"),
198 expected.isDirectory(), result.isDirectory());
199
200 if (expected.isDirectory()) {
201 compareFiles(testCase, expected, result, null, sourceType);
202 continue;
203 }
204
205 if (expected.getName().endsWith(".cbz")
206 || expected.getName().endsWith(".epub")) {
207 File tmpExpected = tempFiles.createTempDir(expected.getName()
208 + "[zip-content]");
209 File tmpResult = tempFiles.createTempDir(result.getName()
210 + "[zip-content]");
211 unzip(expected, tmpExpected);
212 unzip(result, tmpResult);
213 compareFiles(testCase, tmpExpected, tmpResult, null, sourceType);
214 } else {
215 List<String> expectedLines = Arrays.asList(IOUtils
216 .readSmallFile(expected).split("\n"));
217 List<String> resultLines = Arrays.asList(IOUtils.readSmallFile(
218 result).split("\n"));
219
220 String name = expected.getAbsolutePath();
221 if (name.startsWith(expectedDir.getAbsolutePath())) {
222 name = expectedDir.getName()
223 + name.substring(expectedDir.getAbsolutePath()
224 .length());
225 }
226 for (int j = 0; j < expectedLines.size(); j++) {
227 String expectedLine = expectedLines.get(j);
228 String resultLine = resultLines.get(j);
229
230 boolean skip = false;
231 for (Entry<String, List<String>> skipThose : skipCompare
232 .entrySet()) {
233 for (String skipStart : skipThose.getValue()) {
234 if (name.endsWith(skipThose.getKey())
235 && expectedLine.startsWith(skipStart)
236 && resultLine.startsWith(skipStart)) {
237 skip = true;
238 }
239 }
240 }
241
242 if (skip) {
243 continue;
244 }
245
246 testCase.assertEquals("Line " + (j + 1) + " (" + sourceType
247 + ") is not the same in file " + name,
248 expectedLine, resultLine);
249 }
250 }
251 }
252 }
253
254 // TODO: remove and use IOUtils when updated
255 private static void unzip(File zipFile, File targetDirectory)
256 throws IOException {
257 if (targetDirectory.exists() && targetDirectory.isFile()) {
258 throw new IOException("Cannot unzip " + zipFile + " into "
259 + targetDirectory + ": it is not a directory");
260 }
261
262 targetDirectory.mkdir();
263 if (!targetDirectory.exists()) {
264 throw new IOException("Cannot create target directory "
265 + targetDirectory);
266 }
267
268 FileInputStream in = new FileInputStream(zipFile);
269 try {
270 ZipInputStream zipStream = new ZipInputStream(in);
271 try {
272 for (ZipEntry entry = zipStream.getNextEntry(); entry != null; entry = zipStream
273 .getNextEntry()) {
274 File file = new File(targetDirectory, entry.getName());
275 if (entry.isDirectory()) {
276 file.mkdirs();
277 } else {
278 IOUtils.write(zipStream, file);
279 }
280 }
281 } finally {
282 zipStream.close();
283 }
284 } finally {
285 in.close();
286 }
287 }
288 }