add HttpException to the list of handled exceptions within ResidentWebRunner::run (#153527)

Resolves https://github.com/flutter/flutter/issues/153298, a major crasher of the flutter tool. I plan on cherry-picking this change.

In `ResidentWebRunner::run`, many connection-related exceptions are caught, logged, and have `ToolExit`s thrown in their place ([code](d23be7a07d/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart (L370-L385)), [PR that introduced this](https://github.com/flutter/flutter/pull/50895)). However, `HttpException` is not included in this list. See https://github.com/flutter/flutter/issues/153298#issuecomment-2290900158 for details if interested.
This commit is contained in:
Andrew Kolos 2024-08-16 09:40:19 -07:00 committed by GitHub
parent a0c04534f5
commit 080928dda3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 1 deletions

View File

@ -383,6 +383,10 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
appFailedToStart();
_logger.printError('$error', stackTrace: stackTrace);
throwToolExit(kExitMessage);
} on HttpException catch (error, stackTrace) {
appFailedToStart();
_logger.printError('$error', stackTrace: stackTrace);
throwToolExit(kExitMessage);
} on Exception {
appFailedToStart();
rethrow;

View File

@ -1317,6 +1317,59 @@ flutter:
ProcessManager: () => processManager,
});
testUsingContext('Turns HttpException from ChromeTab::connect into ToolExit', () async {
final BufferLogger logger = BufferLogger.test();
final ResidentRunner residentWebRunner = setUpResidentRunner(
flutterDevice,
logger: logger,
);
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
setupMocks();
final FakeChromeConnection chromeConnection = FakeChromeConnection();
final TestChromiumLauncher chromiumLauncher = TestChromiumLauncher();
final FakeProcess process = FakeProcess();
final Chromium chrome = Chromium(
1,
chromeConnection,
chromiumLauncher: chromiumLauncher,
process: process,
logger: logger,
);
chromiumLauncher.setInstance(chrome);
flutterDevice.device = GoogleChromeDevice(
fileSystem: fileSystem,
chromiumLauncher: chromiumLauncher,
logger: logger,
platform: FakePlatform(),
processManager: FakeProcessManager.any(),
);
webDevFS.baseUri = Uri.parse('http://localhost:8765/app/');
final FakeChromeTab chromeTab = FakeChromeTab(
'index.html',
connectException: HttpException(
'Connection closed before full header was received',
uri: Uri(
path: 'http://localhost:50094/devtools/page/3036A94908353E86E183B6A40F54104B',
),
),
);
chromeConnection.tabs.add(chromeTab);
await expectLater(
residentWebRunner.run,
throwsToolExit(
message: 'Failed to establish connection with the application instance in Chrome.',
),
);
expect(logger.errorText, contains('HttpException'));
expect(fakeVmServiceHost.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('Successfully turns AppConnectionException into ToolExit',
() async {
final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
@ -1596,14 +1649,21 @@ class FakeChromeConnection extends Fake implements ChromeConnection {
}
class FakeChromeTab extends Fake implements ChromeTab {
FakeChromeTab(this.url);
FakeChromeTab(this.url, {
Exception? connectException,
}): _connectException = connectException;
@override
final String url;
final Exception? _connectException;
final FakeWipConnection connection = FakeWipConnection();
@override
Future<WipConnection> connect({Function? onError}) async {
if (_connectException != null) {
throw _connectException;
}
return connection;
}
}