/*
* Copyright 2014-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.testutil.TestConsole;
import com.facebook.buck.util.environment.Platform;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
public class ProcessExecutorTest {
@Test
public void testDontExpectStdout() throws IOException, InterruptedException {
CapturingPrintStream stdOut = new CapturingPrintStream();
CapturingPrintStream stdErr = new CapturingPrintStream();
Ansi ansi = Ansi.forceTty();
Console console = new Console(Verbosity.ALL, stdOut, stdErr, ansi);
ProcessExecutor executor = new DefaultProcessExecutor(console);
String cmd = Platform.detect() == Platform.WINDOWS ? "cmd /C echo Hello" : "echo Hello";
ProcessExecutorParams params = ProcessExecutorParams.ofCommand(makeCommandArray(cmd));
ProcessExecutor.Result result = executor.launchAndExecute(params);
assertEquals(ansi.asHighlightedFailureText("Hello\n"), result.getStdout().get());
assertEquals("", result.getStderr().get());
}
@Test
public void testExpectStdout() throws IOException, InterruptedException {
String cmd = Platform.detect() == Platform.WINDOWS ? "cmd /C echo Hello" : "echo Hello";
CapturingPrintStream stdOut = new CapturingPrintStream();
CapturingPrintStream stdErr = new CapturingPrintStream();
Ansi ansi = Ansi.forceTty();
Console console = new Console(Verbosity.ALL, stdOut, stdErr, ansi);
ProcessExecutor executor = new DefaultProcessExecutor(console);
ProcessExecutorParams params = ProcessExecutorParams.ofCommand(makeCommandArray(cmd));
ProcessExecutor.Result result =
executor.launchAndExecute(
params,
EnumSet.of(ProcessExecutor.Option.EXPECTING_STD_OUT),
/* stdin */ Optional.empty(),
/* timeOutMs */ Optional.empty(),
/* timeOutHandler */ Optional.empty());
assertEquals("Hello\n", result.getStdout().get());
assertEquals("", result.getStderr().get());
}
@Test
public void testProcessFailureDoesNotWriteEmptyString() throws IOException, InterruptedException {
String cmd = Platform.detect() == Platform.WINDOWS ? "cmd /C (exit 1)" : "false";
DirtyPrintStreamDecorator stdOut = new DirtyPrintStreamDecorator(new CapturingPrintStream());
DirtyPrintStreamDecorator stdErr = new DirtyPrintStreamDecorator(new CapturingPrintStream());
Ansi ansi = Ansi.forceTty();
Console console = new Console(Verbosity.ALL, stdOut, stdErr, ansi);
ProcessExecutor executor = new DefaultProcessExecutor(console);
ProcessExecutorParams params = ProcessExecutorParams.ofCommand(makeCommandArray(cmd));
executor.launchAndExecute(params);
assertFalse(stdOut.isDirty());
assertFalse(stdErr.isDirty());
}
@Test
public void testProcessTimeoutHandlerIsInvoked() throws IOException, InterruptedException {
@SuppressWarnings("PMD.PrematureDeclaration")
ProcessExecutor executor = new DefaultProcessExecutor(new TestConsole(Verbosity.ALL));
final AtomicBoolean called = new AtomicBoolean(false);
String cmd = (Platform.detect() == Platform.WINDOWS) ? "ping -n 50 0.0.0.0" : "sleep 50";
ProcessExecutorParams params = ProcessExecutorParams.ofCommand(makeCommandArray(cmd));
ProcessExecutor.Result result =
executor.launchAndExecute(
params,
/* options */ ImmutableSet.<ProcessExecutor.Option>builder().build(),
/* stdin */ Optional.empty(),
/* timeOutMs */ Optional.of((long) 100),
/* timeOutHandler */ Optional.of(ignored -> called.set(true)));
assertTrue("process was reported as timed out", result.isTimedOut());
assertTrue("timeOutHandler was called when a timeout was hit", called.get());
}
@Test
public void testProcessTimeoutHandlerThrowsException() throws IOException, InterruptedException {
@SuppressWarnings("PMD.PrematureDeclaration")
ProcessExecutor executor = new DefaultProcessExecutor(new TestConsole(Verbosity.ALL));
String cmd = (Platform.detect() == Platform.WINDOWS) ? "ping -n 50 0.0.0.0" : "sleep 50";
ProcessExecutorParams params = ProcessExecutorParams.ofCommand(makeCommandArray(cmd));
ProcessExecutor.Result result =
executor.launchAndExecute(
params,
/* options */ ImmutableSet.<ProcessExecutor.Option>builder().build(),
/* stdin */ Optional.empty(),
/* timeOutMs */ Optional.of((long) 100),
/* timeOutHandler */ Optional.of(
ignored -> {
throw new RuntimeException("This shouldn't fail the test!");
}));
assertTrue("process was reported as timed out", result.isTimedOut());
}
private static String[] makeCommandArray(String command) {
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdarray[i] = st.nextToken();
}
return cmdarray;
}
}