Expose enable-experiment in Flutter drive (#66311)
diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart
index 8d3517b..2515f94 100644
--- a/packages/flutter_tools/lib/executable.dart
+++ b/packages/flutter_tools/lib/executable.dart
@@ -93,7 +93,7 @@
DevicesCommand(),
DoctorCommand(verbose: verbose),
DowngradeCommand(),
- DriveCommand(),
+ DriveCommand(verboseHelp: verboseHelp),
EmulatorsCommand(),
FormatCommand(),
GenerateCommand(),
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index b086b0e..6e2b638 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -50,9 +50,11 @@
/// successful the exit code will be `0`. Otherwise, you will see a non-zero
/// exit code.
class DriveCommand extends RunCommandBase {
- DriveCommand() {
+ DriveCommand({
+ bool verboseHelp = false,
+ }) {
requiresPubspecYaml();
-
+ addEnableExperimentation(hide: !verboseHelp);
argParser
..addFlag('keep-app-running',
defaultsTo: null,
@@ -322,7 +324,18 @@
}
try {
- await testRunner(<String>[testFile], environment);
+ await testRunner(
+ <String>[
+ if (buildInfo.dartExperiments.isNotEmpty)
+ '--enable-experiment=${buildInfo.dartExperiments.join(',')}',
+ if (buildInfo.nullSafetyMode == NullSafetyMode.sound)
+ '--sound-null-safety',
+ if (buildInfo.nullSafetyMode == NullSafetyMode.unsound)
+ '--no-sound-null-safety',
+ testFile,
+ ],
+ environment,
+ );
} on Exception catch (error, stackTrace) {
if (error is ToolExit) {
rethrow;
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
index e0242ad..d3689c0 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
@@ -205,7 +205,7 @@
return LaunchResult.succeeded();
});
testRunner = expectAsync2((List<String> testArgs, Map<String, String> environment) async {
- expect(testArgs, <String>[testFile]);
+ expect(testArgs, <String>['--no-sound-null-safety', testFile]);
// VM_SERVICE_URL is not set by drive command arguments
expect(environment, <String, String>{
'VM_SERVICE_URL': 'null',
@@ -273,6 +273,90 @@
ProcessManager: () => FakeProcessManager.any(),
});
+ testUsingContext('enable experiment', () async {
+ final MockAndroidDevice mockDevice = MockAndroidDevice();
+ applyDdsMocks(mockDevice);
+ testDeviceManager.addDevice(mockDevice);
+
+ final String testApp = globals.fs.path.join(tempDir.path, 'test', 'e2e.dart');
+ final String testFile = globals.fs.path.join(tempDir.path, 'test_driver', 'e2e_test.dart');
+
+ appStarter = expectAsync2((DriveCommand command, Uri webUri) async {
+ return LaunchResult.succeeded();
+ });
+ testRunner = expectAsync2((List<String> testArgs, Map<String, String> environment) async {
+ expect(
+ testArgs,
+ <String>[
+ '--enable-experiment=experiment1,experiment2',
+ '--no-sound-null-safety',
+ testFile,
+ ]
+ );
+ });
+ appStopper = expectAsync1((DriveCommand command) async {
+ return true;
+ });
+
+ final MemoryFileSystem memFs = fs;
+ await memFs.file(testApp).writeAsString('main() {}');
+ await memFs.file(testFile).writeAsString('main() {}');
+
+ final List<String> args = <String>[
+ 'drive',
+ '--target=$testApp',
+ '--no-pub',
+ '--enable-experiment=experiment1',
+ '--enable-experiment=experiment2',
+ ];
+ await createTestCommandRunner(command).run(args);
+ expect(testLogger.errorText, isEmpty);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => FakeProcessManager.any(),
+ });
+
+ testUsingContext('sound null safety', () async {
+ final MockAndroidDevice mockDevice = MockAndroidDevice();
+ applyDdsMocks(mockDevice);
+ testDeviceManager.addDevice(mockDevice);
+
+ final String testApp = globals.fs.path.join(tempDir.path, 'test', 'e2e.dart');
+ final String testFile = globals.fs.path.join(tempDir.path, 'test_driver', 'e2e_test.dart');
+
+ appStarter = expectAsync2((DriveCommand command, Uri webUri) async {
+ return LaunchResult.succeeded();
+ });
+ testRunner = expectAsync2((List<String> testArgs, Map<String, String> environment) async {
+ expect(
+ testArgs,
+ <String>[
+ '--sound-null-safety',
+ testFile,
+ ]
+ );
+ });
+ appStopper = expectAsync1((DriveCommand command) async {
+ return true;
+ });
+
+ final MemoryFileSystem memFs = fs;
+ await memFs.file(testApp).writeAsString('main() {}');
+ await memFs.file(testFile).writeAsString('main() {}');
+
+ final List<String> args = <String>[
+ 'drive',
+ '--target=$testApp',
+ '--no-pub',
+ '--sound-null-safety',
+ ];
+ await createTestCommandRunner(command).run(args);
+ expect(testLogger.errorText, isEmpty);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => FakeProcessManager.any(),
+ });
+
group('findTargetDevice', () {
testUsingContext('uses specified device', () async {
testDeviceManager.specifiedDeviceId = '123';