From de264b53a75520b32dbf04c8f22b4572d5d1ae3b Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Tue, 21 Feb 2012 10:55:44 -0800 Subject: Added test for CommandLauncher. --- .../core/externaltool/CommandLauncherTest.java | 234 +++++++++++++++++++++ .../core/externaltool/CommandLauncher.java | 19 +- .../internal/core/externaltool/ProcessInvoker.java | 14 +- 3 files changed, 259 insertions(+), 8 deletions(-) create mode 100644 codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncherTest.java diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncherTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncherTest.java new file mode 100644 index 00000000000..dcd2faba891 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncherTest.java @@ -0,0 +1,234 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.core.externaltool; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertArrayEquals; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinter; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinterProvider; +import org.eclipse.cdt.codan.core.externaltool.InvocationFailure; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Tests for {@link CommandLauncher}. + * + * @author alruiz@google.com (Alex Ruiz) + */ +@SuppressWarnings("nls") +public class CommandLauncherTest extends TestCase { + private String externalToolName; + private IPath executablePath; + private String[] args; + private boolean shouldDisplayOutput; + private String command; + private IPath workingDirectory; + private ConsolePrinterProviderStub consolePrinterProvider; + private String[] externalToolOutput; + private ProcessInvokerStub processInvoker; + private OutputParserStub outputParser; + private List outputParsers; + + private CommandLauncher commandLauncher; + + @Override + protected void setUp() throws Exception { + externalToolName = "TestTool"; + executablePath = new Path("/usr/local/testtool"); + args = new String[] { "--include=all", "--debug=true" }; + shouldDisplayOutput = true; + command = "/usr/local/testtool --include=all --debug=true"; + workingDirectory = new Path("/usr/local/project"); + consolePrinterProvider = new ConsolePrinterProviderStub(); + externalToolOutput = new String[] { "line1", "line2" }; + processInvoker = new ProcessInvokerStub(externalToolOutput); + outputParser = new OutputParserStub(); + outputParsers = new ArrayList(); + outputParsers.add(outputParser); + commandLauncher = new CommandLauncher(consolePrinterProvider, processInvoker); + } + + public void testInvokesProcessCorrectly() throws Throwable { + commandLauncher.buildAndLaunchCommand(externalToolName, executablePath, args, + workingDirectory, shouldDisplayOutput, outputParsers); + consolePrinterProvider.assertThatReceivedExternalToolName(externalToolName); + consolePrinterProvider.assertThatReceivedShouldDisplayOutputFlag(shouldDisplayOutput); + consolePrinterProvider.consolePrinter.assertThatPrinted(command, externalToolOutput); + consolePrinterProvider.consolePrinter.assertThatIsClosed(); + processInvoker.assertThatReceivedCommand(command); + processInvoker.assertThatReceivedWorkingDirectory(workingDirectory); + processInvoker.process.assertThatIsDestroyed(); + outputParser.assertThatParsed(externalToolOutput); + } + + private static class ConsolePrinterProviderStub implements IConsolePrinterProvider { + private String externalToolName; + private boolean shouldDisplayOutput; + + final ConsolePrinterStub consolePrinter = new ConsolePrinterStub(); + + @Override + public ConsolePrinterStub createConsole(String externalToolName, boolean shouldDisplayOutput) { + this.externalToolName = externalToolName; + this.shouldDisplayOutput = shouldDisplayOutput; + return consolePrinter; + } + + void assertThatReceivedExternalToolName(String expected) { + assertEquals(expected, externalToolName); + } + + void assertThatReceivedShouldDisplayOutputFlag(boolean expected) { + assertEquals(expected, shouldDisplayOutput); + } + } + + private static class ConsolePrinterStub implements IConsolePrinter { + private final List printed = new ArrayList(); + private boolean closed; + + @Override + public void clear() { + printed.clear(); + } + + @Override + public void println(String message) { + printed.add(message); + } + + @Override + public void println() {} + + @Override + public void close() { + closed = true; + } + + void assertThatPrinted(String command, String[] externalToolOutput) { + List expected = new ArrayList(); + expected.add(command); + expected.addAll(asList(externalToolOutput)); + assertEquals(expected, printed); + } + + void assertThatIsClosed() { + assertTrue(closed); + } + } + + private static class ProcessInvokerStub extends ProcessInvoker { + final ProcessStub process; + + private String command; + private IPath workingDirectory; + + ProcessInvokerStub(String[] externalToolOutput) { + process = new ProcessStub(externalToolOutput); + } + + @Override + public ProcessStub invoke(String command, IPath workingDirectory) throws InvocationFailure { + this.command = command; + this.workingDirectory = workingDirectory; + return process; + } + + void assertThatReceivedCommand(String expected) { + assertEquals(expected, command); + } + + void assertThatReceivedWorkingDirectory(IPath expected) { + assertSame(expected, workingDirectory); + } + } + + private static class ProcessStub extends Process { + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + private final InputStream inputStream; + private final InputStream errorStream; + + private boolean destroyed; + + ProcessStub(String[] externalToolOutput) { + StringBuilder builder = new StringBuilder(); + for (String s : externalToolOutput) { + builder.append(s).append(LINE_SEPARATOR); + } + inputStream = new ByteArrayInputStream(builder.toString().getBytes()); + errorStream = new ByteArrayInputStream(new byte[0]); + } + + @Override + public OutputStream getOutputStream() { + throw new UnsupportedOperationException(); + } + + @Override + public InputStream getInputStream() { + return inputStream; + } + + @Override + public InputStream getErrorStream() { + return errorStream; + } + + @Override + public int waitFor() { + throw new UnsupportedOperationException(); + } + + @Override + public int exitValue() { + throw new UnsupportedOperationException(); + } + + @Override + public void destroy() { + destroyed = true; + } + + void assertThatIsDestroyed() { + assertTrue(destroyed); + } + } + + private static class OutputParserStub extends AbstractOutputParser { + private final List parsed = new ArrayList(); + + @Override + public boolean parse(String line) throws InvocationFailure { + parsed.add(line); + return true; + } + + @Override + public void reset() { + throw new UnsupportedOperationException(); + } + + void assertThatParsed(String[] expected) { + assertArrayEquals(expected, parsed.toArray()); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java index 3ea850ca2ad..8ab1c9dca53 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java @@ -31,8 +31,8 @@ import org.eclipse.core.runtime.IPath; * @since 2.1 */ public class CommandLauncher { - private ProcessInvoker processInvoker = new ProcessInvoker(); private final IConsolePrinterProvider consolePrinterProvider; + private final ProcessInvoker processInvoker; /** * Constructor. @@ -40,7 +40,19 @@ public class CommandLauncher { * tool as its own. */ public CommandLauncher(IConsolePrinterProvider consolePrinterProvider) { + this(consolePrinterProvider, new ProcessInvoker()); + } + + /** + * Constructor. + * @param consolePrinterProvider creates an Eclipse console that uses the name of an external + * tool as its own. + * @param processInvoker executes a command in a separate process. + */ + public CommandLauncher(IConsolePrinterProvider consolePrinterProvider, + ProcessInvoker processInvoker) { this.consolePrinterProvider = consolePrinterProvider; + this.processInvoker = processInvoker; } /** @@ -109,9 +121,4 @@ public class CommandLauncher { } } } - - // Visible for testing. - void setProcessInvoker(ProcessInvoker newVal) { - processInvoker = newVal; - } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java index 81b1a6ee948..dddc8d9a91d 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java @@ -19,12 +19,22 @@ import org.eclipse.core.runtime.IPath; * Executes a command in a separate process. * * @author alruiz@google.com (Alex Ruiz) + * + * @since 2.1 */ -class ProcessInvoker { +public class ProcessInvoker { private static final String[] ENVIRONMENT_VARIABLE_SETTINGS = {}; private static final String ERROR_FORMAT = "Unable to invoke command '%s'"; //$NON-NLS-1$ - Process invoke(String command, IPath workingDirectory) throws InvocationFailure { + /** + * Invokes the given command in a separate process. + * @param command the command to execute. + * @param workingDirectory the working directory of the process, or {@code null} should inherit + * the working directory of the current process. + * @return the process where the given command is being executed. + * @throws InvocationFailure if the command fails to be executed. + */ + public Process invoke(String command, IPath workingDirectory) throws InvocationFailure { try { Runtime runtime = Runtime.getRuntime(); if (workingDirectory == null) { -- cgit v1.2.3