@Deprecated
  public static <T> Task<T> withSideEffect(final Task<T> parent, final Task<?> sideEffect) {
    return parent.withSideEffect(t -> sideEffect);
  }
@Test
  public void testSideEffectCancelled() throws InterruptedException {
    // this task will not complete.
    Task<String> settableTask = new BaseTask<String>() {
      @Override
      protected Promise<? extends String> run(Context context) throws Exception {
        return Promises.settable();
      }
    };

    Task<String> fastTask = new BaseTask<String>() {
      @Override
      protected Promise<? extends String> run(Context context) throws Exception {
        return Promises.value("fast");
      }
    };

    Task<String> withSideEffect = settableTask.withSideEffect(x -> fastTask);
    // add 10 ms delay so that we can cancel settableTask reliably
    getEngine().run(delayedValue("value", 10, TimeUnit.MILLISECONDS).andThen(withSideEffect));
    assertTrue(settableTask.cancel(new Exception("task cancelled")));
    withSideEffect.await();
    fastTask.await(10, TimeUnit.MILLISECONDS);
    assertTrue(withSideEffect.isDone());
    assertFalse(fastTask.isDone());
  }