Clover icon

Coverage Report

  1. Project Clover database Fri Nov 1 2024 11:46:37 GMT
  2. Package jalview.bin

File CommandLineOperations.java

 

Coverage histogram

../../img/srcFileCovDistChart8.png
20% of files have more coverage

Code metrics

28
105
18
2
440
357
42
0.4
5.83
9
2.33

Classes

Class Line # Actions
CommandLineOperations 45 97 35
0.781021978.1%
CommandLineOperations.Worker 74 8 7
1.0100%
 

Contributing tests

This file is covered by 1 test. .

Source view

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 java.io.BufferedReader;
27    import java.io.File;
28    import java.io.IOException;
29    import java.io.InputStreamReader;
30    import java.nio.file.Path;
31    import java.nio.file.Paths;
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.DataProvider;
38    import org.testng.annotations.Test;
39   
40    import io.github.classgraph.ClassGraph;
41    import io.github.classgraph.ModuleRef;
42    import io.github.classgraph.ScanResult;
43    import jalview.gui.JvOptionPane;
44   
 
45    public class CommandLineOperations
46    {
47   
 
48  1 toggle @BeforeClass(alwaysRun = true)
49    public void setUpJvOptionPane()
50    {
51  1 JvOptionPane.setInteractiveMode(false);
52  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
53    }
54   
55    // Note longer timeout needed on full test run than on individual tests
56    private static final int TEST_TIMEOUT = 15000;
57   
58    private static final int SETUP_TIMEOUT = 9500;
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    public 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  20 toggle private Worker(Process process)
85    {
86  20 this.process = process;
87    }
88   
 
89  20 toggle @Override
90    public void run()
91    {
92  20 try
93    {
94  20 exit = process.waitFor();
95    } catch (InterruptedException ignore)
96    {
97  1 return;
98    }
99    }
100   
 
101  55 toggle public BufferedReader getOutputReader()
102    {
103  55 return outputReader;
104    }
105   
 
106  20 toggle public void setOutputReader(BufferedReader outputReader)
107    {
108  20 this.outputReader = outputReader;
109    }
110   
 
111  11 toggle public BufferedReader getErrorReader()
112    {
113  11 return errorReader;
114    }
115   
 
116  20 toggle public void setErrorReader(BufferedReader errorReader)
117    {
118  20 this.errorReader = errorReader;
119    }
120    }
121   
122    private static ClassGraph scanner = null;
123   
124    private static String classpath = null;
125   
126    private static String modules = null;
127   
128    private static String java_exe = null;
129   
 
130  20 toggle public synchronized static String getClassPath()
131    {
132  20 if (scanner == null)
133    {
134  2 scanner = new ClassGraph();
135  2 ScanResult scan = scanner.scan();
136  2 classpath = scan.getClasspath();
137  2 modules = "";
138  2 for (ModuleRef mr : scan.getModules())
139    {
140  0 modules.concat(mr.getName());
141    }
142  2 java_exe = System.getProperty("java.home") + File.separator + "bin"
143    + File.separator + "java";
144   
145    }
146  20 while (classpath == null)
147    {
148  0 try
149    {
150  0 Thread.sleep(10);
151    } catch (InterruptedException x)
152    {
153   
154    }
155    }
156  20 return classpath;
157    }
158   
 
159  20 toggle public static Worker getJalviewDesktopRunner(boolean withAwt, String cmd,
160    int timeout)
161    {
162    // Note: JAL-3065 - don't include quotes for lib/* because the arguments are
163    // not expanded by the shell
164  20 String classpath = getClassPath();
165  20 String _cmd = java_exe + " "
166  20 + (withAwt ? "-Djava.awt.headless=true" : "") + " -classpath "
167    + classpath
168  20 + (modules.length() > 2 ? "--add-modules=\"" + modules + "\""
169    : "")
170    + " jalview.bin.Jalview ";
171  20 Process ls2_proc = null;
172  20 Worker worker = null;
173  20 try
174    {
175  20 ls2_proc = Runtime.getRuntime().exec(_cmd + cmd);
176    } catch (Throwable e1)
177    {
178  0 e1.printStackTrace();
179    }
180  20 if (ls2_proc != null)
181    {
182  20 BufferedReader outputReader = new BufferedReader(
183    new InputStreamReader(ls2_proc.getInputStream()));
184  20 BufferedReader errorReader = new BufferedReader(
185    new InputStreamReader(ls2_proc.getErrorStream()));
186  20 worker = new CommandLineOperations.Worker(ls2_proc);
187  20 worker.start();
188  20 try
189    {
190  20 worker.join(timeout);
191    } catch (InterruptedException e)
192    {
193  1 System.err.println("Thread interrupted");
194    }
195  20 worker.setOutputReader(outputReader);
196  20 worker.setErrorReader(errorReader);
197    }
198  20 return worker;
199    }
200   
 
201  1 toggle @Test(groups = { "Functional" })
202    public void reportCurrentWorkingDirectory()
203    {
204  1 try
205    {
206  1 Path currentRelativePath = Paths.get("");
207  1 String s = currentRelativePath.toAbsolutePath().toString();
208  1 System.out.println("Test CWD is " + s);
209    } catch (Exception q)
210    {
211  0 q.printStackTrace();
212    }
213    }
214   
 
215  1 toggle @BeforeClass(alwaysRun = true)
216    public void initialize()
217    {
218  1 new CommandLineOperations();
219    }
220   
 
221  1 toggle @BeforeClass(alwaysRun = true)
222    public void setUpForHeadlessCommandLineInputOperations()
223    throws IOException
224    {
225  1 String cmds = "nodisplay -open examples/uniref50.fa -sortbytree -props test/jalview/bin/testProps.jvprops -colour zappo "
226    + "-jabaws http://www.compbio.dundee.ac.uk/jabaws -nosortbytree "
227    + "-features examples/testdata/plantfdx.features -annotations examples/testdata/plantfdx.annotations -tree examples/testdata/uniref50_test_tree";
228  1 Worker worker = getJalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
229  1 String ln = null;
230  ? while ((ln = worker.getOutputReader().readLine()) != null)
231    {
232  22 System.out.println("STDOUT: " + ln);
233  22 successfulCMDs.add(ln);
234    }
235  ? while ((ln = worker.getErrorReader().readLine()) != null)
236    {
237  9 System.err.println("STDERR: " + ln);
238  9 successfulCMDs.add(ln);
239    }
240    }
241   
 
242  1 toggle @BeforeClass(alwaysRun = true)
243    public void setUpForCommandLineInputOperations() throws IOException
244    {
245  1 String cmds = "-open examples/uniref50.fa -noquestionnaire -nousagestats";
246  1 final Worker worker = getJalviewDesktopRunner(false, cmds,
247    SETUP_TIMEOUT);
248   
249    // number of lines expected on STDERR when Jalview starts up normally
250    // may need to adjust this if Jalview is excessively noisy ?
251  1 final int STDOUT_SETUPLINES = 50;
252  1 final int STDERR_SETUPLINES = 50;
253   
254    // thread monitors stderr - bails after SETUP_TIMEOUT or when
255    // STDERR_SETUPLINES have been read
256  1 Thread runner = new Thread(new Runnable()
257    {
 
258  1 toggle @Override
259    public void run()
260    {
261  1 String ln = null;
262  1 int stdoutcount = 0;
263  1 int stderrcount = 0;
264  1 try
265    {
266  ? while ((ln = worker.getOutputReader().readLine()) != null)
267    {
268  31 System.out.println(ln);
269  31 successfulCMDs.add(ln);
270  31 if (++stdoutcount > STDOUT_SETUPLINES)
271    {
272  0 break;
273    }
274    }
275  ? while ((ln = worker.getErrorReader().readLine()) != null)
276    {
277  0 System.err.println(ln);
278  0 successfulCMDs.add(ln);
279  0 if (++stderrcount > STDERR_SETUPLINES)
280    {
281  0 break;
282    }
283    }
284    } catch (Exception e)
285    {
286  1 System.err.println(
287    "Unexpected Exception reading stderr from the Jalview process");
288  1 e.printStackTrace();
289    }
290    }
291    });
292  1 long t = System.currentTimeMillis() + SETUP_TIMEOUT;
293  1 runner.start();
294  20 while (!runner.isInterrupted() && System.currentTimeMillis() < t)
295    {
296  19 try
297    {
298  19 Thread.sleep(500);
299    } catch (InterruptedException e)
300    {
301    }
302    }
303  1 runner.interrupt();
304  1 if (worker != null && worker.exit == null)
305    {
306  1 worker.interrupt();
307  1 Thread.currentThread().interrupt();
308  1 worker.process.destroy();
309    }
310    }
311   
 
312  11 toggle @Test(groups = { "Functional" }, dataProvider = "allInputOperationsData")
313    public void testAllInputOperations(String expectedString,
314    String failureMsg)
315    {
316  11 Assert.assertTrue(successfulCMDs.contains(expectedString), failureMsg);
317    }
318   
 
319  16 toggle @Test(
320    groups =
321    { "Functional" },
322    dataProvider = "headlessModeOutputOperationsData")
323    public void testHeadlessModeOutputOperations(String harg, String type,
324    String fileName, boolean withAWT, int expectedMinFileSize,
325    int timeout)
326    {
327  16 String cmd = harg + type + " " + fileName;
328    // System.out.println(">>>>>>>>>>>>>>>> Command : " + cmd);
329  16 File file = new File(fileName);
330  16 file.deleteOnExit();
331  16 Worker worker = getJalviewDesktopRunner(withAWT, cmd, timeout);
332  16 assertNotNull(worker, "worker is null");
333  16 String msg = "Didn't create an output" + type + " file.[" + harg + "]";
334  16 assertTrue(file.exists(), msg);
335  16 FileAssert.assertFile(file, msg);
336  16 FileAssert.assertMinLength(file, expectedMinFileSize);
337  16 if (worker != null && worker.exit == null)
338    {
339  0 worker.interrupt();
340  0 Thread.currentThread().interrupt();
341  0 worker.process.destroy();
342  0 Assert.fail("Jalview did not exit after " + type
343    + " generation (try running test again to verify - timeout at "
344    + timeout + "ms). [" + harg + "]");
345    }
346  16 file.delete();
347    }
348   
 
349  1 toggle @DataProvider(name = "allInputOperationsData")
350    public Object[][] getHeadlessModeInputParams()
351    {
352  1 return new Object[][] {
353    // headless mode input operations
354    { "CMD [-colour zappo] executed successfully!",
355    "Failed command : -colour zappo" },
356    { "CMD [-props test/jalview/bin/testProps.jvprops] executed successfully!",
357    "Failed command : -props File" },
358    { "CMD [-sortbytree] executed successfully!",
359    "Failed command : -sortbytree" },
360    { "CMD [-jabaws http://www.compbio.dundee.ac.uk/jabaws] executed successfully!",
361    "Failed command : -jabaws http://www.compbio.dundee.ac.uk/jabaws" },
362    { "CMD [-open examples/uniref50.fa] executed successfully!",
363    "Failed command : -open examples/uniref50.fa" },
364    { "CMD [-nosortbytree] executed successfully!",
365    "Failed command : -nosortbytree" },
366    { "CMD [-features examples/testdata/plantfdx.features] executed successfully!",
367    "Failed command : -features examples/testdata/plantfdx.features" },
368    { "CMD [-annotations examples/testdata/plantfdx.annotations] executed successfully!",
369    "Failed command : -annotations examples/testdata/plantfdx.annotations" },
370    { "CMD [-tree examples/testdata/uniref50_test_tree] executed successfully!",
371    "Failed command : -tree examples/testdata/uniref50_test_tree" },
372    // non headless mode input operations
373    { "CMD [-nousagestats] executed successfully!",
374    "Failed command : -nousagestats" },
375    { "CMD [-noquestionnaire] executed successfully!",
376    "Failed command : -noquestionnaire" } };
377    }
378   
 
379  1 toggle @DataProvider(name = "headlessModeOutputOperationsData")
380    public static Object[][] getHeadlessModeOutputParams()
381    {
382    // JBPNote: I'm not clear why need to specify full path for output file
383    // when running tests on build server, but we will keep this patch for now
384    // since it works.
385    // https://issues.jalview.org/browse/JAL-1889?focusedCommentId=21609&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-21609
386  1 String workingDir = "test/jalview/bin/";
387  1 return new Object[][] {
388    //
389    { "nodisplay -open examples/uniref50.fa", " -eps",
390    workingDir + "test_uniref50_out.eps", true, MINFILESIZE_BIG,
391    TEST_TIMEOUT },
392    { "nodisplay -open examples/uniref50.fa", " -eps",
393    workingDir + "test_uniref50_out.eps", false, MINFILESIZE_BIG,
394    TEST_TIMEOUT },
395    { "nogui -open examples/uniref50.fa", " -eps",
396    workingDir + "test_uniref50_out.eps", true, MINFILESIZE_BIG,
397    TEST_TIMEOUT },
398    { "nogui -open examples/uniref50.fa", " -eps",
399    workingDir + "test_uniref50_out.eps", false, MINFILESIZE_BIG,
400    TEST_TIMEOUT },
401    { "headless -open examples/uniref50.fa", " -eps",
402    workingDir + "test_uniref50_out.eps", true, MINFILESIZE_BIG,
403    TEST_TIMEOUT },
404    { "headless -open examples/uniref50.fa", " -svg",
405    workingDir + "test_uniref50_out.svg", false, MINFILESIZE_BIG,
406    TEST_TIMEOUT },
407    { "headless -open examples/uniref50.fa", " -png",
408    workingDir + "test_uniref50_out.png", true, MINFILESIZE_BIG,
409    TEST_TIMEOUT },
410    { "headless -open examples/uniref50.fa", " -html",
411    workingDir + "test_uniref50_out.html", true, MINFILESIZE_BIG,
412    TEST_TIMEOUT },
413    { "headless -open examples/uniref50.fa", " -fasta",
414    workingDir + "test_uniref50_out.mfa", true, MINFILESIZE_SMALL,
415    TEST_TIMEOUT },
416    { "headless -open examples/uniref50.fa", " -clustal",
417    workingDir + "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
418    TEST_TIMEOUT },
419    { "headless -open examples/uniref50.fa", " -msf",
420    workingDir + "test_uniref50_out.msf", true, MINFILESIZE_SMALL,
421    TEST_TIMEOUT },
422    { "headless -open examples/uniref50.fa", " -pileup",
423    workingDir + "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
424    TEST_TIMEOUT },
425    { "headless -open examples/uniref50.fa", " -pir",
426    workingDir + "test_uniref50_out.pir", true, MINFILESIZE_SMALL,
427    TEST_TIMEOUT },
428    { "headless -open examples/uniref50.fa", " -pfam",
429    workingDir + "test_uniref50_out.pfam", true, MINFILESIZE_SMALL,
430    TEST_TIMEOUT },
431    { "headless -open examples/uniref50.fa", " -blc",
432    workingDir + "test_uniref50_out.blc", true, MINFILESIZE_SMALL,
433    TEST_TIMEOUT },
434    { "headless -open examples/uniref50.fa", " -jalview",
435    workingDir + "test_uniref50_out.jvp", true, MINFILESIZE_SMALL,
436    TEST_TIMEOUT },
437    //
438    };
439    }
440    }