blob: d50717d9a7c289b4e0f2028f2562cf324ebe841e [file] [log] [blame]
Klaus Aehlig17325a12016-09-30 15:45:27 +00001// Copyright 2016 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.runtime;
15
16import static com.google.common.truth.Truth.assertThat;
lberkiaea56b32017-05-30 12:35:33 +020017import static com.google.common.truth.Truth.assertWithMessage;
Klaus Aehlig9b3b2e92017-05-02 11:18:42 +020018import static org.mockito.Mockito.times;
19import static org.mockito.Mockito.verify;
20import static org.mockito.Mockito.when;
Klaus Aehlig17325a12016-09-30 15:45:27 +000021
Klaus Aehlig0cce00c2017-05-08 08:26:03 -040022import com.google.common.collect.ImmutableList;
23import com.google.common.collect.ImmutableMap;
Klaus Aehlig17325a12016-09-30 15:45:27 +000024import com.google.common.collect.ImmutableSet;
buchgr9e0308e2017-04-25 16:38:45 +020025import com.google.common.eventbus.Subscribe;
buchgr0b937432017-04-06 18:54:22 +000026import com.google.common.util.concurrent.Futures;
buchgr9e0308e2017-04-25 16:38:45 +020027import com.google.common.util.concurrent.ListenableFuture;
lberki86266232018-04-11 00:33:42 -070028import com.google.devtools.build.lib.actions.ActionEnvironment;
ruperts76de73b2018-03-02 16:10:43 -080029import com.google.devtools.build.lib.actions.ActionExecutedEvent;
30import com.google.devtools.build.lib.actions.ActionExecutedEvent.ErrorTiming;
31import com.google.devtools.build.lib.actions.ActionExecutionException;
Klaus Aehligee3e1922017-04-07 14:25:27 +000032import com.google.devtools.build.lib.actions.Artifact;
tomlu1cdcdf92018-01-16 11:07:51 -080033import com.google.devtools.build.lib.actions.ArtifactRoot;
Klaus Aehligee3e1922017-04-07 14:25:27 +000034import com.google.devtools.build.lib.actions.EventReportingArtifacts;
ruperts76de73b2018-03-02 16:10:43 -080035import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
Klaus Aehlig0cce00c2017-05-08 08:26:03 -040036import com.google.devtools.build.lib.analysis.BlazeDirectories;
janakr3b63a4e2017-09-14 09:55:40 +020037import com.google.devtools.build.lib.analysis.ServerDirectories;
Klaus Aehlig0cce00c2017-05-08 08:26:03 -040038import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
Klaus Aehlig0cce00c2017-05-08 08:26:03 -040039import com.google.devtools.build.lib.analysis.config.BuildOptions;
40import com.google.devtools.build.lib.analysis.config.FragmentOptions;
buchgr9e0308e2017-04-25 16:38:45 +020041import com.google.devtools.build.lib.buildeventstream.AnnounceBuildEventTransportsEvent;
Klaus Aehligee3e1922017-04-07 14:25:27 +000042import com.google.devtools.build.lib.buildeventstream.ArtifactGroupNamer;
Klaus Aehlig17325a12016-09-30 15:45:27 +000043import com.google.devtools.build.lib.buildeventstream.BuildEvent;
ulfjack26e586d2018-05-17 08:42:13 -070044import com.google.devtools.build.lib.buildeventstream.BuildEventContext;
Klaus Aehlig17325a12016-09-30 15:45:27 +000045import com.google.devtools.build.lib.buildeventstream.BuildEventId;
ulfjackfbf27562018-05-18 12:46:54 -070046import com.google.devtools.build.lib.buildeventstream.BuildEventProtocolOptions;
Klaus Aehligf75878d2016-11-21 13:41:16 +000047import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
Klaus Aehligee3e1922017-04-07 14:25:27 +000048import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.NamedSetOfFilesId;
Klaus Aehlig17325a12016-09-30 15:45:27 +000049import com.google.devtools.build.lib.buildeventstream.BuildEventTransport;
buchgr9e0308e2017-04-25 16:38:45 +020050import com.google.devtools.build.lib.buildeventstream.BuildEventTransportClosedEvent;
Klaus Aehliga708a022017-07-11 12:54:40 +020051import com.google.devtools.build.lib.buildeventstream.BuildEventWithConfiguration;
Klaus Aehligf75878d2016-11-21 13:41:16 +000052import com.google.devtools.build.lib.buildeventstream.BuildEventWithOrderConstraint;
Klaus Aehlig17325a12016-09-30 15:45:27 +000053import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent;
Klaus Aehligee3e1922017-04-07 14:25:27 +000054import com.google.devtools.build.lib.buildeventstream.PathConverter;
Klaus Aehlig17325a12016-09-30 15:45:27 +000055import com.google.devtools.build.lib.buildeventstream.ProgressEvent;
ruperts76de73b2018-03-02 16:10:43 -080056import com.google.devtools.build.lib.buildeventstream.transports.BuildEventStreamOptions;
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +000057import com.google.devtools.build.lib.buildtool.BuildResult;
Klaus Aehlig17325a12016-09-30 15:45:27 +000058import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
Klaus Aehligee3e1922017-04-07 14:25:27 +000059import com.google.devtools.build.lib.collect.nestedset.NestedSet;
60import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
61import com.google.devtools.build.lib.collect.nestedset.NestedSetView;
62import com.google.devtools.build.lib.testutil.FoundationTestCase;
63import com.google.devtools.build.lib.vfs.Path;
64import com.google.devtools.build.lib.vfs.PathFragment;
tomluee6a6862018-01-17 14:36:26 -080065import com.google.devtools.build.lib.vfs.Root;
ulfjackfbf27562018-05-18 12:46:54 -070066import com.google.devtools.common.options.Options;
Klaus Aehlig17325a12016-09-30 15:45:27 +000067import java.util.ArrayList;
Klaus Aehligf75878d2016-11-21 13:41:16 +000068import java.util.Collection;
buchgr9e0308e2017-04-25 16:38:45 +020069import java.util.Collections;
70import java.util.HashSet;
Klaus Aehlig17325a12016-09-30 15:45:27 +000071import java.util.List;
buchgr9e0308e2017-04-25 16:38:45 +020072import java.util.Set;
73import java.util.concurrent.TimeUnit;
74import java.util.concurrent.locks.LockSupport;
75import org.junit.Before;
Klaus Aehlig17325a12016-09-30 15:45:27 +000076import org.junit.Test;
77import org.junit.runner.RunWith;
78import org.junit.runners.JUnit4;
Klaus Aehlig9b3b2e92017-05-02 11:18:42 +020079import org.mockito.Mockito;
buchgr9e0308e2017-04-25 16:38:45 +020080import org.mockito.MockitoAnnotations;
Klaus Aehlig17325a12016-09-30 15:45:27 +000081
82/** Tests {@link BuildEventStreamer}. */
83@RunWith(JUnit4.class)
Klaus Aehligee3e1922017-04-07 14:25:27 +000084public class BuildEventStreamerTest extends FoundationTestCase {
Klaus Aehlig17325a12016-09-30 15:45:27 +000085
ruperts76de73b2018-03-02 16:10:43 -080086 private static final ActionExecutedEvent SUCCESSFUL_ACTION_EXECUTED_EVENT =
87 new ActionExecutedEvent(
88 new ActionsTestUtil.NullAction(),
89 /* exception= */ null,
90 /* stdout= */ null,
91 /* stderr= */ null,
92 ErrorTiming.NO_ERROR);
93
Klaus Aehlig17325a12016-09-30 15:45:27 +000094 private static class RecordingBuildEventTransport implements BuildEventTransport {
Klaus Aehligee3e1922017-04-07 14:25:27 +000095 private final List<BuildEvent> events = new ArrayList<>();
96 private final List<BuildEventStreamProtos.BuildEvent> eventsAsProtos = new ArrayList<>();
Klaus Aehlig17325a12016-09-30 15:45:27 +000097
98 @Override
buchgr9e0308e2017-04-25 16:38:45 +020099 public String name() {
100 return this.getClass().getSimpleName();
101 }
102
103 @Override
Klaus Aehligee3e1922017-04-07 14:25:27 +0000104 public void sendBuildEvent(BuildEvent event, final ArtifactGroupNamer namer) {
Klaus Aehlig17325a12016-09-30 15:45:27 +0000105 events.add(event);
Klaus Aehligee3e1922017-04-07 14:25:27 +0000106 eventsAsProtos.add(
107 event.asStreamProto(
ulfjack26e586d2018-05-17 08:42:13 -0700108 new BuildEventContext() {
Klaus Aehligee3e1922017-04-07 14:25:27 +0000109 @Override
110 public ArtifactGroupNamer artifactGroupNamer() {
111 return namer;
112 }
113
114 @Override
115 public PathConverter pathConverter() {
116 return new PathConverter() {
117 @Override
118 public String apply(Path path) {
119 return path.toString();
120 }
121 };
122 }
ulfjackfbf27562018-05-18 12:46:54 -0700123
124 @Override
125 public BuildEventProtocolOptions getOptions() {
126 return Options.getDefaults(BuildEventProtocolOptions.class);
127 }
Klaus Aehligee3e1922017-04-07 14:25:27 +0000128 }));
Klaus Aehlig17325a12016-09-30 15:45:27 +0000129 }
130
131 @Override
buchgr9e0308e2017-04-25 16:38:45 +0200132 public ListenableFuture<Void> close() {
buchgr0b937432017-04-06 18:54:22 +0000133 return Futures.immediateFuture(null);
134 }
Klaus Aehlig17325a12016-09-30 15:45:27 +0000135
buchgr0ca8f4b2017-09-12 13:49:21 +0200136 @Override
137 public void closeNow() {
138 }
139
Klaus Aehlig17325a12016-09-30 15:45:27 +0000140 List<BuildEvent> getEvents() {
141 return events;
142 }
Klaus Aehligee3e1922017-04-07 14:25:27 +0000143
144 List<BuildEventStreamProtos.BuildEvent> getEventProtos() {
145 return eventsAsProtos;
146 }
Klaus Aehlig17325a12016-09-30 15:45:27 +0000147 }
148
Klaus Aehligf75878d2016-11-21 13:41:16 +0000149 private static class GenericOrderEvent implements BuildEventWithOrderConstraint {
150 private final BuildEventId id;
151 private final Collection<BuildEventId> children;
152 private final Collection<BuildEventId> after;
153
154 GenericOrderEvent(
155 BuildEventId id, Collection<BuildEventId> children, Collection<BuildEventId> after) {
156 this.id = id;
157 this.children = children;
158 this.after = after;
159 }
160
161 GenericOrderEvent(BuildEventId id, Collection<BuildEventId> children) {
162 this(id, children, children);
163 }
164
165 @Override
166 public BuildEventId getEventId() {
167 return id;
168 }
169
170 @Override
171 public Collection<BuildEventId> getChildrenEvents() {
172 return children;
173 }
174
175 @Override
ulfjack26e586d2018-05-17 08:42:13 -0700176 public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext converters) {
Klaus Aehligf75878d2016-11-21 13:41:16 +0000177 return GenericBuildEvent.protoChaining(this).build();
178 }
179
180 @Override
181 public Collection<BuildEventId> postedAfter() {
182 return after;
183 }
184 }
185
Klaus Aehligee3e1922017-04-07 14:25:27 +0000186 private static class GenericArtifactReportingEvent implements EventReportingArtifacts {
187 private final BuildEventId id;
188 private final Collection<BuildEventId> children;
189 private final Collection<NestedSet<Artifact>> artifacts;
190
191 GenericArtifactReportingEvent(
192 BuildEventId id,
193 Collection<BuildEventId> children,
194 Collection<NestedSet<Artifact>> artifacts) {
195 this.id = id;
196 this.children = children;
197 this.artifacts = artifacts;
198 }
199
200 GenericArtifactReportingEvent(BuildEventId id, Collection<NestedSet<Artifact>> artifacts) {
201 this(id, ImmutableSet.<BuildEventId>of(), artifacts);
202 }
203
204 @Override
205 public BuildEventId getEventId() {
206 return id;
207 }
208
209 @Override
210 public Collection<BuildEventId> getChildrenEvents() {
211 return children;
212 }
213
214 @Override
215 public Collection<NestedSet<Artifact>> reportedArtifacts() {
216 return artifacts;
217 }
218
219 @Override
ulfjack26e586d2018-05-17 08:42:13 -0700220 public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext converters) {
Klaus Aehligee3e1922017-04-07 14:25:27 +0000221 BuildEventStreamProtos.NamedSetOfFiles.Builder builder =
222 BuildEventStreamProtos.NamedSetOfFiles.newBuilder();
223 for (NestedSet<Artifact> artifactset : artifacts) {
224 builder.addFileSets(
225 converters
226 .artifactGroupNamer()
227 .apply((new NestedSetView<Artifact>(artifactset)).identifier()));
228 }
229 return GenericBuildEvent.protoChaining(this).setNamedSetOfFiles(builder.build()).build();
230 }
231 }
232
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400233 private static class GenericConfigurationEvent implements BuildEventWithConfiguration {
234 private final BuildEventId id;
235 private final Collection<BuildEventId> children;
Klaus Aehliga708a022017-07-11 12:54:40 +0200236 private final Collection<BuildEvent> configurations;
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400237
238 GenericConfigurationEvent(
Klaus Aehliga708a022017-07-11 12:54:40 +0200239 BuildEventId id, Collection<BuildEventId> children, Collection<BuildEvent> configurations) {
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400240 this.id = id;
241 this.children = children;
242 this.configurations = configurations;
243 }
244
Klaus Aehliga708a022017-07-11 12:54:40 +0200245 GenericConfigurationEvent(BuildEventId id, BuildEvent configuration) {
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400246 this(id, ImmutableSet.<BuildEventId>of(), ImmutableSet.of(configuration));
247 }
248
249 @Override
250 public BuildEventId getEventId() {
251 return id;
252 }
253
254 @Override
255 public Collection<BuildEventId> getChildrenEvents() {
256 return children;
257 }
258
259 @Override
Klaus Aehliga708a022017-07-11 12:54:40 +0200260 public Collection<BuildEvent> getConfigurations() {
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400261 return configurations;
262 }
263
264 @Override
ulfjack26e586d2018-05-17 08:42:13 -0700265 public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext converters) {
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400266 return GenericBuildEvent.protoChaining(this).build();
267 }
268 }
269
Klaus Aehlig17325a12016-09-30 15:45:27 +0000270 private static BuildEventId testId(String opaque) {
271 return BuildEventId.unknownBuildEventId(opaque);
272 }
273
buchgr9e0308e2017-04-25 16:38:45 +0200274 private static class EventBusHandler {
275
276 Set<BuildEventTransport> transportSet;
277
278 @Subscribe
279 void transportsAnnounced(AnnounceBuildEventTransportsEvent evt) {
280 transportSet = Collections.synchronizedSet(new HashSet<>(evt.transports()));
281 }
282
283 @Subscribe
284 void transportClosed(BuildEventTransportClosedEvent evt) {
285 transportSet.remove(evt.transport());
286 }
287 }
288
289 @Before
290 public void setup() {
291 MockitoAnnotations.initMocks(this);
292 }
293
294 @Test(timeout = 5000)
Klaus Aehlig17325a12016-09-30 15:45:27 +0000295 public void testSimpleStream() {
296 // Verify that a well-formed event is passed through and that completion of the
Klaus Aehligfb3c5722017-07-10 13:08:19 +0200297 // build clears the pending progress-update event. However, there is no guarantee
298 // on the order of the flushed events.
299 // Additionally, assert that the actual last event has the last_message flag set.
Klaus Aehlig17325a12016-09-30 15:45:27 +0000300
buchgr9e0308e2017-04-25 16:38:45 +0200301 EventBusHandler handler = new EventBusHandler();
302 eventBus.register(handler);
lberkiaea56b32017-05-30 12:35:33 +0200303 assertThat(handler.transportSet).isNull();
buchgr9e0308e2017-04-25 16:38:45 +0200304
Klaus Aehlig17325a12016-09-30 15:45:27 +0000305 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000306 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200307 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehlig17325a12016-09-30 15:45:27 +0000308
309 BuildEvent startEvent =
310 new GenericBuildEvent(
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000311 testId("Initial"), ImmutableSet.of(ProgressEvent.INITIAL_PROGRESS_UPDATE,
312 BuildEventId.buildFinished()));
Klaus Aehlig17325a12016-09-30 15:45:27 +0000313
314 streamer.buildEvent(startEvent);
315
aehlig03d55f32017-10-26 11:45:35 +0200316 assertThat(streamer.isClosed()).isFalse();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000317 List<BuildEvent> afterFirstEvent = transport.getEvents();
318 assertThat(afterFirstEvent).hasSize(1);
lberkiaea56b32017-05-30 12:35:33 +0200319 assertThat(afterFirstEvent.get(0).getEventId()).isEqualTo(startEvent.getEventId());
320 assertThat(handler.transportSet).hasSize(1);
Klaus Aehlig17325a12016-09-30 15:45:27 +0000321
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000322 streamer.buildEvent(new BuildCompleteEvent(new BuildResult(0)));
Klaus Aehlig17325a12016-09-30 15:45:27 +0000323
aehlig03d55f32017-10-26 11:45:35 +0200324 assertThat(streamer.isClosed()).isTrue();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000325 List<BuildEvent> finalStream = transport.getEvents();
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000326 assertThat(finalStream).hasSize(3);
Klaus Aehligfb3c5722017-07-10 13:08:19 +0200327 assertThat(ImmutableSet.of(finalStream.get(1).getEventId(), finalStream.get(2).getEventId()))
328 .isEqualTo(
329 ImmutableSet.of(BuildEventId.buildFinished(), ProgressEvent.INITIAL_PROGRESS_UPDATE));
330
331 // verify the "last_message" flag.
332 assertThat(transport.getEventProtos().get(0).getLastMessage()).isFalse();
333 assertThat(transport.getEventProtos().get(1).getLastMessage()).isFalse();
334 assertThat(transport.getEventProtos().get(2).getLastMessage()).isTrue();
buchgr9e0308e2017-04-25 16:38:45 +0200335
336 while (!handler.transportSet.isEmpty()) {
337 LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100));
338 }
Klaus Aehlig17325a12016-09-30 15:45:27 +0000339 }
340
341 @Test
342 public void testChaining() {
343 // Verify that unannounced events are linked in with progress update events, assuming
344 // a correctly formed initial event.
345
346 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000347 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200348 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehlig17325a12016-09-30 15:45:27 +0000349
350 BuildEvent startEvent =
351 new GenericBuildEvent(
352 testId("Initial"), ImmutableSet.of(ProgressEvent.INITIAL_PROGRESS_UPDATE));
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000353 BuildEvent unexpectedEvent =
354 new GenericBuildEvent(testId("unexpected"), ImmutableSet.<BuildEventId>of());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000355
356 streamer.buildEvent(startEvent);
357 streamer.buildEvent(unexpectedEvent);
358
aehlig03d55f32017-10-26 11:45:35 +0200359 assertThat(streamer.isClosed()).isFalse();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000360 List<BuildEvent> eventsSeen = transport.getEvents();
361 assertThat(eventsSeen).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200362 assertThat(eventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
363 assertThat(eventsSeen.get(2).getEventId()).isEqualTo(unexpectedEvent.getEventId());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000364 BuildEvent linkEvent = eventsSeen.get(1);
lberkiaea56b32017-05-30 12:35:33 +0200365 assertThat(linkEvent.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
366 assertWithMessage("Unexpected events should be linked")
367 .that(linkEvent.getChildrenEvents().contains(unexpectedEvent.getEventId()))
368 .isTrue();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000369 }
370
371 @Test
372 public void testBadInitialEvent() {
373 // Verify that, if the initial event does not announce the initial progress update event,
374 // the initial progress event is used instead to chain that event; in this way, new
375 // progress updates can always be chained in.
376
377 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000378 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200379 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehlig17325a12016-09-30 15:45:27 +0000380
381 BuildEvent unexpectedStartEvent =
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000382 new GenericBuildEvent(testId("unexpected start"), ImmutableSet.<BuildEventId>of());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000383
384 streamer.buildEvent(unexpectedStartEvent);
385
386 List<BuildEvent> eventsSeen = transport.getEvents();
387 assertThat(eventsSeen).hasSize(2);
lberkiaea56b32017-05-30 12:35:33 +0200388 assertThat(eventsSeen.get(1).getEventId()).isEqualTo(unexpectedStartEvent.getEventId());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000389 BuildEvent initial = eventsSeen.get(0);
lberkiaea56b32017-05-30 12:35:33 +0200390 assertThat(initial.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
391 assertWithMessage("Event should be linked")
392 .that(initial.getChildrenEvents().contains(unexpectedStartEvent.getEventId()))
393 .isTrue();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000394
395 // The initial event should also announce a new progress event; we test this
396 // by streaming another unannounced event.
397
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000398 BuildEvent unexpectedEvent =
399 new GenericBuildEvent(testId("unexpected"), ImmutableSet.<BuildEventId>of());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000400
401 streamer.buildEvent(unexpectedEvent);
aehlig03d55f32017-10-26 11:45:35 +0200402
403 assertThat(streamer.isClosed()).isFalse();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000404 List<BuildEvent> allEventsSeen = transport.getEvents();
405 assertThat(allEventsSeen).hasSize(4);
lberkiaea56b32017-05-30 12:35:33 +0200406 assertThat(allEventsSeen.get(3).getEventId()).isEqualTo(unexpectedEvent.getEventId());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000407 BuildEvent secondLinkEvent = allEventsSeen.get(2);
lberkiaea56b32017-05-30 12:35:33 +0200408 assertWithMessage("Progress should have been announced")
409 .that(initial.getChildrenEvents().contains(secondLinkEvent.getEventId()))
410 .isTrue();
411 assertWithMessage("Second event should be linked")
412 .that(secondLinkEvent.getChildrenEvents().contains(unexpectedEvent.getEventId()))
413 .isTrue();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000414 }
415
416 @Test
417 public void testReferPastEvent() {
418 // Verify that, if an event is refers to a previously done event, that duplicated
419 // late-referenced event is not expected again.
420 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000421 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200422 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehlig17325a12016-09-30 15:45:27 +0000423
424 BuildEvent startEvent =
425 new GenericBuildEvent(
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000426 testId("Initial"),
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000427 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE,
428 BuildEventId.buildFinished()));
Klaus Aehlig2b1eec32016-10-05 09:21:45 +0000429 BuildEvent earlyEvent =
430 new GenericBuildEvent(testId("unexpected"), ImmutableSet.<BuildEventId>of());
Klaus Aehlig17325a12016-09-30 15:45:27 +0000431 BuildEvent lateReference =
432 new GenericBuildEvent(testId("late reference"), ImmutableSet.of(earlyEvent.getEventId()));
433
434 streamer.buildEvent(startEvent);
435 streamer.buildEvent(earlyEvent);
436 streamer.buildEvent(lateReference);
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000437 streamer.buildEvent(new BuildCompleteEvent(new BuildResult(0)));
Klaus Aehlig17325a12016-09-30 15:45:27 +0000438
aehlig03d55f32017-10-26 11:45:35 +0200439 assertThat(streamer.isClosed()).isTrue();
Klaus Aehlig17325a12016-09-30 15:45:27 +0000440 List<BuildEvent> eventsSeen = transport.getEvents();
441 int earlyEventCount = 0;
442 for (BuildEvent event : eventsSeen) {
443 if (event.getEventId().equals(earlyEvent.getEventId())) {
444 earlyEventCount++;
445 }
446 }
447 // The early event should be reported precisely once.
lberkiaea56b32017-05-30 12:35:33 +0200448 assertThat(earlyEventCount).isEqualTo(1);
Klaus Aehlig17325a12016-09-30 15:45:27 +0000449 }
Klaus Aehligf75878d2016-11-21 13:41:16 +0000450
451 @Test
452 public void testReodering() {
453 // Verify that an event requiring to be posted after another one is indeed.
454
455 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
456 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200457 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehligf75878d2016-11-21 13:41:16 +0000458
459 BuildEventId expectedId = testId("the target");
460 BuildEvent startEvent =
461 new GenericBuildEvent(
462 testId("Initial"),
463 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE, expectedId));
464 BuildEvent rootCause =
465 new GenericBuildEvent(testId("failure event"), ImmutableSet.<BuildEventId>of());
466 BuildEvent failedTarget =
467 new GenericOrderEvent(expectedId, ImmutableSet.<BuildEventId>of(rootCause.getEventId()));
468
469 streamer.buildEvent(startEvent);
470 streamer.buildEvent(failedTarget);
471 streamer.buildEvent(rootCause);
472
aehlig03d55f32017-10-26 11:45:35 +0200473 assertThat(streamer.isClosed()).isFalse();
Klaus Aehligf75878d2016-11-21 13:41:16 +0000474 List<BuildEvent> allEventsSeen = transport.getEvents();
475 assertThat(allEventsSeen).hasSize(4);
lberkiaea56b32017-05-30 12:35:33 +0200476 assertThat(allEventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
Klaus Aehligf75878d2016-11-21 13:41:16 +0000477 BuildEvent linkEvent = allEventsSeen.get(1);
lberkiaea56b32017-05-30 12:35:33 +0200478 assertThat(linkEvent.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
479 assertThat(allEventsSeen.get(2).getEventId()).isEqualTo(rootCause.getEventId());
480 assertThat(allEventsSeen.get(3).getEventId()).isEqualTo(failedTarget.getEventId());
Klaus Aehligf75878d2016-11-21 13:41:16 +0000481 }
482
483 @Test
484 public void testMissingPrerequisits() {
485 // Verify that an event where the prerequisite is never coming till the end of
486 // the build still gets posted, with the prerequisite aborted.
487
488 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
489 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200490 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehligf75878d2016-11-21 13:41:16 +0000491
492 BuildEventId expectedId = testId("the target");
493 BuildEvent startEvent =
494 new GenericBuildEvent(
495 testId("Initial"),
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000496 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE, expectedId,
497 BuildEventId.buildFinished()));
Klaus Aehligf75878d2016-11-21 13:41:16 +0000498 BuildEventId rootCauseId = testId("failure event");
499 BuildEvent failedTarget =
500 new GenericOrderEvent(expectedId, ImmutableSet.<BuildEventId>of(rootCauseId));
501
502 streamer.buildEvent(startEvent);
503 streamer.buildEvent(failedTarget);
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000504 streamer.buildEvent(new BuildCompleteEvent(new BuildResult(0)));
Klaus Aehligf75878d2016-11-21 13:41:16 +0000505
aehlig03d55f32017-10-26 11:45:35 +0200506 assertThat(streamer.isClosed()).isTrue();
Klaus Aehligf75878d2016-11-21 13:41:16 +0000507 List<BuildEvent> allEventsSeen = transport.getEvents();
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000508 assertThat(allEventsSeen).hasSize(6);
lberkiaea56b32017-05-30 12:35:33 +0200509 assertThat(allEventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
510 assertThat(allEventsSeen.get(1).getEventId()).isEqualTo(BuildEventId.buildFinished());
Jakob Buchgraber8c3a4ef2017-02-28 18:49:50 +0000511 BuildEvent linkEvent = allEventsSeen.get(2);
lberkiaea56b32017-05-30 12:35:33 +0200512 assertThat(linkEvent.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
513 assertThat(allEventsSeen.get(3).getEventId()).isEqualTo(rootCauseId);
514 assertThat(allEventsSeen.get(4).getEventId()).isEqualTo(failedTarget.getEventId());
Klaus Aehligf75878d2016-11-21 13:41:16 +0000515 }
Klaus Aehligceb0f622017-03-20 13:52:06 +0000516
517 @Test
518 public void testVeryFirstEventNeedsToWait() {
519 // Verify that we can handle an first event waiting for another event.
520 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
521 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200522 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehligceb0f622017-03-20 13:52:06 +0000523
524 BuildEventId initialId = testId("Initial");
525 BuildEventId waitId = testId("Waiting for initial event");
526 BuildEvent startEvent =
527 new GenericBuildEvent(
528 initialId,
529 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE, waitId));
530 BuildEvent waitingForStart =
531 new GenericOrderEvent(waitId, ImmutableSet.<BuildEventId>of(), ImmutableSet.of(initialId));
532
533 streamer.buildEvent(waitingForStart);
534 streamer.buildEvent(startEvent);
535
aehlig03d55f32017-10-26 11:45:35 +0200536 assertThat(streamer.isClosed()).isFalse();
Klaus Aehligceb0f622017-03-20 13:52:06 +0000537 List<BuildEvent> allEventsSeen = transport.getEvents();
538 assertThat(allEventsSeen).hasSize(2);
lberkiaea56b32017-05-30 12:35:33 +0200539 assertThat(allEventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
540 assertThat(allEventsSeen.get(1).getEventId()).isEqualTo(waitingForStart.getEventId());
Klaus Aehligceb0f622017-03-20 13:52:06 +0000541 }
Klaus Aehligee3e1922017-04-07 14:25:27 +0000542
543 private Artifact makeArtifact(String pathString) {
544 Path path = outputBase.getRelative(PathFragment.create(pathString));
tomluee6a6862018-01-17 14:36:26 -0800545 return new Artifact(path, ArtifactRoot.asSourceRoot(Root.fromPath(outputBase)));
Klaus Aehligee3e1922017-04-07 14:25:27 +0000546 }
547
548 @Test
549 public void testReportedArtifacts() {
550 // Verify that reported artifacts are correctly unfolded into the stream
551 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
552 BuildEventStreamer streamer =
buchgr9e0308e2017-04-25 16:38:45 +0200553 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
Klaus Aehligee3e1922017-04-07 14:25:27 +0000554
555 BuildEvent startEvent =
556 new GenericBuildEvent(
557 testId("Initial"),
558 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE));
559
560 Artifact a = makeArtifact("path/a");
561 Artifact b = makeArtifact("path/b");
562 Artifact c = makeArtifact("path/c");
563 NestedSet<Artifact> innerGroup = NestedSetBuilder.<Artifact>stableOrder().add(a).add(b).build();
564 NestedSet<Artifact> group =
565 NestedSetBuilder.<Artifact>stableOrder().addTransitive(innerGroup).add(c).build();
566 BuildEvent reportingArtifacts =
567 new GenericArtifactReportingEvent(testId("reporting"), ImmutableSet.of(group));
568
569 streamer.buildEvent(startEvent);
570 streamer.buildEvent(reportingArtifacts);
571
aehlig03d55f32017-10-26 11:45:35 +0200572 assertThat(streamer.isClosed()).isFalse();
Klaus Aehligee3e1922017-04-07 14:25:27 +0000573 List<BuildEvent> allEventsSeen = transport.getEvents();
574 List<BuildEventStreamProtos.BuildEvent> eventProtos = transport.getEventProtos();
lberkiaea56b32017-05-30 12:35:33 +0200575 assertThat(allEventsSeen).hasSize(7);
576 assertThat(allEventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
577 assertThat(allEventsSeen.get(1).getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
Klaus Aehligee3e1922017-04-07 14:25:27 +0000578 List<BuildEventStreamProtos.File> firstSetDirects =
579 eventProtos.get(2).getNamedSetOfFiles().getFilesList();
lberkiaea56b32017-05-30 12:35:33 +0200580 assertThat(firstSetDirects).hasSize(2);
581 assertThat(ImmutableSet.of(firstSetDirects.get(0).getUri(), firstSetDirects.get(1).getUri()))
582 .isEqualTo(ImmutableSet.of(a.getPath().toString(), b.getPath().toString()));
Klaus Aehligee3e1922017-04-07 14:25:27 +0000583 List<NamedSetOfFilesId> secondSetTransitives =
584 eventProtos.get(4).getNamedSetOfFiles().getFileSetsList();
lberkiaea56b32017-05-30 12:35:33 +0200585 assertThat(secondSetTransitives).hasSize(1);
586 assertThat(secondSetTransitives.get(0)).isEqualTo(eventProtos.get(2).getId().getNamedSet());
Klaus Aehligee3e1922017-04-07 14:25:27 +0000587 List<NamedSetOfFilesId> reportedArtifactSets =
588 eventProtos.get(6).getNamedSetOfFiles().getFileSetsList();
lberkiaea56b32017-05-30 12:35:33 +0200589 assertThat(reportedArtifactSets).hasSize(1);
590 assertThat(reportedArtifactSets.get(0)).isEqualTo(eventProtos.get(4).getId().getNamedSet());
Klaus Aehligee3e1922017-04-07 14:25:27 +0000591 }
Klaus Aehlig9b3b2e92017-05-02 11:18:42 +0200592
593 @Test
594 public void testStdoutReported() {
595 // Verify that stdout and stderr are reported in the build-event stream on progress
596 // events.
597 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
598 BuildEventStreamer streamer =
599 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
600 BuildEventStreamer.OutErrProvider outErr =
601 Mockito.mock(BuildEventStreamer.OutErrProvider.class);
602 String stdoutMsg = "Some text that was written to stdout.";
603 String stderrMsg = "The UI text that bazel wrote to stderr.";
604 when(outErr.getOut()).thenReturn(stdoutMsg);
605 when(outErr.getErr()).thenReturn(stderrMsg);
606 BuildEvent startEvent =
607 new GenericBuildEvent(
608 testId("Initial"),
609 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE));
610 BuildEvent unexpectedEvent =
611 new GenericBuildEvent(testId("unexpected"), ImmutableSet.<BuildEventId>of());
612
613 streamer.registerOutErrProvider(outErr);
614 streamer.buildEvent(startEvent);
615 streamer.buildEvent(unexpectedEvent);
616
aehlig03d55f32017-10-26 11:45:35 +0200617 assertThat(streamer.isClosed()).isFalse();
Klaus Aehlig9b3b2e92017-05-02 11:18:42 +0200618 List<BuildEvent> eventsSeen = transport.getEvents();
619 assertThat(eventsSeen).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200620 assertThat(eventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
621 assertThat(eventsSeen.get(2).getEventId()).isEqualTo(unexpectedEvent.getEventId());
Klaus Aehlig9b3b2e92017-05-02 11:18:42 +0200622 BuildEvent linkEvent = eventsSeen.get(1);
623 BuildEventStreamProtos.BuildEvent linkEventProto = transport.getEventProtos().get(1);
lberkiaea56b32017-05-30 12:35:33 +0200624 assertThat(linkEvent.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
625 assertWithMessage("Unexpected events should be linked")
626 .that(linkEvent.getChildrenEvents().contains(unexpectedEvent.getEventId()))
627 .isTrue();
628 assertThat(linkEventProto.getProgress().getStdout()).isEqualTo(stdoutMsg);
629 assertThat(linkEventProto.getProgress().getStderr()).isEqualTo(stderrMsg);
Klaus Aehlig9b3b2e92017-05-02 11:18:42 +0200630
631 // As there is only one progress event, the OutErrProvider should be queried
632 // only once for stdout and stderr.
633 verify(outErr, times(1)).getOut();
634 verify(outErr, times(1)).getErr();
635 }
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400636
637 @Test
638 public void testReportedConfigurations() throws Exception {
639 // Verify that configuration events are posted, but only once.
640 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
641 BuildEventStreamer streamer =
642 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
643
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700644 BuildOptions defaultBuildOptions =
645 BuildOptions.of(
646 ImmutableList.<Class<? extends FragmentOptions>>of(BuildConfiguration.Options.class));
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400647 BuildEvent startEvent =
648 new GenericBuildEvent(
649 testId("Initial"),
650 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE));
651 BuildConfiguration configuration =
652 new BuildConfiguration(
janakr3b63a4e2017-09-14 09:55:40 +0200653 new BlazeDirectories(
Klaus Aehligc2499c42018-02-27 05:47:21 -0800654 new ServerDirectories(outputBase, outputBase, outputBase),
655 rootDirectory,
cushon849df362018-05-14 01:51:45 -0700656 /* defaultSystemJavabase= */ null,
Klaus Aehligc2499c42018-02-27 05:47:21 -0800657 "productName"),
lberki406199f2018-04-09 03:16:19 -0700658 /* fragmentsMap= */ ImmutableMap
janakr3b63a4e2017-09-14 09:55:40 +0200659 .<Class<? extends BuildConfiguration.Fragment>, BuildConfiguration.Fragment>of(),
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700660 defaultBuildOptions,
661 BuildOptions.diffForReconstruction(defaultBuildOptions, defaultBuildOptions),
lberki406199f2018-04-09 03:16:19 -0700662 /* reservedActionMnemonics= */ ImmutableSet.of(),
lberki86266232018-04-11 00:33:42 -0700663 ActionEnvironment.EMPTY,
gregce85297462017-08-18 21:20:29 +0200664 "workspace");
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400665 BuildEvent firstWithConfiguration =
shahan50f99d52018-03-10 05:14:09 -0800666 new GenericConfigurationEvent(testId("first"), configuration.toBuildEvent());
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400667 BuildEvent secondWithConfiguration =
shahan50f99d52018-03-10 05:14:09 -0800668 new GenericConfigurationEvent(testId("second"), configuration.toBuildEvent());
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400669
670 streamer.buildEvent(startEvent);
671 streamer.buildEvent(firstWithConfiguration);
672 streamer.buildEvent(secondWithConfiguration);
673
aehlig03d55f32017-10-26 11:45:35 +0200674 assertThat(streamer.isClosed()).isFalse();
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400675 List<BuildEvent> allEventsSeen = transport.getEvents();
lberkiaea56b32017-05-30 12:35:33 +0200676 assertThat(allEventsSeen).hasSize(7);
677 assertThat(allEventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
678 assertThat(allEventsSeen.get(1).getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
shahan50f99d52018-03-10 05:14:09 -0800679 assertThat(allEventsSeen.get(2)).isEqualTo(configuration.toBuildEvent());
lberkiaea56b32017-05-30 12:35:33 +0200680 assertThat(allEventsSeen.get(3).getEventId()).isEqualTo(BuildEventId.progressId(1));
681 assertThat(allEventsSeen.get(4)).isEqualTo(firstWithConfiguration);
682 assertThat(allEventsSeen.get(5).getEventId()).isEqualTo(BuildEventId.progressId(2));
683 assertThat(allEventsSeen.get(6)).isEqualTo(secondWithConfiguration);
Klaus Aehlig0cce00c2017-05-08 08:26:03 -0400684 }
Klaus Aehlig8f6549f2017-06-26 15:30:55 +0200685
686 @Test
687 public void testEarlyFlush() throws Exception {
688 // Verify that the streamer can handle early calls to flush() and still correctly
689 // reports stdout and stderr in the build-event stream.
690 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
691 BuildEventStreamer streamer =
692 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
693 BuildEventStreamer.OutErrProvider outErr =
694 Mockito.mock(BuildEventStreamer.OutErrProvider.class);
695 String firstStdoutMsg = "Some text that was written to stdout.";
696 String firstStderrMsg = "The UI text that bazel wrote to stderr.";
697 String secondStdoutMsg = "More text that was written to stdout, still before the start event.";
698 String secondStderrMsg = "More text written to stderr, still before the start event.";
699 when(outErr.getOut()).thenReturn(firstStdoutMsg).thenReturn(secondStdoutMsg);
700 when(outErr.getErr()).thenReturn(firstStderrMsg).thenReturn(secondStderrMsg);
701 BuildEvent startEvent =
702 new GenericBuildEvent(
703 testId("Initial"),
704 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE));
705
706 streamer.registerOutErrProvider(outErr);
707 streamer.flush();
708 streamer.flush();
709 streamer.buildEvent(startEvent);
710
aehlig03d55f32017-10-26 11:45:35 +0200711 assertThat(streamer.isClosed()).isFalse();
Klaus Aehlig8f6549f2017-06-26 15:30:55 +0200712 List<BuildEvent> eventsSeen = transport.getEvents();
713 assertThat(eventsSeen).hasSize(3);
714 assertThat(eventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
715 BuildEvent progressEvent = eventsSeen.get(1);
716 assertThat(progressEvent.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
717 BuildEventStreamProtos.BuildEvent progressEventProto = transport.getEventProtos().get(1);
718 assertThat(progressEventProto.getProgress().getStdout()).isEqualTo(firstStdoutMsg);
719 assertThat(progressEventProto.getProgress().getStderr()).isEqualTo(firstStderrMsg);
720 BuildEventStreamProtos.BuildEvent secondProgressEventProto = transport.getEventProtos().get(2);
721 assertThat(secondProgressEventProto.getProgress().getStdout()).isEqualTo(secondStdoutMsg);
722 assertThat(secondProgressEventProto.getProgress().getStderr()).isEqualTo(secondStderrMsg);
723
724 // As there is only one progress event, the OutErrProvider should be queried
725 // only once per flush() for stdout and stderr.
726 verify(outErr, times(2)).getOut();
727 verify(outErr, times(2)).getErr();
728 }
729
730 @Test
Klaus Aehlig28221ff2018-01-11 04:28:00 -0800731 public void testNoopFlush() throws Exception {
732 // Verify that the streamer ignores a flush, if neither stream produces any output.
733 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
734 BuildEventStreamer streamer =
735 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
736 BuildEventStreamer.OutErrProvider outErr =
737 Mockito.mock(BuildEventStreamer.OutErrProvider.class);
738 String stdoutMsg = "Some text that was written to stdout.";
739 String stderrMsg = "The UI text that bazel wrote to stderr.";
740 when(outErr.getOut()).thenReturn(stdoutMsg).thenReturn("");
741 when(outErr.getErr()).thenReturn(stderrMsg).thenReturn("");
742 BuildEvent startEvent =
743 new GenericBuildEvent(
744 testId("Initial"),
745 ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE));
746
747 streamer.registerOutErrProvider(outErr);
748 streamer.buildEvent(startEvent);
749 assertThat(transport.getEvents()).hasSize(1);
750 streamer.flush(); // Output, so a new progress event has to be added
751 assertThat(transport.getEvents()).hasSize(2);
752 streamer.flush(); // No further output, so no additional event should be generated.
753 assertThat(transport.getEvents()).hasSize(2);
754
755 assertThat(transport.getEvents().get(0)).isEqualTo(startEvent);
756 assertThat(transport.getEventProtos().get(1).getProgress().getStdout()).isEqualTo(stdoutMsg);
757 assertThat(transport.getEventProtos().get(1).getProgress().getStderr()).isEqualTo(stderrMsg);
758 }
759
760 @Test
Klaus Aehlig8f6549f2017-06-26 15:30:55 +0200761 public void testEarlyFlushBadInitialEvent() throws Exception {
762 // Verify that an early flush works correctly with an unusual start event.
763 // In this case, we expect 3 events in the stream, in that order:
764 // - an artifical progress event as initial event, to properly link in
765 // all events
766 // - the unusal first event we have seen, and
767 // - a progress event reporting the flushed messages.
768 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
769 BuildEventStreamer streamer =
770 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
771 BuildEventStreamer.OutErrProvider outErr =
772 Mockito.mock(BuildEventStreamer.OutErrProvider.class);
773 String stdoutMsg = "Some text that was written to stdout.";
774 String stderrMsg = "The UI text that bazel wrote to stderr.";
775 when(outErr.getOut()).thenReturn(stdoutMsg);
776 when(outErr.getErr()).thenReturn(stderrMsg);
777
778 BuildEvent unexpectedStartEvent =
779 new GenericBuildEvent(testId("unexpected start"), ImmutableSet.<BuildEventId>of());
780
781 streamer.registerOutErrProvider(outErr);
782 streamer.flush();
783 streamer.buildEvent(unexpectedStartEvent);
784
aehlig03d55f32017-10-26 11:45:35 +0200785 assertThat(streamer.isClosed()).isFalse();
786
Klaus Aehlig8f6549f2017-06-26 15:30:55 +0200787 List<BuildEvent> eventsSeen = transport.getEvents();
788 assertThat(eventsSeen).hasSize(3);
789
790 BuildEvent initial = eventsSeen.get(0);
791 assertThat(initial.getEventId()).isEqualTo(ProgressEvent.INITIAL_PROGRESS_UPDATE);
792 BuildEventStreamProtos.BuildEvent initialProto = transport.getEventProtos().get(0);
793 assertThat(initialProto.getProgress().getStdout()).isEmpty();
794 assertThat(initialProto.getProgress().getStderr()).isEmpty();
795
796 assertThat(eventsSeen.get(1).getEventId()).isEqualTo(unexpectedStartEvent.getEventId());
797 assertWithMessage("Unexpected event should be linked")
798 .that(initial.getChildrenEvents().contains(unexpectedStartEvent.getEventId()))
799 .isTrue();
800
801 BuildEventStreamProtos.BuildEvent progressProto = transport.getEventProtos().get(2);
802 assertThat(progressProto.getProgress().getStdout()).isEqualTo(stdoutMsg);
803 assertThat(progressProto.getProgress().getStderr()).isEqualTo(stderrMsg);
804 assertWithMessage("flushed progress should be linked")
805 .that(initial.getChildrenEvents().contains(eventsSeen.get(2).getEventId()))
806 .isTrue();
807
808 verify(outErr, times(1)).getOut();
809 verify(outErr, times(1)).getErr();
810 }
Klaus Aehligdeea6b02017-10-16 12:32:20 +0200811
812 @Test
813 public void testEarlyAbort() throws Exception {
814 // For a build that is aborted before a build-started event is generated,
815 // we still expect that, if a build-started event is forced by some order
816 // constraint (e.g., CommandLine wants to come after build started), then
817 // that gets sorted to the beginning.
818 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
819 BuildEventStreamer streamer =
820 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
821
822 BuildEvent orderEvent =
823 new GenericOrderEvent(
824 testId("event depending on start"),
825 ImmutableList.of(),
826 ImmutableList.of(BuildEventId.buildStartedId()));
827
828 streamer.buildEvent(orderEvent);
829 streamer.buildEvent(new BuildCompleteEvent(new BuildResult(0)));
830
aehlig03d55f32017-10-26 11:45:35 +0200831 assertThat(streamer.isClosed()).isTrue();
Klaus Aehligdeea6b02017-10-16 12:32:20 +0200832 List<BuildEvent> eventsSeen = transport.getEvents();
833 assertThat(eventsSeen).hasSize(4);
834 assertThat(eventsSeen.get(0).getEventId()).isEqualTo(BuildEventId.buildStartedId());
835 assertThat(eventsSeen.get(1).getEventId()).isEqualTo(orderEvent.getEventId());
836 assertThat(ImmutableSet.of(eventsSeen.get(2).getEventId(), eventsSeen.get(3).getEventId()))
837 .isEqualTo(
838 ImmutableSet.of(BuildEventId.buildFinished(), ProgressEvent.INITIAL_PROGRESS_UPDATE));
839 assertThat(transport.getEventProtos().get(3).getLastMessage()).isTrue();
840 }
aehlig03d55f32017-10-26 11:45:35 +0200841
842 @Test
843 public void testFinalEventsLate() throws Exception {
844 // Verify that we correctly handle late events (i.e., events coming only after the
845 // BuildCompleteEvent) that are sent to the streamer after the BuildCompleteEvent.
846 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
847 BuildEventStreamer streamer =
848 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
849 BuildEvent startEvent =
850 new GenericBuildEvent(
851 testId("Initial"),
852 ImmutableSet.of(ProgressEvent.INITIAL_PROGRESS_UPDATE, BuildEventId.buildFinished()));
853 BuildEventId lateId = testId("late event");
854 BuildEvent finishedEvent = new BuildCompleteEvent(new BuildResult(0), ImmutableList.of(lateId));
855
856 streamer.buildEvent(startEvent);
857 streamer.buildEvent(finishedEvent);
858 assertThat(streamer.isClosed()).isFalse();
859 streamer.buildEvent(new GenericBuildEvent(lateId, ImmutableSet.of()));
860 assertThat(streamer.isClosed()).isTrue();
861
862 List<BuildEvent> eventsSeen = transport.getEvents();
863 assertThat(eventsSeen).hasSize(4);
864 assertThat(eventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
865 assertThat(eventsSeen.get(1).getEventId()).isEqualTo(BuildEventId.buildFinished());
866 assertThat(ImmutableSet.of(eventsSeen.get(2).getEventId(), eventsSeen.get(3).getEventId()))
867 .isEqualTo(ImmutableSet.of(lateId, ProgressEvent.INITIAL_PROGRESS_UPDATE));
868 }
869
870 @Test
871 public void testFinalEventsEarly() throws Exception {
872 // Verify that we correctly handle late events (i.e., events coming only after the
873 // BuildCompleteEvent) that are sent to the streamer before the BuildCompleteEvent,
874 // but with an order constraint to come afterwards.
875 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
876 BuildEventStreamer streamer =
877 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter);
878 BuildEvent startEvent =
879 new GenericBuildEvent(
880 testId("Initial"),
881 ImmutableSet.of(ProgressEvent.INITIAL_PROGRESS_UPDATE, BuildEventId.buildFinished()));
882 BuildEventId lateId = testId("late event");
883 BuildEvent finishedEvent = new BuildCompleteEvent(new BuildResult(0), ImmutableList.of(lateId));
884
885 streamer.buildEvent(startEvent);
886 streamer.buildEvent(
887 new GenericOrderEvent(
888 lateId, ImmutableSet.of(), ImmutableList.of(BuildEventId.buildFinished())));
889 streamer.buildEvent(finishedEvent);
890 assertThat(streamer.isClosed()).isTrue();
891
892 List<BuildEvent> eventsSeen = transport.getEvents();
893 assertThat(eventsSeen).hasSize(4);
894 assertThat(eventsSeen.get(0).getEventId()).isEqualTo(startEvent.getEventId());
895 assertThat(eventsSeen.get(1).getEventId()).isEqualTo(BuildEventId.buildFinished());
896 assertThat(ImmutableSet.of(eventsSeen.get(2).getEventId(), eventsSeen.get(3).getEventId()))
897 .isEqualTo(ImmutableSet.of(lateId, ProgressEvent.INITIAL_PROGRESS_UPDATE));
898 }
ruperts76de73b2018-03-02 16:10:43 -0800899
900 @Test
901 public void testSuccessfulActionsAreNotPublishedByDefault() {
902 EventBusHandler handler = new EventBusHandler();
903 eventBus.register(handler);
904
905 BuildEventStreamOptions options = new BuildEventStreamOptions();
906
907 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
908 BuildEventStreamer streamer =
909 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter, options);
910
911 ActionExecutedEvent failedActionExecutedEvent =
912 new ActionExecutedEvent(
913 new ActionsTestUtil.NullAction(),
914 new ActionExecutionException("Exception", /* action= */ null, /* catastrophe= */ false),
915 /* stdout= */ null,
916 /* stderr= */ null,
917 ErrorTiming.BEFORE_EXECUTION);
918
919 streamer.buildEvent(SUCCESSFUL_ACTION_EXECUTED_EVENT);
920 streamer.buildEvent(failedActionExecutedEvent);
921
922 List<BuildEvent> transportedEvents = transport.getEvents();
923
924 assertThat(transportedEvents).doesNotContain(SUCCESSFUL_ACTION_EXECUTED_EVENT);
925 assertThat(transportedEvents).contains(failedActionExecutedEvent);
926 }
927
928 @Test
929 public void testSuccessfulActionsCanBePublished() {
930 EventBusHandler handler = new EventBusHandler();
931 eventBus.register(handler);
932
933 BuildEventStreamOptions options = new BuildEventStreamOptions();
934 options.publishAllActions = true;
935
936 RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
937 BuildEventStreamer streamer =
938 new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport), reporter, options);
939
940 ActionExecutedEvent failedActionExecutedEvent =
941 new ActionExecutedEvent(
942 new ActionsTestUtil.NullAction(),
943 new ActionExecutionException("Exception", /* action= */ null, /* catastrophe= */ false),
944 /* stdout= */ null,
945 /* stderr= */ null,
946 ErrorTiming.BEFORE_EXECUTION);
947
948 streamer.buildEvent(SUCCESSFUL_ACTION_EXECUTED_EVENT);
949 streamer.buildEvent(failedActionExecutedEvent);
950
951 List<BuildEvent> transportedEvents = transport.getEvents();
952
953 assertThat(transportedEvents).contains(SUCCESSFUL_ACTION_EXECUTED_EVENT);
954 assertThat(transportedEvents).contains(failedActionExecutedEvent);
955 }
Klaus Aehlig17325a12016-09-30 15:45:27 +0000956}