| // Copyright 2014 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 'package:flutter_tools/src/base/logger.dart'; |
| import 'package:flutter_tools/src/base/process.dart'; |
| import 'package:flutter_tools/src/ios/xcodeproj.dart'; |
| import 'package:flutter_tools/src/ios/xcresult.dart'; |
| import 'package:flutter_tools/src/macos/xcode.dart'; |
| |
| import '../../src/common.dart'; |
| import '../../src/fake_process_manager.dart'; |
| import 'xcresult_test_data.dart'; |
| |
| void main() { |
| // Creates a FakeCommand for the xcresult get call to build the app |
| // in the given configuration. |
| FakeCommand setUpFakeXCResultGetCommand({ |
| required String stdout, |
| required String tempResultPath, |
| required Xcode xcode, |
| int exitCode = 0, |
| String stderr = '', |
| }) { |
| return FakeCommand( |
| command: <String>[ |
| ...xcode.xcrunCommand(), |
| 'xcresulttool', |
| 'get', |
| '--path', |
| tempResultPath, |
| '--format', |
| 'json', |
| ], |
| stdout: stdout, |
| stderr: stderr, |
| exitCode: exitCode, |
| onRun: () {}, |
| ); |
| } |
| |
| const FakeCommand kWhichSysctlCommand = FakeCommand( |
| command: <String>[ |
| 'which', |
| 'sysctl', |
| ], |
| ); |
| |
| const FakeCommand kx64CheckCommand = FakeCommand( |
| command: <String>[ |
| 'sysctl', |
| 'hw.optional.arm64', |
| ], |
| exitCode: 1, |
| ); |
| |
| XCResultGenerator setupGenerator({ |
| required String resultJson, |
| int exitCode = 0, |
| String stderr = '', |
| }) { |
| final FakeProcessManager fakeProcessManager = |
| FakeProcessManager.list(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| ]); |
| final Xcode xcode = Xcode.test( |
| processManager: fakeProcessManager, |
| xcodeProjectInterpreter: XcodeProjectInterpreter.test( |
| processManager: fakeProcessManager, |
| version: null, |
| ), |
| ); |
| fakeProcessManager.addCommands( |
| <FakeCommand>[ |
| setUpFakeXCResultGetCommand( |
| stdout: resultJson, |
| tempResultPath: _tempResultPath, |
| xcode: xcode, |
| exitCode: exitCode, |
| stderr: stderr, |
| ), |
| ], |
| ); |
| final ProcessUtils processUtils = ProcessUtils( |
| processManager: fakeProcessManager, |
| logger: BufferLogger.test(), |
| ); |
| return XCResultGenerator( |
| resultPath: _tempResultPath, |
| xcode: xcode, |
| processUtils: processUtils, |
| ); |
| } |
| |
| testWithoutContext( |
| 'correctly parse sample result json when there are issues.', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssues); |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 2); |
| expect(result.issues.first.type, XCResultIssueType.error); |
| expect(result.issues.first.subType, 'Semantic Issue'); |
| expect(result.issues.first.message, "Use of undeclared identifier 'asdas'"); |
| expect(result.issues.first.location, '/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56'); |
| expect(result.issues.last.type, XCResultIssueType.warning); |
| expect(result.issues.last.subType, 'Warning'); |
| expect(result.issues.last.message, |
| "The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'correctly parse sample result json when there are issues but invalid url.', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssuesAndInvalidUrl); |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 2); |
| expect(result.issues.first.type, XCResultIssueType.error); |
| expect(result.issues.first.subType, 'Semantic Issue'); |
| expect(result.issues.first.message, "Use of undeclared identifier 'asdas'"); |
| expect(result.issues.first.location, isNull); |
| expect(result.issues.first.warnings.first, '(XCResult) The `url` exists but it was failed to be parsed. url: 3:00'); |
| expect(result.issues.last.type, XCResultIssueType.warning); |
| expect(result.issues.last.subType, 'Warning'); |
| expect(result.issues.last.message, |
| "The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'correctly parse sample result json and discard all warnings', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssues); |
| final XCResultIssueDiscarder discarder = XCResultIssueDiscarder(typeMatcher: XCResultIssueType.warning); |
| final XCResult result = await generator.generate(issueDiscarders: <XCResultIssueDiscarder>[discarder]); |
| expect(result.issues.length, 1); |
| expect(result.issues.first.type, XCResultIssueType.error); |
| expect(result.issues.first.subType, 'Semantic Issue'); |
| expect(result.issues.first.message, "Use of undeclared identifier 'asdas'"); |
| expect(result.issues.first.location, '/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56'); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'correctly parse sample result json and discard base on subType', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssues); |
| final XCResultIssueDiscarder discarder = XCResultIssueDiscarder(subTypeMatcher: RegExp(r'^Warning$')); |
| final XCResult result = await generator.generate(issueDiscarders: <XCResultIssueDiscarder>[discarder]); |
| expect(result.issues.length, 1); |
| expect(result.issues.first.type, XCResultIssueType.error); |
| expect(result.issues.first.subType, 'Semantic Issue'); |
| expect(result.issues.first.message, "Use of undeclared identifier 'asdas'"); |
| expect(result.issues.first.location, '/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56'); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'correctly parse sample result json and discard base on message', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssues); |
| final XCResultIssueDiscarder discarder = XCResultIssueDiscarder(messageMatcher: RegExp(r"^The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99.$")); |
| final XCResult result = await generator.generate(issueDiscarders: <XCResultIssueDiscarder>[discarder]); |
| expect(result.issues.length, 1); |
| expect(result.issues.first.type, XCResultIssueType.error); |
| expect(result.issues.first.subType, 'Semantic Issue'); |
| expect(result.issues.first.message, "Use of undeclared identifier 'asdas'"); |
| expect(result.issues.first.location, '/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56'); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'correctly parse sample result json and discard base on location', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssues); |
| final XCResultIssueDiscarder discarder = XCResultIssueDiscarder(locationMatcher: RegExp(r'/Users/m/Projects/test_create/ios/Runner/AppDelegate.m')); |
| final XCResult result = await generator.generate(issueDiscarders: <XCResultIssueDiscarder>[discarder]); |
| expect(result.issues.length, 1); |
| expect(result.issues.first.type, XCResultIssueType.warning); |
| expect(result.issues.first.subType, 'Warning'); |
| expect(result.issues.first.message, |
| "The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'correctly parse sample result json with multiple discarders.', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonWithIssues); |
| final XCResultIssueDiscarder discardWarnings = XCResultIssueDiscarder(typeMatcher: XCResultIssueType.warning); |
| final XCResultIssueDiscarder discardSemanticIssues = XCResultIssueDiscarder(subTypeMatcher: RegExp(r'^Semantic Issue$')); |
| final XCResult result = await generator.generate(issueDiscarders: <XCResultIssueDiscarder>[discardWarnings, discardSemanticIssues]); |
| expect(result.issues, isEmpty); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext('correctly parse sample result json when no issues.', |
| () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonNoIssues); |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 0); |
| expect(result.parseSuccess, isTrue); |
| expect(result.parsingErrorMessage, isNull); |
| }); |
| |
| testWithoutContext( |
| 'error: `xcresulttool get` process fail should return an `XCResult` with stderr as `parsingErrorMessage`.', |
| () async { |
| const String fakeStderr = 'Fake: fail to parse result json.'; |
| final XCResultGenerator generator = setupGenerator( |
| resultJson: '', |
| exitCode: 1, |
| stderr: fakeStderr, |
| ); |
| |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 0); |
| expect(result.parseSuccess, false); |
| expect(result.parsingErrorMessage, fakeStderr); |
| }); |
| |
| testWithoutContext('error: `xcresulttool get` no stdout', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: ''); |
| |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 0); |
| expect(result.parseSuccess, false); |
| expect(result.parsingErrorMessage, |
| 'xcresult parser: Unrecognized top level json format.'); |
| }); |
| |
| testWithoutContext('error: wrong top level json format.', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: '[]'); |
| |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 0); |
| expect(result.parseSuccess, false); |
| expect(result.parsingErrorMessage, |
| 'xcresult parser: Unrecognized top level json format.'); |
| }); |
| |
| testWithoutContext('error: fail to parse issue map', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: '{}'); |
| |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 0); |
| expect(result.parseSuccess, false); |
| expect(result.parsingErrorMessage, |
| 'xcresult parser: Failed to parse the issues map.'); |
| }); |
| |
| testWithoutContext('error: invalid issue map', () async { |
| final XCResultGenerator generator = setupGenerator(resultJson: kSampleResultJsonInvalidIssuesMap); |
| |
| final XCResult result = await generator.generate(); |
| expect(result.issues.length, 0); |
| expect(result.parseSuccess, false); |
| expect(result.parsingErrorMessage, |
| 'xcresult parser: Failed to parse the issues map.'); |
| }); |
| } |
| |
| const String _tempResultPath = 'temp'; |