// Copyright 2022 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.runtime;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import com.github.luben.zstd.ZstdInputStream;
import com.github.luben.zstd.ZstdOutputStream;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionCompletionEvent;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.actions.DiscoveredInputsEvent;
import com.google.devtools.build.lib.actions.ExecutionGraph;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.SimpleSpawn;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnExecutedEvent;
import com.google.devtools.build.lib.actions.SpawnMetrics;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.SpawnResult.Status;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.bugreport.BugReporter;
import com.google.devtools.build.lib.buildtool.BuildResult;
import com.google.devtools.build.lib.buildtool.BuildResult.BuildToolLogCollection;
import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.exec.util.FakeActionInputFileCache;
import com.google.devtools.build.lib.exec.util.FakeOwner;
import com.google.devtools.build.lib.exec.util.SpawnBuilder;
import com.google.devtools.build.lib.runtime.ExecutionGraphModule.ActionDumpWriter;
import com.google.devtools.build.lib.runtime.ExecutionGraphModule.DependencyInfo;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

/** Unit tests for {@link ExecutionGraphModule}. */
@RunWith(TestParameterInjector.class)
public class ExecutionGraphModuleTest extends FoundationTestCase {
  private ExecutionGraphModule module;
  private ArtifactRoot artifactRoot;

  @Before
  public void createModule() {
    module = new ExecutionGraphModule();
  }

  @Before
  public final void initializeRoots() throws Exception {
    artifactRoot = ArtifactRoot.asDerivedRoot(scratch.resolve("/"), RootType.Output, "output");
  }

  private static ImmutableList<ExecutionGraph.Node> parse(ByteArrayOutputStream buffer)
      throws IOException {
    byte[] data = buffer.toByteArray();
    try (InputStream in = new ZstdInputStream(new ByteArrayInputStream(data))) {
      ImmutableList.Builder<ExecutionGraph.Node> nodeListBuilder = new ImmutableList.Builder<>();
      ExecutionGraph.Node node;
      while ((node = ExecutionGraph.Node.parseDelimitedFrom(in)) != null) {
        nodeListBuilder.add(node);
      }
      return nodeListBuilder.build();
    }
  }

