From faaca13f22647c647e5c7d20d55c0fed9e06ca19 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 30 Sep 2021 09:33:04 -0700 Subject: [PATCH] Catch FormatException from bad simulator log output (#90966) --- .../flutter_tools/lib/src/ios/simulators.dart | 11 +++-- .../general.shard/ios/simulators_test.dart | 47 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index 9032a0d704d..34a40dd8ee0 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart @@ -858,9 +858,14 @@ class _IOSSimulatorLogReader extends DeviceLogReader { // The log command predicate handles filtering, so every log eventMessage should be decoded and added. final Match eventMessageMatch = _unifiedLoggingEventMessageRegex.firstMatch(line); if (eventMessageMatch != null) { - final dynamic decodedJson = jsonDecode(eventMessageMatch.group(1)); - if (decodedJson is String) { - _linesController.add(decodedJson); + final String message = eventMessageMatch.group(1); + try { + final dynamic decodedJson = jsonDecode(message); + if (decodedJson is String) { + _linesController.add(decodedJson); + } + } on FormatException { + globals.printError('Logger returned non-JSON response: $message'); } } } diff --git a/packages/flutter_tools/test/general.shard/ios/simulators_test.dart b/packages/flutter_tools/test/general.shard/ios/simulators_test.dart index af1675dbcda..775f46d35c6 100644 --- a/packages/flutter_tools/test/general.shard/ios/simulators_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/simulators_test.dart @@ -622,6 +622,12 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' }); group('unified logging', () { + BufferLogger logger; + + setUp(() { + logger = BufferLogger.test(); + }); + testUsingContext('log reader handles escaped multiline messages', () async { const String logPredicate = 'eventType = logEvent AND processImagePath ENDSWITH "My Super Awesome App" ' 'AND (senderImagePath ENDSWITH "/Flutter" OR senderImagePath ENDSWITH "/libswiftCore.dylib" ' @@ -676,6 +682,47 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' ProcessManager: () => fakeProcessManager, FileSystem: () => fileSystem, }); + + testUsingContext('log reader handles bad output', () async { + const String logPredicate = 'eventType = logEvent AND processImagePath ENDSWITH "My Super Awesome App" ' + 'AND (senderImagePath ENDSWITH "/Flutter" OR senderImagePath ENDSWITH "/libswiftCore.dylib" ' + 'OR processImageUUID == senderImageUUID) AND NOT(eventMessage CONTAINS ": could not find icon ' + 'for representation -> com.apple.") AND NOT(eventMessage BEGINSWITH "assertion failed: ") ' + 'AND NOT(eventMessage CONTAINS " libxpc.dylib ")'; + fakeProcessManager.addCommand(const FakeCommand( + command: [ + 'xcrun', + 'simctl', + 'spawn', + '123456', + 'log', + 'stream', + '--style', + 'json', + '--predicate', + logPredicate, + ], + stdout: '"eventMessage" : "message with incorrect escaping""', + )); + + final IOSSimulator device = IOSSimulator( + '123456', + simulatorCategory: 'iOS 11.0', + simControl: simControl, + ); + final DeviceLogReader logReader = device.getLogReader( + app: await BuildableIOSApp.fromProject(mockIosProject, null), + ); + + final List lines = await logReader.logLines.toList(); + expect(lines, isEmpty); + expect(logger.errorText, contains('Logger returned non-JSON response')); + expect(fakeProcessManager.hasRemainingExpectations, isFalse); + }, overrides: { + ProcessManager: () => fakeProcessManager, + FileSystem: () => fileSystem, + Logger: () => logger, + }); }); });