OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library test.backend.declarer; | 5 library test.backend.declarer; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import '../frontend/timeout.dart'; | 9 import '../frontend/timeout.dart'; |
10 import '../utils.dart'; | 10 import '../utils.dart'; |
11 import 'group.dart'; | 11 import 'group.dart'; |
12 import 'invoker.dart'; | 12 import 'invoker.dart'; |
13 import 'metadata.dart'; | 13 import 'metadata.dart'; |
14 import 'suite_entry.dart'; | 14 import 'group_entry.dart'; |
15 | 15 |
16 /// A class that manages the state of tests as they're declared. | 16 /// A class that manages the state of tests as they're declared. |
17 /// | 17 /// |
18 /// A nested tree of Declarers tracks the current group, set-up, and tear-down | 18 /// A nested tree of Declarers tracks the current group, set-up, and tear-down |
19 /// functions. Each Declarer in the tree corresponds to a group. This tree is | 19 /// functions. Each Declarer in the tree corresponds to a group. This tree is |
20 /// tracked by a zone-scoped "current" Declarer; the current declarer can be set | 20 /// tracked by a zone-scoped "current" Declarer; the current declarer can be set |
21 /// for a block using [Declarer.declare], and it can be accessed using | 21 /// for a block using [Declarer.declare], and it can be accessed using |
22 /// [Declarer.current]. | 22 /// [Declarer.current]. |
23 class Declarer { | 23 class Declarer { |
24 /// The parent declarer, or `null` if this corresponds to the root group. | 24 /// The parent declarer, or `null` if this corresponds to the root group. |
25 final Declarer _parent; | 25 final Declarer _parent; |
26 | 26 |
27 /// The name of the current test group, including the name of any parent | 27 /// The name of the current test group, including the name of any parent |
28 /// groups. | 28 /// groups. |
29 /// | 29 /// |
30 /// This is `null` if this is the root group. | 30 /// This is `null` if this is the root group. |
31 final String _name; | 31 final String _name; |
32 | 32 |
33 /// The metadata for this group, including the metadata of any parent groups | 33 /// The metadata for this group, including the metadata of any parent groups |
34 /// and of the test suite. | 34 /// and of the test suite. |
35 final Metadata _metadata; | 35 final Metadata _metadata; |
36 | 36 |
37 /// The set-up functions for this group. | 37 /// The set-up functions for this group. |
38 final _setUps = new List<AsyncFunction>(); | 38 final _setUps = new List<AsyncFunction>(); |
39 | 39 |
40 /// The tear-down functions for this group. | 40 /// The tear-down functions for this group. |
41 final _tearDowns = new List<AsyncFunction>(); | 41 final _tearDowns = new List<AsyncFunction>(); |
42 | 42 |
43 /// The children of this group, either tests or sub-groups. | 43 /// The children of this group, either tests or sub-groups. |
44 final _entries = new List<SuiteEntry>(); | 44 final _entries = new List<GroupEntry>(); |
45 | 45 |
46 /// Whether [build] has been called for this declarer. | 46 /// Whether [build] has been called for this declarer. |
47 bool _built = false; | 47 bool _built = false; |
48 | 48 |
49 /// The current zone-scoped declarer. | 49 /// The current zone-scoped declarer. |
50 static Declarer get current => Zone.current[#test.declarer]; | 50 static Declarer get current => Zone.current[#test.declarer]; |
51 | 51 |
52 /// Creates a new declarer for the root group. | 52 /// Creates a new declarer for the root group. |
53 /// | 53 /// |
54 /// This is the implicit group that exists outside of any calls to `group()`. | 54 /// This is the implicit group that exists outside of any calls to `group()`. |
55 /// [metadata] should be the suite's metadata, if available. | 55 /// If [metadata] is passed, it's used as the metadata for the implicit root |
| 56 /// group. |
56 Declarer([Metadata metadata]) | 57 Declarer([Metadata metadata]) |
57 : this._(null, null, metadata == null ? new Metadata() : metadata); | 58 : this._(null, null, metadata == null ? new Metadata() : metadata); |
58 | 59 |
59 Declarer._(this._parent, this._name, this._metadata); | 60 Declarer._(this._parent, this._name, this._metadata); |
60 | 61 |
61 /// Runs [body] with this declarer as [Declarer.current]. | 62 /// Runs [body] with this declarer as [Declarer.current]. |
62 /// | 63 /// |
63 /// Returns the return value of [body]. | 64 /// Returns the return value of [body]. |
64 declare(body()) => runZoned(body, zoneValues: {#test.declarer: this}); | 65 declare(body()) => runZoned(body, zoneValues: {#test.declarer: this}); |
65 | 66 |
(...skipping 25 matching lines...) Expand all Loading... |
91 Map<String, dynamic> onPlatform}) { | 92 Map<String, dynamic> onPlatform}) { |
92 if (_built) { | 93 if (_built) { |
93 throw new StateError("Can't call group() once tests have begun running."); | 94 throw new StateError("Can't call group() once tests have begun running."); |
94 } | 95 } |
95 | 96 |
96 var metadata = _metadata.merge(new Metadata.parse( | 97 var metadata = _metadata.merge(new Metadata.parse( |
97 testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform)); | 98 testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform)); |
98 | 99 |
99 // Don't load the tests for a skipped group. | 100 // Don't load the tests for a skipped group. |
100 if (metadata.skip) { | 101 if (metadata.skip) { |
101 _entries.add(new Group(name, metadata, [])); | 102 _entries.add(new Group(name, [], metadata: metadata)); |
102 return; | 103 return; |
103 } | 104 } |
104 | 105 |
105 var declarer = new Declarer._(this, _prefix(name), metadata); | 106 var declarer = new Declarer._(this, _prefix(name), metadata); |
106 declarer.declare(body); | 107 declarer.declare(body); |
107 _entries.add(new Group(declarer._name, metadata, declarer.build())); | 108 _entries.add(declarer.build()); |
108 } | 109 } |
109 | 110 |
110 /// Returns [name] prefixed with this declarer's group name. | 111 /// Returns [name] prefixed with this declarer's group name. |
111 String _prefix(String name) => _name == null ? name : "$_name $name"; | 112 String _prefix(String name) => _name == null ? name : "$_name $name"; |
112 | 113 |
113 /// Registers a function to be run before each test in this group. | 114 /// Registers a function to be run before each test in this group. |
114 void setUp(callback()) { | 115 void setUp(callback()) { |
115 if (_built) { | 116 if (_built) { |
116 throw new StateError("Can't call setUp() once tests have begun running."); | 117 throw new StateError("Can't call setUp() once tests have begun running."); |
117 } | 118 } |
118 | 119 |
119 _setUps.add(callback); | 120 _setUps.add(callback); |
120 } | 121 } |
121 | 122 |
122 /// Registers a function to be run after each test in this group. | 123 /// Registers a function to be run after each test in this group. |
123 void tearDown(callback()) { | 124 void tearDown(callback()) { |
124 if (_built) { | 125 if (_built) { |
125 throw new StateError( | 126 throw new StateError( |
126 "Can't call tearDown() once tests have begun running."); | 127 "Can't call tearDown() once tests have begun running."); |
127 } | 128 } |
128 | 129 |
129 _tearDowns.add(callback); | 130 _tearDowns.add(callback); |
130 } | 131 } |
131 | 132 |
132 /// Finalizes and returns the tests and groups being declared. | 133 /// Finalizes and returns the group being declared. |
133 List<SuiteEntry> build() { | 134 Group build() { |
134 if (_built) { | 135 if (_built) { |
135 throw new StateError("Can't call Declarer.build() more than once."); | 136 throw new StateError("Can't call Declarer.build() more than once."); |
136 } | 137 } |
137 | 138 |
138 _built = true; | 139 _built = true; |
139 return _entries.toList(); | 140 return new Group(_name, _entries.toList(), metadata: _metadata); |
140 } | 141 } |
141 | 142 |
142 /// Run the set-up functions for this and any parent groups. | 143 /// Run the set-up functions for this and any parent groups. |
143 /// | 144 /// |
144 /// If no set-up functions are declared, this returns a [Future] that | 145 /// If no set-up functions are declared, this returns a [Future] that |
145 /// completes immediately. | 146 /// completes immediately. |
146 Future _runSetUps() { | 147 Future _runSetUps() { |
147 // TODO(nweiz): Use async/await here once issue 23497 has been fixed in two | 148 // TODO(nweiz): Use async/await here once issue 23497 has been fixed in two |
148 // stable versions. | 149 // stable versions. |
149 if (_parent != null) { | 150 if (_parent != null) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 var completer = new Completer(); | 182 var completer = new Completer(); |
182 | 183 |
183 Invoker.current.addOutstandingCallback(); | 184 Invoker.current.addOutstandingCallback(); |
184 Invoker.current.waitForOutstandingCallbacks(() { | 185 Invoker.current.waitForOutstandingCallbacks(() { |
185 new Future.sync(body).whenComplete(completer.complete); | 186 new Future.sync(body).whenComplete(completer.complete); |
186 }).then((_) => Invoker.current.removeOutstandingCallback()); | 187 }).then((_) => Invoker.current.removeOutstandingCallback()); |
187 | 188 |
188 return completer.future; | 189 return completer.future; |
189 } | 190 } |
190 } | 191 } |
OLD | NEW |