  @Test
  public void testOneSpawn() throws IOException {
    UUID uuid = UUID.randomUUID();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    Spawn spawn =
        new SimpleSpawn(
            new FakeOwnerWithPrimaryOutput(
                "Mnemonic", "Progress message", "//foo", "output/foo/out"),
            ImmutableList.of("cmd"),
            ImmutableMap.of("env", "value"),
            ImmutableMap.of("exec", "value"),
            /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
            /* outputs= */ ImmutableSet.of(ActionInputHelper.fromPath("output/foo/out")),
            ResourceSet.ZERO);
    SpawnResult result =
        new SpawnResult.Builder()
            .setRunnerName("local")
            .setStatus(Status.SUCCESS)
            .setExitCode(0)
            .setSpawnMetrics(
                SpawnMetrics.Builder.forLocalExec()
                    .setTotalTimeInMs(1234)
                    .setExecutionWallTimeInMs(2345)
                    .setProcessOutputsTimeInMs(3456)
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.NONE);
    Instant startTimeInstant = Instant.now();
    module.spawnExecuted(
        new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), result, startTimeInstant));
    module.buildComplete(
        new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000)));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    assertThat(nodes).hasSize(1);
    assertThat(nodes.get(0).getTargetLabel()).isEqualTo("//foo:foo");
    assertThat(nodes.get(0).getMnemonic()).isEqualTo("Mnemonic");
    assertThat(nodes.get(0).getMetrics().getDurationMillis()).isEqualTo(1234L);
    assertThat(nodes.get(0).getMetrics().getFetchMillis()).isEqualTo(0);
    assertThat(nodes.get(0).getMetrics().getProcessOutputsMillis()).isEqualTo(3456);
    assertThat(nodes.get(0).getMetrics().getStartTimestampMillis())
        .isEqualTo(startTimeInstant.toEpochMilli());
    assertThat(nodes.get(0).getIndex()).isEqualTo(0);
    assertThat(nodes.get(0).getDependentIndexList()).isEmpty();
  }

  @Test
  public void testSpawnWithDiscoverInputs() throws IOException {
    UUID uuid = UUID.randomUUID();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    Spawn spawn =
        new SimpleSpawn(
            new FakeOwnerWithPrimaryOutput(
                "Mnemonic", "Progress message", "//foo", "output/foo/out"),
            ImmutableList.of("cmd"),
            ImmutableMap.of("env", "value"),
            ImmutableMap.of("exec", "value"),
            /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
            /* outputs= */ ImmutableSet.of(createOutputArtifact("output/foo/out")),
            ResourceSet.ZERO);
    SpawnResult result =
        new SpawnResult.Builder()
            .setRunnerName("local")
            .setStatus(Status.SUCCESS)
            .setExitCode(0)
            .setSpawnMetrics(
                SpawnMetrics.Builder.forLocalExec()
                    .setTotalTimeInMs(1234)
                    .setExecutionWallTimeInMs(2345)
                    .setProcessOutputsTimeInMs(3456)
                    .setParseTimeInMs(2000)
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.NONE);
    Instant startTimeInstant = Instant.ofEpochMilli(999888777L);
    module.discoverInputs(
        new DiscoveredInputsEvent(
            SpawnMetrics.Builder.forOtherExec().setParseTimeInMs(987).setTotalTimeInMs(987).build(),
            new ActionsTestUtil.NullAction(createOutputArtifact("output/foo/out")),
            0));
    module.spawnExecuted(
        new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), result, startTimeInstant));
    module.buildComplete(
        new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000)));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    ExecutionGraph.Metrics metrics = nodes.get(0).getMetrics();
    assertThat(metrics.getDurationMillis()).isEqualTo(2221);
    assertThat(metrics.getFetchMillis()).isEqualTo(0);
    assertThat(metrics.getProcessMillis()).isEqualTo(2345);
    assertThat(metrics.getProcessOutputsMillis()).isEqualTo(3456);
    assertThat(metrics.getParseMillis()).isEqualTo(2000);
    assertThat(metrics.getDiscoverInputsMillis()).isEqualTo(987);
  }

  @Test
  public void actionDepsWithThreeSpawns() throws IOException {
    UUID uuid = UUID.randomUUID();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    ActionInput out1 = ActionInputHelper.fromPath("output/foo/out1");
    ActionInput out2 = ActionInputHelper.fromPath("output/foo/out2");
    ActionInput outTop = ActionInputHelper.fromPath("output/foo/out.top");

    Spawn spawnOut1 =
        new SimpleSpawn(
            new FakeOwnerWithPrimaryOutput(
                "Mnemonic", "Progress message", "//foo", out1.getExecPathString()),
            ImmutableList.of("cmd"),
            ImmutableMap.of("env", "value"),
            ImmutableMap.of("exec", "value"),
            /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
            /* outputs= */ ImmutableSet.of(out1),
            ResourceSet.ZERO);
    Spawn spawnOut2 =
        new SimpleSpawn(
            new FakeOwnerWithPrimaryOutput(
                "Mnemonic", "Progress message", "//foo", out2.getExecPathString()),
            ImmutableList.of("cmd"),
            ImmutableMap.of("env", "value"),
            ImmutableMap.of("exec", "value"),
            /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
            /* outputs= */ ImmutableSet.of(out2),
            ResourceSet.ZERO);
    Spawn spawnTop =
        new SimpleSpawn(
            new FakeOwnerWithPrimaryOutput(
                "Mnemonic", "Progress message", "//foo", outTop.getExecPathString()),
            ImmutableList.of("cmd"),
            ImmutableMap.of("env", "value"),
            ImmutableMap.of("exec", "value"),
            /* inputs= */ NestedSetBuilder.create(Order.COMPILE_ORDER, out1, out2),
            /* outputs= */ ImmutableSet.of(outTop),
            ResourceSet.ZERO);
    SpawnResult result =
        new SpawnResult.Builder()
            .setRunnerName("local")
            .setStatus(Status.SUCCESS)
            .setExitCode(0)
            .setSpawnMetrics(
                SpawnMetrics.Builder.forLocalExec()
                    .setTotalTimeInMs(1234)
                    .setExecutionWallTimeInMs(2345)
                    .setProcessOutputsTimeInMs(3456)
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.ALL);
    Instant startTimeInstant = Instant.now();
    module.spawnExecuted(
        new SpawnExecutedEvent(
            spawnOut1, new FakeActionInputFileCache(), result, startTimeInstant));
    module.spawnExecuted(
        new SpawnExecutedEvent(
            spawnOut2, new FakeActionInputFileCache(), result, startTimeInstant));
    module.spawnExecuted(
        new SpawnExecutedEvent(spawnTop, new FakeActionInputFileCache(), result, startTimeInstant));
    module.buildComplete(
        new BuildCompleteEvent(new BuildResult(startTimeInstant.plusMillis(1000).toEpochMilli())));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    assertThat(nodes).hasSize(3);

    assertThat(nodes.get(0).getIndex()).isEqualTo(0);
    assertThat(nodes.get(0).getDependentIndexList()).isEmpty();

    assertThat(nodes.get(1).getIndex()).isEqualTo(1);
    assertThat(nodes.get(1).getDependentIndexList()).isEmpty();

    assertThat(nodes.get(2).getIndex()).isEqualTo(2);
    assertThat(nodes.get(2).getDependentIndexList()).containsExactly(0, 1);
  }

  private enum FailingOutputStreamFactory {
    CLOSE {
      @Override
      public ZstdOutputStream get() throws IOException {
        return new ZstdOutputStream(OutputStream.nullOutputStream()) {
          @Override
          public synchronized void close() throws IOException {
            throw new IOException("Simulated close failure");
          }
        };
      }
    },
    /** Called from {@link com.google.protobuf.CodedOutputStream#flush}. */
    WRITE {
      @Override
      public ZstdOutputStream get() throws IOException {
        return new ZstdOutputStream(OutputStream.nullOutputStream()) {
          @Override
          public synchronized void write(byte[] b, int off, int len) throws IOException {
            throw new IOException("oh no!");
          }
        };
      }
    };

    abstract ZstdOutputStream get() throws IOException;
  }

  /** Regression test for b/218721483. */
  @Test(timeout = 30_000)
  public void failureInOutputDoesNotHang(
      @TestParameter FailingOutputStreamFactory failingOutputStream) {
    UUID uuid = UUID.randomUUID();
    ActionDumpWriter writer =
        new ActionDumpWriter(
            BugReporter.defaultInstance(),
            /* localLockFreeOutputEnabled= */ false,
            /* logFileWriteEdges= */ false,
            OutputStream.nullOutputStream(),
            uuid,
            DependencyInfo.NONE,
            -1) {
          @Override
          protected void updateLogs(BuildToolLogCollection logs) {}

          @Override
          protected ZstdOutputStream createCompressingOutputStream() throws IOException {
            return failingOutputStream.get();
          }
        };
    module.setWriter(writer);
    eventBus.register(module);

    Instant startTimeInstant = Instant.now();
    eventBus.post(new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000)));
  }

  private void startLogging(
      EventBus eventBus, UUID uuid, OutputStream buffer, DependencyInfo depType) {
    startLogging(
        eventBus,
        BugReporter.defaultInstance(),
        /* localLockFreeOutputEnabled= */ false,
        /* logFileWriteEdges= */ false,
        uuid,
        buffer,
        depType);
  }

  private void startLogging(
      EventBus eventBus,
      BugReporter bugReporter,
      boolean localLockFreeOutputEnabled,
      boolean logFileWriteEdges,
      UUID uuid,
      OutputStream buffer,
      DependencyInfo depType) {
    ActionDumpWriter writer =
        new ActionDumpWriter(
            bugReporter, localLockFreeOutputEnabled, logFileWriteEdges, buffer, uuid, depType, -1) {
          @Override
          protected void updateLogs(BuildToolLogCollection logs) {}
        };
    module.setWriter(writer);
    eventBus.register(module);
  }

  @Test
  public void shutDownWithoutStartTolerated() {
    eventBus.register(module);
    Instant startTimeInstant = Instant.now();
    // Doesn't crash.
    eventBus.post(new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000)));
  }

  @Test
  public void testSpawnWithNullOwnerLabel() throws IOException {
    UUID uuid = UUID.randomUUID();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    Spawn spawn =
        new SimpleSpawn(
            new FakeOwnerWithPrimaryOutput(
                "Mnemonic", "Progress message", "//unused:label", "output/foo/out") {
              @Override
              public ActionOwner getOwner() {
                return ActionOwner.SYSTEM_ACTION_OWNER;
              }
            },
            ImmutableList.of("cmd"),
            ImmutableMap.of("env", "value"),
            ImmutableMap.of("exec", "value"),
            /* inputs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
            /* outputs= */ ImmutableSet.of(ActionInputHelper.fromPath("output/foo/out")),
            ResourceSet.ZERO);
    SpawnResult result =
        new SpawnResult.Builder()
            .setRunnerName("local")
            .setStatus(Status.SUCCESS)
            .setExitCode(0)
            .setSpawnMetrics(
                SpawnMetrics.Builder.forLocalExec()
                    .setTotalTimeInMs(1234)
                    .setExecutionWallTimeInMs(2345)
                    .setProcessOutputsTimeInMs(3456)
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.NONE);
    Instant startTimeInstant = Instant.now();
    module.spawnExecuted(
        new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), result, startTimeInstant));
    module.buildComplete(
        new BuildCompleteEvent(new BuildResult(startTimeInstant.toEpochMilli() + 1000)));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    assertThat(nodes).hasSize(1);
    assertThat(nodes.get(0).getTargetLabel()).isEmpty();
  }

  @Test
  public void spawnAndAction_withSameOutputs() throws Exception {
    var buffer = new ByteArrayOutputStream();
    startLogging(eventBus, UUID.randomUUID(), buffer, DependencyInfo.ALL);
    var options = new ExecutionGraphModule.ExecutionGraphOptions();
    module.setOptions(options);

    module.spawnExecuted(
        new SpawnExecutedEvent(
            new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(),
            new FakeActionInputFileCache(),
            createRemoteSpawnResult(200),
            Instant.ofEpochMilli(100)));
    module.actionComplete(
        new ActionCompletionEvent(
            0,
            0,
            new ActionsTestUtil.NullAction(createOutputArtifact("foo/out")),
            new FakeActionInputFileCache(),
            null));
    module.buildComplete(new BuildCompleteEvent(new BuildResult(1000)));

    assertThat(parse(buffer))
        .containsExactly(
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(0)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(100)
                        .setDurationMillis(200)
                        .setOtherMillis(200))
                .setRunner("remote")
                .setRuleClass("dummy-target-kind")
                .build());
  }

  @Test
  public void spawnAndAction_withDifferentOutputs() throws Exception {
    var buffer = new ByteArrayOutputStream();
    startLogging(eventBus, UUID.randomUUID(), buffer, DependencyInfo.ALL);
    var options = new ExecutionGraphModule.ExecutionGraphOptions();
    module.setOptions(options);
    var nanosToMillis = BlazeClock.createNanosToMillisSinceEpochConverter();
    module.setNanosToMillis(nanosToMillis);

    module.spawnExecuted(
        new SpawnExecutedEvent(
            new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(),
            new FakeActionInputFileCache(),
            createRemoteSpawnResult(200),
            Instant.ofEpochMilli(100)));
    var action = new ActionsTestUtil.NullAction(createOutputArtifact("bar/out"));
    module.actionComplete(
        new ActionCompletionEvent(0, 0, action, new FakeActionInputFileCache(), null));
    module.buildComplete(new BuildCompleteEvent(new BuildResult(1000)));

    assertThat(parse(buffer))
        .containsExactly(
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(0)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(100)
                        .setDurationMillis(200)
                        .setOtherMillis(200))
                .setRuleClass("dummy-target-kind")
                .setRunner("remote")
                .build(),
            executionGraphNodeBuilderForAction(action)
                .setIndex(1)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(nanosToMillis.toEpochMillis(0)))
                .setRuleClass("dummy-kind")
                .build());
  }

  @Test
  public void multipleSpawnsWithSameOutput_recordsBothSpawnsWithRetry() throws Exception {
    var buffer = new ByteArrayOutputStream();
    startLogging(eventBus, UUID.randomUUID(), buffer, DependencyInfo.ALL);
    SpawnResult localResult = createLocalSpawnResult(100);
    SpawnResult remoteResult = createRemoteSpawnResult(200);
    Spawn spawn =
        new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build();

    module.spawnExecuted(
        new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), localResult, Instant.EPOCH));
    module.spawnExecuted(
        new SpawnExecutedEvent(
            spawn, new FakeActionInputFileCache(), remoteResult, Instant.ofEpochMilli(100)));
    module.buildComplete(new BuildCompleteEvent(new BuildResult(1000)));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    assertThat(nodes)
        .containsExactly(
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(0)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(0)
                        .setDurationMillis(100)
                        .setOtherMillis(100))
                .setRunner("local")
                .build(),
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(1)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(100)
                        .setDurationMillis(200)
                        .setOtherMillis(200))
                .setRunner("remote")
                .setRetryOf(0)
                .build())
        .inOrder();
  }

  enum LocalLockFreeOutput {
    LOCAL_LOCK_FREE_OUTPUT_ENABLED(/*optionValue=*/ true) {
      @Override
      void assertBugReport(BugReporter bugReporter) {
        verify(bugReporter, never()).sendNonFatalBugReport(any());
      }
    },
    LOCAL_LOCK_FREE_OUTPUT_DISABLED(/*optionValue=*/ false) {
      @Override
      void assertBugReport(BugReporter bugReporter) {
        var captor = ArgumentCaptor.forClass(Exception.class);
        verify(bugReporter).sendNonFatalBugReport(captor.capture());
        assertThat(captor.getValue())
            .hasMessageThat()
            .contains("Multiple spawns produced 'output/foo/out' with overlapping execution time.");
      }
    };

    LocalLockFreeOutput(boolean optionValue) {
      this.optionValue = optionValue;
    }

    private final boolean optionValue;

    abstract void assertBugReport(BugReporter bugReporter);
  }

  @Test
  public void multipleSpawnsWithSameOutput_overlapping_recordsBothSpawnsWithoutRetry(
      @TestParameter LocalLockFreeOutput localLockFreeOutput) throws Exception {
    var buffer = new ByteArrayOutputStream();
    BugReporter bugReporter = mock(BugReporter.class);
    startLogging(
        eventBus,
        bugReporter,
        localLockFreeOutput.optionValue,
        /* logFileWriteEdges= */ false,
        UUID.randomUUID(),
        buffer,
        DependencyInfo.ALL);
    SpawnResult localResult = createLocalSpawnResult(100);
    SpawnResult remoteResult = createRemoteSpawnResult(200);
    Spawn spawn =
        new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build();

    module.spawnExecuted(
        new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), localResult, Instant.EPOCH));
    module.spawnExecuted(
        new SpawnExecutedEvent(
            spawn, new FakeActionInputFileCache(), remoteResult, Instant.ofEpochMilli(10)));
    module.buildComplete(new BuildCompleteEvent(new BuildResult(1000)));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    assertThat(nodes)
        .containsExactly(
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(0)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(0)
                        .setDurationMillis(100)
                        .setOtherMillis(100))
                .setRunner("local")
                .build(),
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(1)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(10)
                        .setDurationMillis(200)
                        .setOtherMillis(200))
                .setRunner("remote")
                .build())
        .inOrder();
    localLockFreeOutput.assertBugReport(bugReporter);
  }

  @Test
  public void multipleSpawnsWithSameOutput_overlapping_ignoresSecondSpawnForDependencies()
      throws Exception {
    var buffer = new ByteArrayOutputStream();
    startLogging(
        eventBus,
        BugReporter.defaultInstance(),
        /* localLockFreeOutputEnabled= */ true,
        /* logFileWriteEdges= */ false,
        UUID.randomUUID(),
        buffer,
        DependencyInfo.ALL);
    SpawnResult localResult = createLocalSpawnResult(100);
    SpawnResult remoteResult = createRemoteSpawnResult(200);
    Artifact input = createOutputArtifact("foo/input");
    Spawn spawn = new SpawnBuilder().withOwnerPrimaryOutput(input).build();
    Spawn dependentSpawn =
        new SpawnBuilder()
            .withOwnerPrimaryOutput(createOutputArtifact("foo/output"))
            .withInput(input)
            .build();
    SpawnResult dependentResult = createRemoteSpawnResult(300);

    module.spawnExecuted(
        new SpawnExecutedEvent(spawn, new FakeActionInputFileCache(), localResult, Instant.EPOCH));
    module.spawnExecuted(
        new SpawnExecutedEvent(
            spawn, new FakeActionInputFileCache(), remoteResult, Instant.ofEpochMilli(10)));
    module.spawnExecuted(
        new SpawnExecutedEvent(
            dependentSpawn,
            new FakeActionInputFileCache(),
            dependentResult,
            Instant.ofEpochMilli(300)));
    module.buildComplete(new BuildCompleteEvent(new BuildResult(1000)));

    ImmutableList<ExecutionGraph.Node> nodes = parse(buffer);
    assertThat(nodes)
        .containsExactly(
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(0)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(0)
                        .setDurationMillis(100)
                        .setOtherMillis(100))
                .setRunner("local")
                .build(),
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(1)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(10)
                        .setDurationMillis(200)
                        .setOtherMillis(200))
                .setRunner("remote")
                .build(),
            executionGraphNodeBuilderForSpawnBuilderSpawn()
                .setIndex(2)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(300)
                        .setDurationMillis(300)
                        .setOtherMillis(300))
                .setRunner("remote")
                .addDependentIndex(0)
                .build())
        .inOrder();
  }

  private class FakeOwnerWithPrimaryOutput extends FakeOwner {

    private final String primaryOutput;

    public FakeOwnerWithPrimaryOutput(
        String mnemonic, String progressMessage, String ownerLabel, String primaryOutput) {
      super(mnemonic, progressMessage, ownerLabel);
      this.primaryOutput = primaryOutput;
    }

    @Override
    public Artifact getPrimaryOutput() {
      return ActionsTestUtil.createArtifactWithExecPath(
          artifactRoot, PathFragment.create(primaryOutput));
    }
  }

  private Artifact createOutputArtifact(String rootRelativePath) {
    return ActionsTestUtil.createArtifactWithExecPath(
        artifactRoot, artifactRoot.getExecPath().getRelative(rootRelativePath));
  }

  private SpawnResult createLocalSpawnResult(int totalTimeInMs) {
    return new SpawnResult.Builder()
        .setRunnerName("local")
        .setStatus(Status.SUCCESS)
        .setExitCode(0)
        .setSpawnMetrics(
            SpawnMetrics.Builder.forLocalExec().setTotalTimeInMs(totalTimeInMs).build())
        .build();
  }

  private SpawnResult createRemoteSpawnResult(int totalTimeInMs) {
    return new SpawnResult.Builder()
        .setRunnerName("remote")
        .setStatus(Status.SUCCESS)
        .setExitCode(0)
        .setSpawnMetrics(
            SpawnMetrics.Builder.forRemoteExec().setTotalTimeInMs(totalTimeInMs).build())
        .build();
  }

  /**
   * Creates a {@link ExecutionGraph.Node.Builder} with pre-populated defaults for spawns created
   * using {@link SpawnBuilder}.
   */
  private ExecutionGraph.Node.Builder executionGraphNodeBuilderForSpawnBuilderSpawn() {
    return ExecutionGraph.Node.newBuilder()
        .setDescription("action 'progress message'")
        .setTargetLabel("//dummy:label")
        .setMnemonic("Mnemonic")
        .setRuleClass("dummy-target-kind")
        // This comes from SpawnResult.Builder, which defaults to an empty string.
        .setRunnerSubtype("");
  }

  /**
   * Creates a {@link ExecutionGraph.Node.Builder} with pre-populated defaults for action events.
   */
  private ExecutionGraph.Node.Builder executionGraphNodeBuilderForAction(Action action) {
    return ExecutionGraph.Node.newBuilder()
        .setDescription(action.prettyPrint())
        .setTargetLabel(action.getOwner().getLabel().toString())
        .setMnemonic(action.getMnemonic());
  }
}
