blob: 548626253de030aa68bb345dad94cb4214180d40 [file] [log] [blame]
ruperts4050a892017-10-07 00:46:20 +02001// Copyright 2017 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.
14
15package com.google.devtools.build.lib.exec;
16
17import static com.google.common.truth.Truth.assertThat;
olaolac35fe502017-10-17 04:09:07 +020018import static java.nio.charset.StandardCharsets.UTF_8;
19import static org.junit.Assert.fail;
ruperts4050a892017-10-07 00:46:20 +020020import static org.mockito.Matchers.any;
21import static org.mockito.Mockito.when;
22
ruperts7967f332017-11-21 16:37:13 -080023import com.google.common.collect.ImmutableList;
ruperts4050a892017-10-07 00:46:20 +020024import com.google.common.collect.ImmutableMap;
ruperts4050a892017-10-07 00:46:20 +020025import com.google.common.collect.Iterables;
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -070026import com.google.common.collect.MoreCollectors;
ulfjack14bb5cd2018-11-29 04:30:26 -080027import com.google.devtools.build.lib.actions.ActionContext;
ruperts4050a892017-10-07 00:46:20 +020028import com.google.devtools.build.lib.actions.ActionExecutionContext;
ulfjack645fe0f2019-02-28 05:58:36 -080029import com.google.devtools.build.lib.actions.ActionExecutionException;
ulfjack14bb5cd2018-11-29 04:30:26 -080030import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
31import com.google.devtools.build.lib.actions.ActionKeyContext;
ruperts4050a892017-10-07 00:46:20 +020032import com.google.devtools.build.lib.actions.Artifact;
ulfjack0858ae12018-07-27 02:37:53 -070033import com.google.devtools.build.lib.actions.Spawn;
ruperts4050a892017-10-07 00:46:20 +020034import com.google.devtools.build.lib.actions.SpawnActionContext;
ulfjack895c43d2019-03-25 01:58:08 -070035import com.google.devtools.build.lib.actions.SpawnContinuation;
ruperts4050a892017-10-07 00:46:20 +020036import com.google.devtools.build.lib.actions.SpawnResult;
olaolac35fe502017-10-17 04:09:07 +020037import com.google.devtools.build.lib.actions.SpawnResult.Status;
ruperts4050a892017-10-07 00:46:20 +020038import com.google.devtools.build.lib.analysis.ConfiguredTarget;
ulfjack645fe0f2019-02-28 05:58:36 -080039import com.google.devtools.build.lib.analysis.test.TestActionContext;
ruperts4050a892017-10-07 00:46:20 +020040import com.google.devtools.build.lib.analysis.test.TestProvider;
41import com.google.devtools.build.lib.analysis.test.TestResult;
42import com.google.devtools.build.lib.analysis.test.TestRunnerAction;
43import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
ulfjack81eda1d2018-06-07 08:38:21 -070044import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestStatus;
ruperts4050a892017-10-07 00:46:20 +020045import com.google.devtools.build.lib.clock.BlazeClock;
ulfjack14bb5cd2018-11-29 04:30:26 -080046import com.google.devtools.build.lib.clock.Clock;
47import com.google.devtools.build.lib.events.ExtendedEventHandler;
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -070048import com.google.devtools.build.lib.events.StoredEventHandler;
olaolac35fe502017-10-17 04:09:07 +020049import com.google.devtools.build.lib.exec.TestStrategy.TestOutputFormat;
ulfjack3d8e51c2018-11-29 06:54:29 -080050import com.google.devtools.build.lib.util.OS;
olaolac35fe502017-10-17 04:09:07 +020051import com.google.devtools.build.lib.util.io.FileOutErr;
52import com.google.devtools.build.lib.vfs.FileSystemUtils;
ruperts4050a892017-10-07 00:46:20 +020053import com.google.devtools.build.lib.vfs.Path;
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -070054import com.google.devtools.build.lib.view.test.TestStatus.BlazeTestStatus;
olaolac35fe502017-10-17 04:09:07 +020055import com.google.devtools.common.options.Options;
ruperts4050a892017-10-07 00:46:20 +020056import java.io.IOException;
olaolac35fe502017-10-17 04:09:07 +020057import java.io.OutputStream;
ruperts02fb4bb2017-11-04 06:40:14 +010058import java.time.Duration;
ulfjack14bb5cd2018-11-29 04:30:26 -080059import java.util.ArrayList;
ruperts4050a892017-10-07 00:46:20 +020060import java.util.List;
ruperts4050a892017-10-07 00:46:20 +020061import org.junit.Before;
62import org.junit.Test;
63import org.junit.runner.RunWith;
64import org.junit.runners.JUnit4;
65import org.mockito.Mock;
66import org.mockito.MockitoAnnotations;
67
68/** Unit tests for {@link StandaloneTestStrategy}. */
69@RunWith(JUnit4.class)
70public final class StandaloneTestStrategyTest extends BuildViewTestCase {
71
72 private static class TestedStandaloneTestStrategy extends StandaloneTestStrategy {
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -070073 TestResult postedResult = null;
74
ruperts4050a892017-10-07 00:46:20 +020075 public TestedStandaloneTestStrategy(
76 ExecutionOptions executionOptions, BinTools binTools, Path tmpDirRoot) {
77 super(executionOptions, binTools, tmpDirRoot);
78 }
79
80 @Override
ulfjack14bb5cd2018-11-29 04:30:26 -080081 protected void postTestResult(
82 ActionExecutionContext actionExecutionContext, TestResult result) {
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -070083 postedResult = result;
ruperts4050a892017-10-07 00:46:20 +020084 }
85 }
86
ulfjack14bb5cd2018-11-29 04:30:26 -080087 private class FakeActionExecutionContext extends ActionExecutionContext {
88 private final SpawnActionContext spawnActionContext;
89
90 public FakeActionExecutionContext(
91 FileOutErr fileOutErr, SpawnActionContext spawnActionContext) {
92 super(
93 /* executor= */ null,
94 /* actionInputFileCache= */ null,
95 ActionInputPrefetcher.NONE,
96 new ActionKeyContext(),
97 /* metadataHandler= */ null,
98 fileOutErr,
janakraf5df292018-12-17 11:35:44 -080099 /*eventHandler=*/ null,
ulfjack14bb5cd2018-11-29 04:30:26 -0800100 /* clientEnv= */ ImmutableMap.of(),
101 /* topLevelFilesets= */ ImmutableMap.of(),
102 /* artifactExpander= */ null,
103 /* actionFileSystem= */ null,
104 /* skyframeDepsResult= */ null);
105 this.spawnActionContext = spawnActionContext;
106 }
107
108 @Override
109 public Clock getClock() {
110 return BlazeClock.instance();
111 }
112
113 @Override
114 public <T extends ActionContext> T getContext(Class<? extends T> type) {
115 return SpawnActionContext.class.equals(type) ? type.cast(spawnActionContext) : null;
116 }
117
118 @Override
119 public ExtendedEventHandler getEventHandler() {
120 return storedEvents;
121 }
122
123 @Override
124 public Path getExecRoot() {
125 return outputBase.getRelative("execroot");
126 }
127
128 @Override
129 public ActionExecutionContext withFileOutErr(FileOutErr fileOutErr) {
130 return new FakeActionExecutionContext(fileOutErr, spawnActionContext);
131 }
132 }
ruperts4050a892017-10-07 00:46:20 +0200133
134 @Mock private SpawnActionContext spawnActionContext;
135
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700136 private StoredEventHandler storedEvents = new StoredEventHandler();
137
ruperts4050a892017-10-07 00:46:20 +0200138 @Before
139 public final void setUp() throws Exception {
140 MockitoAnnotations.initMocks(this);
141 }
142
ulfjack14bb5cd2018-11-29 04:30:26 -0800143 private FileOutErr createTempOutErr(Path tmpDirRoot) {
144 Path outPath = tmpDirRoot.getRelative("test-out.txt");
145 Path errPath = tmpDirRoot.getRelative("test-err.txt");
146 return new FileOutErr(outPath, errPath);
147 }
148
149 private TestRunnerAction getTestAction(String target) throws Exception {
150 ConfiguredTarget configuredTarget = getConfiguredTarget(target);
151 List<Artifact> testStatusArtifacts =
152 configuredTarget.getProvider(TestProvider.class).getTestParams().getTestStatusArtifacts();
153 Artifact testStatusArtifact = Iterables.getOnlyElement(testStatusArtifacts);
154 TestRunnerAction action = (TestRunnerAction) getGeneratingAction(testStatusArtifact);
155 action.getTestLog().getPath().getParentDirectory().createDirectoryAndParents();
156 return action;
157 }
158
ulfjack645fe0f2019-02-28 05:58:36 -0800159 private List<SpawnResult> execute(
160 TestRunnerAction testRunnerAction,
161 ActionExecutionContext actionExecutionContext,
162 TestActionContext testActionContext)
163 throws ActionExecutionException, InterruptedException {
164 return testRunnerAction.execute(actionExecutionContext, testActionContext).spawnResults();
165 }
166
ruperts4050a892017-10-07 00:46:20 +0200167 @Test
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700168 public void testRunTestOnce() throws Exception {
ruperts4050a892017-10-07 00:46:20 +0200169 ExecutionOptions executionOptions = ExecutionOptions.DEFAULTS;
170 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
ulfjack0588ba02018-02-15 10:40:26 -0800171 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
ruperts4050a892017-10-07 00:46:20 +0200172 TestedStandaloneTestStrategy standaloneTestStrategy =
173 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
174
175 // setup a test action
olaolac35fe502017-10-17 04:09:07 +0200176 scratch.file("standalone/simple_test.sh", "this does not get executed, it is mocked out");
ruperts4050a892017-10-07 00:46:20 +0200177 scratch.file(
178 "standalone/BUILD",
179 "sh_test(",
180 " name = \"simple_test\",",
181 " size = \"small\",",
182 " srcs = [\"simple_test.sh\"],",
183 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800184 TestRunnerAction testRunnerAction = getTestAction("//standalone:simple_test");
ruperts4050a892017-10-07 00:46:20 +0200185
ruperts4050a892017-10-07 00:46:20 +0200186 SpawnResult expectedSpawnResult =
ruperts02fb4bb2017-11-04 06:40:14 +0100187 new SpawnResult.Builder()
188 .setStatus(Status.SUCCESS)
189 .setWallTime(Duration.ofMillis(10))
Googler4dd6f002018-03-27 08:15:39 -0700190 .setRunnerName("test")
ruperts02fb4bb2017-11-04 06:40:14 +0100191 .build();
ulfjack895c43d2019-03-25 01:58:08 -0700192 when(spawnActionContext.beginExecution(any(), any()))
193 .thenReturn(SpawnContinuation.immediate(expectedSpawnResult));
ruperts4050a892017-10-07 00:46:20 +0200194
ulfjack14bb5cd2018-11-29 04:30:26 -0800195 ActionExecutionContext actionExecutionContext =
196 new FakeActionExecutionContext(createTempOutErr(tmpDirRoot), spawnActionContext);
ruperts4050a892017-10-07 00:46:20 +0200197
198 // actual StandaloneTestStrategy execution
ruperts7967f332017-11-21 16:37:13 -0800199 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800200 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
ruperts4050a892017-10-07 00:46:20 +0200201
ulfjack14bb5cd2018-11-29 04:30:26 -0800202 assertThat(spawnResults).contains(expectedSpawnResult);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700203 TestResult result = standaloneTestStrategy.postedResult;
204 assertThat(result).isNotNull();
205 assertThat(result.isCached()).isFalse();
cpovirka4d3da62019-05-02 14:27:33 -0700206 assertThat(result.getTestAction()).isSameInstanceAs(testRunnerAction);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700207 assertThat(result.getData().getTestPassed()).isTrue();
208 assertThat(result.getData().getRemotelyCached()).isFalse();
209 assertThat(result.getData().getIsRemoteStrategy()).isFalse();
210 assertThat(result.getData().getRunDurationMillis()).isEqualTo(10);
211 assertThat(result.getData().getTestTimesList()).containsExactly(10L);
212 TestAttempt attempt =
213 storedEvents
214 .getPosts()
215 .stream()
216 .filter(TestAttempt.class::isInstance)
217 .map(TestAttempt.class::cast)
218 .collect(MoreCollectors.onlyElement());
219 assertThat(attempt.getExecutionInfo().getStrategy()).isEqualTo("test");
220 assertThat(attempt.getExecutionInfo().getHostname()).isEqualTo("");
221 }
222
223 @Test
224 public void testRunFlakyTest() throws Exception {
ulfjack14bb5cd2018-11-29 04:30:26 -0800225 ExecutionOptions executionOptions = Options.getDefaults(ExecutionOptions.class);
226 // TODO(ulfjack): Update this test for split xml generation.
227 executionOptions.splitXmlGeneration = false;
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700228
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700229 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
230 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
231 TestedStandaloneTestStrategy standaloneTestStrategy =
232 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
233
234 // setup a test action
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700235 scratch.file("standalone/simple_test.sh", "this does not get executed, it is mocked out");
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700236 scratch.file(
237 "standalone/BUILD",
238 "sh_test(",
239 " name = \"simple_test\",",
240 " size = \"small\",",
241 " srcs = [\"simple_test.sh\"],",
242 " flaky = True,",
243 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800244 TestRunnerAction testRunnerAction = getTestAction("//standalone:simple_test");
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700245
246 SpawnResult failSpawnResult =
247 new SpawnResult.Builder()
248 .setStatus(Status.NON_ZERO_EXIT)
249 .setExitCode(1)
250 .setWallTime(Duration.ofMillis(10))
251 .setRunnerName("test")
252 .build();
253 SpawnResult passSpawnResult =
254 new SpawnResult.Builder()
255 .setStatus(Status.SUCCESS)
256 .setWallTime(Duration.ofMillis(15))
257 .setRunnerName("test")
258 .build();
ulfjack895c43d2019-03-25 01:58:08 -0700259 when(spawnActionContext.beginExecution(any(), any()))
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700260 .thenThrow(new SpawnExecException("test failed", failSpawnResult, false))
ulfjack895c43d2019-03-25 01:58:08 -0700261 .thenReturn(SpawnContinuation.immediate(passSpawnResult));
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700262
ulfjack14bb5cd2018-11-29 04:30:26 -0800263 ActionExecutionContext actionExecutionContext =
264 new FakeActionExecutionContext(createTempOutErr(tmpDirRoot), spawnActionContext);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700265
266 // actual StandaloneTestStrategy execution
267 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800268 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700269
ulfjackb70f0c12019-02-27 07:23:38 -0800270 assertThat(spawnResults).containsExactly(failSpawnResult, passSpawnResult).inOrder();
ulfjack14bb5cd2018-11-29 04:30:26 -0800271
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700272 TestResult result = standaloneTestStrategy.postedResult;
273 assertThat(result).isNotNull();
274 assertThat(result.isCached()).isFalse();
cpovirka4d3da62019-05-02 14:27:33 -0700275 assertThat(result.getTestAction()).isSameInstanceAs(testRunnerAction);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700276 assertThat(result.getData().getStatus()).isEqualTo(BlazeTestStatus.FLAKY);
277 assertThat(result.getData().getTestPassed()).isTrue();
278 assertThat(result.getData().getRemotelyCached()).isFalse();
279 assertThat(result.getData().getIsRemoteStrategy()).isFalse();
280 assertThat(result.getData().getRunDurationMillis()).isEqualTo(15L);
281 assertThat(result.getData().getTestTimesList()).containsExactly(10L, 15L);
282 List<TestAttempt> attempts =
283 storedEvents
284 .getPosts()
285 .stream()
286 .filter(TestAttempt.class::isInstance)
287 .map(TestAttempt.class::cast)
288 .collect(ImmutableList.toImmutableList());
289 assertThat(attempts).hasSize(2);
290 TestAttempt failedAttempt = attempts.get(0);
291 assertThat(failedAttempt.getExecutionInfo().getStrategy()).isEqualTo("test");
292 assertThat(failedAttempt.getExecutionInfo().getHostname()).isEqualTo("");
ulfjack81eda1d2018-06-07 08:38:21 -0700293 assertThat(failedAttempt.getStatus()).isEqualTo(TestStatus.FAILED);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700294 assertThat(failedAttempt.getExecutionInfo().getCachedRemotely()).isFalse();
295 TestAttempt okAttempt = attempts.get(1);
ulfjack81eda1d2018-06-07 08:38:21 -0700296 assertThat(okAttempt.getStatus()).isEqualTo(TestStatus.PASSED);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700297 assertThat(okAttempt.getExecutionInfo().getStrategy()).isEqualTo("test");
298 assertThat(okAttempt.getExecutionInfo().getHostname()).isEqualTo("");
299 }
300
301 @Test
302 public void testRunTestRemotely() throws Exception {
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700303 ExecutionOptions executionOptions = ExecutionOptions.DEFAULTS;
304 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
305 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
306 TestedStandaloneTestStrategy standaloneTestStrategy =
307 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
308
309 // setup a test action
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700310 scratch.file("standalone/simple_test.sh", "this does not get executed, it is mocked out");
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700311 scratch.file(
312 "standalone/BUILD",
313 "sh_test(",
314 " name = \"simple_test\",",
315 " size = \"small\",",
316 " srcs = [\"simple_test.sh\"],",
317 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800318 TestRunnerAction testRunnerAction = getTestAction("//standalone:simple_test");
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700319
320 SpawnResult expectedSpawnResult =
321 new SpawnResult.Builder()
322 .setStatus(Status.SUCCESS)
323 .setWallTime(Duration.ofMillis(10))
324 .setRunnerName("remote")
325 .setExecutorHostname("a-remote-host")
326 .build();
ulfjack895c43d2019-03-25 01:58:08 -0700327 when(spawnActionContext.beginExecution(any(), any()))
328 .thenReturn(SpawnContinuation.immediate(expectedSpawnResult));
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700329
ulfjack14bb5cd2018-11-29 04:30:26 -0800330 ActionExecutionContext actionExecutionContext =
331 new FakeActionExecutionContext(createTempOutErr(tmpDirRoot), spawnActionContext);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700332
333 // actual StandaloneTestStrategy execution
334 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800335 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700336
ulfjack14bb5cd2018-11-29 04:30:26 -0800337 assertThat(spawnResults).contains(expectedSpawnResult);
338
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700339 TestResult result = standaloneTestStrategy.postedResult;
340 assertThat(result).isNotNull();
341 assertThat(result.isCached()).isFalse();
cpovirka4d3da62019-05-02 14:27:33 -0700342 assertThat(result.getTestAction()).isSameInstanceAs(testRunnerAction);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700343 assertThat(result.getData().getTestPassed()).isTrue();
344 assertThat(result.getData().getRemotelyCached()).isFalse();
345 assertThat(result.getData().getIsRemoteStrategy()).isTrue();
346 assertThat(result.getData().getRunDurationMillis()).isEqualTo(10);
347 assertThat(result.getData().getTestTimesList()).containsExactly(10L);
348 TestAttempt attempt =
349 storedEvents
350 .getPosts()
351 .stream()
352 .filter(TestAttempt.class::isInstance)
353 .map(TestAttempt.class::cast)
354 .collect(MoreCollectors.onlyElement());
ulfjack81eda1d2018-06-07 08:38:21 -0700355 assertThat(attempt.getStatus()).isEqualTo(TestStatus.PASSED);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700356 assertThat(attempt.getExecutionInfo().getStrategy()).isEqualTo("remote");
357 assertThat(attempt.getExecutionInfo().getHostname()).isEqualTo("a-remote-host");
358 }
359
360 @Test
361 public void testRunRemotelyCachedTest() throws Exception {
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700362 ExecutionOptions executionOptions = ExecutionOptions.DEFAULTS;
363 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
364 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
365 TestedStandaloneTestStrategy standaloneTestStrategy =
366 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
367
368 // setup a test action
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700369 scratch.file("standalone/simple_test.sh", "this does not get executed, it is mocked out");
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700370 scratch.file(
371 "standalone/BUILD",
372 "sh_test(",
373 " name = \"simple_test\",",
374 " size = \"small\",",
375 " srcs = [\"simple_test.sh\"],",
376 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800377 TestRunnerAction testRunnerAction = getTestAction("//standalone:simple_test");
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700378
379 SpawnResult expectedSpawnResult =
380 new SpawnResult.Builder()
381 .setStatus(Status.SUCCESS)
382 .setCacheHit(true)
383 .setWallTime(Duration.ofMillis(10))
384 .setRunnerName("remote cache")
385 .build();
ulfjack895c43d2019-03-25 01:58:08 -0700386 when(spawnActionContext.beginExecution(any(), any()))
387 .thenReturn(SpawnContinuation.immediate(expectedSpawnResult));
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700388
ulfjack14bb5cd2018-11-29 04:30:26 -0800389 ActionExecutionContext actionExecutionContext =
390 new FakeActionExecutionContext(createTempOutErr(tmpDirRoot), spawnActionContext);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700391
392 // actual StandaloneTestStrategy execution
393 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800394 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700395
ruperts4050a892017-10-07 00:46:20 +0200396 // check that the rigged SpawnResult was returned
ulfjack14bb5cd2018-11-29 04:30:26 -0800397 assertThat(spawnResults).contains(expectedSpawnResult);
398
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700399 TestResult result = standaloneTestStrategy.postedResult;
400 assertThat(result).isNotNull();
401 assertThat(result.isCached()).isFalse();
cpovirka4d3da62019-05-02 14:27:33 -0700402 assertThat(result.getTestAction()).isSameInstanceAs(testRunnerAction);
Benjamin Peterson1bbeadc2018-04-26 05:27:10 -0700403 assertThat(result.getData().getTestPassed()).isTrue();
404 assertThat(result.getData().getRemotelyCached()).isTrue();
405 assertThat(result.getData().getIsRemoteStrategy()).isFalse();
406 assertThat(result.getData().getRunDurationMillis()).isEqualTo(10);
407 assertThat(result.getData().getTestTimesList()).containsExactly(10L);
408 TestAttempt attempt =
409 storedEvents
410 .getPosts()
411 .stream()
412 .filter(TestAttempt.class::isInstance)
413 .map(TestAttempt.class::cast)
414 .collect(MoreCollectors.onlyElement());
415 assertThat(attempt.getExecutionInfo().getStrategy()).isEqualTo("remote cache");
416 assertThat(attempt.getExecutionInfo().getHostname()).isEqualTo("");
olaolac35fe502017-10-17 04:09:07 +0200417 }
418
419 @Test
420 public void testThatTestLogAndOutputAreReturned() throws Exception {
olaolac35fe502017-10-17 04:09:07 +0200421 ExecutionOptions executionOptions = Options.getDefaults(ExecutionOptions.class);
422 executionOptions.testOutput = TestOutputFormat.ERRORS;
423 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
ulfjack0588ba02018-02-15 10:40:26 -0800424 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
olaolac35fe502017-10-17 04:09:07 +0200425 TestedStandaloneTestStrategy standaloneTestStrategy =
426 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
427
428 // setup a test action
olaolac35fe502017-10-17 04:09:07 +0200429 scratch.file("standalone/failing_test.sh", "this does not get executed, it is mocked out");
olaolac35fe502017-10-17 04:09:07 +0200430 scratch.file(
431 "standalone/BUILD",
432 "sh_test(",
433 " name = \"failing_test\",",
434 " size = \"small\",",
435 " srcs = [\"failing_test.sh\"],",
436 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800437 TestRunnerAction testRunnerAction = getTestAction("//standalone:failing_test");
olaolac35fe502017-10-17 04:09:07 +0200438
439 SpawnResult expectedSpawnResult =
Googler4dd6f002018-03-27 08:15:39 -0700440 new SpawnResult.Builder()
441 .setStatus(Status.NON_ZERO_EXIT)
442 .setExitCode(1)
443 .setRunnerName("test")
444 .build();
ulfjack895c43d2019-03-25 01:58:08 -0700445 when(spawnActionContext.beginExecution(any(), any()))
ulfjack14bb5cd2018-11-29 04:30:26 -0800446 .thenAnswer(
447 (invocation) -> {
Googlerf1bbbff2019-03-19 07:31:40 -0700448 Spawn spawn = invocation.getArgument(0);
ulfjack14bb5cd2018-11-29 04:30:26 -0800449 if (spawn.getOutputFiles().size() != 1) {
Googlerf1bbbff2019-03-19 07:31:40 -0700450 ActionExecutionContext context = invocation.getArgument(1);
451 FileOutErr outErr = context.getFileOutErr();
ulfjack14bb5cd2018-11-29 04:30:26 -0800452 try (OutputStream stream = outErr.getOutputStream()) {
453 stream.write("This will not appear in the test output: bla\n".getBytes(UTF_8));
454 stream.write((TestLogHelper.HEADER_DELIMITER + "\n").getBytes(UTF_8));
455 stream.write("This will appear in the test output: foo\n".getBytes(UTF_8));
456 }
457 throw new SpawnExecException(
458 "Failure!!",
459 expectedSpawnResult,
460 /*forciblyRunRemotely=*/ false,
461 /*catastrophe=*/ false);
462 } else {
ulfjack895c43d2019-03-25 01:58:08 -0700463 return SpawnContinuation.immediate(
ulfjack14bb5cd2018-11-29 04:30:26 -0800464 new SpawnResult.Builder()
465 .setStatus(Status.SUCCESS)
466 .setRunnerName("test")
467 .build());
468 }
469 });
470
471 FileOutErr outErr = createTempOutErr(tmpDirRoot);
472 ActionExecutionContext actionExecutionContext =
473 new FakeActionExecutionContext(outErr, spawnActionContext);
olaolac35fe502017-10-17 04:09:07 +0200474
475 // actual StandaloneTestStrategy execution
ruperts7967f332017-11-21 16:37:13 -0800476 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800477 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
olaolac35fe502017-10-17 04:09:07 +0200478
479 // check that the rigged SpawnResult was returned
ulfjack14bb5cd2018-11-29 04:30:26 -0800480 assertThat(spawnResults).contains(expectedSpawnResult);
olaolac35fe502017-10-17 04:09:07 +0200481 // check that the test log contains all the output
482 try {
483 String logData = FileSystemUtils.readContent(testRunnerAction.getTestLog().getPath(), UTF_8);
484 assertThat(logData).contains("bla");
485 assertThat(logData).contains(TestLogHelper.HEADER_DELIMITER);
486 assertThat(logData).contains("foo");
487 } catch (IOException e) {
488 fail("Test log missing: " + testRunnerAction.getTestLog().getPath());
489 }
490 // check that the test stdout contains all the expected output
491 outErr.close(); // Create the output files.
492 try {
ulfjack14bb5cd2018-11-29 04:30:26 -0800493 String outData = FileSystemUtils.readContent(outErr.getOutputPath(), UTF_8);
olaolac35fe502017-10-17 04:09:07 +0200494 assertThat(outData)
495 .contains("==================== Test output for //standalone:failing_test:");
496 assertThat(outData).doesNotContain("bla");
497 assertThat(outData).doesNotContain(TestLogHelper.HEADER_DELIMITER);
498 assertThat(outData).contains("foo");
499 assertThat(outData)
500 .contains(
501 "================================================================================");
502 } catch (IOException e) {
ulfjack14bb5cd2018-11-29 04:30:26 -0800503 fail("Test stdout file missing: " + outErr.getOutputPath());
olaolac35fe502017-10-17 04:09:07 +0200504 }
ulfjack14bb5cd2018-11-29 04:30:26 -0800505 assertThat(outErr.getErrorPath().exists()).isFalse();
olaolac35fe502017-10-17 04:09:07 +0200506 }
507
508 @Test
ulfjack0858ae12018-07-27 02:37:53 -0700509 public void testThatTestLogAndOutputAreReturnedWithSplitXmlGeneration() throws Exception {
ulfjack0858ae12018-07-27 02:37:53 -0700510 ExecutionOptions executionOptions = Options.getDefaults(ExecutionOptions.class);
511 executionOptions.testOutput = TestOutputFormat.ERRORS;
512 executionOptions.splitXmlGeneration = true;
513 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
514 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
515 TestedStandaloneTestStrategy standaloneTestStrategy =
516 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
517
518 // setup a test action
ulfjack0858ae12018-07-27 02:37:53 -0700519 scratch.file("standalone/failing_test.sh", "this does not get executed, it is mocked out");
ulfjack0858ae12018-07-27 02:37:53 -0700520 scratch.file(
521 "standalone/BUILD",
522 "sh_test(",
523 " name = \"failing_test\",",
524 " size = \"small\",",
525 " srcs = [\"failing_test.sh\"],",
Jakob Buchgraber803801d2019-03-21 09:22:58 -0700526 " tags = [\"local\"],",
ulfjack0858ae12018-07-27 02:37:53 -0700527 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800528 TestRunnerAction testRunnerAction = getTestAction("//standalone:failing_test");
ulfjack0858ae12018-07-27 02:37:53 -0700529
530 SpawnResult testSpawnResult =
531 new SpawnResult.Builder()
532 .setStatus(Status.NON_ZERO_EXIT)
533 .setExitCode(1)
534 .setRunnerName("test")
535 .build();
ulfjack0858ae12018-07-27 02:37:53 -0700536 SpawnResult xmlGeneratorSpawnResult =
537 new SpawnResult.Builder()
538 .setStatus(Status.SUCCESS)
539 .setRunnerName("test")
540 .build();
ulfjack14bb5cd2018-11-29 04:30:26 -0800541 List<FileOutErr> called = new ArrayList<>();
ulfjack895c43d2019-03-25 01:58:08 -0700542 when(spawnActionContext.beginExecution(any(), any()))
ulfjack14bb5cd2018-11-29 04:30:26 -0800543 .thenAnswer(
544 (invocation) -> {
Googlerf1bbbff2019-03-19 07:31:40 -0700545 Spawn spawn = invocation.getArgument(0);
Jakob Buchgraber803801d2019-03-21 09:22:58 -0700546 // Test that both spawns have the local tag attached as a execution info
547 assertThat(spawn.getExecutionInfo()).containsKey("local");
Googlerf1bbbff2019-03-19 07:31:40 -0700548 ActionExecutionContext context = invocation.getArgument(1);
549 FileOutErr outErr = context.getFileOutErr();
ulfjack14bb5cd2018-11-29 04:30:26 -0800550 called.add(outErr);
551 if (spawn.getOutputFiles().size() != 1) {
552 try (OutputStream stream = outErr.getOutputStream()) {
553 stream.write("This will not appear in the test output: bla\n".getBytes(UTF_8));
554 stream.write((TestLogHelper.HEADER_DELIMITER + "\n").getBytes(UTF_8));
555 stream.write("This will appear in the test output: foo\n".getBytes(UTF_8));
556 }
557 throw new SpawnExecException(
558 "Failure!!",
559 testSpawnResult,
560 /*forciblyRunRemotely=*/ false,
561 /*catastrophe=*/ false);
562 } else {
ulfjack3d8e51c2018-11-29 06:54:29 -0800563 String testName =
564 OS.getCurrent() == OS.WINDOWS
565 ? "standalone/failing_test.exe"
566 : "standalone/failing_test";
567 assertThat(spawn.getEnvironment()).containsEntry("TEST_BINARY", testName);
ulfjack895c43d2019-03-25 01:58:08 -0700568 return SpawnContinuation.immediate(xmlGeneratorSpawnResult);
ulfjack14bb5cd2018-11-29 04:30:26 -0800569 }
570 });
571
572 FileOutErr outErr = createTempOutErr(tmpDirRoot);
573 ActionExecutionContext actionExecutionContext =
574 new FakeActionExecutionContext(outErr, spawnActionContext);
ulfjack0858ae12018-07-27 02:37:53 -0700575
576 // actual StandaloneTestStrategy execution
577 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800578 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
ulfjack0858ae12018-07-27 02:37:53 -0700579
580 // check that the rigged SpawnResult was returned
581 assertThat(spawnResults).containsExactly(testSpawnResult, xmlGeneratorSpawnResult);
582 // check that the test log contains all the output
583 String logData = FileSystemUtils.readContent(testRunnerAction.getTestLog().getPath(), UTF_8);
584 assertThat(logData).contains("bla");
585 assertThat(logData).contains(TestLogHelper.HEADER_DELIMITER);
586 assertThat(logData).contains("foo");
587 // check that the test stdout contains all the expected output
588 outErr.close(); // Create the output files.
ulfjack14bb5cd2018-11-29 04:30:26 -0800589 String outData = FileSystemUtils.readContent(outErr.getOutputPath(), UTF_8);
ulfjack0858ae12018-07-27 02:37:53 -0700590 assertThat(outData)
591 .contains("==================== Test output for //standalone:failing_test:");
592 assertThat(outData).doesNotContain("bla");
593 assertThat(outData).doesNotContain(TestLogHelper.HEADER_DELIMITER);
594 assertThat(outData).contains("foo");
595 assertThat(outData)
596 .contains(
597 "================================================================================");
ulfjack14bb5cd2018-11-29 04:30:26 -0800598 assertThat(outErr.getErrorPath().exists()).isFalse();
599 assertThat(called).hasSize(2);
600 assertThat(called).containsNoDuplicates();
ulfjack0858ae12018-07-27 02:37:53 -0700601 }
602
603 @Test
olaolac35fe502017-10-17 04:09:07 +0200604 public void testEmptyOutputCreatesEmptyLogFile() throws Exception {
olaolac35fe502017-10-17 04:09:07 +0200605 ExecutionOptions executionOptions = Options.getDefaults(ExecutionOptions.class);
606 executionOptions.testOutput = TestOutputFormat.ALL;
607 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
ulfjack0588ba02018-02-15 10:40:26 -0800608 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
olaolac35fe502017-10-17 04:09:07 +0200609 TestedStandaloneTestStrategy standaloneTestStrategy =
610 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
611
612 // setup a test action
613 scratch.file("standalone/empty_test.sh", "this does not get executed, it is mocked out");
614 scratch.file(
615 "standalone/BUILD",
616 "sh_test(",
617 " name = \"empty_test\",",
618 " size = \"small\",",
619 " srcs = [\"empty_test.sh\"],",
620 ")");
ulfjack14bb5cd2018-11-29 04:30:26 -0800621 TestRunnerAction testRunnerAction = getTestAction("//standalone:empty_test");
olaolac35fe502017-10-17 04:09:07 +0200622
Googler4dd6f002018-03-27 08:15:39 -0700623 SpawnResult expectedSpawnResult =
624 new SpawnResult.Builder().setStatus(Status.SUCCESS).setRunnerName("test").build();
ulfjack895c43d2019-03-25 01:58:08 -0700625 when(spawnActionContext.beginExecution(any(), any()))
626 .thenReturn(SpawnContinuation.immediate(expectedSpawnResult));
ulfjack14bb5cd2018-11-29 04:30:26 -0800627
628 FileOutErr outErr = createTempOutErr(tmpDirRoot);
629 ActionExecutionContext actionExecutionContext =
630 new FakeActionExecutionContext(outErr, spawnActionContext);
olaolac35fe502017-10-17 04:09:07 +0200631
632 // actual StandaloneTestStrategy execution
ruperts7967f332017-11-21 16:37:13 -0800633 List<SpawnResult> spawnResults =
ulfjack645fe0f2019-02-28 05:58:36 -0800634 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
olaolac35fe502017-10-17 04:09:07 +0200635
636 // check that the rigged SpawnResult was returned
ulfjack14bb5cd2018-11-29 04:30:26 -0800637 assertThat(spawnResults).contains(expectedSpawnResult);
olaolac35fe502017-10-17 04:09:07 +0200638 // check that the test log contains all the output
639 try {
640 String logData = FileSystemUtils.readContent(testRunnerAction.getTestLog().getPath(), UTF_8);
641 assertThat(logData).isEmpty();
642 } catch (IOException e) {
643 fail("Test log missing: " + testRunnerAction.getTestLog().getPath());
644 }
645 // check that the test stdout contains all the expected output
646 outErr.close(); // Create the output files.
647 try {
ulfjack14bb5cd2018-11-29 04:30:26 -0800648 String outData = FileSystemUtils.readContent(outErr.getOutputPath(), UTF_8);
olaolac35fe502017-10-17 04:09:07 +0200649 String emptyOutput =
650 "==================== Test output for //standalone:empty_test:(\\s)*"
651 + "================================================================================(\\s)*";
652 assertThat(outData).matches(emptyOutput);
653 } catch (IOException e) {
ulfjack14bb5cd2018-11-29 04:30:26 -0800654 fail("Test stdout file missing: " + outErr.getOutputPath());
olaolac35fe502017-10-17 04:09:07 +0200655 }
ulfjack14bb5cd2018-11-29 04:30:26 -0800656 assertThat(outErr.getErrorPath().exists()).isFalse();
shahan18726b72018-03-15 14:18:46 -0700657 }
ulfjack0ff19c62019-05-21 08:50:23 -0700658
659 @Test
660 public void testAppendStdErrDoesNotBusyLoop() throws Exception {
661 ExecutionOptions executionOptions = Options.getDefaults(ExecutionOptions.class);
662 executionOptions.testOutput = TestOutputFormat.ALL;
663 Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
664 BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
665 TestedStandaloneTestStrategy standaloneTestStrategy =
666 new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
667
668 // setup a test action
669 scratch.file("standalone/empty_test.sh", "this does not get executed, it is mocked out");
670 scratch.file(
671 "standalone/BUILD",
672 "sh_test(",
673 " name = \"empty_test\",",
674 " size = \"small\",",
675 " srcs = [\"empty_test.sh\"],",
676 ")");
677 TestRunnerAction testRunnerAction = getTestAction("//standalone:empty_test");
678
679 SpawnResult expectedSpawnResult =
680 new SpawnResult.Builder().setStatus(Status.SUCCESS).setRunnerName("test").build();
681 when(spawnActionContext.beginExecution(any(), any()))
682 .then(
683 (invocation) -> {
684 ((ActionExecutionContext) invocation.getArgument(1)).getFileOutErr().printErr("Foo");
685 return SpawnContinuation.immediate(expectedSpawnResult);
686 });
687
688 FileOutErr outErr = createTempOutErr(tmpDirRoot);
689 ActionExecutionContext actionExecutionContext =
690 new FakeActionExecutionContext(outErr, spawnActionContext);
691
692 // actual StandaloneTestStrategy execution
693 execute(testRunnerAction, actionExecutionContext, standaloneTestStrategy);
694
695 // check that the test stdout contains all the expected output
696 try {
697 String outData = FileSystemUtils.readContent(outErr.getOutputPath(), UTF_8);
698 assertThat(outData).contains("Foo");
699 } catch (IOException e) {
700 fail("Test stdout file missing: " + outErr.getOutputPath());
701 }
702 }
ruperts4050a892017-10-07 00:46:20 +0200703}