Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6245149

Browse files
author
Nurhan Turgut
authored
[web] using pkill to quit safari (#17533)
* adding an apple script to quit safari * making changes to utils and adding cleanup after unit tests failed * switch saai quit to pkill instead of applescript * adding toolexception * adding a cleanup function option to felt. * removing unnecassary await's added for the previos version of the PR * removing unnecassary async * fix analyze error
1 parent f6b8eda commit 6245149

File tree

8 files changed

+124
-67
lines changed

8 files changed

+124
-67
lines changed

lib/web_ui/dev/chrome_installer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'package:yaml/yaml.dart';
1313

1414
import 'common.dart';
1515
import 'environment.dart';
16+
import 'exceptions.dart';
1617

1718
class ChromeArgParser extends BrowserArgParser {
1819
static final ChromeArgParser _singletonInstance = ChromeArgParser._();

lib/web_ui/dev/common.dart

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,6 @@ const int kMaxScreenshotWidth = 1024;
1818
const int kMaxScreenshotHeight = 1024;
1919
const double kMaxDiffRateFailure = 0.28 / 100; // 0.28%
2020

21-
class BrowserInstallerException implements Exception {
22-
BrowserInstallerException(this.message);
23-
24-
final String message;
25-
26-
@override
27-
String toString() => message;
28-
}
29-
30-
class DriverException implements Exception {
31-
DriverException(this.message);
32-
33-
final String message;
34-
35-
@override
36-
String toString() => message;
37-
}
38-
3921
abstract class PlatformBinding {
4022
static PlatformBinding get instance {
4123
if (_instance == null) {
@@ -250,14 +232,3 @@ class DevNull implements StringSink {
250232
}
251233

252234
bool get isCirrus => io.Platform.environment['CIRRUS_CI'] == 'true';
253-
254-
/// There might be proccesses started during the tests.
255-
///
256-
/// Use this list to store those Processes, for cleaning up before shutdown.
257-
final List<io.Process> processesToCleanUp = List<io.Process>();
258-
259-
/// There might be temporary directories created during the tests.
260-
///
261-
/// Use this list to store those directories and for deleteing them before
262-
/// shutdown.
263-
final List<io.Directory> temporaryDirectories = List<io.Directory>();

lib/web_ui/dev/environment.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import 'dart:io' as io;
77
import 'package:path/path.dart' as pathlib;
88

9+
import 'exceptions.dart';
10+
911
/// Contains various environment variables, such as common file paths and command-line options.
1012
Environment get environment {
1113
_environment ??= Environment();
@@ -26,8 +28,7 @@ class Environment {
2628

2729
for (io.Directory expectedDirectory in <io.Directory>[engineSrcDir, outDir, hostDebugUnoptDir, dartSdkDir, webUiRootDir]) {
2830
if (!expectedDirectory.existsSync()) {
29-
io.stderr.writeln('$expectedDirectory does not exist.');
30-
io.exit(1);
31+
throw ToolException('$expectedDirectory does not exist.');
3132
}
3233
}
3334

lib/web_ui/dev/exceptions.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
class BrowserInstallerException implements Exception {
6+
BrowserInstallerException(this.message);
7+
8+
final String message;
9+
10+
@override
11+
String toString() => message;
12+
}
13+
14+
class DriverException implements Exception {
15+
DriverException(this.message);
16+
17+
final String message;
18+
19+
@override
20+
String toString() => message;
21+
}
22+
23+
class ToolException implements Exception {
24+
ToolException(this.message);
25+
26+
final String message;
27+
28+
@override
29+
String toString() => message;
30+
}

lib/web_ui/dev/felt.dart

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import 'package:args/command_runner.dart';
99

1010
import 'build.dart';
1111
import 'clean.dart';
12-
import 'common.dart';
1312
import 'licenses.dart';
13+
import 'exceptions.dart';
1414
import 'test_runner.dart';
15+
import 'utils.dart';
1516

1617
CommandRunner runner = CommandRunner<bool>(
1718
'felt',
@@ -31,50 +32,46 @@ void main(List<String> args) async {
3132

3233
_listenToShutdownSignals();
3334

35+
int exitCode = -1;
3436
try {
3537
final bool result = (await runner.run(args)) as bool;
3638
if (result == false) {
3739
print('Sub-command returned false: `${args.join(' ')}`');
38-
_cleanup();
39-
io.exit(1);
40+
await cleanup();
41+
exitCode = 1;
4042
}
4143
} on UsageException catch (e) {
4244
print(e);
43-
io.exit(64); // Exit code 64 indicates a usage error.
45+
exitCode = 64; // Exit code 64 indicates a usage error.
46+
} on ToolException catch (e) {
47+
io.stderr.writeln(e.message);
48+
exitCode = 1;
4449
} catch (e) {
4550
rethrow;
4651
} finally {
47-
_cleanup();
52+
await cleanup();
53+
// The exit code is changed by one of the branches.
54+
if(exitCode != -1) {
55+
io.exit(exitCode);
56+
}
4857
}
4958

5059
// Sometimes the Dart VM refuses to quit.
5160
io.exit(io.exitCode);
5261
}
5362

54-
void _cleanup() {
55-
// Cleanup remaining processes if any.
56-
if (processesToCleanUp.length > 0) {
57-
for (io.Process process in processesToCleanUp) {
58-
process.kill();
59-
}
60-
}
61-
// Delete temporary directories.
62-
if (temporaryDirectories.length > 0) {
63-
for (io.Directory directory in temporaryDirectories) {
64-
directory.deleteSync(recursive: true);
65-
}
66-
}
67-
}
68-
69-
void _listenToShutdownSignals() {
70-
io.ProcessSignal.sigint.watch().listen((_) {
63+
void _listenToShutdownSignals() async {
64+
io.ProcessSignal.sigint.watch().listen((_) async {
7165
print('Received SIGINT. Shutting down.');
66+
await cleanup();
7267
io.exit(1);
7368
});
69+
7470
// SIGTERM signals are not generated under Windows.
7571
// See https://docs.microsoft.com/en-us/previous-versions/xdkz3x12(v%3Dvs.140)
7672
if (!io.Platform.isWindows) {
77-
io.ProcessSignal.sigterm.watch().listen((_) {
73+
io.ProcessSignal.sigterm.watch().listen((_) async {
74+
await cleanup();
7875
print('Received SIGTERM. Shutting down.');
7976
io.exit(1);
8077
});

lib/web_ui/dev/firefox_installer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:yaml/yaml.dart';
1212

1313
import 'common.dart';
1414
import 'environment.dart';
15+
import 'exceptions.dart';
1516

1617
class FirefoxArgParser extends BrowserArgParser {
1718
static final FirefoxArgParser _singletonInstance = FirefoxArgParser._();

lib/web_ui/dev/test_runner.dart

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_im
1515
import 'package:test_core/src/executable.dart'
1616
as test; // ignore: implementation_imports
1717

18+
import 'exceptions.dart';
1819
import 'integration_tests_manager.dart';
1920
import 'supported_browsers.dart';
2021
import 'test_platform.dart';
@@ -151,6 +152,26 @@ class TestCommand extends Command<bool> with ArgUtils {
151152
}
152153

153154
await _buildTests(targets: targetFiles);
155+
156+
// Many tabs will be left open after Safari runs, quit Safari during
157+
// cleanup.
158+
if (browser == 'safari') {
159+
cleanupCallbacks.add(() async {
160+
// Only close Safari if felt is running in CI environments. Do not close
161+
// Safari for the local testing.
162+
if (io.Platform.environment['LUCI_CONTEXT'] != null || isCirrus) {
163+
print('INFO: Safari tests ran. Quit Safari.');
164+
await runProcess(
165+
'sudo',
166+
['pkill', '-lf', 'Safari'],
167+
workingDirectory: environment.webUiRootDir.path,
168+
);
169+
} else {
170+
print('INFO: Safari tests ran. Please quit Safari tabs.');
171+
}
172+
});
173+
}
174+
154175
if (runAllTests) {
155176
await _runAllTests();
156177
} else {
@@ -179,7 +200,7 @@ class TestCommand extends Command<bool> with ArgUtils {
179200
bool get runAllTests => targets.isEmpty;
180201

181202
/// The name of the browser to run tests in.
182-
String get browser => stringArg('browser');
203+
String get browser => (argResults != null) ? stringArg('browser') : 'chrome';
183204

184205
/// Whether [browser] is set to "chrome".
185206
bool get isChrome => browser == 'chrome';
@@ -275,8 +296,7 @@ class TestCommand extends Command<bool> with ArgUtils {
275296

276297
void _checkExitCode() {
277298
if (io.exitCode != 0) {
278-
io.stderr.writeln('Process exited with exit code ${io.exitCode}.');
279-
io.exit(1);
299+
throw ToolException('Process exited with exit code ${io.exitCode}.');
280300
}
281301
}
282302

@@ -290,9 +310,8 @@ class TestCommand extends Command<bool> with ArgUtils {
290310
);
291311

292312
if (exitCode != 0) {
293-
io.stderr
294-
.writeln('Failed to run pub get. Exited with exit code $exitCode');
295-
io.exit(1);
313+
throw ToolException(
314+
'Failed to run pub get. Exited with exit code $exitCode');
296315
}
297316
}
298317

@@ -333,9 +352,8 @@ class TestCommand extends Command<bool> with ArgUtils {
333352
);
334353

335354
if (exitCode != 0) {
336-
io.stderr.writeln(
337-
'Failed to compile ${hostDartFile.path}. Compiler exited with exit code $exitCode');
338-
io.exit(1);
355+
throw ToolException('Failed to compile ${hostDartFile.path}. Compiler '
356+
'exited with exit code $exitCode');
339357
}
340358

341359
// Record the timestamp to avoid rebuilding unless the file changes.
@@ -363,9 +381,8 @@ class TestCommand extends Command<bool> with ArgUtils {
363381
);
364382

365383
if (exitCode != 0) {
366-
io.stderr.writeln(
384+
throw ToolException(
367385
'Failed to compile tests. Compiler exited with exit code $exitCode');
368-
io.exit(1);
369386
}
370387
}
371388

lib/web_ui/dev/utils.dart

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:args/command_runner.dart';
1010
import 'package:meta/meta.dart';
1111
import 'package:path/path.dart' as path;
1212

13-
import 'common.dart';
1413
import 'environment.dart';
1514

1615
class FilePath {
@@ -130,7 +129,8 @@ class ProcessException implements Exception {
130129
message
131130
..writeln(description)
132131
..writeln('Command: $executable ${arguments.join(' ')}')
133-
..writeln('Working directory: ${workingDirectory ?? io.Directory.current.path}')
132+
..writeln(
133+
'Working directory: ${workingDirectory ?? io.Directory.current.path}')
134134
..writeln('Exit code: $exitCode');
135135
return '$message';
136136
}
@@ -161,3 +161,42 @@ mixin ArgUtils<T> on Command<T> {
161161
return value;
162162
}
163163
}
164+
165+
/// There might be proccesses started during the tests.
166+
///
167+
/// Use this list to store those Processes, for cleaning up before shutdown.
168+
final List<io.Process> processesToCleanUp = List<io.Process>();
169+
170+
/// There might be temporary directories created during the tests.
171+
///
172+
/// Use this list to store those directories and for deleteing them before
173+
/// shutdown.
174+
final List<io.Directory> temporaryDirectories = List<io.Directory>();
175+
176+
typedef AsyncCallback = Future<void> Function();
177+
178+
/// There might be additional cleanup needs to be done after the tools ran.
179+
///
180+
/// Add these operations here to make sure that they will run before felt
181+
/// exit.
182+
final List<AsyncCallback> cleanupCallbacks = List<AsyncCallback>();
183+
184+
/// Cleanup the remaning processes, close open browsers, delete temp files.
185+
void cleanup() async {
186+
// Cleanup remaining processes if any.
187+
if (processesToCleanUp.length > 0) {
188+
for (io.Process process in processesToCleanUp) {
189+
process.kill();
190+
}
191+
}
192+
// Delete temporary directories.
193+
if (temporaryDirectories.length > 0) {
194+
for (io.Directory directory in temporaryDirectories) {
195+
directory.deleteSync(recursive: true);
196+
}
197+
}
198+
199+
cleanupCallbacks.forEach((element) {
200+
element.call();
201+
});
202+
}

0 commit comments

Comments
 (0)