blob: 95cf263df95752ad8e4d199b0586a173a47f25f4 [file] [log] [blame]
Philipp Wollermann1ee94412015-11-25 13:52:17 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.standalone;
15
16import static com.google.common.truth.Truth.assertThat;
lberkiaea56b32017-05-30 12:35:33 +020017import static com.google.common.truth.Truth.assertWithMessage;
michajlo660d17f2020-03-27 09:01:57 -070018import static org.junit.Assert.assertThrows;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000019
20import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableMap;
ulfjacke4cca142020-01-08 04:44:40 -080022import com.google.common.collect.ImmutableSet;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000023import com.google.common.collect.Sets;
24import com.google.common.eventbus.EventBus;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000025import com.google.devtools.build.lib.actions.ActionExecutionContext;
mschallerb4c83ec2019-12-26 08:27:08 -080026import com.google.devtools.build.lib.actions.ActionExecutionContext.LostInputsCheck;
Yun Peng7e4c9d52020-01-15 07:28:07 -080027import com.google.devtools.build.lib.actions.ActionExecutionException;
ulfjack5b99e502017-07-20 22:22:36 +020028import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
tomlu3d1a1942017-11-29 14:01:21 -080029import com.google.devtools.build.lib.actions.ActionKeyContext;
ulfjackacd291a2017-06-16 15:25:42 +020030import com.google.devtools.build.lib.actions.Artifact;
31import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000032import com.google.devtools.build.lib.actions.ExecException;
Ulf Adamscddaaa62017-03-02 17:32:28 +000033import com.google.devtools.build.lib.actions.ResourceManager;
34import com.google.devtools.build.lib.actions.ResourceSet;
ulfjack4d7f8f72017-11-29 03:37:04 -080035import com.google.devtools.build.lib.actions.SimpleSpawn;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000036import com.google.devtools.build.lib.actions.Spawn;
ruperts4050a892017-10-07 00:46:20 +020037import com.google.devtools.build.lib.actions.SpawnResult;
janakr13b737a2021-07-02 14:24:25 -070038import com.google.devtools.build.lib.actions.ThreadStateReceiver;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000039import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
janakr15ee8372020-10-15 07:44:24 -070040import com.google.devtools.build.lib.actions.util.ActionsTestUtil.NullAction;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000041import com.google.devtools.build.lib.analysis.BlazeDirectories;
janakr3b63a4e2017-09-14 09:55:40 +020042import com.google.devtools.build.lib.analysis.ServerDirectories;
ulfjacke4cca142020-01-08 04:44:40 -080043import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
ajurkowskia1d57ea2020-03-05 19:27:38 -080044import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
ulfjacke4cca142020-01-08 04:44:40 -080045import com.google.devtools.build.lib.collect.nestedset.Order;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000046import com.google.devtools.build.lib.events.PrintingEventHandler;
47import com.google.devtools.build.lib.events.Reporter;
felly472320c2018-10-29 14:27:00 -070048import com.google.devtools.build.lib.exec.BinTools;
Ulf Adamsdba3c832016-12-21 16:50:02 +000049import com.google.devtools.build.lib.exec.BlazeExecutor;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000050import com.google.devtools.build.lib.exec.ExecutionOptions;
buchgr580038e2019-09-02 02:16:19 -070051import com.google.devtools.build.lib.exec.RunfilesTreeUpdater;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000052import com.google.devtools.build.lib.exec.SingleBuildFileCache;
jcater9c3e6782020-04-16 10:35:43 -070053import com.google.devtools.build.lib.exec.SpawnStrategyResolver;
ulfjackacd291a2017-06-16 15:25:42 +020054import com.google.devtools.build.lib.exec.local.LocalExecutionOptions;
ulfjack19befaf2017-07-24 11:09:40 +020055import com.google.devtools.build.lib.exec.local.LocalSpawnRunner;
schmitt771fe382020-01-27 07:58:50 -080056import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
Ulf Adams6447ad92016-11-18 09:55:47 +000057import com.google.devtools.build.lib.integration.util.IntegrationMock;
kchodorow85ae1902017-04-22 15:07:22 -040058import com.google.devtools.build.lib.testutil.TestConstants;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000059import com.google.devtools.build.lib.testutil.TestUtils;
Dmitry Lomov9d74eba2015-11-26 11:04:01 +000060import com.google.devtools.build.lib.util.OS;
ulfjackacd291a2017-06-16 15:25:42 +020061import com.google.devtools.build.lib.util.io.FileOutErr;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000062import com.google.devtools.build.lib.vfs.FileSystem;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000063import com.google.devtools.build.lib.vfs.Path;
twerthd05f92e2021-05-11 05:45:32 -070064import com.google.devtools.build.lib.vfs.UnixGlob;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000065import com.google.devtools.build.lib.vfs.util.FileSystems;
ulfjackacd291a2017-06-16 15:25:42 +020066import com.google.devtools.common.options.Options;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000067import com.google.devtools.common.options.OptionsParser;
Klaus Aehligd2fcd9d2016-08-26 08:16:25 +000068import java.io.IOException;
ulfjackacd291a2017-06-16 15:25:42 +020069import java.util.Collection;
Yun Peng7e4c9d52020-01-15 07:28:07 -080070import java.util.HashSet;
ruperts7967f332017-11-21 16:37:13 -080071import java.util.List;
Florian Weikertc4975fa2015-12-03 10:27:10 +000072import org.junit.Before;
73import org.junit.Test;
74import org.junit.runner.RunWith;
75import org.junit.runners.JUnit4;
buchgr580038e2019-09-02 02:16:19 -070076import org.mockito.Mockito;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000077
Philipp Wollermann1ee94412015-11-25 13:52:17 +000078/**
79 * Test StandaloneSpawnStrategy.
80 */
Florian Weikertc4975fa2015-12-03 10:27:10 +000081@RunWith(JUnit4.class)
82public class StandaloneSpawnStrategyTest {
ulfjackacd291a2017-06-16 15:25:42 +020083 private static final ArtifactExpander SIMPLE_ARTIFACT_EXPANDER =
84 new ArtifactExpander() {
85 @Override
86 public void expand(Artifact artifact, Collection<? super Artifact> output) {
87 output.add(artifact);
88 }
89 };
Yun Peng7e4c9d52020-01-15 07:28:07 -080090 private static final String WINDOWS_SYSTEM_DRIVE = "C:";
91 private static final String CMD_EXE = getWinSystemBinary("cmd.exe");
Philipp Wollermann1ee94412015-11-25 13:52:17 +000092
Klaus Aehlig777b30d2017-02-24 16:30:15 +000093 private Reporter reporter =
94 new Reporter(new EventBus(), PrintingEventHandler.ERRORS_AND_WARNINGS_TO_STDERR);
Philipp Wollermann1ee94412015-11-25 13:52:17 +000095 private BlazeExecutor executor;
96 private FileSystem fileSystem;
ulfjackacd291a2017-06-16 15:25:42 +020097 private FileOutErr outErr;
Philipp Wollermann1ee94412015-11-25 13:52:17 +000098
99 private Path createTestRoot() throws IOException {
Yun Peng22eb3322016-06-21 14:38:12 +0000100 fileSystem = FileSystems.getNativeFileSystem();
jmmva2a2f9d2020-10-07 06:40:44 -0700101 Path testRoot = fileSystem.getPath(TestUtils.tmpDir()).getRelative("test");
102 testRoot.createDirectoryAndParents();
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000103 try {
jmmv5cc1f652019-03-20 09:34:08 -0700104 testRoot.deleteTreesBelow();
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000105 } catch (IOException e) {
106 System.err.println("Failed to remove directory " + testRoot + ": " + e.getMessage());
107 throw e;
108 }
109 return testRoot;
110 }
111
Yun Peng7e4c9d52020-01-15 07:28:07 -0800112 /**
113 * We assume Windows is installed on C: and all system binaries exist under C:\Windows\System32\
114 */
115 private static String getWinSystemBinary(String binary) {
116 return WINDOWS_SYSTEM_DRIVE + "\\Windows\\System32\\" + binary;
117 }
118
Florian Weikertc4975fa2015-12-03 10:27:10 +0000119 @Before
120 public final void setUp() throws Exception {
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000121 Path testRoot = createTestRoot();
Ulf Adams015aad92016-07-13 16:49:40 +0000122 Path workspaceDir = testRoot.getRelative("workspace-name");
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000123 workspaceDir.createDirectory();
ulfjackacd291a2017-06-16 15:25:42 +0200124 outErr = new FileOutErr(testRoot.getRelative("stdout"), testRoot.getRelative("stderr"));
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000125
126 // setup output base & directories
127 Path outputBase = testRoot.getRelative("outputBase");
128 outputBase.createDirectory();
129
Ulf Adams84e10322016-07-13 17:23:33 +0000130 BlazeDirectories directories =
janakr3b63a4e2017-09-14 09:55:40 +0200131 new BlazeDirectories(
Klaus Aehligc2499c42018-02-27 05:47:21 -0800132 new ServerDirectories(outputBase, outputBase, outputBase),
133 workspaceDir,
cushon849df362018-05-14 01:51:45 -0700134 /* defaultSystemJavabase= */ null,
Klaus Aehligc2499c42018-02-27 05:47:21 -0800135 "mock-product-name");
Ulf Adams6447ad92016-11-18 09:55:47 +0000136 // This call implicitly symlinks the integration bin tools into the exec root.
felly472320c2018-10-29 14:27:00 -0700137 IntegrationMock.get().getIntegrationBinTools(fileSystem, directories);
jcater06d624a2019-06-18 09:07:58 -0700138 OptionsParser optionsParser =
139 OptionsParser.builder().optionsClasses(ExecutionOptions.class).build();
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000140 optionsParser.parse("--verbose_failures");
ulfjackacd291a2017-06-16 15:25:42 +0200141 LocalExecutionOptions localExecutionOptions = Options.getDefaults(LocalExecutionOptions.class);
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000142
Ulf Adamscddaaa62017-03-02 17:32:28 +0000143 ResourceManager resourceManager = ResourceManager.instanceForTestingOnly();
144 resourceManager.setAvailableResources(
ulfjack4f189862018-10-26 09:59:33 -0700145 ResourceSet.create(/*memoryMb=*/1, /*cpuUsage=*/1, /*localTestCount=*/1));
kchodorow85ae1902017-04-22 15:07:22 -0400146 Path execRoot = directories.getExecRoot(TestConstants.WORKSPACE_NAME);
schmitt771fe382020-01-27 07:58:50 -0800147 BinTools binTools = BinTools.forIntegrationTesting(directories, ImmutableList.of());
148 StandaloneSpawnStrategy strategy =
149 new StandaloneSpawnStrategy(
kchodorow85ae1902017-04-22 15:07:22 -0400150 execRoot,
schmitt771fe382020-01-27 07:58:50 -0800151 new LocalSpawnRunner(
152 execRoot,
153 localExecutionOptions,
154 resourceManager,
155 (env, binTools1, fallbackTmpDir) -> ImmutableMap.copyOf(env),
156 binTools,
jmmv511cfd92020-05-11 07:35:04 -0700157 /*processWrapper=*/ null,
janakr619dcf82020-09-22 14:08:59 -0700158 Mockito.mock(RunfilesTreeUpdater.class)),
159 /*verboseFailures=*/ false);
schmitt771fe382020-01-27 07:58:50 -0800160 this.executor =
161 new TestExecutorBuilder(fileSystem, directories, binTools)
jcater18e78502020-03-26 13:14:56 -0700162 .addStrategy(strategy, "standalone")
163 .setDefaultStrategies("standalone")
schmitt771fe382020-01-27 07:58:50 -0800164 .build();
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000165
ulfjack9f6995a2018-02-09 04:34:48 -0800166 executor.getExecRoot().createDirectoryAndParents();
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000167 }
168
169 private Spawn createSpawn(String... arguments) {
ulfjack4d7f8f72017-11-29 03:37:04 -0800170 return new SimpleSpawn(
Ulf Adamscddaaa62017-03-02 17:32:28 +0000171 new ActionsTestUtil.NullAction(),
ulfjack4d7f8f72017-11-29 03:37:04 -0800172 ImmutableList.copyOf(arguments),
173 /*environment=*/ ImmutableMap.of(),
174 /*executionInfo=*/ ImmutableMap.of(),
ulfjacke4cca142020-01-08 04:44:40 -0800175 /*inputs=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
176 /*outputs=*/ ImmutableSet.of(),
Ulf Adamscddaaa62017-03-02 17:32:28 +0000177 ResourceSet.ZERO);
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000178 }
179
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000180 private String out() {
181 return outErr.outAsLatin1();
182 }
183 private String err() {
184 return outErr.errAsLatin1();
185 }
186
Florian Weikertc4975fa2015-12-03 10:27:10 +0000187 @Test
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000188 public void testBinTrueExecutesFine() throws Exception {
Dmitry Lomov9d74eba2015-11-26 11:04:01 +0000189 Spawn spawn = createSpawn(getTrueCommand());
jcater9c3e6782020-04-16 10:35:43 -0700190 executor.getContext(SpawnStrategyResolver.class).exec(spawn, createContext());
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000191
Yun Peng7e4c9d52020-01-15 07:28:07 -0800192 if (OS.getCurrent() != OS.WINDOWS) {
193 assertThat(out()).isEmpty();
194 }
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000195 assertThat(err()).isEmpty();
196 }
197
ruperts7967f332017-11-21 16:37:13 -0800198 private List<SpawnResult> run(Spawn spawn) throws Exception {
jcater9c3e6782020-04-16 10:35:43 -0700199 return executor.getContext(SpawnStrategyResolver.class).exec(spawn, createContext());
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000200 }
ruperts4050a892017-10-07 00:46:20 +0200201
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000202 private ActionExecutionContext createContext() {
203 Path execRoot = executor.getExecRoot();
204 return new ActionExecutionContext(
205 executor,
206 new SingleBuildFileCache(execRoot.getPathString(), execRoot.getFileSystem()),
ulfjack7599a4d2017-07-21 13:58:33 +0200207 ActionInputPrefetcher.NONE,
tomlu3d1a1942017-11-29 14:01:21 -0800208 new ActionKeyContext(),
ulfjack256be112019-04-05 05:42:01 -0700209 /*metadataHandler=*/ null,
mschallerb20f5122020-04-23 21:36:25 -0700210 /*rewindingEnabled=*/ false,
mschallerb4c83ec2019-12-26 08:27:08 -0800211 LostInputsCheck.NONE,
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000212 outErr,
ulfjack256be112019-04-05 05:42:01 -0700213 reporter,
214 /*clientEnv=*/ ImmutableMap.of(),
215 /*topLevelFilesets=*/ ImmutableMap.of(),
shahanb1dd4e32018-05-09 08:23:31 -0700216 SIMPLE_ARTIFACT_EXPANDER,
felly2b3befd2018-08-10 10:37:56 -0700217 /*actionFileSystem=*/ null,
ajurkowskia1d57ea2020-03-05 19:27:38 -0800218 /*skyframeDepsResult=*/ null,
twerthd05f92e2021-05-11 05:45:32 -0700219 NestedSetExpander.DEFAULT,
janakr13b737a2021-07-02 14:24:25 -0700220 UnixGlob.DEFAULT_SYSCALLS,
221 ThreadStateReceiver.NULL_INSTANCE);
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000222 }
223
Florian Weikertc4975fa2015-12-03 10:27:10 +0000224 @Test
Yun Peng7e4c9d52020-01-15 07:28:07 -0800225 public void testBinFalseYieldsException() {
jcater7472b372019-04-30 07:40:50 -0700226 ExecException e = assertThrows(ExecException.class, () -> run(createSpawn(getFalseCommand())));
227 assertWithMessage("got: " + e.getMessage())
Yun Peng7e4c9d52020-01-15 07:28:07 -0800228 .that(e.getMessage().contains("failed: error executing command"))
jcater7472b372019-04-30 07:40:50 -0700229 .isTrue();
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000230 }
231
Dmitry Lomov9d74eba2015-11-26 11:04:01 +0000232 private static String getFalseCommand() {
Yun Peng7e4c9d52020-01-15 07:28:07 -0800233 if (OS.getCurrent() == OS.WINDOWS) {
234 // No false command on Windows, we use help.exe as an alternative,
235 // the caveat is that the command will have some output to stdout.
236 // Default exit code of help is 1
237 return getWinSystemBinary("help.exe");
238 }
Dmitry Lomov9d74eba2015-11-26 11:04:01 +0000239 return OS.getCurrent() == OS.DARWIN ? "/usr/bin/false" : "/bin/false";
240 }
241
242 private static String getTrueCommand() {
Yun Peng7e4c9d52020-01-15 07:28:07 -0800243 if (OS.getCurrent() == OS.WINDOWS) {
244 // No true command on Windows, we use whoami.exe as an alternative,
245 // the caveat is that the command will have some output to stdout.
246 // Default exit code of help is 0
247 return getWinSystemBinary("whoami.exe");
248 }
Dmitry Lomov9d74eba2015-11-26 11:04:01 +0000249 return OS.getCurrent() == OS.DARWIN ? "/usr/bin/true" : "/bin/true";
250 }
251
Florian Weikertc4975fa2015-12-03 10:27:10 +0000252 @Test
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000253 public void testBinEchoPrintsArguments() throws Exception {
Yun Peng7e4c9d52020-01-15 07:28:07 -0800254 Spawn spawn;
255 if (OS.getCurrent() == OS.WINDOWS) {
256 spawn = createSpawn(CMD_EXE, "/c", "echo", "Hello,", "world.");
257 } else {
258 spawn = createSpawn("/bin/echo", "Hello,", "world.");
259 }
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000260 run(spawn);
Yun Peng7e4c9d52020-01-15 07:28:07 -0800261 assertThat(out()).isEqualTo("Hello, world." + System.lineSeparator());
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000262 assertThat(err()).isEmpty();
263 }
264
Florian Weikertc4975fa2015-12-03 10:27:10 +0000265 @Test
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000266 public void testCommandRunsInWorkingDir() throws Exception {
Yun Peng7e4c9d52020-01-15 07:28:07 -0800267 Spawn spawn;
268 if (OS.getCurrent() == OS.WINDOWS) {
269 spawn = createSpawn(CMD_EXE, "/c", "cd");
270 } else {
271 spawn = createSpawn("/bin/pwd");
272 }
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000273 run(spawn);
Yun Peng7e4c9d52020-01-15 07:28:07 -0800274 assertThat(out().replace('\\', '/')).isEqualTo(executor.getExecRoot() + System.lineSeparator());
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000275 }
276
Florian Weikertc4975fa2015-12-03 10:27:10 +0000277 @Test
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000278 public void testCommandHonorsEnvironment() throws Exception {
ulfjacke4cca142020-01-08 04:44:40 -0800279 Spawn spawn =
280 new SimpleSpawn(
281 new ActionsTestUtil.NullAction(),
Yun Peng7e4c9d52020-01-15 07:28:07 -0800282 OS.getCurrent() == OS.WINDOWS
283 ? ImmutableList.of(CMD_EXE, "/c", "set")
284 : ImmutableList.of("/usr/bin/env"),
ulfjacke4cca142020-01-08 04:44:40 -0800285 /*environment=*/ ImmutableMap.of("foo", "bar", "baz", "boo"),
286 /*executionInfo=*/ ImmutableMap.of(),
287 /*inputs=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
288 /*outputs=*/ ImmutableSet.of(),
289 ResourceSet.ZERO);
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000290 run(spawn);
Yun Peng7e4c9d52020-01-15 07:28:07 -0800291 HashSet<String> environment = Sets.newHashSet(out().split(System.lineSeparator()));
292 if (OS.getCurrent() == OS.WINDOWS || OS.getCurrent() == OS.DARWIN) {
293 // On Windows and macOS, we may have some other env vars
294 // (eg. SystemRoot or __CF_USER_TEXT_ENCODING).
295 assertThat(environment).contains("foo=bar");
296 assertThat(environment).contains("baz=boo");
297 } else {
298 assertThat(environment).isEqualTo(Sets.newHashSet("foo=bar", "baz=boo"));
299 }
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000300 }
301
Florian Weikertc4975fa2015-12-03 10:27:10 +0000302 @Test
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000303 public void testStandardError() throws Exception {
Yun Peng7e4c9d52020-01-15 07:28:07 -0800304 Spawn spawn;
305 if (OS.getCurrent() == OS.WINDOWS) {
306 spawn = createSpawn(CMD_EXE, "/c", "echo Oops!>&2");
307 } else {
308 spawn = createSpawn("/bin/sh", "-c", "echo Oops! >&2");
309 }
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000310 run(spawn);
Yun Peng7e4c9d52020-01-15 07:28:07 -0800311 assertThat(err()).isEqualTo("Oops!" + System.lineSeparator());
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000312 assertThat(out()).isEmpty();
313 }
Yun Peng7e4c9d52020-01-15 07:28:07 -0800314
315 /**
316 * Regression test for https://github.com/bazelbuild/bazel/issues/10572 Make sure we do have the
317 * command line executed in the error message of ActionExecutionException when --verbose_failures
318 * is enabled.
319 */
320 @Test
321 public void testVerboseFailures() {
322 ExecException e = assertThrows(ExecException.class, () -> run(createSpawn(getFalseCommand())));
janakrdf701352020-10-13 08:20:35 -0700323 ActionExecutionException actionExecutionException =
janakr15ee8372020-10-15 07:44:24 -0700324 e.toActionExecutionException(new NullAction());
Yun Peng7e4c9d52020-01-15 07:28:07 -0800325 assertWithMessage("got: " + actionExecutionException.getMessage())
326 .that(actionExecutionException.getMessage().contains("failed: error executing command"))
327 .isTrue();
328 }
Philipp Wollermann1ee94412015-11-25 13:52:17 +0000329}