e104e21470a45501c142d0f83a12379be3fd473c
[jalview.git] / test / jalview / bin / CommandLineOperations.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.bin;
22
23 import static org.testng.Assert.assertNotNull;
24 import static org.testng.Assert.assertTrue;
25
26 import jalview.gui.JvOptionPane;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.IOException;
31 import java.io.InputStreamReader;
32 import java.util.ArrayList;
33
34 import org.testng.Assert;
35 import org.testng.FileAssert;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.BeforeTest;
38 import org.testng.annotations.DataProvider;
39 import org.testng.annotations.Test;
40
41 import io.github.classgraph.ClassGraph;
42 import io.github.classgraph.ScanResult;
43
44 @Test(singleThreaded = true)
45 public class CommandLineOperations
46 {
47
48   @BeforeClass(alwaysRun = true)
49   public void setUpJvOptionPane()
50   {
51     JvOptionPane.setInteractiveMode(false);
52     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
53   }
54
55   private static final int TEST_TIMEOUT = 9000; // Note longer timeout needed on
56                                                 // full test run than on
57                                                 // individual tests
58
59   private static final int SETUP_TIMEOUT = 9000;
60
61   private static final int MINFILESIZE_SMALL = 2096;
62
63   private static final int MINFILESIZE_BIG = 4096;
64
65   private ArrayList<String> successfulCMDs = new ArrayList<>();
66
67   /***
68    * from
69    * http://stackoverflow.com/questions/808276/how-to-add-a-timeout-value-when
70    * -using-javas-runtime-exec
71    * 
72    * @author jimp
73    * 
74    */
75   private static class Worker extends Thread
76   {
77     private final Process process;
78
79     private BufferedReader outputReader;
80
81     private BufferedReader errorReader;
82
83     private Integer exit;
84
85     private Worker(Process process)
86     {
87       this.process = process;
88     }
89
90     @Override
91     public void run()
92     {
93       try
94       {
95         exit = process.waitFor();
96       } catch (InterruptedException ignore)
97       {
98         return;
99       }
100     }
101
102     public BufferedReader getOutputReader()
103     {
104       return outputReader;
105     }
106
107     public void setOutputReader(BufferedReader outputReader)
108     {
109       this.outputReader = outputReader;
110     }
111
112     public BufferedReader getErrorReader()
113     {
114       return errorReader;
115     }
116
117     public void setErrorReader(BufferedReader errorReader)
118     {
119       this.errorReader = errorReader;
120     }
121   }
122
123   private static ClassGraph scanner = null;
124
125   private static String classpath = null;
126
127   public synchronized static String getClassPath()
128   {
129     if (scanner == null)
130     {
131       scanner = new ClassGraph();
132       ScanResult scan = scanner.scan();
133       classpath = scan.getClasspath();
134     }
135     while (classpath == null)
136     {
137       try
138       {
139         Thread.sleep(10);
140       } catch (InterruptedException x)
141       {
142
143       }
144     }
145     return classpath;
146   }
147
148   private Worker getJalviewDesktopRunner(boolean withAwt, String cmd,
149           int timeout)
150   {
151     // Note: JAL-3065 - don't include quotes for lib/* because the arguments are
152     // not expanded by the shell
153     String classpath = getClassPath();
154     String _cmd = "java "
155             + (withAwt ? "-Djava.awt.headless=true" : "")
156             + " -classpath " + classpath + " jalview.bin.Jalview ";
157     Process ls2_proc = null;
158     Worker worker = null;
159     try
160     {
161       ls2_proc = Runtime.getRuntime().exec(_cmd + cmd);
162     } catch (Throwable e1)
163     {
164       e1.printStackTrace();
165     }
166     if (ls2_proc != null)
167     {
168       BufferedReader outputReader = new BufferedReader(
169               new InputStreamReader(ls2_proc.getInputStream()));
170       BufferedReader errorReader = new BufferedReader(
171               new InputStreamReader(ls2_proc.getErrorStream()));
172       worker = new Worker(ls2_proc);
173       worker.setOutputReader(outputReader);
174       worker.setErrorReader(errorReader);
175       worker.start();
176       try
177       {
178         
179         worker.join(timeout);
180         
181       } catch (InterruptedException e)
182       {
183         System.err.println("Thread interrupted");
184       }
185     }
186     return worker;
187   }
188
189   @BeforeTest(alwaysRun = true)
190   public void initialize()
191   {
192     new CommandLineOperations();
193   }
194
195   @BeforeTest(alwaysRun = true)
196   public void setUpForHeadlessCommandLineInputOperations()
197           throws IOException
198   {
199     String cmds = "nodisplay -open examples/uniref50.fa -sortbytree -props test/jalview/io/testProps.jvprops -colour zappo "
200             + "-jabaws http://www.compbio.dundee.ac.uk/jabaws -nosortbytree "
201             + "-features examples/testdata/plantfdx.features -annotations examples/testdata/plantfdx.annotations -tree examples/testdata/uniref50_test_tree";
202     System.out.println("CommandLine test " + ++ntest);
203     Worker worker = getJalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
204     String ln = null;
205     while ((ln = worker.getOutputReader().readLine()) != null)
206     {
207       System.out.println(ln);
208       successfulCMDs.add(ln);
209       if (ln.equals(Jalview.TERMINATOR_LINE))
210       {
211         break;
212       }
213     }
214     if (worker != null && worker.exit == null)
215     {
216       worker.interrupt();
217       Thread.currentThread().interrupt();
218       worker.process.destroy();
219     }
220     // while ((ln = worker.getErrorReader().readLine()) != null)
221     // {
222     // System.err.println(ln);
223     // }
224
225   }
226
227   int ntest = 0;
228
229   @BeforeTest(alwaysRun = true)
230   public void setUpForNonHeadlessInputOperations() throws IOException
231   {
232     String cmds = "-open examples/uniref50.fa -noquestionnaire -nousagestats";
233     Worker worker = getJalviewDesktopRunner(false, cmds, SETUP_TIMEOUT);
234     String ln = null;
235     int count = 0;
236     while ((ln = worker.getErrorReader().readLine()) != null)
237     {
238       System.out.println(ln);
239       successfulCMDs.add(ln);
240       if (ln.equals(Jalview.TERMINATOR_LINE))
241       {
242         break;
243       }
244
245       if (++count > 5)
246       {
247         break;
248       }
249     }
250     if (worker != null && worker.exit == null)
251     {
252       worker.interrupt();
253       Thread.currentThread().interrupt();
254       worker.process.destroy();
255     }
256   }
257
258   @Test(groups = { "Functional" }, dataProvider = "allInputOperationsData")
259   public void testAllInputOperations(String expectedString,
260           String failureMsg)
261   {
262     Assert.assertTrue(successfulCMDs.contains(expectedString), failureMsg);
263   }
264
265   @Test(
266     groups =
267     { "Functional" },
268     dataProvider = "headlessModeOutputOperationsData")
269   public void testHeadlessModeOutputOperations(String harg, String type,
270           String fileName, boolean withAWT, int expectedMinFileSize,
271           int timeout) throws IOException
272   {
273     File file = new File(fileName);
274     String cmd = harg + type + " "
275             + file.getAbsolutePath().replace('\\', '/');
276     System.out.println(">>>>>>>>>>>>>>>> Command : " + cmd);
277
278     file.deleteOnExit();
279     Worker worker = getJalviewDesktopRunner(withAWT, cmd, timeout);
280     assertNotNull(worker, "worker is null");
281     String msg = "Didn't create an output" + type + " file: "
282             + file.getAbsolutePath() + " [" + harg + "]";
283     while (worker.isAlive())
284     {
285     }
286     while (worker.getOutputReader().ready())
287     {
288       String ln = worker.getOutputReader().readLine();
289       System.out.println(ln);
290     }
291     assertTrue(file.exists(), msg);
292     FileAssert.assertFile(file, msg);
293     FileAssert.assertMinLength(file, expectedMinFileSize);
294     if (worker != null && worker.exit == null)
295     {
296       worker.interrupt();
297       Thread.currentThread().interrupt();
298       worker.process.destroy();
299       // Assert.fail("Jalview did not exit after "
300       // + type
301       // + " generation (try running test again to verify - timeout at "
302       // + SETUP_TIMEOUT + "ms). ["
303       // + harg + "]");
304     }
305     file.delete();
306   }
307
308   @DataProvider(name = "allInputOperationsData")
309   public Object[][] getAllInputParams()
310   {
311     return new Object[][] {
312         // headless mode input operations
313         { "CMD [-color zappo] executed successfully!",
314             "Failed command : -color zappo" },
315         { "CMD [-props test/jalview/io/testProps.jvprops] executed successfully!",
316             "Failed command : -props File" },
317         { "CMD [-sortbytree] executed successfully!",
318             "Failed command : -sortbytree" },
319         { "CMD [-jabaws http://www.compbio.dundee.ac.uk/jabaws] executed successfully!",
320             "Failed command : -jabaws http://www.compbio.dundee.ac.uk/jabaws" },
321         { "CMD [-open examples/uniref50.fa] executed successfully!",
322             "Failed command : -open examples/uniref50.fa" },
323         { "CMD [-nosortbytree] executed successfully!",
324             "Failed command : -nosortbytree" },
325         { "CMD [-features examples/testdata/plantfdx.features]  executed successfully!",
326             "Failed command : -features examples/testdata/plantfdx.features" },
327         { "CMD [-annotations examples/testdata/plantfdx.annotations] executed successfully!",
328             "Failed command : -annotations examples/testdata/plantfdx.annotations" },
329         { "CMD [-tree examples/testdata/uniref50_test_tree] executed successfully!",
330             "Failed command : -tree examples/testdata/uniref50_test_tree" },
331         // non headless mode input operations
332         { "CMD [-nousagestats] executed successfully!",
333             "Failed command : -nousagestats" },
334         { "CMD [-noquestionnaire] executed successfully!",
335             "Failed command : -noquestionnaire" } };
336   }
337
338   @DataProvider(name = "headlessModeOutputOperationsData")
339   public static Object[][] getHeadlessModeOutputParams()
340   {
341     return new Object[][] {
342         // works
343         { "nodisplay -open examples/uniref50.fa", " -eps",
344             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
345             TEST_TIMEOUT },
346         { "nodisplay -open examples/uniref50.fa", " -eps",
347             "test/jalview/bin/test_uniref50_out.eps", false,
348             MINFILESIZE_BIG, TEST_TIMEOUT },
349         { "nogui -open examples/uniref50.fa", " -eps",
350             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
351             TEST_TIMEOUT },
352         { "nogui -open examples/uniref50.fa", " -eps",
353             "test/jalview/bin/test_uniref50_out.eps", false,
354             MINFILESIZE_BIG, TEST_TIMEOUT },
355         { "headless -open examples/uniref50.fa", " -eps",
356             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
357             TEST_TIMEOUT },
358         { "headless -open examples/uniref50.fa", " -svg",
359             "test/jalview/bin/test_uniref50_out.svg", false,
360             MINFILESIZE_BIG, TEST_TIMEOUT },
361         { "headless -open examples/uniref50.fa", " -png",
362             "test/jalview/bin/test_uniref50_out.png", true, MINFILESIZE_BIG,
363             TEST_TIMEOUT },
364         { "headless -open examples/uniref50.fa", " -html",
365             "test/jalview/bin/test_uniref50_out.html", true,
366             MINFILESIZE_BIG, TEST_TIMEOUT },
367         { "headless -open examples/uniref50.fa", " -fasta",
368             "test/jalview/bin/test_uniref50_out.mfa", true,
369             MINFILESIZE_SMALL, TEST_TIMEOUT },
370         { "headless -open examples/uniref50.fa", " -clustal",
371             "test/jalview/bin/test_uniref50_out.aln", true,
372             MINFILESIZE_SMALL, TEST_TIMEOUT },
373         { "headless -open examples/uniref50.fa", " -msf",
374             "test/jalview/bin/test_uniref50_out.msf", true,
375             MINFILESIZE_SMALL, TEST_TIMEOUT },
376         { "headless -open examples/uniref50.fa", " -pileup",
377             "test/jalview/bin/test_uniref50_out.aln", true,
378             MINFILESIZE_SMALL, TEST_TIMEOUT },
379         { "headless -open examples/uniref50.fa", " -pir",
380             "test/jalview/bin/test_uniref50_out.pir", true,
381             MINFILESIZE_SMALL, TEST_TIMEOUT },
382         { "headless -open examples/uniref50.fa", " -pfam",
383             "test/jalview/bin/test_uniref50_out.pfam", true,
384             MINFILESIZE_SMALL, TEST_TIMEOUT },
385         { "headless -open examples/uniref50.fa", " -blc",
386             "test/jalview/bin/test_uniref50_out.blc", true,
387             MINFILESIZE_SMALL, TEST_TIMEOUT },
388         { "headless -open examples/uniref50.fa", " -jalview",
389             "test/jalview/bin/test_uniref50_out.jvp", true,
390             MINFILESIZE_SMALL, TEST_TIMEOUT },
391     };
392   }
393 }