[flutter_tools] fix failure to create ansi spinner if download needs to be retried (#65797)

Because the Status spinner was only created on setup, the second stop would asset/crash.

Fixes #65449
This commit is contained in:
Jonah Williams 2020-09-14 17:55:11 -07:00 committed by GitHub
parent 4e20f00053
commit 6acea15f22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 6 deletions

View file

@ -81,7 +81,10 @@ class OutputPreferences {
/// The command line terminal, if available.
abstract class Terminal {
factory Terminal.test() = _TestTerminal;
/// Create a new test [Terminal].
///
/// If not specified, [supportsColor] defaults to `false`.
factory Terminal.test({bool supportsColor}) = _TestTerminal;
/// Whether the current terminal supports color escape codes.
bool get supportsColor;
@ -300,6 +303,8 @@ class AnsiTerminal implements Terminal {
}
class _TestTerminal implements Terminal {
_TestTerminal({this.supportsColor = false});
@override
bool usesTerminalUi;
@ -329,7 +334,7 @@ class _TestTerminal implements Terminal {
set singleCharMode(bool value) { }
@override
bool get supportsColor => false;
final bool supportsColor;
@override
bool get supportsEmoji => false;

View file

@ -1466,13 +1466,14 @@ class ArtifactUpdater {
) async {
final String downloadPath = flattenNameSubdirs(url, _fileSystem);
final File tempFile = _createDownloadFile(downloadPath);
final Status status = _logger.startProgress(
message,
timeout: null, // This will take a variable amount of time based on network connectivity.
);
Status status;
int retries = _kRetryCount;
while (retries > 0) {
status = _logger.startProgress(
message,
timeout: null, // This will take a variable amount of time based on network connectivity.
);
try {
_ensureExists(tempFile.parent);
final IOSink ioSink = tempFile.openWrite();

View file

@ -10,10 +10,12 @@ import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:mockito/mockito.dart';
import '../src/common.dart';
import '../src/mocks.dart';
final Platform testPlatform = FakePlatform(environment: <String, String>{});
@ -41,6 +43,34 @@ void main() {
expect(fileSystem.file('out/test'), exists);
});
testWithoutContext('ArtifactUpdater will restart the status ticker if it needs to retry the download', () async {
final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final Logger logger = StdoutLogger(
terminal: Terminal.test(supportsColor: true),
stdio: MockStdio(),
outputPreferences: OutputPreferences.test(),
timeoutConfiguration: const TimeoutConfiguration(),
);
final ArtifactUpdater artifactUpdater = ArtifactUpdater(
fileSystem: fileSystem,
logger: logger,
operatingSystemUtils: operatingSystemUtils,
platform: testPlatform,
httpClient: MockHttpClient()..exceptionOnFirstRun = true,
tempStorage: fileSystem.currentDirectory.childDirectory('temp')
..createSync(),
);
await artifactUpdater.downloadZipArchive(
'test message',
Uri.parse('http:///test.zip'),
fileSystem.currentDirectory.childDirectory('out'),
);
expect(fileSystem.file('out/test'), exists);
});
testWithoutContext('ArtifactUpdater will re-attempt on a non-200 response', () async {
final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
@ -249,10 +279,15 @@ class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {
class MockHttpClient extends Mock implements HttpClient {
int attempts = 0;
bool argumentError = false;
bool exceptionOnFirstRun = false;
final MockHttpClientRequest testRequest = MockHttpClientRequest();
@override
Future<HttpClientRequest> getUrl(Uri url) async {
if (exceptionOnFirstRun && attempts == 0) {
attempts += 1;
throw Exception();
}
attempts += 1;
if (argumentError) {
throw ArgumentError();