web testing: use "--no-sandbox" and implement some cleanup logic (#10058)
diff --git a/packages/devtools_app/webdriver_test/web_compiler_test.dart b/packages/devtools_app/webdriver_test/web_compiler_test.dart index 4ba497d..db60bc6 100644 --- a/packages/devtools_app/webdriver_test/web_compiler_test.dart +++ b/packages/devtools_app/webdriver_test/web_compiler_test.dart
@@ -14,52 +14,88 @@ import '../integration_test/test_infra/run/run_test.dart'; void main() { - late Process devtoolsProcess; - late WebDriver driver; + ChromeDriver? chromedriver; + Process? devtoolsProcess; + WebDriver? driver; late String devToolsServerAddress; const serverStartupTimeout = Duration(minutes: 1); + Future<void> cleanUp() async { + // Close the browser session (ignore errors if it already crashed). + try { + await driver?.quit(); + } catch (e) { + // ignore: avoid_print, this is test code. + print('Warning: Failed to quit WebDriver cleanly: $e'); + } + + // Stop background processes. + devtoolsProcess?.kill(); + try { + await chromedriver?.stop(debugLogging: true); + } catch (e) { + // ignore: avoid_print, this is test code. + print('Warning: Failed to stop chromedriver cleanly: $e'); + } + + // Reset state. + driver = null; + devtoolsProcess = null; + chromedriver = null; + } + setUpAll(() async { - await ChromeDriver().start(debugLogging: true); + try { + chromedriver = ChromeDriver(); + await chromedriver!.start(debugLogging: true); - // TODO(https://github.com/flutter/devtools/issues/9197): Launch the - // DevTools server from source. - // For now, this test uses the version of DevTools bundled in the Dart SDK - // because building and running from source is too prohibitive until - // DevTools is moved into the Dart SDK. See issue for details. - devtoolsProcess = await startDevToolsServer(); - devToolsServerAddress = await listenForDevToolsAddress( - devtoolsProcess, - timeout: serverStartupTimeout, - ); + // TODO(https://github.com/flutter/devtools/issues/9197): Launch the + // DevTools server from source. + // For now, this test uses the version of DevTools bundled in the Dart SDK + // because building and running from source is too prohibitive until + // DevTools is moved into the Dart SDK. See issue for details. + final startedDevToolsProcess = await startDevToolsServer(); + devtoolsProcess = startedDevToolsProcess; + devToolsServerAddress = await listenForDevToolsAddress( + startedDevToolsProcess, + timeout: serverStartupTimeout, + ); - driver = await createDriver( - uri: Uri.parse('http://127.0.0.1:${ChromeDriver.port}'), - desired: { - ...Capabilities.chrome, - Capabilities.chromeOptions: { - 'binary': ?Platform.environment['CHROME_EXECUTABLE'], - 'args': [ - '--headless', - // Explicitly enable SwiftShader on headless Linux and Windows VMs - // without a hardware GPU so WebGL is available for the skwasm - // renderer. See https://github.com/flutter/devtools/issues/10032. - if (Platform.isLinux || Platform.isWindows) ...[ - '--use-gl=angle', - '--use-angle=swiftshader', - '--enable-unsafe-swiftshader', - '--disable-gpu-sandbox', + driver = await createDriver( + uri: Uri.parse('http://127.0.0.1:${ChromeDriver.port}'), + desired: { + ...Capabilities.chrome, + Capabilities.chromeOptions: { + 'binary': ?Platform.environment['CHROME_EXECUTABLE'], + 'args': [ + '--headless', + // Apparently, on Ubuntu 24.04+, AppArmor restricts unprivileged user + // namespaces, so this Chrome must be run with '--no-sandbox'. + // Flutter's `ChromiumLauncher.launch` similarly adds '--no-sandbox' + // when headless. + if (Platform.isLinux) '--no-sandbox', + // Explicitly enable SwiftShader on headless Linux and Windows VMs + // without a hardware GPU so WebGL is available for the skwasm + // renderer. See https://github.com/flutter/devtools/issues/10032. + if (Platform.isLinux || Platform.isWindows) ...[ + '--use-gl=angle', + '--use-angle=swiftshader', + '--enable-unsafe-swiftshader', + '--disable-gpu-sandbox', + ], ], - ], + }, }, - }, - ); + ); + } catch (_) { + await cleanUp(); + rethrow; + } }); tearDownAll(() async { - await driver.quit(); - devtoolsProcess.kill(); + await cleanUp(); }); /// Reads the "flt-renderer" attribute on the body element. @@ -68,7 +104,7 @@ /// https://github.com/flutter/devtools/pull/9406#pullrequestreview-3142210823 Future<String?> readRendererAttribute() => retryAsync<String?>( () async { - final body = await driver.findElement(const By.tagName('body')); + final body = await driver!.findElement(const By.tagName('body')); return body.attributes['flt-renderer']; }, condition: (result) => result != null, @@ -80,7 +116,7 @@ timeout: longTimeout, () async { // Open the DevTools URL with ?compiler=wasm. - await driver.get( + await driver!.get( _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'wasm'), ); @@ -88,7 +124,7 @@ expect(await readRendererAttribute(), equals('skwasm')); // Open the DevTools URL with ?compiler=js. - await driver.get( + await driver!.get( _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'js'), );