Unverified Commit b8f5394a authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] Fix Future error handling ArgumentError in doctor --android-licenses (#119977)

* wip

* write test

* make error handling printError

* remove diff
parent 2e39badf
...@@ -436,11 +436,14 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -436,11 +436,14 @@ class AndroidLicenseValidator extends DoctorValidator {
unawaited(process.stdin.addStream(_stdio.stdin) unawaited(process.stdin.addStream(_stdio.stdin)
// If the process exits unexpectedly with an error, that will be // If the process exits unexpectedly with an error, that will be
// handled by the caller. // handled by the caller.
.catchError((dynamic err, StackTrace stack) { .then(
_logger.printTrace('Echoing stdin to the licenses subprocess failed:'); (Object? socket) => socket,
_logger.printTrace('$err\n$stack'); onError: (dynamic err, StackTrace stack) {
} _logger.printError('Echoing stdin to the licenses subprocess failed:');
)); _logger.printError('$err\n$stack');
},
),
);
// Wait for stdout and stderr to be fully processed, because process.exitCode // Wait for stdout and stderr to be fully processed, because process.exitCode
// may complete first. // may complete first.
...@@ -450,8 +453,8 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -450,8 +453,8 @@ class AndroidLicenseValidator extends DoctorValidator {
_stdio.addStderrStream(process.stderr), _stdio.addStderrStream(process.stderr),
]); ]);
} on Exception catch (err, stack) { } on Exception catch (err, stack) {
_logger.printTrace('Echoing stdout or stderr from the license subprocess failed:'); _logger.printError('Echoing stdout or stderr from the license subprocess failed:');
_logger.printTrace('$err\n$stack'); _logger.printError('$err\n$stack');
} }
final int exitCode = await process.exitCode; final int exitCode = await process.exitCode;
......
...@@ -7,6 +7,7 @@ import 'package:flutter_tools/src/android/android_sdk.dart'; ...@@ -7,6 +7,7 @@ import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/android/android_studio.dart'; import 'package:flutter_tools/src/android/android_studio.dart';
import 'package:flutter_tools/src/android/android_workflow.dart'; import 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/user_messages.dart'; import 'package:flutter_tools/src/base/user_messages.dart';
...@@ -311,6 +312,37 @@ Review licenses that have not been accepted (y/N)? ...@@ -311,6 +312,37 @@ Review licenses that have not been accepted (y/N)?
expect(licenseValidator.runLicenseManager(), throwsToolExit()); expect(licenseValidator.runLicenseManager(), throwsToolExit());
}); });
testWithoutContext('runLicenseManager handles broken pipe without ArgumentError', () async {
sdk.sdkManagerPath = '/foo/bar/sdkmanager';
const String exceptionMessage = 'Write failed (OS Error: Broken pipe, errno = 32), port = 0';
const SocketException exception = SocketException(exceptionMessage);
// By using a `Socket` generic parameter, the stdin.addStream will return a `Future<Socket>`
// We are testing that our error handling properly handles futures of this type
final ThrowingStdin<Socket> fakeStdin = ThrowingStdin<Socket>(exception);
final FakeCommand licenseCommand = FakeCommand(
command: <String>[sdk.sdkManagerPath!, '--licenses'],
stdin: fakeStdin,
);
processManager.addCommand(licenseCommand);
final BufferLogger logger = BufferLogger.test();
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
androidSdk: sdk,
fileSystem: fileSystem,
processManager: processManager,
platform: FakePlatform(environment: <String, String>{'HOME': '/home/me'}),
stdio: stdio,
logger: logger,
userMessages: UserMessages(),
androidStudio: FakeAndroidStudio(),
operatingSystemUtils: FakeOperatingSystemUtils(),
);
await licenseValidator.runLicenseManager();
expect(logger.errorText, contains(exceptionMessage));
expect(processManager, hasNoRemainingExpectations);
});
testWithoutContext('runLicenseManager errors when sdkmanager fails to run', () async { testWithoutContext('runLicenseManager errors when sdkmanager fails to run', () async {
sdk.sdkManagerPath = '/foo/bar/sdkmanager'; sdk.sdkManagerPath = '/foo/bar/sdkmanager';
processManager.excludedExecutables.add('/foo/bar/sdkmanager'); processManager.excludedExecutables.add('/foo/bar/sdkmanager');
...@@ -574,3 +606,14 @@ class FakeAndroidStudio extends Fake implements AndroidStudio { ...@@ -574,3 +606,14 @@ class FakeAndroidStudio extends Fake implements AndroidStudio {
@override @override
String get javaPath => 'java'; String get javaPath => 'java';
} }
class ThrowingStdin<T> extends Fake implements IOSink {
ThrowingStdin(this.exception);
final Exception exception;
@override
Future<dynamic> addStream(Stream<List<int>> stream) {
return Future<T>.error(exception);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment