Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.bin

File CommandLineOperations.java

 

Coverage histogram

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

Code metrics

32
114
18
2
471
388
47
0.41
6.33
9
2.61

Classes

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