Unverified Commit bfff43cf authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove mocks from code signing test (#83188)

parent 14930901
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
// @dart = 2.8 // @dart = 2.8
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter_tools/src/base/config.dart'; import 'package:flutter_tools/src/base/config.dart';
...@@ -12,23 +13,24 @@ import 'package:flutter_tools/src/base/logger.dart'; ...@@ -12,23 +13,24 @@ import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals; import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/ios/code_signing.dart'; import 'package:flutter_tools/src/ios/code_signing.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/fake_process_manager.dart'; import '../../src/fake_process_manager.dart';
const String kCertificates = '''
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
3 valid identities found''';
void main() { void main() {
group('Auto signing', () { group('Auto signing', () {
ProcessManager mockProcessManager;
Config testConfig; Config testConfig;
AnsiTerminal testTerminal; AnsiTerminal testTerminal;
BufferLogger logger; BufferLogger logger;
setUp(() async { setUp(() async {
logger = BufferLogger.test(); logger = BufferLogger.test();
mockProcessManager = MockProcessManager();
// Assume all binaries exist and are executable
when(mockProcessManager.canRun(any)).thenReturn(true);
testConfig = Config.test(); testConfig = Config.test();
testTerminal = TestTerminal(); testTerminal = TestTerminal();
testTerminal.usesTerminalUi = true; testTerminal.usesTerminalUi = true;
...@@ -37,7 +39,7 @@ void main() { ...@@ -37,7 +39,7 @@ void main() {
testWithoutContext('No auto-sign if Xcode project settings are not available', () async { testWithoutContext('No auto-sign if Xcode project settings are not available', () async {
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: null, buildSettings: null,
processManager: mockProcessManager, processManager: FakeProcessManager.empty(),
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -50,7 +52,7 @@ void main() { ...@@ -50,7 +52,7 @@ void main() {
buildSettings: <String, String>{ buildSettings: <String, String>{
'DEVELOPMENT_TEAM': 'abc', 'DEVELOPMENT_TEAM': 'abc',
}, },
processManager: mockProcessManager, processManager: FakeProcessManager.empty(),
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -62,13 +64,18 @@ void main() { ...@@ -62,13 +64,18 @@ void main() {
}); });
testWithoutContext('No auto-sign if security or openssl not available', () async { testWithoutContext('No auto-sign if security or openssl not available', () async {
when(mockProcessManager.run(<String>['which', 'security'])) final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
.thenAnswer((_) => Future<ProcessResult>.value(exitsFail)); const FakeCommand(
command: <String>['which', 'security'],
exitCode: 1,
),
]);
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -77,25 +84,21 @@ void main() { ...@@ -77,25 +84,21 @@ void main() {
}); });
testWithoutContext('No valid code signing certificates shows instructions', () async { testWithoutContext('No valid code signing certificates shows instructions', () async {
when(mockProcessManager.run( final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
<String>['which', 'security'], const FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: <String>['which', 'security'],
environment: anyNamed('environment'), ),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); const FakeCommand(
when(mockProcessManager.run( command: <String>['which', 'openssl'],
<String>['which', 'openssl'], ),
workingDirectory: anyNamed('workingDirectory'), const FakeCommand(
environment: anyNamed('environment'), command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); ),
when(mockProcessManager.run( ]);
argThat(contains('find-identity')),
environment: anyNamed('environment'), await expectLater(() => getCodeSigningIdentityDevelopmentTeam(
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
expect(() async => getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{}, buildSettings: <String, String>{},
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -103,64 +106,46 @@ void main() { ...@@ -103,64 +106,46 @@ void main() {
}); });
testWithoutContext('Test single identity and certificate organization works', () async { testWithoutContext('Test single identity and certificate organization works', () async {
when(mockProcessManager.run( final Completer<void> completer = Completer<void>();
<String>['which', 'security'], final StreamController<List<int>> controller = StreamController<List<int>>();
workingDirectory: anyNamed('workingDirectory'), const String certificates = '''
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
<String>['which', 'openssl'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
argThat(contains('find-identity')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'''
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)" 1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
1 valid identities found''', 1 valid identities found''';
'', final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
))); const FakeCommand(
when(mockProcessManager.run( command: <String>['which', 'security'],
<String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'], ),
environment: anyNamed('environment'), const FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: <String>['which', 'openssl'],
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( ),
1, // pid const FakeCommand(
0, // exitCode command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
'This is a mock certificate', stdout: certificates,
'', ),
))); const FakeCommand(
command: <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
final MockProcess mockProcess = MockProcess(); stdout: 'This is a fake certificate',
final MockStdIn mockStdIn = MockStdIn(); ),
final MockStream mockStdErr = MockStream(); FakeCommand(
command: const <String>['openssl', 'x509', '-subject'],
when(mockProcessManager.start( stdin: IOSink(controller.sink),
argThat(contains('openssl')), stdout: 'subject= /CN=iPhone Developer: Profile 1 (1111AAAA11)/OU=3333CCCC33/O=My Team/C=US',
environment: anyNamed('environment'), completer: completer,
workingDirectory: anyNamed('workingDirectory'), )
)).thenAnswer((Invocation invocation) => Future<Process>.value(mockProcess)); ]);
when(mockProcess.stdin).thenReturn(mockStdIn); // Verify that certifacte value is passed into openssl command.
when(mockProcess.stdout) String stdin;
.thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture( controller.stream.listen((List<int> chunk) {
Future<List<int>>.value(utf8.encode( stdin = utf8.decode(chunk);
'subject= /CN=iPhone Developer: Profile 1 (1111AAAA11)/OU=3333CCCC33/O=My Team/C=US' completer.complete();
)) });
));
when(mockProcess.stderr).thenAnswer((Invocation invocation) => mockStdErr);
when(mockProcess.exitCode).thenAnswer((_) async => 0);
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -168,149 +153,101 @@ void main() { ...@@ -168,149 +153,101 @@ void main() {
expect(logger.statusText, contains('iPhone Developer: Profile 1 (1111AAAA11)')); expect(logger.statusText, contains('iPhone Developer: Profile 1 (1111AAAA11)'));
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
verify(mockStdIn.write('This is a mock certificate')); expect(stdin, 'This is a fake certificate');
expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '3333CCCC33'}); expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '3333CCCC33'});
}); });
testWithoutContext('Test single identity (Catalina format) and certificate organization works', () async { testWithoutContext('Test single identity (Catalina format) and certificate organization works', () async {
when(mockProcessManager.run( final Completer<void> completer = Completer<void>();
<String>['which', 'security'], final StreamController<List<int>> controller = StreamController<List<int>>();
workingDirectory: anyNamed('workingDirectory'), const String certificates = '''
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
<String>['which', 'openssl'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
argThat(contains('find-identity')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'''
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "Apple Development: Profile 1 (1111AAAA11)" 1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "Apple Development: Profile 1 (1111AAAA11)"
1 valid identities found''', 1 valid identities found''';
'', final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
))); const FakeCommand(
when(mockProcessManager.run( command: <String>['which', 'security'],
<String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'], ),
environment: anyNamed('environment'), const FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: <String>['which', 'openssl'],
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( ),
1, // pid const FakeCommand(
0, // exitCode command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
'This is a mock certificate', stdout: certificates,
'', ),
))); const FakeCommand(
command: <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
final MockProcess mockProcess = MockProcess(); stdout: 'This is a fake certificate',
final MockStdIn mockStdIn = MockStdIn(); ),
final MockStream mockStdErr = MockStream(); FakeCommand(
command: const <String>['openssl', 'x509', '-subject'],
when(mockProcessManager.start( stdin: IOSink(controller.sink),
argThat(contains('openssl')), stdout: 'subject= /CN=iPhone Developer: Profile 1 (1111AAAA11)/OU=3333CCCC33/O=My Team/C=US',
environment: anyNamed('environment'), completer: completer,
workingDirectory: anyNamed('workingDirectory'), )
)).thenAnswer((Invocation invocation) => Future<Process>.value(mockProcess)); ]);
when(mockProcess.stdin).thenReturn(mockStdIn); // Verify that certifacte value is passed into openssl command.
when(mockProcess.stdout) String stdin;
.thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture( controller.stream.listen((List<int> chunk) {
Future<List<int>>.value(utf8.encode( stdin = utf8.decode(chunk);
'subject= /CN=iPhone Developer: Profile 1 (1111AAAA11)/OU=3333CCCC33/O=My Team/C=US' completer.complete();
)) });
));
when(mockProcess.stderr).thenAnswer((Invocation invocation) => mockStdErr);
when(mockProcess.exitCode).thenAnswer((_) async => 0);
Map<String, String> signingConfigs; final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
try {
signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
); );
} on Exception catch (e) {
// This should not throw
fail('Code signing threw: $e');
}
expect(logger.statusText, contains('Apple Development: Profile 1 (1111AAAA11)')); expect(logger.statusText, contains('Apple Development: Profile 1 (1111AAAA11)'));
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
verify(mockStdIn.write('This is a mock certificate')); expect(stdin, 'This is a fake certificate');
expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '3333CCCC33'}); expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '3333CCCC33'});
}); });
testWithoutContext('Test multiple identity and certificate organization works', () async { testWithoutContext('Test multiple identity and certificate organization works', () async {
when(mockProcessManager.run( final Completer<void> completer = Completer<void>();
<String>['which', 'security'], final StreamController<List<int>> controller = StreamController<List<int>>();
workingDirectory: anyNamed('workingDirectory'), mockTerminalStdInStream = Stream<String>.value('3');
environment: anyNamed('environment'), final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); const FakeCommand(
when(mockProcessManager.run( command: <String>['which', 'security'],
<String>['which', 'openssl'], ),
workingDirectory: anyNamed('workingDirectory'), const FakeCommand(
environment: anyNamed('environment'), command: <String>['which', 'openssl'],
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); ),
when(mockProcessManager.run( const FakeCommand(
argThat(contains('find-identity')), command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
environment: anyNamed('environment'), stdout: kCertificates,
workingDirectory: anyNamed('workingDirectory'), ),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( const FakeCommand(
1, // pid command: <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
0, // exitCode stdout: 'This is a fake certificate',
''' ),
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)" FakeCommand(
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)" command: const <String>['openssl', 'x509', '-subject'],
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)" stdin: IOSink(controller.sink),
3 valid identities found''', stdout: 'subject= /CN=iPhone Developer: Profile 3 (3333CCCC33)/OU=4444DDDD44/O=My Team/C=US',
'', completer: completer,
))); )
mockTerminalStdInStream = ]);
Stream<String>.fromFuture(Future<String>.value('3'));
when(mockProcessManager.run( // Verify that certifacte value is passed into openssl command.
<String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'], String stdin;
environment: anyNamed('environment'), controller.stream.listen((List<int> chunk) {
workingDirectory: anyNamed('workingDirectory'), stdin = utf8.decode(chunk);
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( completer.complete();
1, // pid });
0, // exitCode
'This is a mock certificate',
'',
)));
final MockProcess mockOpenSslProcess = MockProcess();
final MockStdIn mockOpenSslStdIn = MockStdIn();
final MockStream mockOpenSslStdErr = MockStream();
when(mockProcessManager.start(
argThat(contains('openssl')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
when(mockOpenSslProcess.stdin).thenReturn(mockOpenSslStdIn);
when(mockOpenSslProcess.stdout)
.thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
Future<List<int>>.value(utf8.encode(
'subject= /CN=iPhone Developer: Profile 3 (3333CCCC33)/OU=4444DDDD44/O=My Team/C=US'
))
));
when(mockOpenSslProcess.stderr).thenAnswer((Invocation invocation) => mockOpenSslStdErr);
when(mockOpenSslProcess.exitCode).thenAnswer((_) => Future<int>.value(0));
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -325,76 +262,50 @@ void main() { ...@@ -325,76 +262,50 @@ void main() {
contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 3 (3333CCCC33)"'), contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 3 (3333CCCC33)"'),
); );
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
verify(mockOpenSslStdIn.write('This is a mock certificate')); expect(stdin, 'This is a fake certificate');
expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '4444DDDD44'}); expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '4444DDDD44'});
expect(testConfig.getValue('ios-signing-cert'), 'iPhone Developer: Profile 3 (3333CCCC33)'); expect(testConfig.getValue('ios-signing-cert'), 'iPhone Developer: Profile 3 (3333CCCC33)');
}); });
testWithoutContext('Test multiple identity in machine mode works', () async { testWithoutContext('Test multiple identity in machine mode works', () async {
testTerminal.usesTerminalUi = false; testTerminal.usesTerminalUi = false;
when(mockProcessManager.run( final Completer<void> completer = Completer<void>();
<String>['which', 'security'], final StreamController<List<int>> controller = StreamController<List<int>>();
workingDirectory: anyNamed('workingDirectory'), final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
environment: anyNamed('environment'), const FakeCommand(
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); command: <String>['which', 'security'],
when(mockProcessManager.run( ),
<String>['which', 'openssl'], const FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: <String>['which', 'openssl'],
environment: anyNamed('environment'), ),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); const FakeCommand(
when(mockProcessManager.run( command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
argThat(contains('find-identity')), stdout: kCertificates,
environment: anyNamed('environment'), ),
workingDirectory: anyNamed('workingDirectory'), const FakeCommand(
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( command: <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
1, // pid stdout: 'This is a fake certificate',
0, // exitCode ),
''' FakeCommand(
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)" command: const <String>['openssl', 'x509', '-subject'],
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)" stdin: IOSink(controller.sink),
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)" stdout: 'subject= /CN=iPhone Developer: Profile 3 (1111AAAA11)/OU=5555EEEE55/O=My Team/C=US',
3 valid identities found''', completer: completer,
'', )
))); ]);
mockTerminalStdInStream =
Stream<String>.fromFuture(Future<String>.error(Exception('Cannot read from StdIn'))); // Verify that certifacte value is passed into openssl command.
when(mockProcessManager.run( String stdin;
<String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'], controller.stream.listen((List<int> chunk) {
environment: anyNamed('environment'), stdin = utf8.decode(chunk);
workingDirectory: anyNamed('workingDirectory'), completer.complete();
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( });
1, // pid
0, // exitCode
'This is a mock certificate',
'',
)));
final MockProcess mockOpenSslProcess = MockProcess();
final MockStdIn mockOpenSslStdIn = MockStdIn();
final MockStream mockOpenSslStdErr = MockStream();
when(mockProcessManager.start(
argThat(contains('openssl')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
when(mockOpenSslProcess.stdin).thenReturn(mockOpenSslStdIn);
when(mockOpenSslProcess.stdout)
.thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
Future<List<int>>.value(utf8.encode(
'subject= /CN=iPhone Developer: Profile 1 (1111AAAA11)/OU=5555EEEE55/O=My Team/C=US'
)),
));
when(mockOpenSslProcess.stderr).thenAnswer((Invocation invocation) => mockOpenSslStdErr);
when(mockOpenSslProcess.exitCode).thenAnswer((_) => Future<int>.value(0));
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -405,72 +316,49 @@ void main() { ...@@ -405,72 +316,49 @@ void main() {
contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 1 (1111AAAA11)"'), contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 1 (1111AAAA11)"'),
); );
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
verify(mockOpenSslStdIn.write('This is a mock certificate')); expect(stdin, 'This is a fake certificate');
expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '5555EEEE55'}); expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '5555EEEE55'});
}); });
testWithoutContext('Test saved certificate used', () async { testWithoutContext('Test saved certificate used', () async {
when(mockProcessManager.run(
<String>['which', 'security'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
<String>['which', 'openssl'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
argThat(contains('find-identity')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'''
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
3 valid identities found''',
'',
)));
when(mockProcessManager.run(
<String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'This is a mock certificate',
'',
)));
final MockProcess mockOpenSslProcess = MockProcess();
final MockStdIn mockOpenSslStdIn = MockStdIn();
final MockStream mockOpenSslStdErr = MockStream();
when(mockProcessManager.start(
argThat(contains('openssl')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
when(mockOpenSslProcess.stdin).thenReturn(mockOpenSslStdIn);
when(mockOpenSslProcess.stdout)
.thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
Future<List<int>>.value(utf8.encode(
'subject= /CN=iPhone Developer: Profile 3 (3333CCCC33)/OU=4444DDDD44/O=My Team/C=US'
))
));
when(mockOpenSslProcess.stderr).thenAnswer((Invocation invocation) => mockOpenSslStdErr);
when(mockOpenSslProcess.exitCode).thenAnswer((_) => Future<int>.value(0));
testConfig.setValue('ios-signing-cert', 'iPhone Developer: Profile 3 (3333CCCC33)'); testConfig.setValue('ios-signing-cert', 'iPhone Developer: Profile 3 (3333CCCC33)');
final Completer<void> completer = Completer<void>();
final StreamController<List<int>> controller = StreamController<List<int>>();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
command: <String>['which', 'security'],
),
const FakeCommand(
command: <String>['which', 'openssl'],
),
const FakeCommand(
command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
stdout: kCertificates,
),
const FakeCommand(
command: <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
stdout: 'This is a fake certificate',
),
FakeCommand(
command: const <String>['openssl', 'x509', '-subject'],
stdin: IOSink(controller.sink),
stdout: 'subject= /CN=iPhone Developer: Profile 3 (3333CCCC33)/OU=4444DDDD44/O=My Team/C=US',
completer: completer,
)
]);
// Verify that certifacte value is passed into openssl command.
String stdin;
controller.stream.listen((List<int> chunk) {
stdin = utf8.decode(chunk);
completer.complete();
});
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -485,116 +373,87 @@ void main() { ...@@ -485,116 +373,87 @@ void main() {
contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 3 (3333CCCC33)"'), contains('Signing iOS app for device deployment using developer identity: "iPhone Developer: Profile 3 (3333CCCC33)"'),
); );
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
verify(mockOpenSslStdIn.write('This is a mock certificate')); expect(stdin, 'This is a fake certificate');
expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '4444DDDD44'}); expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '4444DDDD44'});
}); });
testWithoutContext('Test invalid saved certificate shows error and prompts again', () async { testWithoutContext('Test invalid saved certificate shows error and prompts again', () async {
when(mockProcessManager.run(
<String>['which', 'security'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
<String>['which', 'openssl'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
when(mockProcessManager.run(
argThat(contains('find-identity')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'''
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
3 valid identities found''',
'',
)));
mockTerminalStdInStream =
Stream<String>.fromFuture(Future<String>.value('3'));
when(mockProcessManager.run(
<String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'This is a mock certificate',
'',
)));
final MockProcess mockOpenSslProcess = MockProcess();
final MockStdIn mockOpenSslStdIn = MockStdIn();
final MockStream mockOpenSslStdErr = MockStream();
when(mockProcessManager.start(
argThat(contains('openssl')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
when(mockOpenSslProcess.stdin).thenReturn(mockOpenSslStdIn);
when(mockOpenSslProcess.stdout)
.thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
Future<List<int>>.value(utf8.encode(
'subject= /CN=iPhone Developer: Profile 3 (3333CCCC33)/OU=4444DDDD44/O=My Team/C=US'
))
));
when(mockOpenSslProcess.stderr).thenAnswer((Invocation invocation) => mockOpenSslStdErr);
when(mockOpenSslProcess.exitCode).thenAnswer((_) => Future<int>.value(0));
testConfig.setValue('ios-signing-cert', 'iPhone Developer: Invalid Profile'); testConfig.setValue('ios-signing-cert', 'iPhone Developer: Invalid Profile');
mockTerminalStdInStream = Stream<String>.value('3');
final Completer<void> completer = Completer<void>();
final StreamController<List<int>> controller = StreamController<List<int>>();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
command: <String>['which', 'security'],
),
const FakeCommand(
command: <String>['which', 'openssl'],
),
const FakeCommand(
command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
stdout: kCertificates,
),
const FakeCommand(
command: <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
stdout: 'This is a fake certificate',
),
FakeCommand(
command: const <String>['openssl', 'x509', '-subject'],
stdin: IOSink(controller.sink),
stdout: 'subject= /CN=iPhone Developer: Profile 3 (3333CCCC33)/OU=4444DDDD44/O=My Team/C=US',
completer: completer,
)
]);
// Verify that certifacte value is passed into openssl command.
String stdin;
controller.stream.listen((List<int> chunk) {
stdin = utf8.decode(chunk);
completer.complete();
});
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
); );
expect( expect(
logger.errorText.replaceAll('\n', ' '), logger.errorText,
contains('Saved signing certificate "iPhone Developer: Invalid Profile" is not a valid development certificate'), containsIgnoringWhitespace('Saved signing certificate "iPhone Developer: Invalid Profile" is not a valid development certificate'),
); );
expect( expect(
logger.statusText, logger.statusText,
contains('Certificate choice "iPhone Developer: Profile 3 (3333CCCC33)"'), contains('Certificate choice "iPhone Developer: Profile 3 (3333CCCC33)"'),
); );
expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '4444DDDD44'}); expect(signingConfigs, <String, String>{'DEVELOPMENT_TEAM': '4444DDDD44'});
expect(stdin, 'This is a fake certificate');
expect(testConfig.getValue('ios-signing-cert'), 'iPhone Developer: Profile 3 (3333CCCC33)'); expect(testConfig.getValue('ios-signing-cert'), 'iPhone Developer: Profile 3 (3333CCCC33)');
}); });
testWithoutContext('find-identity failure', () async { testWithoutContext('find-identity failure', () async {
when(mockProcessManager.run( final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
<String>['which', 'security'], const FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: <String>['which', 'security'],
environment: anyNamed('environment'), ),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); const FakeCommand(
when(mockProcessManager.run( command: <String>['which', 'openssl'],
<String>['which', 'openssl'], ),
workingDirectory: anyNamed('workingDirectory'), const FakeCommand(
environment: anyNamed('environment'), command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); exitCode: 1,
when(mockProcessManager.run( ),
argThat(contains('find-identity')), ]);
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(
ProcessResult(0, 1, '', '')
));
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -603,45 +462,30 @@ void main() { ...@@ -603,45 +462,30 @@ void main() {
}); });
testWithoutContext('find-certificate failure', () async { testWithoutContext('find-certificate failure', () async {
when(mockProcessManager.run( mockTerminalStdInStream = Stream<String>.value('3');
<String>['which', 'security'],
workingDirectory: anyNamed('workingDirectory'), final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
environment: anyNamed('environment'), const FakeCommand(
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); command: <String>['which', 'security'],
when(mockProcessManager.run( ),
<String>['which', 'openssl'], const FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: <String>['which', 'openssl'],
environment: anyNamed('environment'), ),
)).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy)); const FakeCommand(
when(mockProcessManager.run( command: <String>['security', 'find-identity', '-p', 'codesigning', '-v'],
argThat(contains('find-identity')), stdout: kCertificates,
environment: anyNamed('environment'), ),
workingDirectory: anyNamed('workingDirectory'), const FakeCommand(
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult( command: <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
1, // pid exitCode: 1,
0, // exitCode ),
''' ]);
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
3 valid identities found''',
'',
)));
mockTerminalStdInStream =
Stream<String>.fromFuture(Future<String>.value('3'));
when(mockProcessManager.run(
<String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(
ProcessResult(1, 1, '', '' ))
);
final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam( final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(
buildSettings: <String, String>{ buildSettings: <String, String>{
'bogus': 'bogus', 'bogus': 'bogus',
}, },
processManager: mockProcessManager, processManager: processManager,
logger: logger, logger: logger,
config: testConfig, config: testConfig,
terminal: testTerminal, terminal: testTerminal,
...@@ -651,25 +495,6 @@ void main() { ...@@ -651,25 +495,6 @@ void main() {
}); });
} }
final ProcessResult exitsHappy = ProcessResult(
1, // pid
0, // exitCode
'', // stdout
'', // stderr
);
final ProcessResult exitsFail = ProcessResult(
2, // pid
1, // exitCode
'', // stdout
'', // stderr
);
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
class MockStream extends Mock implements Stream<List<int>> {}
class MockStdIn extends Mock implements IOSink {}
Stream<String> mockTerminalStdInStream; Stream<String> mockTerminalStdInStream;
class TestTerminal extends AnsiTerminal { class TestTerminal extends AnsiTerminal {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment