mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
Deflake AnsiSpinner tests (#27825)
This commit is contained in:
parent
e711fd9744
commit
fdcb861b05
|
@ -6,6 +6,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import '../base/context.dart';
|
||||||
import 'io.dart';
|
import 'io.dart';
|
||||||
import 'platform.dart';
|
import 'platform.dart';
|
||||||
import 'terminal.dart';
|
import 'terminal.dart';
|
||||||
|
@ -464,7 +465,7 @@ abstract class Status {
|
||||||
final VoidCallback onFinish;
|
final VoidCallback onFinish;
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
final Stopwatch _stopwatch = Stopwatch();
|
final Stopwatch _stopwatch = context[Stopwatch] ?? Stopwatch();
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
|
|
|
@ -63,20 +63,24 @@ void main() {
|
||||||
|
|
||||||
group('Spinners', () {
|
group('Spinners', () {
|
||||||
MockStdio mockStdio;
|
MockStdio mockStdio;
|
||||||
AnsiStatus ansiStatus;
|
FakeStopwatch mockStopwatch;
|
||||||
int called;
|
int called;
|
||||||
const List<String> testPlatforms = <String>['linux', 'macos', 'windows', 'fuchsia'];
|
const List<String> testPlatforms = <String>['linux', 'macos', 'windows', 'fuchsia'];
|
||||||
final RegExp secondDigits = RegExp(r'[0-9,.]*[0-9]m?s');
|
final RegExp secondDigits = RegExp(r'[0-9,.]*[0-9]m?s');
|
||||||
|
|
||||||
setUp(() {
|
AnsiStatus _createAnsiStatus() {
|
||||||
mockStdio = MockStdio();
|
mockStopwatch = FakeStopwatch();
|
||||||
called = 0;
|
return AnsiStatus(
|
||||||
ansiStatus = AnsiStatus(
|
|
||||||
message: 'Hello world',
|
message: 'Hello world',
|
||||||
timeout: const Duration(milliseconds: 10),
|
timeout: const Duration(seconds: 2),
|
||||||
padding: 20,
|
padding: 20,
|
||||||
onFinish: () => called += 1,
|
onFinish: () => called += 1,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
mockStdio = MockStdio();
|
||||||
|
called = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
List<String> outputStdout() => mockStdio.writtenToStdout.join('').split('\n');
|
List<String> outputStdout() => mockStdio.writtenToStdout.join('').split('\n');
|
||||||
|
@ -221,20 +225,17 @@ void main() {
|
||||||
Stdio: () => mockStdio,
|
Stdio: () => mockStdio,
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('AnsiStatus works for $testOs', () async {
|
testUsingContext('AnsiStatus works for $testOs', () {
|
||||||
|
final AnsiStatus ansiStatus = _createAnsiStatus();
|
||||||
bool done = false;
|
bool done = false;
|
||||||
// We pad the time here so that we have a little slack in terms of the first part of this test
|
FakeAsync().run((FakeAsync time) {
|
||||||
// taking longer to run than we'd like, since we are forced to start the timer before the actual
|
|
||||||
// stopwatch that we're trying to test. This is an unfortunate possible race condition. If this
|
|
||||||
// turns out to be flaky, we will need to find another solution.
|
|
||||||
final Future<void> tenMillisecondsLater = Future<void>.delayed(const Duration(milliseconds: 15));
|
|
||||||
await FakeAsync().run((FakeAsync time) async {
|
|
||||||
ansiStatus.start();
|
ansiStatus.start();
|
||||||
|
mockStopwatch.elapsed = const Duration(seconds: 1);
|
||||||
doWhileAsync(time, () => ansiStatus.ticks < 10); // one second
|
doWhileAsync(time, () => ansiStatus.ticks < 10); // one second
|
||||||
expect(ansiStatus.seemsSlow, isFalse);
|
expect(ansiStatus.seemsSlow, isFalse);
|
||||||
expect(outputStdout().join('\n'), isNot(contains('This is taking an unexpectedly long time.')));
|
expect(outputStdout().join('\n'), isNot(contains('This is taking an unexpectedly long time.')));
|
||||||
expect(outputStdout().join('\n'), isNot(contains('(!)')));
|
expect(outputStdout().join('\n'), isNot(contains('(!)')));
|
||||||
await tenMillisecondsLater;
|
mockStopwatch.elapsed = const Duration(seconds: 3);
|
||||||
doWhileAsync(time, () => ansiStatus.ticks < 30); // three seconds
|
doWhileAsync(time, () => ansiStatus.ticks < 30); // three seconds
|
||||||
expect(ansiStatus.seemsSlow, isTrue);
|
expect(ansiStatus.seemsSlow, isTrue);
|
||||||
expect(outputStdout().join('\n'), contains('This is taking an unexpectedly long time.'));
|
expect(outputStdout().join('\n'), contains('This is taking an unexpectedly long time.'));
|
||||||
|
@ -246,12 +247,15 @@ void main() {
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
Platform: () => FakePlatform(operatingSystem: testOs),
|
Platform: () => FakePlatform(operatingSystem: testOs),
|
||||||
Stdio: () => mockStdio,
|
Stdio: () => mockStdio,
|
||||||
|
Stopwatch: () => mockStopwatch,
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('AnsiStatus works when cancelled for $testOs', () async {
|
testUsingContext('AnsiStatus works when cancelled for $testOs', () async {
|
||||||
|
final AnsiStatus ansiStatus = _createAnsiStatus();
|
||||||
bool done = false;
|
bool done = false;
|
||||||
FakeAsync().run((FakeAsync time) {
|
FakeAsync().run((FakeAsync time) {
|
||||||
ansiStatus.start();
|
ansiStatus.start();
|
||||||
|
mockStopwatch.elapsed = const Duration(seconds: 1);
|
||||||
doWhileAsync(time, () => ansiStatus.ticks < 10);
|
doWhileAsync(time, () => ansiStatus.ticks < 10);
|
||||||
List<String> lines = outputStdout();
|
List<String> lines = outputStdout();
|
||||||
expect(lines[0], startsWith(platform.isWindows
|
expect(lines[0], startsWith(platform.isWindows
|
||||||
|
@ -280,12 +284,15 @@ void main() {
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
Platform: () => FakePlatform(operatingSystem: testOs),
|
Platform: () => FakePlatform(operatingSystem: testOs),
|
||||||
Stdio: () => mockStdio,
|
Stdio: () => mockStdio,
|
||||||
|
Stopwatch: () => mockStopwatch,
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('AnsiStatus works when stopped for $testOs', () async {
|
testUsingContext('AnsiStatus works when stopped for $testOs', () async {
|
||||||
|
final AnsiStatus ansiStatus = _createAnsiStatus();
|
||||||
bool done = false;
|
bool done = false;
|
||||||
FakeAsync().run((FakeAsync time) {
|
FakeAsync().run((FakeAsync time) {
|
||||||
ansiStatus.start();
|
ansiStatus.start();
|
||||||
|
mockStopwatch.elapsed = const Duration(seconds: 1);
|
||||||
doWhileAsync(time, () => ansiStatus.ticks < 10);
|
doWhileAsync(time, () => ansiStatus.ticks < 10);
|
||||||
List<String> lines = outputStdout();
|
List<String> lines = outputStdout();
|
||||||
expect(lines, hasLength(1));
|
expect(lines, hasLength(1));
|
||||||
|
@ -323,6 +330,7 @@ void main() {
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
Platform: () => FakePlatform(operatingSystem: testOs),
|
Platform: () => FakePlatform(operatingSystem: testOs),
|
||||||
Stdio: () => mockStdio,
|
Stdio: () => mockStdio,
|
||||||
|
Stopwatch: () => mockStopwatch,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -685,3 +693,39 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FakeStopwatch implements Stopwatch {
|
||||||
|
@override
|
||||||
|
bool get isRunning => _isRunning;
|
||||||
|
bool _isRunning = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void start() => _isRunning = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void stop() => _isRunning = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Duration elapsed = Duration.zero;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get elapsedMicroseconds => elapsed.inMicroseconds;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get elapsedMilliseconds => elapsed.inMilliseconds;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get elapsedTicks => elapsed.inMilliseconds;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get frequency => 1000;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void reset() {
|
||||||
|
_isRunning = false;
|
||||||
|
elapsed = Duration.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => '$runtimeType $elapsed $isRunning';
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue