Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Unified Diff: packages/pool/test/pool_test.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « packages/pool/pubspec.yaml ('k') | packages/quiver/.gitattributes » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/pool/test/pool_test.dart
diff --git a/packages/pool/test/pool_test.dart b/packages/pool/test/pool_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..65fd00ee25f0ed9a498681d61077198f2d67283f
--- /dev/null
+++ b/packages/pool/test/pool_test.dart
@@ -0,0 +1,428 @@
+// Copyright (c) 2014, 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.
+
+import 'dart:async';
+
+import 'package:fake_async/fake_async.dart';
+import 'package:pool/pool.dart';
+import 'package:stack_trace/stack_trace.dart';
+import 'package:test/test.dart';
+
+void main() {
+ group("request()", () {
+ test("resources can be requested freely up to the limit", () {
+ var pool = new Pool(50);
+ for (var i = 0; i < 50; i++) {
+ expect(pool.request(), completes);
+ }
+ });
+
+ test("resources block past the limit", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50);
+ for (var i = 0; i < 50; i++) {
+ expect(pool.request(), completes);
+ }
+ expect(pool.request(), doesNotComplete);
+
+ async.elapse(new Duration(seconds: 1));
+ });
+ });
+
+ test("a blocked resource is allocated when another is released", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50);
+ for (var i = 0; i < 49; i++) {
+ expect(pool.request(), completes);
+ }
+
+ pool.request().then((lastAllocatedResource) {
+ // This will only complete once [lastAllocatedResource] is released.
+ expect(pool.request(), completes);
+
+ new Future.delayed(new Duration(microseconds: 1)).then((_) {
+ lastAllocatedResource.release();
+ });
+ });
+
+ async.elapse(new Duration(seconds: 1));
+ });
+ });
+ });
+
+ group("withResource()", () {
+ test("can be called freely up to the limit", () {
+ var pool = new Pool(50);
+ for (var i = 0; i < 50; i++) {
+ pool.withResource(expectAsync(() => new Completer().future));
+ }
+ });
+
+ test("blocks the callback past the limit", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50);
+ for (var i = 0; i < 50; i++) {
+ pool.withResource(expectAsync(() => new Completer().future));
+ }
+ pool.withResource(expectNoAsync());
+
+ async.elapse(new Duration(seconds: 1));
+ });
+ });
+
+ test("a blocked resource is allocated when another is released", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50);
+ for (var i = 0; i < 49; i++) {
+ pool.withResource(expectAsync(() => new Completer().future));
+ }
+
+ var completer = new Completer();
+ pool.withResource(() => completer.future);
+ var blockedResourceAllocated = false;
+ pool.withResource(() {
+ blockedResourceAllocated = true;
+ });
+
+ new Future.delayed(new Duration(microseconds: 1)).then((_) {
+ expect(blockedResourceAllocated, isFalse);
+ completer.complete();
+ return new Future.delayed(new Duration(microseconds: 1));
+ }).then((_) {
+ expect(blockedResourceAllocated, isTrue);
+ });
+
+ async.elapse(new Duration(seconds: 1));
+ });
+ });
+ });
+
+ group("with a timeout", () {
+ test("doesn't time out if there are no pending requests", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50, timeout: new Duration(seconds: 5));
+ for (var i = 0; i < 50; i++) {
+ expect(pool.request(), completes);
+ }
+
+ async.elapse(new Duration(seconds: 6));
+ });
+ });
+
+ test("resets the timer if a resource is returned", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50, timeout: new Duration(seconds: 5));
+ for (var i = 0; i < 49; i++) {
+ expect(pool.request(), completes);
+ }
+
+ pool.request().then((lastAllocatedResource) {
+ // This will only complete once [lastAllocatedResource] is released.
+ expect(pool.request(), completes);
+
+ new Future.delayed(new Duration(seconds: 3)).then((_) {
+ lastAllocatedResource.release();
+ expect(pool.request(), doesNotComplete);
+ });
+ });
+
+ async.elapse(new Duration(seconds: 6));
+ });
+ });
+
+ test("resets the timer if a resource is requested", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50, timeout: new Duration(seconds: 5));
+ for (var i = 0; i < 50; i++) {
+ expect(pool.request(), completes);
+ }
+ expect(pool.request(), doesNotComplete);
+
+ new Future.delayed(new Duration(seconds: 3)).then((_) {
+ expect(pool.request(), doesNotComplete);
+ });
+
+ async.elapse(new Duration(seconds: 6));
+ });
+ });
+
+ test("times out if nothing happens", () {
+ new FakeAsync().run((async) {
+ var pool = new Pool(50, timeout: new Duration(seconds: 5));
+ for (var i = 0; i < 50; i++) {
+ expect(pool.request(), completes);
+ }
+ expect(pool.request(), throwsA(new isInstanceOf<TimeoutException>()));
+
+ async.elapse(new Duration(seconds: 6));
+ });
+ });
+ });
+
+ group("allowRelease()", () {
+ test("runs the callback once the resource limit is exceeded", () async {
+ var pool = new Pool(50);
+ for (var i = 0; i < 49; i++) {
+ expect(pool.request(), completes);
+ }
+
+ var resource = await pool.request();
+ var onReleaseCalled = false;
+ resource.allowRelease(() => onReleaseCalled = true);
+ await new Future.delayed(Duration.ZERO);
+ expect(onReleaseCalled, isFalse);
+
+ expect(pool.request(), completes);
+ await new Future.delayed(Duration.ZERO);
+ expect(onReleaseCalled, isTrue);
+ });
+
+ test("runs the callback immediately if there are blocked requests",
+ () async {
+ var pool = new Pool(1);
+ var resource = await pool.request();
+
+ // This will be blocked until [resource.allowRelease] is called.
+ expect(pool.request(), completes);
+
+ var onReleaseCalled = false;
+ resource.allowRelease(() => onReleaseCalled = true);
+ await new Future.delayed(Duration.ZERO);
+ expect(onReleaseCalled, isTrue);
+ });
+
+ test("blocks the request until the callback completes", () async {
+ var pool = new Pool(1);
+ var resource = await pool.request();
+
+ var requestComplete = false;
+ pool.request().then((_) => requestComplete = true);
+
+ var completer = new Completer();
+ resource.allowRelease(() => completer.future);
+ await new Future.delayed(Duration.ZERO);
+ expect(requestComplete, isFalse);
+
+ completer.complete();
+ await new Future.delayed(Duration.ZERO);
+ expect(requestComplete, isTrue);
+ });
+
+ test("completes requests in request order regardless of callback order",
+ () async {
+ var pool = new Pool(2);
+ var resource1 = await pool.request();
+ var resource2 = await pool.request();
+
+ var request1Complete = false;
+ pool.request().then((_) => request1Complete = true);
+ var request2Complete = false;
+ pool.request().then((_) => request2Complete = true);
+
+ var onRelease1Called = false;
+ var completer1 = new Completer();
+ resource1.allowRelease(() {
+ onRelease1Called = true;
+ return completer1.future;
+ });
+ await new Future.delayed(Duration.ZERO);
+ expect(onRelease1Called, isTrue);
+
+ var onRelease2Called = false;
+ var completer2 = new Completer();
+ resource2.allowRelease(() {
+ onRelease2Called = true;
+ return completer2.future;
+ });
+ await new Future.delayed(Duration.ZERO);
+ expect(onRelease2Called, isTrue);
+ expect(request1Complete, isFalse);
+ expect(request2Complete, isFalse);
+
+ // Complete the second resource's onRelease callback first. Even though it
+ // was triggered by the second blocking request, it should complete the
+ // first one to preserve ordering.
+ completer2.complete();
+ await new Future.delayed(Duration.ZERO);
+ expect(request1Complete, isTrue);
+ expect(request2Complete, isFalse);
+
+ completer1.complete();
+ await new Future.delayed(Duration.ZERO);
+ expect(request1Complete, isTrue);
+ expect(request2Complete, isTrue);
+ });
+
+ test("runs onRequest in the zone it was created", () async {
+ var pool = new Pool(1);
+ var resource = await pool.request();
+
+ var outerZone = Zone.current;
+ runZoned(() {
+ var innerZone = Zone.current;
+ expect(innerZone, isNot(equals(outerZone)));
+
+ resource.allowRelease(expectAsync(() {
+ expect(Zone.current, equals(innerZone));
+ }));
+ });
+
+ pool.request();
+ });
+ });
+
+ group("close()", () {
+ test("disallows request() and withResource()", () {
+ var pool = new Pool(1)..close();
+ expect(pool.request, throwsStateError);
+ expect(() => pool.withResource(() {}), throwsStateError);
+ });
+
+ test("pending requests are fulfilled", () async {
+ var pool = new Pool(1);
+ var resource1 = await pool.request();
+ expect(pool.request().then((resource2) {
+ resource2.release();
+ }), completes);
+ expect(pool.close(), completes);
+ resource1.release();
+ });
+
+ test("pending requests are fulfilled with allowRelease", () async {
+ var pool = new Pool(1);
+ var resource1 = await pool.request();
+
+ var completer = new Completer();
+ expect(pool.request().then((resource2) {
+ expect(completer.isCompleted, isTrue);
+ resource2.release();
+ }), completes);
+ expect(pool.close(), completes);
+
+ resource1.allowRelease(() => completer.future);
+ await new Future.delayed(Duration.ZERO);
+
+ completer.complete();
+ });
+
+ test("doesn't complete until all resources are released", () async {
+ var pool = new Pool(2);
+ var resource1 = await pool.request();
+ var resource2 = await pool.request();
+ var resource3Future = pool.request();
+
+ var resource1Released = false;
+ var resource2Released = false;
+ var resource3Released = false;
+ expect(pool.close().then((_) {
+ expect(resource1Released, isTrue);
+ expect(resource2Released, isTrue);
+ expect(resource3Released, isTrue);
+ }), completes);
+
+ resource1Released = true;
+ resource1.release();
+ await new Future.delayed(Duration.ZERO);
+
+ resource2Released = true;
+ resource2.release();
+ await new Future.delayed(Duration.ZERO);
+
+ var resource3 = await resource3Future;
+ resource3Released = true;
+ resource3.release();
+ });
+
+ test("active onReleases complete as usual", () async {
+ var pool = new Pool(1);
+ var resource = await pool.request();
+
+ // Set up an onRelease callback whose completion is controlled by
+ // [completer].
+ var completer = new Completer();
+ resource.allowRelease(() => completer.future);
+ expect(pool.request().then((_) {
+ expect(completer.isCompleted, isTrue);
+ }), completes);
+
+ await new Future.delayed(Duration.ZERO);
+ pool.close();
+
+ await new Future.delayed(Duration.ZERO);
+ completer.complete();
+ });
+
+ test("inactive onReleases fire", () async {
+ var pool = new Pool(2);
+ var resource1 = await pool.request();
+ var resource2 = await pool.request();
+
+ var completer1 = new Completer();
+ resource1.allowRelease(() => completer1.future);
+ var completer2 = new Completer();
+ resource2.allowRelease(() => completer2.future);
+
+ expect(pool.close().then((_) {
+ expect(completer1.isCompleted, isTrue);
+ expect(completer2.isCompleted, isTrue);
+ }), completes);
+
+ await new Future.delayed(Duration.ZERO);
+ completer1.complete();
+
+ await new Future.delayed(Duration.ZERO);
+ completer2.complete();
+ });
+
+ test("new allowReleases fire immediately", () async {
+ var pool = new Pool(1);
+ var resource = await pool.request();
+
+ var completer = new Completer();
+ expect(pool.close().then((_) {
+ expect(completer.isCompleted, isTrue);
+ }), completes);
+
+ await new Future.delayed(Duration.ZERO);
+ resource.allowRelease(() => completer.future);
+
+ await new Future.delayed(Duration.ZERO);
+ completer.complete();
+ });
+
+ test("an onRelease error is piped to the return value", () async {
+ var pool = new Pool(1);
+ var resource = await pool.request();
+
+ var completer = new Completer();
+ resource.allowRelease(() => completer.future);
+
+ expect(pool.close(), throwsA("oh no!"));
+
+ await new Future.delayed(Duration.ZERO);
+ completer.completeError("oh no!");
+ });
+ });
+}
+
+/// Returns a function that will cause the test to fail if it's called.
+///
+/// This should only be called within a [FakeAsync.run] zone.
+Function expectNoAsync() {
+ var stack = new Trace.current(1);
+ return () => registerException(
+ new TestFailure("Expected function not to be called."), stack);
+}
+
+/// A matcher for Futures that asserts that they don't complete.
+///
+/// This should only be called within a [FakeAsync.run] zone.
+Matcher get doesNotComplete => predicate((future) {
+ expect(future, new isInstanceOf<Future>());
+
+ var stack = new Trace.current(1);
+ future.then((_) => registerException(
+ new TestFailure("Expected future not to complete."), stack));
+ return true;
+});
« no previous file with comments | « packages/pool/pubspec.yaml ('k') | packages/quiver/.gitattributes » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698