Reland: [macos] add flavor options to tool commands (#119564)

* Reland: [macos] add flavor options to tool commands

Adds --flavor option to flutter run and flutter build. Running against
preexisting devicelab flavor tests for feature parity between macOS,
iOS, and Android.

This relands #118421 by alex-wallen which was reverted in #118858 due to
the following test failures:

The bail-out with "Host and target are the same. Nothing to install."
added in `packages/flutter_tools/lib/src/commands/install.dart`
triggered failures in the following tests, which unconditionally attempt
to install the built app, which is unsupported on desktop since the
host and target are the same:

* https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8791495589540422465/+/u/run_flutter_view_macos__start_up/test_stdout
* https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8791496218824259121/+/u/run_complex_layout_win_desktop__start_up/test_stdout
* https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8791496218165602641/+/u/run_flutter_gallery_win_desktop__start_up/test_stdout

Fixes #64088

* Partial revert: eliminate install check on desktop

The original flavour support patch included a check that triggered a
failure when flutter install is run on desktop OSes. This was
intentional, since the host and target devices are the same and
installation is unnecessary to launch the app on currently-supported
desktop OSes.

Note that Windows UWP apps *do* require installation to run, and we used
to have an install command for those apps, though UWP is no longer
supported.

Since that part of the change was orthogonal to flavour support itself,
I'm reverting that component of the change and we can deal with it
separately if so desired.
diff --git a/.ci.yaml b/.ci.yaml
index 30b76f4..4ba10f0 100644
--- a/.ci.yaml
+++ b/.ci.yaml
@@ -2637,6 +2637,20 @@
       - bin/**
       - .ci.yaml
 
+  - name: Mac flavors_test_macos
+    bringup: true
+    recipe: devicelab/devicelab_drone
+    timeout: 60
+    properties:
+      dependencies: >-
+        [
+          {"dependency": "xcode", "version": "14a5294e"},
+          {"dependency": "gems", "version": "v3.3.14"}
+        ]
+      tags: >
+        ["devicelab", "hostonly", "mac"]
+      task_name: flavors_test_macos
+
   - name: Mac flutter_gallery_macos__compile
     presubmit: false
     recipe: devicelab/devicelab_drone
diff --git a/TESTOWNERS b/TESTOWNERS
index 39c29b3..2736efe 100644
--- a/TESTOWNERS
+++ b/TESTOWNERS
@@ -218,6 +218,7 @@
 /dev/devicelab/bin/tasks/complex_layout_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
 /dev/devicelab/bin/tasks/dart_plugin_registry_test.dart @stuartmorgan @flutter/plugin
 /dev/devicelab/bin/tasks/entrypoint_dart_registrant.dart @aaclarke @flutter/plugin
+/dev/devicelab/bin/tasks/flavors_test_macos.dart @cbracken @flutter/desktop
 /dev/devicelab/bin/tasks/flutter_gallery_macos__compile.dart @a-wallen @flutter/desktop
 /dev/devicelab/bin/tasks/flutter_gallery_macos__start_up.dart @a-wallen @flutter/desktop
 /dev/devicelab/bin/tasks/flutter_gallery_win_desktop__compile.dart @yaakovschectman @flutter/desktop
diff --git a/dev/devicelab/bin/tasks/flavors_test_macos.dart b/dev/devicelab/bin/tasks/flavors_test_macos.dart
new file mode 100644
index 0000000..346bc31
--- /dev/null
+++ b/dev/devicelab/bin/tasks/flavors_test_macos.dart
@@ -0,0 +1,39 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_devicelab/framework/devices.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+import 'package:flutter_devicelab/framework/task_result.dart';
+import 'package:flutter_devicelab/framework/utils.dart';
+import 'package:flutter_devicelab/tasks/integration_tests.dart';
+
+Future<void> main() async {
+  deviceOperatingSystem = DeviceOperatingSystem.macos;
+  await task(() async {
+    await createFlavorsTest().call();
+    await createIntegrationTestFlavorsTest().call();
+
+    await inDirectory('${flutterDirectory.path}/dev/integration_tests/flavors', () async {
+      final StringBuffer stderr = StringBuffer();
+
+      await evalFlutter(
+        'install',
+        canFail: true,
+        stderr: stderr,
+        options: <String>[
+          '--d', 'macos',
+          '--flavor', 'free'
+        ],
+      );
+
+      final String stderrString = stderr.toString();
+      if (!stderrString.contains('Host and target are the same. Nothing to install.')) {
+        print(stderrString);
+        return TaskResult.failure('Installing a macOS app on macOS should no-op');
+      }
+    });
+
+    return TaskResult.success(null);
+  });
+}
diff --git a/dev/integration_tests/flavors/macos/Runner.xcodeproj/project.pbxproj b/dev/integration_tests/flavors/macos/Runner.xcodeproj/project.pbxproj
index af934cb..dff962e 100644
--- a/dev/integration_tests/flavors/macos/Runner.xcodeproj/project.pbxproj
+++ b/dev/integration_tests/flavors/macos/Runner.xcodeproj/project.pbxproj
@@ -651,6 +651,7 @@
 					"@executable_path/../Frameworks",
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
+				PRODUCT_FLAVOR = free;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -673,6 +674,7 @@
 					"@executable_path/../Frameworks",
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.flavors.free;
+				PRODUCT_FLAVOR = free;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_VERSION = 5.0;
diff --git a/packages/flutter_tools/bin/macos_assemble.sh b/packages/flutter_tools/bin/macos_assemble.sh
index 8c5934a..f4df20b 100755
--- a/packages/flutter_tools/bin/macos_assemble.sh
+++ b/packages/flutter_tools/bin/macos_assemble.sh
@@ -17,6 +17,32 @@
   echo "$@" 1>&2
 }
 
+ParseFlutterBuildMode() {
+  # Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
+  # This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
+  # they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
+  local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
+
+  case "$build_mode" in
+    *release*) build_mode="release";;
+    *profile*) build_mode="profile";;
+    *debug*) build_mode="debug";;
+    *)
+      EchoError "========================================================================"
+      EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${build_mode}."
+      EchoError "Valid values are 'Debug', 'Profile', or 'Release' (case insensitive)."
+      EchoError "This is controlled by the FLUTTER_BUILD_MODE environment variable."
+      EchoError "If that is not set, the CONFIGURATION environment variable is used."
+      EchoError ""
+      EchoError "You can fix this by either adding an appropriately named build"
+      EchoError "configuration, or adding an appropriate value for FLUTTER_BUILD_MODE to the"
+      EchoError ".xcconfig file for the current build configuration (${CONFIGURATION})."
+      EchoError "========================================================================"
+      exit -1;;
+  esac
+  echo "${build_mode}"
+}
+
 BuildApp() {
   # Set the working directory to the project root
   local project_path="${SOURCE_ROOT}/.."
@@ -28,8 +54,10 @@
       target_path="${FLUTTER_TARGET}"
   fi
 
-  # Set the build mode
-  local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
+  # Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
+  # This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
+  # they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
+  local build_mode="$(ParseFlutterBuildMode)"
 
   if [[ -n "$LOCAL_ENGINE" ]]; then
     if [[ $(echo "$LOCAL_ENGINE" | tr "[:upper:]" "[:lower:]") != *"$build_mode"* ]]; then
diff --git a/packages/flutter_tools/lib/src/desktop_device.dart b/packages/flutter_tools/lib/src/desktop_device.dart
index c60abbd..ae1df62 100644
--- a/packages/flutter_tools/lib/src/desktop_device.dart
+++ b/packages/flutter_tools/lib/src/desktop_device.dart
@@ -123,9 +123,9 @@
     }
 
     // Ensure that the executable is locatable.
-    final BuildMode buildMode = debuggingOptions.buildInfo.mode;
+    final BuildInfo buildInfo = debuggingOptions.buildInfo;
     final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
-    final String? executable = executablePathForDevice(package, buildMode);
+    final String? executable = executablePathForDevice(package, buildInfo);
     if (executable == null) {
       _logger.printError('Unable to find executable to run');
       return LaunchResult.failed();
@@ -161,7 +161,7 @@
     try {
       final Uri? observatoryUri = await observatoryDiscovery.uri;
       if (observatoryUri != null) {
-        onAttached(package, buildMode, process);
+        onAttached(package, buildInfo, process);
         return LaunchResult.succeeded(observatoryUri: observatoryUri);
       }
       _logger.printError(
@@ -203,11 +203,11 @@
 
   /// Returns the path to the executable to run for [package] on this device for
   /// the given [buildMode].
-  String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode);
+  String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo);
 
   /// Called after a process is attached, allowing any device-specific extra
   /// steps to be run.
-  void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
+  void onAttached(ApplicationPackage package, BuildInfo buildInfo, Process process) {}
 
   /// Computes a set of environment variables used to pass debugging information
   /// to the engine without interfering with application level command line
diff --git a/packages/flutter_tools/lib/src/linux/linux_device.dart b/packages/flutter_tools/lib/src/linux/linux_device.dart
index b017389..8e6b141 100644
--- a/packages/flutter_tools/lib/src/linux/linux_device.dart
+++ b/packages/flutter_tools/lib/src/linux/linux_device.dart
@@ -70,8 +70,8 @@
   }
 
   @override
-  String executablePathForDevice(covariant LinuxApp package, BuildMode buildMode) {
-    return package.executable(buildMode);
+  String executablePathForDevice(covariant LinuxApp package, BuildInfo buildInfo) {
+    return package.executable(buildInfo.mode);
   }
 }
 
diff --git a/packages/flutter_tools/lib/src/macos/application_package.dart b/packages/flutter_tools/lib/src/macos/application_package.dart
index 37fb60c..3debf60 100644
--- a/packages/flutter_tools/lib/src/macos/application_package.dart
+++ b/packages/flutter_tools/lib/src/macos/application_package.dart
@@ -106,9 +106,9 @@
   @override
   String get displayName => id;
 
-  String? applicationBundle(BuildMode buildMode);
+  String? applicationBundle(BuildInfo buildInfo);
 
-  String? executable(BuildMode buildMode);
+  String? executable(BuildInfo buildInfo);
 }
 
 class PrebuiltMacOSApp extends MacOSApp implements PrebuiltApplicationPackage {
@@ -135,10 +135,10 @@
   String get name => bundleName;
 
   @override
-  String? applicationBundle(BuildMode buildMode) => uncompressedBundle.path;
+  String? applicationBundle(BuildInfo buildInfo) => uncompressedBundle.path;
 
   @override
-  String? executable(BuildMode buildMode) => _executable;
+  String? executable(BuildInfo buildInfo) => _executable;
 
   /// A [File] or [Directory] pointing to the application bundle.
   ///
@@ -156,23 +156,30 @@
   String get name => 'macOS';
 
   @override
-  String? applicationBundle(BuildMode buildMode) {
+  String? applicationBundle(BuildInfo buildInfo) {
     final File appBundleNameFile = project.nameFile;
     if (!appBundleNameFile.existsSync()) {
       globals.printError('Unable to find app name. ${appBundleNameFile.path} does not exist');
       return null;
     }
+
     return globals.fs.path.join(
         getMacOSBuildDirectory(),
         'Build',
         'Products',
-        sentenceCase(getNameForBuildMode(buildMode)),
+        bundleDirectory(buildInfo),
         appBundleNameFile.readAsStringSync().trim());
   }
 
+  String bundleDirectory(BuildInfo buildInfo) {
+    return sentenceCase(buildInfo.mode.name) + (buildInfo.flavor != null
+      ? ' ${sentenceCase(buildInfo.flavor!)}'
+      : '');
+  }
+
   @override
-  String? executable(BuildMode buildMode) {
-    final String? directory = applicationBundle(buildMode);
+  String? executable(BuildInfo buildInfo) {
+    final String? directory = applicationBundle(buildInfo);
     if (directory == null) {
       return null;
     }
diff --git a/packages/flutter_tools/lib/src/macos/build_macos.dart b/packages/flutter_tools/lib/src/macos/build_macos.dart
index 57a7309..9a74f5e 100644
--- a/packages/flutter_tools/lib/src/macos/build_macos.dart
+++ b/packages/flutter_tools/lib/src/macos/build_macos.dart
@@ -114,7 +114,7 @@
       'xcodebuild',
       '-workspace', xcodeWorkspace.path,
       '-configuration', configuration,
-      '-scheme', 'Runner',
+      '-scheme', scheme,
       '-derivedDataPath', flutterBuildDir.absolute.path,
       '-destination', 'platform=macOS',
       'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
diff --git a/packages/flutter_tools/lib/src/macos/macos_device.dart b/packages/flutter_tools/lib/src/macos/macos_device.dart
index 8ed98fa..1de3ad9 100644
--- a/packages/flutter_tools/lib/src/macos/macos_device.dart
+++ b/packages/flutter_tools/lib/src/macos/macos_device.dart
@@ -78,17 +78,17 @@
   }
 
   @override
-  String? executablePathForDevice(covariant MacOSApp package, BuildMode buildMode) {
-    return package.executable(buildMode);
+  String? executablePathForDevice(covariant MacOSApp package, BuildInfo buildInfo) {
+    return package.executable(buildInfo);
   }
 
   @override
-  void onAttached(covariant MacOSApp package, BuildMode buildMode, Process process) {
+  void onAttached(covariant MacOSApp package, BuildInfo buildInfo, Process process) {
     // Bring app to foreground. Ideally this would be done post-launch rather
     // than post-attach, since this won't run for release builds, but there's
     // no general-purpose way of knowing when a process is far enough along in
     // the launch process for 'open' to foreground it.
-    final String? applicationBundle = package.applicationBundle(buildMode);
+    final String? applicationBundle = package.applicationBundle(buildInfo);
     if (applicationBundle == null) {
       _logger.printError('Failed to foreground app; application bundle not found');
       return;
diff --git a/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart b/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart
index 5358436..a8a61de 100644
--- a/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart
+++ b/packages/flutter_tools/lib/src/macos/macos_ipad_device.dart
@@ -54,7 +54,7 @@
   }
 
   @override
-  String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode) => null;
+  String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo) => null;
 
   @override
   Future<LaunchResult> startApp(
diff --git a/packages/flutter_tools/lib/src/windows/windows_device.dart b/packages/flutter_tools/lib/src/windows/windows_device.dart
index 8be3316..d94b8bb 100644
--- a/packages/flutter_tools/lib/src/windows/windows_device.dart
+++ b/packages/flutter_tools/lib/src/windows/windows_device.dart
@@ -61,8 +61,8 @@
   }
 
   @override
-  String executablePathForDevice(covariant WindowsApp package, BuildMode buildMode) {
-    return package.executable(buildMode);
+  String executablePathForDevice(covariant WindowsApp package, BuildInfo buildInfo) {
+    return package.executable(buildInfo.mode);
   }
 }
 
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/install_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/install_test.dart
index 0305c95..808cf3f 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/install_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/install_test.dart
@@ -157,6 +157,9 @@
     IOSApp app, {
     String? userIdentifier,
   }) async => true;
+
+  @override
+  String get name => 'iOS';
 }
 
 // Unfortunately Device, despite not being immutable, has an `operator ==`.
@@ -177,4 +180,7 @@
     AndroidApk app, {
     String? userIdentifier,
   }) async => true;
+
+  @override
+  String get name => 'Android';
 }
diff --git a/packages/flutter_tools/test/general.shard/desktop_device_test.dart b/packages/flutter_tools/test/general.shard/desktop_device_test.dart
index 4417bce..937f0c7 100644
--- a/packages/flutter_tools/test/general.shard/desktop_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/desktop_device_test.dart
@@ -86,7 +86,7 @@
         ),
       ]);
       final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager, fileSystem: fileSystem);
-      final String? executableName = device.executablePathForDevice(FakeApplicationPackage(), BuildMode.debug);
+      final String? executableName = device.executablePathForDevice(FakeApplicationPackage(), BuildInfo.debug);
       fileSystem.file(executableName).writeAsStringSync('\n');
       final FakeApplicationPackage package = FakeApplicationPackage();
       final LaunchResult result = await device.startApp(
@@ -367,11 +367,11 @@
 
   // Dummy implementation that just returns the build mode name.
   @override
-  String? executablePathForDevice(ApplicationPackage package, BuildMode buildMode) {
+  String? executablePathForDevice(ApplicationPackage package, BuildInfo buildInfo) {
     if (nullExecutablePathForDevice) {
       return null;
     }
-    return getNameForBuildMode(buildMode);
+    return getNameForBuildMode(buildInfo.mode);
   }
 }
 
diff --git a/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart b/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart
index 22cecda..79bf8d2 100644
--- a/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart
@@ -154,9 +154,9 @@
       operatingSystemUtils: FakeOperatingSystemUtils(),
     );
 
-    expect(device.executablePathForDevice(mockApp, BuildMode.debug), 'debug/executable');
-    expect(device.executablePathForDevice(mockApp, BuildMode.profile), 'profile/executable');
-    expect(device.executablePathForDevice(mockApp, BuildMode.release), 'release/executable');
+    expect(device.executablePathForDevice(mockApp, BuildInfo.debug), 'debug/executable');
+    expect(device.executablePathForDevice(mockApp, BuildInfo.profile), 'profile/executable');
+    expect(device.executablePathForDevice(mockApp, BuildInfo.release), 'release/executable');
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/macos/application_package_test.dart b/packages/flutter_tools/test/general.shard/macos/application_package_test.dart
index 57e11ff..40652af 100644
--- a/packages/flutter_tools/test/general.shard/macos/application_package_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/application_package_test.dart
@@ -10,6 +10,7 @@
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
 import 'package:flutter_tools/src/base/utils.dart';
+import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
 import 'package:flutter_tools/src/ios/plist_parser.dart';
 import 'package:flutter_tools/src/macos/application_package.dart';
@@ -155,6 +156,20 @@
       expect(macosApp.id, 'com.example.placeholder');
       expect(macosApp.name, 'macOS');
     }, overrides: overrides);
+
+    testUsingContext('Chooses the correct directory for application.', () {
+      final MacOSProject project = FlutterProject.fromDirectory(globals.fs.currentDirectory).macos;
+      final BuildableMacOSApp macosApp = MacOSApp.fromMacOSProject(project) as BuildableMacOSApp;
+
+      const BuildInfo vanillaApp = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
+      String? applicationBundle = macosApp.bundleDirectory(vanillaApp);
+      expect(applicationBundle, 'Debug');
+
+      const BuildInfo flavoredApp = BuildInfo(BuildMode.release, 'flavor', treeShakeIcons: false);
+      applicationBundle = macosApp.bundleDirectory(flavoredApp);
+      expect(applicationBundle, 'Release Flavor');
+
+    }, overrides: overrides);
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart
index 1900c26..6d20cc8 100644
--- a/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart
@@ -235,9 +235,9 @@
     const String profilePath = 'profile/executable';
     const String releasePath = 'release/executable';
 
-    expect(device.executablePathForDevice(package, BuildMode.debug), debugPath);
-    expect(device.executablePathForDevice(package, BuildMode.profile), profilePath);
-    expect(device.executablePathForDevice(package, BuildMode.release), releasePath);
+    expect(device.executablePathForDevice(package, BuildInfo.debug), debugPath);
+    expect(device.executablePathForDevice(package, BuildInfo.profile), profilePath);
+    expect(device.executablePathForDevice(package, BuildInfo.release), releasePath);
   });
 }
 
@@ -251,13 +251,13 @@
 
 class FakeMacOSApp extends Fake implements MacOSApp {
   @override
-  String executable(BuildMode buildMode) {
-    switch (buildMode) {
-      case BuildMode.debug:
+  String executable(BuildInfo buildInfo) {
+    switch (buildInfo) {
+      case BuildInfo.debug:
         return 'debug/executable';
-      case BuildMode.profile:
+      case BuildInfo.profile:
         return 'profile/executable';
-      case BuildMode.release:
+      case BuildInfo.release:
         return 'release/executable';
       default:
         throw StateError('');
diff --git a/packages/flutter_tools/test/general.shard/macos/macos_ipad_device_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_ipad_device_test.dart
index b5a9aaf..01493f5 100644
--- a/packages/flutter_tools/test/general.shard/macos/macos_ipad_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/macos_ipad_device_test.dart
@@ -142,7 +142,7 @@
       throwsA(isA<UnimplementedError>()),
     );
     await expectLater(() => device.buildForDevice(buildInfo: BuildInfo.debug), throwsA(isA<UnimplementedError>()));
-    expect(device.executablePathForDevice(FakeIOSApp(), BuildMode.debug), null);
+    expect(device.executablePathForDevice(FakeIOSApp(), BuildInfo.debug), null);
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart b/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart
index 5de2d54..99387e6 100644
--- a/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart
@@ -101,9 +101,9 @@
     final WindowsDevice windowsDevice = setUpWindowsDevice();
     final FakeWindowsApp fakeApp = FakeWindowsApp();
 
-    expect(windowsDevice.executablePathForDevice(fakeApp, BuildMode.debug), 'debug/executable');
-    expect(windowsDevice.executablePathForDevice(fakeApp, BuildMode.profile), 'profile/executable');
-    expect(windowsDevice.executablePathForDevice(fakeApp, BuildMode.release), 'release/executable');
+    expect(windowsDevice.executablePathForDevice(fakeApp, BuildInfo.debug), 'debug/executable');
+    expect(windowsDevice.executablePathForDevice(fakeApp, BuildInfo.profile), 'profile/executable');
+    expect(windowsDevice.executablePathForDevice(fakeApp, BuildInfo.release), 'release/executable');
   });
 }