aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java
diff options
context:
space:
mode:
authorGravatar Philipp Wollermann <philwo@google.com>2015-09-08 17:11:08 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-09-08 17:27:04 +0000
commitd93922b7cbfc4522746c6b7b3dc4652575b178c1 (patch)
tree14a9b16830ad13b5ada74a09c3d8894088c9a896 /src/test/java
parenta86c9a2392fe209b05925fcd5b245cd37ff2d7f2 (diff)
sandbox: Better error messages and the noisy debug logs of the namespace-runner now have to be explicitly activated via --sandbox_debug.
Fixes #424. -- MOS_MIGRATED_REVID=102566625
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/BUILD7
-rw-r--r--src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTest.java155
-rw-r--r--src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTestCase.java126
-rw-r--r--src/test/java/com/google/devtools/build/lib/sandbox/LocalLinuxSandboxedStrategyTest.java93
-rw-r--r--src/test/java/com/google/devtools/build/lib/sandbox/SandboxLocalTests.java38
-rw-r--r--src/test/java/com/google/devtools/build/lib/sandbox/SandboxTests.java35
6 files changed, 364 insertions, 90 deletions
diff --git a/src/test/java/BUILD b/src/test/java/BUILD
index 8315e1ccc0..9f3ead75c8 100644
--- a/src/test/java/BUILD
+++ b/src/test/java/BUILD
@@ -586,8 +586,15 @@ java_test(
args = ["com.google.devtools.build.lib.AllTests"],
data = [":embedded_scripts"],
deps = [
+ ":actions_testutil",
":analysis_testutil",
+ ":foundations_testutil",
":testutil",
+ "//src/main/java:actions",
+ "//src/main/java:analysis-exec-rules-skyframe",
+ "//src/main/java:events",
+ "//src/main/java:options",
+ "//src/main/java:shell",
"//src/main/java:vfs",
"//src/main/java/com/google/devtools/build/lib/sandbox",
"//third_party:guava",
diff --git a/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTest.java b/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTest.java
index 74333e3d27..f91bb0dbb8 100644
--- a/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTest.java
@@ -20,20 +20,14 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.sandbox.LinuxSandboxedStrategy.MountMap;
-import com.google.devtools.build.lib.testutil.TestUtils;
-import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
-import com.google.devtools.build.lib.vfs.UnixFileSystem;
-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.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -53,28 +47,7 @@ import java.util.Map.Entry;
* tree of files given only the set of input files.
*/
@RunWith(JUnit4.class)
-public class LinuxSandboxedStrategyTest {
- private FileSystem testFS;
- private Path workingDir;
- private Path fakeSandboxDir;
-
- @Before
- public void setUp() throws Exception {
- testFS = new UnixFileSystem();
- workingDir = testFS.getPath(new File(TestUtils.tmpDir()).getCanonicalPath());
- fakeSandboxDir = workingDir.getRelative("sandbox");
- fakeSandboxDir.createDirectory();
- }
-
- @After
- public void tearDown() throws Exception {
- FileSystemUtils.deleteTreesBelow(workingDir);
- }
-
- private Path getSandboxPath(Path entry) {
- return fakeSandboxDir.getRelative(entry.asFragment().relativeTo("/"));
- }
-
+public class LinuxSandboxedStrategyTest extends LinuxSandboxedStrategyTestCase {
/**
* Strips the working directory (which can be very long) from the file names in the input map, to
* make assertion failures easier to read.
@@ -82,42 +55,30 @@ public class LinuxSandboxedStrategyTest {
private ImmutableMap<String, String> userFriendlyMap(Map<Path, Path> input) {
ImmutableMap.Builder<String, String> userFriendlyMap = ImmutableMap.builder();
for (Entry<Path, Path> entry : input.entrySet()) {
- String key = entry.getKey().getPathString().replace(workingDir.getPathString(), "");
- String value = entry.getValue().getPathString().replace(workingDir.getPathString(), "");
+ String key = entry.getKey().getPathString().replace(workspaceDir.getPathString(), "");
+ String value = entry.getValue().getPathString().replace(workspaceDir.getPathString(), "");
userFriendlyMap.put(key, value);
}
return userFriendlyMap.build();
}
- private void createTreeStructure(Map<String, String> linksAndFiles) throws IOException {
- for (Entry<String, String> entry : linksAndFiles.entrySet()) {
- Path filePath = workingDir.getRelative(entry.getKey());
- String linkTarget = entry.getValue();
-
- FileSystemUtils.createDirectoryAndParents(filePath.getParentDirectory());
-
- if (!linkTarget.isEmpty()) {
- filePath.createSymbolicLink(new PathFragment(linkTarget));
- } else if (filePath.getPathString().endsWith("/")) {
- filePath.createDirectory();
- } else {
- FileSystemUtils.createEmptyFile(filePath);
- }
- }
- }
-
/**
* Takes a map of file specifications, creates the necessary files / symlinks / dirs,
* mounts files listed in customMount at their canonical location in the sandbox and returns the
* output of {@code LinuxSandboxedStrategy#fixMounts} for it.
*/
+ private ImmutableMap<String, String> userFriendlyMounts(
+ Map<String, String> linksAndFiles, List<String> customMounts) throws IOException {
+ return userFriendlyMap(mounts(linksAndFiles, customMounts));
+ }
+
private ImmutableMap<Path, Path> mounts(
Map<String, String> linksAndFiles, List<String> customMounts) throws IOException {
createTreeStructure(linksAndFiles);
ImmutableMap.Builder<Path, Path> mounts = ImmutableMap.builder();
for (String customMount : customMounts) {
- Path customMountPath = workingDir.getRelative(customMount);
+ Path customMountPath = workspaceDir.getRelative(customMount);
mounts.put(getSandboxPath(customMountPath), customMountPath);
}
return LinuxSandboxedStrategy.validateMounts(
@@ -126,45 +87,57 @@ public class LinuxSandboxedStrategyTest {
fakeSandboxDir, LinuxSandboxedStrategy.withRecursedDirs(mounts.build())));
}
- private ImmutableMap<String, String> userFriendlyMounts(
- Map<String, String> linksAndFiles, List<String> customMounts) throws IOException {
- return userFriendlyMap(mounts(linksAndFiles, customMounts));
- }
-
/**
* Takes a map of file specifications, creates the necessary files / symlinks / dirs,
* mounts the first file of the specification at its canonical location in the sandbox and returns
* the output of {@code LinuxSandboxedStrategy#fixMounts} for it.
*/
- private Map<Path, Path> mounts(Map<String, String> linksAndFiles) throws IOException {
- return mounts(
- linksAndFiles, ImmutableList.of(Iterables.getFirst(linksAndFiles.keySet(), null)));
- }
-
private Map<String, String> userFriendlyMounts(Map<String, String> linksAndFiles)
throws IOException {
return userFriendlyMap(mounts(linksAndFiles));
}
+ private Map<Path, Path> mounts(Map<String, String> linksAndFiles) throws IOException {
+ return mounts(
+ linksAndFiles, ImmutableList.of(Iterables.getFirst(linksAndFiles.keySet(), null)));
+ }
+
/**
* Returns a map of mount entries for a list files, which can be used to assert that all
* expected mounts have been made by the LinuxSandboxedStrategy.
*/
+ private ImmutableMap<String, String> userFriendlyAsserts(List<String> asserts) {
+ return userFriendlyMap(asserts(asserts));
+ }
+
private ImmutableMap<Path, Path> asserts(List<String> asserts) {
ImmutableMap.Builder<Path, Path> pathifiedAsserts = ImmutableMap.builder();
for (String fileName : asserts) {
- Path inputPath = workingDir.getRelative(fileName);
+ Path inputPath = workspaceDir.getRelative(fileName);
pathifiedAsserts.put(getSandboxPath(inputPath), inputPath);
}
return pathifiedAsserts.build();
}
- private ImmutableMap<String, String> userFriendlyAsserts(List<String> asserts) {
- return userFriendlyMap(asserts(asserts));
+ private void createTreeStructure(Map<String, String> linksAndFiles) throws IOException {
+ for (Entry<String, String> entry : linksAndFiles.entrySet()) {
+ Path filePath = workspaceDir.getRelative(entry.getKey());
+ String linkTarget = entry.getValue();
+
+ FileSystemUtils.createDirectoryAndParents(filePath.getParentDirectory());
+
+ if (!linkTarget.isEmpty()) {
+ filePath.createSymbolicLink(new PathFragment(linkTarget));
+ } else if (filePath.getPathString().endsWith("/")) {
+ filePath.createDirectory();
+ } else {
+ FileSystemUtils.createEmptyFile(filePath);
+ }
+ }
}
@Test
- public void resolvesRelativeFileToFileSymlinkInSameDir() throws IOException {
+ public void testResolvesRelativeFileToFileSymlinkInSameDir() throws IOException {
Map<String, String> testFiles = new LinkedHashMap<>();
testFiles.put("symlink.txt", "goal.txt");
testFiles.put("goal.txt", "");
@@ -177,7 +150,7 @@ public class LinuxSandboxedStrategyTest {
}
@Test
- public void resolvesRelativeFileToFileSymlinkInSubDir() throws IOException {
+ public void testResolvesRelativeFileToFileSymlinkInSubDir() throws IOException {
Map<String, String> testFiles =
ImmutableMap.of(
"symlink.txt", "x/goal.txt",
@@ -188,7 +161,7 @@ public class LinuxSandboxedStrategyTest {
}
@Test
- public void resolvesRelativeFileToFileSymlinkInParentDir() throws IOException {
+ public void testResolvesRelativeFileToFileSymlinkInParentDir() throws IOException {
Map<String, String> testFiles =
ImmutableMap.of(
"x/symlink.txt", "../goal.txt",
@@ -200,7 +173,7 @@ public class LinuxSandboxedStrategyTest {
}
@Test
- public void recursesSubDirs() throws IOException {
+ public void testRecursesSubDirs() throws IOException {
ImmutableList<String> inputFile = ImmutableList.of("a/b");
Map<String, String> testFiles =
@@ -219,7 +192,7 @@ public class LinuxSandboxedStrategyTest {
* Test that the algorithm correctly identifies and refuses symlink loops.
*/
@Test
- public void catchesSymlinkLoop() throws IOException {
+ public void testCatchesSymlinkLoop() throws IOException {
try {
mounts(
ImmutableMap.of(
@@ -231,7 +204,7 @@ public class LinuxSandboxedStrategyTest {
.hasMessage(
String.format(
"%s (Too many levels of symbolic links)",
- workingDir.getRelative("a").getPathString()));
+ workspaceDir.getRelative("a").getPathString()));
}
}
@@ -240,7 +213,7 @@ public class LinuxSandboxedStrategyTest {
* directories (e.g. "a -> dir/file/file").
*/
@Test
- public void catchesIllegalSymlink() throws IOException {
+ public void testCatchesIllegalSymlink() throws IOException {
try {
mounts(
ImmutableMap.of(
@@ -250,19 +223,20 @@ public class LinuxSandboxedStrategyTest {
} catch (IOException e) {
assertThat(e)
.hasMessage(
- String.format("%s (Not a directory)", workingDir.getRelative("a/c").getPathString()));
+ String.format(
+ "%s (Not a directory)", workspaceDir.getRelative("a/c").getPathString()));
}
}
@Test
public void testParseManifestFile() throws IOException {
- Path targetDir = workingDir.getRelative("runfiles");
+ Path targetDir = workspaceDir.getRelative("runfiles");
targetDir.createDirectory();
- Path testFile = workingDir.getRelative("testfile");
+ Path testFile = workspaceDir.getRelative("testfile");
FileSystemUtils.createEmptyFile(testFile);
- Path manifestFile = workingDir.getRelative("MANIFEST");
+ Path manifestFile = workspaceDir.getRelative("MANIFEST");
FileSystemUtils.writeContent(
manifestFile,
Charset.defaultCharset(),
@@ -279,47 +253,47 @@ public class LinuxSandboxedStrategyTest {
fakeSandboxDir.getRelative("runfiles/x/testfile"),
testFile,
fakeSandboxDir.getRelative("runfiles/x/emptyfile"),
- testFS.getPath("/dev/null"))));
+ fileSystem.getPath("/dev/null"))));
}
@Test
public void testMountMapWithNormalMounts() throws IOException {
// Allowed: Just two normal mounts (a -> sandbox/a, b -> sandbox/b)
MountMap<Path, Path> mounts = new MountMap<>();
- mounts.put(fakeSandboxDir.getRelative("a"), workingDir.getRelative("a"));
- mounts.put(fakeSandboxDir.getRelative("b"), workingDir.getRelative("b"));
+ mounts.put(fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("a"));
+ mounts.put(fakeSandboxDir.getRelative("b"), workspaceDir.getRelative("b"));
assertThat(mounts)
.isEqualTo(
ImmutableMap.of(
- fakeSandboxDir.getRelative("a"), workingDir.getRelative("a"),
- fakeSandboxDir.getRelative("b"), workingDir.getRelative("b")));
+ fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("a"),
+ fakeSandboxDir.getRelative("b"), workspaceDir.getRelative("b")));
}
@Test
public void testMountMapWithSameMountTwice() throws IOException {
// Allowed: Mount same thing twice (a -> sandbox/a, a -> sandbox/a, b -> sandbox/b)
MountMap<Path, Path> mounts = new MountMap<>();
- mounts.put(fakeSandboxDir.getRelative("a"), workingDir.getRelative("a"));
- mounts.put(fakeSandboxDir.getRelative("a"), workingDir.getRelative("a"));
- mounts.put(fakeSandboxDir.getRelative("b"), workingDir.getRelative("b"));
+ mounts.put(fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("a"));
+ mounts.put(fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("a"));
+ mounts.put(fakeSandboxDir.getRelative("b"), workspaceDir.getRelative("b"));
assertThat(mounts)
.isEqualTo(
ImmutableMap.of(
- fakeSandboxDir.getRelative("a"), workingDir.getRelative("a"),
- fakeSandboxDir.getRelative("b"), workingDir.getRelative("b")));
+ fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("a"),
+ fakeSandboxDir.getRelative("b"), workspaceDir.getRelative("b")));
}
@Test
public void testMountMapWithOneThingTwoTargets() throws IOException {
// Allowed: Mount one thing in two targets (x -> sandbox/a, x -> sandbox/b)
MountMap<Path, Path> mounts = new MountMap<>();
- mounts.put(fakeSandboxDir.getRelative("a"), workingDir.getRelative("x"));
- mounts.put(fakeSandboxDir.getRelative("b"), workingDir.getRelative("x"));
+ mounts.put(fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("x"));
+ mounts.put(fakeSandboxDir.getRelative("b"), workspaceDir.getRelative("x"));
assertThat(mounts)
.isEqualTo(
ImmutableMap.of(
- fakeSandboxDir.getRelative("a"), workingDir.getRelative("x"),
- fakeSandboxDir.getRelative("b"), workingDir.getRelative("x")));
+ fakeSandboxDir.getRelative("a"), workspaceDir.getRelative("x"),
+ fakeSandboxDir.getRelative("b"), workspaceDir.getRelative("x")));
}
@Test
@@ -327,17 +301,18 @@ public class LinuxSandboxedStrategyTest {
// Forbidden: Mount two things onto the same target (x -> sandbox/a, y -> sandbox/a)
try {
MountMap<Path, Path> mounts = new MountMap<>();
- mounts.put(fakeSandboxDir.getRelative("x"), workingDir.getRelative("a"));
- mounts.put(fakeSandboxDir.getRelative("x"), workingDir.getRelative("b"));
+ mounts.put(fakeSandboxDir.getRelative("x"), workspaceDir.getRelative("a"));
+ mounts.put(fakeSandboxDir.getRelative("x"), workspaceDir.getRelative("b"));
fail();
} catch (IllegalArgumentException e) {
assertThat(e)
.hasMessage(
String.format(
"Cannot mount both '%s' and '%s' onto '%s'",
- workingDir.getRelative("a"),
- workingDir.getRelative("b"),
+ workspaceDir.getRelative("a"),
+ workspaceDir.getRelative("b"),
fakeSandboxDir.getRelative("x")));
}
}
+
}
diff --git a/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTestCase.java b/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTestCase.java
new file mode 100644
index 0000000000..7fb6c8bf4d
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategyTestCase.java
@@ -0,0 +1,126 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.google.devtools.build.lib.sandbox;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.eventbus.EventBus;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.devtools.build.lib.actions.ActionContextProvider;
+import com.google.devtools.build.lib.actions.BlazeExecutor;
+import com.google.devtools.build.lib.actions.Executor.ActionContext;
+import com.google.devtools.build.lib.actions.SpawnActionContext;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.events.PrintingEventHandler;
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.exec.ExecutionOptions;
+import com.google.devtools.build.lib.testutil.BlazeTestUtils;
+import com.google.devtools.build.lib.testutil.TestFileOutErr;
+import com.google.devtools.build.lib.testutil.TestUtils;
+import com.google.devtools.build.lib.util.BlazeClock;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.util.FileSystems;
+import com.google.devtools.common.options.OptionsParser;
+
+import org.junit.Before;
+
+import java.io.IOException;
+
+/**
+ * Common parts of all {@link LinuxSandboxedStrategy} tests.
+ */
+public class LinuxSandboxedStrategyTestCase {
+ private Reporter reporter = new Reporter(PrintingEventHandler.ERRORS_AND_WARNINGS_TO_STDERR);
+ private Path outputBase;
+
+ protected FileSystem fileSystem;
+ protected Path workspaceDir;
+ protected Path fakeSandboxDir;
+ protected Path fakeSandboxExecRoot;
+
+ protected BlazeExecutor executor;
+ protected BlazeDirectories blazeDirs;
+
+ protected TestFileOutErr outErr = new TestFileOutErr();
+
+ protected String out() {
+ return outErr.outAsLatin1();
+ }
+
+ protected String err() {
+ return outErr.errAsLatin1();
+ }
+
+ protected Path getSandboxPath(Path entry) {
+ return fakeSandboxDir.getRelative(entry.asFragment().relativeTo("/"));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Path testRoot = createTestRoot();
+
+ workspaceDir = testRoot.getRelative("workspace");
+ workspaceDir.createDirectory();
+
+ outputBase = testRoot.getRelative("outputBase");
+ outputBase.createDirectory();
+
+ fakeSandboxDir = testRoot.getRelative("sandbox");
+ fakeSandboxDir.createDirectory();
+
+ blazeDirs = new BlazeDirectories(outputBase, outputBase, workspaceDir);
+ BlazeTestUtils.getIntegrationBinTools(blazeDirs);
+
+ OptionsParser optionsParser =
+ OptionsParser.newOptionsParser(ExecutionOptions.class, SandboxOptions.class);
+ optionsParser.parse("--verbose_failures");
+
+ EventBus bus = new EventBus();
+
+ this.executor =
+ new BlazeExecutor(
+ blazeDirs.getExecRoot(),
+ blazeDirs.getOutputPath(),
+ reporter,
+ bus,
+ BlazeClock.instance(),
+ optionsParser,
+ /* verboseFailures */ true,
+ /* showSubcommands */ false,
+ ImmutableList.<ActionContext>of(),
+ ImmutableMap.<String, SpawnActionContext>of(
+ "",
+ new LinuxSandboxedStrategy(
+ ImmutableMap.<String, String>of(),
+ blazeDirs,
+ MoreExecutors.newDirectExecutorService(),
+ true,
+ false)),
+ ImmutableList.<ActionContextProvider>of());
+ }
+
+ private Path createTestRoot() throws IOException {
+ fileSystem = FileSystems.initDefaultAsNative();
+ Path testRoot = fileSystem.getPath(TestUtils.tmpDir());
+ try {
+ FileSystemUtils.deleteTreesBelow(testRoot);
+ } catch (IOException e) {
+ System.err.println("Failed to remove directory " + testRoot + ": " + e.getMessage());
+ throw e;
+ }
+ return testRoot;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/sandbox/LocalLinuxSandboxedStrategyTest.java b/src/test/java/com/google/devtools/build/lib/sandbox/LocalLinuxSandboxedStrategyTest.java
new file mode 100644
index 0000000000..7563d1fadb
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/sandbox/LocalLinuxSandboxedStrategyTest.java
@@ -0,0 +1,93 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.google.devtools.build.lib.sandbox;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionMetadata;
+import com.google.devtools.build.lib.actions.BaseSpawn;
+import com.google.devtools.build.lib.actions.ResourceSet;
+import com.google.devtools.build.lib.actions.Spawn;
+import com.google.devtools.build.lib.actions.UserExecException;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.exec.SingleBuildFileCache;
+import com.google.devtools.build.lib.shell.BadExitStatusException;
+import com.google.devtools.build.lib.testutil.TestSpec;
+import com.google.devtools.build.lib.util.CommandFailureUtils;
+import com.google.devtools.build.lib.util.OS;
+import com.google.devtools.build.lib.vfs.Path;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Tests for {@code LinuxSandboxedStrategy} that must run locally, because they need to actually
+ * run the namespace-sandbox binary.
+ */
+@TestSpec(localOnly = true, supportedOs = OS.LINUX)
+@RunWith(JUnit4.class)
+public class LocalLinuxSandboxedStrategyTest extends LinuxSandboxedStrategyTestCase {
+ protected Spawn createSpawn(String... arguments) {
+ Map<String, String> environment = ImmutableMap.<String, String>of();
+ Map<String, String> executionInfo = ImmutableMap.<String, String>of();
+ ActionMetadata action = new ActionsTestUtil.NullAction();
+ ResourceSet localResources = ResourceSet.ZERO;
+ return new BaseSpawn(
+ Arrays.asList(arguments), environment, executionInfo, action, localResources);
+ }
+
+ protected ActionExecutionContext createContext() {
+ Path execRoot = executor.getExecRoot();
+ return new ActionExecutionContext(
+ executor,
+ new SingleBuildFileCache(execRoot.getPathString(), execRoot.getFileSystem()),
+ null,
+ outErr,
+ null);
+ }
+
+ @Test
+ public void testExecutionSuccess() throws Exception {
+ Spawn spawn = createSpawn("/bin/sh", "-c", "echo Hello, world.; touch dummy");
+ executor.getSpawnActionContext(spawn.getMnemonic()).exec(spawn, createContext());
+ assertThat(out()).isEqualTo("Hello, world.\n");
+ assertThat(err()).isEmpty();
+ }
+
+ @Test
+ public void testExecutionFailurePrintsCorrectMessage() throws Exception {
+ Spawn spawn = createSpawn("/bin/sh", "-c", "echo ERROR >&2; exit 1");
+ try {
+ executor.getSpawnActionContext(spawn.getMnemonic()).exec(spawn, createContext());
+ fail();
+ } catch (UserExecException e) {
+ assertThat(err()).isEqualTo("ERROR\n");
+ assertThat(e.getMessage())
+ .startsWith(
+ CommandFailureUtils.describeCommandFailure(
+ true,
+ spawn.getArguments(),
+ spawn.getEnvironment(),
+ blazeDirs.getExecRoot().toString()));
+ assertThat(e.getCause()).isInstanceOf(BadExitStatusException.class);
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/sandbox/SandboxLocalTests.java b/src/test/java/com/google/devtools/build/lib/sandbox/SandboxLocalTests.java
new file mode 100644
index 0000000000..5a72adeeac
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/sandbox/SandboxLocalTests.java
@@ -0,0 +1,38 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.google.devtools.build.lib.sandbox;
+
+import com.google.common.base.Predicates;
+import com.google.devtools.build.lib.testutil.BlazeTestSuiteBuilder;
+import com.google.devtools.build.lib.testutil.CustomSuite;
+
+import org.junit.runner.RunWith;
+
+import java.util.Set;
+
+/**
+ * Test suite that runs all tests that are local-only.
+ */
+@RunWith(CustomSuite.class)
+public class SandboxLocalTests extends BlazeTestSuiteBuilder {
+ public static Set<Class<?>> suite() {
+ return new SandboxLocalTests()
+ .getBuilder()
+ .matchClasses(
+ Predicates.and(
+ BlazeTestSuiteBuilder.TEST_IS_LOCAL_ONLY,
+ BlazeTestSuiteBuilder.TEST_SUPPORTS_CURRENT_OS))
+ .create();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/sandbox/SandboxTests.java b/src/test/java/com/google/devtools/build/lib/sandbox/SandboxTests.java
new file mode 100644
index 0000000000..ee676cc244
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/sandbox/SandboxTests.java
@@ -0,0 +1,35 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.google.devtools.build.lib.sandbox;
+
+import com.google.common.base.Predicates;
+import com.google.devtools.build.lib.testutil.BlazeTestSuiteBuilder;
+import com.google.devtools.build.lib.testutil.CustomSuite;
+
+import org.junit.runner.RunWith;
+
+import java.util.Set;
+
+/**
+ * Test suite that runs all tests that are not local-only.
+ */
+@RunWith(CustomSuite.class)
+public class SandboxTests extends BlazeTestSuiteBuilder {
+ public static Set<Class<?>> suite() {
+ return new SandboxTests()
+ .getBuilder()
+ .matchClasses(Predicates.not(BlazeTestSuiteBuilder.TEST_IS_LOCAL_ONLY))
+ .create();
+ }
+}