From 7f400af35a0716efc86f5b9401dcbedc501c2ed7 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 12 May 2020 07:35:02 -0700 Subject: [PATCH] [flutter_tools] expand Regexp log match to include more AndroidRuntime failures (#56943) --- .../lib/src/android/android_device.dart | 2 + .../android/adb_log_reader_test.dart | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 84671cbbea4..dfeb21b1fbb 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart @@ -986,6 +986,7 @@ class AdbLogReader extends DeviceLogReader { RegExp(r'^[VDIWEF]\/flutter[^:]*:\s+', caseSensitive: false), RegExp(r'^[IE]\/DartVM[^:]*:\s+'), RegExp(r'^[WEF]\/AndroidRuntime:\s+'), + RegExp(r'^[WEF]\/AndroidRuntime\([0-9]+\):\s+'), RegExp(r'^[WEF]\/ActivityManager:\s+.*(\bflutter\b|\bdomokit\b|\bsky\b)'), RegExp(r'^[WEF]\/System\.err:\s+'), RegExp(r'^[F]\/[\S^:]+:\s+'), @@ -1019,6 +1020,7 @@ class AdbLogReader extends DeviceLogReader { } final Match timeMatch = AndroidDevice._timeRegExp.firstMatch(line); if (timeMatch == null || line.length == timeMatch.end) { + _acceptedLastLine = false; return; } // Chop off the time. diff --git a/packages/flutter_tools/test/general.shard/android/adb_log_reader_test.dart b/packages/flutter_tools/test/general.shard/android/adb_log_reader_test.dart index 9bee6206c33..b1175d82cd7 100644 --- a/packages/flutter_tools/test/general.shard/android/adb_log_reader_test.dart +++ b/packages/flutter_tools/test/general.shard/android/adb_log_reader_test.dart @@ -13,6 +13,11 @@ import '../../src/context.dart'; const int kLollipopVersionCode = 21; const String kLastLogcatTimestamp = '11-27 15:39:04.506'; +/// By default the android log reader accepts lines that match no patterns +/// if the previous line was a match. Include an intentionally non-matching +/// line as the first input to disable this behavior. +const String kDummyLine = 'Contents are not important\n'; + void main() { testWithoutContext('AdbLogReader calls adb logcat with expected flags apiVersion 21', () async { final FakeProcessManager processManager = FakeProcessManager.list([ @@ -128,6 +133,40 @@ void main() { logReader.dispose(); await onDone.future; }); + + testWithoutContext('AdbLogReader does not filter output from AndroidRuntime crashes', () async { + final FakeProcessManager processManager = FakeProcessManager.list([ + FakeCommand( + command: const [ + 'adb', + '-s', + '1234', + 'logcat', + '-v', + 'time', + ], + completer: Completer.sync(), + // Example stack trace from an incorrectly named application:name in the AndroidManfiest.xml + stdout: + kDummyLine + + '05-11 12:54:46.665 E/AndroidRuntime(11787): FATAL EXCEPTION: main\n' + '05-11 12:54:46.665 E/AndroidRuntime(11787): Process: com.example.foobar, PID: 11787\n' + '05-11 12:54:46.665 java.lang.RuntimeException: Unable to instantiate application ' + 'io.flutter.app.FlutterApplication2: java.lang.ClassNotFoundException:\n', + ) + ]); + final AdbLogReader logReader = await AdbLogReader.createLogReader( + createMockDevice(null), + processManager, + ); + await expectLater(logReader.logLines, emitsInOrder([ + 'E/AndroidRuntime(11787): FATAL EXCEPTION: main', + 'E/AndroidRuntime(11787): Process: com.example.foobar, PID: 11787', + 'java.lang.RuntimeException: Unable to instantiate application io.flutter.app.FlutterApplication2: java.lang.ClassNotFoundException:', + ])); + + logReader.dispose(); + }); } MockAndroidDevice createMockDevice(int sdkLevel) {