mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
**This pull request is opened against a release branch.<br> To request a cherry pick of a commit, please fill in the form below.** (Questions with an asterisk are required.)<br> **To fill in the form, you can edit this PR description and type your answers after the 'My Answer' keywords. <br> A flutter domain expert will evaluate this cherry pick request shortly after ALL questions are answered.** * Issue Link: What is the link to the issue this cherry-pick is addressing?<br> <pre> <b>My Answer:</b> https://github.com/flutter/flutter/issues/140934 </pre> * Changelog Description: Explain this cherry pick in one line that is accessible to most Flutter developers See https://github.com/flutter/flutter/wiki/Hotfix-Documentation-Best-Practices for examples (Bug fix, feature, docs update, ...)<br> <pre> <b>My Answer:</b> This cherry pick enables code signing test to run on release branches. </pre> * Impacted Users: Approximately who will hit this issue (ex. all Flutter devs, Windows developers, all end-customers, apps using X framework feature)?<br> <pre> <b>My Answer:</b> Release engineers who run code signing tests on releases. </pre> * impact_description: What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping production app (the app crashes on launch)<br> <pre> <b>My Answer:</b> Enabling codesigning Test would test the release artifact, and make sure both binaries and bundles are code signed. </pre> * Workaround: Is there a workaround for this issue?<br> <pre> <b>My Answer:</b> We can verify manually, but enabling an automated Code signing test would be better. </pre> * Risk: What is the risk level of this cherry-pick?<br> <pre> <b>My Answer:</b> </pre> * Test Coverage: Are you confident that your fix is well-tested by automated tests?<br> <pre> <b>My Answer:</b> </pre> * Validation Steps: What are the steps to validate that this fix works?<br> <pre> <b>My Answer:</b> code sign test should run on post submit of release branches and pass </pre>
382 lines
12 KiB
Dart
382 lines
12 KiB
Dart
// 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.
|
|
|
|
@TestOn('mac-os')
|
|
library;
|
|
|
|
import '../../../packages/flutter_tools/test/src/fake_process_manager.dart';
|
|
import '../test.dart';
|
|
import './common.dart';
|
|
|
|
void main() async {
|
|
const String flutterRoot = '/a/b/c';
|
|
final List<String> allExpectedFiles = binariesWithEntitlements(flutterRoot) + binariesWithoutEntitlements(flutterRoot);
|
|
final String allFilesStdout = allExpectedFiles.join('\n');
|
|
final List<String> allExpectedXcframeworks = signedXcframeworks(flutterRoot);
|
|
final String allXcframeworksStdout = allExpectedXcframeworks.join('\n');
|
|
final List<String> withEntitlements = binariesWithEntitlements(flutterRoot);
|
|
|
|
group('verifyExist', () {
|
|
test('Not all files found', () async {
|
|
final ProcessManager processManager = FakeProcessManager.list(
|
|
<FakeCommand>[
|
|
const FakeCommand(
|
|
command: <String>[
|
|
'find',
|
|
'/a/b/c/bin/cache',
|
|
'-type',
|
|
'f',
|
|
],
|
|
stdout: '/a/b/c/bin/cache/artifacts/engine/android-arm-profile/darwin-x64/gen_snapshot',
|
|
),
|
|
const FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
'/a/b/c/bin/cache/artifacts/engine/android-arm-profile/darwin-x64/gen_snapshot',
|
|
],
|
|
stdout: 'application/x-mach-binary',
|
|
),
|
|
],
|
|
);
|
|
expect(
|
|
() async => verifyExist(flutterRoot, processManager: processManager),
|
|
throwsExceptionWith('Did not find all expected binaries!'),
|
|
);
|
|
});
|
|
|
|
test('All files found', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
final FakeCommand findCmd = FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'f',],
|
|
stdout: allFilesStdout,
|
|
);
|
|
commandList.add(findCmd);
|
|
for (final String expectedFile in allExpectedFiles) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
expectedFile,
|
|
],
|
|
stdout: 'application/x-mach-binary',
|
|
)
|
|
);
|
|
}
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
await expectLater(verifyExist('/a/b/c', processManager: processManager), completes);
|
|
});
|
|
});
|
|
|
|
group('find paths', () {
|
|
test('All binary files found', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
final FakeCommand findCmd = FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'f',],
|
|
stdout: allFilesStdout,
|
|
);
|
|
commandList.add(findCmd);
|
|
for (final String expectedFile in allExpectedFiles) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
expectedFile,
|
|
],
|
|
stdout: 'application/x-mach-binary',
|
|
)
|
|
);
|
|
}
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final List<String> foundFiles = await findBinaryPaths('$flutterRoot/bin/cache', processManager: processManager);
|
|
expect(foundFiles, allExpectedFiles);
|
|
});
|
|
|
|
test('Empty file list', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
const FakeCommand findCmd = FakeCommand(
|
|
command: <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'f',],
|
|
);
|
|
commandList.add(findCmd);
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final List<String> foundFiles = await findBinaryPaths('$flutterRoot/bin/cache', processManager: processManager);
|
|
expect(foundFiles, <String>[]);
|
|
});
|
|
|
|
test('All xcframeworks files found', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[
|
|
FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'd',
|
|
'-name',
|
|
'*xcframework',
|
|
],
|
|
stdout: allXcframeworksStdout,
|
|
)
|
|
];
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final List<String> foundFiles = await findXcframeworksPaths('$flutterRoot/bin/cache', processManager: processManager);
|
|
expect(foundFiles, allExpectedXcframeworks);
|
|
});
|
|
|
|
group('isBinary', () {
|
|
test('isTrue', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
const String fileToCheck = '/a/b/c/one.zip';
|
|
const FakeCommand findCmd = FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
fileToCheck,
|
|
],
|
|
stdout: 'application/x-mach-binary',
|
|
);
|
|
commandList.add(findCmd);
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final bool result = await isBinary(fileToCheck, processManager: processManager);
|
|
expect(result, isTrue);
|
|
});
|
|
|
|
test('isFalse', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
const String fileToCheck = '/a/b/c/one.zip';
|
|
const FakeCommand findCmd = FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
fileToCheck,
|
|
],
|
|
stdout: 'text/xml',
|
|
);
|
|
commandList.add(findCmd);
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final bool result = await isBinary(fileToCheck, processManager: processManager);
|
|
expect(result, isFalse);
|
|
});
|
|
});
|
|
|
|
group('hasExpectedEntitlements', () {
|
|
test('expected entitlements', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
const String fileToCheck = '/a/b/c/one.zip';
|
|
const FakeCommand codesignCmd = FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'--display',
|
|
'--entitlements',
|
|
':-',
|
|
fileToCheck,
|
|
],
|
|
);
|
|
commandList.add(codesignCmd);
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final bool result = await hasExpectedEntitlements(fileToCheck, flutterRoot, processManager: processManager);
|
|
expect(result, isTrue);
|
|
});
|
|
|
|
test('unexpected entitlements', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
const String fileToCheck = '/a/b/c/one.zip';
|
|
const FakeCommand codesignCmd = FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'--display',
|
|
'--entitlements',
|
|
':-',
|
|
fileToCheck,
|
|
],
|
|
exitCode: 1,
|
|
);
|
|
commandList.add(codesignCmd);
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
final bool result = await hasExpectedEntitlements(fileToCheck, flutterRoot, processManager: processManager);
|
|
expect(result, isFalse);
|
|
});
|
|
});
|
|
});
|
|
|
|
group('verifySignatures', () {
|
|
|
|
test('succeeds if every binary is codesigned and has correct entitlements', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
final FakeCommand findCmd = FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'f',],
|
|
stdout: allFilesStdout,
|
|
);
|
|
commandList.add(findCmd);
|
|
for (final String expectedFile in allExpectedFiles) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
expectedFile,
|
|
],
|
|
stdout: 'application/x-mach-binary',
|
|
)
|
|
);
|
|
}
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'd',
|
|
'-name',
|
|
'*xcframework',
|
|
],
|
|
stdout: allXcframeworksStdout,
|
|
),
|
|
);
|
|
for (final String expectedFile in allExpectedFiles) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'-vvv',
|
|
expectedFile,
|
|
],
|
|
)
|
|
);
|
|
if (withEntitlements.contains(expectedFile)) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'--display',
|
|
'--entitlements',
|
|
':-',
|
|
expectedFile,
|
|
],
|
|
stdout: expectedEntitlements.join('\n'),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
for (final String expectedXcframework in allExpectedXcframeworks) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'-vvv',
|
|
expectedXcframework,
|
|
],
|
|
)
|
|
);
|
|
}
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
await expectLater(verifySignatures(flutterRoot, processManager: processManager), completes);
|
|
});
|
|
|
|
test('fails if binaries do not have the right entitlements', () async {
|
|
final List<FakeCommand> commandList = <FakeCommand>[];
|
|
final FakeCommand findCmd = FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'f',],
|
|
stdout: allFilesStdout,
|
|
);
|
|
commandList.add(findCmd);
|
|
for (final String expectedFile in allExpectedFiles) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'file',
|
|
'--mime-type',
|
|
'-b',
|
|
expectedFile,
|
|
],
|
|
stdout: 'application/x-mach-binary',
|
|
)
|
|
);
|
|
}
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: const <String>[
|
|
'find',
|
|
'$flutterRoot/bin/cache',
|
|
'-type',
|
|
'd',
|
|
'-name',
|
|
'*xcframework',
|
|
],
|
|
stdout: allXcframeworksStdout,
|
|
),
|
|
);
|
|
for (final String expectedFile in allExpectedFiles) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'-vvv',
|
|
expectedFile,
|
|
],
|
|
)
|
|
);
|
|
if (withEntitlements.contains(expectedFile)) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'--display',
|
|
'--entitlements',
|
|
':-',
|
|
expectedFile,
|
|
],
|
|
)
|
|
);
|
|
}
|
|
}
|
|
for (final String expectedXcframework in allExpectedXcframeworks) {
|
|
commandList.add(
|
|
FakeCommand(
|
|
command: <String>[
|
|
'codesign',
|
|
'-vvv',
|
|
expectedXcframework,
|
|
],
|
|
)
|
|
);
|
|
}
|
|
final ProcessManager processManager = FakeProcessManager.list(commandList);
|
|
|
|
expect(
|
|
() async => verifySignatures(flutterRoot, processManager: processManager),
|
|
throwsExceptionWith('Test failed because files found with the wrong entitlements'),
|
|
);
|
|
});
|
|
});
|
|
}
|