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