OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 library test.cancelable_future; |
| 6 |
| 7 import 'dart:async'; |
| 8 |
| 9 import 'package:analyzer/src/cancelable_future.dart'; |
| 10 import 'package:unittest/unittest.dart'; |
| 11 import 'package:watcher/src/utils.dart'; |
| 12 |
| 13 import 'reflective_tests.dart'; |
| 14 import 'utils.dart'; |
| 15 |
| 16 void main() { |
| 17 initializeTestEnvironment(); |
| 18 runReflectiveTests(CancelableCompleterTests); |
| 19 runReflectiveTests(CancelableFutureTests); |
| 20 } |
| 21 |
| 22 @reflectiveTest |
| 23 class CancelableCompleterTests { |
| 24 CancelableCompleter<Object> completer; |
| 25 int cancelCount = 0; |
| 26 |
| 27 void setUp() { |
| 28 completer = new CancelableCompleter<Object>(() { |
| 29 cancelCount++; |
| 30 }); |
| 31 } |
| 32 |
| 33 Future test_cancel_after_cancel() { |
| 34 // It is permissible to cancel multiple times, but only the first |
| 35 // cancellation has any effect. |
| 36 expect(cancelCount, 0); |
| 37 completer.future.cancel(); |
| 38 expect(cancelCount, 1); |
| 39 completer.future.cancel(); |
| 40 expect(cancelCount, 1); |
| 41 // Make sure the future still completes with error. |
| 42 return completer.future.then((_) { |
| 43 fail('Expected error completion'); |
| 44 }, onError: (error) { |
| 45 expect(error, new isInstanceOf<FutureCanceledError>()); |
| 46 // And make sure nothing else happens. |
| 47 }).then((_) => pumpEventQueue()).then((_) { |
| 48 expect(completer.isCompleted, isFalse); |
| 49 expect(cancelCount, 1); |
| 50 }); |
| 51 } |
| 52 |
| 53 Future test_cancel_after_chaining() { |
| 54 bool callbackInvoked = false; |
| 55 completer.future.then((_) { |
| 56 fail('Expected error completion'); |
| 57 }, onError: (error) { |
| 58 expect(callbackInvoked, isFalse); |
| 59 expect(error, new isInstanceOf<FutureCanceledError>()); |
| 60 callbackInvoked = true; |
| 61 }); |
| 62 expect(cancelCount, 0); |
| 63 completer.future.cancel(); |
| 64 // The cancel callback should have been invoked immediately. |
| 65 expect(cancelCount, 1); |
| 66 // But the completer should remain in the "not completed" state. |
| 67 expect(completer.isCompleted, isFalse); |
| 68 // The callback should be deferred to a microtask. |
| 69 expect(callbackInvoked, isFalse); |
| 70 return pumpEventQueue().then((_) { |
| 71 expect(callbackInvoked, isTrue); |
| 72 expect(completer.isCompleted, isFalse); |
| 73 expect(cancelCount, 1); |
| 74 }); |
| 75 } |
| 76 |
| 77 Future test_cancel_after_complete() { |
| 78 Object obj = new Object(); |
| 79 completer.complete(obj); |
| 80 completer.future.cancel(); |
| 81 // The cancel callback should not have been invoked, because it was too |
| 82 // late to cancel. |
| 83 expect(cancelCount, 0); |
| 84 // Make sure the future still completes with the object. |
| 85 return completer.future.then((result) { |
| 86 expect(result, same(obj)); |
| 87 // And make sure nothing else happens. |
| 88 }).then((_) => pumpEventQueue()).then((_) { |
| 89 expect(completer.isCompleted, isTrue); |
| 90 expect(cancelCount, 0); |
| 91 }); |
| 92 } |
| 93 |
| 94 Future test_cancel_before_chaining() { |
| 95 completer.future.cancel(); |
| 96 // The cancel callback should have been invoked immediately. |
| 97 expect(cancelCount, 1); |
| 98 // But the completer should remain in the "not completed" state. |
| 99 expect(completer.isCompleted, isFalse); |
| 100 bool callbackInvoked = false; |
| 101 completer.future.then((_) { |
| 102 fail('Expected error completion'); |
| 103 }, onError: (error) { |
| 104 expect(callbackInvoked, isFalse); |
| 105 expect(error, new isInstanceOf<FutureCanceledError>()); |
| 106 callbackInvoked = true; |
| 107 }); |
| 108 // The callback should be deferred to a microtask. |
| 109 expect(callbackInvoked, isFalse); |
| 110 expect(completer.isCompleted, isFalse); |
| 111 return pumpEventQueue().then((_) { |
| 112 expect(callbackInvoked, isTrue); |
| 113 expect(completer.isCompleted, isFalse); |
| 114 expect(cancelCount, 1); |
| 115 }); |
| 116 } |
| 117 |
| 118 Future test_complete_after_cancel() { |
| 119 completer.future.cancel(); |
| 120 // The cancel callback should have been invoked immediately. |
| 121 expect(cancelCount, 1); |
| 122 // Completing should have no effect other than to set the isCompleted |
| 123 // flag. |
| 124 expect(completer.isCompleted, isFalse); |
| 125 Object obj = new Object(); |
| 126 completer.complete(obj); |
| 127 expect(completer.isCompleted, isTrue); |
| 128 // Make sure the future still completer with error. |
| 129 return completer.future.then((_) { |
| 130 fail('Expected error completion'); |
| 131 }, onError: (error) { |
| 132 expect(error, new isInstanceOf<FutureCanceledError>()); |
| 133 // And make sure nothing else happens. |
| 134 }).then((_) => pumpEventQueue()).then((_) { |
| 135 expect(completer.isCompleted, isTrue); |
| 136 expect(cancelCount, 1); |
| 137 }); |
| 138 } |
| 139 |
| 140 Future test_complete_after_chaining() { |
| 141 Object obj = new Object(); |
| 142 bool callbackInvoked = false; |
| 143 completer.future.then((result) { |
| 144 expect(callbackInvoked, isFalse); |
| 145 expect(result, same(obj)); |
| 146 callbackInvoked = true; |
| 147 }, onError: (error) { |
| 148 fail('Expected successful completion'); |
| 149 }); |
| 150 expect(completer.isCompleted, isFalse); |
| 151 // Running the event loop should have no effect since the completer hasn't |
| 152 // been completed yet. |
| 153 return pumpEventQueue().then((_) { |
| 154 completer.complete(obj); |
| 155 expect(completer.isCompleted, isTrue); |
| 156 // The callback should be deferred to a microtask. |
| 157 expect(callbackInvoked, isFalse); |
| 158 }).then((_) => pumpEventQueue()).then((_) { |
| 159 expect(callbackInvoked, isTrue); |
| 160 expect(completer.isCompleted, isTrue); |
| 161 expect(cancelCount, 0); |
| 162 }); |
| 163 } |
| 164 |
| 165 void test_complete_after_complete() { |
| 166 // As with an ordinary Completer, calling complete() (or completeError) |
| 167 // after calling complete() should throw an exception. |
| 168 completer.complete(); |
| 169 expect(() { |
| 170 completer.complete(); |
| 171 }, throws); |
| 172 expect(() { |
| 173 completer.completeError(new Object()); |
| 174 }, throws); |
| 175 } |
| 176 |
| 177 void test_complete_after_completeError() { |
| 178 // As with an ordinary Completer, calling complete() (or completeError) |
| 179 // after calling completeError() should throw an exception. |
| 180 completer.completeError(new Object()); |
| 181 expect(() { |
| 182 completer.complete(); |
| 183 }, throws); |
| 184 expect(() { |
| 185 completer.completeError(new Object()); |
| 186 }, throws); |
| 187 // Now absorb the error that's in the completer's future. |
| 188 completer.future.catchError((_) => null); |
| 189 } |
| 190 |
| 191 Future test_complete_before_chaining() { |
| 192 Object obj = new Object(); |
| 193 completer.complete(obj); |
| 194 expect(completer.isCompleted, isTrue); |
| 195 bool callbackInvoked = false; |
| 196 completer.future.then((result) { |
| 197 expect(callbackInvoked, isFalse); |
| 198 expect(result, same(obj)); |
| 199 callbackInvoked = true; |
| 200 }, onError: (error) { |
| 201 fail('Expected successful completion'); |
| 202 }); |
| 203 // The callback should be deferred to a microtask. |
| 204 expect(callbackInvoked, isFalse); |
| 205 expect(completer.isCompleted, isTrue); |
| 206 return pumpEventQueue().then((_) { |
| 207 expect(callbackInvoked, isTrue); |
| 208 expect(completer.isCompleted, isTrue); |
| 209 expect(cancelCount, 0); |
| 210 }); |
| 211 } |
| 212 |
| 213 Future test_completeError_after_cancel() { |
| 214 completer.future.cancel(); |
| 215 // The cancel callback should have been invoked immediately. |
| 216 expect(cancelCount, 1); |
| 217 // Completing should have no effect other than to set the isCompleted |
| 218 // flag. |
| 219 expect(completer.isCompleted, isFalse); |
| 220 Object obj = new Object(); |
| 221 completer.completeError(obj); |
| 222 expect(completer.isCompleted, isTrue); |
| 223 // Make sure the future still completes with error. |
| 224 return completer.future.then((_) { |
| 225 fail('Expected error completion'); |
| 226 }, onError: (error) { |
| 227 expect(error, new isInstanceOf<FutureCanceledError>()); |
| 228 // And make sure nothing else happens. |
| 229 }).then((_) => pumpEventQueue()).then((_) { |
| 230 expect(completer.isCompleted, isTrue); |
| 231 expect(cancelCount, 1); |
| 232 }); |
| 233 } |
| 234 |
| 235 Future test_completeError_after_chaining() { |
| 236 Object obj = new Object(); |
| 237 bool callbackInvoked = false; |
| 238 completer.future.then((_) { |
| 239 fail('Expected error completion'); |
| 240 }, onError: (error) { |
| 241 expect(callbackInvoked, isFalse); |
| 242 expect(error, same(obj)); |
| 243 callbackInvoked = true; |
| 244 }); |
| 245 expect(completer.isCompleted, isFalse); |
| 246 // Running the event loop should have no effect since the completer hasn't |
| 247 // been completed yet. |
| 248 return pumpEventQueue().then((_) { |
| 249 completer.completeError(obj); |
| 250 expect(completer.isCompleted, isTrue); |
| 251 // The callback should be deferred to a microtask. |
| 252 expect(callbackInvoked, isFalse); |
| 253 }).then((_) => pumpEventQueue()).then((_) { |
| 254 expect(callbackInvoked, isTrue); |
| 255 expect(completer.isCompleted, isTrue); |
| 256 expect(cancelCount, 0); |
| 257 }); |
| 258 } |
| 259 |
| 260 Future test_completeError_before_chaining() { |
| 261 Object obj = new Object(); |
| 262 completer.completeError(obj); |
| 263 expect(completer.isCompleted, isTrue); |
| 264 bool callbackInvoked = false; |
| 265 completer.future.then((_) { |
| 266 fail('Expected error completion'); |
| 267 }, onError: (error) { |
| 268 expect(callbackInvoked, isFalse); |
| 269 expect(error, same(obj)); |
| 270 callbackInvoked = true; |
| 271 }); |
| 272 // The callback should be deferred to a microtask. |
| 273 expect(callbackInvoked, isFalse); |
| 274 expect(completer.isCompleted, isTrue); |
| 275 return pumpEventQueue().then((_) { |
| 276 expect(callbackInvoked, isTrue); |
| 277 expect(completer.isCompleted, isTrue); |
| 278 expect(cancelCount, 0); |
| 279 }); |
| 280 } |
| 281 |
| 282 void test_initialState() { |
| 283 expect(completer.isCompleted, isFalse); |
| 284 expect(cancelCount, 0); |
| 285 } |
| 286 } |
| 287 |
| 288 @reflectiveTest |
| 289 class CancelableFutureTests { |
| 290 Future test_defaultConstructor_returnFuture() { |
| 291 Object obj = new Object(); |
| 292 bool callbackInvoked = false; |
| 293 new CancelableFuture(() => new Future(() => obj)).then((result) { |
| 294 expect(callbackInvoked, isFalse); |
| 295 expect(result, same(obj)); |
| 296 callbackInvoked = true; |
| 297 }, onError: (error) { |
| 298 fail('Expected successful completion'); |
| 299 }); |
| 300 expect(callbackInvoked, isFalse); |
| 301 return pumpEventQueue().then((_) { |
| 302 expect(callbackInvoked, isTrue); |
| 303 }); |
| 304 } |
| 305 |
| 306 Future test_defaultConstructor_returnValue() { |
| 307 Object obj = new Object(); |
| 308 bool callbackInvoked = false; |
| 309 new CancelableFuture(() => obj).then((result) { |
| 310 expect(callbackInvoked, isFalse); |
| 311 expect(result, same(obj)); |
| 312 callbackInvoked = true; |
| 313 }, onError: (error) { |
| 314 fail('Expected successful completion'); |
| 315 }); |
| 316 expect(callbackInvoked, isFalse); |
| 317 return pumpEventQueue().then((_) { |
| 318 expect(callbackInvoked, isTrue); |
| 319 }); |
| 320 } |
| 321 |
| 322 Future test_defaultConstructor_throwException() { |
| 323 Object obj = new Object(); |
| 324 bool callbackInvoked = false; |
| 325 new CancelableFuture(() { |
| 326 throw obj; |
| 327 }).then((result) { |
| 328 fail('Expected error completion'); |
| 329 }, onError: (error) { |
| 330 expect(callbackInvoked, isFalse); |
| 331 expect(error, same(obj)); |
| 332 callbackInvoked = true; |
| 333 }); |
| 334 expect(callbackInvoked, isFalse); |
| 335 return pumpEventQueue().then((_) { |
| 336 expect(callbackInvoked, isTrue); |
| 337 }); |
| 338 } |
| 339 |
| 340 Future test_delayed_noCallback() { |
| 341 DateTime start = new DateTime.now(); |
| 342 return new CancelableFuture.delayed(new Duration(seconds: 1)) |
| 343 .then((result) { |
| 344 DateTime end = new DateTime.now(); |
| 345 expect(result, isNull); |
| 346 expect(end.difference(start).inMilliseconds > 900, isTrue); |
| 347 }); |
| 348 } |
| 349 |
| 350 Future test_delayed_withCallback() { |
| 351 Object obj = new Object(); |
| 352 DateTime start = new DateTime.now(); |
| 353 return new CancelableFuture.delayed(new Duration(seconds: 1), () { |
| 354 DateTime end = new DateTime.now(); |
| 355 expect(end.difference(start).inMilliseconds > 900, isTrue); |
| 356 return obj; |
| 357 }).then((result) { |
| 358 expect(result, same(obj)); |
| 359 }); |
| 360 } |
| 361 |
| 362 Future test_error() { |
| 363 Object obj = new Object(); |
| 364 return new CancelableFuture.error(obj).then((result) { |
| 365 fail('Expected error completion'); |
| 366 }, onError: (error) { |
| 367 expect(error, same(obj)); |
| 368 }); |
| 369 } |
| 370 |
| 371 Future test_microtask() { |
| 372 Object obj = new Object(); |
| 373 bool callbackInvoked = false; |
| 374 new CancelableFuture.microtask(() => obj).then((result) { |
| 375 expect(callbackInvoked, isFalse); |
| 376 expect(result, same(obj)); |
| 377 callbackInvoked = true; |
| 378 }, onError: (error) { |
| 379 fail('Expected successful completion'); |
| 380 }); |
| 381 expect(callbackInvoked, isFalse); |
| 382 return pumpEventQueue().then((_) { |
| 383 expect(callbackInvoked, isTrue); |
| 384 }); |
| 385 } |
| 386 |
| 387 Future test_sync() { |
| 388 Object obj = new Object(); |
| 389 bool callbackInvoked = false; |
| 390 new CancelableFuture.sync(() => obj).then((result) { |
| 391 expect(callbackInvoked, isFalse); |
| 392 expect(result, same(obj)); |
| 393 callbackInvoked = true; |
| 394 }, onError: (error) { |
| 395 fail('Expected successful completion'); |
| 396 }); |
| 397 expect(callbackInvoked, isFalse); |
| 398 return pumpEventQueue().then((_) { |
| 399 expect(callbackInvoked, isTrue); |
| 400 }); |
| 401 } |
| 402 |
| 403 Future test_value() { |
| 404 Object obj = new Object(); |
| 405 return new CancelableFuture.value(obj).then((result) { |
| 406 expect(result, same(obj)); |
| 407 }, onError: (error) { |
| 408 fail('Expected successful completion'); |
| 409 }); |
| 410 } |
| 411 } |
OLD | NEW |