View Javadoc
1   /*
2    * The akquinet maven-latex-plugin project
3    *
4    * Copyright (c) 2011 by akquinet tech@spree GmbH
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package eu.simuline.m2latex.core;
20  
21  import eu.simuline.m2latex.mojo.MavenLogWrapper;
22  import eu.simuline.m2latex.mojo.PdfMojo;
23  
24  import java.io.File;
25  import java.io.FileFilter;
26  // import java.io.FileWriter;
27  // import java.io.Writer;
28  import java.io.IOException;
29  
30  import org.apache.maven.plugin.logging.Log;
31  import org.apache.maven.plugin.logging.SystemStreamLog;
32  
33  import static org.mockito.Mockito.mock;
34  import static org.mockito.Mockito.RETURNS_SMART_NULLS;
35  import static org.mockito.Mockito.when;
36  import static org.mockito.Mockito.doNothing;
37  import static org.mockito.Mockito.doThrow;
38  import static org.mockito.Mockito.doCallRealMethod;
39  import static org.mockito.Mockito.verify;
40  import static org.mockito.Mockito.spy;
41  import static org.mockito.Mockito.verifyNoMoreInteractions;
42  import static org.mockito.Mockito.atLeastOnce;
43  import static org.mockito.Mockito.inOrder;
44  
45  import static org.mockito.ArgumentMatchers.any;
46  import static org.mockito.ArgumentMatchers.anyString;
47  import static org.mockito.ArgumentMatchers.isNull;
48  import static org.mockito.ArgumentMatchers.eq;
49  import static org.mockito.AdditionalMatchers.aryEq;
50  
51  import org.mockito.InOrder;
52  
53  import org.mockito.stubbing.Answer;
54  import org.mockito.invocation.InvocationOnMock;
55  
56  import org.junit.Test;
57  import org.junit.Ignore;
58  import org.junit.Before;
59  import org.junit.After;
60  //import org.junit.BeforeClass;
61  //import org.junit.AfterClass;
62  
63  // FIXME: missing: test of logging 
64  // FIXME: mocking and verification in parallel 
65  // FIXME: rename: mock-->stub 
66  // FIXME: missing: test of warnings and errors 
67  public class LatexProcessorTest {
68  
69      private final static File WORKING_DIR = 
70  	new File(System.getProperty("testResourcesDir"));
71  
72      /**
73       * Filter rejecting all files. 
74       */
75      private final static FileFilter FILTER_FALSE = new FileFilter() {
76  		public boolean accept(File pathname) {
77  		    return false;
78  		}
79  	    };
80  
81      private final CommandExecutor executor = mock(CommandExecutor.class,
82  						  RETURNS_SMART_NULLS);
83      // pertained because of bugfixes 
84      //private final InOrder inOrderExec = inOrder(this.executor);
85  
86      private final TexFileUtils fileUtils = mock(TexFileUtils.class,
87  						RETURNS_SMART_NULLS);
88  
89      // pertained because of bugfixes 
90      //private final InOrder inOrderFileUtils = inOrder(this.fileUtils);
91  
92      private final InOrder inOrder = inOrder(this.executor, this.fileUtils);
93  
94      private final Settings settings = new Settings();
95  
96      // mock 
97      // - ignores debug and info 
98      // - verifies error and warn
99  //     private LogWrapper log = mock(MavenLogWrapper.class,
100 // 				  new Answer<Void>() {
101 // 	public Void answer(InvocationOnMock invocation) throws Throwable {
102 // System.out.println("answer..");
103 	    
104 // 	    String methodName = invocation.getMethod().getName();
105 // System.out.println("methodName: "+methodName);
106 // 	    if (methodName.equals("debug") || methodName.equals("info")) {
107 // //		invocation.callRealMethod();
108 // 	    } else {
109 // 		assert methodName.equals("error") || methodName.equals("warn");
110 // 		LogWrapper lw = (LogWrapper)invocation.getMock();
111 // 		if (methodName.equals("error")) {
112 // 		    verify(lw).error(anyString());
113 // 		} else {
114 // 		    verify(lw).warn(anyString());
115 // 		}
116 // 		// Object[] args = invocation.getArguments();
117 // 		// Object mock = invocation.getMock();
118 // 	    }
119 // System.out.println("..answer");
120 // return null;
121 // 	}
122 //     });
123 //private LogWrapper log = mock(MavenLogWrapper.class, RETURNS_SMART_NULLS);
124     private final LogWrapper log = 
125 	spy(new MavenLogWrapper(new SystemStreamLog()));
126 
127     private final LatexProcessor processor = new LatexProcessor
128 	(this.settings, this.executor, this.log, this.fileUtils,new PdfMojo());
129 
130     // FIXME: eliminate all those files 
131     // present in LatexMainDesc 
132     // and even the others defining LatexMainDescExt including these also 
133     private File texFile = new File(WORKING_DIR, "test.tex");// LatexMainDesc 
134     private File pdfFile = new File(WORKING_DIR, "test.pdf");// LatexMainDesc 
135     private File dviFile = new File(WORKING_DIR, "test.dvi");// LatexMainDesc 
136     // FIXME: used only once
137     private File dviPdfFile = new File
138      	(WORKING_DIR, "test."+settings.getPdfViaDvi().getLatexOutputFormat());
139     private File htmlFile= new File(WORKING_DIR, "test.html");
140     private File auxFile = new File(WORKING_DIR, "test.aux");
141     private File logFile = new File(WORKING_DIR, "test.log");// LatexMainDesc 
142 
143     private File bblFile = new File(WORKING_DIR, "test.bbl");
144     private File blgFile = new File(WORKING_DIR, "test.blg");
145 
146     private File idxFile = new File(WORKING_DIR, "test.idx");// LatexMainDesc 
147     private File indFile = new File(WORKING_DIR, "test.ind");// LatexMainDesc 
148     private File ilgFile = new File(WORKING_DIR, "test.ilg");// LatexMainDesc 
149 
150     // private File istFile = new File(WORKING_DIR, "test.ist");
151     // private File xdyFile = new File(WORKING_DIR, "test.xdy");
152     private File glsFile = new File(WORKING_DIR, "test.gls");// LatexMainDesc 
153     private File gloFile = new File(WORKING_DIR, "test.glo");// LatexMainDesc 
154     private File glgFile = new File(WORKING_DIR, "test.glg");// LatexMainDesc 
155     // this one does never exist. 
156     private File xxxFile = new File(WORKING_DIR, "test");// LatexMainDesc 
157 
158     // FIXME: needed for later use: test also if toc/lof/lot are not present 
159     private File tocFile = new File(WORKING_DIR, "test.toc");
160     private File lofFile = new File(WORKING_DIR, "test.lof");
161     private File lotFile = new File(WORKING_DIR, "test.lot");
162 
163     public LatexProcessorTest() {
164 	//this.settings.setPdfViaDvi(true);
165 
166 	// ensures that neither an error nor a warning occurs 
167 	// FIXME: add tests with errors and warnings. 
168 	doThrow(new AssertionError("Found error. "))
169 	    .when(this.log).error(anyString());
170 	doThrow(new AssertionError("Found warning. "))
171 	    .when(this.log).warn(anyString());
172 	doCallRealMethod().when(this.log).info(anyString());
173 	doNothing().when(this.log).debug(anyString());
174     }
175 
176     // FIXME: occurs also in other testclasses: 
177     // to be unified. 
178     private static void cleanWorkingDir() {
179 	assert WORKING_DIR.isDirectory() : "Expected directory. ";
180 	File[] files = WORKING_DIR.listFiles();
181 	assert files != null : "Working directory is not readable. ";
182 	for (File file : files) {
183 	    if (!file.isHidden()) {
184 		file.delete();
185 	    }
186 	}
187     }
188 
189     @Before public void setUp() throws IOException {
190 	cleanWorkingDir();
191 	//this.texFile.createNewFile();
192 	//this.auxFile.createNewFile();
193 	this.logFile.createNewFile();
194 	this.blgFile.createNewFile();
195 	//this.pdfFile.createNewFile();
196     }
197 
198     @After public void tearDown() throws IOException {
199 	cleanWorkingDir();
200     }
201 
202     //@Ignore 
203     // FIXME: does not take pdfViaDvi into account 
204     @Test public void testProcessLatexSimple() throws BuildFailureException {
205 	
206 	mockProcessLatex2pdf(false, false, false);
207 
208 	this.processor.processLatex2pdf(this.texFile);
209 	verifyProcessLatex2pdf(false, false, false);
210 	verifyNoMoreInteractions(this.executor);
211 	verifyNoMoreInteractions(this.fileUtils);
212 	//verifyNoMoreInteractions(this.log);
213     }
214 
215     //@Ignore 
216     @Test public void testProcessLatexWithBibtex() 
217 	throws BuildFailureException {
218 
219 	mockProcessLatex2pdf(true, false, false);
220 
221         this.processor.processLatex2pdf(this.texFile);
222 	verifyProcessLatex2pdf(true, false, false);
223 	verifyNoMoreInteractions(this.executor);
224 	verifyNoMoreInteractions(this.fileUtils);
225 	//verifyNoMoreInteractions(this.log);
226     }
227 
228    //@Ignore 
229     @Test public void testProcessLatex2html() throws BuildFailureException {
230 
231 	mockProcessLatex2html(false, false, false);
232 
233 	this.processor.processLatex2html(this.texFile);
234 
235 	verifyProcessLatex2html(false, false, false);
236 	verifyNoMoreInteractions(this.executor);
237 	verifyNoMoreInteractions(this.fileUtils);
238 	//verifyNoMoreInteractions(this.log);
239     }
240 
241     private void mockProcessLatex2pdf(boolean needBibtex,
242 				      boolean needMakeIndex,
243 				      boolean needMakeGlossaries) 
244 	throws BuildFailureException {
245 	
246 	mockConstrLatexMainDesc();
247 	assert !this.settings.getPdfViaDvi().isViaDvi();
248 	// FIXME: here should be mockProcessLatex2dev
249 	mockProcessLatex2devCore(needBibtex, needMakeIndex, needMakeGlossaries);
250 
251 	when(this.fileUtils.matchInFile(this.logFile, 
252 					LatexProcessor.PATTERN_OUFULL_HVBOX))
253 	    .thenReturn(Boolean.FALSE);
254 
255 	when(this.fileUtils.matchInFile(this.logFile, 
256 					this.settings.getPatternWarnLatex()))
257 	    .thenReturn(Boolean.FALSE);
258     }
259 
260     private void verifyProcessLatex2pdf(boolean needBibtex,
261 					boolean needMakeIndex,
262 					boolean needMakeGlossary) 
263 	throws BuildFailureException {
264 
265 	verifyConstrLatexMainDesc();
266 	assert !this.settings.getPdfViaDvi().isViaDvi();
267 	// FIXME: here should be verifyProcessLatex2dev
268 	verifyProcessLatex2devCore(needBibtex, needMakeIndex, needMakeGlossary);
269 
270 	this.inOrder.verify(this.fileUtils).matchInFile
271 	    (this.logFile, LatexProcessor.PATTERN_OUFULL_HVBOX);
272 	this.inOrder.verify(this.fileUtils).matchInFile
273 	    (this.logFile, this.settings.getPatternWarnLatex());
274     }
275 
276     private void mockProcessLatex2html(boolean needBibtex,
277 				       boolean needMakeIndex,
278 				       boolean needMakeGlossaries) 
279 	throws BuildFailureException {
280 
281 	mockConstrLatexMainDesc();
282 	mockPreProcessLatex2dev(needBibtex, needMakeIndex, needMakeGlossaries);
283         mockRunLatex2html();
284     }
285 
286     private void verifyProcessLatex2html(boolean needBibtex,
287 					 boolean needMakeIndex,
288 					 boolean needMakeGlossary) 
289 	throws BuildFailureException {
290 
291 	verifyConstrLatexMainDesc();
292 	verifyPreProcessLatex2dev(needBibtex, needMakeIndex, needMakeGlossary);
293         verifyRunLatex2html();
294     }
295 
296     private void mockConstrLatexMainDesc() {
297 	//this.desc = this.processor.getLatexMainDesc(this.texFile);
298 
299 	File texFile = this.texFile;
300   	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_VOID))
301 	    .thenReturn(this.xxxFile);
302 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_PDF))
303 	    .thenReturn(this.pdfFile);
304 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_DVI))
305 	    .thenReturn(this.dviFile);
306 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_LOG))
307 	    .thenReturn(this.logFile);
308 
309 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_IDX))
310 	    .thenReturn(this.idxFile);
311 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_IND))
312 	    .thenReturn(this.indFile);
313 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_ILG))
314 	    .thenReturn(this.ilgFile);
315 
316 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_GLS))
317 	    .thenReturn(this.glsFile);
318 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_GLO))
319 	    .thenReturn(this.gloFile);
320 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_GLG))
321 	    .thenReturn(this.glgFile);
322     }
323 
324     private void verifyConstrLatexMainDesc() {
325 	// FIXME: doubling from mockConstrLatexMainDesc()
326 	String[] suffixes = new String[] {
327 	    LatexProcessor.SUFFIX_VOID,
328 	    LatexProcessor.SUFFIX_PDF,
329 	    LatexProcessor.SUFFIX_DVI,
330 	    LatexProcessor.SUFFIX_LOG,
331 	    LatexProcessor.SUFFIX_IDX,
332 	    LatexProcessor.SUFFIX_IND,
333 	    LatexProcessor.SUFFIX_ILG,
334 	    LatexProcessor.SUFFIX_GLS,
335 	    LatexProcessor.SUFFIX_GLO,
336 	    LatexProcessor.SUFFIX_GLG
337 	};
338 	for (int idx = 0; idx < suffixes.length; idx++) {
339 	    // FIXME: should work also in order. 
340 	    // FIXME: observation: in order works iff no atLeastOnce is required
341 	    // On the other hand, I am not sure 
342 	    // why I need this in the individual cases. 
343 	    //this.inOrder.
344 	    //if (idx == 1 ||idx == 2) {continue;}
345 	    verify(this.fileUtils, atLeastOnce())
346 		.replaceSuffix(this.texFile, suffixes[idx]);
347 	}
348     }
349 
350     // FIXME: pdf never via dvi 
351     // FIXME: parametrization of needMakeIndex, needMakeGlossaries 
352     // 
353     private void mockPreProcessLatex2dev(boolean needBibtex,
354 					 boolean needMakeIndex,
355 					 boolean needMakeGlossaries) 
356 	throws BuildFailureException {
357 	assert !needMakeIndex && !needMakeGlossaries;
358 
359  	// run latex 
360         mockRunLatex();
361 	// FIXME: to indicate whether makeindex must be run: 
362 	// method creates .idx or not: use Mockito.thenAnswer for that
363 
364 	// run bibtex, makeIndex and makeGlossary by need 
365 	mockRunBibtexByNeed(needBibtex);
366 	mockRunMakeIndexByNeed(needMakeIndex);
367 	mockRunMakeGlossaryByNeed(needMakeGlossaries);
368 
369 	if (needBibtex) {
370 	    return;
371 	}
372 	// FIXME: not the truth if makeindex and makeglossaries are included 
373 	// and also not if TOC exists. 
374 
375 	assert !this.tocFile.exists() 
376 	    && !this.lofFile.exists() 
377 	    && !this.lotFile.exists();
378 	// determine from presence of toc, lof, lot (and idx and other criteria)
379 	// whether to rerun latex: no 
380 	File texFile = this.texFile;
381 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_TOC))
382 	    .thenReturn(this.tocFile);
383 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_LOF))
384 	    .thenReturn(this.lofFile);
385 	when(this.fileUtils.replaceSuffix(texFile, LatexProcessor.SUFFIX_LOT))
386 	    .thenReturn(this.lotFile);
387     }
388 
389     private void verifyPreProcessLatex2dev(boolean needBibtex,
390 					   boolean needMakeIndex,
391 					   boolean needMakeGlossaries) 
392 	throws BuildFailureException {
393 	assert !needMakeIndex && !needMakeGlossaries;
394 
395 	// run latex 
396         verifyRunLatex();
397 
398 	// run bibtex, makeIndex and makeGlossary by need 
399 	verifyRunBibtexByNeed(needBibtex);
400 	verifyRunMakeIndexByNeed(needMakeIndex);
401 	verifyRunMakeGlossaryByNeed(needMakeGlossaries);
402 
403 	if (needBibtex) {
404 	    return;
405 	}
406 	// FIXME: not the truth if makeindex and makeglossaries are included 
407 	// and also not if TOC exists. 
408 
409 	assert !this.tocFile.exists() 
410 	    && !this.lofFile.exists() 
411 	    && !this.lotFile.exists();
412 	// determine from presence of toc, lof, lot (and idx and other criteria)
413 	// whether to rerun latex: no 
414 
415 
416 	// FIXME: duplicate 
417 	String[] suffixes = new String[] {
418 	    LatexProcessor.SUFFIX_TOC,
419 	    LatexProcessor.SUFFIX_LOF,
420 	    LatexProcessor.SUFFIX_LOT
421 	};
422 	for (int idx = 0; idx < suffixes.length; idx++) {
423 	    this.inOrder.verify(this.fileUtils)
424 		.replaceSuffix(this.texFile, suffixes[idx]);
425 	}
426     }
427 
428     // FIXME: currently, neither toc nor lof nor lot exist 
429     private void mockProcessLatex2devCore(boolean needBibtex,
430 					  boolean needMakeIndex,
431 					  boolean needMakeGlossaries) 
432 	throws BuildFailureException {
433 
434 	assert !needMakeIndex && !needMakeGlossaries;
435 	assert !this.tocFile.exists() 
436 	    && !this.lofFile.exists() 
437 	    && !this.lotFile.exists();
438 	// FIXME: would be safer to define = -1 
439 	assert this.settings.getMaxNumReRunsLatex() == 5;
440 
441 	mockPreProcessLatex2dev(needBibtex, needMakeIndex, needMakeGlossaries);
442 	// preProcessLatex2dev returns 
443 	// 2 if needBibtex 
444 	// since currently neither makeindex nor makeglossaries are supported 
445 	// and neither toc, lof or lot exist: 
446 	// 0 else 
447 
448 	if (needBibtex) {
449 	    // numLatexReRuns == 2 
450 	    mockRunLatex();
451 	    // numLatexReRuns == 1 
452 	    // enter for-loop... 
453 	    mockNeedRun(false, this.settings.getPatternReRunMakeIndex());
454 	    mockRunLatex();
455 	    mockNeedRun(false, this.settings.getPatternReRunLatex());
456 	    // second loop 
457 	    mockNeedRun(false, this.settings.getPatternReRunMakeIndex());
458 	    // exit for-loop 
459 	} else {
460 	    mockNeedRun(false, this.settings.getPatternReRunLatex());
461 	    // enter for-loop... 
462 	    mockNeedRun(false, this.settings.getPatternReRunMakeIndex());
463 	    // since both conditions are false 
464 	    // exit for-loop 
465  	}
466     }
467 
468     // FIXME: currently, neither toc nor lof nor lot exist 
469     private void verifyProcessLatex2devCore(boolean needBibtex,
470 					    boolean needMakeIndex,
471 					    boolean needMakeGlossary) 
472 	throws BuildFailureException {
473 
474 	assert !needMakeIndex && !needMakeGlossary;
475 	assert !this.tocFile.exists() 
476 	    && !this.lofFile.exists() 
477 	    && !this.lotFile.exists();
478 	// FIXME: would be safer to define = -1 
479 	assert this.settings.getMaxNumReRunsLatex() == 5;
480 
481 	verifyPreProcessLatex2dev(needBibtex, needMakeIndex, needMakeGlossary);
482 	// preProcessLatex2dev returns 
483 	// 2 if needBibtex 
484 	// since currently neither makeindex nor makeglossaries are supported 
485 	// and neither toc, lof or lot exist: 
486 	// 0 else 
487 
488 	if (needBibtex) {
489 	    // numLatexReRuns == 2 
490 	    verifyRunLatex();
491 	    // numLatexReRuns == 1 
492 	    // enter for-loop... 
493 	    verifyNeedRun(this.logFile, 
494 			  this.settings.getPatternReRunMakeIndex());
495 	    verifyRunLatex();
496 	    verifyNeedRun(this.logFile, 
497 			  this.settings.getPatternReRunLatex());
498 	    // second loop 
499 	    verifyNeedRun(this.logFile, 
500 			  this.settings.getPatternReRunMakeIndex());
501 	    // exit for-loop 
502 	} else {
503 	    verifyNeedRun(this.logFile, 
504 			  this.settings.getPatternReRunLatex());
505 	    // enter for-loop... 
506 	    verifyNeedRun(this.logFile, 
507 			  this.settings.getPatternReRunMakeIndex());
508 	    // since both conditions are false 
509 	    // exit for-loop 
510 	}
511     }
512 
513     private void mockNeedRun(Boolean retVal, String pattern)
514         throws BuildFailureException {
515 
516 	when(this.fileUtils.matchInFile(this.logFile, pattern))
517 	    .thenReturn(retVal);
518     }
519 
520     private void verifyNeedRun(File file, String pattern)
521         throws BuildFailureException {
522 	// FIXME: should work also in order. 
523 	//this.inOrder.
524 	verify(this.fileUtils, atLeastOnce()).matchInFile(file, pattern);
525     }
526 
527     private void mockRunBibtexByNeed(Boolean runBibtex) 
528 	throws BuildFailureException {
529 	
530 	when(this.fileUtils.replaceSuffix
531 	     (this.texFile, LatexProcessor.SUFFIX_AUX))
532 	    .thenReturn(this.auxFile);
533 	when(this.fileUtils.matchInFile
534 	     (this.auxFile, LatexProcessor.PATTERN_NEED_BIBTEX_RUN))
535 	    .thenReturn(runBibtex);
536 
537 	// FIXME: really needed?? 
538 //	Writer writer = new FileWriter(this.auxFile);
539 	if (!runBibtex) {
540 //	    writer.write("% no bibtex run");
541 //	    writer.flush();
542 	    return;
543 	}
544 //	writer.write("\\bibdata % bibtex run"); 
545 //	writer.flush();
546 
547 	when(this.fileUtils.replaceSuffix(this.texFile, 
548 					  LatexProcessor.SUFFIX_BBL))
549 	    .thenReturn(this.bblFile);
550 
551 	// when(this.executor.execute(texFile.getParentFile(),
552 	// 			   this.settings.getTexPath(),
553 	// 			   this.settings.getBibtexCommand(),
554 	// 			   LatexProcessor.buildArguments
555 	// 			   (this.settings.getBibtexOptions(), 
556 	// 			    this.auxFile),
557 	// 			   this.bblFile))
558 	//     .thenReturn("");
559 
560 	// log file 
561 	when(this.fileUtils.replaceSuffix(this.texFile, 
562 					  LatexProcessor.SUFFIX_BLG))
563 	    .thenReturn(this.blgFile);
564 	// logging errors and warnings 
565 	when(this.fileUtils.matchInFile(this.blgFile, 
566 					this.settings.getPatternErrBibtex()))
567 	    .thenReturn(Boolean.FALSE);
568 	when(this.fileUtils.matchInFile(this.blgFile, 
569 					this.settings.getPatternWarnBibtex()))
570 	    .thenReturn(Boolean.FALSE);
571     }
572 
573     private void verifyRunBibtexByNeed(Boolean runBibtex) 
574 	throws BuildFailureException {
575 
576 	this.inOrder.verify(this.fileUtils)
577 	    .replaceSuffix(this.texFile, LatexProcessor.SUFFIX_AUX);
578 	verifyNeedRun(this.auxFile,  LatexProcessor.PATTERN_NEED_BIBTEX_RUN);
579 
580 	if (!runBibtex) {
581 	    return;
582 	}
583 
584 	this.inOrder.verify(this.fileUtils)
585 	    .replaceSuffix(this.texFile, LatexProcessor.SUFFIX_BBL);
586 	this.inOrder.verify(this.executor)
587 	    .execute(eq(WORKING_DIR),
588 		     isNull(),
589 		     eq(this.settings.getBibtexCommand()),
590 		     aryEq(LatexProcessor.buildArguments
591 			   (this.settings.getBibtexOptions(), this.auxFile)),
592 		     eq(this.bblFile));
593 
594 	// log file 
595 	this.inOrder.verify(this.fileUtils)
596 	    .replaceSuffix(this.texFile, LatexProcessor.SUFFIX_BLG);
597 	// logging errors and warnings 
598 	this.inOrder.verify(this.fileUtils)
599 	    .matchInFile(this.blgFile, this.settings.getPatternErrBibtex());
600 	this.inOrder.verify(this.fileUtils)
601 	    .matchInFile(this.blgFile, this.settings.getPatternWarnBibtex());
602     }
603 
604     private void mockRunMakeIndexByNeed(boolean runMakeIndex) 
605 	throws BuildFailureException {
606 
607 	when(this.fileUtils.getFileFilterReplace(this.idxFile, "-.+"))
608 	    .thenReturn(FILTER_FALSE);
609 
610 	when(this.fileUtils.listFilesOrWarn(WORKING_DIR, FILTER_FALSE))
611 	    .thenReturn(new File[0]);
612 
613 	assert !runMakeIndex;
614 
615 	if (!runMakeIndex) {
616 	    return;
617 	}
618 	mockRunMakeIndex();
619     }
620 
621     private void verifyRunMakeIndexByNeed(boolean runMakeIndex) 
622 	throws BuildFailureException {
623 
624 	this.inOrder.verify(this.fileUtils)
625 	    .getFileFilterReplace(this.idxFile, "-.+");
626 	this.inOrder.verify(this.fileUtils)
627 	    .listFilesOrWarn(WORKING_DIR, FILTER_FALSE);
628 
629 	assert !runMakeIndex;
630 
631 	if (!runMakeIndex) {
632 	    return;
633 	}
634 	verifyRunMakeIndex();
635     }
636 
637     private void mockRunMakeIndex() throws BuildFailureException {
638 	assert false;
639 	
640 	// when(this.executor.execute(this.texFile.getParentFile(),
641 	// 			   this.settings.getTexPath(),
642 	// 			   this.settings.getMakeIndexCommand(),
643 	// 			   LatexProcessor.buildArguments
644 	// 			   (this.settings.getMakeIndexOptions(), 
645 	// 			    this.idxFile),
646 	// 			   this.indFile))
647 	//     .thenReturn("");
648 
649 	// since ilg file does not exist 
650 	when(this.fileUtils.matchInFile(this.ilgFile, 
651 					this.settings.getPatternErrMakeIndex()))
652 	    .thenReturn(Boolean.FALSE);
653     }
654 
655     private void verifyRunMakeIndex() throws BuildFailureException {
656 	assert false;
657 
658 	this.inOrder.verify(this.executor)
659 	    .execute(eq(WORKING_DIR),
660 		     isNull(),
661 		     eq(this.settings.getMakeIndexCommand()),
662 		     aryEq(LatexProcessor.buildArguments
663 			   (this.settings.getMakeIndexOptions(), this.idxFile)),
664 		     eq(this.indFile));
665 	this.inOrder.verify(this.fileUtils)
666 	    .matchInFile(this.ilgFile, this.settings.getPatternErrMakeIndex());
667     }
668 
669     private void mockRunMakeGlossaryByNeed(boolean runMakeGlossaries) 
670 	throws BuildFailureException {
671  
672 	assert !runMakeGlossaries;
673 	if (!runMakeGlossaries) {
674 	    return;
675 	}
676 	assert false;
677 
678 	// when(this.executor.execute(this.texFile.getParentFile(),
679 	// 			   this.settings.getTexPath(),
680 	// 			   this.settings.getMakeGlossariesCommand(),
681 	// 			   LatexProcessor.buildArguments
682 	// 			   (this.settings.getMakeGlossariesOptions(), 
683 	// 			    xxxFile),
684 	// 			   glsFile))
685 	//     .thenReturn("");
686 
687 	// since glg file does not exist 
688 	when(this.fileUtils.matchInFile
689 	     (this.glgFile, this.settings.getPatternErrMakeGlossaries()))
690 	    .thenReturn(Boolean.FALSE);
691     }
692 
693     private void verifyRunMakeGlossaryByNeed(boolean runMakeGlossaries) 
694 	throws BuildFailureException {
695  
696 	assert !runMakeGlossaries;
697 	if (!runMakeGlossaries) {
698 	    return;
699 	}
700 	assert false;
701 
702 	this.inOrder.verify(this.executor)
703 	    .execute(eq(WORKING_DIR),
704 		     isNull(),
705 		     eq(this.settings.getMakeGlossariesCommand()),
706 		     aryEq(LatexProcessor.buildArguments
707 			   (this.settings.getMakeGlossariesOptions(), 
708 			    this.xxxFile)),
709 		     eq(this.glsFile));
710 	this.inOrder.verify(this.fileUtils)
711 	    .matchInFile(this.ilgFile, 
712 			 this.settings.getPatternErrMakeGlossaries());
713     }
714 
715     private void mockRunLatex() throws BuildFailureException {
716 
717 	// when(this.executor.execute(this.texFile.getParentFile(),
718 	// 			   this.settings.getTexPath(),
719 	// 			   this.settings.getLatex2pdfCommand(),
720 	// 			   LatexProcessor
721 	// 			   .buildLatexArguments(this.settings, 
722 	// 						this.settings
723 	// 						.getPdfViaDvi(), 
724 	// 						this.texFile),
725 	// 			   this.dviPdfFile))
726 	//     .thenReturn("");
727 
728 	// Ensure that no failure occurred 
729 	// FIXME: missing: testcases with error 
730 	when(this.fileUtils.matchInFile(this.logFile, 
731 					this.settings.getPatternErrLatex()))
732 	    .thenReturn(Boolean.FALSE);
733     }
734 
735     private void verifyRunLatex() throws BuildFailureException {
736 	
737 	// FIXME: should work also in order. 
738 	//this.inOrder.
739 	verify(this.executor, atLeastOnce())
740 	    .execute(eq(WORKING_DIR),
741 		     isNull(),
742 		     eq(this.settings.getLatex2pdfCommand()),
743 		     aryEq(LatexProcessor.buildLatexArguments
744 			(this.settings, 
745 			 this.settings.getPdfViaDvi(), 
746 			 this.texFile)),
747 		     eq(this.dviPdfFile));
748 
749 	// FIXME: should work also in order. 
750 	//this.inOrder.
751 	verify(this.fileUtils, atLeastOnce())
752 	    .matchInFile(this.logFile, this.settings.getPatternErrLatex());
753     }
754 
755     private void mockRunLatex2html() throws BuildFailureException {
756 	// html to verify whether execution created the expected html file 
757 	when(this.fileUtils.replaceSuffix(this.texFile, 
758 					  LatexProcessor.SUFFIX_HTML))
759 	    .thenReturn(this.htmlFile);
760 
761 	// when(this.executor.execute(this.texFile.getParentFile(),
762 	// 			   this.settings.getTexPath(),
763 	// 			   this.settings.getTex4htCommand(),
764 	// 			   LatexProcessor.buildHtlatexArguments
765 	// 			   (this.settings, this.texFile),
766 	// 			   this.htmlFile))
767 	//     .thenReturn("");
768 
769 
770 	// logging errors, bad boxes and other warnings 
771 	when(this.fileUtils.matchInFile(this.logFile, 
772 					this.settings.getPatternErrLatex()))
773 	    .thenReturn(Boolean.FALSE);
774 	when(this.fileUtils.matchInFile(this.logFile, 
775 					LatexProcessor.PATTERN_OUFULL_HVBOX))
776 	    .thenReturn(Boolean.FALSE);
777 	when(this.fileUtils.matchInFile(this.logFile, 
778 					this.settings.getPatternWarnLatex()))
779 	    .thenReturn(Boolean.FALSE);
780     }
781 
782     private void verifyRunLatex2html() throws BuildFailureException {
783 	this.inOrder.verify(this.fileUtils)
784 	    .replaceSuffix(this.texFile, LatexProcessor.SUFFIX_HTML);
785 	this.inOrder.verify(this.executor)
786 	    .execute(eq(WORKING_DIR),
787 		     isNull(),
788 		     eq(this.settings.getTex4htCommand()),
789 		     aryEq(LatexProcessor.buildHtlatexArguments
790 			 (this.settings, this.texFile)),
791 		     eq(this.htmlFile));
792 	String[] patterns = new String[] {
793 	    this.settings.getPatternErrLatex(),
794 	    LatexProcessor.PATTERN_OUFULL_HVBOX,
795 	    this.settings.getPatternWarnLatex()
796 	};
797 	for (int idx = 0; idx < patterns.length; idx++) {
798 	    this.inOrder.verify(this.fileUtils)
799 		.matchInFile(this.logFile, patterns[idx]);
800 	}
801     }
802 }