aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2017-06-14 12:33:35 +0200
committerGravatar Yun Peng <pcloudy@google.com>2017-06-14 13:17:24 +0200
commit746655f21f2f555606db84183e5f90cee9cb3dd5 (patch)
tree90f2b7803b9ede82699a9258d52f6a20d5058b2f
parent45820abe0e4da93b8f1ce97d4296e7d42f0d617e (diff)
Fix local execution to not throw an exception
The SpawnInputExpander returns null for empty files, but the ActionInputPrefetcher does not expect null values, and implementations may throw NPE. PiperOrigin-RevId: 158960425
-rw-r--r--src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java5
-rw-r--r--src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java31
2 files changed, 35 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java
index 418646b1cd..acbb578cdd 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java
@@ -18,6 +18,8 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.SEVERE;
import com.google.common.base.Joiner;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
import com.google.devtools.build.lib.actions.ResourceManager;
@@ -214,7 +216,8 @@ public final class LocalSpawnRunner implements SpawnRunner {
if (Spawns.shouldPrefetchInputsForLocalExecution(spawn)) {
stepLog(INFO, "prefetching inputs for local execution");
setState(State.PREFETCHING_LOCAL_INPUTS);
- actionInputPrefetcher.prefetchFiles(policy.getInputMapping().values());
+ actionInputPrefetcher.prefetchFiles(
+ Iterables.filter(policy.getInputMapping().values(), Predicates.notNull()));
}
stepLog(INFO, "running locally");
diff --git a/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java b/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java
index 29e46e9ba4..d2370b819f 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java
@@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputFileCache;
+import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
import com.google.devtools.build.lib.actions.ResourceManager;
import com.google.devtools.build.lib.actions.ResourceSet;
@@ -428,6 +429,36 @@ public class LocalSpawnRunnerTest {
runner.exec(spawn, policy);
}
+ /**
+ * Regression test: the SpawnInputExpander can return null values for empty files, but the
+ * ActionInputPrefetcher expects no null values.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void checkPrefetchCalledNonNull() throws Exception {
+ Subprocess.Factory factory = mock(Subprocess.Factory.class);
+ when(factory.create(any())).thenReturn(new FinishedSubprocess(0));
+ SubprocessBuilder.setSubprocessFactory(factory);
+ ActionInputPrefetcher mockPrefetcher = mock(ActionInputPrefetcher.class);
+ @SuppressWarnings("rawtypes")
+ ArgumentCaptor<Iterable> captor = ArgumentCaptor.forClass(Iterable.class);
+
+ LocalExecutionOptions options = Options.getDefaults(LocalExecutionOptions.class);
+ LocalSpawnRunner runner = new LocalSpawnRunner(
+ logger, execCount, fs.getPath("/execroot"), mockPrefetcher, options, resourceManager,
+ USE_WRAPPER, "product-name", LocalEnvProvider.UNMODIFIED);
+
+ policy.inputMapping.put(PathFragment.create("relative/path"), null);
+ policy.inputMapping.put(
+ PathFragment.create("another/relative/path"), ActionInputHelper.fromPath("/absolute/path"));
+ timeoutMillis = 123 * 1000L;
+ outErr = new FileOutErr(fs.getPath("/out/stdout"), fs.getPath("/out/stderr"));
+ runner.exec(SIMPLE_SPAWN, policy);
+ verify(mockPrefetcher).prefetchFiles(captor.capture());
+ assertThat(captor.getValue()).doesNotContain(null);
+ assertThat(captor.getValue()).containsExactly(ActionInputHelper.fromPath("/absolute/path"));
+ }
+
@Test
public void checkLocalEnvProviderCalled() throws Exception {
Subprocess.Factory factory = mock(Subprocess.Factory.class);