Add a flag to print the effective (Spawn)ActionContexts for debugging.
By specifying the flag "--debug_print_action_contexts", Bazel will print the contents of the internal SpawnActionContext and ContextMap maps, which allows developers to see which kind of actions are run using which strategy.
Example output of Bazel at HEAD:
$ ./output/bazel build --debug_print_action_contexts
INFO: SpawnActionContextMap: "" = LinuxSandboxedStrategy
INFO: SpawnActionContextMap: "Closure" = WorkerSpawnStrategy
INFO: SpawnActionContextMap: "Javac" = WorkerSpawnStrategy
INFO: ContextMap: Context = BazelWorkspaceStatusActionContext
INFO: ContextMap: CppCompileActionContext = SpawnGccStrategy
INFO: ContextMap: CppLinkActionContext = SpawnLinkStrategy
INFO: ContextMap: FileWriteActionContext = FileWriteStrategy
INFO: ContextMap: FilesetActionContext = FilesetActionContextImpl
INFO: ContextMap: IncludeScanningContext = DummyIncludeScanningContext
INFO: ContextMap: SpawnActionContext = LinuxSandboxedStrategy
INFO: ContextMap: SymlinkTreeActionContext = SymlinkTreeStrategy
INFO: ContextMap: TestActionContext = ExclusiveTestStrategy
(Can you spot the bug found by this feature here? The default TestActionContext is ExclusiveTestStrategy, which is probably not what we want.)
--
PiperOrigin-RevId: 146233390
MOS_MIGRATED_REVID=146233390
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
index c332127..48bc11c 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
@@ -299,8 +299,6 @@
env.getEventBus(),
runtime.getClock(),
request,
- request.getOptions(ExecutionOptions.class).verboseFailures,
- request.getOptions(ExecutionOptions.class).showSubcommands,
strategies,
spawnStrategyMap,
actionContextProviders);
diff --git a/src/main/java/com/google/devtools/build/lib/exec/BlazeExecutor.java b/src/main/java/com/google/devtools/build/lib/exec/BlazeExecutor.java
index 3f7e070..a9cb8b0 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/BlazeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/BlazeExecutor.java
@@ -38,6 +38,8 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -67,31 +69,29 @@
new HashMap<>();
/**
- * Constructs an Executor, bound to a specified output base path, and which
- * will use the specified reporter to announce SUBCOMMAND events,
- * the given event bus to delegate events and the given output streams
- * for streaming output. The list of
- * strategy implementation classes is used to construct instances of the
- * strategies mapped by their declared abstract type. This list is uniquified
- * before using. Each strategy instance is created with a reference to this
- * Executor as well as the given options object.
- * <p>
- * Don't forget to call startBuildRequest() and stopBuildRequest() for each
- * request, and shutdown() when you're done with this executor.
+ * Constructs an Executor, bound to a specified output base path, and which will use the specified
+ * reporter to announce SUBCOMMAND events, the given event bus to delegate events and the given
+ * output streams for streaming output. The list of strategy implementation classes is used to
+ * construct instances of the strategies mapped by their declared abstract type. This list is
+ * uniquified before using. Each strategy instance is created with a reference to this Executor as
+ * well as the given options object.
+ *
+ * <p>Don't forget to call startBuildRequest() and stopBuildRequest() for each request, and
+ * shutdown() when you're done with this executor.
*/
- public BlazeExecutor(Path execRoot,
+ public BlazeExecutor(
+ Path execRoot,
Reporter reporter,
EventBus eventBus,
Clock clock,
OptionsClassProvider options,
- boolean verboseFailures,
- boolean showSubcommands,
List<ActionContext> contextImplementations,
Map<String, SpawnActionContext> spawnActionContextMap,
Iterable<ActionContextProvider> contextProviders)
throws ExecutorInitException {
- this.verboseFailures = verboseFailures;
- this.showSubcommands = showSubcommands;
+ ExecutionOptions executionOptions = options.getOptions(ExecutionOptions.class);
+ this.verboseFailures = executionOptions.verboseFailures;
+ this.showSubcommands = executionOptions.showSubcommands;
this.execRoot = execRoot;
this.reporter = reporter;
this.eventBus = eventBus;
@@ -105,7 +105,6 @@
allContexts.addAll(contextImplementations);
allContexts.addAll(spawnActionContextMap.values());
this.spawnActionContextMap = ImmutableMap.copyOf(spawnActionContextMap);
-
for (ActionContext context : contextImplementations) {
ExecutionStrategy annotation = context.getClass().getAnnotation(ExecutionStrategy.class);
if (annotation != null) {
@@ -114,6 +113,31 @@
contextMap.put(context.getClass(), context);
}
+ // Print a sorted list of our (Spawn)ActionContext maps.
+ if (executionOptions.debugPrintActionContexts) {
+ for (Entry<String, SpawnActionContext> entry :
+ new TreeMap<>(spawnActionContextMap).entrySet()) {
+ reporter.handle(
+ Event.info(
+ String.format(
+ "SpawnActionContextMap: \"%s\" = %s",
+ entry.getKey(), entry.getValue().getClass().getSimpleName())));
+ }
+
+ TreeMap<String, String> sortedContextMapWithSimpleNames = new TreeMap<>();
+ for (Entry<Class<? extends ActionContext>, ActionContext> entry : contextMap.entrySet()) {
+ sortedContextMapWithSimpleNames.put(
+ entry.getKey().getSimpleName(), entry.getValue().getClass().getSimpleName());
+ }
+ for (Entry<String, String> entry : sortedContextMapWithSimpleNames.entrySet()) {
+ // Skip uninteresting identity mappings of contexts.
+ if (!entry.getKey().equals(entry.getValue())) {
+ reporter.handle(
+ Event.info(String.format("ContextMap: %s = %s", entry.getKey(), entry.getValue())));
+ }
+ }
+ }
+
for (ActionContextProvider factory : contextProviders) {
factory.executorCreated(allContexts);
}
diff --git a/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java b/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
index dc823f2..b8b2ac2 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
@@ -197,4 +197,12 @@
public boolean usingLocalTestJobs() {
return localTestJobs != 0;
}
+
+ @Option(
+ name = "debug_print_action_contexts",
+ defaultValue = "false",
+ category = "undocumented",
+ help = "Print the contents of the SpawnActionContext and ContextProviders maps."
+ )
+ public boolean debugPrintActionContexts;
}
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 1bcbec9..445140d 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -1162,13 +1162,16 @@
":testutil",
"//src/main/java/com/google/devtools/build/lib:bazel-rules",
"//src/main/java/com/google/devtools/build/lib:build-base",
+ "//src/main/java/com/google/devtools/build/lib:events",
"//src/main/java/com/google/devtools/build/lib:inmemoryfs",
"//src/main/java/com/google/devtools/build/lib:util",
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/cmdline",
+ "//src/main/java/com/google/devtools/common/options",
"//third_party:guava",
"//third_party:junit4",
+ "//third_party:mockito",
"//third_party:truth",
"//third_party/protobuf",
],
diff --git a/src/test/java/com/google/devtools/build/lib/exec/BlazeExecutorTest.java b/src/test/java/com/google/devtools/build/lib/exec/BlazeExecutorTest.java
new file mode 100644
index 0000000..105829a
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/exec/BlazeExecutorTest.java
@@ -0,0 +1,85 @@
+// Copyright 2016 The Bazel Authors. 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.exec;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.SpawnActionContext;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.analysis.config.BinTools;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.events.StoredEventHandler;
+import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
+import com.google.devtools.build.lib.testutil.Suite;
+import com.google.devtools.build.lib.testutil.TestSpec;
+import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
+import com.google.devtools.common.options.OptionsParser;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
+
+/** Tests for {@link BlazeExecutor}. */
+@RunWith(JUnit4.class)
+@TestSpec(size = Suite.SMALL_TESTS)
+public class BlazeExecutorTest {
+ private BlazeDirectories directories;
+ private BinTools binTools;
+
+ @Before
+ public final void setUpDirectoriesAndTools() throws Exception {
+ InMemoryFileSystem fs = new InMemoryFileSystem();
+ directories =
+ new BlazeDirectories(
+ fs.getPath("/install"),
+ fs.getPath("/base"),
+ fs.getPath("/workspace"),
+ "mock-product-name");
+ binTools = BinTools.empty(directories);
+ }
+
+ @Test
+ public void testDebugPrintActionContexts() throws Exception {
+ TestExecutorBuilder builder = new TestExecutorBuilder(directories, binTools);
+ OptionsParser parser = OptionsParser.newOptionsParser(TestExecutorBuilder.DEFAULT_OPTIONS);
+ parser.parse("--debug_print_action_contexts");
+
+ Reporter reporter = new Reporter();
+ StoredEventHandler storedEventHandler = new StoredEventHandler();
+ reporter.addHandler(storedEventHandler);
+
+ SpawnActionContext mockStrategy = Mockito.mock(SpawnActionContext.class);
+
+ builder.setReporter(reporter).setOptionsParser(parser).setExecution("mock", mockStrategy);
+ builder.build();
+
+ Event event =
+ Iterables.find(
+ storedEventHandler.getEvents(),
+ new Predicate<Event>() {
+ @Override
+ public boolean apply(@Nullable Event event) {
+ return event.getMessage().contains("SpawnActionContextMap: \"mock\" = ");
+ }
+ });
+ assertThat(event).isNotNull();
+ assertThat(event.getMessage())
+ .contains("\"mock\" = " + mockStrategy.getClass().getSimpleName());
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/exec/util/TestExecutorBuilder.java b/src/test/java/com/google/devtools/build/lib/exec/util/TestExecutorBuilder.java
index 1459eb0..972fd9e 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/util/TestExecutorBuilder.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/util/TestExecutorBuilder.java
@@ -95,11 +95,14 @@
}
public BlazeExecutor build() throws ExecutorInitException {
- return new BlazeExecutor(directories.getExecRoot(), reporter, bus,
- BlazeClock.instance(), optionsParser,
- optionsParser.getOptions(ExecutionOptions.class).verboseFailures,
- optionsParser.getOptions(ExecutionOptions.class).showSubcommands,
+ return new BlazeExecutor(
+ directories.getExecRoot(),
+ reporter,
+ bus,
+ BlazeClock.instance(),
+ optionsParser,
strategies,
- ImmutableMap.copyOf(spawnStrategyMap), ImmutableList.<ActionContextProvider>of());
+ ImmutableMap.copyOf(spawnStrategyMap),
+ ImmutableList.<ActionContextProvider>of());
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
index a456e06..d05a44e 100644
--- a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
@@ -102,8 +102,6 @@
bus,
BlazeClock.instance(),
optionsParser,
- /* verboseFailures */ false,
- /* showSubcommands */ false,
ImmutableList.<ActionContext>of(),
ImmutableMap.<String, SpawnActionContext>of(
"",