blob: 04182a48a26ed00ef9c91b0af73998945dd30f0c [file] [log] [blame]
// Copyright 2016 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 'package:test/test.dart';
import 'package:collection/collection.dart';
import 'package:cocoon_agent/src/adb.dart';
import 'package:cocoon_agent/src/utils.dart';
void main() {
group('AndroidDeviceDiscovery', () {
FakeAndroidDeviceDiscovery deviceDiscovery;
setUp(() {
deviceDiscovery = FakeAndroidDeviceDiscovery();
});
test('deviceDiscovery no retries', () async {
deviceDiscovery.outputs = <dynamic>['List of devices attached'];
expect(await deviceDiscovery.discoverDevices(), isEmpty);
StringBuffer sb = new StringBuffer();
sb.writeln('List of devices attached');
sb.writeln('ZY223JQNMR device');
deviceDiscovery.outputs = <dynamic>[sb.toString()];
List<Device> devices = await deviceDiscovery.discoverDevices();
expect(devices.length, equals(1));
expect(devices[0].deviceId, equals('ZY223JQNMR'));
});
test('deviceDiscovery retries', () async {
StringBuffer sb = new StringBuffer();
sb.writeln('List of devices attached');
sb.writeln('ZY223JQNMR device');
deviceDiscovery.outputs = <dynamic>[
new TimeoutException('a'),
new TimeoutException('b'),
sb.toString()
];
List<Device> devices =
await deviceDiscovery.discoverDevices(retriesDelayMs: 1);
expect(devices.length, equals(1));
expect(devices[0].deviceId, equals('ZY223JQNMR'));
});
test('deviceDiscovery fails', () async {
deviceDiscovery.outputs = <dynamic>[
new TimeoutException('a'),
new TimeoutException('b'),
new TimeoutException('c')
];
expect(() => deviceDiscovery.discoverDevices(retriesDelayMs: 1),
throwsA(TypeMatcher<TimeoutException>()));
});
});
group('Android device', () {
AndroidDevice device;
setUp(() {
FakeDevice.resetLog();
device = null;
device = FakeDevice();
});
tearDown(() {});
group('isAwake/isAsleep', () {
test('reads Awake', () async {
FakeDevice.pretendAwake();
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([
cmd(command: 'input', arguments: ['keyevent', '26']),
]);
});
});
group('wakeUp', () {
test('when awake', () async {
FakeDevice.pretendAwake();
await device.wakeUp();
expectLog([
cmd(command: 'dumpsys', arguments: ['power']),
]);
});
test('when asleep', () async {
FakeDevice.pretendAsleep();
await device.wakeUp();
expectLog([
cmd(command: 'dumpsys', arguments: ['power']),
cmd(command: 'input', arguments: ['keyevent', '26']),
]);
});
});
group('sendToSleep', () {
test('when asleep', () async {
FakeDevice.pretendAsleep();
await device.sendToSleep();
expectLog([
cmd(command: 'dumpsys', arguments: ['power']),
]);
});
test('when awake', () async {
FakeDevice.pretendAwake();
await device.sendToSleep();
expectLog([
cmd(command: 'dumpsys', arguments: ['power']),
cmd(command: 'input', arguments: ['keyevent', '26']),
]);
});
});
group('unlock', () {
test('sends unlock event', () async {
FakeDevice.pretendAwake();
await device.unlock();
expectLog([
cmd(command: 'dumpsys', arguments: ['power']),
cmd(command: 'input', arguments: ['keyevent', '82']),
]);
});
});
group('battery health', () {
test('battery health unknown', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_UNKNOWN);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isTrue);
expect(batteryHealth.details, contains('unknown'));
});
test('battery health good', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_GOOD);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isTrue);
expect(batteryHealth.details, isNull);
});
test('battery overheated', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_OVERHEAT);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isFalse);
expect(batteryHealth.details, contains('overheat'));
});
test('battery dead', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_DEAD);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isFalse);
expect(batteryHealth.details, contains('dead'));
});
test('battery over voltage', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_OVER_VOLTAGE);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isFalse);
expect(batteryHealth.details, contains('over voltage'));
});
test('battery health unspecified failure', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_UNSPECIFIED_FAILURE);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isFalse);
expect(batteryHealth.details, contains('Unspecified'));
});
test('battery cold', () async {
FakeDevice.pretendBatteryHealth(
AndroidBatteryHealth.BATTERY_HEALTH_COLD);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isFalse);
expect(batteryHealth.details, contains('cold'));
});
test('battery health value not recognized', () async {
FakeDevice.pretendBatteryHealth(42);
final HealthCheckResult batteryHealth = await device.batteryHealth();
expect(batteryHealth.succeeded, isTrue);
expect(batteryHealth.details, contains('42'));
});
});
});
}
void expectLog(List<CommandArgs> log) {
expect(FakeDevice.commandLog, log);
}
CommandArgs cmd(
{String command, List<String> arguments, Map<String, String> env}) =>
CommandArgs(command: command, arguments: arguments, env: env);
typedef dynamic ExitErrorFactory();
class CommandArgs {
CommandArgs({this.command, this.arguments, this.env});
final String command;
final List<String> arguments;
final Map<String, String> env;
@override
String toString() =>
'CommandArgs(command: $command, arguments: $arguments, env: $env)';
@override
bool operator ==(Object other) {
if (other is CommandArgs) {
return other.command == this.command &&
const ListEquality<String>()
.equals(other.arguments, this.arguments) &&
const MapEquality<String, String>().equals(other.env, this.env);
}
return false;
}
@override
int get hashCode => 17 * (17 * command.hashCode + _hashArguments) + _hashEnv;
int get _hashArguments => arguments != null
? const ListEquality<String>().hash(arguments)
: null.hashCode;
int get _hashEnv => env != null
? const MapEquality<String, String>().hash(env)
: null.hashCode;
}
class FakeDevice extends AndroidDevice {
FakeDevice({String deviceId}) : super(deviceId: deviceId);
static String output = '';
static ExitErrorFactory exitErrorFactory = () => null;
static List<CommandArgs> commandLog = <CommandArgs>[];
static void resetLog() {
commandLog.clear();
}
static void pretendAwake() {
output = '''
mWakefulness=Awake
''';
}
static void pretendAsleep() {
output = '''
mWakefulness=Asleep
''';
}
static void pretendBatteryHealth(int batteryHealth) {
output = '''
health: $batteryHealth
''';
}
@override
Future<String> shellEval(String command, List<String> arguments,
{Map<String, String> env}) async {
commandLog
.add(CommandArgs(command: command, arguments: arguments, env: env));
return output;
}
@override
Future<Null> shellExec(String command, List<String> arguments,
{Map<String, String> env}) async {
commandLog
.add(CommandArgs(command: command, arguments: arguments, env: env));
dynamic exitError = exitErrorFactory();
if (exitError != null) throw exitError;
}
}
class FakeAndroidDeviceDiscovery extends AndroidDeviceDiscovery {
FakeAndroidDeviceDiscovery() : super.testing();
List<dynamic> _outputs;
int _pos = 0;
set outputs(List<dynamic> outputs) {
_pos = 0;
_outputs = outputs;
}
@override
Future<String> deviceListOutput() async {
_pos++;
if (_outputs[_pos - 1] is String) {
return _outputs[_pos - 1] as String;
} else {
throw _outputs[_pos - 1];
}
}
@override
void killAdbServer() async {}
}