From 2f8d64e67022530068cec3f119343787f0ae45bc Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 8 Sep 2022 13:42:26 -0700 Subject: [PATCH] Squash of flutter-preview-device-3 branch: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit preview preview ++ ++ ++ ++ ++ rename artifact fix compilation remove test diff restore changes to examples get flutter build _preview working hack prepare_package.dart wip fix test fix another test migrate more fix another test fix more fix more fix another test fix test fix another test fix last test add test wip get compiling fix build_preview.dart path get build preview and run -d preview to use artifact cleanup todos and a test fix unit test cleanup restore usptream prepare_package.dart fix test fix commands/build_test fix hermetic/build_linux_test.dart fix hermetic/build_macos_test fix hermetic/build_test.dart fix test fix hermetic/build_ipa_test.dart fix build_ios_test.dart add more tests fix build_ios_test cleanup some todos, do not require pubspec.yaml in working dir fix test Convert relative to absolute import. (#135337) Requested here: https://github.com/flutter/flutter/pull/133952#discussion_r1334860858 Move some tests from staging to prod (#135333) This PR moves tests running on Pixel 7 Pro that use Skia from staging to prod. [iOS,macOS] Clean up obsolete PlatformView warning (#135040) PlatformViews have been supported without a custom engine build on iOS for quite some time now, and are nearing support for macOS. Adds a link to the website documentation covering creation of PlatformViews for iOS and adds a TODO to do the same once the macOS PlatformView documentation is ready. Related: https://github.com/flutter/website/issues/9424 Roll Flutter Engine from e4bfdc1a67de to 564480337eae (4 revisions) (#135341) https://github.com/flutter/engine/compare/e4bfdc1a67de...564480337eae 2023-09-22 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from ZyajVWocCHVIuJkzM... to M9rDyhmn7VY4iTxzQ... (flutter/engine#46215) 2023-09-22 skia-flutter-autoroll@skia.org Roll Dart SDK from 4ddff752a6b0 to 692273b46610 (1 revision) (flutter/engine#46212) 2023-09-22 skia-flutter-autoroll@skia.org Roll Skia from 78fced84372d to e9358f92110c (4 revisions) (flutter/engine#46211) 2023-09-22 bdero@google.com [Impeller] Incorporate backdrop filters in subpass coverage. (flutter/engine#46130) Also rolling transitive DEPS: fuchsia/sdk/core/mac-amd64 from ZyajVWocCHVI to M9rDyhmn7VY4 If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 564480337eae to 614859053262 (7 revisions) (#135362) https://github.com/flutter/engine/compare/564480337eae...614859053262 2023-09-23 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from M9rDyhmn7VY4iTxzQ... to de4D1aoqF6LBk18Rd... (flutter/engine#46229) 2023-09-23 ychris@google.com [ios] Fix default assets url (flutter/engine#46214) 2023-09-23 skia-flutter-autoroll@skia.org Roll Skia from 15ccdeaba011 to 983f42f4c76b (1 revision) (flutter/engine#46223) 2023-09-23 chillers@google.com Revert "[Impeller] fail if software backend is chosen and Impeller is enabled on iOS" (flutter/engine#46217) 2023-09-23 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from QcxgV9KlY7j3o3b4j... to PCEkaltiQ-iEKlmEj... (flutter/engine#46221) 2023-09-22 jonahwilliams@google.com [Impeller] dont treat non-rects as rects. (flutter/engine#46218) 2023-09-22 skia-flutter-autoroll@skia.org Roll Skia from e9358f92110c to 15ccdeaba011 (1 revision) (flutter/engine#46216) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from QcxgV9KlY7j3 to PCEkaltiQ-iE fuchsia/sdk/core/mac-amd64 from M9rDyhmn7VY4 to de4D1aoqF6LB If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 614859053262 to ee27600dfbe2 (1 revision) (#135364) https://github.com/flutter/engine/compare/614859053262...ee27600dfbe2 2023-09-23 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from PCEkaltiQ-iEKlmEj... to M-fNM9YP2Lpc8Y_Dj... (flutter/engine#46231) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from PCEkaltiQ-iE to M-fNM9YP2Lpc If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Marks Linux_android opacity_peephole_grid_of_alpha_savelayers_perf__e2e_summary to be flaky (#135119) Issue link: https://github.com/flutter/flutter/issues/135118 Marks Linux_android flutter_gallery__start_up_delayed to be flaky (#134632) Issue link: https://github.com/flutter/flutter/issues/134631 Marks Linux_android platform_channels_benchmarks to be flaky (#135106) Issue link: https://github.com/flutter/flutter/issues/135105 Marks Mac_ios static_path_tessellation_perf_ios__timeline_summary to be unflaky (#133127) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20static_path_tessellation_perf_ios__timeline_summary%22). This test can be marked as unflaky. Marks Mac_ios animated_advanced_blend_perf_ios__timeline_summary to be unflaky (#132630) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20animated_advanced_blend_perf_ios__timeline_summary%22). This test can be marked as unflaky. Marks Mac_ios very_long_picture_scrolling_perf_ios__e2e_summary to be unflaky (#134629) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20very_long_picture_scrolling_perf_ios__e2e_summary%22). This test can be marked as unflaky. Roll Flutter Engine from ee27600dfbe2 to 2daf5e7bb249 (1 revision) (#135371) https://github.com/flutter/engine/compare/ee27600dfbe2...2daf5e7bb249 2023-09-24 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from de4D1aoqF6LBk18Rd... to W1uZC0_FbXyoCmwJ1... (flutter/engine#46238) Also rolling transitive DEPS: fuchsia/sdk/core/mac-amd64 from de4D1aoqF6LB to W1uZC0_FbXyo If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Marks Linux_pixel_7pro picture_cache_perf__timeline_summary to be unflaky (#134118) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Linux_pixel_7pro%20picture_cache_perf__timeline_summary%22). This test can be marked as unflaky. Marks Mac_ios draw_points_perf_ios__timeline_summary to be unflaky (#127933) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20draw_points_perf_ios__timeline_summary%22). This test can be marked as unflaky. Marks Mac_ios dynamic_path_tessellation_perf_ios__timeline_summary to be unflaky (#133128) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20dynamic_path_tessellation_perf_ios__timeline_summary%22). This test can be marked as unflaky. Marks Windows module_test to be unflaky (#134121) The issue https://github.com/flutter/flutter/issues/133639 has been closed, and the test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Windows%20module_test%22). This test can be marked as unflaky. Marks Mac_ios draw_vertices_perf_ios__timeline_summary to be unflaky (#134625) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20draw_vertices_perf_ios__timeline_summary%22). This test can be marked as unflaky. Marks Mac_ios draw_atlas_perf_ios__timeline_summary to be unflaky (#134626) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Mac_ios%20draw_atlas_perf_ios__timeline_summary%22). This test can be marked as unflaky. Marks Windows_android channels_integration_test_win to be unflaky (#135374) The issue https://github.com/flutter/flutter/issues/134636 has been closed, and the test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Windows_android%20channels_integration_test_win%22). This test can be marked as unflaky. Marks Linux_pixel_7pro hello_world_impeller to be unflaky (#135372) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Linux_pixel_7pro%20hello_world_impeller%22). This test can be marked as unflaky. Fix failing test at master. (#135394) Marks Linux_samsung_a02 new_gallery__transition_perf to be unflaky (#135373) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Linux_samsung_a02%20new_gallery__transition_perf%22). This test can be marked as unflaky. Revert "Marks Linux_samsung_a02 new_gallery__transition_perf to be unflaky" (#135399) Reverts flutter/flutter#135373 Add a basic golden test for `CupertinoTextSelectionToolbar` (#135267) Goden tests are easier to understand than `paints..` since the toolbar has a relatively complex path, and this should make PRs that make visual changes easier to review. The current goldens don't look correct since I messed up the y offset of the tip of the arrow when the arrow is pointing up. Should be fixed in https://github.com/flutter/flutter/pull/133386 Roll Flutter Engine from 2daf5e7bb249 to 3ea1174ecfaa (4 revisions) (#135396) https://github.com/flutter/engine/compare/2daf5e7bb249...3ea1174ecfaa 2023-09-25 zanderso@users.noreply.github.com In run_tests.py, separate Dart package unit tests from other tests (flutter/engine#46232) 2023-09-24 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from SqWjDvrDsMfiisUoA... to VKAiabs4VzJ1Py-oA... (flutter/engine#46241) 2023-09-24 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from W1uZC0_FbXyoCmwJ1... to 0Jl20zAW45rRsTNEu... (flutter/engine#46240) 2023-09-24 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from M-fNM9YP2Lpc8Y_Dj... to SqWjDvrDsMfiisUoA... (flutter/engine#46239) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from M-fNM9YP2Lpc to VKAiabs4VzJ1 fuchsia/sdk/core/mac-amd64 from W1uZC0_FbXyo to 0Jl20zAW45rR If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 3ea1174ecfaa to e1c1022c2d6d (2 revisions) (#135403) https://github.com/flutter/engine/compare/3ea1174ecfaa...e1c1022c2d6d 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from 983f42f4c76b to b8bc0c080aa8 (1 revision) (flutter/engine#46247) 2023-09-25 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from 0Jl20zAW45rRsTNEu... to SNqQGAfjWL3PbUABh... (flutter/engine#46246) Also rolling transitive DEPS: fuchsia/sdk/core/mac-amd64 from 0Jl20zAW45rR to SNqQGAfjWL3P If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from e1c1022c2d6d to e6d3bac5c723 (2 revisions) (#135410) https://github.com/flutter/engine/compare/e1c1022c2d6d...e6d3bac5c723 2023-09-25 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from VKAiabs4VzJ1Py-oA... to uY9WEf2tJxa1Hpp4v... (flutter/engine#46252) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from b8bc0c080aa8 to 31ceb1669d1c (1 revision) (flutter/engine#46249) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from VKAiabs4VzJ1 to uY9WEf2tJxa1 If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Revert "Marks Linux_pixel_7pro hello_world_impeller to be unflaky" (#135388) Reverts flutter/flutter#135372 Roll Flutter Engine from e6d3bac5c723 to 2c4c1108aa87 (1 revision) (#135424) https://github.com/flutter/engine/compare/e6d3bac5c723...2c4c1108aa87 2023-09-25 49699333+dependabot[bot]@users.noreply.github.com Bump archive from 3.3.9 to 3.4.2 in /lib/web_ui (flutter/engine#46253) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Packages from 98ebcd3d9c05 to e548ae1d2045 (5 revisions) (#135431) https://github.com/flutter/packages/compare/98ebcd3d9c05...e548ae1d2045 2023-09-23 49699333+dependabot[bot]@users.noreply.github.com Bump github/codeql-action from 2.21.7 to 2.21.8 (flutter/packages#4952) 2023-09-23 engine-flutter-autoroll@skia.org Manual roll Flutter from 893650416352 to f92884c7b846 (48 revisions) (flutter/packages#4985) 2023-09-22 geral.sbi2@gmail.com [image_picker_android] check if data from result is empty when picking a single img or video (flutter/packages#4836) 2023-09-22 me@nils.re [camera_android] Removes usage of `_ambiguate` method in tests (flutter/packages#4948) 2023-09-22 49699333+dependabot[bot]@users.noreply.github.com [sign_in]: Bump com.google.android.gms:play-services-auth from 20.6.0 to 20.7.0 in /packages/google_sign_in/google_sign_in_android/android (flutter/packages#4841) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 2c4c1108aa87 to 1ae3d20332f0 (4 revisions) (#135438) https://github.com/flutter/engine/compare/2c4c1108aa87...1ae3d20332f0 2023-09-25 54558023+keyonghan@users.noreply.github.com Switch goma to reclient for Linux host engine targets (flutter/engine#45884) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from 7a49397a02b4 to e16a9b5b2c48 (1 revision) (flutter/engine#46258) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from 569a30fbdbdf to 7a49397a02b4 (2 revisions) (flutter/engine#46257) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from 31ceb1669d1c to 569a30fbdbdf (1 revision) (flutter/engine#46256) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md simulatedAccessibilityTraversal account for force merging (#135178) fixes https://github.com/flutter/flutter/issues/135144 [Velocity Tracker] Fix: Issue 97761: Flutter Scrolling does not match iOS; inadvertent scrolling when user lifts up finger (#132291) **Issue:** https://github.com/flutter/flutter/issues/97761 https://github.com/flutter/flutter/assets/1863934/53c5e0df-b85a-483c-a17d-bddd18db3aa9 The bug is very simple to understand - `velocity_tracker.dart` **only adds new samples while your finger is moving**. **Therefore**, if you move your finger quickly & (important) stop suddenly with no extra movement, the last 3 samples will all be > 0 dy. Regardless of how long you wait, you will get movement when you lift up your finger. **Logs from velocity_tracker.dart:** Notice: all 3 `_previousVelocityAt` are `dy > 0` despite a 2 second delay since the last scroll ``` // start moving finger flutter: addPosition dy:-464.0 flutter: addPosition dy:-465.0 flutter: addPosition dy:-466.0 flutter: addPosition dy:-467.0 flutter: addPosition dy:-468.0 flutter: addPosition dy:-469.0 flutter: addPosition dy:-470.0 // stop moving finger here, keep it still for 2 seconds & lift it up flutter: _previousVelocityAt(-2) samples(-467.0, -468.0)) dy:-176.772140710624 flutter: _previousVelocityAt(-1) samples(-468.0, -469.0)) dy:-375.0937734433609 flutter: _previousVelocityAt(0) samples(-469.0, -470.0)) dy:-175.71604287471447 flutter: primaryVelocity DragEndDetails(Velocity(0.0, -305.5)).primaryVelocity flutter: createBallisticSimulation pixels 464.16666666666663 velocity 305.4699824197211 ``` **There are 3 options to fix it:** A. sample uniformly *per unit time* (a larger more risky change, hurts battery life) B. consider elapsed time since the last sample. If greater than X, assume no more velocity. (easy & just as valid) C. similar to B, but instead add "ghost samples" of velocity zero, and run calculations as normal (a bit tricker, of dubious benefit imo) **For Option B I considered two approaches:** 1. _get the current timestamp and compare to event timestamp._ This is tricky because events are documented to use an arbitrary timescale & I wasn't able to find the code that generates the timestamps. This approach could be considered more. 2. _get a new timestamp using Stopwatch and compare now vs when the last sample was added._ This is the solution implemented here. There is a limitation in that we don't know when addSamples is called relative to the event. But, this estimation is already on a very low latency path & still it gives us a *minimum* time bound which is sufficient for comparison. **This PR chooses the simplest of the all solutions. Please try it our yourself, it completely solves the problem 😀** Option _B.1_ would be a nice alternative as well, if we can define and access the same timesource as the pointer tracker in a maintainable simple way. https://github.com/flutter/flutter/assets/1863934/be50d8e7-d5da-495a-a4af-c71bc541cbe3 Fix and Test Conditional Validator Behavior in FormField (#132714) In the FormField widget, if a validator is initially set (and validation fails), then subsequently the validator is set to null, the form incorrectly retains its error state. This is not expected behavior as removing the validator should clear any validation errors. [macOS,iOS] Improve CocoaPods upgrade instructions (#135453) In our CocoaPods doctor check, if the version of CocoaPods is found to be too low, rather than emitting a link to the install instructions, emit a link to the upgrade instructions. Since this check operates on CocoaPodsStatus, an enum, swtich to using a case statement and cover all cases. - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [X] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat Roll Flutter Engine from 1ae3d20332f0 to 3f606570ac7c (6 revisions) (#135457) https://github.com/flutter/engine/compare/1ae3d20332f0...3f606570ac7c 2023-09-25 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Switch goma to reclient for Linux clang_tidy targets" (flutter/engine#46267) 2023-09-25 43759233+kenzieschmoll@users.noreply.github.com Add description to assert in `history.dart` (flutter/engine#46072) 2023-09-25 54558023+keyonghan@users.noreply.github.com Switch goma to reclient for Linux clang_tidy targets (flutter/engine#45898) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from e16a9b5b2c48 to a19a325cd670 (6 revisions) (flutter/engine#46261) 2023-09-25 skia-flutter-autoroll@skia.org Roll Dart SDK from 692273b46610 to 216b25f9ea6f (6 revisions) (flutter/engine#46260) 2023-09-25 54558023+keyonghan@users.noreply.github.com Switch goma to reclient for Linux fuchsia/unopt/android_aot (flutter/engine#45899) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 3f606570ac7c to 6bf8067392cf (8 revisions) (#135472) https://github.com/flutter/engine/compare/3f606570ac7c...6bf8067392cf 2023-09-25 54558023+keyonghan@users.noreply.github.com Restore goma from rbe before 3.16 branching (flutter/engine#46272) 2023-09-25 bkonyi@google.com Add package:tar to DEPS to fix broken 3H configurations (flutter/engine#46273) 2023-09-25 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from SNqQGAfjWL3PbUABh... to we5owZaebdO_3kyjz... (flutter/engine#46270) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from a19a325cd670 to 00e4d00021a7 (6 revisions) (flutter/engine#46269) 2023-09-25 jonahwilliams@google.com [Impeller] fallback to position data if texture coordinates are undefined. (flutter/engine#46264) 2023-09-25 ian@mckellar.org fuchsia: Update FIDL for unknown interactions (flutter/engine#45773) 2023-09-25 jonahwilliams@google.com [Engine] use QoS classes in iOS engine. (flutter/engine#46265) 2023-09-25 jonahwilliams@google.com Revert "Switch goma to reclient for Linux clang_tidy targets (#45898)" (flutter/engine#46266) Also rolling transitive DEPS: fuchsia/sdk/core/mac-amd64 from SNqQGAfjWL3P to we5owZaebdO_ If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Add "Frame Request Pending" lag to collected metrics (#135279) This measures the wall clock time between a new frame being scheduled in dart code to the Vsync callback in the engine It's an important source of lag which isn't shown in the top-level UI / Build time graphs, and can correlate with "invisible" missed/non-scheduled frames I had to change a few unrelated timings in the test, it was only passing based on luck of sort order, and broke when I added more entries to the timeline. Part of #129150 Roll Flutter Engine from 6bf8067392cf to 75950dc280d5 (4 revisions) (#135480) https://github.com/flutter/engine/compare/6bf8067392cf...75950dc280d5 2023-09-26 skia-flutter-autoroll@skia.org Roll Dart SDK from 216b25f9ea6f to 7c749713c688 (1 revision) (flutter/engine#46284) 2023-09-25 bdero@google.com [Impeller] Support applying color filters on the CPU for the RRect fast path. (flutter/engine#46281) 2023-09-25 skia-flutter-autoroll@skia.org Roll Skia from 00e4d00021a7 to b961fc353715 (6 revisions) (flutter/engine#46280) 2023-09-25 jonahwilliams@google.com [Impeller] Dont blow away coverage hint on advanced blends. (flutter/engine#46219) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jonahwilliams@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 75950dc280d5 to 230dfeed79ed (3 revisions) (#135489) https://github.com/flutter/engine/compare/75950dc280d5...230dfeed79ed 2023-09-26 skia-flutter-autoroll@skia.org Roll Dart SDK from 7c749713c688 to 7c3588c05f87 (1 revision) (flutter/engine#46288) 2023-09-26 godofredoc@google.com Prepare fuchsia script to coexist with v1 and v2 of fuchsia builders. (flutter/engine#46126) 2023-09-26 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from uY9WEf2tJxa1Hpp4v... to a56c8yPp4DDlj_Qbl... (flutter/engine#46285) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from uY9WEf2tJxa1 to a56c8yPp4DDl If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jacksongardner@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 230dfeed79ed to 7b989a28514e (2 revisions) (#135494) https://github.com/flutter/engine/compare/230dfeed79ed...7b989a28514e 2023-09-26 skia-flutter-autoroll@skia.org Roll Skia from b961fc353715 to 8264a73430de (1 revision) (flutter/engine#46289) 2023-09-26 49699333+dependabot[bot]@users.noreply.github.com Bump actions/checkout from 4.0.0 to 4.1.0 (flutter/engine#46290) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jacksongardner@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Packages from e548ae1d2045 to 619af75f7966 (4 revisions) (#135505) https://github.com/flutter/packages/compare/e548ae1d2045...619af75f7966 2023-09-25 47866232+chunhtai@users.noreply.github.com [go_router] Fixes the Android back button ignores top level route's o… (flutter/packages#4984) 2023-09-25 49699333+dependabot[bot]@users.noreply.github.com Bump actions/checkout from 4.0.0 to 4.1.0 (flutter/packages#4988) 2023-09-25 34871572+gmackall@users.noreply.github.com [camera_android] Set buildconfig to true for compatibility with AGP 8.0+ (flutter/packages#4951) 2023-09-25 stuartmorgan@google.com [various] Remove obsolete symlinks (flutter/packages#4993) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Wait for CONFIGURATION_BUILD_DIR to update when debugging with Xcode (#135444) So there appears to be a race situation between the flutter CLI and Xcode. In the CLI, we update the `CONFIGURATION_BUILD_DIR` in the Xcode build settings and then tell Xcode to install, launch, and debug the app. When Xcode installs the app, it should use the `CONFIGURATION_BUILD_DIR` to find the bundle. However, it appears that sometimes Xcode hasn't processed the change to the build settings before the install happens, which causes it to not be able to find the bundle. Fixes https://github.com/flutter/flutter/issues/135442 --- Since it's a timing issue, there's not really a consistent way to test it. I was able to confirm that it works, though, by using the following steps: 1. Create a flutter project 2. Open the project in Xcode 3. `flutter clean` 4. `flutter run --profile -v` If I saw a print line `stderr: CONFIGURATION_BUILD_DIR: build/Debug-iphoneos`, that means it first found the old and incorrect `CONFIGURATION_BUILD_DIR` before updating to the the new, so I was able to confirm that it would wait until it updated. [Windows] Add more Arm64 compile and run tests (#135475) Part of: https://github.com/flutter/flutter/issues/129806 Test runs kicked off using `led`: * Compile tests * ✅ [flutter_gallery_win_desktop__compile](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/a23b73ca25cc56309a725c77be0107aaa1f2d09b1f41f1cc04276b85fac34366/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR2Yv8iS9YbTxMZKS2i5zmAz9E8FCNjW6waLq4e8HwtaFtMlapl66UHf73w) * Start up tests * ✅ [windows_startup_test](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/e615b28993c8b4fcb90e2d52226f9e4d9478850bee67f1f19a88d37e767dcfc2/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR1YtPTpAr6FRq71fy392orp6PO8t9jN8n-mpWvlDF0xRnnOsq3zsAPabWg) * ✅ [flutter_gallery_win_desktop__start_up](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/a0148122f81f3eee512ba8e59adcfcff86195eac10dc9a95969b36ae63e0d3e0/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR29O3jW-LyaVAwD54jUmnhfZ2mswqtaZascRoGvteT5gaHihxKI4IastgM) * ✅ [flutter_view_win_desktop__start_up](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/6dac552365a2d5502aeda81563f4e62f7bdb73f383d98ed8d8ae52c62e00edea/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR2_irHDuoZ0V-PSjYDW082yx8ZeDVhOIk0yjQBAZNVa5iKVIGAWZs8v4lo) * ✅ [platform_view_win_desktop__start_up](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/e6522c77bcbecabdd1f6d38f3b4e1ea41055d8ae7d61f92b741cc953b94d2e15/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR2X7KJDGjQUWJtpq7KY-nUFK-LA6LvmrAinzj0QuF8pEbpwfsAz6Kv3OkM) * ✅ [complex_layout_win_desktop__start_up](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/a811334185bc077a5cb69e46fc109ee3e679df6a924ee28d3c73f8b18717fa31/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR0gIiXFMnB_MSaqUxVyTpgpJqc37xSKqOzEsf2oD_oU-AhKPqrGQ-ZD7IY) * `flutter run` console output tests * ✅ [run_debug_test_windows](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/1b275a8b161c965c44c09565a5a9784e322cded973b52dc24645496f43aead5a/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR1IlBr0824cq9UKi46j_11eto6HTEQ9KVXF5Is1ZxcSIO7G6IlN-slsyI8) * ✅ [run_release_test_windows](https://ci.chromium.org/raw/build/logs.chromium.org/flutter/led/loicsharma_google.com/5b259bb5e2c07666fa12f053c3f5bd782bf074563a9afeeea231fa48bd33daa2/+/build.proto?server=chromium-swarm.appspot.com&fbclid=IwAR3DSHzCGL-KN26E-7hQL58qxV2p0Dtb9hE4AZ0HvEY4hp8mCMzX9jznsFQ) /cc @pbo-linaro Roll Flutter Engine from 7b989a28514e to acdb364a42d5 (2 revisions) (#135516) https://github.com/flutter/engine/compare/7b989a28514e...acdb364a42d5 2023-09-26 skia-flutter-autoroll@skia.org Roll Fuchsia Mac SDK from we5owZaebdO_3kyjz... to OMrTgAfDg9PKXTzq0... (flutter/engine#46294) 2023-09-26 skia-flutter-autoroll@skia.org Roll Skia from 8264a73430de to dd6a4e3655fc (2 revisions) (flutter/engine#46291) Also rolling transitive DEPS: fuchsia/sdk/core/mac-amd64 from we5owZaebdO_ to OMrTgAfDg9PK If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jacksongardner@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Switch flutter_tools to run frontend server from AOT snapshot (#135255) Co-authored-by: Christopher Fujino SelectionArea long press selection overlay behavior should match native (#133967) During a long press, on native iOS the context menu does not show until the long press has ended. The handles are shown immediately when the long press begins. This is true for static and editable text. For static text on Android, the context menu appears when the long press is initiated, but the handles do not appear until the long press has ended. For editable text on Android, the context menu does not appear until the long press ended, and the handles also do not appear until the end. For both platforms in editable/static contexts the context menu does not show while doing a long press drag. I think the behavior where the context menu is not shown until the long press ends makes the most sense even though Android varies in this depending on the context. The user is not able to react to the context menu until the long press has ended. Other details: On a windows touch screen device the context menu does not show up until the long press ends in editable/static text contexts. On a long press hold it selects the word on drag start as well as popping up the selection handles (static text). Allow multiple ParentDataWidgets to write to ParentData (#133581) Fixes https://github.com/flutter/flutter/issues/133089 This allows more than one ParentDataWidget to write to the ParentData of a child render object. Previously only one was allowed. There are some rules though: 1. Only one of a given type of `ParentDataWidget` can write to the `ParentData` of a given child. a. For example, 2 `Positioned` widgets wrapping a child of a `Stack` would not be allowed, as only one of type `Positioned` can contribute data. 2. The type of `ParentData` **must** be compatible with all of the `ParentDataWidget`s that want to contribute data. a. For example, `TwoDimensionalViewportParentData` mixes in the `KeepAliveParentDataMixin`. So the `ParentData` of a given child would be compatible with the `KeepAlive` `ParentDataWidget`, as well as another `ParentDataWidget` that writes `TwoDimensionalViewportParentData` (or a subclass of `TwoDimensionalViewportParentData` - This was the motivation for this change, where a `ParentDataWidget` is being used in `TableView` with the parent data type being a subclass of `TwoDimensionalViewportParentData`.) [flutter_tools] fix tests with no native assets running native asset build (#135474) Fixes https://github.com/flutter/flutter/issues/135461 [documentation] remove repeated "For example," in RenderSliverEdgeInsetsPadding documentation (#135297) There was a repeated "For example," in the documentation of `RenderSliverEdgeInsetsPadding`. This PR fix this. Revert "Switch flutter_tools to run frontend server from AOT snapshot" (#135537) Reverts flutter/flutter#135255 This broke Google Testing, and requires an internal patch before relanding. Roll Flutter Engine from acdb364a42d5 to 0a8ad236e4af (5 revisions) (#135527) https://github.com/flutter/engine/compare/acdb364a42d5...0a8ad236e4af 2023-09-26 1961493+harryterkelsen@users.noreply.github.com [canvaskit] Use DirectionalLight_Shadow flag for drawing shadows (flutter/engine#46292) 2023-09-26 30870216+gaaclarke@users.noreply.github.com [Impeller] fixes behavior for blurred rounded rect clear (flutter/engine#46167) 2023-09-26 skia-flutter-autoroll@skia.org Roll Skia from dd6a4e3655fc to bc4f22353590 (6 revisions) (flutter/engine#46299) 2023-09-26 30870216+gaaclarke@users.noreply.github.com Clean up the docstring for ColorFilter.matrix (flutter/engine#46298) 2023-09-26 49699333+dependabot[bot]@users.noreply.github.com Bump uuid from 4.0.0 to 4.1.0 in /lib/web_ui (flutter/engine#46293) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jacksongardner@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Roll Flutter Engine from 0a8ad236e4af to f70f65f7a622 (5 revisions) (#135549) https://github.com/flutter/engine/compare/0a8ad236e4af...f70f65f7a622 2023-09-27 skia-flutter-autoroll@skia.org Roll Skia from d1215b38667c to 76aecbaea259 (1 revision) (flutter/engine#46309) 2023-09-27 skia-flutter-autoroll@skia.org Roll Skia from bc4f22353590 to d1215b38667c (4 revisions) (flutter/engine#46306) 2023-09-26 skia-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from a56c8yPp4DDlj_Qbl... to Lg6FR6iDnZeV6y-E8... (flutter/engine#46302) 2023-09-26 ychris@google.com [ios] Fix app extension not able to find assets from unloaded bundle (flutter/engine#46283) 2023-09-26 leroux_bruno@yahoo.fr [Android] Fix enableSuggestions set to false not honored (flutter/engine#46037) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from a56c8yPp4DDl to Lg6FR6iDnZeV If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC jacksongardner@google.com,rmistry@google.com,zra@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md ✨ `flutter config --list` (#135401) Resolves #81831. The PR improves the `config` command in below ways: - Does not print the settings in usages or other options. - Adds the `--list` flag to print the full settings list. - Separates usages for settings and analytics. - Prints the restart tip when clearing features. Native assets support for Windows (#134203) Support for FFI calls with `@Native external` functions through Native assets on Windows. This enables bundling native code without any build-system boilerplate code. For more info see: * https://github.com/flutter/flutter/issues/129757 Mainly follows the design of https://github.com/flutter/flutter/pull/134031. Specifically for Windows in this PR is the logic for finding the compiler `cl.exe` and environment variables that contain the paths to the Windows headers `vcvars.bat` based on `vswhere.exe`. Marks Linux_pixel_7pro hello_world_impeller to be unflaky (#135564) The test has been passing for [50 consecutive runs](https://data.corp.google.com/sites/flutter_infra_metrics_datasite/flutter_check_test_flakiness_status_dashboard/?p=BUILDER_NAME:%22Linux_pixel_7pro%20hello_world_impeller%22). This test can be marked as unflaky. Roll Packages from 619af75f7966 to 21c2ebb39c07 (6 revisions) (#135602) https://github.com/flutter/packages/compare/619af75f7966...21c2ebb39c07 2023-09-26 43054281+camsim99@users.noreply.github.com [Android] Add new tasks for subset of tests to run API 33 (flutter/packages#4974) 2023-09-26 stuartmorgan@google.com [video_player] Update iOS prefixes (flutter/packages#4994) 2023-09-26 srawlins@google.com [go_router] Fix @tool directive with missing @end-tool (flutter/packages#4998) 2023-09-26 84124091+opxdelwin@users.noreply.github.com [GoRouter] option to override initial route set by platform (flutter/packages#4717) 2023-09-26 ditman@gmail.com [video_player] Ensures autoplay is false on the web. (flutter/packages#4961) 2023-09-26 34871572+gmackall@users.noreply.github.com [camera_android] Downgrade to AGP 7.3.0 to fix build_alll_packages test failures (flutter/packages#4997) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Config changes for linux coverage. (#135604) This build runs for over and hour and it does not need to run on presubmit or release candidate branches. Fix `SearchAnchor`'s search view isn't updated when the theme changes & widgets inside the search view do not inherit local themes (#132749) fixes [SearchAnchor (search view) UI glitch on platform brightness changes](https://github.com/flutter/flutter/issues/131835) fixes [Search view widgets cannot inherit local themes](https://github.com/flutter/flutter/issues/132741) - This fixes an issue where the `SearchAnchor`'s search view isn't updated when the platform brightness changes. - Fixes an issue where widgets inside the search view cannot use local themes `SearchAnchor` currently passed both global and local themes on the search view popup pushing and it uses anchor. button's context to look up the theme. ![search_view drawio (1)](https://github.com/flutter/flutter/assets/48603081/b5317fb1-ee73-461c-a119-f2a1e29f5909) As a result, when the platform changes and the search view is rebuilt, it cannot use the updated theme. https://github.com/flutter/flutter/assets/48603081/2f1ebe74-e7d5-4ef3-b97c-a741c3d68964 Similar to `PopupMenuButton`, the theme should be located in the search view so that when the platform brightness is updated and the search view is rebuilt it can use the updated theme. ![search_view drawio](https://github.com/flutter/flutter/assets/48603081/4e48c0cb-a558-4de6-9865-5f51981a343f) https://github.com/flutter/flutter/assets/48603081/d8d85982-c661-4cac-83e8-0488b1d93daf However, the search view's context cannot access local themes so I added support for `InheritedTheme`, which fixes the local. theme issue for both the search view and widgets inside the search view. ![Screenshot 2023-08-17 at 15 54 02](https://github.com/flutter/flutter/assets/48603081/dec18ba3-9f01-4706-987a-eb2fd4afb180) ![Screenshot 2023-08-17 at 15 55 15](https://github.com/flutter/flutter/assets/48603081/13f2797a-7f70-43b5-bc56-7971cf76a61d) made top level if checks gaurd clauses (#135070) This is a tiny tweak to replace some top level if clauses with guard clauses in `FutureBuilder`. I find the resultant code much more readable, but this is a matter of taste and I didn't see any info one way or another on it in the style guide so let me know if this is not to your all's preference. Support ensureVisible/showOnScreen/showInViewport for 2D Scrolling (#135182) fix last test get compiling fix implement features --- .../windows/flutter/CMakeLists.txt | 8 +- .../flutter/generated_plugin_registrant.cc | 14 + .../flutter/generated_plugin_registrant.h | 15 + .../windows/flutter/generated_plugins.cmake | 24 + .../flutter/generated_plugin_registrant.cc | 11 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 23 + packages/flutter_tools/lib/executable.dart | 2 + packages/flutter_tools/lib/src/artifacts.dart | 15 +- .../flutter_tools/lib/src/commands/build.dart | 29 +- .../lib/src/commands/build_preview.dart | 105 +++ packages/flutter_tools/lib/src/features.dart | 17 + .../lib/src/flutter_device_manager.dart | 9 + .../lib/src/flutter_features.dart | 3 + .../flutter_tools/lib/src/preview_device.dart | 103 ++- .../lib/src/windows/build_windows.dart | 7 +- .../hermetic/build_ios_test.dart | 735 ++++++++++-------- .../hermetic/build_ipa_test.dart | 413 ++++++---- .../hermetic/build_linux_test.dart | 162 ++-- .../hermetic/build_macos_test.dart | 92 ++- .../commands.shard/hermetic/build_test.dart | 50 +- .../hermetic/build_web_test.dart | 59 +- .../hermetic/build_windows_test.dart | 4 +- .../permeable/build_preview_test.dart | 53 ++ .../test/general.shard/analytics_test.dart | 21 +- .../general.shard/base/os_utils_test.dart | 4 +- .../general.shard/commands/build_test.dart | 14 +- .../general.shard/preview_device_test.dart | 104 ++- ...crub_generated_plugin_registrant_test.dart | 30 +- packages/flutter_tools/test/src/context.dart | 3 +- packages/flutter_tools/test/src/fakes.dart | 40 +- 31 files changed, 1528 insertions(+), 656 deletions(-) create mode 100644 dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc create mode 100644 dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h create mode 100644 dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake create mode 100644 examples/hello_world/linux/flutter/generated_plugin_registrant.cc create mode 100644 examples/hello_world/linux/flutter/generated_plugin_registrant.h create mode 100644 examples/hello_world/linux/flutter/generated_plugins.cmake create mode 100644 packages/flutter_tools/lib/src/commands/build_preview.dart create mode 100644 packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt b/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt index 903f4899d6fce..b2e4bd8d658b2 100644 --- a/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt +++ b/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt @@ -1,4 +1,3 @@ -# This file controls Flutter-level build steps. It should not be edited. cmake_minimum_required(VERSION 3.14) set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") @@ -10,11 +9,6 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -97,7 +91,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ + windows-x64 $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000000..4f7884874da74 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000000..dc139d85a9310 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000000000..88b22e5c775e5 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/examples/hello_world/linux/flutter/generated_plugin_registrant.cc b/examples/hello_world/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000000..e71a16d23d058 --- /dev/null +++ b/examples/hello_world/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/examples/hello_world/linux/flutter/generated_plugin_registrant.h b/examples/hello_world/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000000..e0f0a47bc08f3 --- /dev/null +++ b/examples/hello_world/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/examples/hello_world/linux/flutter/generated_plugins.cmake b/examples/hello_world/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000000000..2e1de87a7eb61 --- /dev/null +++ b/examples/hello_world/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 9bd3ea190d1f7..6831d6f8f8cf1 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -173,9 +173,11 @@ List generateCommands({ fileSystem: globals.fs, ), BuildCommand( + artifacts: globals.artifacts!, fileSystem: globals.fs, buildSystem: globals.buildSystem, osUtils: globals.os, + processUtils: globals.processUtils, verboseHelp: verboseHelp, androidSdk: globals.androidSdk, logger: globals.logger, diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 161e8b6ae7daa..fd23e85f94a60 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -69,6 +69,9 @@ enum Artifact { /// The location of file generators. flutterToolsFileGenerators, + + /// Pre-built desktop debug app. + flutterPreviewDevice, } /// A subset of [Artifact]s that are platform and build mode independent @@ -213,6 +216,8 @@ String? _artifactToFileName(Artifact artifact, Platform hostPlatform, [ BuildMod return 'const_finder.dart.snapshot'; case Artifact.flutterToolsFileGenerators: return ''; + case Artifact.flutterPreviewDevice: + return 'flutter_preview$exe'; } } @@ -573,6 +578,7 @@ class CachedArtifacts implements Artifacts { case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: return _getHostArtifactPath(artifact, platform, mode); } } @@ -612,6 +618,7 @@ class CachedArtifacts implements Artifacts { case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: return _getHostArtifactPath(artifact, platform, mode); } } @@ -663,6 +670,7 @@ class CachedArtifacts implements Artifacts { case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: return _getHostArtifactPath(artifact, platform, mode); } } @@ -745,6 +753,9 @@ class CachedArtifacts implements Artifacts { throw StateError('Artifact $artifact not available for platform $platform.'); case Artifact.flutterToolsFileGenerators: return _getFileGeneratorsPath(); + case Artifact.flutterPreviewDevice: + assert(platform == TargetPlatform.windows_x64); + return _cache.getArtifactDirectory('flutter_preview').childFile('flutter_preview.exe').path; } } @@ -1016,6 +1027,8 @@ class CachedLocalEngineArtifacts implements Artifacts { return _fileSystem.path.join(_getDartSdkPath(), 'bin', 'utils', artifactFileName); case Artifact.flutterToolsFileGenerators: return _getFileGeneratorsPath(); + case Artifact.flutterPreviewDevice: + throw UnimplementedError('TODO!'); // TODO } } @@ -1118,7 +1131,6 @@ class CachedLocalWebSdkArtifacts implements Artifacts { _platform = platform, _operatingSystemUtils = operatingSystemUtils; - final Artifacts _parent; final String _webSdkPath; final FileSystem _fileSystem; @@ -1169,6 +1181,7 @@ class CachedLocalWebSdkArtifacts implements Artifacts { case Artifact.fontSubset: case Artifact.constFinder: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: break; } } diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart index cad3d81453ebb..5bca720f71783 100644 --- a/packages/flutter_tools/lib/src/commands/build.dart +++ b/packages/flutter_tools/lib/src/commands/build.dart @@ -5,11 +5,14 @@ import 'package:meta/meta.dart'; import '../android/android_sdk.dart'; +import '../artifacts.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; import '../base/os.dart'; +import '../base/process.dart'; import '../build_info.dart'; import '../build_system/build_system.dart'; +import '../cache.dart'; import '../commands/build_linux.dart'; import '../commands/build_macos.dart'; import '../commands/build_windows.dart'; @@ -21,15 +24,18 @@ import 'build_bundle.dart'; import 'build_ios.dart'; import 'build_ios_framework.dart'; import 'build_macos_framework.dart'; +import 'build_preview.dart'; import 'build_web.dart'; class BuildCommand extends FlutterCommand { BuildCommand({ + required Artifacts artifacts, required FileSystem fileSystem, required BuildSystem buildSystem, required OperatingSystemUtils osUtils, required Logger logger, required AndroidSdk? androidSdk, + required ProcessUtils processUtils, bool verboseHelp = false, }){ _addSubcommand( @@ -67,6 +73,14 @@ class BuildCommand extends FlutterCommand { verboseHelp: verboseHelp )); _addSubcommand(BuildWindowsCommand(logger: logger, verboseHelp: verboseHelp)); + _addSubcommand(BuildPreviewCommand( + artifacts: artifacts, + flutterRoot: Cache.flutterRoot!, + fs: fileSystem, + logger: logger, + processUtils: processUtils, + verboseHelp: verboseHelp, + )); } void _addSubcommand(BuildSubCommand command) { @@ -90,14 +104,15 @@ class BuildCommand extends FlutterCommand { abstract class BuildSubCommand extends FlutterCommand { BuildSubCommand({ - required Logger logger, + required this.logger, required bool verboseHelp - }): _logger = logger { + }) { requiresPubspecYaml(); usesFatalWarningsOption(verboseHelp: verboseHelp); } - final Logger _logger; + @protected + final Logger logger; @override bool get reportNullSafety => true; @@ -111,15 +126,15 @@ abstract class BuildSubCommand extends FlutterCommand { @protected void displayNullSafetyMode(BuildInfo buildInfo) { if (buildInfo.nullSafetyMode != NullSafetyMode.sound) { - _logger.printStatus(''); - _logger.printStatus( + logger.printStatus(''); + logger.printStatus( 'Building without sound null safety ⚠️', emphasis: true, ); - _logger.printStatus( + logger.printStatus( 'Dart 3 will only support sound null safety, see https://dart.dev/null-safety', ); } - _logger.printStatus(''); + logger.printStatus(''); } } diff --git a/packages/flutter_tools/lib/src/commands/build_preview.dart b/packages/flutter_tools/lib/src/commands/build_preview.dart new file mode 100644 index 0000000000000..05a81da19cecf --- /dev/null +++ b/packages/flutter_tools/lib/src/commands/build_preview.dart @@ -0,0 +1,105 @@ +import 'package:file/file.dart'; + +import '../artifacts.dart'; +import '../base/common.dart'; +import '../base/io.dart'; +import '../base/process.dart'; +import '../build_info.dart'; +import '../cache.dart'; +import '../globals.dart' as globals; +import '../project.dart'; +import '../runner/flutter_command.dart' show FlutterCommandResult; +import '../windows/build_windows.dart'; +import 'build.dart'; + +class BuildPreviewCommand extends BuildSubCommand { + BuildPreviewCommand({ + required super.logger, + required bool verboseHelp, + required this.fs, + required this.flutterRoot, + required this.processUtils, + required this.artifacts, + }) : super(verboseHelp: verboseHelp) { + addCommonDesktopBuildOptions(verboseHelp: verboseHelp); + } + + @override + final String name = '_preview'; + + @override + final bool hidden = true; + + @override + Future> get requiredArtifacts async => { + DevelopmentArtifact.windows, + }; + + @override + final String description = 'Build Flutter preview (desktop) app.'; + + final FileSystem fs; + final String flutterRoot; + final ProcessUtils processUtils; + final Artifacts artifacts; + + static const BuildInfo buildInfo = BuildInfo( + BuildMode.debug, + null, // no flavor + // users may add icons later + treeShakeIcons: false, + ); + + @override + void requiresPubspecYaml() {} + + static const String appName = 'flutter_preview'; + + @override + Future runCommand() async { + final Directory targetDir = fs.systemTempDirectory.createTempSync('flutter-build-preview'); + final FlutterProject flutterProject = await _createProject(targetDir); + if (!globals.platform.isWindows) { + throwToolExit('"build _preview" is currently only supported on Windows hosts.'); + } + await buildWindows( + flutterProject.windows, + buildInfo, + ); + + final File previewDevice = targetDir + .childDirectory(getWindowsBuildDirectory(TargetPlatform.windows_x64)) + .childDirectory('runner') + .childDirectory('Debug') + .childFile('$appName.exe'); + if (!previewDevice.existsSync()) { + throw StateError('Preview device not found at ${previewDevice.absolute.path}'); + } + final String newPath = artifacts.getArtifactPath(Artifact.flutterPreviewDevice); + fs.file(newPath).parent.createSync(recursive: true); + previewDevice.copySync(newPath); + return FlutterCommandResult.success(); + } + + Future _createProject(Directory targetDir) async { + final List args = [ + fs.path.join(flutterRoot, 'bin', 'flutter.bat'), + 'create', + '--empty', + '--project-name', + 'flutter_preview', + targetDir.path, + ]; + final RunResult result = await processUtils.run( + args, + allowReentrantFlutter: true, + ); + if (result.exitCode != 0) { + final StringBuffer buffer = StringBuffer('${args.join(' ')} exited with code ${result.exitCode}'); + buffer.writeln('stdout:\n${result.stdout}\n'); + buffer.writeln('stderr:\n${result.stderr}'); + throw ProcessException(args.first, args.sublist(1), buffer.toString(), result.exitCode); + } + return FlutterProject.fromDirectory(targetDir); + } +} diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart index 284416992133b..ec3657ef6b880 100644 --- a/packages/flutter_tools/lib/src/features.dart +++ b/packages/flutter_tools/lib/src/features.dart @@ -53,6 +53,9 @@ abstract class FeatureFlags { /// Whether native assets compilation and bundling is enabled. bool get isNativeAssetsEnabled => false; + /// Whether native assets compilation and bundling is enabled. + bool get isPreviewDeviceEnabled => true; + /// Whether a particular feature is enabled for the current channel. /// /// Prefer using one of the specific getters above instead of this API. @@ -72,6 +75,7 @@ const List allFeatures = [ flutterWebWasm, cliAnimation, nativeAssets, + previewDevice, ]; /// All current Flutter feature flags that can be configured. @@ -172,6 +176,19 @@ const Feature nativeAssets = Feature( ), ); +/// Enable Flutter preview prebuilt device. +const Feature previewDevice = Feature( + name: 'Flutter preview prebuilt device', + configSetting: 'enable-flutter-preview', + environmentOverride: 'FLUTTER_PREVIEW_DEVICE', + master: FeatureChannelSetting( + available: true, + ), + beta: FeatureChannelSetting( + available: true, + ), +); + /// A [Feature] is a process for conditionally enabling tool features. /// /// All settings are optional, and if not provided will generally default to diff --git a/packages/flutter_tools/lib/src/flutter_device_manager.dart b/packages/flutter_tools/lib/src/flutter_device_manager.dart index dc98b4a7d0dcb..3b9558e53d0f5 100644 --- a/packages/flutter_tools/lib/src/flutter_device_manager.dart +++ b/packages/flutter_tools/lib/src/flutter_device_manager.dart @@ -27,6 +27,7 @@ import 'macos/macos_device.dart'; import 'macos/macos_ipad_device.dart'; import 'macos/macos_workflow.dart'; import 'macos/xcdevice.dart'; +import 'preview_device.dart'; import 'tester/flutter_tester.dart'; import 'version.dart'; import 'web/web_device.dart'; @@ -104,6 +105,14 @@ class FlutterDeviceManager extends DeviceManager { fileSystem: fileSystem, operatingSystemUtils: operatingSystemUtils, ), + PreviewDeviceDiscovery( + platform: platform, + artifacts: artifacts, + fileSystem: fileSystem, + logger: logger, + processManager: processManager, + featureFlags: featureFlags, + ), LinuxDevices( platform: platform, featureFlags: featureFlags, diff --git a/packages/flutter_tools/lib/src/flutter_features.dart b/packages/flutter_tools/lib/src/flutter_features.dart index 1418e90009631..ebb3403b154f5 100644 --- a/packages/flutter_tools/lib/src/flutter_features.dart +++ b/packages/flutter_tools/lib/src/flutter_features.dart @@ -58,6 +58,9 @@ class FlutterFeatureFlags implements FeatureFlags { @override bool get isNativeAssetsEnabled => isEnabled(nativeAssets); + @override + bool get isPreviewDeviceEnabled => isEnabled(previewDevice); + @override bool isEnabled(Feature feature) { final String currentChannel = _flutterVersion.channel; diff --git a/packages/flutter_tools/lib/src/preview_device.dart b/packages/flutter_tools/lib/src/preview_device.dart index aff36eebc30ae..a4fbd7104c93f 100644 --- a/packages/flutter_tools/lib/src/preview_device.dart +++ b/packages/flutter_tools/lib/src/preview_device.dart @@ -8,17 +8,18 @@ import 'package:meta/meta.dart'; import 'package:process/process.dart'; import 'application_package.dart'; +import 'artifacts.dart'; import 'base/file_system.dart'; import 'base/io.dart'; import 'base/logger.dart'; import 'base/platform.dart'; import 'build_info.dart'; import 'bundle_builder.dart'; -import 'cache.dart'; import 'desktop_device.dart'; import 'devfs.dart'; import 'device.dart'; import 'device_port_forwarder.dart'; +import 'features.dart'; import 'project.dart'; import 'protocol_discovery.dart'; @@ -28,6 +29,75 @@ BundleBuilder _defaultBundleBuilder() { return BundleBuilder(); } +class PreviewDeviceDiscovery extends DeviceDiscovery { + PreviewDeviceDiscovery({ + required Platform platform, + required Artifacts artifacts, + required FileSystem fileSystem, + required Logger logger, + required ProcessManager processManager, + required FeatureFlags featureFlags, + }) : _artifacts = artifacts, + _logger = logger, + _processManager = processManager, + _fileSystem = fileSystem, + _platform = platform, + _features = featureFlags; + + final Platform _platform; + final Artifacts _artifacts; + final Logger _logger; + final ProcessManager _processManager; + final FileSystem _fileSystem; + final FeatureFlags _features; + + @override + bool get canListAnything => _platform.isWindows; + + @override + Future> devices({ + Duration? timeout, + DeviceDiscoveryFilter? filter, + }) async { + final PreviewDevice device = PreviewDevice( + artifacts: _artifacts, + fileSystem: _fileSystem, + logger: _logger, + processManager: _processManager, + previewBinary: _fileSystem.file(_artifacts.getArtifactPath(Artifact.flutterPreviewDevice)), + ); + + final bool matchesRequirements; + if (!_platform.isWindows) { + matchesRequirements = false; + } else if (_features.isPreviewDeviceEnabled) { + matchesRequirements = false; + } else if (filter == null) { + matchesRequirements = true; + } else { + matchesRequirements = await filter.matchesRequirements(device); + } + return [ + if (matchesRequirements) + device, + ]; + } + + @override + Future> discoverDevices({ + Duration? timeout, + DeviceDiscoveryFilter? filter, + }) { + return devices(); + } + + @override + bool get supportsPlatform => true; + + @override + List get wellKnownIds => ['preview']; +} + /// A device type that runs a prebuilt desktop binary alongside a locally compiled kernel file. /// /// This could be used to support debug local development without plugins on machines that @@ -35,23 +105,26 @@ BundleBuilder _defaultBundleBuilder() { /// device is not currently discoverable. class PreviewDevice extends Device { PreviewDevice({ - required Platform platform, required ProcessManager processManager, required Logger logger, required FileSystem fileSystem, + required Artifacts artifacts, + required File previewBinary, @visibleForTesting BundleBuilderFactory builderFactory = _defaultBundleBuilder, - }) : _platform = platform, + }) : _previewBinary = previewBinary, _processManager = processManager, _logger = logger, _fileSystem = fileSystem, _bundleBuilderFactory = builderFactory, + _artifacts = artifacts, super('preview', ephemeral: false, category: Category.desktop, platformType: PlatformType.custom); - final Platform _platform; final ProcessManager _processManager; final Logger _logger; final FileSystem _fileSystem; final BundleBuilderFactory _bundleBuilderFactory; + final Artifacts _artifacts; + final File _previewBinary; @override void clearLogs() { } @@ -116,7 +189,7 @@ class PreviewDevice extends Device { await _bundleBuilderFactory().build( buildInfo: debuggingOptions.buildInfo, mainPath: mainPath, - platform: TargetPlatform.tester, + platform: TargetPlatform.windows_x64, assetDirPath: getAssetBuildDirectory(), ); copyDirectory(_fileSystem.directory( @@ -128,13 +201,18 @@ class PreviewDevice extends Device { } // Merge with precompiled executable. - final Directory precompiledDirectory = _fileSystem.directory(_fileSystem.path.join(Cache.flutterRoot!, 'artifacts_temp', 'Debug')); - copyDirectory(precompiledDirectory, assetDirectory); + final String copiedPreviewBinaryPath = assetDirectory.childFile(_previewBinary.basename).path; + _previewBinary.copySync(copiedPreviewBinaryPath); + + final String windowsPath = _artifacts + .getArtifactPath(Artifact.windowsDesktopPath, platform: TargetPlatform.windows_x64, mode: BuildMode.debug); + final File windowsDll = _fileSystem.file(_fileSystem.path.join(windowsPath, 'flutter_windows.dll')); + final File icu = _fileSystem.file(_fileSystem.path.join(windowsPath, 'icudtl.dat')); + windowsDll.copySync(assetDirectory.childFile('flutter_windows.dll').path); + icu.copySync(assetDirectory.childDirectory('data').childFile('icudtl.dat').path); final Process process = await _processManager.start( - [ - assetDirectory.childFile('splash').path, - ], + [copiedPreviewBinaryPath], ); _process = process; _logReader.initializeProcess(process); @@ -169,10 +247,7 @@ class PreviewDevice extends Device { @override Future get targetPlatform async { - if (_platform.isWindows) { - return TargetPlatform.windows_x64; - } - return TargetPlatform.tester; + return TargetPlatform.windows_x64; } @override diff --git a/packages/flutter_tools/lib/src/windows/build_windows.dart b/packages/flutter_tools/lib/src/windows/build_windows.dart index dddc0d424d2bf..2a4af0408a81e 100644 --- a/packages/flutter_tools/lib/src/windows/build_windows.dart +++ b/packages/flutter_tools/lib/src/windows/build_windows.dart @@ -56,9 +56,10 @@ Future buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, { // TODO(pbo-linaro): Add support for windows-arm64 platform, https://github.com/flutter/flutter/issues/129807 const TargetPlatform targetPlatform = TargetPlatform.windows_x64; - final Directory buildDirectory = globals.fs.directory( - getWindowsBuildDirectory(targetPlatform) - ); + final Directory buildDirectory = globals.fs.directory(globals.fs.path.join( + projectPath, + getWindowsBuildDirectory(targetPlatform), + )); final List migrators = [ CmakeCustomCommandMigration(windowsProject, globals.logger), diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart index 8f0ae0d5b3257..9cdbbdd3751ea 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart @@ -5,11 +5,13 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/android_sdk.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -30,7 +32,6 @@ import '../../src/test_build_system.dart'; import '../../src/test_flutter_command_runner.dart'; class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInterpreter { - FakeXcodeProjectInterpreterWithBuildSettings({this.productBundleIdentifier, this.developmentTeam = 'abc'}); @override @@ -69,6 +70,10 @@ final Platform notMacosPlatform = FakePlatform( void main() { late FileSystem fileSystem; late TestUsage usage; + late BufferLogger logger; + late FakeProcessManager processManager; + late ProcessUtils processUtils; + late Artifacts artifacts; setUpAll(() { Cache.disableLocking(); @@ -76,7 +81,14 @@ void main() { setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); usage = TestUsage(); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); // Sets up the minimal mock project files necessary to look like a Flutter project. @@ -192,10 +204,12 @@ void main() { testUsingContext('ios build fails when there is no ios project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -206,16 +220,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build fails in debug with code analysis', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -226,16 +242,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build fails on non-macOS platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -250,169 +268,175 @@ void main() { }, overrides: { Platform: () => notMacosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(onRun: () { + fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); + await createTestCommandRunner(command).run( const ['build', 'ios', '--no-pub'] ); expect(testLogger.statusText, contains('build/ios/iphoneos/Runner.app')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(onRun: () { - fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build with renamed xcodeproj and xcworkspace', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(customNaming: true, onRun: () { + fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); + fileSystem.directory(fileSystem.path.join('ios', 'RenamedProj.xcodeproj')).createSync(recursive: true); fileSystem.directory(fileSystem.path.join('ios', 'RenamedWorkspace.xcworkspace')).createSync(recursive: true); fileSystem.file(fileSystem.path.join('ios', 'RenamedProj.xcodeproj', 'project.pbxproj')).createSync(); createCoreMockProjectFiles(); await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub'] + const ['build', 'ios', '--no-pub'] ); expect(testLogger.statusText, contains('build/ios/iphoneos/Runner.app')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(customNaming: true, onRun: () { - fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build with device ID', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(deviceId: '1234', onRun: () { + fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub', '--device-id', '1234'] + const ['build', 'ios', '--no-pub', '--device-id', '1234'], ); expect(testLogger.statusText, contains('build/ios/iphoneos/Runner.app')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(deviceId: '1234', onRun: () { - fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios simulator build invokes xcode build', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(simulator: true, onRun: () { + fileSystem.directory('build/ios/Debug-iphonesimulator/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); await createTestCommandRunner(command).run( - const ['build', 'ios', '--simulator', '--no-pub'] + const ['build', 'ios', '--simulator', '--no-pub'], ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(simulator: true, onRun: () { - fileSystem.directory('build/ios/Debug-iphonesimulator/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build with verbosity', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); - - await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub', '-v'] - ); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler(verbose: true, onRun: () { fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); }), setUpRsyncCommand(), - ]), + ]); + + await createTestCommandRunner(command).run( + const ['build', 'ios', '--no-pub', '-v'], + ); + }, overrides: { + FileSystem: () => fileSystem, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - createMinimalMockProjectFiles(); - - await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub', '--analyze-size'] - ); - - expect(testLogger.statusText, contains('A summary of your iOS bundle analysis can be found at')); - expect(testLogger.statusText, contains('dart devtools --appSizeBase=')); - expect(usage.events, contains( - const TestUsageEvent('code-size-analysis', 'ios'), - )); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler(onRun: () { fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); @@ -434,7 +458,22 @@ void main() { setUpRsyncCommand(onRun: () => fileSystem.file('build/ios/iphoneos/Runner.app/Frameworks/App.framework/App') ..createSync(recursive: true) ..writeAsBytesSync(List.generate(10000, (int index) => 0))), - ]), + ]); + createMinimalMockProjectFiles(); + + await createTestCommandRunner(command).run( + const ['build', 'ios', '--no-pub', '--analyze-size'] + ); + + expect(logger.statusText, contains('A summary of your iOS bundle analysis can be found at')); + expect(logger.statusText, contains('dart devtools --appSizeBase=')); + expect(usage.events, contains( + const TestUsageEvent('code-size-analysis', 'ios'), + )); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, FileSystemUtils: () => FileSystemUtils(fileSystem: fileSystem, platform: macosPlatform), Usage: () => usage, @@ -461,11 +500,13 @@ void main() { testUsingContext('Sends an analytics event when Impeller is enabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, ); createMinimalMockProjectFiles(); @@ -504,11 +545,13 @@ void main() { testUsingContext('Sends an analytics event when Impeller is disabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, ); createMinimalMockProjectFiles(); @@ -570,12 +613,22 @@ void main() { group('xcresults device', () { testUsingContext('Trace error if xcresult is empty.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -584,29 +637,34 @@ void main() { throwsToolExit(), ); - expect(testLogger.traceText, contains('xcresult parser: Unrecognized top level json format.')); + expect(logger.traceText, contains('xcresult parser: Unrecognized top level json format.')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Display xcresult issues on console if parsed, suppress Xcode output', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }, stdout: 'Lots of spew from Xcode', + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -615,33 +673,36 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.statusText, isNot(contains("Xcode's output"))); - expect(testLogger.statusText, isNot(contains('Lots of spew from Xcode'))); + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.statusText, isNot(contains("Xcode's output"))); + expect(logger.statusText, isNot(contains('Lots of spew from Xcode'))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }, stdout: 'Lots of spew from Xcode', - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Do not display xcresult issues that needs to be discarded.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssuesToBeDiscarded), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -650,32 +711,34 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); - expect(testLogger.warningText, isNot(contains("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(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); + expect(logger.warningText, isNot(contains("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."))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssuesToBeDiscarded), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Trace if xcresult bundle does not exist.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -687,24 +750,29 @@ void main() { expect(testLogger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Extra error message for provision profile issue in xcresult bundle.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -713,33 +781,40 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains('Some Provisioning profile issue.')); - expect(testLogger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); - expect(testLogger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); - expect(testLogger.errorText, contains('open ios/Runner.xcworkspace')); - expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); + expect(logger.errorText, contains('Some Provisioning profile issue.')); + expect(logger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); + expect(logger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); + expect(logger.errorText, contains('open ios/Runner.xcworkspace')); + expect(logger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Display xcresult issues with no provisioning profile.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -748,33 +823,34 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains('Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor')); - expect(testLogger.errorText, contains(noProvisioningProfileInstruction)); + expect(logger.errorText, contains('Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor')); + expect(logger.errorText, contains(noProvisioningProfileInstruction)); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Extra error message for missing simulator platform in xcresult bundle.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(stdout: kSampleResultJsonWithActionIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -783,38 +859,26 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains(missingPlatformInstructions('iOS 17.0'))); + expect(logger.errorText, contains(missingPlatformInstructions('iOS 17.0'))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(stdout: kSampleResultJsonWithActionIssues), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Delete xcresult bundle before each xcodebuild command.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']); - - expect(testLogger.statusText, contains('Xcode build done.')); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, // Intentionally fail the first xcodebuild command with concurrent run failure message. setUpFakeXcodeBuildHandler( @@ -836,32 +900,32 @@ void main() { ), setUpXCResultCommand(stdout: kSampleResultJsonNoIssues), setUpRsyncCommand(), - ], - ), + ]); + + createMinimalMockProjectFiles(); + + await createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']); + + expect(logger.statusText, contains('Xcode build done.')); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Failed to parse xcresult but display missing provisioning profile issue from stdout.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.errorText, contains(noProvisioningProfileInstruction)); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( exitCode: 1, @@ -874,19 +938,45 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.errorText, contains(noProvisioningProfileInstruction)); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Failed to parse xcresult but detected no development team issue.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -895,30 +985,23 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.errorText, contains(noDevelopmentTeamInstruction)); + expect(logger.errorText, contains(noDevelopmentTeamInstruction)); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); testUsingContext('xcresult did not detect issue but detected by stdout.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); @@ -953,12 +1036,25 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig testUsingContext('xcresult did not detect issue, no development team is detected from build setting.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -970,29 +1066,32 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig expect(testLogger.errorText, contains(noDevelopmentTeamInstruction)); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); testUsingContext('No development team issue error message is not displayed if no provisioning profile issue is detected from xcresult first.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -1001,33 +1100,37 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.errorText, contains(noProvisioningProfileInstruction)); - expect(testLogger.errorText, isNot(contains(noDevelopmentTeamInstruction))); + expect(logger.errorText, contains(noProvisioningProfileInstruction)); + expect(logger.errorText, isNot(contains(noDevelopmentTeamInstruction))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); testUsingContext('General provisioning profile issue error message is not displayed if no development team issue is detected first.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -1036,21 +1139,12 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.errorText, contains(noDevelopmentTeamInstruction)); - expect(testLogger.errorText, isNot(contains('It appears that there was a problem signing your application prior to installation on the device.'))); + expect(logger.errorText, contains(noDevelopmentTeamInstruction)); + expect(logger.errorText, isNot(contains('It appears that there was a problem signing your application prior to installation on the device.'))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); @@ -1059,24 +1153,15 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig group('xcresults simulator', () { testUsingContext('Trace error if xcresult is empty.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.traceText, contains('xcresult parser: Unrecognized top level json format.')); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( simulator: true, @@ -1087,32 +1172,35 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.traceText, contains('xcresult parser: Unrecognized top level json format.')); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Display xcresult issues on console if parsed.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( simulator: true, @@ -1123,34 +1211,37 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Do not display xcresult issues that needs to be discarded.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); - expect(testLogger.warningText, isNot(contains("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."))); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( simulator: true, @@ -1161,19 +1252,46 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(stdout: kSampleResultJsonWithIssuesToBeDiscarded), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); + expect(logger.warningText, isNot(contains("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."))); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Trace if xcresult bundle does not exist.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + simulator: true, + exitCode: 1, + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -1182,18 +1300,11 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); + expect(logger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - simulator: true, - exitCode: 1, - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart index e925821917847..6e2c083e1a3ac 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart @@ -6,9 +6,11 @@ import 'dart:typed_data'; import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; @@ -33,10 +35,10 @@ class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInter @override Future> getBuildSettings( - String projectPath, { - XcodeProjectBuildContext? buildContext, - Duration timeout = const Duration(minutes: 1), - }) async { + String projectPath, { + XcodeProjectBuildContext? buildContext, + Duration timeout = const Duration(minutes: 1), + }) async { return { ...overrides, 'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject', @@ -72,7 +74,10 @@ void main() { late FileSystem fileSystem; late TestUsage usage; late FakeProcessManager fakeProcessManager; + late ProcessUtils processUtils; late FakePlistUtils plistUtils; + late BufferLogger logger; + late Artifacts artifacts; setUpAll(() { Cache.disableLocking(); @@ -80,8 +85,14 @@ void main() { setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); usage = TestUsage(); fakeProcessManager = FakeProcessManager.empty(); + logger = BufferLogger.test(); + processUtils = ProcessUtils( + logger: logger, + processManager: fakeProcessManager, + ); plistUtils = FakePlistUtils(); }); @@ -196,10 +207,12 @@ void main() { testUsingContext('ipa build fails when there is no ios project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -210,16 +223,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails in debug with code analysis', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -230,16 +245,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails on non-macOS platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -253,18 +270,21 @@ void main() { ), supported ? throwsToolExit() : throwsA(isA())); }, overrides: { Platform: () => notMacosPlatform, + Logger: () => logger, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails when export plist does not exist', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -281,7 +301,8 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + Logger: () => logger, + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -290,10 +311,12 @@ void main() { testUsingContext('ipa build fails when export plist is not a file', () async { final Directory bogus = fileSystem.directory('bogus')..createSync(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -310,17 +333,19 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails when --export-options-plist and --export-method are used together', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -339,17 +364,19 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build reports when IPA fails', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -379,13 +406,14 @@ void main() { const ['build', 'ipa', '--no-pub'] ); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building App Store IPA')); - expect(testLogger.errorText, contains('Encountered error while creating the IPA:')); - expect(testLogger.errorText, contains('error: exportArchive: "Runner.app" requires a provisioning profile.')); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building App Store IPA')); + expect(logger.errorText, contains('Encountered error while creating the IPA:')); + expect(logger.errorText, contains('error: exportArchive: "Runner.app" requires a provisioning profile.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -394,10 +422,12 @@ void main() { testUsingContext('ipa build invokes xcodebuild and archives for app store', () async { final File cachedExportOptionsPlist = fileSystem.file('/CachedExportOptions.plist'); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -427,14 +457,15 @@ void main() { final String actualIpaPlistContents = fileSystem.file(cachedExportOptionsPlist).readAsStringSync(); expect(actualIpaPlistContents, expectedIpaPlistContents); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building App Store IPA')); - expect(testLogger.statusText, contains('Built IPA to /build/ios/ipa')); - expect(testLogger.statusText, contains('To upload to the App Store')); - expect(testLogger.statusText, contains('Apple Transporter macOS app')); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building App Store IPA')); + expect(logger.statusText, contains('Built IPA to /build/ios/ipa')); + expect(logger.statusText, contains('To upload to the App Store')); + expect(logger.statusText, contains('Apple Transporter macOS app')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -443,10 +474,12 @@ void main() { testUsingContext('ipa build invokes xcodebuild and archives for ad-hoc distribution', () async { final File cachedExportOptionsPlist = fileSystem.file('/CachedExportOptions.plist'); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -476,14 +509,15 @@ void main() { final String actualIpaPlistContents = fileSystem.file(cachedExportOptionsPlist).readAsStringSync(); expect(actualIpaPlistContents, expectedIpaPlistContents); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building ad-hoc IPA')); - expect(testLogger.statusText, contains('Built IPA to /build/ios/ipa')); - // Don't instruct how to upload to the App Store. - expect(testLogger.statusText, isNot(contains('To upload'))); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building ad-hoc IPA')); + expect(logger.statusText, contains('Built IPA to /build/ios/ipa')); + // Don'ltruct how to upload to the App Store. + expect(logger.statusText, isNot(contains('To upload'))); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -492,10 +526,12 @@ void main() { testUsingContext('ipa build invokes xcodebuild and archives for enterprise distribution', () async { final File cachedExportOptionsPlist = fileSystem.file('/CachedExportOptions.plist'); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -525,14 +561,15 @@ void main() { final String actualIpaPlistContents = fileSystem.file(cachedExportOptionsPlist).readAsStringSync(); expect(actualIpaPlistContents, expectedIpaPlistContents); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building enterprise IPA')); - expect(testLogger.statusText, contains('Built IPA to /build/ios/ipa')); - // Don't instruct how to upload to the App Store. - expect(testLogger.statusText, isNot(contains('To upload'))); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building enterprise IPA')); + expect(logger.statusText, contains('Built IPA to /build/ios/ipa')); + // Don'ltruct how to upload to the App Store. + expect(logger.statusText, isNot(contains('To upload'))); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -540,10 +577,12 @@ void main() { testUsingContext('ipa build invokes xcode build with verbosity', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -559,6 +598,7 @@ void main() { expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -566,10 +606,12 @@ void main() { testUsingContext('ipa build --no-codesign skips codesigning and IPA creation', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -605,9 +647,10 @@ void main() { const ['build', 'ipa', '--no-pub', '--no-codesign'] ); expect(fakeProcessManager, hasNoRemainingExpectations); - expect(testLogger.statusText, contains('Codesigning disabled with --no-codesign, skipping IPA')); + expect(logger.statusText, contains('Codesigning disabled with --no-codesign, skipping IPA')); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -615,14 +658,17 @@ void main() { testUsingContext('code size analysis fails when app not found', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); + fakeProcessManager.addCommand(setUpFakeXcodeBuildHandler()); await expectToolExitLater( createTestCommandRunner(command).run( const ['build', 'ipa', '--no-pub', '--analyze-size'] @@ -631,17 +677,19 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -674,14 +722,15 @@ void main() { const ['build', 'ipa', '--no-pub', '--analyze-size'] ); - expect(testLogger.statusText, contains('A summary of your iOS bundle analysis can be found at')); - expect(testLogger.statusText, contains('dart devtools --appSizeBase=')); + expect(logger.statusText, contains('A summary of your iOS bundle analysis can be found at')); + expect(logger.statusText, contains('dart devtools --appSizeBase=')); expect(usage.events, contains( const TestUsageEvent('code-size-analysis', 'ios'), )); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, FileSystemUtils: () => FileSystemUtils(fileSystem: fileSystem, platform: macosPlatform), @@ -695,10 +744,12 @@ void main() { final File exportOptions = fileSystem.file('ExportOptions.plist') ..createSync(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -718,10 +769,11 @@ void main() { ], ); - expect(testLogger.statusText, contains('Built IPA to $outputPath.')); + expect(logger.statusText, contains('Built IPA to $outputPath.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -729,10 +781,12 @@ void main() { testUsingContext('Trace error if xcresult is empty.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -749,10 +803,11 @@ void main() { throwsToolExit(), ); - expect(testLogger.traceText, contains('xcresult parser: Unrecognized top level json format.')); + expect(logger.traceText, contains('xcresult parser: Unrecognized top level json format.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -760,10 +815,12 @@ void main() { testUsingContext('Display xcresult issues on console if parsed.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -780,11 +837,12 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -792,10 +850,12 @@ void main() { testUsingContext('Do not display xcresult issues that needs to be discarded.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -812,13 +872,14 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); - expect(testLogger.warningText, isNot(contains("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(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); + expect(logger.warningText, isNot(contains("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(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -826,10 +887,12 @@ void main() { testUsingContext('Trace if xcresult bundle does not exist.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -843,10 +906,11 @@ void main() { throwsToolExit(), ); - expect(testLogger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); + expect(logger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -855,10 +919,12 @@ void main() { testUsingContext('Extra error message for provision profile issue in xcresulb bundle.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -875,14 +941,15 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains('Some Provisioning profile issue.')); - expect(testLogger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); - expect(testLogger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); - expect(testLogger.errorText, contains('open ios/Runner.xcworkspace')); - expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); + expect(logger.errorText, contains('Some Provisioning profile issue.')); + expect(logger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); + expect(logger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); + expect(logger.errorText, contains('open ios/Runner.xcworkspace')); + expect(logger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -907,17 +974,19 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains( '[!] App Settings Validation\n' ' ! Version Number: Missing\n' @@ -928,11 +997,12 @@ void main() { ' ! You must set up the missing app settings.\n' )); expect( - testLogger.statusText, + logger.statusText, contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios') ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -963,17 +1033,19 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains( '[✓] App Settings Validation\n' ' • Version Number: 12.34.56\n' @@ -984,11 +1056,12 @@ void main() { ) ); expect( - testLogger.statusText, + logger.statusText, contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios') ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1018,32 +1091,35 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, - contains( - '[✓] App Settings Validation\n' - ' • Version Number: 12.34.56\n' - ' • Build Number: 666\n' - ' • Display Name: Awesome Gallery\n' - ' • Deployment Target: 11.0\n' - ' • Bundle Identifier: io.flutter.someProject\n' - ) + logger.statusText, + contains( + '[✓] App Settings Validation\n' + ' • Version Number: 12.34.56\n' + ' • Build Number: 666\n' + ' • Display Name: Awesome Gallery\n' + ' • Deployment Target: 11.0\n' + ' • Bundle Identifier: io.flutter.someProject\n' + ), ); expect( - testLogger.statusText, - contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios') + logger.statusText, + contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1069,21 +1145,25 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); expect( - testLogger.statusText, - contains(' ! Your application still contains the default "com.example" bundle identifier.') + logger.statusText, + contains(' ! Your application still contains the default "com.example" bundle identifier.'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1108,21 +1188,24 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, isNot(contains(' ! Your application still contains the default "com.example" bundle identifier.')) ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1189,21 +1272,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains(' ! App icon is set to the default placeholder icon. Replace with unique icons.'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1268,21 +1354,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, - isNot(contains(' ! App icon is set to the default placeholder icon. Replace with unique icons.')) + logger.statusText, + isNot(contains('! App icon is set to the default placeholder icon. Replace with unique icons.')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1327,21 +1416,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).') ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1386,21 +1478,25 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); expect( - testLogger.statusText, - contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).') + logger.statusText, + contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1445,21 +1541,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, - isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')) + logger.statusText, + isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1505,22 +1604,26 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); // The validation should be skipped, even when the icon size is incorrect. expect( - testLogger.statusText, + logger.statusText, isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1609,24 +1712,28 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); // The validation should be skipped, even when the image size is incorrect. for (final String imageFileName in imageFileNames) { expect( - testLogger.statusText, - isNot(contains(' ! App icon is using the incorrect size (e.g. $imageFileName).')) + logger.statusText, + isNot(contains(' ! App icon is using the incorrect size (e.g. $imageFileName).')), ); } }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1689,21 +1796,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains(' ! Launch image is set to the default placeholder icon. Replace with unique launch image.'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1767,21 +1877,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, isNot(contains(' ! Launch image is set to the default placeholder icon. Replace with unique launch image.')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart index d5f533465e6db..ec3bc880ddeb7 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart @@ -5,10 +5,12 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/utils.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -47,13 +49,23 @@ void main() { }); late FileSystem fileSystem; - late ProcessManager processManager; + late FakeProcessManager processManager; + late ProcessUtils processUtils; + late Logger logger; late TestUsage usage; + late Artifacts artifacts; setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); Cache.flutterRoot = _kTestFlutterRoot; usage = TestUsage(); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); // Creates the mock files necessary to look like a Flutter project. @@ -110,10 +122,12 @@ void main() { testUsingContext('Linux build fails when there is no linux project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockCoreProjectFiles(); @@ -126,16 +140,18 @@ void main() { }, overrides: { Platform: () => linuxPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), }); testUsingContext('Linux build fails on non-linux platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -146,16 +162,18 @@ void main() { }, overrides: { Platform: () => notLinuxPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), }); testUsingContext('Linux build fails when feature is disabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -166,19 +184,21 @@ void main() { }, overrides: { Platform: () => linuxPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(), }); testUsingContext('Linux build invokes CMake and ninja, and writes temporary files', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release'), ]); @@ -199,10 +219,12 @@ void main() { testUsingContext('Handles missing cmake', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -222,14 +244,16 @@ void main() { testUsingContext('Handles argument error from missing ninja', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release', onRun: () { throw ArgumentError(); @@ -249,14 +273,16 @@ void main() { testUsingContext('Linux build does not spew stdout to status logger', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug'), ninjaCommand('debug', stdout: 'STDOUT STUFF', @@ -280,10 +306,12 @@ void main() { testUsingContext('Linux build extracts errors from stdout', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -309,7 +337,7 @@ ninja: build stopped: subcommand failed. ERROR: No file or variants found for asset: images/a_dot_burr.jpeg '''; - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release', stdout: stdout, @@ -340,14 +368,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux verbose build sets VERBOSE_SCRIPT_LOGGING', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug'), ninjaCommand('debug', environment: const { @@ -366,6 +396,7 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg expect(testLogger.errorText, isNot(contains('STDOUT STUFF'))); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => processManager, Platform: () => linuxPlatform, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), @@ -374,14 +405,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on x64 build --debug passes debug mode to cmake and ninja', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug'), ninjaCommand('debug'), ]); @@ -391,6 +424,7 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => processManager, Platform: () => linuxPlatform, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), @@ -399,14 +433,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on ARM64 build --debug passes debug mode to cmake and ninja', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug', target: 'arm64'), ninjaCommand('debug', target: 'arm64'), ]); @@ -423,14 +459,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on x64 build --profile passes profile mode to make', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('profile'), ninjaCommand('profile'), ]); @@ -448,14 +486,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on ARM64 build --profile passes profile mode to make', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('profile', target: 'arm64'), ninjaCommand('profile', target: 'arm64'), ]); @@ -472,10 +512,12 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Not support Linux cross-build for x64 on arm64', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); @@ -489,14 +531,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux build configures CMake exports', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release'), ]); @@ -576,21 +620,25 @@ set(BINARY_NAME "fizz_bar") expect(getCmakeExecutableName(flutterProject.linux), 'fizz_bar'); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), }); testUsingContext('Refuses to build for Linux when feature is disabled', () { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); - expect(() => runner.run(['build', 'linux', '--no-pub']), - throwsToolExit()); + expect( + () => runner.run(['build', 'linux', '--no-pub']), + throwsToolExit(), + ); }, overrides: { FeatureFlags: () => TestFeatureFlags(), }); @@ -611,14 +659,16 @@ set(BINARY_NAME "fizz_bar") testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release', onRun: () { fileSystem.file('build/flutter_size_01/snapshot.linux-x64.json') @@ -662,14 +712,16 @@ set(BINARY_NAME "fizz_bar") testUsingContext('Linux on ARM64 build --release passes, and check if the LinuxBuildDirectory for arm64 can be referenced correctly by using analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release', target: 'arm64'), ninjaCommand('release', target: 'arm64', onRun: () { fileSystem.file('build/flutter_size_01/snapshot.linux-arm64.json') diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart index 014ae63b6e07a..1d643369053b3 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart @@ -10,6 +10,7 @@ import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -65,7 +66,10 @@ void main() { late FileSystem fileSystem; late TestUsage usage; late FakeProcessManager fakeProcessManager; + late ProcessUtils processUtils; + late BufferLogger logger; late XcodeProjectInterpreter xcodeProjectInterpreter; + late Artifacts artifacts; setUpAll(() { Cache.disableLocking(); @@ -73,8 +77,14 @@ void main() { setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); + logger = BufferLogger.test(); usage = TestUsage(); fakeProcessManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: fakeProcessManager, + ); xcodeProjectInterpreter = FakeXcodeProjectInterpreter(); }); @@ -139,10 +149,12 @@ STDERR STUFF testUsingContext('macOS build fails when there is no macos project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -161,10 +173,12 @@ STDERR STUFF testUsingContext('macOS build successfully with renamed .xcodeproj/.xcworkspace files', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); @@ -184,10 +198,12 @@ STDERR STUFF testUsingContext('macOS build fails on non-macOS platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -206,10 +222,12 @@ STDERR STUFF testUsingContext('macOS build fails when feature is disabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -228,10 +246,12 @@ STDERR STUFF testUsingContext('macOS build forwards error stdout to status logger error', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -258,10 +278,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (debug)', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -280,10 +302,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (debug) with verbosity', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -303,10 +327,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (profile)', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -326,10 +352,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (release)', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -348,10 +376,12 @@ STDERR STUFF testUsingContext('macOS build supports standard desktop build options', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -439,10 +469,12 @@ STDERR STUFF ]); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); @@ -461,10 +493,12 @@ STDERR STUFF testUsingContext('macOS build supports build-name and build-number', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -496,10 +530,12 @@ STDERR STUFF testUsingContext('Refuses to build for macOS when feature is disabled', () { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -526,10 +562,12 @@ STDERR STUFF testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart index 435c5d583400f..3422c2eb99b29 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart @@ -4,8 +4,10 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; @@ -28,23 +30,37 @@ void main() { ]), throwsToolExit(message: '"--${FlutterOptions.kDartObfuscationOption}" can only be used in ' 'combination with "--${FlutterOptions.kSplitDebugInfoOption}"')); }); + group('Fatal Logs', () { late FakeBuildCommand command; late MemoryFileSystem fs; + late BufferLogger logger; + late ProcessManager processManager; + late ProcessUtils processUtils; + late Artifacts artifacts; setUp(() { fs = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fs); fs.file('/package/pubspec.yaml').createSync(recursive: true); fs.currentDirectory = '/package'; Cache.disableLocking(); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); testUsingContext("doesn't fail if --fatal-warnings specified and no warnings occur", () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); try { @@ -58,15 +74,17 @@ void main() { } }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext("doesn't fail if --fatal-warnings not specified", () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); testLogger.printWarning('Warning: Mild annoyance Will Robinson!'); @@ -80,15 +98,17 @@ void main() { } }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('fails if --fatal-warnings specified and warnings emitted', () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); testLogger.printWarning('Warning: Mild annoyance Will Robinson!'); @@ -99,15 +119,17 @@ void main() { ]), throwsToolExit(message: 'Logger received warning output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.')); }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('fails if --fatal-warnings specified and errors emitted', () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); testLogger.printError('Error: Danger Will Robinson!'); @@ -118,7 +140,7 @@ void main() { ]), throwsToolExit(message: 'Logger received error output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.')); }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); }); } @@ -149,8 +171,10 @@ class FakeBuildCommand extends BuildCommand { required super.osUtils, required Logger logger, required super.androidSdk, + required super.processUtils, + required super.artifacts, bool verboseHelp = false, - }) : super(logger: logger, verboseHelp: verboseHelp,) { + }) : super(logger: logger) { addSubcommand(FakeBuildSubcommand(logger: logger, verboseHelp: verboseHelp)); } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart index c9a5547239e52..a9a1bc1839c7c 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart @@ -4,9 +4,11 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -28,6 +30,10 @@ void main() { 'FLUTTER_ROOT': '/', }, ); + late ProcessUtils processUtils; + late BufferLogger logger; + late ProcessManager processManager; + late Artifacts artifacts; setUpAll(() { Cache.flutterRoot = ''; @@ -42,15 +48,24 @@ void main() { fileSystem.file('.packages').createSync(); fileSystem.file(fileSystem.path.join('web', 'index.html')).createSync(recursive: true); fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true); + artifacts = Artifacts.test(fileSystem: fileSystem); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); testUsingContext('Refuses to build for web when missing index.html', () async { fileSystem.file(fileSystem.path.join('web', 'index.html')).deleteSync(); final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -62,15 +77,17 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Refuses to build a debug build for web', () async { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -79,15 +96,17 @@ void main() { }, overrides: { Platform: () => fakePlatform, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Refuses to build for web when feature is disabled', () async { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -99,15 +118,17 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Setup for a web build with default output directory', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); final CommandRunner runner = createTestCommandRunner(buildCommand); @@ -121,7 +142,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { expect(environment.defines, { 'TargetFile': 'lib/main.dart', @@ -144,11 +165,13 @@ void main() { testUsingContext('Does not allow -O0 optimization level', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, ); final CommandRunner runner = createTestCommandRunner(buildCommand); setupFileSystemForEndToEndTest(fileSystem); @@ -191,10 +214,12 @@ void main() { testUsingContext('Setup for a web build with a user specified output directory', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); final CommandRunner runner = createTestCommandRunner(buildCommand); @@ -219,7 +244,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { expect(environment.defines, { 'TargetFile': 'lib/main.dart', @@ -246,7 +271,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('not hidden if feature flag is enabled', () async { @@ -255,7 +280,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Defaults to web renderer auto mode when no option is specified', () async { @@ -270,7 +295,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); @@ -295,7 +320,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); @@ -311,7 +336,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); @@ -327,7 +352,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart index f77e830ebdb23..ec80512529886 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart @@ -82,7 +82,7 @@ void main() { '-S', fileSystem.path.absolute(fileSystem.path.dirname(buildFilePath)), '-B', - r'build\windows\x64', + r'C:\build\windows\x64', '-G', generator, '-A', @@ -103,7 +103,7 @@ void main() { command: [ _cmakePath, '--build', - r'build\windows\x64', + r'C:\build\windows\x64', '--config', buildMode, ...['--target', 'INSTALL'], diff --git a/packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart b/packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart new file mode 100644 index 0000000000000..e78d653416710 --- /dev/null +++ b/packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart @@ -0,0 +1,53 @@ +// 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:args/command_runner.dart'; +import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/cache.dart'; +import 'package:flutter_tools/src/commands/build_preview.dart'; +import 'package:flutter_tools/src/globals.dart' as globals; + +import '../../src/common.dart'; +import '../../src/context.dart'; +import '../../src/test_flutter_command_runner.dart'; + +void main() { + Cache.disableLocking(); + + late Directory tempDir; + late BufferLogger logger; + final FileSystem fs = LocalFileSystemBlockingSetCurrentDirectory(); + + setUp(() { + tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_packages_test.'); + logger = BufferLogger.test(); + }); + + tearDown(() { + tryToDelete(tempDir); + }); + + testUsingContext('foo bar', () async { + final String projectPath = await createProject( + tempDir, + arguments: ['--no-pub', '--template=app'], + ); + final BuildPreviewCommand command = BuildPreviewCommand( + logger: logger, + verboseHelp: true, + fs: fs, + processUtils: globals.processUtils, + flutterRoot: Cache.flutterRoot!, + artifacts: globals.artifacts!, + ); + final CommandRunner runner = createTestCommandRunner(command); + await runner.run([ + '_preview', + '--no-pub', + fs.path.join(projectPath, 'lib', 'main.dart'), + ]); + }, skip: !const LocalPlatform().isWindows); +} diff --git a/packages/flutter_tools/test/general.shard/analytics_test.dart b/packages/flutter_tools/test/general.shard/analytics_test.dart index c6cdf97745b98..a3d23bf6d4169 100644 --- a/packages/flutter_tools/test/general.shard/analytics_test.dart +++ b/packages/flutter_tools/test/general.shard/analytics_test.dart @@ -6,11 +6,13 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/android_studio.dart'; import 'package:flutter_tools/src/android/android_workflow.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/config.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/time.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -42,6 +44,7 @@ void main() { late Directory tempDir; late Config testConfig; late FileSystem fs; + const String flutterRoot = '/path/to/flutter'; setUp(() { @@ -161,6 +164,9 @@ void main() { late FakeClock fakeClock; late FakeDoctor doctor; late FakeAndroidStudio androidStudio; + late ProcessManager processManager; + late BufferLogger logger; + late ProcessUtils processUtils; setUp(() { memoryFileSystem = MemoryFileSystem.test(); @@ -169,6 +175,9 @@ void main() { fakeClock = FakeClock(); doctor = FakeDoctor(); androidStudio = FakeAndroidStudio(); + processManager = FakeProcessManager.empty(); + logger = BufferLogger.test(); + processUtils = ProcessUtils(logger: logger, processManager: processManager); }); testUsingContext('flutter commands send timing events', () async { @@ -220,17 +229,17 @@ void main() { testUsingContext('compound command usage path', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: Artifacts.test(fileSystem: memoryFileSystem), androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: memoryFileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); final FlutterCommand buildApkCommand = buildCommand.subcommands['apk']! as FlutterCommand; expect(await buildApkCommand.usagePath, 'build/apk'); - }, overrides: { - Usage: () => testUsage, }); testUsingContext('command sends localtime', () async { @@ -253,7 +262,7 @@ void main() { expect(log.contains(formatDateTime(dateTime)), isTrue); }, overrides: { FileSystem: () => memoryFileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, SystemClock: () => fakeClock, Platform: () => FakePlatform( environment: { @@ -283,7 +292,7 @@ void main() { expect(log.contains(formatDateTime(dateTime)), isTrue); }, overrides: { FileSystem: () => memoryFileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, SystemClock: () => fakeClock, Platform: () => FakePlatform( environment: { diff --git a/packages/flutter_tools/test/general.shard/base/os_utils_test.dart b/packages/flutter_tools/test/general.shard/base/os_utils_test.dart index 0ec8408a65872..6a8685df3c445 100644 --- a/packages/flutter_tools/test/general.shard/base/os_utils_test.dart +++ b/packages/flutter_tools/test/general.shard/base/os_utils_test.dart @@ -6,10 +6,10 @@ import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; -import 'package:flutter_tools/src/base/signals.dart'; import 'package:process/process.dart'; import '../../src/common.dart'; +import '../../src/context.dart'; void main() { group('OperatingSystemUtils', () { @@ -17,7 +17,7 @@ void main() { late FileSystem fileSystem; setUp(() { - fileSystem = LocalFileSystem.test(signals: Signals.test()); + fileSystem = LocalFileSystem.test(signals: FakeSignals()); tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_tools_os_utils_test.'); }); diff --git a/packages/flutter_tools/test/general.shard/commands/build_test.dart b/packages/flutter_tools/test/general.shard/commands/build_test.dart index 9663a387cb848..090924bed9335 100644 --- a/packages/flutter_tools/test/general.shard/commands/build_test.dart +++ b/packages/flutter_tools/test/general.shard/commands/build_test.dart @@ -5,10 +5,12 @@ import 'package:args/args.dart'; import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/signals.dart'; import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/build_info.dart'; @@ -111,11 +113,19 @@ void main() { }); testUsingContext('Include only supported sub commands', () { + final BufferLogger logger = BufferLogger.test(); + final ProcessUtils processUtils = ProcessUtils( + logger: logger, + processManager: FakeProcessManager.empty(), + ); + final MemoryFileSystem fs = MemoryFileSystem.test(); final BuildCommand command = BuildCommand( + artifacts: Artifacts.test(fileSystem: fs), androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); for (final Command x in command.subcommands.values) { diff --git a/packages/flutter_tools/test/general.shard/preview_device_test.dart b/packages/flutter_tools/test/general.shard/preview_device_test.dart index 876dbc64950ad..928631aa5c628 100644 --- a/packages/flutter_tools/test/general.shard/preview_device_test.dart +++ b/packages/flutter_tools/test/general.shard/preview_device_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/application_package.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; @@ -22,20 +23,38 @@ import 'package:test/fake.dart'; import '../src/common.dart'; import '../src/context.dart'; +import '../src/fakes.dart'; void main() { + String? flutterRootBackup; + late MemoryFileSystem fs; + late File previewBinary; + + setUp(() { + fs = MemoryFileSystem.test(style: FileSystemStyle.windows); + Cache.flutterRoot = r'C:\path\to\flutter'; + previewBinary = fs.file('${Cache.flutterRoot}\\bin\\cache\\artifacts\\flutter_preview\\flutter_preview.exe'); + previewBinary.createSync(recursive: true); + flutterRootBackup = Cache.flutterRoot; + }); + + tearDown(() { + Cache.flutterRoot = flutterRootBackup; + }); + testWithoutContext('PreviewDevice defaults', () async { final PreviewDevice device = PreviewDevice( - fileSystem: MemoryFileSystem.test(), + artifacts: Artifacts.test(), + fileSystem: fs, processManager: FakeProcessManager.any(), + previewBinary: previewBinary, logger: BufferLogger.test(), - platform: FakePlatform(), ); expect(await device.isLocalEmulator, false); expect(device.name, 'preview'); expect(await device.sdkNameAndVersion, 'preview'); - expect(await device.targetPlatform, TargetPlatform.tester); + expect(await device.targetPlatform, TargetPlatform.windows_x64); expect(device.category, Category.desktop); expect(device.ephemeral, false); expect(device.id, 'preview'); @@ -48,29 +67,33 @@ void main() { }); testUsingContext('Can build a simulator app', () async { - Cache.flutterRoot = ''; final Completer completer = Completer(); - final FileSystem fileSystem = MemoryFileSystem.test(); final BufferLogger logger = BufferLogger.test(); final PreviewDevice device = PreviewDevice( - fileSystem: fileSystem, + artifacts: Artifacts.test(), + fileSystem: fs, + previewBinary: previewBinary, processManager: FakeProcessManager.list([ FakeCommand( command: const [ - '/.tmp_rand0/flutter_preview.rand0/splash', + r'C:\.tmp_rand0\flutter_preview.rand0\flutter_preview.exe', ], stdout: 'The Dart VM service is listening on http://127.0.0.1:64494/fZ_B2N6JRwY=/\n', completer: completer, ), ]), logger: logger, - platform: FakePlatform(), - builderFactory: () => FakeBundleBuilder(fileSystem), + builderFactory: () => FakeBundleBuilder(fs), ); - fileSystem + fs .directory('artifacts_temp') .childDirectory('Debug') .createSync(recursive: true); + final Directory previewDeviceCacheDir = fs + .directory('Artifact.windowsDesktopPath.TargetPlatform.windows_x64.debug') + ..createSync(recursive: true); + previewDeviceCacheDir.childFile('flutter_windows.dll').writeAsStringSync('1010101'); + previewDeviceCacheDir.childFile('icudtl.dat').writeAsStringSync('1010101'); final LaunchResult result = await device.startApp( FakeApplicationPackage(), @@ -80,6 +103,67 @@ void main() { expect(result.started, true); expect(result.vmServiceUri, Uri.parse('http://127.0.0.1:64494/fZ_B2N6JRwY=/')); }); + + group('PreviewDeviceDiscovery', () { + late Artifacts artifacts; + late ProcessManager processManager; + final FakePlatform windowsPlatform = FakePlatform(operatingSystem: 'windows'); + final FakePlatform macPlatform = FakePlatform(operatingSystem: 'macos'); + final FakePlatform linuxPlatform = FakePlatform(); + final TestFeatureFlags featureFlags = TestFeatureFlags(isPreviewDeviceEnabled: true); + + setUp(() { + artifacts = Artifacts.test(fileSystem: fs); + processManager = FakeProcessManager.empty(); + }); + + testWithoutContext('PreviewDeviceDiscovery on linux', () async { + final PreviewDeviceDiscovery discovery = PreviewDeviceDiscovery( + artifacts: artifacts, + fileSystem: fs, + logger: BufferLogger.test(), + processManager: processManager, + platform: linuxPlatform, + featureFlags: featureFlags, + ); + + final List devices = await discovery.devices(); + + expect(devices, isEmpty); + }); + + testWithoutContext('PreviewDeviceDiscovery on macOS', () async { + final PreviewDeviceDiscovery discovery = PreviewDeviceDiscovery( + artifacts: artifacts, + fileSystem: fs, + logger: BufferLogger.test(), + processManager: processManager, + platform: macPlatform, + featureFlags: featureFlags, + ); + + final List devices = await discovery.devices(); + + expect(devices, isEmpty); + }); + + testWithoutContext('PreviewDeviceDiscovery on Windows', () async { + final PreviewDeviceDiscovery discovery = PreviewDeviceDiscovery( + artifacts: artifacts, + fileSystem: fs, + logger: BufferLogger.test(), + processManager: processManager, + platform: windowsPlatform, + featureFlags: featureFlags, + ); + + final List devices = await discovery.devices(); + + expect(devices, hasLength(1)); + final Device previewDevice = devices.first; + expect(previewDevice, isA()); + }); + }); } class FakeFlutterProject extends Fake implements FlutterProject { } diff --git a/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart b/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart index 4261dd88a7ffa..1b7ac91b06330 100644 --- a/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart +++ b/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart @@ -3,8 +3,10 @@ // found in the LICENSE file. import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; @@ -26,14 +28,24 @@ void main() { late File registrant; // Environment overrides + late Artifacts artifacts; late FileSystem fileSystem; late ProcessManager processManager; late BuildSystem buildSystem; + late ProcessUtils processUtils; + late BufferLogger logger; setUp(() { // Prepare environment overrides fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); processManager = FakeProcessManager.any(); + logger = BufferLogger.test(); + processUtils = ProcessUtils( + processManager: processManager, + logger: logger, + ); + buildSystem = TestBuildSystem.all(BuildResult(success: true)); // Write some initial state into our testing filesystem setupFileSystemForEndToEndTest(fileSystem); @@ -47,11 +59,13 @@ void main() { expect(registrant.existsSync(), isFalse); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, )) .run(['build', 'web', '--no-pub']); @@ -70,11 +84,13 @@ void main() { expect(contentsBeforeBuild, isNot(contains('lib/generated_plugin_registrant.dart'))); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, )) .run(['build', 'web', '--no-pub']); @@ -92,10 +108,12 @@ void main() { expect(gitignore.readAsStringSync(), contains('lib/generated_plugin_registrant.dart')); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )) .run(['build', 'web', '--no-pub']); @@ -113,10 +131,12 @@ void main() { expect(registrant.existsSync(), isTrue); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )) .run(['build', 'web', '--no-pub']); @@ -136,10 +156,12 @@ void main() { expect(gitignore.readAsStringSync(), contains('lib/generated_plugin_registrant.dart')); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )) .run(['build', 'web', '--no-pub']); diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart index 4fc36d2ce0831..5b0861ac4d49e 100644 --- a/packages/flutter_tools/test/src/context.dart +++ b/packages/flutter_tools/test/src/context.dart @@ -382,7 +382,8 @@ class NoopCrashReporter implements CrashReporter { } class LocalFileSystemBlockingSetCurrentDirectory extends LocalFileSystem { - // Use [FakeSignals] so developers running the test suite can kill the test runner. + // Use [FakeSignals] so developers running the test suite can kill the test + // runner. LocalFileSystemBlockingSetCurrentDirectory() : super.test(signals: FakeSignals()); @override diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index bca86131dc4e8..33dfdb554ab63 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -462,6 +462,7 @@ class TestFeatureFlags implements FeatureFlags { this.isFlutterWebWasmEnabled = false, this.isCliAnimationEnabled = true, this.isNativeAssetsEnabled = false, + this.isPreviewDeviceEnabled = false, }); @override @@ -497,31 +498,24 @@ class TestFeatureFlags implements FeatureFlags { @override final bool isNativeAssetsEnabled; + @override + final bool isPreviewDeviceEnabled; + @override bool isEnabled(Feature feature) { - switch (feature) { - case flutterWebFeature: - return isWebEnabled; - case flutterLinuxDesktopFeature: - return isLinuxEnabled; - case flutterMacOSDesktopFeature: - return isMacOSEnabled; - case flutterWindowsDesktopFeature: - return isWindowsEnabled; - case flutterAndroidFeature: - return isAndroidEnabled; - case flutterIOSFeature: - return isIOSEnabled; - case flutterFuchsiaFeature: - return isFuchsiaEnabled; - case flutterCustomDevicesFeature: - return areCustomDevicesEnabled; - case cliAnimation: - return isCliAnimationEnabled; - case nativeAssets: - return isNativeAssetsEnabled; - } - return false; + return switch (feature) { + flutterWebFeature => isWebEnabled, + flutterLinuxDesktopFeature => isLinuxEnabled, + flutterMacOSDesktopFeature => isMacOSEnabled, + flutterWindowsDesktopFeature => isWindowsEnabled, + flutterAndroidFeature => isAndroidEnabled, + flutterIOSFeature => isIOSEnabled, + flutterFuchsiaFeature => isFuchsiaEnabled, + flutterCustomDevicesFeature => areCustomDevicesEnabled, + cliAnimation => isCliAnimationEnabled, + nativeAssets => isNativeAssetsEnabled, + _ => false, + }; } }