// Copyright 2018 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.dynamic;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;

import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.BaseSpawn;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.ExecutionStrategy;
import com.google.devtools.build.lib.actions.ExecutorInitException;
import com.google.devtools.build.lib.actions.LocalHostCapacity;
import com.google.devtools.build.lib.actions.ResourceManager;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.SandboxedSpawnActionContext;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnActionContext;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil.NullAction;
import com.google.devtools.build.lib.exec.ExecutionPolicy;
import com.google.devtools.build.lib.testutil.TestThread;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.util.FileSystems;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link DynamicSpawnStrategy}. */
@RunWith(JUnit4.class)
public class DynamicSpawnStrategyTest {
  protected FileSystem fileSystem;
  protected Path testRoot;
  private ExecutorService executorService;
  private MockLocalSpawnStrategy localStrategy;
  private MockRemoteSpawnStrategy remoteStrategy;
  private SpawnActionContext dynamicSpawnStrategy;
  private Artifact inputArtifact;
  private Artifact outputArtifact;
  private FileOutErr outErr;
  private ActionExecutionContext actionExecutionContext;
  private DynamicExecutionOptions options;
  private final ActionKeyContext actionKeyContext = new ActionKeyContext();

  abstract static class MockSpawnStrategy implements SandboxedSpawnActionContext {
    private final Path testRoot;
    private final int delayMs;
    private volatile Spawn executedSpawn;
    private CountDownLatch succeeded = new CountDownLatch(1);
    private boolean failsDuringExecution;
    private CountDownLatch beforeExecutionWaitFor;
    private Callable<List<SpawnResult>> execute;

    public MockSpawnStrategy(Path testRoot, int delayMs) {
      this.testRoot = testRoot;
      this.delayMs = delayMs;
    }

    @Override
    public List<SpawnResult> exec(Spawn spawn, ActionExecutionContext actionExecutionContext)
        throws ExecException, InterruptedException {
      return exec(spawn, actionExecutionContext, null);
    }

    @Override
    public boolean canExec(Spawn spawn) {
      return true;
    }

    @Override
    public List<SpawnResult> exec(
        Spawn spawn,
        ActionExecutionContext actionExecutionContext,
        AtomicReference<Class<? extends SpawnActionContext>> writeOutputFiles)
        throws ExecException, InterruptedException {
      executedSpawn = spawn;

      if (beforeExecutionWaitFor != null) {
        beforeExecutionWaitFor.countDown();
        beforeExecutionWaitFor.await();
      }

      if (delayMs > 0) {
        Thread.sleep(delayMs);
      }

      List<SpawnResult> spawnResults = ImmutableList.of();
      if (execute != null) {
        try {
          spawnResults = execute.call();
        } catch (ExecException | InterruptedException e) {
          throw e;
        } catch (Exception e) {
          Throwables.throwIfUnchecked(e);
          throw new IllegalStateException(e);
        }
      }
      if (failsDuringExecution) {
        try {
          FileSystemUtils.appendIsoLatin1(
              actionExecutionContext.getFileOutErr().getOutputPath(),
              "action failed with " + getClass().getSimpleName());
        } catch (IOException e) {
          throw new IllegalStateException(e);
        }
        throw new UserExecException(getClass().getSimpleName() + " failed to execute the Spawn");
      }

      if (writeOutputFiles != null && !writeOutputFiles.compareAndSet(null, getClass())) {
        throw new InterruptedException(getClass() + " could not acquire barrier");
      } else {
        for (ActionInput output : spawn.getOutputFiles()) {
          try {
            FileSystemUtils.writeIsoLatin1(
                testRoot.getRelative(output.getExecPath()), getClass().getSimpleName());
          } catch (IOException e) {
            throw new IllegalStateException(e);
          }
        }
      }

      try {
        FileSystemUtils.appendIsoLatin1(
            actionExecutionContext.getFileOutErr().getOutputPath(),
            "output files written with " + getClass().getSimpleName());
      } catch (IOException e) {
        throw new IllegalStateException(e);
      }

      succeeded.countDown();

      return spawnResults;
    }

    public Spawn getExecutedSpawn() {
      return executedSpawn;
    }

