package uk.ac.ox.zoo.seeg.abraid.mp.modelwrapper.model.commonsexec;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteResultHandler;
import org.apache.commons.exec.Executor;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import uk.ac.ox.zoo.seeg.abraid.mp.modelwrapper.model.ProcessException;
import uk.ac.ox.zoo.seeg.abraid.mp.modelwrapper.model.ProcessHandler;
import uk.ac.ox.zoo.seeg.abraid.mp.modelwrapper.model.ProcessRunner;
import java.io.File;
import java.util.HashMap;
import static com.googlecode.catchexception.CatchException.catchException;
import static com.googlecode.catchexception.CatchException.caughtException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
import static uk.ac.ox.zoo.seeg.abraid.mp.testutils.GeneralTestUtils.captorForClass;
/**
* Tests the CommonsExecProcessRunner class.
* Copyright (c) 2014 University of Oxford
*/
public class CommonsExecProcessRunnerTest {
@Rule
public TemporaryFolder testFolder = new TemporaryFolder(); ///CHECKSTYLE:SUPPRESS VisibilityModifier
@Test
public void runCallsExecuteWithCorrectCommand() throws Exception {
// Arrange
Executor mockExecutor = mock(Executor.class);
File executable = testFolder.newFile("file1");
String[] executionArguments = new String[]{"arg1", "arg2", "${arg3}"};
File script = testFolder.newFile("file2");
HashMap<String, File> fileArguments = new HashMap<>();
fileArguments.put("arg3", script);
ProcessRunner target = new CommonsExecProcessRunner(mockExecutor, testFolder.getRoot(), executable,
executionArguments, fileArguments, 10);
String expectation = "[" + executable + ", arg1, arg2, " + script + "]";
// Act
target.run(mock(ProcessHandler.class));
// Assert
ArgumentCaptor<CommandLine> commandLineCaptor = captorForClass(CommandLine.class);
verify(mockExecutor).execute(commandLineCaptor.capture(), any(ExecuteResultHandler.class));
assertThat(commandLineCaptor.getValue().toString()).isEqualTo(expectation);
}
@Test
public void runSetsCorrectDirectory() throws Exception {
// Arrange
Executor mockExecutor = mock(Executor.class);
File expectedWorkingDir = testFolder.getRoot();
ProcessRunner target = new CommonsExecProcessRunner(mockExecutor, expectedWorkingDir, new File("exe"),
new String[0], new HashMap<String, File>(), 10);
// Act
target.run(mock(ProcessHandler.class));
// Assert
verify(mockExecutor).setWorkingDirectory(eq(expectedWorkingDir));
}
@Test
public void runWrapsInnerExceptionInErrorCase() throws Exception {
// Arrange
Executor mockExecutor = mock(Executor.class);
ExecuteException expectedCause = new ExecuteException("foo", -1);
doThrow(expectedCause).when(mockExecutor).execute(any(CommandLine.class), any(ExecuteResultHandler.class));
ProcessRunner target = new CommonsExecProcessRunner(mockExecutor, testFolder.getRoot(), new File("exe"),
new String[0], new HashMap<String, File>(), 10);
// Act
catchException(target).run(mock(ProcessHandler.class));
Exception result = caughtException();
// Assert
assertThat(result).isInstanceOf(ProcessException.class);
assertThat(result.getCause()).isEqualTo(expectedCause);
}
@Test
public void runCanNotBeCalledMoreThanOnce() throws Exception {
// Arrange
Executor mockExecutor = mock(Executor.class);
ProcessRunner target = new CommonsExecProcessRunner(mockExecutor, testFolder.getRoot(), new File("exe"),
new String[0], new HashMap<String, File>(), 10);
// Act
catchException(target).run(mock(ProcessHandler.class)); // Once
Exception firstRunException = caughtException();
catchException(target).run(mock(ProcessHandler.class)); //Twice
Exception secondRunException = caughtException();
// Assert
assertThat(firstRunException).isNull();
assertThat(secondRunException).isInstanceOf(ProcessException.class);
}
}