feat(shorebird_cli): add logcat to Adb (#836)

This commit is contained in:
Felix Angelov
2023-07-11 17:35:57 -04:00
committed by GitHub
parent 5cbfd0dbca
commit 121c793dc0
2 changed files with 82 additions and 0 deletions
+18
View File
@@ -1,3 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'package:shorebird_cli/src/android_sdk.dart';
import 'package:shorebird_cli/src/process.dart';
@@ -10,6 +13,13 @@ class Adb {
return process.run(adbPath, command.split(' '));
}
Future<Process> _stream(String command) async {
final adbPath = androidSdk.adbPath;
if (adbPath == null) throw Exception('Unable to locate adb.');
return process.start(adbPath, command.split(' '));
}
/// Starts the app with the given [package] name.
Future<void> startApp(String package) async {
final result = await _exec('shell monkey -p $package 1');
@@ -17,4 +27,12 @@ class Adb {
throw Exception('Unable to start app: ${result.stderr}');
}
}
Future<Process> logcat({String? filter}) async {
final logcat = await _stream('logcat');
if (filter == null) return logcat;
final grep = await process.start('grep', [filter]);
unawaited(logcat.stdout.pipe(grep.stdin));
return grep;
}
}
@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:mocktail/mocktail.dart';
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/adb.dart';
@@ -9,6 +11,10 @@ class _MockAndroidSdk extends Mock implements AndroidSdk {}
class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
class _MockProcess extends Mock implements Process {}
class _MockIOSink extends Mock implements IOSink {}
void main() {
group(Adb, () {
const adbPath = '/path/to/adb';
@@ -27,6 +33,10 @@ void main() {
);
}
setUpAll(() {
registerFallbackValue(const Stream<List<int>>.empty());
});
setUp(() {
androidSdk = _MockAndroidSdk();
process = _MockShorebirdProcess();
@@ -92,5 +102,59 @@ void main() {
).called(1);
});
});
group('logcat', () {
test('throws when unable to locate adb', () async {
when(() => androidSdk.adbPath).thenReturn(null);
await expectLater(
() => runWithOverrides(() => adb.logcat()),
throwsA(
isA<Exception>().having(
(e) => e.toString(),
'exception()',
contains('Unable to locate adb'),
),
),
);
});
test('returns correct process (unfiltered)', () async {
final Process logcatProcess = _MockProcess();
when(() => process.start(any(), any())).thenAnswer((invocation) async {
final executable = invocation.positionalArguments[0] as String;
if (executable == adbPath) return logcatProcess;
fail('Unexpected executable: $executable');
});
final result = await runWithOverrides(() => adb.logcat());
expect(result, equals(logcatProcess));
verify(() => process.start(adbPath, ['logcat'])).called(1);
});
test('returns correct process (filtered)', () async {
const filter = 'flutter';
final logcatProcess = _MockProcess();
final grepProcess = _MockProcess();
final grepStdin = _MockIOSink();
const logcatStdout = Stream<List<int>>.empty();
when(grepStdin.close).thenAnswer((_) async {});
when(() => grepStdin.addStream(any())).thenAnswer((_) async {});
when(() => grepProcess.stdin).thenReturn(grepStdin);
when(
() => logcatProcess.stdout,
).thenAnswer((_) => logcatStdout);
when(() => process.start(any(), any())).thenAnswer((invocation) async {
final executable = invocation.positionalArguments[0] as String;
if (executable == adbPath) return logcatProcess;
if (executable == 'grep') return grepProcess;
fail('Unexpected executable: $executable');
});
final result = await runWithOverrides(() => adb.logcat(filter: filter));
expect(result, equals(grepProcess));
verify(() => process.start(adbPath, ['logcat'])).called(1);
verify(() => process.start('grep', [filter])).called(1);
verify(() => grepStdin.addStream(logcatStdout)).called(1);
});
});
});
}