@@ -7,6 +7,7 @@ import 'package:flutter_tools/src/android/android_sdk.dart';
77import 'package:flutter_tools/src/android/android_studio.dart' ;
88import 'package:flutter_tools/src/android/android_workflow.dart' ;
99import 'package:flutter_tools/src/base/file_system.dart' ;
10+ import 'package:flutter_tools/src/base/io.dart' ;
1011import 'package:flutter_tools/src/base/logger.dart' ;
1112import 'package:flutter_tools/src/base/platform.dart' ;
1213import 'package:flutter_tools/src/base/user_messages.dart' ;
@@ -311,6 +312,37 @@ Review licenses that have not been accepted (y/N)?
311312 expect (licenseValidator.runLicenseManager (), throwsToolExit ());
312313 });
313314
315+ testWithoutContext ('runLicenseManager handles broken pipe without ArgumentError' , () async {
316+ sdk.sdkManagerPath = '/foo/bar/sdkmanager' ;
317+ const String exceptionMessage = 'Write failed (OS Error: Broken pipe, errno = 32), port = 0' ;
318+ const SocketException exception = SocketException (exceptionMessage);
319+ // By using a `Socket` generic parameter, the stdin.addStream will return a `Future<Socket>`
320+ // We are testing that our error handling properly handles futures of this type
321+ final ThrowingStdin <Socket > fakeStdin = ThrowingStdin <Socket >(exception);
322+ final FakeCommand licenseCommand = FakeCommand (
323+ command: < String > [sdk.sdkManagerPath! , '--licenses' ],
324+ stdin: fakeStdin,
325+ );
326+ processManager.addCommand (licenseCommand);
327+ final BufferLogger logger = BufferLogger .test ();
328+
329+ final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator (
330+ androidSdk: sdk,
331+ fileSystem: fileSystem,
332+ processManager: processManager,
333+ platform: FakePlatform (environment: < String , String > {'HOME' : '/home/me' }),
334+ stdio: stdio,
335+ logger: logger,
336+ userMessages: UserMessages (),
337+ androidStudio: FakeAndroidStudio (),
338+ operatingSystemUtils: FakeOperatingSystemUtils (),
339+ );
340+
341+ await licenseValidator.runLicenseManager ();
342+ expect (logger.errorText, contains (exceptionMessage));
343+ expect (processManager, hasNoRemainingExpectations);
344+ });
345+
314346 testWithoutContext ('runLicenseManager errors when sdkmanager fails to run' , () async {
315347 sdk.sdkManagerPath = '/foo/bar/sdkmanager' ;
316348 processManager.excludedExecutables.add ('/foo/bar/sdkmanager' );
@@ -574,3 +606,14 @@ class FakeAndroidStudio extends Fake implements AndroidStudio {
574606 @override
575607 String get javaPath => 'java' ;
576608}
609+
610+ class ThrowingStdin <T > extends Fake implements IOSink {
611+ ThrowingStdin (this .exception);
612+
613+ final Exception exception;
614+
615+ @override
616+ Future <dynamic > addStream (Stream <List <int >> stream) {
617+ return Future <T >.error (exception);
618+ }
619+ }
0 commit comments