Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 1 | // Copyright 2022 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 | package com.google.devtools.build.lib.runtime; |
| 15 | |
| 16 | import static com.google.common.truth.Truth.assertThat; |
| 17 | import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 18 | import static org.mockito.ArgumentMatchers.any; |
| 19 | import static org.mockito.Mockito.mock; |
| 20 | import static org.mockito.Mockito.never; |
| 21 | import static org.mockito.Mockito.verify; |
| 22 | |
| 23 | import com.github.luben.zstd.ZstdInputStream; |
| 24 | import com.github.luben.zstd.ZstdOutputStream; |
| 25 | import com.google.common.collect.ImmutableList; |
| 26 | import com.google.common.collect.ImmutableMap; |
| 27 | import com.google.common.collect.ImmutableSet; |
| 28 | import com.google.common.eventbus.EventBus; |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 29 | import com.google.devtools.build.lib.actions.Action; |
| 30 | import com.google.devtools.build.lib.actions.ActionCompletionEvent; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 31 | import com.google.devtools.build.lib.actions.ActionInput; |
| 32 | import com.google.devtools.build.lib.actions.ActionInputHelper; |
| 33 | import com.google.devtools.build.lib.actions.ActionOwner; |
| 34 | import com.google.devtools.build.lib.actions.Artifact; |
| 35 | import com.google.devtools.build.lib.actions.ArtifactRoot; |
| 36 | import com.google.devtools.build.lib.actions.ArtifactRoot.RootType; |
Googler | 0e099d9 | 2023-01-09 10:58:55 -0800 | [diff] [blame] | 37 | import com.google.devtools.build.lib.actions.DiscoveredInputsEvent; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 38 | import com.google.devtools.build.lib.actions.ExecutionGraph; |
| 39 | import com.google.devtools.build.lib.actions.ResourceSet; |
| 40 | import com.google.devtools.build.lib.actions.SimpleSpawn; |
| 41 | import com.google.devtools.build.lib.actions.Spawn; |
| 42 | import com.google.devtools.build.lib.actions.SpawnExecutedEvent; |
| 43 | import com.google.devtools.build.lib.actions.SpawnMetrics; |
| 44 | import com.google.devtools.build.lib.actions.SpawnResult; |
| 45 | import com.google.devtools.build.lib.actions.SpawnResult.Status; |
| 46 | import com.google.devtools.build.lib.actions.util.ActionsTestUtil; |
| 47 | import com.google.devtools.build.lib.bugreport.BugReporter; |
| 48 | import com.google.devtools.build.lib.buildtool.BuildResult; |
| 49 | import com.google.devtools.build.lib.buildtool.BuildResult.BuildToolLogCollection; |
| 50 | import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent; |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 51 | import com.google.devtools.build.lib.clock.BlazeClock; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 52 | import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; |
| 53 | import com.google.devtools.build.lib.collect.nestedset.Order; |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 54 | import com.google.devtools.build.lib.exec.util.FakeActionInputFileCache; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 55 | import com.google.devtools.build.lib.exec.util.FakeOwner; |
| 56 | import com.google.devtools.build.lib.exec.util.SpawnBuilder; |
Googler | a2177dc | 2022-09-22 10:18:10 -0700 | [diff] [blame] | 57 | import com.google.devtools.build.lib.runtime.ExecutionGraphModule.ActionDumpWriter; |
| 58 | import com.google.devtools.build.lib.runtime.ExecutionGraphModule.DependencyInfo; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 59 | import com.google.devtools.build.lib.testutil.FoundationTestCase; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 60 | import com.google.devtools.build.lib.vfs.PathFragment; |
| 61 | import com.google.testing.junit.testparameterinjector.TestParameter; |
| 62 | import com.google.testing.junit.testparameterinjector.TestParameterInjector; |
| 63 | import java.io.ByteArrayInputStream; |
| 64 | import java.io.ByteArrayOutputStream; |
| 65 | import java.io.IOException; |
| 66 | import java.io.InputStream; |
| 67 | import java.io.OutputStream; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 68 | import java.time.Instant; |
| 69 | import java.util.UUID; |
| 70 | import org.junit.Before; |
| 71 | import org.junit.Test; |
| 72 | import org.junit.runner.RunWith; |
| 73 | import org.mockito.ArgumentCaptor; |
| 74 | |
Googler | a2177dc | 2022-09-22 10:18:10 -0700 | [diff] [blame] | 75 | /** Unit tests for {@link ExecutionGraphModule}. */ |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 76 | @RunWith(TestParameterInjector.class) |
Googler | a2177dc | 2022-09-22 10:18:10 -0700 | [diff] [blame] | 77 | public class ExecutionGraphModuleTest extends FoundationTestCase { |
| 78 | private ExecutionGraphModule module; |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 79 | private ArtifactRoot artifactRoot; |
| 80 | |
| 81 | @Before |
| 82 | public void createModule() { |
Googler | a2177dc | 2022-09-22 10:18:10 -0700 | [diff] [blame] | 83 | module = new ExecutionGraphModule(); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | @Before |
| 87 | public final void initializeRoots() throws Exception { |
| 88 | artifactRoot = ArtifactRoot.asDerivedRoot(scratch.resolve("/"), RootType.Output, "output"); |
| 89 | } |
| 90 | |
| 91 | private static ImmutableList<ExecutionGraph.Node> parse(ByteArrayOutputStream buffer) |
| 92 | throws IOException { |
| 93 | byte[] data = buffer.toByteArray(); |
| 94 | try (InputStream in = new ZstdInputStream(new ByteArrayInputStream(data))) { |
| 95 | ImmutableList.Builder<ExecutionGraph.Node> nodeListBuilder = new ImmutableList.Builder<>(); |
| 96 | ExecutionGraph.Node node; |
| 97 | while ((node = ExecutionGraph.Node.parseDelimitedFrom(in)) != null) { |
| 98 | nodeListBuilder.add(node); |
| 99 | } |
| 100 | return nodeListBuilder.build(); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | @Test |
| 105 | public void testOneSpawn() throws IOException { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 106 | UUID uuid = UUID.randomUUID(); |
| 107 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| 108 | Spawn spawn = |
| 109 | new SimpleSpawn( |
| 110 | new FakeOwnerWithPrimaryOutput( |
| 111 | "Mnemonic", "Progress message", "//foo", "output/foo/out"), |
| 112 | ImmutableList.of("cmd"), |
| 113 | ImmutableMap.of("env", "value"), |
| 114 | ImmutableMap.of("exec", "value"), |
| 115 | /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER), |
| 116 | /* outputs= */ ImmutableSet.of(ActionInputHelper.fromPath("output/foo/out")), |
| 117 | ResourceSet.ZERO); |
| 118 | SpawnResult result = |
| 119 | new SpawnResult.Builder() |
| 120 | .setRunnerName("local") |
| 121 | .setStatus(Status.SUCCESS) |
| 122 | .setExitCode(0) |
| 123 | .setSpawnMetrics( |
| 124 | SpawnMetrics.Builder.forLocalExec() |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 125 | .setTotalTimeInMs(1234) |
| 126 | .setExecutionWallTimeInMs(2345) |
| 127 | .setProcessOutputsTimeInMs(3456) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 128 | .build()) |
| 129 | .build(); |
| 130 | startLogging(eventBus, uuid, buffer, DependencyInfo.NONE); |
| 131 | Instant startTimeInstant = Instant.now(); |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 132 | module.spawnExecuted( |
| 133 | new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), result, startTimeInstant)); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 134 | module.buildComplete( |
| 135 | new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000))); |
| 136 | |
| 137 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 138 | assertThat(nodes).hasSize(1); |
| 139 | assertThat(nodes.get(0).getTargetLabel()).isEqualTo("//foo:foo"); |
| 140 | assertThat(nodes.get(0).getMnemonic()).isEqualTo("Mnemonic"); |
| 141 | assertThat(nodes.get(0).getMetrics().getDurationMillis()).isEqualTo(1234L); |
| 142 | assertThat(nodes.get(0).getMetrics().getFetchMillis()).isEqualTo(0); |
| 143 | assertThat(nodes.get(0).getMetrics().getProcessOutputsMillis()).isEqualTo(3456); |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 144 | assertThat(nodes.get(0).getMetrics().getStartTimestampMillis()) |
| 145 | .isEqualTo(startTimeInstant.toEpochMilli()); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 146 | assertThat(nodes.get(0).getIndex()).isEqualTo(0); |
| 147 | assertThat(nodes.get(0).getDependentIndexList()).isEmpty(); |
| 148 | } |
| 149 | |
| 150 | @Test |
Googler | 0e099d9 | 2023-01-09 10:58:55 -0800 | [diff] [blame] | 151 | public void testSpawnWithDiscoverInputs() throws IOException { |
| 152 | UUID uuid = UUID.randomUUID(); |
| 153 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| 154 | Spawn spawn = |
| 155 | new SimpleSpawn( |
| 156 | new FakeOwnerWithPrimaryOutput( |
| 157 | "Mnemonic", "Progress message", "//foo", "output/foo/out"), |
| 158 | ImmutableList.of("cmd"), |
| 159 | ImmutableMap.of("env", "value"), |
| 160 | ImmutableMap.of("exec", "value"), |
| 161 | /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER), |
| 162 | /* outputs= */ ImmutableSet.of(createOutputArtifact("output/foo/out")), |
| 163 | ResourceSet.ZERO); |
| 164 | SpawnResult result = |
| 165 | new SpawnResult.Builder() |
| 166 | .setRunnerName("local") |
| 167 | .setStatus(Status.SUCCESS) |
| 168 | .setExitCode(0) |
| 169 | .setSpawnMetrics( |
| 170 | SpawnMetrics.Builder.forLocalExec() |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 171 | .setTotalTimeInMs(1234) |
| 172 | .setExecutionWallTimeInMs(2345) |
| 173 | .setProcessOutputsTimeInMs(3456) |
| 174 | .setParseTimeInMs(2000) |
Googler | 0e099d9 | 2023-01-09 10:58:55 -0800 | [diff] [blame] | 175 | .build()) |
| 176 | .build(); |
| 177 | startLogging(eventBus, uuid, buffer, DependencyInfo.NONE); |
| 178 | Instant startTimeInstant = Instant.ofEpochMilli(999888777L); |
| 179 | module.discoverInputs( |
| 180 | new DiscoveredInputsEvent( |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 181 | SpawnMetrics.Builder.forOtherExec().setParseTimeInMs(987).setTotalTimeInMs(987).build(), |
Googler | 0e099d9 | 2023-01-09 10:58:55 -0800 | [diff] [blame] | 182 | new ActionsTestUtil.NullAction(createOutputArtifact("output/foo/out")), |
| 183 | 0)); |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 184 | module.spawnExecuted( |
| 185 | new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), result, startTimeInstant)); |
Googler | 0e099d9 | 2023-01-09 10:58:55 -0800 | [diff] [blame] | 186 | module.buildComplete( |
| 187 | new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000))); |
| 188 | |
| 189 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 190 | ExecutionGraph.Metrics metrics = nodes.get(0).getMetrics(); |
| 191 | assertThat(metrics.getDurationMillis()).isEqualTo(2221); |
| 192 | assertThat(metrics.getFetchMillis()).isEqualTo(0); |
| 193 | assertThat(metrics.getProcessMillis()).isEqualTo(2345); |
| 194 | assertThat(metrics.getProcessOutputsMillis()).isEqualTo(3456); |
| 195 | assertThat(metrics.getParseMillis()).isEqualTo(2000); |
| 196 | assertThat(metrics.getDiscoverInputsMillis()).isEqualTo(987); |
| 197 | } |
| 198 | |
| 199 | @Test |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 200 | public void actionDepsWithThreeSpawns() throws IOException { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 201 | UUID uuid = UUID.randomUUID(); |
| 202 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| 203 | |
| 204 | ActionInput out1 = ActionInputHelper.fromPath("output/foo/out1"); |
| 205 | ActionInput out2 = ActionInputHelper.fromPath("output/foo/out2"); |
| 206 | ActionInput outTop = ActionInputHelper.fromPath("output/foo/out.top"); |
| 207 | |
| 208 | Spawn spawnOut1 = |
| 209 | new SimpleSpawn( |
| 210 | new FakeOwnerWithPrimaryOutput( |
| 211 | "Mnemonic", "Progress message", "//foo", out1.getExecPathString()), |
| 212 | ImmutableList.of("cmd"), |
| 213 | ImmutableMap.of("env", "value"), |
| 214 | ImmutableMap.of("exec", "value"), |
| 215 | /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER), |
| 216 | /* outputs= */ ImmutableSet.of(out1), |
| 217 | ResourceSet.ZERO); |
| 218 | Spawn spawnOut2 = |
| 219 | new SimpleSpawn( |
| 220 | new FakeOwnerWithPrimaryOutput( |
| 221 | "Mnemonic", "Progress message", "//foo", out2.getExecPathString()), |
| 222 | ImmutableList.of("cmd"), |
| 223 | ImmutableMap.of("env", "value"), |
| 224 | ImmutableMap.of("exec", "value"), |
| 225 | /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER), |
| 226 | /* outputs= */ ImmutableSet.of(out2), |
| 227 | ResourceSet.ZERO); |
| 228 | Spawn spawnTop = |
| 229 | new SimpleSpawn( |
| 230 | new FakeOwnerWithPrimaryOutput( |
| 231 | "Mnemonic", "Progress message", "//foo", outTop.getExecPathString()), |
| 232 | ImmutableList.of("cmd"), |
| 233 | ImmutableMap.of("env", "value"), |
| 234 | ImmutableMap.of("exec", "value"), |
| 235 | /* inputs= */ NestedSetBuilder.create(Order.COMPILE_ORDER, out1, out2), |
| 236 | /* outputs= */ ImmutableSet.of(outTop), |
| 237 | ResourceSet.ZERO); |
| 238 | SpawnResult result = |
| 239 | new SpawnResult.Builder() |
| 240 | .setRunnerName("local") |
| 241 | .setStatus(Status.SUCCESS) |
| 242 | .setExitCode(0) |
| 243 | .setSpawnMetrics( |
| 244 | SpawnMetrics.Builder.forLocalExec() |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 245 | .setTotalTimeInMs(1234) |
| 246 | .setExecutionWallTimeInMs(2345) |
| 247 | .setProcessOutputsTimeInMs(3456) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 248 | .build()) |
| 249 | .build(); |
| 250 | startLogging(eventBus, uuid, buffer, DependencyInfo.ALL); |
| 251 | Instant startTimeInstant = Instant.now(); |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 252 | module.spawnExecuted( |
| 253 | new SpawnExecutedEvent( |
| 254 | spawnOut1, new FakeActionInputFileCache(), result, startTimeInstant)); |
| 255 | module.spawnExecuted( |
| 256 | new SpawnExecutedEvent( |
| 257 | spawnOut2, new FakeActionInputFileCache(), result, startTimeInstant)); |
| 258 | module.spawnExecuted( |
| 259 | new SpawnExecutedEvent(spawnTop, new FakeActionInputFileCache(), result, startTimeInstant)); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 260 | module.buildComplete( |
| 261 | new BuildCompleteEvent(new BuildResult(startTimeInstant.plusMillis(1000).toEpochMilli()))); |
| 262 | |
| 263 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 264 | assertThat(nodes).hasSize(3); |
| 265 | |
| 266 | assertThat(nodes.get(0).getIndex()).isEqualTo(0); |
| 267 | assertThat(nodes.get(0).getDependentIndexList()).isEmpty(); |
| 268 | |
| 269 | assertThat(nodes.get(1).getIndex()).isEqualTo(1); |
| 270 | assertThat(nodes.get(1).getDependentIndexList()).isEmpty(); |
| 271 | |
| 272 | assertThat(nodes.get(2).getIndex()).isEqualTo(2); |
| 273 | assertThat(nodes.get(2).getDependentIndexList()).containsExactly(0, 1); |
| 274 | } |
| 275 | |
| 276 | private enum FailingOutputStreamFactory { |
| 277 | CLOSE { |
| 278 | @Override |
| 279 | public ZstdOutputStream get() throws IOException { |
| 280 | return new ZstdOutputStream(OutputStream.nullOutputStream()) { |
| 281 | @Override |
| 282 | public synchronized void close() throws IOException { |
| 283 | throw new IOException("Simulated close failure"); |
| 284 | } |
| 285 | }; |
| 286 | } |
| 287 | }, |
| 288 | /** Called from {@link com.google.protobuf.CodedOutputStream#flush}. */ |
| 289 | WRITE { |
| 290 | @Override |
| 291 | public ZstdOutputStream get() throws IOException { |
| 292 | return new ZstdOutputStream(OutputStream.nullOutputStream()) { |
| 293 | @Override |
| 294 | public synchronized void write(byte[] b, int off, int len) throws IOException { |
| 295 | throw new IOException("oh no!"); |
| 296 | } |
| 297 | }; |
| 298 | } |
| 299 | }; |
| 300 | |
| 301 | abstract ZstdOutputStream get() throws IOException; |
| 302 | } |
| 303 | |
| 304 | /** Regression test for b/218721483. */ |
| 305 | @Test(timeout = 30_000) |
| 306 | public void failureInOutputDoesNotHang( |
| 307 | @TestParameter FailingOutputStreamFactory failingOutputStream) { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 308 | UUID uuid = UUID.randomUUID(); |
| 309 | ActionDumpWriter writer = |
| 310 | new ActionDumpWriter( |
| 311 | BugReporter.defaultInstance(), |
Googler | 4973166 | 2023-03-21 01:37:10 -0700 | [diff] [blame] | 312 | /* localLockFreeOutputEnabled= */ false, |
| 313 | /* logFileWriteEdges= */ false, |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 314 | OutputStream.nullOutputStream(), |
| 315 | uuid, |
| 316 | DependencyInfo.NONE, |
| 317 | -1) { |
| 318 | @Override |
| 319 | protected void updateLogs(BuildToolLogCollection logs) {} |
| 320 | |
| 321 | @Override |
| 322 | protected ZstdOutputStream createCompressingOutputStream() throws IOException { |
| 323 | return failingOutputStream.get(); |
| 324 | } |
| 325 | }; |
| 326 | module.setWriter(writer); |
| 327 | eventBus.register(module); |
| 328 | |
| 329 | Instant startTimeInstant = Instant.now(); |
| 330 | eventBus.post(new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000))); |
| 331 | } |
| 332 | |
| 333 | private void startLogging( |
| 334 | EventBus eventBus, UUID uuid, OutputStream buffer, DependencyInfo depType) { |
| 335 | startLogging( |
| 336 | eventBus, |
| 337 | BugReporter.defaultInstance(), |
Googler | 4973166 | 2023-03-21 01:37:10 -0700 | [diff] [blame] | 338 | /* localLockFreeOutputEnabled= */ false, |
| 339 | /* logFileWriteEdges= */ false, |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 340 | uuid, |
| 341 | buffer, |
| 342 | depType); |
| 343 | } |
| 344 | |
| 345 | private void startLogging( |
| 346 | EventBus eventBus, |
| 347 | BugReporter bugReporter, |
| 348 | boolean localLockFreeOutputEnabled, |
Googler | 4973166 | 2023-03-21 01:37:10 -0700 | [diff] [blame] | 349 | boolean logFileWriteEdges, |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 350 | UUID uuid, |
| 351 | OutputStream buffer, |
| 352 | DependencyInfo depType) { |
| 353 | ActionDumpWriter writer = |
Googler | 4973166 | 2023-03-21 01:37:10 -0700 | [diff] [blame] | 354 | new ActionDumpWriter( |
| 355 | bugReporter, localLockFreeOutputEnabled, logFileWriteEdges, buffer, uuid, depType, -1) { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 356 | @Override |
| 357 | protected void updateLogs(BuildToolLogCollection logs) {} |
| 358 | }; |
| 359 | module.setWriter(writer); |
| 360 | eventBus.register(module); |
| 361 | } |
| 362 | |
| 363 | @Test |
| 364 | public void shutDownWithoutStartTolerated() { |
| 365 | eventBus.register(module); |
| 366 | Instant startTimeInstant = Instant.now(); |
| 367 | // Doesn't crash. |
| 368 | eventBus.post(new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000))); |
| 369 | } |
| 370 | |
| 371 | @Test |
| 372 | public void testSpawnWithNullOwnerLabel() throws IOException { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 373 | UUID uuid = UUID.randomUUID(); |
| 374 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| 375 | Spawn spawn = |
| 376 | new SimpleSpawn( |
| 377 | new FakeOwnerWithPrimaryOutput( |
| 378 | "Mnemonic", "Progress message", "//unused:label", "output/foo/out") { |
| 379 | @Override |
| 380 | public ActionOwner getOwner() { |
| 381 | return ActionOwner.SYSTEM_ACTION_OWNER; |
| 382 | } |
| 383 | }, |
| 384 | ImmutableList.of("cmd"), |
| 385 | ImmutableMap.of("env", "value"), |
| 386 | ImmutableMap.of("exec", "value"), |
| 387 | /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER), |
| 388 | /* outputs= */ ImmutableSet.of(ActionInputHelper.fromPath("output/foo/out")), |
| 389 | ResourceSet.ZERO); |
| 390 | SpawnResult result = |
| 391 | new SpawnResult.Builder() |
| 392 | .setRunnerName("local") |
| 393 | .setStatus(Status.SUCCESS) |
| 394 | .setExitCode(0) |
| 395 | .setSpawnMetrics( |
| 396 | SpawnMetrics.Builder.forLocalExec() |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 397 | .setTotalTimeInMs(1234) |
| 398 | .setExecutionWallTimeInMs(2345) |
| 399 | .setProcessOutputsTimeInMs(3456) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 400 | .build()) |
| 401 | .build(); |
| 402 | startLogging(eventBus, uuid, buffer, DependencyInfo.NONE); |
| 403 | Instant startTimeInstant = Instant.now(); |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 404 | module.spawnExecuted( |
| 405 | new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), result, startTimeInstant)); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 406 | module.buildComplete( |
| 407 | new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000))); |
| 408 | |
| 409 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 410 | assertThat(nodes).hasSize(1); |
| 411 | assertThat(nodes.get(0).getTargetLabel()).isEmpty(); |
| 412 | } |
| 413 | |
| 414 | @Test |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 415 | public void spawnAndAction_withSameOutputs() throws Exception { |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 416 | var buffer = new ByteArrayOutputStream(); |
| 417 | startLogging(eventBus, UUID.randomUUID(), buffer, DependencyInfo.ALL); |
Googler | a2177dc | 2022-09-22 10:18:10 -0700 | [diff] [blame] | 418 | var options = new ExecutionGraphModule.ExecutionGraphOptions(); |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 419 | module.setOptions(options); |
| 420 | |
| 421 | module.spawnExecuted( |
| 422 | new SpawnExecutedEvent( |
| 423 | new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(), |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 424 | new FakeActionInputFileCache(), |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 425 | createRemoteSpawnResult(200), |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 426 | Instant.ofEpochMilli(100))); |
| 427 | module.actionComplete( |
| 428 | new ActionCompletionEvent( |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 429 | 0, |
| 430 | 0, |
| 431 | new ActionsTestUtil.NullAction(createOutputArtifact("foo/out")), |
| 432 | new FakeActionInputFileCache(), |
| 433 | null)); |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 434 | module.buildComplete(new BuildCompleteEvent(new BuildResult(1000))); |
| 435 | |
| 436 | assertThat(parse(buffer)) |
| 437 | .containsExactly( |
| 438 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 439 | .setIndex(0) |
| 440 | .setMetrics( |
| 441 | ExecutionGraph.Metrics.newBuilder() |
| 442 | .setStartTimestampMillis(100) |
| 443 | .setDurationMillis(200) |
| 444 | .setOtherMillis(200)) |
| 445 | .setRunner("remote") |
Googler | c0b0996 | 2023-12-04 08:16:44 -0800 | [diff] [blame] | 446 | .setRuleClass("dummy-target-kind") |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 447 | .build()); |
| 448 | } |
| 449 | |
| 450 | @Test |
| 451 | public void spawnAndAction_withDifferentOutputs() throws Exception { |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 452 | var buffer = new ByteArrayOutputStream(); |
| 453 | startLogging(eventBus, UUID.randomUUID(), buffer, DependencyInfo.ALL); |
Googler | a2177dc | 2022-09-22 10:18:10 -0700 | [diff] [blame] | 454 | var options = new ExecutionGraphModule.ExecutionGraphOptions(); |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 455 | module.setOptions(options); |
| 456 | var nanosToMillis = BlazeClock.createNanosToMillisSinceEpochConverter(); |
| 457 | module.setNanosToMillis(nanosToMillis); |
| 458 | |
| 459 | module.spawnExecuted( |
| 460 | new SpawnExecutedEvent( |
| 461 | new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(), |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 462 | new FakeActionInputFileCache(), |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 463 | createRemoteSpawnResult(200), |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 464 | Instant.ofEpochMilli(100))); |
| 465 | var action = new ActionsTestUtil.NullAction(createOutputArtifact("bar/out")); |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 466 | module.actionComplete( |
| 467 | new ActionCompletionEvent(0, 0, action, new FakeActionInputFileCache(), null)); |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 468 | module.buildComplete(new BuildCompleteEvent(new BuildResult(1000))); |
| 469 | |
| 470 | assertThat(parse(buffer)) |
| 471 | .containsExactly( |
| 472 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 473 | .setIndex(0) |
| 474 | .setMetrics( |
| 475 | ExecutionGraph.Metrics.newBuilder() |
| 476 | .setStartTimestampMillis(100) |
| 477 | .setDurationMillis(200) |
| 478 | .setOtherMillis(200)) |
Googler | c0b0996 | 2023-12-04 08:16:44 -0800 | [diff] [blame] | 479 | .setRuleClass("dummy-target-kind") |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 480 | .setRunner("remote") |
| 481 | .build(), |
| 482 | executionGraphNodeBuilderForAction(action) |
| 483 | .setIndex(1) |
| 484 | .setMetrics( |
| 485 | ExecutionGraph.Metrics.newBuilder() |
| 486 | .setStartTimestampMillis(nanosToMillis.toEpochMillis(0))) |
Googler | c0b0996 | 2023-12-04 08:16:44 -0800 | [diff] [blame] | 487 | .setRuleClass("dummy-kind") |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 488 | .build()); |
| 489 | } |
| 490 | |
| 491 | @Test |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 492 | public void multipleSpawnsWithSameOutput_recordsBothSpawnsWithRetry() throws Exception { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 493 | var buffer = new ByteArrayOutputStream(); |
| 494 | startLogging(eventBus, UUID.randomUUID(), buffer, DependencyInfo.ALL); |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 495 | SpawnResult localResult = createLocalSpawnResult(100); |
| 496 | SpawnResult remoteResult = createRemoteSpawnResult(200); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 497 | Spawn spawn = |
| 498 | new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(); |
| 499 | |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 500 | module.spawnExecuted( |
| 501 | new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), localResult, Instant.EPOCH)); |
| 502 | module.spawnExecuted( |
| 503 | new SpawnExecutedEvent( |
| 504 | spawn, new FakeActionInputFileCache(), remoteResult, Instant.ofEpochMilli(100))); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 505 | module.buildComplete(new BuildCompleteEvent(new BuildResult(1000))); |
| 506 | |
| 507 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 508 | assertThat(nodes) |
| 509 | .containsExactly( |
| 510 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 511 | .setIndex(0) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 512 | .setMetrics( |
| 513 | ExecutionGraph.Metrics.newBuilder() |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 514 | .setStartTimestampMillis(0) |
| 515 | .setDurationMillis(100) |
| 516 | .setOtherMillis(100)) |
| 517 | .setRunner("local") |
| 518 | .build(), |
| 519 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 520 | .setIndex(1) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 521 | .setMetrics( |
| 522 | ExecutionGraph.Metrics.newBuilder() |
| 523 | .setStartTimestampMillis(100) |
| 524 | .setDurationMillis(200) |
| 525 | .setOtherMillis(200)) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 526 | .setRunner("remote") |
| 527 | .setRetryOf(0) |
| 528 | .build()) |
| 529 | .inOrder(); |
| 530 | } |
| 531 | |
| 532 | enum LocalLockFreeOutput { |
| 533 | LOCAL_LOCK_FREE_OUTPUT_ENABLED(/*optionValue=*/ true) { |
| 534 | @Override |
| 535 | void assertBugReport(BugReporter bugReporter) { |
| 536 | verify(bugReporter, never()).sendNonFatalBugReport(any()); |
| 537 | } |
| 538 | }, |
| 539 | LOCAL_LOCK_FREE_OUTPUT_DISABLED(/*optionValue=*/ false) { |
| 540 | @Override |
| 541 | void assertBugReport(BugReporter bugReporter) { |
| 542 | var captor = ArgumentCaptor.forClass(Exception.class); |
| 543 | verify(bugReporter).sendNonFatalBugReport(captor.capture()); |
| 544 | assertThat(captor.getValue()) |
| 545 | .hasMessageThat() |
| 546 | .contains("Multiple spawns produced 'output/foo/out' with overlapping execution time."); |
| 547 | } |
| 548 | }; |
| 549 | |
| 550 | LocalLockFreeOutput(boolean optionValue) { |
| 551 | this.optionValue = optionValue; |
| 552 | } |
| 553 | |
| 554 | private final boolean optionValue; |
| 555 | |
| 556 | abstract void assertBugReport(BugReporter bugReporter); |
| 557 | } |
| 558 | |
| 559 | @Test |
| 560 | public void multipleSpawnsWithSameOutput_overlapping_recordsBothSpawnsWithoutRetry( |
| 561 | @TestParameter LocalLockFreeOutput localLockFreeOutput) throws Exception { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 562 | var buffer = new ByteArrayOutputStream(); |
| 563 | BugReporter bugReporter = mock(BugReporter.class); |
| 564 | startLogging( |
| 565 | eventBus, |
| 566 | bugReporter, |
| 567 | localLockFreeOutput.optionValue, |
Googler | 4973166 | 2023-03-21 01:37:10 -0700 | [diff] [blame] | 568 | /* logFileWriteEdges= */ false, |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 569 | UUID.randomUUID(), |
| 570 | buffer, |
| 571 | DependencyInfo.ALL); |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 572 | SpawnResult localResult = createLocalSpawnResult(100); |
| 573 | SpawnResult remoteResult = createRemoteSpawnResult(200); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 574 | Spawn spawn = |
| 575 | new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(); |
| 576 | |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 577 | module.spawnExecuted( |
| 578 | new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), localResult, Instant.EPOCH)); |
| 579 | module.spawnExecuted( |
| 580 | new SpawnExecutedEvent( |
| 581 | spawn, new FakeActionInputFileCache(), remoteResult, Instant.ofEpochMilli(10))); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 582 | module.buildComplete(new BuildCompleteEvent(new BuildResult(1000))); |
| 583 | |
| 584 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 585 | assertThat(nodes) |
| 586 | .containsExactly( |
| 587 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 588 | .setIndex(0) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 589 | .setMetrics( |
| 590 | ExecutionGraph.Metrics.newBuilder() |
| 591 | .setStartTimestampMillis(0) |
| 592 | .setDurationMillis(100) |
| 593 | .setOtherMillis(100)) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 594 | .setRunner("local") |
| 595 | .build(), |
| 596 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 597 | .setIndex(1) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 598 | .setMetrics( |
| 599 | ExecutionGraph.Metrics.newBuilder() |
| 600 | .setStartTimestampMillis(10) |
| 601 | .setDurationMillis(200) |
| 602 | .setOtherMillis(200)) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 603 | .setRunner("remote") |
| 604 | .build()) |
| 605 | .inOrder(); |
| 606 | localLockFreeOutput.assertBugReport(bugReporter); |
| 607 | } |
| 608 | |
| 609 | @Test |
| 610 | public void multipleSpawnsWithSameOutput_overlapping_ignoresSecondSpawnForDependencies() |
| 611 | throws Exception { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 612 | var buffer = new ByteArrayOutputStream(); |
| 613 | startLogging( |
| 614 | eventBus, |
| 615 | BugReporter.defaultInstance(), |
Googler | 4973166 | 2023-03-21 01:37:10 -0700 | [diff] [blame] | 616 | /* localLockFreeOutputEnabled= */ true, |
| 617 | /* logFileWriteEdges= */ false, |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 618 | UUID.randomUUID(), |
| 619 | buffer, |
| 620 | DependencyInfo.ALL); |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 621 | SpawnResult localResult = createLocalSpawnResult(100); |
| 622 | SpawnResult remoteResult = createRemoteSpawnResult(200); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 623 | Artifact input = createOutputArtifact("foo/input"); |
| 624 | Spawn spawn = new SpawnBuilder().withOwnerPrimaryOutput(input).build(); |
| 625 | Spawn dependentSpawn = |
| 626 | new SpawnBuilder() |
| 627 | .withOwnerPrimaryOutput(createOutputArtifact("foo/output")) |
| 628 | .withInput(input) |
| 629 | .build(); |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 630 | SpawnResult dependentResult = createRemoteSpawnResult(300); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 631 | |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 632 | module.spawnExecuted( |
Googler | 17f678b | 2024-01-31 06:39:16 -0800 | [diff] [blame] | 633 | new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), localResult, Instant.EPOCH)); |
| 634 | module.spawnExecuted( |
| 635 | new SpawnExecutedEvent( |
| 636 | spawn, new FakeActionInputFileCache(), remoteResult, Instant.ofEpochMilli(10))); |
| 637 | module.spawnExecuted( |
| 638 | new SpawnExecutedEvent( |
| 639 | dependentSpawn, |
| 640 | new FakeActionInputFileCache(), |
| 641 | dependentResult, |
| 642 | Instant.ofEpochMilli(300))); |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 643 | module.buildComplete(new BuildCompleteEvent(new BuildResult(1000))); |
| 644 | |
| 645 | ImmutableList<ExecutionGraph.Node> nodes = parse(buffer); |
| 646 | assertThat(nodes) |
| 647 | .containsExactly( |
| 648 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 649 | .setIndex(0) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 650 | .setMetrics( |
| 651 | ExecutionGraph.Metrics.newBuilder() |
| 652 | .setStartTimestampMillis(0) |
| 653 | .setDurationMillis(100) |
| 654 | .setOtherMillis(100)) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 655 | .setRunner("local") |
| 656 | .build(), |
| 657 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 658 | .setIndex(1) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 659 | .setMetrics( |
| 660 | ExecutionGraph.Metrics.newBuilder() |
| 661 | .setStartTimestampMillis(10) |
| 662 | .setDurationMillis(200) |
| 663 | .setOtherMillis(200)) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 664 | .setRunner("remote") |
| 665 | .build(), |
| 666 | executionGraphNodeBuilderForSpawnBuilderSpawn() |
| 667 | .setIndex(2) |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 668 | .setMetrics( |
| 669 | ExecutionGraph.Metrics.newBuilder() |
| 670 | .setStartTimestampMillis(300) |
| 671 | .setDurationMillis(300) |
| 672 | .setOtherMillis(300)) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 673 | .setRunner("remote") |
| 674 | .addDependentIndex(0) |
| 675 | .build()) |
| 676 | .inOrder(); |
| 677 | } |
| 678 | |
| 679 | private class FakeOwnerWithPrimaryOutput extends FakeOwner { |
| 680 | |
| 681 | private final String primaryOutput; |
| 682 | |
| 683 | public FakeOwnerWithPrimaryOutput( |
| 684 | String mnemonic, String progressMessage, String ownerLabel, String primaryOutput) { |
| 685 | super(mnemonic, progressMessage, ownerLabel); |
| 686 | this.primaryOutput = primaryOutput; |
| 687 | } |
| 688 | |
| 689 | @Override |
| 690 | public Artifact getPrimaryOutput() { |
| 691 | return ActionsTestUtil.createArtifactWithExecPath( |
| 692 | artifactRoot, PathFragment.create(primaryOutput)); |
| 693 | } |
| 694 | } |
| 695 | |
| 696 | private Artifact createOutputArtifact(String rootRelativePath) { |
| 697 | return ActionsTestUtil.createArtifactWithExecPath( |
| 698 | artifactRoot, artifactRoot.getExecPath().getRelative(rootRelativePath)); |
| 699 | } |
| 700 | |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 701 | private SpawnResult createLocalSpawnResult(int totalTimeInMs) { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 702 | return new SpawnResult.Builder() |
| 703 | .setRunnerName("local") |
| 704 | .setStatus(Status.SUCCESS) |
| 705 | .setExitCode(0) |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 706 | .setSpawnMetrics( |
| 707 | SpawnMetrics.Builder.forLocalExec().setTotalTimeInMs(totalTimeInMs).build()) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 708 | .build(); |
| 709 | } |
| 710 | |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 711 | private SpawnResult createRemoteSpawnResult(int totalTimeInMs) { |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 712 | return new SpawnResult.Builder() |
| 713 | .setRunnerName("remote") |
| 714 | .setStatus(Status.SUCCESS) |
| 715 | .setExitCode(0) |
Googler | 9961a75 | 2023-02-23 05:21:53 -0800 | [diff] [blame] | 716 | .setSpawnMetrics( |
| 717 | SpawnMetrics.Builder.forRemoteExec().setTotalTimeInMs(totalTimeInMs).build()) |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 718 | .build(); |
| 719 | } |
| 720 | |
| 721 | /** |
| 722 | * Creates a {@link ExecutionGraph.Node.Builder} with pre-populated defaults for spawns created |
| 723 | * using {@link SpawnBuilder}. |
| 724 | */ |
| 725 | private ExecutionGraph.Node.Builder executionGraphNodeBuilderForSpawnBuilderSpawn() { |
| 726 | return ExecutionGraph.Node.newBuilder() |
| 727 | .setDescription("action 'progress message'") |
| 728 | .setTargetLabel("//dummy:label") |
| 729 | .setMnemonic("Mnemonic") |
Googler | c0b0996 | 2023-12-04 08:16:44 -0800 | [diff] [blame] | 730 | .setRuleClass("dummy-target-kind") |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 731 | // This comes from SpawnResult.Builder, which defaults to an empty string. |
| 732 | .setRunnerSubtype(""); |
| 733 | } |
Googler | 034f024 | 2022-09-21 11:34:24 -0700 | [diff] [blame] | 734 | |
| 735 | /** |
| 736 | * Creates a {@link ExecutionGraph.Node.Builder} with pre-populated defaults for action events. |
| 737 | */ |
| 738 | private ExecutionGraph.Node.Builder executionGraphNodeBuilderForAction(Action action) { |
| 739 | return ExecutionGraph.Node.newBuilder() |
| 740 | .setDescription(action.prettyPrint()) |
| 741 | .setTargetLabel(action.getOwner().getLabel().toString()) |
| 742 | .setMnemonic(action.getMnemonic()); |
| 743 | } |
Googler | 7f32687 | 2022-09-20 11:19:43 -0700 | [diff] [blame] | 744 | } |