aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java
diff options
context:
space:
mode:
authorGravatar Lukacs Berki <lberki@google.com>2016-07-01 14:32:53 +0000
committerGravatar Lukacs Berki <lberki@google.com>2016-07-04 07:18:05 +0000
commit0451cf0b5a16688bb56396af276a6ef4ebbe5d4d (patch)
tree5c05180bea38d3898e0a2d4f8b5217e3e6bf8933 /src/test/java
parent6382bfd45ee39f97809a185216a183686e1a8f1b (diff)
Add an implementation for SubprocessFactory based on the new JNI interface to Windows process management.
With this change, Bazel can build itself using native Windows process management and Ctrl-C works in server mode as expected. Yay! Flipping the flag will come in a separate change that's easy to roll back if need be. -- MOS_MIGRATED_REVID=126408264
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/com/google/devtools/build/lib/windows/MockSubprocess.java13
-rw-r--r--src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java106
2 files changed, 68 insertions, 51 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/windows/MockSubprocess.java b/src/test/java/com/google/devtools/build/lib/windows/MockSubprocess.java
index 7e2d90cef6..1562532b3d 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/MockSubprocess.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/MockSubprocess.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.windows;
import java.io.PrintStream;
import java.nio.charset.Charset;
+import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
@@ -28,6 +29,8 @@ import java.util.Map;
* <li><code>E-&lt;string&gt;</code>: Write a string to stderr</li>
* <li><code>O$&lt;variable&gt;</code>: Write an environment variable to stdout</li>
* <li><code>E$&lt;variable&gt;</code>: Write an environment variable to stderr</li>
+ * <li><code>O.</code>: Write the cwd stdout</li>
+ * <li><code>E.</code>: Write the cwd stderr</li>
* <li><code>O&lt;register&gt;</code>: Write the contents of a register to stdout</li>
* <li><code>E&lt;register&gt;</code>: Write the contents of a register to stderr</li>
* <li><code>X&lt;exit code%gt;</code>: Exit with the specified exit code</li>
@@ -45,18 +48,24 @@ import java.util.Map;
*/
public class MockSubprocess {
private static Map<Character, byte[]> registers = new HashMap<>();
+ private static final Charset UTF8 = Charset.forName("UTF-8");
private static void writeBytes(PrintStream stream, String arg) throws Exception {
+
byte[] buf;
switch (arg.charAt(1)) {
case '-':
// Immediate string
- buf = arg.substring(2).getBytes(Charset.forName("UTF-8"));
+ buf = arg.substring(2).getBytes(UTF8);
break;
case '$':
// Environment variable
- buf = System.getenv(arg.substring(2)).getBytes(Charset.forName("UTF-8"));
+ buf = System.getenv(arg.substring(2)).getBytes(UTF8);
+ break;
+
+ case '.':
+ buf = Paths.get(".").toAbsolutePath().normalize().toString().getBytes(UTF8);
break;
default:
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java
index ecd7c26229..bdfe95ffd6 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java
@@ -16,22 +16,22 @@ package com.google.devtools.build.lib.windows;
import static com.google.common.truth.Truth.assertThat;
-import com.google.common.util.concurrent.Uninterruptibles;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.util.OS;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.TimeUnit;
/**
* Unit tests for {@link WindowsProcesses}.
@@ -83,7 +83,7 @@ public class WindowsProcessesTest {
@Test
public void testSmoke() throws Exception {
- process = WindowsProcesses.nativeCreateProcess(mockArgs("Ia5", "Oa"), null, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("Ia5", "Oa"), null, null, null, null);
assertNoError();
byte[] input = "HELLO".getBytes(UTF8);
@@ -104,7 +104,7 @@ public class WindowsProcessesTest {
}
process = WindowsProcesses.nativeCreateProcess(mockArgs(args.toArray(new String[] {})), null,
- null, null);
+ null, null, null);
for (int i = 0; i < 100; i++) {
byte[] input = String.format("%03d", i).getBytes(UTF8);
assertThat(input.length).isEqualTo(3);
@@ -115,42 +115,17 @@ public class WindowsProcessesTest {
}
}
- private void startInterruptThread(final long delayMilliseconds) {
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- Uninterruptibles.sleepUninterruptibly(delayMilliseconds, TimeUnit.MILLISECONDS);
- WindowsProcesses.nativeInterrupt(process);
- }
- }
- });
-
- thread.setDaemon(true);
- thread.start();
- }
-
- @Test
- public void testInterruption() throws Exception {
- process = WindowsProcesses.nativeCreateProcess(mockArgs("Ia1"), null, null, null); // hang
- startInterruptThread(1000);
- // If the interruption doesn't work, this will hang indefinitely, but there isn't a lot
- // we can do in that case because we can't just tell native code to stop whatever it's doing
- // from Java.
- assertThat(WindowsProcesses.nativeWaitFor(process)).isEqualTo(-1);
- assertThat(WindowsProcesses.nativeIsInterrupted(process)).isTrue();
- }
-
@Test
public void testExitCode() throws Exception {
- process = WindowsProcesses.nativeCreateProcess(mockArgs("X42"), null, null, null);
- assertThat(WindowsProcesses.nativeWaitFor(process)).isEqualTo(42);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("X42"), null, null, null, null);
+ assertThat(WindowsProcesses.nativeWaitFor(process)).isTrue();
+ assertThat(WindowsProcesses.nativeGetExitCode(process)).isEqualTo(42);
assertNoError();
}
@Test
public void testPartialRead() throws Exception {
- process = WindowsProcesses.nativeCreateProcess(mockArgs("O-HELLO"), null, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("O-HELLO"), null, null, null, null);
byte[] one = new byte[2];
byte[] two = new byte[3];
@@ -165,7 +140,7 @@ public class WindowsProcessesTest {
@Test
public void testArrayOutOfBounds() throws Exception {
- process = WindowsProcesses.nativeCreateProcess(mockArgs("O-oob"), null, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("O-oob"), null, null, null, null);
byte[] buf = new byte[3];
assertThat(WindowsProcesses.nativeReadStdout(process, buf, -1, 3)).isEqualTo(-1);
assertThat(WindowsProcesses.nativeReadStdout(process, buf, 0, 5)).isEqualTo(-1);
@@ -198,7 +173,7 @@ public class WindowsProcessesTest {
@Test
public void testOffsetedOps() throws Exception {
- process = WindowsProcesses.nativeCreateProcess(mockArgs("Ia3", "Oa"), null, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("Ia3", "Oa"), null, null, null, null);
byte[] input = "01234".getBytes(UTF8);
byte[] output = "abcde".getBytes(UTF8);
@@ -215,7 +190,7 @@ public class WindowsProcessesTest {
public void testParallelStdoutAndStderr() throws Exception {
process = WindowsProcesses.nativeCreateProcess(mockArgs(
"O-out1", "E-err1", "O-out2", "E-err2", "E-err3", "O-out3", "E-err4", "O-out4"),
- null, null, null);
+ null, null, null, null);
byte[] buf = new byte[4];
assertThat(WindowsProcesses.nativeReadStdout(process, buf, 0, 4)).isEqualTo(4);
@@ -241,7 +216,8 @@ public class WindowsProcessesTest {
@Test
public void testExecutableNotFound() throws Exception {
- process = WindowsProcesses.nativeCreateProcess("ThisExecutableDoesNotExist", null, null, null);
+ process = WindowsProcesses.nativeCreateProcess("ThisExecutableDoesNotExist",
+ null, null, null, null);
assertThat(WindowsProcesses.nativeGetLastError(process))
.contains("The system cannot find the file specified.");
byte[] buf = new byte[1];
@@ -250,7 +226,7 @@ public class WindowsProcessesTest {
@Test
public void testReadingAndWritingAfterTermination() throws Exception {
- process = WindowsProcesses.nativeCreateProcess("X42", null, null, null);
+ process = WindowsProcesses.nativeCreateProcess("X42", null, null, null, null);
byte[] buf = new byte[1];
assertThat(WindowsProcesses.nativeReadStdout(process, buf, 0, 1)).isEqualTo(-1);
assertThat(WindowsProcesses.nativeReadStderr(process, buf, 0, 1)).isEqualTo(-1);
@@ -260,7 +236,8 @@ public class WindowsProcessesTest {
@Test
public void testNewEnvironmentVariables() throws Exception {
byte[] data = "ONE=one\0TWO=twotwo\0\0".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockArgs("O$ONE", "O$TWO"), data, null, null);
+ process = WindowsProcesses.nativeCreateProcess(
+ mockArgs("O$ONE", "O$TWO"), data, null, null, null);
assertNoError();
byte[] buf = new byte[3];
assertThat(WindowsProcesses.nativeReadStdout(process, buf, 0, 3)).isEqualTo(3);
@@ -273,34 +250,49 @@ public class WindowsProcessesTest {
@Test
public void testNoZeroInEnvBuffer() throws Exception {
byte[] data = "clown".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null, null);
assertThat(WindowsProcesses.nativeGetLastError(process)).isNotEmpty();
}
@Test
- public void testOneZeroInEnvBuffer() throws Exception {
+ public void testMissingFinalDoubleZeroInEnvBuffer() throws Exception {
byte[] data = "FOO=bar\0".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null, null);
assertThat(WindowsProcesses.nativeGetLastError(process)).isNotEmpty();
}
@Test
public void testOneByteEnvBuffer() throws Exception {
byte[] data = "a".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null, null);
assertThat(WindowsProcesses.nativeGetLastError(process)).isNotEmpty();
}
@Test
+ public void testOneZeroEnvBuffer() throws Exception {
+ byte[] data = "\0".getBytes(UTF8);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.nativeGetLastError(process)).isNotEmpty();
+ }
+
+ @Test
+ public void testTwoZerosInEnvBuffer() throws Exception {
+ byte[] data = "\0\0".getBytes(UTF8);
+ process = WindowsProcesses.nativeCreateProcess(mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.nativeGetLastError(process)).isEmpty();
+ }
+
+ @Test
public void testRedirect() throws Exception {
String stdoutFile = System.getenv("TEST_TMPDIR") + "\\stdout_redirect";
String stderrFile = System.getenv("TEST_TMPDIR") + "\\stderr_redirect";
process = WindowsProcesses.nativeCreateProcess(mockArgs("O-one", "E-two"),
- null, stdoutFile, stderrFile);
+ null, null, stdoutFile, stderrFile);
assertThat(process).isGreaterThan(0L);
assertNoError();
- WindowsProcesses.nativeWaitFor(process);
+ assertThat(WindowsProcesses.nativeWaitFor(process)).isTrue();
+ WindowsProcesses.nativeGetExitCode(process);
assertNoError();
byte[] stdout = Files.readAllBytes(Paths.get(stdoutFile));
byte[] stderr = Files.readAllBytes(Paths.get(stderrFile));
@@ -313,10 +305,11 @@ public class WindowsProcessesTest {
String file = System.getenv("TEST_TMPDIR") + "\\captured_";
process = WindowsProcesses.nativeCreateProcess(mockArgs("O-one", "E-two"),
- null, file, file);
+ null, null, file, file);
assertThat(process).isGreaterThan(0L);
assertNoError();
- WindowsProcesses.nativeWaitFor(process);
+ assertThat(WindowsProcesses.nativeWaitFor(process)).isTrue();
+ WindowsProcesses.nativeGetExitCode(process);
assertNoError();
byte[] bytes = Files.readAllBytes(Paths.get(file));
assertThat(new String(bytes, UTF8)).isEqualTo("onetwo");
@@ -327,7 +320,7 @@ public class WindowsProcessesTest {
String stdoutFile = System.getenv("TEST_TMPDIR") + "\\captured_stdout";
String stderrFile = System.getenv("TEST_TMPDIR") + "\\captured_stderr";
- process = WindowsProcesses.nativeCreateProcess(mockArgs("O-one", "E-two"), null,
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("O-one", "E-two"), null, null,
stdoutFile, stderrFile);
assertNoError();
byte[] buf = new byte[1];
@@ -346,13 +339,28 @@ public class WindowsProcessesTest {
Files.write(stderr, "err1".getBytes(UTF8));
process = WindowsProcesses.nativeCreateProcess(mockArgs("O-out2", "E-err2"), null,
- stdoutFile, stderrFile);
+ null, stdoutFile, stderrFile);
assertNoError();
WindowsProcesses.nativeWaitFor(process);
+ WindowsProcesses.nativeGetExitCode(process);
assertNoError();
byte[] stdoutBytes = Files.readAllBytes(Paths.get(stdoutFile));
byte[] stderrBytes = Files.readAllBytes(Paths.get(stderrFile));
assertThat(new String(stdoutBytes, UTF8)).isEqualTo("out1out2");
assertThat(new String(stderrBytes, UTF8)).isEqualTo("err1err2");
}
+
+ @Test
+ public void testCwd() throws Exception {
+ String dir1 = System.getenv("TEST_TMPDIR") + "/dir1";
+ new File(dir1).mkdir();
+
+ process = WindowsProcesses.nativeCreateProcess(mockArgs("O."), null, dir1, null, null);
+ assertNoError();
+ byte[] buf = new byte[1024]; // Windows MAX_PATH is 256, but whatever
+ int len = WindowsProcesses.nativeReadStdout(process, buf, 0, 1024);
+ assertNoError();
+ assertThat(new String(buf, 0, len, UTF8).replace("\\", "/")).isEqualTo(dir1);
+
+ }
}