Merge branch 'develop' into task/JAL-3130_Java_11_investigations-getdown_src
[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
55                                                 // 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 " + (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.start();
173       try
174       {
175         worker.join(timeout);
176       } catch (InterruptedException e)
177       {
178         System.err.println("Thread interrupted");
179       }
180       worker.setOutputReader(outputReader);
181       worker.setErrorReader(errorReader);
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     Worker worker = getJalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
200     String ln = null;
201     while ((ln = worker.getOutputReader().readLine()) != null)
202     {
203       System.out.println(ln);
204       successfulCMDs.add(ln);
205     }
206     while ((ln = worker.getErrorReader().readLine()) != null)
207     {
208       System.err.println(ln);
209     }
210   }
211
212   @BeforeTest(alwaysRun = true)
213   public void setUpForCommandLineInputOperations() throws IOException
214   {
215     String cmds = "-open examples/uniref50.fa -noquestionnaire -nousagestats";
216     Worker worker = getJalviewDesktopRunner(false, cmds, SETUP_TIMEOUT);
217     String ln = null;
218     int count = 0;
219     while ((ln = worker.getErrorReader().readLine()) != null)
220     {
221       System.out.println(ln);
222       successfulCMDs.add(ln);
223       if (++count > 5)
224       {
225         break;
226       }
227     }
228     if (worker != null && worker.exit == null)
229     {
230       worker.interrupt();
231       Thread.currentThread().interrupt();
232       worker.process.destroy();
233     }
234   }
235
236   @Test(groups = { "Functional" }, dataProvider = "allInputOperationsData")
237   public void testAllInputOperations(String expectedString,
238           String failureMsg)
239   {
240     Assert.assertTrue(successfulCMDs.contains(expectedString), failureMsg);
241   }
242
243   @Test(
244     groups =
245     { "Functional", "testben" },
246     dataProvider = "headlessModeOutputOperationsData")
247   public void testHeadlessModeOutputOperations(String harg, String type,
248           String fileName, boolean withAWT, int expectedMinFileSize,
249           int timeout)
250   {
251     String cmd = harg + type + " " + fileName;
252     // System.out.println(">>>>>>>>>>>>>>>> Command : " + cmd);
253     File file = new File(fileName);
254     file.deleteOnExit();
255     Worker worker = getJalviewDesktopRunner(withAWT, cmd, timeout);
256     assertNotNull(worker, "worker is null");
257     String msg = "Didn't create an output" + type + " file.[" + harg + "]";
258     assertTrue(file.exists(), msg);
259     FileAssert.assertFile(file, msg);
260     FileAssert.assertMinLength(file, expectedMinFileSize);
261     if (worker != null && worker.exit == null)
262     {
263       worker.interrupt();
264       Thread.currentThread().interrupt();
265       worker.process.destroy();
266       Assert.fail("Jalview did not exit after " + type
267               + " generation (try running test again to verify - timeout at "
268               + timeout + "ms). [" + harg + "]");
269     }
270     file.delete();
271   }
272
273   @DataProvider(name = "allInputOperationsData")
274   public Object[][] getHeadlessModeInputParams()
275   {
276     return new Object[][] {
277         // headless mode input operations
278         { "CMD [-color zappo] executed successfully!",
279             "Failed command : -color zappo" },
280         { "CMD [-props test/jalview/io/testProps.jvprops] executed successfully!",
281             "Failed command : -props File" },
282         { "CMD [-sortbytree] executed successfully!",
283             "Failed command : -sortbytree" },
284         { "CMD [-jabaws http://www.compbio.dundee.ac.uk/jabaws] executed successfully!",
285             "Failed command : -jabaws http://www.compbio.dundee.ac.uk/jabaws" },
286         { "CMD [-open examples/uniref50.fa] executed successfully!",
287             "Failed command : -open examples/uniref50.fa" },
288         { "CMD [-nosortbytree] executed successfully!",
289             "Failed command : -nosortbytree" },
290         { "CMD [-features examples/testdata/plantfdx.features]  executed successfully!",
291             "Failed command : -features examples/testdata/plantfdx.features" },
292         { "CMD [-annotations examples/testdata/plantfdx.annotations] executed successfully!",
293             "Failed command : -annotations examples/testdata/plantfdx.annotations" },
294         { "CMD [-tree examples/testdata/uniref50_test_tree] executed successfully!",
295             "Failed command : -tree examples/testdata/uniref50_test_tree" },
296         // non headless mode input operations
297         { "CMD [-nousagestats] executed successfully!",
298             "Failed command : -nousagestats" },
299         { "CMD [-noquestionnaire] executed successfully!",
300             "Failed command : -noquestionnaire" } };
301   }
302
303   @DataProvider(name = "headlessModeOutputOperationsData")
304   public static Object[][] getHeadlessModeOutputParams()
305   {
306     return new Object[][] { { "nodisplay -open examples/uniref50.fa",
307         " -eps", "test/jalview/bin/test_uniref50_out.eps", true,
308         MINFILESIZE_BIG, TEST_TIMEOUT },
309         { "nodisplay -open examples/uniref50.fa", " -eps",
310             "test/jalview/bin/test_uniref50_out.eps", false,
311             MINFILESIZE_BIG, TEST_TIMEOUT },
312         { "nogui -open examples/uniref50.fa", " -eps",
313             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
314             TEST_TIMEOUT },
315         { "nogui -open examples/uniref50.fa", " -eps",
316             "test/jalview/bin/test_uniref50_out.eps", false,
317             MINFILESIZE_BIG, TEST_TIMEOUT },
318         { "headless -open examples/uniref50.fa", " -eps",
319             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
320             TEST_TIMEOUT },
321         { "headless -open examples/uniref50.fa", " -svg",
322             "test/jalview/bin/test_uniref50_out.svg", false,
323             MINFILESIZE_BIG, TEST_TIMEOUT },
324         { "headless -open examples/uniref50.fa", " -png",
325             "test/jalview/bin/test_uniref50_out.png", true, MINFILESIZE_BIG,
326             TEST_TIMEOUT },
327         { "headless -open examples/uniref50.fa", " -html",
328             "test/jalview/bin/test_uniref50_out.html", true,
329             MINFILESIZE_BIG, TEST_TIMEOUT },
330         { "headless -open examples/uniref50.fa", " -fasta",
331             "test_uniref50_out.mfa", true, MINFILESIZE_SMALL,
332             TEST_TIMEOUT },
333         { "headless -open examples/uniref50.fa", " -clustal",
334             "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
335             TEST_TIMEOUT },
336         { "headless -open examples/uniref50.fa", " -msf",
337             "test_uniref50_out.msf", true, MINFILESIZE_SMALL,
338             TEST_TIMEOUT },
339         { "headless -open examples/uniref50.fa", " -pileup",
340             "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
341             TEST_TIMEOUT },
342         { "headless -open examples/uniref50.fa", " -pir",
343             "test_uniref50_out.pir", true, MINFILESIZE_SMALL,
344             TEST_TIMEOUT },
345         { "headless -open examples/uniref50.fa", " -pfam",
346             "test_uniref50_out.pfam", true, MINFILESIZE_SMALL,
347             TEST_TIMEOUT },
348         { "headless -open examples/uniref50.fa", " -blc",
349             "test_uniref50_out.blc", true, MINFILESIZE_SMALL,
350             TEST_TIMEOUT },
351         { "headless -open examples/uniref50.fa", " -jalview",
352             "test_uniref50_out.jvp", true, MINFILESIZE_SMALL,
353             TEST_TIMEOUT }, };
354   }
355 }