Update conversion tests and test files
[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, "Generate "
102 + type);
103
104 // LATEX not supported as input
105 if (BasicOutput.OutputType.LATEX.equals(type)) {
106 return;
107 }
108
109 // Cross-checks:
110 for (BasicOutput.OutputType crossType : realTypes) {
111 File crossDir = tempFiles.createTempDir("cross-result");
112 generate(this, target, crossDir, crossType);
113 compareFiles(this, resultDir, crossDir, crossType,
114 "Cross compare " + crossType + " generated from "
115 + type);
116 }
117 }
118 };
119 }
120
121 private File generate(TestCase testCase, File testFile, File resultDir,
122 BasicOutput.OutputType type) throws Exception {
123 final List<String> errors = new ArrayList<String>();
124
125 TraceHandler previousTraceHandler = Instance.getTraceHandler();
126 Instance.setTraceHandler(new TraceHandler(true, true, 0) {
127 @Override
128 public void error(String message) {
129 errors.add(message);
130 }
131
132 @Override
133 public void error(Exception e) {
134 error(" ");
135 for (Throwable t = e; t != null; t = t.getCause()) {
136 error(((t == e) ? "(" : "..caused by: (")
137 + t.getClass().getSimpleName() + ") "
138 + t.getMessage());
139 for (StackTraceElement s : t.getStackTrace()) {
140 error("\t" + s.toString());
141 }
142 }
143 }
144 });
145
146 try {
147 File target = new File(resultDir, type.toString());
148 int code = Main.convert(testFile.getAbsolutePath(),
149 type.toString(), target.getAbsolutePath(), false, null);
150
151 String error = "";
152 for (String err : errors) {
153 if (!error.isEmpty())
154 error += "\n";
155 error += err;
156 }
157 testCase.assertEquals("The conversion returned an error message: "
158 + error, 0, errors.size());
159 if (code != 0) {
160 testCase.fail("The conversion failed with return code: " + code);
161 }
162
163 return target;
164 } finally {
165 Instance.setTraceHandler(previousTraceHandler);
166 }
167 }
168
169 private void compareFiles(TestCase testCase, File expectedDir,
170 File resultDir, final BasicOutput.OutputType limitTiFiles,
171 final String errMess) throws Exception {
172 FilenameFilter filter = null;
173 if (limitTiFiles != null) {
174 filter = new FilenameFilter() {
175 @Override
176 public boolean accept(File dir, String name) {
177 return name.toLowerCase().startsWith(
178 limitTiFiles.toString().toLowerCase());
179 }
180 };
181 }
182
183 List<String> resultFiles = Arrays.asList(resultDir.list(filter));
184 resultFiles.sort(null);
185 List<String> expectedFiles = Arrays.asList(expectedDir.list(filter));
186 expectedFiles.sort(null);
187
188 testCase.assertEquals(errMess, expectedFiles, resultFiles);
189
190 for (int i = 0; i < resultFiles.size(); i++) {
191 File expected = new File(expectedDir, expectedFiles.get(i));
192 File result = new File(resultDir, resultFiles.get(i));
193
194 testCase.assertEquals(errMess + ": 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, errMess);
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, errMess);
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(errMess + ": line " + (j + 1)
247 + " is not the same in file " + name, expectedLine,
248 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 }