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