Merge pull request #101 from DrMarcII/master
Add awaitChecking mode to Lock class.
diff --git a/lib/support/async.dart b/lib/support/async.dart
index 137df94..d8f2314 100644
--- a/lib/support/async.dart
+++ b/lib/support/async.dart
@@ -17,6 +17,7 @@
import 'dart:async' show Completer, Future;
import 'package:matcher/matcher.dart' as m;
+import 'package:stack_trace/stack_trace.dart' show Chain;
import 'package:unittest/unittest.dart' as ut;
const defaultInterval = const Duration(milliseconds: 500);
@@ -103,12 +104,30 @@
class Lock {
Completer _lock;
+ Chain _stack;
- Future acquire() async {
- while (isHeld) {
- await _lock.future;
+ final bool awaitChecking;
+
+ Lock({this.awaitChecking: false});
+
+ Future acquire() {
+ if (awaitChecking) {
+ if (isHeld) {
+ return new Future.error(new StateError(
+ 'Maybe you missed an await? Lock is already held by:\n$_stack'));
+ } else {
+ _stack = new Chain.current().terse;
+ _lock = new Completer();
+ return new Future.value();
+ }
+ } else {
+ return () async {
+ while (isHeld) {
+ await _lock.future;
+ }
+ _lock = new Completer();
+ }();
}
- _lock = new Completer();
}
void release() {
@@ -117,6 +136,7 @@
}
_lock.complete();
_lock = null;
+ _stack = null;
}
bool get isHeld => _lock != null;
diff --git a/test/src/command_event.dart b/test/src/command_event.dart
index 0baa524..aea573f 100644
--- a/test/src/command_event.dart
+++ b/test/src/command_event.dart
@@ -22,54 +22,49 @@
import '../test_util.dart';
void runTests() {
- group(
- 'CommandEvent',
- () {
- WebDriver driver;
+ group('CommandEvent', () {
+ WebDriver driver;
- var events = [];
- var sub;
+ var events = [];
+ var sub;
- setUp(() async {
- driver = await createTestDriver();
- sub = driver.onCommand.listen(events.add);
+ setUp(() async {
+ driver = await createTestDriver();
+ sub = driver.onCommand.listen(events.add);
- await driver.get(testPagePath);
- });
+ await driver.get(testPagePath);
+ });
- tearDown(() async {
- sub.cancel();
- sub = null;
- events.clear();
- await driver.quit();
- driver = null;
- });
+ tearDown(() async {
+ sub.cancel();
+ sub = null;
+ events.clear();
+ await driver.quit();
+ driver = null;
+ });
- test('handles exceptions', () async {
- try {
- await driver.switchTo.alert;
- } catch (e) {}
- await waitFor(() => events, matcher: hasLength(2));
- expect(events[1].method, 'GET');
- expect(events[1].endPoint, contains('alert'));
- expect(events[1].exception, new isInstanceOf<WebDriverException>());
- expect(events[1].result, isNull);
- expect(events[1].startTime.isBefore(events[1].endTime), isTrue);
- expect(events[1].stackTrace, new isInstanceOf<Chain>());
- });
+ test('handles exceptions', () async {
+ try {
+ await driver.switchTo.alert;
+ } catch (e) {}
+ await waitFor(() => events, matcher: hasLength(2));
+ expect(events[1].method, 'GET');
+ expect(events[1].endPoint, contains('alert'));
+ expect(events[1].exception, new isInstanceOf<WebDriverException>());
+ expect(events[1].result, isNull);
+ expect(events[1].startTime.isBefore(events[1].endTime), isTrue);
+ expect(events[1].stackTrace, new isInstanceOf<Chain>());
+ });
- test('handles normal operation', () async {
- await driver
- .findElements(const By.cssSelector('nosuchelement'))
- .toList();
- await waitFor(() => events, matcher: hasLength(2));
- expect(events[1].method, 'POST');
- expect(events[1].endPoint, contains('elements'));
- expect(events[1].exception, isNull);
- expect(events[1].result, hasLength(0));
- expect(events[1].startTime.isBefore(events[1].endTime), isTrue);
- expect(events[1].stackTrace, new isInstanceOf<Chain>());
- });
- },
- testOn: '!js');
+ test('handles normal operation', () async {
+ await driver.findElements(const By.cssSelector('nosuchelement')).toList();
+ await waitFor(() => events, matcher: hasLength(2));
+ expect(events[1].method, 'POST');
+ expect(events[1].endPoint, contains('elements'));
+ expect(events[1].exception, isNull);
+ expect(events[1].result, hasLength(0));
+ expect(events[1].startTime.isBefore(events[1].endTime), isTrue);
+ expect(events[1].stackTrace, new isInstanceOf<Chain>());
+ });
+ }, testOn: '!js');
}
diff --git a/test/src/navigation.dart b/test/src/navigation.dart
index c86bad6..5739c68 100644
--- a/test/src/navigation.dart
+++ b/test/src/navigation.dart
@@ -31,16 +31,13 @@
tearDown(() => driver.quit());
- test(
- 'forward/back',
- () async {
- await driver.get('http://www.yahoo.com');
- await driver.navigate.back();
- await waitFor(() => driver.title, matcher: contains('Google'));
- await driver.navigate.forward();
- await waitFor(() => driver.title, matcher: contains('Yahoo'));
- },
- skip: 'TODO(DrMarcII): fix test');
+ test('forward/back', () async {
+ await driver.get('http://www.yahoo.com');
+ await driver.navigate.back();
+ await waitFor(() => driver.title, matcher: contains('Google'));
+ await driver.navigate.forward();
+ await waitFor(() => driver.title, matcher: contains('Yahoo'));
+ }, skip: 'TODO(DrMarcII): fix test');
test('refresh', () async {
var element = await driver.findElement(const By.name('q'));
diff --git a/test/src/web_driver.dart b/test/src/web_driver.dart
index 57870f8..1c2f0d5 100644
--- a/test/src/web_driver.dart
+++ b/test/src/web_driver.dart
@@ -38,17 +38,14 @@
await driver.quit();
});
- test(
- 'firefox',
- () async {
- WebDriver driver = await createTestDriver(
- additionalCapabilities: Capabilities.firefox);
- await driver.get('http://www.google.com');
- var element = await driver.findElement(const By.name('q'));
- expect(await element.name, 'input');
- await driver.quit();
- },
- skip: runningOnTravis);
+ test('firefox', () async {
+ WebDriver driver = await createTestDriver(
+ additionalCapabilities: Capabilities.firefox);
+ await driver.get('http://www.google.com');
+ var element = await driver.findElement(const By.name('q'));
+ expect(await element.name, 'input');
+ await driver.quit();
+ }, skip: runningOnTravis);
});
group('methods', () {
diff --git a/test/src/window.dart b/test/src/window.dart
index 2e547bc..0b60fe0 100644
--- a/test/src/window.dart
+++ b/test/src/window.dart
@@ -32,47 +32,38 @@
tearDown(() => driver.quit());
- test(
- 'size',
- () async {
- var window = await driver.window;
- var size = const Rectangle<int>(0, 0, 600, 400);
- await window.setSize(size);
- expect(await window.size, size);
- },
- skip: true);
+ test('size', () async {
+ var window = await driver.window;
+ var size = const Rectangle<int>(0, 0, 600, 400);
+ await window.setSize(size);
+ expect(await window.size, size);
+ }, skip: true);
- test(
- 'location',
- () async {
- var window = await driver.window;
- var position = const Point<int>(100, 200);
- await window.setLocation(position);
- expect(await window.location, position);
- },
- skip: true);
+ test('location', () async {
+ var window = await driver.window;
+ var position = const Point<int>(100, 200);
+ await window.setLocation(position);
+ expect(await window.location, position);
+ }, skip: true);
// May not work on some OS/browser combinations (notably Mac OS X).
- test(
- 'maximize',
- () async {
- var window = await driver.window;
- await window.setSize(const Rectangle<int>(0, 0, 300, 200));
- await window.setLocation(const Point<int>(100, 200));
- await window.maximize();
+ test('maximize', () async {
+ var window = await driver.window;
+ await window.setSize(const Rectangle<int>(0, 0, 300, 200));
+ await window.setLocation(const Point<int>(100, 200));
+ await window.maximize();
- // maximizing can take some time
- await waitFor(() async => (await window.size).height,
- matcher: greaterThan(200));
+ // maximizing can take some time
+ await waitFor(() async => (await window.size).height,
+ matcher: greaterThan(200));
- var location = await window.location;
- var size = await window.size;
- // Changed from `lessThan(100)` to pass the test on Mac.
- expect(location.x, lessThanOrEqualTo(100));
- expect(location.y, lessThan(200));
- expect(size.height, greaterThan(200));
- expect(size.width, greaterThan(300));
- },
- skip: true);
+ var location = await window.location;
+ var size = await window.size;
+ // Changed from `lessThan(100)` to pass the test on Mac.
+ expect(location.x, lessThanOrEqualTo(100));
+ expect(location.y, lessThan(200));
+ expect(size.height, greaterThan(200));
+ expect(size.width, greaterThan(300));
+ }, skip: true);
});
}
diff --git a/test/support/async_test.dart b/test/support/async_test.dart
index b38e990..d185fd6 100644
--- a/test/support/async_test.dart
+++ b/test/support/async_test.dart
@@ -52,6 +52,15 @@
await new Future.delayed(const Duration(seconds: 1));
expect(secondLockAcquired, isTrue);
});
+
+ test('awaitChecking throws exception on acquire of held lock', () async {
+ var lock = new Lock(awaitChecking: true);
+ await lock.acquire();
+ expect(lock.acquire(), throws);
+ lock.release();
+ await lock.acquire();
+ lock.release();
+ });
});
group('Clock.waitFor', () {