From 91f0878fedb61342535312ef35e71d04525e19c6 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Fri, 26 Jan 2024 10:04:09 -0800 Subject: [PATCH] Move iOS content validation devicelab test into tool integration test (#142272) The archiving was running in devicelab because certs are needed to codesign (see #73577). However now the certs are available in chromium bots. Move the archiving test into the existing tool integration test, and delete the devicelab variant. arm64: https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8757886514651624673/+/u/run_test.dart_for_tool_host_cross_arch_tests_shard_and_subshard_None/test_stdout#L6074_4 x64: https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8757886514651624689/+/u/run_test.dart_for_tool_host_cross_arch_tests_shard_and_subshard_None/test_stdout#L6389_2 Part of https://github.com/flutter/flutter/issues/142070 --- .ci.yaml | 19 --- TESTOWNERS | 1 - .../tasks/ios_content_validation_test.dart | 118 ------------------ .../ios_content_validation_test.dart | 105 +++++++++++++++- 4 files changed, 104 insertions(+), 139 deletions(-) delete mode 100644 dev/devicelab/bin/tasks/ios_content_validation_test.dart diff --git a/.ci.yaml b/.ci.yaml index 325da96e24..7a1706d9ce 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -4520,25 +4520,6 @@ targets: ["devicelab", "hostonly", "mac", "arm64"] task_name: ios_app_with_extensions_test - - name: Mac_x64_ios ios_content_validation_test - recipe: devicelab/devicelab_drone - bringup: true - presubmit: false - timeout: 60 - properties: - tags: > - ["devicelab", "ios", "mac"] - task_name: ios_content_validation_test - - - name: Mac_arm64_ios ios_content_validation_test - recipe: devicelab/devicelab_drone - presubmit: false - timeout: 60 - properties: - tags: > - ["devicelab", "ios", "mac", "arm64"] - task_name: ios_content_validation_test - - name: Mac_ios ios_defines_test recipe: devicelab/devicelab_drone presubmit: false diff --git a/TESTOWNERS b/TESTOWNERS index 8f918a4a3b..ec301b021f 100644 --- a/TESTOWNERS +++ b/TESTOWNERS @@ -195,7 +195,6 @@ /dev/devicelab/bin/tasks/integration_ui_ios_screenshot.dart @vashworth @flutter/tool /dev/devicelab/bin/tasks/integration_ui_ios_textfield.dart @vashworth @flutter/tool /dev/devicelab/bin/tasks/ios_app_with_extensions_test.dart @vashworth @flutter/tool -/dev/devicelab/bin/tasks/ios_content_validation_test.dart @christopherfujino @flutter/tool /dev/devicelab/bin/tasks/ios_defines_test.dart @vashworth @flutter/tool /dev/devicelab/bin/tasks/ios_picture_cache_complexity_scoring_perf__timeline_summary.dart @flar @flutter/engine /dev/devicelab/bin/tasks/ios_platform_view_tests.dart @stuartmorgan @flutter/plugin diff --git a/dev/devicelab/bin/tasks/ios_content_validation_test.dart b/dev/devicelab/bin/tasks/ios_content_validation_test.dart deleted file mode 100644 index 156c509b54..0000000000 --- a/dev/devicelab/bin/tasks/ios_content_validation_test.dart +++ /dev/null @@ -1,118 +0,0 @@ -// 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 'dart:io'; - -import 'package:flutter_devicelab/framework/apk_utils.dart'; -import 'package:flutter_devicelab/framework/framework.dart'; -import 'package:flutter_devicelab/framework/task_result.dart'; -import 'package:flutter_devicelab/framework/utils.dart'; -import 'package:path/path.dart' as path; - -Future main() async { - await task(() async { - try { - await runProjectTest((FlutterProject flutterProject) async { - section('Archive'); - - await inDirectory(flutterProject.rootPath, () async { - final File appIconFile = File(path.join( - flutterProject.rootPath, - 'ios', - 'Runner', - 'Assets.xcassets', - 'AppIcon.appiconset', - 'Icon-App-20x20@1x.png', - )); - // Resizes app icon to 123x456 (it is supposed to be 20x20). - appIconFile.writeAsBytesSync(appIconFile.readAsBytesSync() - ..buffer.asByteData().setInt32(16, 123) - ..buffer.asByteData().setInt32(20, 456) - ); - - final String output = await evalFlutter('build', options: [ - 'xcarchive', - '-v', - ]); - - // Note this isBot so usage won't actually be sent, - // this log line is printed whenever the app is archived. - if (!output.contains('Sending archive event if usage enabled')) { - throw TaskResult.failure('Usage archive event not sent'); - } - - // The output contains extra time related prefix, so cannot use a single string. - const List expectedValidationMessages = [ - '[!] App Settings Validation\n', - ' • Version Number: 1.0.0\n', - ' • Build Number: 1\n', - ' • Display Name: Hello\n', - ' • Deployment Target: 12.0\n', - ' • Bundle Identifier: com.example.hello\n', - ' ! Your application still contains the default "com.example" bundle identifier.\n', - '[!] App Icon and Launch Image Assets Validation\n', - ' ! App icon is set to the default placeholder icon. Replace with unique icons.\n', - ' ! App icon is using the incorrect size (e.g. Icon-App-20x20@1x.png).\n', - ' ! Launch image is set to the default placeholder icon. Replace with unique launch image.\n', - 'To update the settings, please refer to https://docs.flutter.dev/deployment/ios\n', - ]; - if (expectedValidationMessages.any((String message) => !output.contains(message))) { - throw TaskResult.failure('Must have the expected validation message'); - } - }); - - final String archivePath = path.join( - flutterProject.rootPath, - 'build', - 'ios', - 'archive', - 'Runner.xcarchive', - ); - - final String products = path.join(archivePath, 'Products'); - - checkDirectoryExists(products); - - checkDirectoryExists(path.join( - archivePath, - 'dSYMs', - 'Runner.app.dSYM', - )); - final Directory applications = Directory(path.join(products, 'Applications')); - - final Directory appBundle = applications - .listSync() - .whereType() - .singleWhere((Directory directory) => path.extension(directory.path) == '.app'); - - final String flutterFramework = path.join( - appBundle.path, - 'Frameworks', - 'Flutter.framework', - 'Flutter', - ); - // Exits 0 only if codesigned. - final Future flutterCodesign = - eval('xcrun', ['codesign', '--verify', flutterFramework]); - - final String appFramework = path.join( - appBundle.path, - 'Frameworks', - 'App.framework', - 'App', - ); - final Future appCodesign = - eval('xcrun', ['codesign', '--verify', appFramework]); - await flutterCodesign; - await appCodesign; - }); - - return TaskResult.success(null); - } on TaskResult catch (taskResult) { - return taskResult; - } catch (e) { - return TaskResult.failure(e.toString()); - } - }); -} diff --git a/packages/flutter_tools/test/host_cross_arch.shard/ios_content_validation_test.dart b/packages/flutter_tools/test/host_cross_arch.shard/ios_content_validation_test.dart index 8b68c28be8..2e0587524e 100644 --- a/packages/flutter_tools/test/host_cross_arch.shard/ios_content_validation_test.dart +++ b/packages/flutter_tools/test/host_cross_arch.shard/ios_content_validation_test.dart @@ -354,7 +354,110 @@ void main() { expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library x86_64')); expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library arm64')); }); + + testWithoutContext('archive', () { + final File appIconFile = fileSystem.file(fileSystem.path.join( + projectRoot, + 'ios', + 'Runner', + 'Assets.xcassets', + 'AppIcon.appiconset', + 'Icon-App-20x20@1x.png', + )); + // Resizes app icon to 123x456 (it is supposed to be 20x20). + appIconFile.writeAsBytesSync(appIconFile.readAsBytesSync() + ..buffer.asByteData().setInt32(16, 123) + ..buffer.asByteData().setInt32(20, 456)); + + final ProcessResult output = processManager.runSync( + [ + flutterBin, + ...getLocalEngineArguments(), + 'build', + 'xcarchive', + '--verbose', + ], + workingDirectory: projectRoot, + ); + + // Note this isBot so usage won't actually be sent, + // this log line is printed whenever the app is archived. + expect(output.stdout, contains('Sending archive event if usage enabled')); + + // The output contains extra time related prefix, so cannot use a single string. + const List expectedValidationMessages = [ + '[!] App Settings Validation\n', + ' • Version Number: 1.0.0\n', + ' • Build Number: 1\n', + ' • Display Name: Hello\n', + ' • Deployment Target: 12.0\n', + ' • Bundle Identifier: com.example.hello\n', + ' ! Your application still contains the default "com.example" bundle identifier.\n', + '[!] App Icon and Launch Image Assets Validation\n', + ' ! App icon is set to the default placeholder icon. Replace with unique icons.\n', + ' ! App icon is using the incorrect size (e.g. Icon-App-20x20@1x.png).\n', + ' ! Launch image is set to the default placeholder icon. Replace with unique launch image.\n', + 'To update the settings, please refer to https://docs.flutter.dev/deployment/ios\n', + ]; + expect(expectedValidationMessages, unorderedEquals(expectedValidationMessages)); + + final Directory archivePath = fileSystem.directory(fileSystem.path.join( + projectRoot, + 'build', + 'ios', + 'archive', + 'Runner.xcarchive', + )); + + final Directory products = archivePath.childDirectory('Products'); + expect(products, exists); + + final Directory dSYM = archivePath.childDirectory('dSYMs').childDirectory('Runner.app.dSYM'); + expect(dSYM, exists); + + final Directory applications = products.childDirectory('Applications'); + + final Directory appBundle = applications + .listSync() + .whereType() + .singleWhere((Directory directory) => fileSystem.path.extension(directory.path) == '.app'); + + final String flutterFramework = fileSystem.path.join( + appBundle.path, + 'Frameworks', + 'Flutter.framework', + 'Flutter', + ); + + // Exits 0 only if codesigned. + final ProcessResult flutterCodesign = processManager.runSync( + [ + 'xcrun', + 'codesign', + '--verify', + flutterFramework, + ], + ); + expect(flutterCodesign, const ProcessResultMatcher()); + + final String appFramework = fileSystem.path.join( + appBundle.path, + 'Frameworks', + 'App.framework', + 'App', + ); + + final ProcessResult appCodesign = processManager.runSync( + [ + 'xcrun', + 'codesign', + '--verify', + appFramework, + ], + ); + expect(appCodesign, const ProcessResultMatcher()); + }); }, skip: !platform.isMacOS, // [intended] only makes sense for macos platform. - timeout: const Timeout(Duration(minutes: 7)) + timeout: const Timeout(Duration(minutes: 10)) ); }