flutter/dev/devicelab/test/adb_test.dart
Michael Goderbauer 5491c8c146
Auto-format Framework (#160545)
This auto-formats all *.dart files in the repository outside of the
`engine` subdirectory and enforces that these files stay formatted with
a presubmit check.

**Reviewers:** Please carefully review all the commits except for the
one titled "formatted". The "formatted" commit was auto-generated by
running `dev/tools/format.sh -a -f`. The other commits were hand-crafted
to prepare the repo for the formatting change. I recommend reviewing the
commits one-by-one via the "Commits" tab and avoiding Github's "Files
changed" tab as it will likely slow down your browser because of the
size of this PR.

---------

Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
2024-12-19 20:06:21 +00:00

453 lines
12 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:collection/collection.dart' show ListEquality, MapEquality;
import 'package:flutter_devicelab/framework/devices.dart';
import 'package:meta/meta.dart';
import 'common.dart';
void main() {
group('device', () {
late Device device;
setUp(() {
FakeDevice.resetLog();
device = FakeDevice(deviceId: 'fakeDeviceId');
});
tearDown(() {});
group('cpu check', () {
test('arm64', () async {
FakeDevice.pretendArm64();
final AndroidDevice androidDevice = device as AndroidDevice;
expect(await androidDevice.isArm64(), isTrue);
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'getprop', arguments: <String>['ro.product.cpu.abi']),
]);
});
});
group('isAwake/isAsleep', () {
test('reads Awake', () async {
FakeDevice.pretendAwake();
expect(await device.isAwake(), isTrue);
expect(await device.isAsleep(), isFalse);
});
test('reads Awake - samsung devices', () async {
FakeDevice.pretendAwakeSamsung();
expect(await device.isAwake(), isTrue);
expect(await device.isAsleep(), isFalse);
});
test('reads Asleep', () async {
FakeDevice.pretendAsleep();
expect(await device.isAwake(), isFalse);
expect(await device.isAsleep(), isTrue);
});
});
group('togglePower', () {
test('sends power event', () async {
await device.togglePower();
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'input', arguments: <String>['keyevent', '26']),
]);
});
});
group('wakeUp', () {
test('when awake', () async {
FakeDevice.pretendAwake();
await device.wakeUp();
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'dumpsys', arguments: <String>['power']),
]);
});
test('when asleep', () async {
FakeDevice.pretendAsleep();
await device.wakeUp();
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'dumpsys', arguments: <String>['power']),
cmd(command: 'input', arguments: <String>['keyevent', '26']),
]);
});
});
group('sendToSleep', () {
test('when asleep', () async {
FakeDevice.pretendAsleep();
await device.sendToSleep();
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'dumpsys', arguments: <String>['power']),
]);
});
test('when awake', () async {
FakeDevice.pretendAwake();
await device.sendToSleep();
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'dumpsys', arguments: <String>['power']),
cmd(command: 'input', arguments: <String>['keyevent', '26']),
]);
});
});
group('unlock', () {
test('sends unlock event', () async {
FakeDevice.pretendAwake();
await device.unlock();
expectLog(<CommandArgs>[
cmd(
command: 'getprop',
arguments: <String>[
'ro.bootimage.build.fingerprint',
';',
'getprop',
'ro.build.version.release',
';',
'getprop',
'ro.build.version.sdk',
],
),
cmd(command: 'dumpsys', arguments: <String>['power']),
cmd(command: 'input', arguments: <String>['keyevent', '82']),
]);
});
});
group('adb', () {
test('tap', () async {
FakeDevice.resetLog();
await device.tap(100, 200);
expectLog(<CommandArgs>[
cmd(command: 'input', arguments: <String>['tap', '100', '200']),
]);
});
test('awaitDevice', () async {
FakeDevice.resetLog();
// The expected value from `adb shell getprop sys.boot_completed`
FakeDevice.output = '1';
await device.awaitDevice();
expectLog(<CommandArgs>[
cmd(
command: 'adb',
environment: <String, String>{FakeDevice.canFailKey: 'false'},
arguments: <String>['-s', device.deviceId, 'wait-for-device'],
),
cmd(
command: 'adb',
environment: <String, String>{FakeDevice.canFailKey: 'false'},
arguments: <String>['-s', device.deviceId, 'shell', 'getprop sys.boot_completed'],
),
]);
});
test('reboot', () async {
FakeDevice.resetLog();
await device.reboot();
expectLog(<CommandArgs>[
cmd(
command: 'adb',
environment: <String, String>{FakeDevice.canFailKey: 'false'},
arguments: <String>['-s', device.deviceId, 'reboot'],
),
]);
});
test('clearLog', () async {
FakeDevice.resetLog();
await device.clearLogs();
expectLog(<CommandArgs>[
cmd(
command: 'adb',
environment: <String, String>{FakeDevice.canFailKey: 'true'},
arguments: <String>['-s', device.deviceId, 'logcat', '-c'],
),
]);
});
test('startLoggingToSink calls adb', () async {
FakeDevice.resetLog();
await device.startLoggingToSink(IOSink(_MemoryIOSink()));
expectLog(<CommandArgs>[
cmd(
command: 'adb',
environment: <String, String>{FakeDevice.canFailKey: 'true'},
arguments: <String>['-s', device.deviceId, 'logcat', '--clear'],
),
]);
});
});
});
}
void expectLog(List<CommandArgs> log) {
expect(FakeDevice.commandLog, log);
}
CommandArgs cmd({
required String command,
List<String>? arguments,
Map<String, String>? environment,
}) {
return CommandArgs(command: command, arguments: arguments, environment: environment);
}
@immutable
class CommandArgs {
const CommandArgs({required this.command, this.arguments, this.environment});
final String command;
final List<String>? arguments;
final Map<String, String>? environment;
@override
String toString() =>
'CommandArgs(command: $command, arguments: $arguments, environment: $environment)';
@override
bool operator ==(Object other) {
if (other.runtimeType != CommandArgs) {
return false;
}
return other is CommandArgs &&
other.command == command &&
const ListEquality<String>().equals(other.arguments, arguments) &&
const MapEquality<String, String>().equals(other.environment, environment);
}
@override
int get hashCode {
return Object.hash(
command,
Object.hashAll(arguments ?? const <String>[]),
Object.hashAllUnordered(environment?.keys ?? const <String>[]),
Object.hashAllUnordered(environment?.values ?? const <String>[]),
);
}
}
class FakeDevice extends AndroidDevice {
FakeDevice({required super.deviceId});
static const String canFailKey = 'canFail';
static String output = '';
static List<CommandArgs> commandLog = <CommandArgs>[];
static void resetLog() {
commandLog.clear();
}
static void pretendAwake() {
output = '''
mWakefulness=Awake
''';
}
static void pretendAwakeSamsung() {
output = '''
getWakefulnessLocked()=Awake
''';
}
static void pretendAsleep() {
output = '''
mWakefulness=Asleep
''';
}
static void pretendArm64() {
output = '''
arm64
''';
}
@override
Future<String> adb(
List<String> arguments, {
Map<String, String>? environment,
bool silent = false,
bool canFail = false,
}) async {
environment ??= <String, String>{};
commandLog.add(
CommandArgs(
command: 'adb',
// ignore: prefer_spread_collections
arguments: <String>['-s', deviceId]..addAll(arguments),
environment: environment..putIfAbsent('canFail', () => '$canFail'),
),
);
return output;
}
@override
Future<String> shellEval(
String command,
List<String> arguments, {
Map<String, String>? environment,
bool silent = false,
}) async {
commandLog.add(CommandArgs(command: command, arguments: arguments, environment: environment));
return output;
}
@override
Future<void> shellExec(
String command,
List<String> arguments, {
Map<String, String>? environment,
bool silent = false,
}) async {
commandLog.add(CommandArgs(command: command, arguments: arguments, environment: environment));
}
}
/// An IOSink that collects whatever is written to it.
/// Inspired by packages/flutter_tools/lib/src/base/net.dart
class _MemoryIOSink implements IOSink {
@override
Encoding encoding = utf8;
final BytesBuilder writes = BytesBuilder(copy: false);
@override
void add(List<int> data) {
writes.add(data);
}
@override
Future<void> addStream(Stream<List<int>> stream) {
final Completer<void> completer = Completer<void>();
stream.listen(add).onDone(completer.complete);
return completer.future;
}
@override
void writeCharCode(int charCode) {
add(<int>[charCode]);
}
@override
void write(Object? obj) {
add(encoding.encode('$obj'));
}
@override
void writeln([Object? obj = '']) {
add(encoding.encode('$obj\n'));
}
@override
void writeAll(Iterable<dynamic> objects, [String separator = '']) {
bool addSeparator = false;
for (final dynamic object in objects) {
if (addSeparator) {
write(separator);
}
write(object);
addSeparator = true;
}
}
@override
void addError(dynamic error, [StackTrace? stackTrace]) {
throw UnimplementedError();
}
@override
Future<void> get done => close();
@override
Future<void> close() async {}
@override
Future<void> flush() async {}
}