    boolean succeeded() {
      return succeeded.getCount() == 0;
    }

    CountDownLatch getSucceededLatch() {
      return succeeded;
    }

    public void failsDuringExecution() {
      failsDuringExecution = true;
    }

    public void beforeExecutionWaitFor(CountDownLatch countDownLatch) {
      beforeExecutionWaitFor = countDownLatch;
    }

    void setExecute(Callable<List<SpawnResult>> execute) {
      this.execute = execute;
    }
  }

  @ExecutionStrategy(
    name = {"mock-remote"},
    contextType = SpawnActionContext.class
  )
  private static class MockRemoteSpawnStrategy extends MockSpawnStrategy {
    public MockRemoteSpawnStrategy(Path testRoot, int delayMs) {
      super(testRoot, delayMs);
    }
  }

  @ExecutionStrategy(
    name = {"mock-local"},
    contextType = SpawnActionContext.class
  )
  private static class MockLocalSpawnStrategy extends MockSpawnStrategy {
    public MockLocalSpawnStrategy(Path testRoot, int delayMs) {
      super(testRoot, delayMs);
    }
  }

  private static class DynamicSpawnStrategyUnderTest extends DynamicSpawnStrategy {
    public DynamicSpawnStrategyUnderTest(
        ExecutorService executorService,
        DynamicExecutionOptions options,
        Function<Spawn, ExecutionPolicy> executionPolicy) {
      super(executorService, options, executionPolicy);
    }
  }

  @Before
  public void setUp() throws Exception {
    ResourceManager.instance().setAvailableResources(LocalHostCapacity.getLocalHostCapacity());
    ResourceManager.instance()
        .setRamUtilizationPercentage(ResourceManager.DEFAULT_RAM_UTILIZATION_PERCENTAGE);
    ResourceManager.instance().resetResourceUsage();

    fileSystem = FileSystems.getNativeFileSystem();
    testRoot = fileSystem.getPath(TestUtils.tmpDir());
    testRoot.deleteTreesBelow();
    executorService = Executors.newCachedThreadPool();
    inputArtifact =
        ActionsTestUtil.createArtifact(
            ArtifactRoot.asSourceRoot(Root.fromPath(testRoot)), "input.txt");
    outputArtifact =
        ActionsTestUtil.createArtifact(
            ArtifactRoot.asSourceRoot(Root.fromPath(testRoot)), "output.txt");
    outErr = new FileOutErr(testRoot.getRelative("stdout"), testRoot.getRelative("stderr"));
    actionExecutionContext =
        ActionsTestUtil.createContext(
            /*executor=*/ null,
            /*eventHandler=*/ null,
            actionKeyContext,
            outErr,
            testRoot,
            /*metadataHandler=*/ null,
            /*actionGraph=*/ null);
  }

  void createSpawnStrategy(int localDelay, int remoteDelay) throws ExecutorInitException {
    localStrategy = new MockLocalSpawnStrategy(testRoot, localDelay);
    remoteStrategy = new MockRemoteSpawnStrategy(testRoot, remoteDelay);
    options = new DynamicExecutionOptions();
    options.dynamicLocalStrategy = "mock-local";
    options.dynamicRemoteStrategy = "mock-remote";
    options.dynamicWorkerStrategy = "mock-local";
    options.internalSpawnScheduler = true;
    options.localExecutionDelay = 0;
    dynamicSpawnStrategy =
        new DynamicSpawnStrategyUnderTest(executorService, options, this::getExecutionPolicy);
    dynamicSpawnStrategy.executorCreated(ImmutableList.of(localStrategy, remoteStrategy));
  }

  ExecutionPolicy getExecutionPolicy(Spawn spawn) {
    if (spawn.getExecutionInfo().containsKey("local")) {
      return ExecutionPolicy.LOCAL_EXECUTION_ONLY;
    } else if (spawn.getExecutionInfo().containsKey("remote")) {
      return ExecutionPolicy.REMOTE_EXECUTION_ONLY;
    } else {
      return ExecutionPolicy.ANYWHERE;
    }
  }

  @After
  public void tearDown() throws Exception {
    executorService.shutdownNow();
  }

