[flutter_tools] Remove context usage from status and clean up test cases (#48446)
diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart index 6dbebee..e3a61a1 100644 --- a/packages/flutter_tools/lib/src/base/logger.dart +++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -5,6 +5,7 @@ import 'dart:async'; import 'package:meta/meta.dart'; +import 'package:platform/platform.dart'; import '../base/context.dart'; import '../globals.dart' as globals; @@ -21,6 +22,15 @@ /// If not provided via injection, a default instance is provided. TimeoutConfiguration get timeoutConfiguration => context.get<TimeoutConfiguration>() ?? const TimeoutConfiguration(); +/// A factory for generating [Stopwatch] instances for [Status] instances. +class StopwatchFactory { + /// const constructor so that subclasses may be const. + const StopwatchFactory(); + + /// Create a new [Stopwatch] instance. + Stopwatch createStopwatch() => Stopwatch(); +} + class TimeoutConfiguration { const TimeoutConfiguration(); @@ -166,11 +176,15 @@ @required Stdio stdio, @required OutputPreferences outputPreferences, @required TimeoutConfiguration timeoutConfiguration, + @required Platform platform, + StopwatchFactory stopwatchFactory = const StopwatchFactory(), }) : _stdio = stdio, _terminal = terminal, _timeoutConfiguration = timeoutConfiguration, - _outputPreferences = outputPreferences; + _outputPreferences = outputPreferences, + _stopwatchFactory = stopwatchFactory, + _platform = platform; @override final AnsiTerminal _terminal; @@ -179,6 +193,8 @@ @override final TimeoutConfiguration _timeoutConfiguration; final Stdio _stdio; + final StopwatchFactory _stopwatchFactory; + final Platform _platform; Status _status; @@ -273,7 +289,8 @@ return SilentStatus( timeout: timeout, onFinish: _clearStatus, - timeoutConfiguration: _timeoutConfiguration + timeoutConfiguration: _timeoutConfiguration, + stopwatch: _stopwatchFactory.createStopwatch(), )..start(); } if (supportsColor) { @@ -285,6 +302,8 @@ onFinish: _clearStatus, stdio: _stdio, timeoutConfiguration: _timeoutConfiguration, + platform: _platform, + stopwatch: _stopwatchFactory.createStopwatch(), )..start(); } else { _status = SummaryStatus( @@ -294,6 +313,7 @@ onFinish: _clearStatus, stdio: _stdio, timeoutConfiguration: _timeoutConfiguration, + stopwatch: _stopwatchFactory.createStopwatch(), )..start(); } return _status; @@ -321,11 +341,15 @@ @required Stdio stdio, @required OutputPreferences outputPreferences, @required TimeoutConfiguration timeoutConfiguration, + @required Platform platform, + StopwatchFactory stopwatchFactory = const StopwatchFactory(), }) : super( terminal: terminal, stdio: stdio, outputPreferences: outputPreferences, timeoutConfiguration: timeoutConfiguration, + stopwatchFactory: stopwatchFactory, + platform: platform, ); @override @@ -342,10 +366,12 @@ BufferLogger({ @required AnsiTerminal terminal, @required OutputPreferences outputPreferences, - TimeoutConfiguration timeoutConfiguration = const TimeoutConfiguration() + TimeoutConfiguration timeoutConfiguration = const TimeoutConfiguration(), + StopwatchFactory stopwatchFactory = const StopwatchFactory(), }) : _outputPreferences = outputPreferences, _terminal = terminal, - _timeoutConfiguration = timeoutConfiguration; + _timeoutConfiguration = timeoutConfiguration, + _stopwatchFactory = stopwatchFactory; @override final OutputPreferences _outputPreferences; @@ -356,6 +382,8 @@ @override final TimeoutConfiguration _timeoutConfiguration; + final StopwatchFactory _stopwatchFactory; + @override bool get isVerbose => false; @@ -437,7 +465,7 @@ return SilentStatus( timeout: timeout, timeoutConfiguration: _timeoutConfiguration, - + stopwatch: _stopwatchFactory.createStopwatch(), )..start(); } @@ -453,8 +481,10 @@ } class VerboseLogger extends Logger { - VerboseLogger(this.parent, { @required Stopwatch stopwatch }) : - _stopwatch = stopwatch ?? context.get<Stopwatch>() ?? Stopwatch() { + VerboseLogger(this.parent, { + StopwatchFactory stopwatchFactory = const StopwatchFactory() + }) : _stopwatch = stopwatchFactory.createStopwatch(), + _stopwatchFactory = stopwatchFactory { _stopwatch.start(); } @@ -471,6 +501,8 @@ @override TimeoutConfiguration get _timeoutConfiguration => parent._timeoutConfiguration; + final StopwatchFactory _stopwatchFactory; + @override bool get isVerbose => true; @@ -529,10 +561,12 @@ }) { assert(progressIndicatorPadding != null); printStatus(message); - final Stopwatch timer = Stopwatch()..start(); + final Stopwatch timer = _stopwatchFactory.createStopwatch()..start(); return SilentStatus( timeout: timeout, timeoutConfiguration: _timeoutConfiguration, + // This is intentionally a different stopwatch than above. + stopwatch: _stopwatchFactory.createStopwatch(), onFinish: () { String time; if (timeout == null || timeout > _timeoutConfiguration.fastOperation) { @@ -623,28 +657,36 @@ @required this.timeout, @required TimeoutConfiguration timeoutConfiguration, this.onFinish, - }) : _timeoutConfiguration = timeoutConfiguration; + @required Stopwatch stopwatch, + }) : _timeoutConfiguration = timeoutConfiguration, + _stopwatch = stopwatch; /// A [SilentStatus] or an [AnsiSpinner] (depending on whether the /// terminal is fancy enough), already started. factory Status.withSpinner({ @required Duration timeout, @required TimeoutConfiguration timeoutConfiguration, + @required Stopwatch stopwatch, + @required bool supportsColor, + @required Platform platform, VoidCallback onFinish, SlowWarningCallback slowWarningCallback, }) { - if (globals.terminal.supportsColor) { + if (supportsColor) { return AnsiSpinner( timeout: timeout, onFinish: onFinish, slowWarningCallback: slowWarningCallback, timeoutConfiguration: timeoutConfiguration, + stopwatch: stopwatch, + platform: platform, )..start(); } return SilentStatus( timeout: timeout, onFinish: onFinish, timeoutConfiguration: timeoutConfiguration, + stopwatch: stopwatch, )..start(); } @@ -653,7 +695,7 @@ final TimeoutConfiguration _timeoutConfiguration; @protected - final Stopwatch _stopwatch = context.get<Stopwatch>() ?? Stopwatch(); + final Stopwatch _stopwatch; @protected @visibleForTesting @@ -704,11 +746,13 @@ SilentStatus({ @required Duration timeout, @required TimeoutConfiguration timeoutConfiguration, + @required Stopwatch stopwatch, VoidCallback onFinish, }) : super( timeout: timeout, onFinish: onFinish, timeoutConfiguration: timeoutConfiguration, + stopwatch: stopwatch, ); } @@ -718,14 +762,20 @@ SummaryStatus({ this.message = '', @required Duration timeout, + @required TimeoutConfiguration timeoutConfiguration, + @required Stopwatch stopwatch, this.padding = kDefaultStatusPadding, VoidCallback onFinish, Stdio stdio, - @required TimeoutConfiguration timeoutConfiguration, }) : assert(message != null), assert(padding != null), _stdio = stdio ?? globals.stdio, - super(timeout: timeout, onFinish: onFinish, timeoutConfiguration: timeoutConfiguration); + super( + timeout: timeout, + onFinish: onFinish, + timeoutConfiguration: timeoutConfiguration, + stopwatch: stopwatch, + ); final String message; final int padding; @@ -794,16 +844,25 @@ class AnsiSpinner extends Status { AnsiSpinner({ @required Duration timeout, + @required TimeoutConfiguration timeoutConfiguration, + @required Stopwatch stopwatch, + @required Platform platform, VoidCallback onFinish, this.slowWarningCallback, Stdio stdio, - @required TimeoutConfiguration timeoutConfiguration, }) : _stdio = stdio ?? globals.stdio, - super(timeout: timeout, onFinish: onFinish, timeoutConfiguration: timeoutConfiguration); + _isWindows = platform.isWindows, + super( + timeout: timeout, + onFinish: onFinish, + timeoutConfiguration: timeoutConfiguration, + stopwatch: stopwatch, + ); final String _backspaceChar = '\b'; final String _clearChar = ' '; final Stdio _stdio; + final bool _isWindows; bool timedOut = false; @@ -811,9 +870,9 @@ Timer timer; // Windows console font has a limited set of Unicode characters. - List<String> get _animation => globals.platform.isWindows - ? <String>[r'-', r'\', r'|', r'/'] - : <String>['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']; + List<String> get _animation => _isWindows + ? const <String>[r'-', r'\', r'|', r'/'] + : const <String>['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']; static const String _defaultSlowWarning = '(This is taking an unexpectedly long time.)'; final SlowWarningCallback slowWarningCallback; @@ -903,16 +962,25 @@ class AnsiStatus extends AnsiSpinner { AnsiStatus({ this.message = '', - @required Duration timeout, this.multilineOutput = false, this.padding = kDefaultStatusPadding, + @required Duration timeout, + @required Stopwatch stopwatch, + @required Platform platform, VoidCallback onFinish, Stdio stdio, TimeoutConfiguration timeoutConfiguration, }) : assert(message != null), assert(multilineOutput != null), assert(padding != null), - super(timeout: timeout, onFinish: onFinish, stdio: stdio, timeoutConfiguration: timeoutConfiguration); + super( + timeout: timeout, + onFinish: onFinish, + stdio: stdio, + timeoutConfiguration: timeoutConfiguration, + stopwatch: stopwatch, + platform: platform, + ); final String message; final bool multilineOutput;
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index b33a963..b03f056 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -974,7 +974,11 @@ }) { assert(timeout != null); printStatus(message); - return SilentStatus(timeout: timeout, timeoutConfiguration: timeoutConfiguration); + return SilentStatus( + timeout: timeout, + timeoutConfiguration: timeoutConfiguration, + stopwatch: Stopwatch(), + ); } void dispose() { @@ -1181,7 +1185,7 @@ 'progressId': progressId, 'finished': true, }); - })..start(); + }, stopwatch: Stopwatch())..start(); return _status; }
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart index 92d6ba5..a6e7e5b 100644 --- a/packages/flutter_tools/lib/src/context_runner.dart +++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -108,12 +108,14 @@ stdio: globals.stdio, outputPreferences: outputPreferences, timeoutConfiguration: timeoutConfiguration, + platform: globals.platform, ) : StdoutLogger( terminal: globals.terminal, stdio: globals.stdio, outputPreferences: outputPreferences, timeoutConfiguration: timeoutConfiguration, + platform: globals.platform, ), MacOSWorkflow: () => const MacOSWorkflow(), MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart index a7cd3ec..cd7afb8 100644 --- a/packages/flutter_tools/lib/src/doctor.dart +++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -259,6 +259,9 @@ timeout: timeoutConfiguration.fastOperation, slowWarningCallback: () => validator.slowWarning, timeoutConfiguration: timeoutConfiguration, + stopwatch: Stopwatch(), + supportsColor: globals.terminal.supportsColor, + platform: globals.platform, ); ValidationResult result; try {
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 7b4203d..b3c7f74 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -285,6 +285,9 @@ final Status status = Status.withSpinner( timeout: timeoutConfiguration.fastOperation, timeoutConfiguration: timeoutConfiguration, + platform: globals.platform, + stopwatch: Stopwatch(), + supportsColor: globals.terminal.supportsColor, ); final List<String> showBuildSettingsCommand = <String>[ _executable,
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart index ee6d56a..511de9a 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -239,7 +239,7 @@ // Check for verbose. if (topLevelResults['verbose'] as bool) { // Override the logger. - contextOverrides[Logger] = VerboseLogger(globals.logger, stopwatch: Stopwatch()); + contextOverrides[Logger] = VerboseLogger(globals.logger); } // Don't set wrapColumns unless the user said to: if it's set, then all
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart index 8e589ab..c51c372 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
@@ -704,7 +704,11 @@ int progressIndicatorPadding = kDefaultStatusPadding, }) { _log('[progress] $message'); - return SilentStatus(timeout: timeout, timeoutConfiguration: timeoutConfiguration)..start(); + return SilentStatus( + timeout: timeout, + timeoutConfiguration: timeoutConfiguration, + stopwatch: Stopwatch(), + )..start(); } bool _interrupt = false;
diff --git a/packages/flutter_tools/test/general.shard/base/logger_test.dart b/packages/flutter_tools/test/general.shard/base/logger_test.dart index 7095381..3b15509 100644 --- a/packages/flutter_tools/test/general.shard/base/logger_test.dart +++ b/packages/flutter_tools/test/general.shard/base/logger_test.dart
@@ -5,24 +5,20 @@ import 'dart:convert' show jsonEncode; import 'package:platform/platform.dart'; -import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/terminal.dart'; -import 'package:flutter_tools/src/globals.dart' as globals; import 'package:quiver/testing/async.dart'; import '../../src/common.dart'; -import '../../src/context.dart'; import '../../src/mocks.dart'; final Platform _kNoAnsiPlatform = FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false; +final String red = RegExp.escape(AnsiTerminal.red); +final String bold = RegExp.escape(AnsiTerminal.bold); +final String resetBold = RegExp.escape(AnsiTerminal.resetBold); +final String resetColor = RegExp.escape(AnsiTerminal.resetColor); void main() { - final String red = RegExp.escape(AnsiTerminal.red); - final String bold = RegExp.escape(AnsiTerminal.bold); - final String resetBold = RegExp.escape(AnsiTerminal.resetBold); - final String resetColor = RegExp.escape(AnsiTerminal.resetColor); - group('AppContext', () { FakeStopwatch fakeStopWatch; @@ -37,7 +33,10 @@ ), outputPreferences: OutputPreferences.test(showColor: false), ); - final VerboseLogger verboseLogger = VerboseLogger(mockLogger, stopwatch: fakeStopWatch); + final VerboseLogger verboseLogger = VerboseLogger( + mockLogger, + stopwatchFactory: FakeStopwatchFactory(fakeStopWatch), + ); verboseLogger.printStatus('Hey Hey Hey Hey'); verboseLogger.printTrace('Oooh, I do I do I do'); @@ -57,7 +56,9 @@ ), outputPreferences: OutputPreferences.test(showColor: true), ); - final VerboseLogger verboseLogger = VerboseLogger(mockLogger, stopwatch: fakeStopWatch); + final VerboseLogger verboseLogger = VerboseLogger( + mockLogger, stopwatchFactory: FakeStopwatchFactory(fakeStopWatch), + ); verboseLogger.printStatus('Hey Hey Hey Hey'); verboseLogger.printTrace('Oooh, I do I do I do'); @@ -77,25 +78,16 @@ group('Spinners', () { MockStdio mockStdio; FakeStopwatch mockStopwatch; + FakeStopwatchFactory stopwatchFactory; int called; const List<String> testPlatforms = <String>['linux', 'macos', 'windows', 'fuchsia']; final RegExp secondDigits = RegExp(r'[0-9,.]*[0-9]m?s'); - AnsiStatus _createAnsiStatus() { - return AnsiStatus( - message: 'Hello world', - timeout: const Duration(seconds: 2), - padding: 20, - onFinish: () => called += 1, - stdio: mockStdio, - timeoutConfiguration: const TimeoutConfiguration(), - ); - } - setUp(() { mockStopwatch = FakeStopwatch(); mockStdio = MockStdio(); called = 0; + stopwatchFactory = FakeStopwatchFactory(mockStopwatch); }); List<String> outputStdout() => mockStdio.writtenToStdout.join('').split('\n'); @@ -109,7 +101,21 @@ } for (final String testOs in testPlatforms) { - testUsingContext('AnsiSpinner works for $testOs (1)', () async { + Platform currentPlatform() => FakePlatform(operatingSystem: testOs); + + AnsiStatus createAnsiStatus() { + return AnsiStatus( + message: 'Hello world', + timeout: const Duration(seconds: 2), + padding: 20, + onFinish: () => called += 1, + stdio: mockStdio, + timeoutConfiguration: const TimeoutConfiguration(), + stopwatch: stopwatchFactory.createStopwatch(), + platform: currentPlatform(), + ); + } + testWithoutContext('AnsiSpinner works for $testOs (1)', () async { bool done = false; mockStopwatch = FakeStopwatch(); FakeAsync().run((FakeAsync time) { @@ -117,38 +123,35 @@ timeout: const Duration(hours: 10), stdio: mockStdio, timeoutConfiguration: const TimeoutConfiguration(), + stopwatch: stopwatchFactory.createStopwatch(), + platform: currentPlatform(), )..start(); doWhileAsync(time, () => ansiSpinner.ticks < 10); List<String> lines = outputStdout(); expect(lines[0], startsWith( - globals.platform.isWindows + currentPlatform().isWindows ? ' \b\\\b|\b/\b-\b\\\b|\b/\b-' : ' \b⣽\b⣻\b⢿\b⡿\b⣟\b⣯\b⣷\b⣾\b⣽\b⣻' ), ); expect(lines[0].endsWith('\n'), isFalse); expect(lines.length, equals(1)); + ansiSpinner.stop(); lines = outputStdout(); + expect(lines[0], endsWith('\b \b')); expect(lines.length, equals(1)); // Verify that stopping or canceling multiple times throws. - expect(() { - ansiSpinner.stop(); - }, throwsA(isInstanceOf<AssertionError>())); - expect(() { - ansiSpinner.cancel(); - }, throwsA(isInstanceOf<AssertionError>())); + expect(ansiSpinner.stop, throwsA(isInstanceOf<AssertionError>())); + expect(ansiSpinner.cancel, throwsA(isInstanceOf<AssertionError>())); done = true; }); expect(done, isTrue); - }, overrides: <Type, Generator>{ - Platform: () => FakePlatform(operatingSystem: testOs), - Stopwatch: () => mockStopwatch, }); - testUsingContext('AnsiSpinner works for $testOs (2)', () async { + testWithoutContext('AnsiSpinner works for $testOs (2)', () async { bool done = false; mockStopwatch = FakeStopwatch(); FakeAsync().run((FakeAsync time) { @@ -156,13 +159,17 @@ timeout: const Duration(seconds: 2), stdio: mockStdio, timeoutConfiguration: const TimeoutConfiguration(), + stopwatch: mockStopwatch, + platform: FakePlatform(operatingSystem: testOs), )..start(); mockStopwatch.elapsed = const Duration(seconds: 1); doWhileAsync(time, () => ansiSpinner.ticks < 10); // one second + expect(ansiSpinner.seemsSlow, isFalse); expect(outputStdout().join('\n'), isNot(contains('This is taking an unexpectedly long time.'))); mockStopwatch.elapsed = const Duration(seconds: 3); doWhileAsync(time, () => ansiSpinner.ticks < 30); // three seconds + expect(ansiSpinner.seemsSlow, isTrue); // Check the 2nd line to verify there's a newline before the warning expect(outputStdout()[1], contains('This is taking an unexpectedly long time.')); @@ -171,13 +178,9 @@ done = true; }); expect(done, isTrue); - }, overrides: <Type, Generator>{ - Platform: () => FakePlatform(operatingSystem: testOs), - Stopwatch: () => mockStopwatch, }); - // Uses Stopwatch from context. - testUsingContext('Stdout startProgress on colored terminal for $testOs', () async { + testWithoutContext('Stdout startProgress on colored terminal for $testOs', () async { bool done = false; FakeAsync().run((FakeAsync time) { final Logger logger = StdoutLogger( @@ -188,27 +191,31 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: true), timeoutConfiguration: const TimeoutConfiguration(), + stopwatchFactory: stopwatchFactory, + platform: currentPlatform(), ); final Status status = logger.startProgress( 'Hello', progressId: null, - timeout: timeoutConfiguration.slowOperation, + timeout: const TimeoutConfiguration().slowOperation, progressIndicatorPadding: 20, // this minus the "Hello" equals the 15 below. ); expect(outputStderr().length, equals(1)); expect(outputStderr().first, isEmpty); // the 5 below is the margin that is always included between the message and the time. - expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\$' : - r'^Hello {15} {5} {8}[\b]{8} {7}⣽$')); + expect(outputStdout().join('\n'), + matches(currentPlatform().isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\$' : + r'^Hello {15} {5} {8}[\b]{8} {7}⣽$')); status.stop(); - expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$' : - r'^Hello {15} {5} {8}[\b]{8} {7}⣽[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$')); + expect(outputStdout().join('\n'), + matches(currentPlatform().isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$' : + r'^Hello {15} {5} {8}[\b]{8} {7}⣽[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$')); done = true; }); expect(done, isTrue); }); - testUsingContext('Stdout startProgress on colored terminal pauses on $testOs', () async { + testWithoutContext('Stdout startProgress on colored terminal pauses on $testOs', () async { bool done = false; FakeAsync().run((FakeAsync time) { mockStopwatch.elapsed = const Duration(seconds: 5); @@ -220,6 +227,8 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: true), timeoutConfiguration: const TimeoutConfiguration(), + stopwatchFactory: stopwatchFactory, + platform: currentPlatform(), ); final Status status = logger.startProgress( 'Knock Knock, Who\'s There', @@ -228,8 +237,9 @@ ); logger.printStatus('Rude Interrupting Cow'); status.stop(); - final String a = globals.platform.isWindows ? '\\' : '⣽'; - final String b = globals.platform.isWindows ? '|' : '⣻'; + final String a = currentPlatform().isWindows ? '\\' : '⣽'; + final String b = currentPlatform().isWindows ? '|' : '⣻'; + expect( outputStdout().join('\n'), 'Knock Knock, Who\'s There ' // initial message @@ -250,22 +260,22 @@ done = true; }); expect(done, isTrue); - }, overrides: <Type, Generator>{ - Stopwatch: () => mockStopwatch, }); - testUsingContext('AnsiStatus works for $testOs', () { - final AnsiStatus ansiStatus = _createAnsiStatus(); + testWithoutContext('AnsiStatus works for $testOs', () { + final AnsiStatus ansiStatus = createAnsiStatus(); bool done = false; FakeAsync().run((FakeAsync time) { ansiStatus.start(); mockStopwatch.elapsed = const Duration(seconds: 1); doWhileAsync(time, () => ansiStatus.ticks < 10); // one second + expect(ansiStatus.seemsSlow, isFalse); expect(outputStdout().join('\n'), isNot(contains('This is taking an unexpectedly long time.'))); expect(outputStdout().join('\n'), isNot(contains('(!)'))); mockStopwatch.elapsed = const Duration(seconds: 3); doWhileAsync(time, () => ansiStatus.ticks < 30); // three seconds + expect(ansiStatus.seemsSlow, isTrue); expect(outputStdout().join('\n'), contains('This is taking an unexpectedly long time.')); @@ -283,20 +293,18 @@ done = true; }); expect(done, isTrue); - }, overrides: <Type, Generator>{ - Platform: () => FakePlatform(operatingSystem: testOs), - Stopwatch: () => mockStopwatch, }); - testUsingContext('AnsiStatus works when canceled for $testOs', () async { - final AnsiStatus ansiStatus = _createAnsiStatus(); + testWithoutContext('AnsiStatus works when canceled for $testOs', () async { + final AnsiStatus ansiStatus = createAnsiStatus(); bool done = false; FakeAsync().run((FakeAsync time) { ansiStatus.start(); mockStopwatch.elapsed = const Duration(seconds: 1); doWhileAsync(time, () => ansiStatus.ticks < 10); List<String> lines = outputStdout(); - expect(lines[0], startsWith(globals.platform.isWindows + + expect(lines[0], startsWith(testOs == 'windows' ? 'Hello world \b\b\b\b\b\b\b\b \\\b\b\b\b\b\b\b\b |\b\b\b\b\b\b\b\b /\b\b\b\b\b\b\b\b -\b\b\b\b\b\b\b\b \\\b\b\b\b\b\b\b\b |\b\b\b\b\b\b\b\b /\b\b\b\b\b\b\b\b -\b\b\b\b\b\b\b\b \\\b\b\b\b\b\b\b\b |' : 'Hello world \b\b\b\b\b\b\b\b ⣽\b\b\b\b\b\b\b\b ⣻\b\b\b\b\b\b\b\b ⢿\b\b\b\b\b\b\b\b ⡿\b\b\b\b\b\b\b\b ⣟\b\b\b\b\b\b\b\b ⣯\b\b\b\b\b\b\b\b ⣷\b\b\b\b\b\b\b\b ⣾\b\b\b\b\b\b\b\b ⣽\b\b\b\b\b\b\b\b ⣻')); expect(lines.length, equals(1)); @@ -307,8 +315,9 @@ lines = outputStdout(); final List<Match> matches = secondDigits.allMatches(lines[0]).toList(); expect(matches, isEmpty); - final String x = globals.platform.isWindows ? '|' : '⣻'; - expect(lines[0], endsWith('$x\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b')); + final String leading = currentPlatform().isWindows ? '|' : '⣻'; + + expect(lines[0], endsWith('$leading\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b')); expect(called, equals(1)); expect(lines.length, equals(2)); expect(lines[1], equals('')); @@ -319,22 +328,20 @@ done = true; }); expect(done, isTrue); - }, overrides: <Type, Generator>{ - Platform: () => FakePlatform(operatingSystem: testOs), - Stopwatch: () => mockStopwatch, }); - testUsingContext('AnsiStatus works when stopped for $testOs', () async { - final AnsiStatus ansiStatus = _createAnsiStatus(); + testWithoutContext('AnsiStatus works when stopped for $testOs', () async { + final AnsiStatus ansiStatus = createAnsiStatus(); bool done = false; FakeAsync().run((FakeAsync time) { ansiStatus.start(); mockStopwatch.elapsed = const Duration(seconds: 1); doWhileAsync(time, () => ansiStatus.ticks < 10); List<String> lines = outputStdout(); + expect(lines, hasLength(1)); expect(lines[0], - globals.platform.isWindows + currentPlatform().isWindows ? 'Hello world \b\b\b\b\b\b\b\b \\\b\b\b\b\b\b\b\b |\b\b\b\b\b\b\b\b /\b\b\b\b\b\b\b\b -\b\b\b\b\b\b\b\b \\\b\b\b\b\b\b\b\b |\b\b\b\b\b\b\b\b /\b\b\b\b\b\b\b\b -\b\b\b\b\b\b\b\b \\\b\b\b\b\b\b\b\b |' : 'Hello world \b\b\b\b\b\b\b\b ⣽\b\b\b\b\b\b\b\b ⣻\b\b\b\b\b\b\b\b ⢿\b\b\b\b\b\b\b\b ⡿\b\b\b\b\b\b\b\b ⣟\b\b\b\b\b\b\b\b ⣯\b\b\b\b\b\b\b\b ⣷\b\b\b\b\b\b\b\b ⣾\b\b\b\b\b\b\b\b ⣽\b\b\b\b\b\b\b\b ⣻', ); @@ -344,7 +351,7 @@ lines = outputStdout(); expect(lines, hasLength(2)); expect(lines[0], matches( - globals.platform.isWindows + currentPlatform().isWindows ? r'Hello world {8}[\b]{8} {7}\\[\b]{8} {7}|[\b]{8} {7}/[\b]{8} {7}-[\b]{8} {7}\\[\b]{8} {7}|[\b]{8} {7}/[\b]{8} {7}-[\b]{8} {7}\\[\b]{8} {7}|[\b]{8} {7} [\b]{8}[\d., ]{6}[\d]ms$' : r'Hello world {8}[\b]{8} {7}⣽[\b]{8} {7}⣻[\b]{8} {7}⢿[\b]{8} {7}⡿[\b]{8} {7}⣟[\b]{8} {7}⣯[\b]{8} {7}⣷[\b]{8} {7}⣾[\b]{8} {7}⣽[\b]{8} {7}⣻[\b]{8} {7} [\b]{8}[\d., ]{5}[\d]ms$' )); @@ -353,20 +360,18 @@ expect(times, isNotNull); expect(times, hasLength(1)); final Match match = times.single; + expect(lines[0], endsWith(match.group(0))); expect(called, equals(1)); expect(lines.length, equals(2)); expect(lines[1], equals('')); // Verify that stopping or canceling multiple times throws. - expect(() { ansiStatus.stop(); }, throwsA(isInstanceOf<AssertionError>())); - expect(() { ansiStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>())); + expect(ansiStatus.stop, throwsA(isInstanceOf<AssertionError>())); + expect(ansiStatus.cancel, throwsA(isInstanceOf<AssertionError>())); done = true; }); expect(done, isTrue); - }, overrides: <Type, Generator>{ - Platform: () => FakePlatform(operatingSystem: testOs), - Stopwatch: () => mockStopwatch, }); } }); @@ -381,11 +386,12 @@ called = 0; summaryStatus = SummaryStatus( message: 'Hello world', - timeout: timeoutConfiguration.slowOperation, + timeout: const TimeoutConfiguration().slowOperation, padding: 20, onFinish: () => called++, stdio: mockStdio, timeoutConfiguration: const TimeoutConfiguration(), + stopwatch: FakeStopwatch(), ); }); @@ -401,6 +407,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printError('0123456789' * 15); final List<String> lines = outputStderr(); @@ -422,6 +429,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printError('0123456789' * 15, indent: 5); final List<String> lines = outputStderr(); @@ -446,6 +454,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printError('0123456789' * 15, hangingIndent: 5); final List<String> lines = outputStderr(); @@ -470,6 +479,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printError('0123456789' * 15, indent: 4, hangingIndent: 5); final List<String> lines = outputStderr(); @@ -494,6 +504,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus('0123456789' * 15); final List<String> lines = outputStdout(); @@ -515,6 +526,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus('0123456789' * 15, indent: 5); final List<String> lines = outputStdout(); @@ -539,6 +551,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus('0123456789' * 15, hangingIndent: 5); final List<String> lines = outputStdout(); @@ -554,7 +567,7 @@ expect(lines[5], isEmpty); }); - testUsingContext('Stdout logs are wrapped, indented, and can have hanging indent.', () async { + testWithoutContext('Stdout logs are wrapped, indented, and can have hanging indent.', () async { final Logger logger = StdoutLogger( terminal: AnsiTerminal( stdio: mockStdio, @@ -563,6 +576,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus('0123456789' * 15, indent: 4, hangingIndent: 5); final List<String> lines = outputStdout(); @@ -587,6 +601,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: true), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printError('Pants on fire!'); final List<String> lines = outputStderr(); @@ -605,6 +620,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: true), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus('All good.'); @@ -623,6 +639,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: true), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus( null, @@ -647,6 +664,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.printStatus( null, @@ -661,8 +679,7 @@ expect(lines[0], equals('')); }); - // Status uses Stopwatch from context. - test('Stdout startProgress on non-color terminal', () async { + testWithoutContext('Stdout startProgress on non-color terminal', () async { bool done = false; FakeAsync().run((FakeAsync time) { final Logger logger = StdoutLogger( @@ -673,6 +690,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); final Status status = logger.startProgress( 'Hello', @@ -683,17 +701,24 @@ expect(outputStderr().length, equals(1)); expect(outputStderr().first, isEmpty); // the 5 below is the margin that is always included between the message and the time. - expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5}$' : - r'^Hello {15} {5}$')); + expect(outputStdout().join('\n'), matches(r'^Hello {15} {5}$')); status.stop(); - expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5}[\d, ]{4}[\d]\.[\d]s[\n]$' : - r'^Hello {15} {5}[\d, ]{4}[\d]\.[\d]s[\n]$')); + expect(outputStdout().join('\n'), matches(r'^Hello {15} {5}[\d, ]{4}[\d]\.[\d]s[\n]$')); done = true; }); expect(done, isTrue); }); - testUsingContext('SummaryStatus works when canceled', () async { + testWithoutContext('SummaryStatus works when canceled', () async { + final SummaryStatus summaryStatus = SummaryStatus( + message: 'Hello world', + timeout: const TimeoutConfiguration().slowOperation, + padding: 20, + onFinish: () => called++, + stdio: mockStdio, + timeoutConfiguration: const TimeoutConfiguration(), + stopwatch: FakeStopwatch(), + ); summaryStatus.start(); List<String> lines = outputStdout(); expect(lines[0], startsWith('Hello world ')); @@ -711,13 +736,11 @@ expect(lines[1], equals('')); // Verify that stopping or canceling multiple times throws. - expect(() { summaryStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>())); - expect(() { summaryStatus.stop(); }, throwsA(isInstanceOf<AssertionError>())); - }, overrides: <Type, Generator>{ - Platform: () => _kNoAnsiPlatform, + expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>())); + expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>())); }); - testUsingContext('SummaryStatus works when stopped', () async { + testWithoutContext('SummaryStatus works when stopped', () async { summaryStatus.start(); List<String> lines = outputStdout(); expect(lines[0], startsWith('Hello world ')); @@ -736,16 +759,11 @@ expect(lines[1], equals('')); // Verify that stopping or canceling multiple times throws. - expect(() { summaryStatus.stop(); }, throwsA(isInstanceOf<AssertionError>())); - expect(() { summaryStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>())); - }, overrides: <Type, Generator>{ - Platform: () => _kNoAnsiPlatform, + expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>())); + expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>())); }); - // Status still uses Stopwatch from context. - // TODO(jonahwilliams): switch to testWithoutContext once logger uses a - // TimerFactory. - test('sequential startProgress calls with StdoutLogger', () async { + testWithoutContext('sequential startProgress calls with StdoutLogger', () async { final Logger logger = StdoutLogger( terminal: AnsiTerminal( stdio: mockStdio, @@ -754,6 +772,7 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(showColor: false), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ); logger.startProgress('AAA', timeout: const TimeoutConfiguration().fastOperation)..stop(); logger.startProgress('BBB', timeout: const TimeoutConfiguration().fastOperation)..stop(); @@ -768,8 +787,7 @@ expect(output[1], matches(RegExp(r'BBB[ ]{61}[\d, ]{5}[\d]ms'))); }); - // Status still uses Stopwatch from context. - test('sequential startProgress calls with VerboseLogger and StdoutLogger', () async { + testWithoutContext('sequential startProgress calls with VerboseLogger and StdoutLogger', () async { final Logger logger = VerboseLogger( StdoutLogger( terminal: AnsiTerminal( @@ -779,8 +797,9 @@ stdio: mockStdio, outputPreferences: OutputPreferences.test(), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ), - stopwatch: FakeStopwatch(), + stopwatchFactory: FakeStopwatchFactory(), ); logger.startProgress('AAA', timeout: const TimeoutConfiguration().fastOperation)..stop(); logger.startProgress('BBB', timeout: const TimeoutConfiguration().fastOperation)..stop(); @@ -794,8 +813,7 @@ ]); }); - // Status still uses Stopwatch from context. - test('sequential startProgress calls with BufferLogger', () async { + testWithoutContext('sequential startProgress calls with BufferLogger', () async { final BufferLogger logger = BufferLogger( terminal: AnsiTerminal( stdio: mockStdio, @@ -846,3 +864,14 @@ @override String toString() => '$runtimeType $elapsed $isRunning'; } + +class FakeStopwatchFactory implements StopwatchFactory { + FakeStopwatchFactory([this.stopwatch]); + + Stopwatch stopwatch; + + @override + Stopwatch createStopwatch() { + return stopwatch ?? FakeStopwatch(); + } +}
diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart index 5e4fb07..f7ea226 100644 --- a/packages/flutter_tools/test/general.shard/vmservice_test.dart +++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart
@@ -196,6 +196,7 @@ stdio: mockStdio, terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ), WebSocketConnector: () => (String url, {CompressionOptions compression}) async => throw const SocketException('test'), }); @@ -275,6 +276,7 @@ terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), stdio: mockStdio, timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ), }); @@ -292,6 +294,7 @@ terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), stdio: mockStdio, timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ), }); @@ -310,6 +313,7 @@ terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()), stdio: mockStdio, timeoutConfiguration: const TimeoutConfiguration(), + platform: FakePlatform(), ), }); });