Clover icon

Coverage Report

  1. Project Clover database Wed Nov 13 2024 16:12:26 GMT
  2. Package jalview.bin

File CommandLineOperationsNG.java

 

Coverage histogram

../../img/srcFileCovDistChart9.png
13% of files have more coverage

Code metrics

28
116
21
2
537
421
48
0.41
5.52
10.5
2.29

Classes

Class Line # Actions
CommandLineOperationsNG 47 108 41
0.8145695381.5%
CommandLineOperationsNG.Worker 76 8 7
1.0100%
 

Contributing tests

No tests hitting this source file were found.

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.Files;
31    import java.nio.file.Path;
32    import java.nio.file.Paths;
33    import java.util.ArrayList;
34    import java.util.List;
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   
 
47    public class CommandLineOperationsNG
48    {
49   
 
50  1 toggle @BeforeClass(alwaysRun = true)
51    public void setUpJvOptionPane()
52    {
53  1 JvOptionPane.setInteractiveMode(false);
54  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
55    }
56   
57    // Note longer timeout needed on full test run than on individual tests
58    private static final int TEST_TIMEOUT = 13000;
59   
60    private static final int SETUP_TIMEOUT = 9500;
61   
62    private static final int MINFILESIZE_SMALL = 2096;
63   
64    private static final int MINFILESIZE_BIG = 4096;
65   
66    private List<String> successfulCMDs = new ArrayList<>();
67   
68    /***
69    * from
70    * http://stackoverflow.com/questions/808276/how-to-add-a-timeout-value-when
71    * -using-javas-runtime-exec
72    *
73    * @author jimp
74    *
75    */
 
76    private static class Worker extends Thread
77    {
78    private final Process process;
79   
80    private BufferedReader outputReader;
81   
82    private BufferedReader errorReader;
83   
84    private Integer exit;
85   
 
86  26 toggle private Worker(Process process)
87    {
88  26 this.process = process;
89    }
90   
 
91  26 toggle @Override
92    public void run()
93    {
94  26 try
95    {
96  26 exit = process.waitFor();
97    } catch (InterruptedException ignore)
98    {
99  1 return;
100    }
101    }
102   
 
103  18944 toggle public BufferedReader getOutputReader()
104    {
105  18944 return outputReader;
106    }
107   
 
108  26 toggle public void setOutputReader(BufferedReader outputReader)
109    {
110  26 this.outputReader = outputReader;
111    }
112   
 
113  6 toggle public BufferedReader getErrorReader()
114    {
115  6 return errorReader;
116    }
117   
 
118  26 toggle public void setErrorReader(BufferedReader errorReader)
119    {
120  26 this.errorReader = errorReader;
121    }
122    }
123   
124    private static ClassGraph scanner = null;
125   
126    private static String classpath = null;
127   
128    private static String modules = null;
129   
130    private static String java_exe = null;
131   
 
132  26 toggle public synchronized static String getClassPath()
133    {
134  26 if (scanner == null)
135    {
136  1 scanner = new ClassGraph();
137  1 ScanResult scan = scanner.scan();
138  1 classpath = scan.getClasspath();
139  1 modules = "";
140  1 for (ModuleRef mr : scan.getModules())
141    {
142  0 modules.concat(mr.getName());
143    }
144  1 java_exe = System.getProperty("java.home") + File.separator + "bin"
145    + File.separator + "java";
146   
147    }
148   
149  26 while (classpath == null)
150    {
151  0 try
152    {
153  0 Thread.sleep(10);
154    } catch (InterruptedException x)
155    {
156   
157    }
158    }
159  26 return classpath;
160    }
161   
 
162  18 toggle private Worker getJalviewDesktopRunner(boolean withAwt, String cmd,
163    int timeout)
164    {
165  18 return getJalviewDesktopRunner(withAwt, cmd, timeout, true);
166    }
167   
 
168  26 toggle private Worker getJalviewDesktopRunner(boolean withAwt, String cmd,
169    int timeout, boolean testoutput)
170    {
171    /*
172    boolean win = System.getProperty("os.name").indexOf("Win") >= 0;
173    String pwd = "";
174    try
175    {
176    Path currentRelativePath = Paths.get("");
177    pwd = currentRelativePath.toAbsolutePath().toString();
178    } catch (Exception q)
179    {
180    q.printStackTrace();
181    }
182    if (pwd == null || pwd.length() == 0)
183    pwd = ".";
184    String[] classpaths = new String[] { pwd + "/bin/main",
185    pwd + "/j11lib/*", pwd + "/resources", pwd + "/help" };
186    String classpath = String.join(win ? ";" : ":", classpaths);
187    getClassPath();
188    */
189    // Note: JAL-3065 - don't include quotes for lib/* because the arguments are
190    // not expanded by the shell
191  26 String classpath = getClassPath();
192  26 String _cmd = java_exe + " "
193  26 + (withAwt ? "-Djava.awt.headless=true" : "") + " -classpath "
194    + classpath
195  26 + ((modules != null && modules.length() > 2)
196    ? "--add-modules=\"" + modules + "\""
197    : "")
198    + " jalview.bin.Jalview ";
199  26 Process ls2_proc = null;
200  26 Worker worker = null;
201  26 try
202    {
203  26 cmd = cmd + (testoutput ? " --testoutput " : "");
204  26 System.out.println("Running '" + _cmd + cmd + "'");
205  26 ls2_proc = Runtime.getRuntime().exec(_cmd + cmd);
206    } catch (Throwable e1)
207    {
208  0 e1.printStackTrace();
209    }
210  26 if (ls2_proc != null)
211    {
212  26 BufferedReader outputReader = new BufferedReader(
213    new InputStreamReader(ls2_proc.getInputStream()));
214  26 BufferedReader errorReader = new BufferedReader(
215    new InputStreamReader(ls2_proc.getErrorStream()));
216  26 worker = new Worker(ls2_proc);
217  26 worker.start();
218  26 try
219    {
220  26 worker.join(timeout);
221    } catch (InterruptedException e)
222    {
223  1 System.err.println("Thread interrupted");
224    }
225  26 worker.setOutputReader(outputReader);
226  26 worker.setErrorReader(errorReader);
227    }
228  26 return worker;
229    }
230   
 
231  1 toggle @Test(groups = { "Functional", "testTask1" })
232    public void reportCurrentWorkingDirectory()
233    {
234  1 try
235    {
236  1 Path currentRelativePath = Paths.get("");
237  1 String s = currentRelativePath.toAbsolutePath().toString();
238  1 System.out.println("Test CWD is " + s);
239    } catch (Exception q)
240    {
241  0 q.printStackTrace();
242    }
243    }
244   
 
245  1 toggle @BeforeClass(alwaysRun = true)
246    public void initialize()
247    {
248  1 new CommandLineOperationsNG();
249    }
250   
 
251  1 toggle @BeforeClass(alwaysRun = true)
252    public void setUpForHeadlessCommandLineInputOperations()
253    throws IOException
254    {
255  1 String cmds = "--headless " + "--open examples/uniref50.fa "
256    + "--sortbytree "
257    + "--props test/jalview/bin/testProps.jvprops "
258    + "--colour zappo "
259    + "--jabaws http://www.compbio.dundee.ac.uk/jabaws "
260    + "--features examples/testdata/plantfdx.features "
261    + "--annotations examples/testdata/plantfdx.annotations "
262    + "--tree examples/testdata/uniref50_test_tree "
263    + "--nousagestats ";
264  1 Worker worker = getJalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
265  1 String ln = null;
266  ? while ((ln = worker.getOutputReader().readLine()) != null)
267    {
268  23 System.out.println(ln);
269  23 successfulCMDs.add(ln);
270    }
271  ? while ((ln = worker.getErrorReader().readLine()) != null)
272    {
273  5 System.err.println(ln);
274    }
275    }
276   
 
277  1 toggle @BeforeClass(alwaysRun = true)
278    public void setUpForCommandLineInputOperations() throws IOException
279    {
280  1 String cmds = "--open examples/uniref50.fa --noquestionnaire --nousagestats";
281  1 final Worker worker = getJalviewDesktopRunner(false, cmds,
282    SETUP_TIMEOUT);
283   
284    // number of lines expected on STDERR when Jalview starts up normally
285    // may need to adjust this if Jalview is excessively noisy ?
286  1 final int STDERR_SETUPLINES = 50;
287   
288    // thread monitors stderr - bails after SETUP_TIMEOUT or when
289    // STDERR_SETUPLINES have been read
290  1 Thread runner = new Thread(new Runnable()
291    {
 
292  1 toggle @Override
293    public void run()
294    {
295  1 String ln = null;
296  1 int count = 0;
297  1 try
298    {
299  ? while ((ln = worker.getOutputReader().readLine()) != null)
300    {
301  33 System.out.println(ln);
302  33 successfulCMDs.add(ln);
303  33 if (++count > STDERR_SETUPLINES)
304    {
305  0 break;
306    }
307    }
308    } catch (Exception e)
309    {
310  0 System.err.println(
311    "Unexpected Exception reading stderr from the Jalview process");
312  0 e.printStackTrace();
313    }
314    }
315    });
316  1 long t = System.currentTimeMillis() + SETUP_TIMEOUT;
317  1 runner.start();
318  20 while (!runner.isInterrupted() && System.currentTimeMillis() < t)
319    {
320  19 try
321    {
322  19 Thread.sleep(500);
323    } catch (InterruptedException e)
324    {
325    }
326    }
327  1 runner.interrupt();
328  1 if (worker != null && worker.exit == null)
329    {
330  1 worker.interrupt();
331  1 Thread.currentThread().interrupt();
332  1 worker.process.destroy();
333    }
334    }
335   
 
336  10 toggle @Test(
337    groups =
338    { "Functional", "testTask1" },
339    dataProvider = "allInputOperationsData")
340    public void testAllInputOperations(String expectedString,
341    String failureMsg)
342    {
343  10 Assert.assertTrue(successfulCMDs.contains(expectedString),
344    failureMsg + "; was expecting '" + expectedString + "'");
345    }
346   
 
347  16 toggle @Test(
348    groups =
349    { "Functional", "testTask1" },
350    dataProvider = "headlessModeOutputOperationsData")
351    public void testHeadlessModeOutputOperations(String harg, String type,
352    String fileName, boolean withAWT, int expectedMinFileSize,
353    int timeout)
354    {
355  16 String cmd = harg + type + " " + fileName;
356    // System.out.println(">>>>>>>>>>>>>>>> Command : " + cmd);
357  16 File file = new File(fileName);
358  16 file.deleteOnExit();
359  16 Worker worker = getJalviewDesktopRunner(withAWT, cmd, timeout);
360  16 assertNotNull(worker, "worker is null");
361  16 String msg = "Didn't create an output" + type + " file '" + fileName
362    + "'. [" + cmd + "]";
363  16 assertTrue(file.exists(), msg);
364  16 FileAssert.assertFile(file, msg);
365  16 FileAssert.assertMinLength(file, expectedMinFileSize);
366  16 if (worker != null && worker.exit == null)
367    {
368  0 worker.interrupt();
369  0 Thread.currentThread().interrupt();
370  0 worker.process.destroy();
371  0 Assert.fail("Jalview did not exit after " + type
372    + " generation (try running test again to verify - timeout at "
373    + timeout + "ms). [" + harg + "]");
374    }
375  16 file.delete();
376    }
377   
 
378  8 toggle @Test(
379    groups =
380    { "Functional", "testTask1" },
381    dataProvider = "headlessModeOutputToStdout")
382    public void testHeadlessModeOutputToStdout(String args,
383    String comparisonFile, int timeout)
384    {
385  8 String cmd = args;
386  8 File file = new File(comparisonFile);
387  8 Worker worker = getJalviewDesktopRunner(true, cmd, timeout, false);
388  8 int b = -1;
389  8 StringBuilder sb = new StringBuilder();
390  8 try
391    {
392  ? while ((b = worker.getOutputReader().read()) != -1)
393    {
394  18878 sb.append(Character.toChars(b));
395    }
396    } catch (IOException e)
397    {
398  0 Assert.fail("IOException whilst trying to read from jalview process");
399    }
400   
401  8 String comparisonContent = null;
402  8 try
403    {
404  8 comparisonContent = new String(Files.readAllBytes(file.toPath()));
405    } catch (IOException e)
406    {
407  0 Assert.fail("IOException whilst trying to read comparison file");
408    }
409   
410  8 Assert.assertEquals(sb.toString(), comparisonContent,
411    "STDOUT from jalview command did not match the comparison file");
412    }
413   
 
414  1 toggle @DataProvider(name = "allInputOperationsData")
415    public Object[][] getHeadlessModeInputParams()
416    {
417  1 return new Object[][] {
418    // headless mode input operations
419    { "[TESTOUTPUT] arg --colour='zappo' was set",
420    "Failed setting arg --colour" },
421    { "[TESTOUTPUT] arg --props='test/jalview/bin/testProps.jvprops' was set",
422    "Failed setting arg --props" },
423    { "[TESTOUTPUT] arg --sortbytree was set",
424    "Failed setting arg --sortbytree" },
425    { "[TESTOUTPUT] arg --jabaws='http://www.compbio.dundee.ac.uk/jabaws' was set",
426    "Failed setting arg --jabaws" },
427    { "[TESTOUTPUT] arg --open='examples/uniref50.fa' was set",
428    "Failed setting arg --open" },
429    { "[TESTOUTPUT] arg --features='examples/testdata/plantfdx.features' was set",
430    "Failed setting arg --features" },
431    { "[TESTOUTPUT] arg --annotations='examples/testdata/plantfdx.annotations' was set",
432    "Failed setting arg --annotations" },
433    { "[TESTOUTPUT] arg --tree='examples/testdata/uniref50_test_tree' was set",
434    "Failed setting arg --tree" },
435    // non headless mode input operations
436    { "[TESTOUTPUT] arg --nousagestats was set",
437    "Failed setting arg --nousagestats" },
438    { "[TESTOUTPUT] arg --noquestionnaire was set",
439    "Failed setting arg --noquestionnaire" }
440    //
441    };
442    }
443   
 
444  1 toggle @DataProvider(name = "headlessModeOutputOperationsData")
445    public static Object[][] getHeadlessModeOutputParams()
446    {
447    // JBPNote: I'm not clear why need to specify full path for output file
448    // when running tests on build server, but we will keep this patch for now
449    // since it works.
450    // https://issues.jalview.org/browse/JAL-1889?focusedCommentId=21609&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-21609
451  1 String workingDir = "test/jalview/bin/";
452  1 return new Object[][] {
453    //
454    { "--headless --open examples/uniref50.fa", " --image",
455    workingDir + "test_uniref50_out.eps", true, MINFILESIZE_BIG,
456    TEST_TIMEOUT },
457    { "--headless --open examples/uniref50.fa", " --image",
458    workingDir + "test_uniref50_out.eps", false, MINFILESIZE_BIG,
459    TEST_TIMEOUT },
460    { "--headless --open examples/uniref50.fa", " --image",
461    workingDir + "test_uniref50_out.eps", true, MINFILESIZE_BIG,
462    TEST_TIMEOUT },
463    { "--headless --open examples/uniref50.fa", " --image",
464    workingDir + "test_uniref50_out.eps", false, MINFILESIZE_BIG,
465    TEST_TIMEOUT },
466    { "--headless --open examples/uniref50.fa", " --image",
467    workingDir + "test_uniref50_out.eps", true, MINFILESIZE_BIG,
468    TEST_TIMEOUT },
469    { "--headless --open examples/uniref50.fa", " --image",
470    workingDir + "test_uniref50_out.svg", false, MINFILESIZE_BIG,
471    TEST_TIMEOUT },
472    { "--headless --open examples/uniref50.fa", " --image",
473    workingDir + "test_uniref50_out.png", true, MINFILESIZE_BIG,
474    TEST_TIMEOUT },
475    { "--headless --open examples/uniref50.fa", " --image",
476    workingDir + "test_uniref50_out.html", true, MINFILESIZE_BIG,
477    TEST_TIMEOUT },
478    { "--headless --open examples/uniref50.fa", " --output",
479    workingDir + "test_uniref50_out.mfa", true, MINFILESIZE_SMALL,
480    TEST_TIMEOUT },
481    { "--headless --open examples/uniref50.fa", " --output",
482    workingDir + "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
483    TEST_TIMEOUT },
484    { "--headless --open examples/uniref50.fa", " --output",
485    workingDir + "test_uniref50_out.msf", true, MINFILESIZE_SMALL,
486    TEST_TIMEOUT },
487    { "--headless --open examples/uniref50.fa", " --output",
488    workingDir + "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
489    TEST_TIMEOUT },
490    { "--headless --open examples/uniref50.fa", " --output",
491    workingDir + "test_uniref50_out.pir", true, MINFILESIZE_SMALL,
492    TEST_TIMEOUT },
493    { "--headless --open examples/uniref50.fa", " --output",
494    workingDir + "test_uniref50_out.pfam", true, MINFILESIZE_SMALL,
495    TEST_TIMEOUT },
496    { "--headless --open examples/uniref50.fa", " --output",
497    workingDir + "test_uniref50_out.blc", true, MINFILESIZE_SMALL,
498    TEST_TIMEOUT },
499    { "--headless --open examples/uniref50.fa", " --output",
500    workingDir + "test_uniref50_out.jvp", true, MINFILESIZE_SMALL,
501    TEST_TIMEOUT },
502    //
503    };
504    }
505   
 
506  1 toggle @DataProvider(name = "headlessModeOutputToStdout")
507    public static Object[][] getHeadlessModeOutputToStdout()
508    {
509    // JBPNote: I'm not clear why need to specify full path for output file
510    // when running tests on build server, but we will keep this patch for now
511    // since it works.
512    // https://issues.jalview.org/browse/JAL-1889?focusedCommentId=21609&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-21609
513  1 String workingDir = "test/jalview/bin";
514  1 return new Object[][] {
515    //
516    { "--open=examples/uniref50.fa --output=-",
517    workingDir + "/uniref50-output.fa", TEST_TIMEOUT },
518    { "--open examples/uniref50.fa --output -",
519    workingDir + "/uniref50-output.fa", TEST_TIMEOUT },
520    { "--open examples/uniref50.fa --output=[format=blc]-",
521    workingDir + "/uniref50-output.blc", TEST_TIMEOUT },
522    { "--open examples/uniref50.fa --output - --format blc",
523    workingDir + "/uniref50-output.blc", TEST_TIMEOUT },
524    { "./examples/uniref50.fa --output=-",
525    workingDir + "/uniref50-output.fa", TEST_TIMEOUT },
526    { "./examples/uniref50.fa --output - --format blc",
527    workingDir + "/uniref50-output.blc", TEST_TIMEOUT },
528    // remember you can't use shell wildcards for filenames in a test
529    { "./test/jalview/bin/argparser/testfiles/test1.fa ./test/jalview/bin/argparser/testfiles/test2.fa ./test/jalview/bin/argparser/testfiles/test3.fa --all --output -",
530    workingDir + "/test1-3.fa", TEST_TIMEOUT },
531    // but you can use java wildcards when using an equals sign
532    { "--open=./test/jalview/bin/argparser/testfiles/test*.fa --all --output -",
533    workingDir + "/test1-3.fa", TEST_TIMEOUT },
534    //
535    };
536    }
537    }