/*
* Copyright (C) 2013 SeqWare
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.seqware.pipeline.plugins;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import net.sourceforge.seqware.common.util.Log;
import net.sourceforge.seqware.common.util.filetools.FileTools;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.junit.Assert;
/**
*
* @author dyuen
*/
public class ITUtility {
public static String runSeqwareCLI(String parameters, int expectedReturnValue, File workingDir) throws IOException {
return runSeqwareCLI(parameters, expectedReturnValue, workingDir, null);
}
/**
* Run the new SeqWare simplified command-line script given a particular set of parameters and check for an expected return value.
*
* @param parameters
* @param expectedReturnValue
* this will be checked via a JUnit assert
* @param workingDir
* @param environment
* @return
* @throws IOException
*/
public static String runSeqwareCLI(String parameters, int expectedReturnValue, File workingDir, Map environment) throws IOException {
File script = retrieveCompiledSeqwareScript();
script.setExecutable(true);
if (workingDir == null) {
workingDir = Files.createTempDir();
workingDir.deleteOnExit();
}
String line = "bash " + script.getAbsolutePath() + " " + parameters;
String output = runArbitraryCommand(line, expectedReturnValue, workingDir, environment);
return output;
}
/**
* Run the SeqWare jar given a particular set of parameters and check for an expected return value.
*
* The beauty of this approach is that we can later move this out into its own class, create an interface, and then we can reuse the
* same tests running against our code directly rather than through a jar, so we can compute code coverage and the like.
*
* @param parameters
* @param expectedReturnValue
* @param workingDir
* null, if caller does not care about the working directory
* @return
* @throws IOException
*/
public static String runSeqWareJar(String parameters, int expectedReturnValue, File workingDir) throws IOException {
File jar = retrieveFullAssembledJar();
// this might be uncommented if we go to the extent of coverage analysis for extended tests
// Properties props = new Properties();
// props.load(ITUtility.class.getClassLoader().getResourceAsStream("project.properties"));
// String itCoverageAgent = (String) props.get("itCoverageAgent");
if (workingDir == null) {
workingDir = Files.createTempDir();
workingDir.deleteOnExit();
}
// String line = "java " + itCoverageAgent + " -jar " + jar.getAbsolutePath() + " " + parameters;
String line = "java -jar " + jar.getAbsolutePath() + " " + parameters;
String output = runArbitraryCommand(line, expectedReturnValue, workingDir);
return output;
}
/**
*
* @param seqTargetDir
* the value of seqTargetDir
*/
private static File searchForFullJar(File seqTargetDir) {
File targetFullJar = null;
if (!seqTargetDir.exists()) {
throw new RuntimeException(seqTargetDir.getAbsolutePath() + " does not exist!");
}
for (File files : seqTargetDir.listFiles()) {
if (files.getName().contains("full") && !files.getName().contains("-qe-")) {
targetFullJar = files;
}
}
return targetFullJar;
}
private static boolean isRootOfSeqWare(File workingDirectory) {
String[] list = workingDirectory.list();
for (String file : list) {
if (file.contains("seqware-distribution")) {
return true;
}
}
return false;
}
/**
* This is the hackiest hack in the universe of hacks for getting the final assembly jar so I can run tests.
*
* There has got to be a better way of getting the path of the assembled jar via maven properties or some such. But I really need
* something to help me run tests on production bundles
*
* @return
*/
protected static File retrieveFullAssembledJar() {
String workingDir = System.getProperty("user.dir");
File workingDirectory = new File(workingDir);
File targetFullJar = searchForFullJar(workingDirectory);
if (targetFullJar != null) {
return targetFullJar;
}
while (!isRootOfSeqWare(workingDirectory)) {
workingDirectory = workingDirectory.getParentFile();
}
File seqDistDir = new File(workingDirectory, "seqware-distribution");
File seqTargetDir = new File(seqDistDir, "target");
targetFullJar = searchForFullJar(seqTargetDir);
return targetFullJar;
}
public static String runArbitraryCommand(String line, int expectedReturnValue, File dir) throws IOException {
return runArbitraryCommand(line, expectedReturnValue, dir, null);
}
/**
* Run an arbitrary command and check it against an expected return value
*
* @param line
* @param expectedReturnValue
* @param dir
* working directory, can be null if you don't want to change directories
* @param environment
* @return
* @throws IOException
*/
public static String runArbitraryCommand(String line, int expectedReturnValue, File dir, Map environment) throws IOException {
Log.info("Running " + line);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CommandLine commandline = CommandLine.parse(line);
DefaultExecutor exec = new DefaultExecutor();
if (dir != null) {
exec.setWorkingDirectory(dir);
}
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
exec.setStreamHandler(streamHandler);
exec.setExitValue(expectedReturnValue);
try {
int exitValue = exec.execute(commandline, environment);
Assert.assertTrue("exit value for full jar with no params should be " + expectedReturnValue + " was " + exitValue,
exitValue == expectedReturnValue);
String output = outputStream.toString();
return output;
} catch (ExecuteException e) {
Log.error("Execution failed with:");
Log.error(outputStream.toString());
throw e;
}
}
private static final Pattern SWID = Pattern.compile("SWID\\D*(\\d+)");
public static int extractSwid(String s) {
String[] lines = s.split(System.getProperty("line.separator"));
for (String line : lines) {
Matcher m = SWID.matcher(line);
if (m.find()) {
return Integer.parseInt(m.group(1));
}
}
throw new RuntimeException("Could not parse SWID from string: " + s);
}
public static String extractValueFrom(String listOutput, String key) {
String[] lines = listOutput.split(System.getProperty("line.separator"));
for (String line : lines) {
if (line.startsWith(key)) {
String[] parts = line.split(" ");
return parts[parts.length - 1];
}
}
return null;
}
public static String getLocalhost() {
OptionParser parser = new OptionParser();
OptionSet set = parser.parse("");
String localhost = FileTools.getLocalhost(set).hostname;
return localhost;
}
/**
* Grab the location of the compiled seqware script.
*
* This uses Maven system properties to pass variables from Maven into Java
*
* @return script file
*/
public static File retrieveCompiledSeqwareScript() {
String property = System.getProperty("cliPath");
if (property == null) {
// try PATH
File p = new File(System.getProperty("user.home") + "/bin", "seqware");
if (p.exists()) {
return p;
}
throw new RuntimeException("Could not locate seqware script");
}
File seqwareScript = new File(property);
return seqwareScript;
}
}