Line data Source code
1 : // Copyright (c) 2021, 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 : import 'dart:async'; 6 : 7 : import 'package:stack_trace/stack_trace.dart'; 8 : 9 : import 'src/backend/closed_exception.dart'; 10 : import 'src/backend/invoker.dart'; 11 : import 'src/backend/stack_trace_formatter.dart'; 12 : 13 : export 'src/backend/test_failure.dart' show TestFailure; 14 : export 'src/scaffolding/utils.dart' show pumpEventQueue; 15 : 16 : class TestHandle { 17 : /// Returns handle for the currently running test. 18 : /// 19 : /// This must be called from within the zone that the test is running in. If 20 : /// the current zone is not a test's zone throws [OutsideTestException]. 21 11 : static TestHandle get current { 22 11 : final invoker = Invoker.current; 23 0 : if (invoker == null) throw OutsideTestException(); 24 11 : return TestHandle._( 25 11 : invoker, StackTraceFormatter.current ?? _defaultFormatter); 26 : } 27 : 28 0 : static final _defaultFormatter = StackTraceFormatter(); 29 : 30 : final Invoker _invoker; 31 : final StackTraceFormatter _stackTraceFormatter; 32 11 : TestHandle._(this._invoker, this._stackTraceFormatter); 33 : 34 0 : String get name => _invoker.liveTest.test.name; 35 : 36 : /// Whether this test has already completed successfully. 37 : /// 38 : /// If a callback originating from a test case is invoked after the test has 39 : /// already passed it may be an indication of a test that fails to wait for 40 : /// all work to be finished, or of an asynchronous callback that is called 41 : /// more times or later than expected. 42 0 : bool get shouldBeDone => _invoker.liveTest.state.shouldBeDone; 43 : 44 : /// Marks this test as skipped. 45 : /// 46 : /// A skipped test may still fail if any exception is thrown, including 47 : /// uncaught asynchronous errors. 48 0 : void markSkipped(String message) { 49 0 : if (_invoker.closed) throw ClosedException(); 50 0 : _invoker.skip(message); 51 : } 52 : 53 : /// Indicates that this test should not be considered done until the returned 54 : /// [OutstandingWork] is marked as complete. 55 : /// 56 : /// The test may time out before the outstanding work completes. 57 5 : OutstandingWork markPending() { 58 10 : if (_invoker.closed) throw ClosedException(); 59 15 : return OutstandingWork._(_invoker, Zone.current); 60 : } 61 : 62 : /// Converts [stackTrace] to a [Chain] according to the current test's 63 : /// configuration. 64 0 : Chain formatStackTrace(StackTrace stackTrace) => 65 0 : _stackTraceFormatter.formatStackTrace(stackTrace); 66 : } 67 : 68 : class OutstandingWork { 69 : final Invoker _invoker; 70 : final Zone _zone; 71 : var _isComplete = false; 72 5 : OutstandingWork._(this._invoker, this._zone) { 73 10 : _invoker.addOutstandingCallback(); 74 : } 75 5 : void complete() { 76 5 : if (_isComplete) return; 77 5 : _isComplete = true; 78 20 : _zone.run(_invoker.removeOutstandingCallback); 79 : } 80 : } 81 : 82 : class OutsideTestException implements Exception {}