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