  Spawn getSpawnForTest(boolean forceLocal, boolean forceRemote) {
    Preconditions.checkArgument(
        !(forceLocal && forceRemote), "Cannot force local and remote at the same time");
    ActionExecutionMetadata action =
        new NullAction(ImmutableList.of(inputArtifact), outputArtifact);
    return new BaseSpawn(
        ImmutableList.<String>of(),
        ImmutableMap.<String, String>of(),
        forceLocal
            ? ImmutableMap.of("local", "1")
            : forceRemote ? ImmutableMap.of("remote", "1") : ImmutableMap.<String, String>of(),
        action,
        ResourceSet.create(1, 0, 0));
  }

  @Test
  public void nonRemotableSpawnRunsLocally() throws Exception {
    Spawn spawn = getSpawnForTest(true, false);
    createSpawnStrategy(0, 0);

    dynamicSpawnStrategy.exec(spawn, actionExecutionContext);

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isTrue();
    assertThat(remoteStrategy.getExecutedSpawn()).isNull();
    assertThat(remoteStrategy.succeeded()).isFalse();

    assertThat(outErr.outAsLatin1()).contains("output files written with MockLocalSpawnStrategy");
    assertThat(outErr.outAsLatin1()).doesNotContain("MockRemoteSpawnStrategy");
  }

