blob: 9ed1db54ed8a38e398b61fb2691a54d1067b8f12 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Tests for Future.immediate
testImmediate() {
final future = new Future<String>.immediate("42");
Expect.isTrue(future.isComplete);
Expect.isTrue(future.hasValue);
var value = null;
future.then((x) => value = x);
Expect.equals("42", value);
}
// Tests for getters (value, exception, isComplete, isValue)
testNeverComplete() {
final completer = new Completer<int>();
final future = completer.future;
Expect.isFalse(future.isComplete);
Expect.isFalse(future.hasValue);
Expect.throws(() { future.value; });
Expect.throws(() { future.exception; });
}
testComplete() {
final completer = new Completer<int>();
final future = completer.future;
completer.complete(3);
Expect.isTrue(future.isComplete);
Expect.isTrue(future.hasValue);
Expect.equals(3, future.value);
Expect.isNull(future.exception);
}
// Tests for [onComplete]
testCompleteWithCompleteHandlerBeforeComplete() {
final completer = new Completer<int>();
final future = completer.future;
int before;
future.onComplete((f) {
Expect.equals(future, f);
Expect.isTrue(f.isComplete);
Expect.isTrue(f.hasValue);
before = f.value;
});
Expect.throws(() => future.value);
Expect.isNull(before);
completer.complete(3);
Expect.equals(3, future.value);
Expect.equals(3, before);
}
testExceptionWithCompleteHandlerBeforeComplete() {
final completer = new Completer<int>();
final future = completer.future;
final exception = new Exception();
var err;
future.onComplete((f) {
Expect.equals(future, f);
Expect.isTrue(f.isComplete);
Expect.isFalse(f.hasValue);
err = f.exception;
});
Expect.throws(() => future.exception);
Expect.isNull(err);
completer.completeException(exception);
Expect.equals(exception, future.exception);
Expect.equals(exception, err);
Expect.throws(() => future.value, (e) => e.source == exception);
}
testCompleteWithCompleteHandlerAfterComplete() {
final completer = new Completer<int>();
final future = completer.future;
int after;
completer.complete(3);
future.onComplete((f) {
Expect.equals(future, f);
Expect.isTrue(f.isComplete);
Expect.isTrue(f.hasValue);
after = f.value;
});
Expect.equals(3, future.value);
Expect.equals(3, after);
}
testExceptionWithCompleteHandlerAfterComplete() {
final completer = new Completer<int>();
final future = completer.future;
final exception = new Exception();
var err;
completer.completeException(exception);
future.onComplete((f) {
Expect.equals(future, f);
Expect.isTrue(f.isComplete);
Expect.isFalse(f.hasValue);
err = f.exception;
});
Expect.equals(exception, future.exception);
Expect.equals(exception, err);
Expect.throws(() => future.value, (e) => e.source == exception);
}
testCompleteWithManyCompleteHandlers() {
final completer = new Completer<int>();
final future = completer.future;
int before;
int after1;
int after2;
future.onComplete((f) { before = f.value; });
completer.complete(3);
future.onComplete((f) { after1 = f.value; });
future.onComplete((f) { after2 = f.value; });
Expect.equals(3, future.value);
Expect.equals(3, before);
Expect.equals(3, after1);
Expect.equals(3, after2);
}
testExceptionWithManyCompleteHandlers() {
final completer = new Completer<int>();
final future = completer.future;
final exception = new Exception();
var before;
var after1;
var after2;
future.onComplete((f) { before = f.exception; });
completer.completeException(exception);
future.onComplete((f) { after1 = f.exception; });
future.onComplete((f) { after2 = f.exception; });
Expect.equals(exception, future.exception);
Expect.equals(exception, before);
Expect.equals(exception, after1);
Expect.equals(exception, after2);
Expect.throws(() => future.value, (e) => e.source == exception);
}
// Tests for [then]
testCompleteWithSuccessHandlerBeforeComplete() {
final completer = new Completer<int>();
final future = completer.future;
int before;
future.then((int v) { before = v; });
Expect.throws(() { future.value; });
Expect.isNull(before);
completer.complete(3);
Expect.equals(3, future.value);
Expect.equals(3, before);
}
testCompleteWithSuccessHandlerAfterComplete() {
final completer = new Completer<int>();
final future = completer.future;
int after;
completer.complete(3);
Expect.equals(3, future.value);
Expect.isNull(after);
future.then((int v) { after = v; });
Expect.equals(3, future.value);
Expect.equals(3, after);
}
testCompleteManySuccessHandlers() {
final completer = new Completer<int>();
final future = completer.future;
int before;
int after1;
int after2;
future.then((int v) { before = v; });
completer.complete(3);
future.then((int v) { after1 = v; });
future.then((int v) { after2 = v; });
Expect.equals(3, future.value);
Expect.equals(3, before);
Expect.equals(3, after1);
Expect.equals(3, after2);
}
// Tests for [handleException]
testException() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
future.then((_) {}); // exception is thrown if we plan to use the value
Expect.throws(
() { completer.completeException(ex); },
(e) => e.source == ex);
}
testExceptionNoSuccessListeners() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
completer.completeException(ex); // future.then is not called, so no exception
}
testExceptionHandler() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
var ex2;
future.handleException((e) { ex2 = e; return true; });
completer.completeException(ex);
Expect.equals(ex, ex2);
}
testExceptionHandlerReturnsTrue() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
bool reached = false;
future.handleException((e) { return true; });
future.handleException((e) { reached = true; return false; }); // overshadowed
completer.completeException(ex);
Expect.isFalse(reached);
}
testExceptionHandlerReturnsTrue2() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
bool reached = false;
future.handleException((e) { return false; });
future.handleException((e) { reached = true; return true; });
completer.completeException(ex);
Expect.isTrue(reached);
}
testExceptionHandlerReturnsFalse() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
bool reached = false;
future.then((_) {}); // ensure exception is thrown...
future.handleException((e) { return false; });
future.handleException((e) { reached = true; return false; }); // overshadowed
Expect.throws(
() { completer.completeException(ex); },
(e) => e.source == ex);
Expect.isTrue(reached);
}
testExceptionHandlerReturnsFalse2() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
bool reached = false;
future.handleException((e) { return false; });
future.handleException((e) { reached = true; return false; }); // overshadowed
completer.completeException(ex); // future.then is not called, so no exception
Expect.isTrue(reached);
}
testExceptionHandlerAfterCompleteThenNotCalled() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
var ex2;
completer.completeException(ex);
future.handleException((e) { ex2 = e; return true; });
future.then((e) { });
Expect.equals(ex, ex2);
}
testExceptionHandlerAfterCompleteReturnsFalseThenThrows() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
var ex2;
completer.completeException(ex);
future.handleException((e) { ex2 = e; return false; });
Expect.throws(() { future.then((e) { }); });
Expect.equals(ex, ex2);
}
// Tests for accessing the exception call stack.
testCallStackThrowsIfNotComplete() {
var exception;
try {
new Completer().future.stackTrace;
} catch (ex) {
exception = ex;
}
Expect.isTrue(exception is FutureNotCompleteException);
}
testCallStackIsNullIfCompletedSuccessfully() {
Expect.isNull(new Future.immediate('blah').stackTrace);
}
testCallStackReturnsCallstackPassedToCompleteException() {
final completer = new Completer();
final future = completer.future;
final stackTrace = 'fake stack trace';
completer.completeException(new Exception(), stackTrace);
Expect.equals(stackTrace, future.stackTrace);
}
testCallStackIsCapturedIfTransformCallbackThrows() {
final completer = new Completer();
final transformed = completer.future.transform((_) {
throw 'whoops!';
});
final stackTrace = 'fake stack trace';
completer.complete('blah');
Expect.isNotNull(transformed.stackTrace);
}
testCallStackIsCapturedIfChainCallbackThrows() {
final completer = new Completer();
final chained = completer.future.chain((_) {
throw 'whoops!';
});
final stackTrace = 'fake stack trace';
completer.complete('blah');
Expect.isNotNull(chained.stackTrace);
}
// Tests for mixed usage of [onComplete], [then], and [handleException]
testCompleteWithCompletionAndSuccessHandlers() {
final completer = new Completer<int>();
final future = completer.future;
var valueFromSuccessHandler;
var valueFromCompletionHandler;
future.onComplete((f) {
Expect.isNotNull(valueFromSuccessHandler);
valueFromCompletionHandler = f.value;
});
future.then((v) {
Expect.isNull(valueFromCompletionHandler);
valueFromSuccessHandler = v;
});
completer.complete(42);
Expect.equals(42, valueFromSuccessHandler);
Expect.equals(42, valueFromCompletionHandler);
Expect.equals(42, future.value);
}
testExceptionWithCompletionAndSuccessHandlers() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
var exceptionFromCompleteHandler;
future.onComplete((f) {
Expect.equals(future, f);
Expect.isFalse(f.hasValue);
exceptionFromCompleteHandler = f.exception;
});
future.then((v) => Expect.fail("Should not succeed"));
Expect.throws(() => completer.completeException(ex), (e) => e.source == ex);
Expect.equals(ex, exceptionFromCompleteHandler);
}
testExceptionWithCompletionAndSuccessAndExceptionHandlers() {
final completer = new Completer<int>();
final future = completer.future;
final ex = new Exception();
var exceptionFromCompleteHandler;
var exceptionFromExceptionHandler;
future.onComplete((f) {
Expect.equals(future, f);
Expect.isFalse(f.hasValue);
exceptionFromCompleteHandler = f.exception;
});
future.handleException((e) {
exceptionFromExceptionHandler = e;
return true;
});
future.then((v) => Expect.fail("Should not succeed"));
completer.completeException(ex);
Expect.equals(ex, exceptionFromCompleteHandler);
Expect.equals(ex, exceptionFromExceptionHandler);
}
// Tests for Future.transform
testTransformSuccess() {
final completer = new Completer<String>();
final transformedFuture = completer.future.transform((x) => "** $x **");
Expect.isFalse(transformedFuture.isComplete);
completer.complete("42");
Expect.equals("** 42 **", transformedFuture.value);
}
testTransformFutureFails() {
final completer = new Completer<String>();
final error = new Exception("Oh no!");
final transformedFuture = completer.future.transform((x) {
Expect.fail("transformer shouldn't be called");
});
Expect.isFalse(transformedFuture.isComplete);
completer.completeException(error);
Expect.equals(error, transformedFuture.exception);
}
testTransformTransformerFails() {
final completer = new Completer<String>();
final error = new Exception("Oh no!");
final transformedFuture = completer.future.transform((x) { throw error; });
Expect.isFalse(transformedFuture.isComplete);
transformedFuture.then((v) => null);
Expect.throws(() => completer.complete("42"), (e) => e.source == error);
Expect.equals(error, transformedFuture.exception);
}
// Tests for Future.chain
testChainSuccess() {
final completerA = new Completer<String>();
final completerB = new Completer<String>();
final chainedFuture = completerA.future.chain((x) {
Expect.equals("42", x);
return completerB.future;
});
Expect.isFalse(chainedFuture.isComplete);
completerA.complete("42");
Expect.isFalse(chainedFuture.isComplete);
completerB.complete("43");
Expect.equals("43", chainedFuture.value);
}
testChainFirstFutureFails() {
final completerA = new Completer<String>();
final error = new Exception("Oh no!");
final chainedFuture = completerA.future.chain((x) {
Expect.fail("transformer shouldn't be called");
});
Expect.isFalse(chainedFuture.isComplete);
completerA.completeException(error);
Expect.equals(error, chainedFuture.exception);
}
testChainTransformerFails() {
final completerA = new Completer<String>();
final error = new Exception("Oh no!");
final chainedFuture = completerA.future.chain((x) {
Expect.equals("42", x);
throw error;
});
chainedFuture.then((v) => null);
Expect.isFalse(chainedFuture.isComplete);
Expect.throws(() => completerA.complete("42"), (e) => e.source == error);
Expect.equals(error, chainedFuture.exception);
}
testChainSecondFutureFails() {
final completerA = new Completer<String>();
final completerB = new Completer<String>();
final error = new Exception("Oh no!");
final chainedFuture = completerA.future.chain((x) {
Expect.equals("42", x);
return completerB.future;
});
Expect.isFalse(chainedFuture.isComplete);
completerA.complete("42");
Expect.isFalse(chainedFuture.isComplete);
completerB.completeException(error);
Expect.equals(error, chainedFuture.exception);
}
// Tests for Future.transformException
testTransformExceptionCompletesNormally() {
final completer = new Completer<String>();
var called = false;
final transformedFuture = completer.future.transformException((ex) {
Expect.fail("should not get here");
});
completer.complete("value");
Expect.isTrue(transformedFuture.isComplete);
Expect.equals("value", transformedFuture.value);
}
testTransformExceptionThrows() {
final completer = new Completer<String>();
var called = false;
final transformedFuture = completer.future.transformException((ex) {
Expect.equals("original error", ex);
called = true;
throw "transformed error";
});
completer.completeException("original error");
Expect.isTrue(called);
Expect.isTrue(transformedFuture.isComplete);
Expect.equals("transformed error", transformedFuture.exception);
}
testTransformExceptionReturns() {
final completer = new Completer<String>();
var called = false;
final transformedFuture = completer.future.transformException((ex) {
Expect.equals("original error", ex);
called = true;
return "transformed value";
});
completer.completeException("original error");
Expect.isTrue(called);
Expect.isTrue(transformedFuture.isComplete);
Expect.equals("transformed value", transformedFuture.value);
}
testTransformExceptionReturnsAFuture() {
final completer = new Completer<String>();
var called = false;
final returnedCompleter = new Completer<String>();
final transformedFuture = completer.future.transformException((ex) {
Expect.equals("original error", ex);
called = true;
return returnedCompleter.future;
});
completer.completeException("original error");
Expect.isTrue(called);
Expect.isFalse(transformedFuture.isComplete);
returnedCompleter.complete("transformed value");
Expect.isTrue(transformedFuture.isComplete);
Expect.equals("transformed value", transformedFuture.value);
}
main() {
testImmediate();
testNeverComplete();
testComplete();
testCompleteWithCompleteHandlerBeforeComplete();
testExceptionWithCompleteHandlerBeforeComplete();
testCompleteWithCompleteHandlerAfterComplete();
testExceptionWithCompleteHandlerAfterComplete();
testCompleteWithManyCompleteHandlers();
testExceptionWithManyCompleteHandlers();
testCompleteWithSuccessHandlerBeforeComplete();
testCompleteWithSuccessHandlerAfterComplete();
testCompleteManySuccessHandlers();
testException();
testExceptionHandler();
testExceptionHandlerReturnsTrue();
testExceptionHandlerReturnsTrue2();
testExceptionHandlerReturnsFalse();
testExceptionHandlerReturnsFalse2();
testExceptionHandlerAfterCompleteThenNotCalled();
testExceptionHandlerAfterCompleteReturnsFalseThenThrows();
testCallStackThrowsIfNotComplete();
testCallStackIsNullIfCompletedSuccessfully();
testCallStackReturnsCallstackPassedToCompleteException();
testCallStackIsCapturedIfTransformCallbackThrows();
testCallStackIsCapturedIfChainCallbackThrows();
testCompleteWithCompletionAndSuccessHandlers();
testExceptionWithCompletionAndSuccessHandlers();
testExceptionWithCompletionAndSuccessAndExceptionHandlers();
testTransformSuccess();
testTransformFutureFails();
testTransformTransformerFails();
testChainSuccess();
testChainFirstFutureFails();
testChainTransformerFails();
testChainSecondFutureFails();
testTransformExceptionCompletesNormally();
testTransformExceptionThrows();
testTransformExceptionReturns();
testTransformExceptionReturnsAFuture();
}