mirror of
https://github.com/flutter/flutter
synced 2024-09-29 21:14:10 +00:00
allow adb to set canfail then use canFail=true for clearing logs (#150517)
Fixes https://github.com/flutter/flutter/issues/150093 New tests added to cover that we at least pass the arguments we expect to adb. The test for #150093 is not ideal in that it does not verify the behavior of a failed process but instead ensures we set the parameter that contains the behavior we want. devicelab code and tests are not setup to enable fake process or fake output from stdin/stderr and hang if adb or no hardware are present.
This commit is contained in:
parent
7292c94bac
commit
1eb7cd2c73
|
@ -60,6 +60,10 @@ Running the devicelab will do things to your environment.
|
|||
|
||||
Notably, it will start and stop Gradle, for instance.
|
||||
|
||||
### Running tests in `test/...`
|
||||
|
||||
`dart test test/{NAME_OF_TEST}`
|
||||
|
||||
### Running specific tests
|
||||
|
||||
To run a test, use option `-t` (`--task`):
|
||||
|
|
|
@ -706,6 +706,7 @@ class AndroidDevice extends Device {
|
|||
List<String> arguments, {
|
||||
Map<String, String>? environment,
|
||||
bool silent = false,
|
||||
bool canFail = false, // as in, whether failures are ok. False means that they are fatal.
|
||||
}) {
|
||||
return eval(
|
||||
adbPath,
|
||||
|
@ -713,6 +714,7 @@ class AndroidDevice extends Device {
|
|||
environment: environment,
|
||||
printStdout: !silent,
|
||||
printStderr: !silent,
|
||||
canFail: canFail,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -735,7 +737,7 @@ class AndroidDevice extends Device {
|
|||
@override
|
||||
Future<void> startLoggingToSink(IOSink sink, {bool clear = true}) async {
|
||||
if (clear) {
|
||||
await adb(<String>['logcat', '--clear'], silent: true);
|
||||
await adb(<String>['logcat', '--clear'], silent: true, canFail: true);
|
||||
}
|
||||
_loggingProcess = await startProcess(
|
||||
adbPath,
|
||||
|
@ -770,7 +772,7 @@ class AndroidDevice extends Device {
|
|||
|
||||
@override
|
||||
Future<void> clearLogs() {
|
||||
return adb(<String>['logcat', '-c']);
|
||||
return adb(<String>['logcat', '-c'], canFail: true);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// 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';
|
||||
|
@ -18,8 +23,7 @@ void main() {
|
|||
device = FakeDevice(deviceId: 'fakeDeviceId');
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
});
|
||||
tearDown(() {});
|
||||
|
||||
group('cpu check', () {
|
||||
test('arm64', () async {
|
||||
|
@ -119,12 +123,80 @@ void main() {
|
|||
|
||||
group('adb', () {
|
||||
test('tap', () async {
|
||||
FakeDevice.resetLog();
|
||||
await device.tap(100, 200);
|
||||
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>['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',
|
||||
]),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -181,6 +253,8 @@ class CommandArgs {
|
|||
class FakeDevice extends AndroidDevice {
|
||||
FakeDevice({required super.deviceId});
|
||||
|
||||
static const String canFailKey = 'canFail';
|
||||
|
||||
static String output = '';
|
||||
|
||||
static List<CommandArgs> commandLog = <CommandArgs>[];
|
||||
|
@ -213,6 +287,21 @@ class FakeDevice extends AndroidDevice {
|
|||
''';
|
||||
}
|
||||
|
||||
@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(
|
||||
|
@ -232,3 +321,65 @@ class FakeDevice extends AndroidDevice {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue