// 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.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.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.Duration;
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()
                    .setTotalTime(Duration.ofMillis(1234L))
                    .setExecutionWallTime(Duration.ofMillis(2345L))
                    .setProcessOutputsTime(Duration.ofMillis(3456L))
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.NONE);
    Instant startTimeInstant = Instant.now();
    module.spawnExecuted(new SpawnExecutedEvent(spawn, 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 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()
                    .setTotalTime(Duration.ofMillis(1234L))
                    .setExecutionWallTime(Duration.ofMillis(2345L))
                    .setProcessOutputsTime(Duration.ofMillis(3456L))
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.ALL);
    Instant startTimeInstant = Instant.now();
    module.spawnExecuted(new SpawnExecutedEvent(spawnOut1, result, startTimeInstant));
    module.spawnExecuted(new SpawnExecutedEvent(spawnOut2, result, startTimeInstant));
    module.spawnExecuted(new SpawnExecutedEvent(spawnTop, 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,
            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,
        uuid,
        buffer,
        depType);
  }

  private void startLogging(
      EventBus eventBus,
      BugReporter bugReporter,
      boolean localLockFreeOutputEnabled,
      UUID uuid,
      OutputStream buffer,
      DependencyInfo depType) {
    ActionDumpWriter writer =
        new ActionDumpWriter(bugReporter, localLockFreeOutputEnabled, 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()
                    .setTotalTime(Duration.ofMillis(1234L))
                    .setExecutionWallTime(Duration.ofMillis(2345L))
                    .setProcessOutputsTime(Duration.ofMillis(3456L))
                    .build())
            .build();
    startLogging(eventBus, uuid, buffer, DependencyInfo.NONE);
    Instant startTimeInstant = Instant.now();
    module.spawnExecuted(new SpawnExecutedEvent(spawn, 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();
    options.logMissedActions = true;
    module.setOptions(options);

    module.spawnExecuted(
        new SpawnExecutedEvent(
            new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(),
            createRemoteSpawnResult(Duration.ofMillis(200)),
            Instant.ofEpochMilli(100)));
    module.actionComplete(
        new ActionCompletionEvent(
            0, new ActionsTestUtil.NullAction(createOutputArtifact("foo/out")), 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")
                .build());
  }

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

    module.spawnExecuted(
        new SpawnExecutedEvent(
            new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build(),
            createRemoteSpawnResult(Duration.ofMillis(200)),
            Instant.ofEpochMilli(100)));
    var action = new ActionsTestUtil.NullAction(createOutputArtifact("bar/out"));
    module.actionComplete(new ActionCompletionEvent(0, action, 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")
                .build(),
            executionGraphNodeBuilderForAction(action)
                .setIndex(1)
                .setMetrics(
                    ExecutionGraph.Metrics.newBuilder()
                        .setStartTimestampMillis(nanosToMillis.toEpochMillis(0)))
                .build());
  }

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

    module.spawnExecuted(new SpawnExecutedEvent(spawn, localResult, Instant.EPOCH));
    module.spawnExecuted(new SpawnExecutedEvent(spawn, 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,
        UUID.randomUUID(),
        buffer,
        DependencyInfo.ALL);
    SpawnResult localResult = createLocalSpawnResult(Duration.ofMillis(100));
    SpawnResult remoteResult = createRemoteSpawnResult(Duration.ofMillis(200));
    Spawn spawn =
        new SpawnBuilder().withOwnerPrimaryOutput(createOutputArtifact("foo/out")).build();

    module.spawnExecuted(new SpawnExecutedEvent(spawn, localResult, Instant.EPOCH));
    module.spawnExecuted(new SpawnExecutedEvent(spawn, 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,
        UUID.randomUUID(),
        buffer,
        DependencyInfo.ALL);
    SpawnResult localResult = createLocalSpawnResult(Duration.ofMillis(100));
    SpawnResult remoteResult = createRemoteSpawnResult(Duration.ofMillis(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(Duration.ofMillis(300));

    module.spawnExecuted(new SpawnExecutedEvent(spawn, localResult, Instant.EPOCH));
    module.spawnExecuted(new SpawnExecutedEvent(spawn, remoteResult, Instant.ofEpochMilli(10)));
    module.spawnExecuted(
        new SpawnExecutedEvent(dependentSpawn, 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(Duration totalTime) {
    return new SpawnResult.Builder()
        .setRunnerName("local")
        .setStatus(Status.SUCCESS)
        .setExitCode(0)
        .setSpawnMetrics(SpawnMetrics.Builder.forLocalExec().setTotalTime(totalTime).build())
        .build();
  }

  private SpawnResult createRemoteSpawnResult(Duration totalTime) {
    return new SpawnResult.Builder()
        .setRunnerName("remote")
        .setStatus(Status.SUCCESS)
        .setExitCode(0)
        .setSpawnMetrics(SpawnMetrics.Builder.forRemoteExec().setTotalTime(totalTime).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")
        // 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());
  }
}
