diff options
7 files changed, 145 insertions, 26 deletions
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 c332127b8a..48bc11c8d9 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 @@ public class ExecutionTool { 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 3f7e07075b..a9cb8b094d 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.HashMap; 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 @@ public final class BlazeExecutor implements Executor { 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 @@ public final class BlazeExecutor implements Executor { 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 @@ public final class BlazeExecutor implements Executor { 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 dc823f2be7..b8b2ac2509 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 class ExecutionOptions extends OptionsBase { 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 1bcbec9eca..445140d9db 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 @@ java_test( ":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 0000000000..105829a8c2 --- /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 1459eb0c19..972fd9eb21 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 class TestExecutorBuilder { } 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 a456e06665..d05a44e010 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 @@ public class StandaloneSpawnStrategyTest { bus, BlazeClock.instance(), optionsParser, - /* verboseFailures */ false, - /* showSubcommands */ false, ImmutableList.<ActionContext>of(), ImmutableMap.<String, SpawnActionContext>of( "", |