  @Test
  public void nonLocallyExecutableSpawnRunsRemotely() throws Exception {
    Spawn spawn = getSpawnForTest(false, true);
    createSpawnStrategy(0, 0);

    dynamicSpawnStrategy.exec(spawn, actionExecutionContext);

    assertThat(localStrategy.getExecutedSpawn()).isNull();
    assertThat(localStrategy.succeeded()).isFalse();
    assertThat(remoteStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(remoteStrategy.succeeded()).isTrue();

    assertThat(outErr.outAsLatin1()).contains("output files written with MockRemoteSpawnStrategy");
    assertThat(outErr.outAsLatin1()).doesNotContain("MockLocalSpawnStrategy");
  }

  @Test
  public void actionSucceedsIfLocalExecutionSucceedsEvenIfRemoteFailsLater() throws Exception {
    Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(0, 2000);
    CountDownLatch countDownLatch = new CountDownLatch(2);
    localStrategy.beforeExecutionWaitFor(countDownLatch);
    remoteStrategy.beforeExecutionWaitFor(countDownLatch);
    remoteStrategy.failsDuringExecution();

    dynamicSpawnStrategy.exec(spawn, actionExecutionContext);

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isTrue();
    assertThat(remoteStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(remoteStrategy.succeeded()).isFalse();

    assertThat(outErr.outAsLatin1()).contains("output files written with MockLocalSpawnStrategy");
    assertThat(outErr.outAsLatin1()).doesNotContain("MockRemoteSpawnStrategy");
  }

  @Test
  public void actionSucceedsIfRemoteExecutionSucceedsEvenIfLocalFailsLater() throws Exception {
    Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(2000, 0);
    CountDownLatch countDownLatch = new CountDownLatch(2);
    localStrategy.beforeExecutionWaitFor(countDownLatch);
    localStrategy.failsDuringExecution();
    remoteStrategy.beforeExecutionWaitFor(countDownLatch);

    dynamicSpawnStrategy.exec(spawn, actionExecutionContext);

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isFalse();
    assertThat(remoteStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(remoteStrategy.succeeded()).isTrue();

    assertThat(outErr.outAsLatin1()).contains("output files written with MockRemoteSpawnStrategy");
    assertThat(outErr.outAsLatin1()).doesNotContain("MockLocalSpawnStrategy");
  }

  @Test
  public void actionFailsIfLocalFailsImmediatelyEvenIfRemoteSucceedsLater() throws Exception {
    Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(0, 2000);
    CountDownLatch countDownLatch = new CountDownLatch(2);
    localStrategy.beforeExecutionWaitFor(countDownLatch);
    localStrategy.failsDuringExecution();
    remoteStrategy.beforeExecutionWaitFor(countDownLatch);

    ExecException e =
        assertThrows(
            ExecException.class, () -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
    assertThat(e).hasMessageThat().matches("MockLocalSpawnStrategy failed to execute the Spawn");

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isFalse();
    assertThat(remoteStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(remoteStrategy.succeeded()).isFalse();

    assertThat(outErr.outAsLatin1()).contains("action failed with MockLocalSpawnStrategy");
    assertThat(outErr.outAsLatin1()).doesNotContain("MockRemoteSpawnStrategy");
  }

  @Test
  public void actionFailsIfRemoteFailsImmediatelyEvenIfLocalSucceedsLater() throws Exception {
    Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(2000, 0);
    CountDownLatch countDownLatch = new CountDownLatch(2);
    localStrategy.beforeExecutionWaitFor(countDownLatch);
    remoteStrategy.beforeExecutionWaitFor(countDownLatch);
    remoteStrategy.failsDuringExecution();

    ExecException e =
        assertThrows(
            ExecException.class, () -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
    assertThat(e).hasMessageThat().matches("MockRemoteSpawnStrategy failed to execute the Spawn");

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isFalse();
    assertThat(remoteStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(remoteStrategy.succeeded()).isFalse();

    assertThat(outErr.outAsLatin1()).contains("action failed with MockRemoteSpawnStrategy");
    assertThat(outErr.outAsLatin1()).doesNotContain("MockLocalSpawnStrategy");
  }

  @Test
  public void actionFailsIfLocalAndRemoteFail() throws Exception {
    Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(0, 0);
    CountDownLatch countDownLatch = new CountDownLatch(2);
    localStrategy.beforeExecutionWaitFor(countDownLatch);
    remoteStrategy.beforeExecutionWaitFor(countDownLatch);
    localStrategy.failsDuringExecution();
    remoteStrategy.failsDuringExecution();

    ExecException e =
        assertThrows(
            ExecException.class, () -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
    assertThat(e)
        .hasMessageThat()
        .matches("Mock(Local|Remote)SpawnStrategy failed to execute the Spawn");

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isFalse();
    assertThat(remoteStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(remoteStrategy.succeeded()).isFalse();
  }

  @Test
  public void noDeadlockWithSingleThreadedExecutor() throws Exception {
    final Spawn spawn = getSpawnForTest(/*forceLocal=*/ false, /*forceRemote=*/ false);

    // Replace the executorService with a single threaded one.
    executorService = Executors.newSingleThreadExecutor();
    createSpawnStrategy(/*localDelay=*/ 0, /*remoteDelay=*/ 0);

    dynamicSpawnStrategy.exec(spawn, actionExecutionContext);

    assertThat(localStrategy.getExecutedSpawn()).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isTrue();

    /**
     * The single-threaded executorService#invokeAny does not comply to the contract where
     * the callables are *always* called sequentially. In this case, both spawns will start
     * executing, but the local one will always succeed as it's the first to be called. The remote
     * one will then be cancelled, or is null if the local one completes before the remote one
     * starts.
     *
     * See the documentation of {@link BoundedExectorService#invokeAny(Collection)}, specifically:
     * "The following is less efficient (it goes on submitting tasks even if there is some task
     * already finished), but quite straight-forward.".
     */
    assertThat(remoteStrategy.getExecutedSpawn()).isAnyOf(spawn, null);
    assertThat(remoteStrategy.succeeded()).isFalse();
  }

  @Test
  public void interruptDuringExecutionDoesActuallyInterruptTheExecution() throws Exception {
    final Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(60000, 60000);
    CountDownLatch countDownLatch = new CountDownLatch(2);
    localStrategy.beforeExecutionWaitFor(countDownLatch);
    remoteStrategy.beforeExecutionWaitFor(countDownLatch);

    TestThread testThread =
        new TestThread() {
          @Override
          public void runTest() throws Exception {
            try {
              dynamicSpawnStrategy.exec(spawn, actionExecutionContext);
            } catch (InterruptedException e) {
              // This is expected.
            }
          }
        };
    testThread.start();
    countDownLatch.await(5, TimeUnit.SECONDS);
    testThread.interrupt();
    testThread.joinAndAssertState(5000);

    assertThat(outErr.getOutputPath().exists()).isFalse();
    assertThat(outErr.getErrorPath().exists()).isFalse();
  }

  private void strategyWaitsForBothSpawnsToFinish(boolean interruptThread, boolean executionFails)
      throws Exception {
    final Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(0, 0);
    CountDownLatch waitToFinish = new CountDownLatch(1);
    CountDownLatch wasInterrupted = new CountDownLatch(1);
    CountDownLatch executionCanProceed = new CountDownLatch(2);
    localStrategy.setExecute(
        () -> {
          executionCanProceed.countDown();
          try {
            Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
            throw new IllegalStateException("Should have been interrupted");
          } catch (InterruptedException e) {
            // Expected.
          }
          wasInterrupted.countDown();
          try {
            Preconditions.checkState(
                waitToFinish.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS));
          } catch (InterruptedException e) {
            throw new IllegalStateException(e);
          }
          return ImmutableList.of();
        });
    if (executionFails) {
      remoteStrategy.failsDuringExecution();
    }
    remoteStrategy.beforeExecutionWaitFor(executionCanProceed);

    TestThread testThread =
        new TestThread() {
          @Override
          public void runTest() {
            try {
              dynamicSpawnStrategy.exec(spawn, actionExecutionContext);
              Preconditions.checkState(!interruptThread && !executionFails);
            } catch (InterruptedException e) {
              Preconditions.checkState(interruptThread && !executionFails);
              Preconditions.checkState(!Thread.currentThread().isInterrupted());
            } catch (ExecException e) {
              Preconditions.checkState(executionFails);
              Preconditions.checkState(Thread.currentThread().isInterrupted() == interruptThread);
            }
          }
        };
    testThread.start();
    if (!executionFails) {
      assertThat(
              remoteStrategy
                  .getSucceededLatch()
                  .await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS))
          .isTrue();
    }
    assertThat(wasInterrupted.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS)).isTrue();
    assertThat(testThread.isAlive()).isTrue();
    if (interruptThread) {
      testThread.interrupt();
    }
    // Wait up to 5 seconds for this thread to finish. It should not have finished.
    testThread.join(5000);
    assertThat(testThread.isAlive()).isTrue();
    waitToFinish.countDown();
    testThread.joinAndAssertState(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
  }

  @Test
  public void strategyWaitsForBothSpawnsToFinish() throws Exception {
    strategyWaitsForBothSpawnsToFinish(false, false);
  }

  @Test
  public void strategyWaitsForBothSpawnsToFinishEvenIfInterrupted() throws Exception {
    strategyWaitsForBothSpawnsToFinish(true, false);
  }

  @Test
  public void strategyWaitsForBothSpawnsToFinishOnFailure() throws Exception {
    strategyWaitsForBothSpawnsToFinish(false, true);
  }

  @Test
  public void strategyWaitsForBothSpawnsToFinishOnFailureEvenIfInterrupted() throws Exception {
    strategyWaitsForBothSpawnsToFinish(true, true);
  }

  @Test
  public void strategyPropagatesFasterLocalException() throws Exception {
    strategyPropagatesException(true);
  }

  @Test
  public void strategyPropagatesFasterRemoteException() throws Exception {
    strategyPropagatesException(false);
  }

  private void strategyPropagatesException(boolean preferLocal) throws Exception {
    final Spawn spawn = getSpawnForTest(false, false);
    createSpawnStrategy(!preferLocal ? 60000 : 0, preferLocal ? 60000 : 0);

    String message = "Mock spawn execution exception";
    Callable<List<SpawnResult>> execute = () -> {
      throw new IllegalStateException(message);
    };
    localStrategy.setExecute(execute);
    remoteStrategy.setExecute(execute);

    ExecException e =
        assertThrows(
            ExecException.class, () -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
    assertThat(e).hasMessageThat().matches("java.lang.IllegalStateException: " + message);

    Spawn executedSpawn = localStrategy.getExecutedSpawn();
    executedSpawn = executedSpawn == null ? remoteStrategy.getExecutedSpawn() : executedSpawn;
    assertThat(executedSpawn).isEqualTo(spawn);
    assertThat(localStrategy.succeeded()).isFalse();
    assertThat(remoteStrategy.succeeded()).isFalse();
  }
}
