@Test(expected = CancellationException.class)
public void cancelBeforeExecutionShouldThrowAndNotExecute() throws Exception {

    LocalCommandExecutor localCommandExecutor = new AbstractLocalCommandExecutor() {
        @Override
        void nonZeroLog(List<String> cmdLs, int exitCode) {
        }
        @Override
        public int execute(String program, List<String> args, Path outFile, Path errFile, Path workingDir, Map<String, String> env) throws IOException, InterruptedException {
            fail();
            return 0;
        }
    };
    CountDownLatch waitForBefore = new CountDownLatch(1);
    CountDownLatch waitForCancel = new CountDownLatch(1);
    try (ComputationManager computationManager = new LocalComputationManager(config, localCommandExecutor, ForkJoinPool.commonPool())) {
        Lock lock = new ReentrantLock();
        lock.lock();
        CompletableFuture<Object> result = computationManager.execute(ExecutionEnvironment.createDefault(), new AbstractExecutionHandler<Object>() {
            @Override
            public List<CommandExecution> before(Path workingDir) {
                waitForBefore.countDown();
                awaitUninterruptibly(waitForCancel);
                return dummyExecutions();
            }
            @Override
            public Object after(Path workingDir, ExecutionReport report) throws IOException {
                fail();
                return super.after(workingDir, report);
            }
        });
        waitForBefore.await();
        result.cancel(true);
        waitForCancel.countDown();
        result.get();
    }
}