[devicelab] re-land cocoon auto-restart (#69710)
Due to #69707 the SkSL tests need the process killing logic still.
This commit is contained in:
parent
91b82347af
commit
c985fd35cd
@ -131,6 +131,9 @@ abstract class Device {
|
|||||||
/// Assumes the device doesn't have a secure unlock pattern.
|
/// Assumes the device doesn't have a secure unlock pattern.
|
||||||
Future<void> unlock();
|
Future<void> unlock();
|
||||||
|
|
||||||
|
/// Attempt to reboot the phone, if possible.
|
||||||
|
Future<void> reboot();
|
||||||
|
|
||||||
/// Emulate a tap on the touch screen.
|
/// Emulate a tap on the touch screen.
|
||||||
Future<void> tap(int x, int y);
|
Future<void> tap(int x, int y);
|
||||||
|
|
||||||
@ -575,6 +578,11 @@ class AndroidDevice extends Device {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return '$deviceId $deviceInfo';
|
return '$deviceId $deviceInfo';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> reboot() {
|
||||||
|
return adb(<String>['reboot']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IosDeviceDiscovery implements DeviceDiscovery {
|
class IosDeviceDiscovery implements DeviceDiscovery {
|
||||||
@ -740,6 +748,11 @@ class IosDevice extends Device {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> stop(String packageName) async {}
|
Future<void> stop(String packageName) async {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> reboot() {
|
||||||
|
return Process.run('idevicesyslog', <String>['reboot', '-u', deviceId]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fuchsia device.
|
/// Fuchsia device.
|
||||||
@ -783,6 +796,11 @@ class FuchsiaDevice extends Device {
|
|||||||
Stream<String> get logcat {
|
Stream<String> get logcat {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> reboot() async {
|
||||||
|
// Unsupported.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Path to the `adb` executable.
|
/// Path to the `adb` executable.
|
||||||
@ -846,6 +864,11 @@ class FakeDevice extends Device {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> stop(String packageName) async {}
|
Future<void> stop(String packageName) async {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> reboot() async {
|
||||||
|
// Unsupported.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeDeviceDiscovery implements DeviceDiscovery {
|
class FakeDeviceDiscovery implements DeviceDiscovery {
|
||||||
|
@ -12,10 +12,21 @@ import 'package:path/path.dart' as path;
|
|||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:stack_trace/stack_trace.dart';
|
import 'package:stack_trace/stack_trace.dart';
|
||||||
|
|
||||||
|
import 'adb.dart';
|
||||||
import 'running_processes.dart';
|
import 'running_processes.dart';
|
||||||
import 'task_result.dart';
|
import 'task_result.dart';
|
||||||
import 'utils.dart';
|
import 'utils.dart';
|
||||||
|
|
||||||
|
/// Identifiers for devices that should never be rebooted.
|
||||||
|
final Set<String> noRebootForbidList = <String>{
|
||||||
|
'822ef7958bba573829d85eef4df6cbdd86593730', // 32bit iPhone requires manual intervention on reboot.
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The maximum number of test runs before a device must be rebooted.
|
||||||
|
///
|
||||||
|
/// This number was chosen arbitrarily.
|
||||||
|
const int maxiumRuns = 30;
|
||||||
|
|
||||||
/// Represents a unit of work performed in the CI environment that can
|
/// Represents a unit of work performed in the CI environment that can
|
||||||
/// succeed, fail and be retried independently of others.
|
/// succeed, fail and be retried independently of others.
|
||||||
typedef TaskFunction = Future<TaskResult> Function();
|
typedef TaskFunction = Future<TaskResult> Function();
|
||||||
@ -29,7 +40,7 @@ bool _isTaskRegistered = false;
|
|||||||
///
|
///
|
||||||
/// It is OK for a [task] to perform many things. However, only one task can be
|
/// It is OK for a [task] to perform many things. However, only one task can be
|
||||||
/// registered per Dart VM.
|
/// registered per Dart VM.
|
||||||
Future<TaskResult> task(TaskFunction task) {
|
Future<TaskResult> task(TaskFunction task) async {
|
||||||
if (_isTaskRegistered)
|
if (_isTaskRegistered)
|
||||||
throw StateError('A task is already registered');
|
throw StateError('A task is already registered');
|
||||||
|
|
||||||
@ -92,15 +103,15 @@ class _TaskRunner {
|
|||||||
print('[LEAK]: ${info.commandLine} ${info.creationDate} ${info.pid} ');
|
print('[LEAK]: ${info.commandLine} ${info.creationDate} ${info.pid} ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print('enabling configs for macOS, Linux, Windows, and Web...');
|
print('enabling configs for macOS, Linux, Windows, and Web...');
|
||||||
final int configResult = await exec(path.join(flutterDirectory.path, 'bin', 'flutter'), <String>[
|
final int configResult = await exec(path.join(flutterDirectory.path, 'bin', 'flutter'), <String>[
|
||||||
'config',
|
'config',
|
||||||
|
'-v',
|
||||||
'--enable-macos-desktop',
|
'--enable-macos-desktop',
|
||||||
'--enable-windows-desktop',
|
'--enable-windows-desktop',
|
||||||
'--enable-linux-desktop',
|
'--enable-linux-desktop',
|
||||||
'--enable-web'
|
'--enable-web'
|
||||||
]);
|
], canFail: true);
|
||||||
if (configResult != 0) {
|
if (configResult != 0) {
|
||||||
print('Failed to enable configuration, tasks may not run.');
|
print('Failed to enable configuration, tasks may not run.');
|
||||||
}
|
}
|
||||||
@ -129,14 +140,6 @@ class _TaskRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Set<RunningProcessInfo> allEndProcesses = await getRunningProcesses().toSet();
|
|
||||||
for (final RunningProcessInfo info in allEndProcesses) {
|
|
||||||
if (allProcesses.contains(info)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
print('[LEAK]: ${info.commandLine} ${info.creationDate} ${info.pid} ');
|
|
||||||
}
|
|
||||||
|
|
||||||
_completer.complete(result);
|
_completer.complete(result);
|
||||||
return result;
|
return result;
|
||||||
} on TimeoutException catch (err, stackTrace) {
|
} on TimeoutException catch (err, stackTrace) {
|
||||||
@ -145,12 +148,42 @@ class _TaskRunner {
|
|||||||
print(stackTrace);
|
print(stackTrace);
|
||||||
return TaskResult.failure('Task timed out after $taskTimeout');
|
return TaskResult.failure('Task timed out after $taskTimeout');
|
||||||
} finally {
|
} finally {
|
||||||
print('Cleaning up after task...');
|
await checkForRebootRequired();
|
||||||
await forceQuitRunningProcesses();
|
await forceQuitRunningProcesses();
|
||||||
_closeKeepAlivePort();
|
_closeKeepAlivePort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> checkForRebootRequired() async {
|
||||||
|
print('Checking for reboot');
|
||||||
|
try {
|
||||||
|
final Device device = await devices.workingDevice;
|
||||||
|
if (noRebootForbidList.contains(device.deviceId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final File rebootFile = _rebootFile();
|
||||||
|
int runCount;
|
||||||
|
if (rebootFile.existsSync()) {
|
||||||
|
runCount = int.tryParse(rebootFile.readAsStringSync().trim());
|
||||||
|
} else {
|
||||||
|
runCount = 0;
|
||||||
|
}
|
||||||
|
if (runCount < maxiumRuns) {
|
||||||
|
rebootFile
|
||||||
|
..createSync()
|
||||||
|
..writeAsStringSync((runCount + 1).toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rebootFile.deleteSync();
|
||||||
|
print('rebooting');
|
||||||
|
await device.reboot();
|
||||||
|
} on TimeoutException {
|
||||||
|
// Could not find device in order to reboot.
|
||||||
|
} on DeviceException {
|
||||||
|
// No attached device needed to reboot.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Causes the Dart VM to stay alive until a request to run the task is
|
/// Causes the Dart VM to stay alive until a request to run the task is
|
||||||
/// received via the VM service protocol.
|
/// received via the VM service protocol.
|
||||||
void keepVmAliveUntilTaskRunRequested() {
|
void keepVmAliveUntilTaskRunRequested() {
|
||||||
@ -199,3 +232,13 @@ class _TaskRunner {
|
|||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File _rebootFile() {
|
||||||
|
if (Platform.isLinux || Platform.isMacOS) {
|
||||||
|
return File(path.join(Platform.environment['HOME'], '.reboot-count'));
|
||||||
|
}
|
||||||
|
if (!Platform.isWindows) {
|
||||||
|
throw StateError('Unexpected platform ${Platform.operatingSystem}');
|
||||||
|
}
|
||||||
|
return File(path.join(Platform.environment['USERPROFILE'], '.reboot-count'));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user