// 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 org.junit.Assert.fail;

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.PathFragment;
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 =
        new Artifact(
            PathFragment.create("input.txt"), ArtifactRoot.asSourceRoot(Root.fromPath(testRoot)));
    outputArtifact =
        new Artifact(
            PathFragment.create("output.txt"), ArtifactRoot.asSourceRoot(Root.fromPath(testRoot)));
    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);

    try {
      dynamicSpawnStrategy.exec(spawn, actionExecutionContext);
      fail("Expected dynamicSpawnStrategy to throw an ExecException");
    } catch (ExecException e) {
      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();

    try {
      dynamicSpawnStrategy.exec(spawn, actionExecutionContext);
      fail("Expected dynamicSpawnStrategy to throw an ExecException");
    } catch (ExecException e) {
      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();

    try {
      dynamicSpawnStrategy.exec(spawn, actionExecutionContext);
      fail("Expected dynamicSpawnStrategy to throw an ExecException");
    } catch (ExecException e) {
      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);

    try {
      dynamicSpawnStrategy.exec(spawn, actionExecutionContext);
      fail("Expected dynamicSpawnStrategy to throw an ExecException");
    } catch (ExecException e) {
      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();
  }
}
