add an --enable-vmservice flag (#50663)
diff --git a/packages/flutter_tools/bin/fuchsia_tester.dart b/packages/flutter_tools/bin/fuchsia_tester.dart
index 0e60a96..0fc00e5 100644
--- a/packages/flutter_tools/bin/fuchsia_tester.dart
+++ b/packages/flutter_tools/bin/fuchsia_tester.dart
@@ -142,7 +142,8 @@
tests[source] = dill;
}
- exitCode = await runTests(
+ // TODO(dnfield): This should be injected.
+ exitCode = await const FlutterTestRunner().runTests(
const TestWrapper(),
tests.keys.toList(),
workDir: testDirectory,
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 101b142..a4a26f7 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -27,6 +27,7 @@
TestCommand({
bool verboseHelp = false,
this.testWrapper = const TestWrapper(),
+ this.testRunner = const FlutterTestRunner(),
}) : assert(testWrapper != null) {
requiresPubspecYaml();
usesPubOption();
@@ -110,6 +111,15 @@
'test cases (must be a 32bit unsigned integer).\n'
'If "random", pick a random seed to use.\n'
'If 0 or not set, do not randomize test case execution order.',
+ )
+ ..addFlag('enable-vmservice',
+ defaultsTo: false,
+ hide: !verboseHelp,
+ help: 'Enables the vmservice without --start-paused. This flag is '
+ 'intended for use with tests that will use dart:developer to '
+ 'interact with the vmservice at runtime.\n'
+ 'This flag is ignored if --start-paused or coverage are requested. '
+ 'The vmservice will be enabled no matter what in those cases.'
);
usesTrackWidgetCreation(verboseHelp: verboseHelp);
}
@@ -117,6 +127,9 @@
/// The interface for starting and configuring the tester.
final TestWrapper testWrapper;
+ /// Interface for running the tester process.
+ final FlutterTestRunner testRunner;
+
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{};
@@ -235,14 +248,14 @@
final bool disableServiceAuthCodes =
boolArg('disable-service-auth-codes');
- final int result = await runTests(
+ final int result = await testRunner.runTests(
testWrapper,
files,
workDir: workDir,
names: names,
plainNames: plainNames,
watcher: watcher,
- enableObservatory: collector != null || startPaused,
+ enableObservatory: collector != null || startPaused || boolArg('enable-vmservice'),
startPaused: startPaused,
disableServiceAuthCodes: disableServiceAuthCodes,
ipv6: boolArg('ipv6'),
diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart
index 1577d1c..6f1b095 100644
--- a/packages/flutter_tools/lib/src/test/runner.dart
+++ b/packages/flutter_tools/lib/src/test/runner.dart
@@ -20,141 +20,177 @@
import 'test_wrapper.dart';
import 'watcher.dart';
-/// Runs tests using package:test and the Flutter engine.
-Future<int> runTests(
- TestWrapper testWrapper,
- List<String> testFiles, {
- Directory workDir,
- List<String> names = const <String>[],
- List<String> plainNames = const <String>[],
- bool enableObservatory = false,
- bool startPaused = false,
- bool disableServiceAuthCodes = false,
- bool ipv6 = false,
- bool machine = false,
- String precompiledDillPath,
- Map<String, String> precompiledDillFiles,
- @required BuildMode buildMode,
- bool trackWidgetCreation = false,
- bool updateGoldens = false,
- TestWatcher watcher,
- @required int concurrency,
- bool buildTestAssets = false,
- FlutterProject flutterProject,
- String icudtlPath,
- Directory coverageDirectory,
- bool web = false,
- String randomSeed = '0',
-}) async {
- // Configure package:test to use the Flutter engine for child processes.
- final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester);
- if (!globals.processManager.canRun(shellPath)) {
- throwToolExit('Cannot execute Flutter tester at $shellPath');
- }
+/// A class that abstracts launching the test process from the test runner.
+abstract class FlutterTestRunner {
+ const factory FlutterTestRunner() = _FlutterTestRunnerImpl;
- // Compute the command-line arguments for package:test.
- final List<String> testArgs = <String>[
- if (!globals.terminal.supportsColor)
- '--no-color',
- if (startPaused)
- '--pause-after-load',
- if (machine)
- ...<String>['-r', 'json']
- else
- ...<String>['-r', 'compact'],
- '--concurrency=$concurrency',
- for (final String name in names)
- ...<String>['--name', name],
- for (final String plainName in plainNames)
- ...<String>['--plain-name', plainName],
- '--test-randomize-ordering-seed=$randomSeed',
- ];
- if (web) {
- final String tempBuildDir = globals.fs.systemTempDirectory
- .createTempSync('flutter_test.')
- .absolute
- .uri
- .toFilePath();
- final bool result = await webCompilationProxy.initialize(
- projectDirectory: flutterProject.directory,
- testOutputDir: tempBuildDir,
- testFiles: testFiles,
- projectName: flutterProject.manifest.appName,
- initializePlatform: true,
- );
- if (!result) {
- throwToolExit('Failed to compile tests');
+ /// Runs tests using package:test and the Flutter engine.
+ Future<int> runTests(
+ TestWrapper testWrapper,
+ List<String> testFiles, {
+ Directory workDir,
+ List<String> names = const <String>[],
+ List<String> plainNames = const <String>[],
+ bool enableObservatory = false,
+ bool startPaused = false,
+ bool disableServiceAuthCodes = false,
+ bool ipv6 = false,
+ bool machine = false,
+ String precompiledDillPath,
+ Map<String, String> precompiledDillFiles,
+ @required BuildMode buildMode,
+ bool trackWidgetCreation = false,
+ bool updateGoldens = false,
+ TestWatcher watcher,
+ @required int concurrency,
+ bool buildTestAssets = false,
+ FlutterProject flutterProject,
+ String icudtlPath,
+ Directory coverageDirectory,
+ bool web = false,
+ String randomSeed = '0',
+ });
+}
+
+class _FlutterTestRunnerImpl implements FlutterTestRunner {
+ const _FlutterTestRunnerImpl();
+
+ @override
+ Future<int> runTests(
+ TestWrapper testWrapper,
+ List<String> testFiles, {
+ Directory workDir,
+ List<String> names = const <String>[],
+ List<String> plainNames = const <String>[],
+ bool enableObservatory = false,
+ bool startPaused = false,
+ bool disableServiceAuthCodes = false,
+ bool ipv6 = false,
+ bool machine = false,
+ String precompiledDillPath,
+ Map<String, String> precompiledDillFiles,
+ @required BuildMode buildMode,
+ bool trackWidgetCreation = false,
+ bool updateGoldens = false,
+ TestWatcher watcher,
+ @required int concurrency,
+ bool buildTestAssets = false,
+ FlutterProject flutterProject,
+ String icudtlPath,
+ Directory coverageDirectory,
+ bool web = false,
+ String randomSeed = '0',
+ }) async {
+ // Configure package:test to use the Flutter engine for child processes.
+ final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester);
+ if (!globals.processManager.canRun(shellPath)) {
+ throwToolExit('Cannot execute Flutter tester at $shellPath');
}
+
+ // Compute the command-line arguments for package:test.
+ final List<String> testArgs = <String>[
+ if (!globals.terminal.supportsColor)
+ '--no-color',
+ if (startPaused)
+ '--pause-after-load',
+ if (machine)
+ ...<String>['-r', 'json']
+ else
+ ...<String>['-r', 'compact'],
+ '--concurrency=$concurrency',
+ for (final String name in names)
+ ...<String>['--name', name],
+ for (final String plainName in plainNames)
+ ...<String>['--plain-name', plainName],
+ '--test-randomize-ordering-seed=$randomSeed',
+ ];
+ if (web) {
+ final String tempBuildDir = globals.fs.systemTempDirectory
+ .createTempSync('flutter_test.')
+ .absolute
+ .uri
+ .toFilePath();
+ final bool result = await webCompilationProxy.initialize(
+ projectDirectory: flutterProject.directory,
+ testOutputDir: tempBuildDir,
+ testFiles: testFiles,
+ projectName: flutterProject.manifest.appName,
+ initializePlatform: true,
+ );
+ if (!result) {
+ throwToolExit('Failed to compile tests');
+ }
+ testArgs
+ ..add('--platform=chrome')
+ ..add('--precompiled=$tempBuildDir')
+ ..add('--')
+ ..addAll(testFiles);
+ testWrapper.registerPlatformPlugin(
+ <Runtime>[Runtime.chrome],
+ () {
+ return FlutterWebPlatform.start(
+ flutterProject.directory.path,
+ updateGoldens: updateGoldens,
+ shellPath: shellPath,
+ flutterProject: flutterProject,
+ pauseAfterLoad: startPaused,
+ );
+ },
+ );
+ await testWrapper.main(testArgs);
+ return exitCode;
+ }
+
testArgs
- ..add('--platform=chrome')
- ..add('--precompiled=$tempBuildDir')
..add('--')
..addAll(testFiles);
- testWrapper.registerPlatformPlugin(
- <Runtime>[Runtime.chrome],
- () {
- return FlutterWebPlatform.start(
- flutterProject.directory.path,
- updateGoldens: updateGoldens,
- shellPath: shellPath,
- flutterProject: flutterProject,
- pauseAfterLoad: startPaused,
- );
- },
+
+ final InternetAddressType serverType =
+ ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4;
+
+ final loader.FlutterPlatform platform = loader.installHook(
+ testWrapper: testWrapper,
+ shellPath: shellPath,
+ watcher: watcher,
+ enableObservatory: enableObservatory,
+ machine: machine,
+ startPaused: startPaused,
+ disableServiceAuthCodes: disableServiceAuthCodes,
+ serverType: serverType,
+ precompiledDillPath: precompiledDillPath,
+ precompiledDillFiles: precompiledDillFiles,
+ buildMode: buildMode,
+ trackWidgetCreation: trackWidgetCreation,
+ updateGoldens: updateGoldens,
+ buildTestAssets: buildTestAssets,
+ projectRootDirectory: globals.fs.currentDirectory.uri,
+ flutterProject: flutterProject,
+ icudtlPath: icudtlPath,
);
- await testWrapper.main(testArgs);
- return exitCode;
- }
- testArgs
- ..add('--')
- ..addAll(testFiles);
+ // Make the global packages path absolute.
+ // (Makes sure it still works after we change the current directory.)
+ PackageMap.globalPackagesPath =
+ globals.fs.path.normalize(globals.fs.path.absolute(PackageMap.globalPackagesPath));
- final InternetAddressType serverType =
- ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4;
+ // Call package:test's main method in the appropriate directory.
+ final Directory saved = globals.fs.currentDirectory;
+ try {
+ if (workDir != null) {
+ globals.printTrace('switching to directory $workDir to run tests');
+ globals.fs.currentDirectory = workDir;
+ }
- final loader.FlutterPlatform platform = loader.installHook(
- testWrapper: testWrapper,
- shellPath: shellPath,
- watcher: watcher,
- enableObservatory: enableObservatory,
- machine: machine,
- startPaused: startPaused,
- disableServiceAuthCodes: disableServiceAuthCodes,
- serverType: serverType,
- precompiledDillPath: precompiledDillPath,
- precompiledDillFiles: precompiledDillFiles,
- buildMode: buildMode,
- trackWidgetCreation: trackWidgetCreation,
- updateGoldens: updateGoldens,
- buildTestAssets: buildTestAssets,
- projectRootDirectory: globals.fs.currentDirectory.uri,
- flutterProject: flutterProject,
- icudtlPath: icudtlPath,
- );
+ globals.printTrace('running test package with arguments: $testArgs');
+ await testWrapper.main(testArgs);
- // Make the global packages path absolute.
- // (Makes sure it still works after we change the current directory.)
- PackageMap.globalPackagesPath =
- globals.fs.path.normalize(globals.fs.path.absolute(PackageMap.globalPackagesPath));
+ // test.main() sets dart:io's exitCode global.
+ globals.printTrace('test package returned with exit code $exitCode');
- // Call package:test's main method in the appropriate directory.
- final Directory saved = globals.fs.currentDirectory;
- try {
- if (workDir != null) {
- globals.printTrace('switching to directory $workDir to run tests');
- globals.fs.currentDirectory = workDir;
+ return exitCode;
+ } finally {
+ globals.fs.currentDirectory = saved;
+ await platform.close();
}
-
- globals.printTrace('running test package with arguments: $testArgs');
- await testWrapper.main(testArgs);
-
- // test.main() sets dart:io's exitCode global.
- globals.printTrace('test package returned with exit code $exitCode');
-
- return exitCode;
- } finally {
- globals.fs.currentDirectory = saved;
- await platform.close();
}
}
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
index b8145cf..792a0c8 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
@@ -7,9 +7,13 @@
import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/test.dart';
+import 'package:flutter_tools/src/project.dart';
+import 'package:flutter_tools/src/test/runner.dart';
import 'package:flutter_tools/src/test/test_wrapper.dart';
+import 'package:flutter_tools/src/test/watcher.dart';
import 'package:process/process.dart';
import '../../src/common.dart';
@@ -73,6 +77,92 @@
ProcessManager: () => FakeProcessManager.any(),
Cache: () => FakeCache(),
});
+
+ testUsingContext('Pipes enable-observatory', () async {
+ final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
+
+ final TestCommand testCommand = TestCommand(testRunner: testRunner);
+ final CommandRunner<void> commandRunner =
+ createTestCommandRunner(testCommand);
+
+ await commandRunner.run(const <String>[
+ 'test',
+ '--no-pub',
+ '--enable-vmservice',
+ '--',
+ 'test/fake_test.dart',
+ ]);
+ expect(
+ testRunner.lastEnableObservatoryValue,
+ true,
+ );
+
+ await commandRunner.run(const <String>[
+ 'test',
+ '--no-pub',
+ '--start-paused',
+ '--no-enable-vmservice',
+ '--',
+ 'test/fake_test.dart',
+ ]);
+ expect(
+ testRunner.lastEnableObservatoryValue,
+ true,
+ );
+
+ await commandRunner.run(const <String>[
+ 'test',
+ '--no-pub',
+ '--',
+ 'test/fake_test.dart',
+ ]);
+ expect(
+ testRunner.lastEnableObservatoryValue,
+ false,
+ );
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => FakeProcessManager.any(),
+ Cache: () => FakeCache(),
+ });
+}
+
+class FakeFlutterTestRunner implements FlutterTestRunner {
+ FakeFlutterTestRunner(this.exitCode);
+
+ int exitCode;
+ bool lastEnableObservatoryValue;
+
+ @override
+ Future<int> runTests(
+ TestWrapper testWrapper,
+ List<String> testFiles, {
+ Directory workDir,
+ List<String> names = const <String>[],
+ List<String> plainNames = const <String>[],
+ bool enableObservatory = false,
+ bool startPaused = false,
+ bool disableServiceAuthCodes = false,
+ bool ipv6 = false,
+ bool machine = false,
+ String precompiledDillPath,
+ Map<String, String> precompiledDillFiles,
+ BuildMode buildMode,
+ bool trackWidgetCreation = false,
+ bool updateGoldens = false,
+ TestWatcher watcher,
+ int concurrency,
+ bool buildTestAssets = false,
+ FlutterProject flutterProject,
+ String icudtlPath,
+ Directory coverageDirectory,
+ bool web = false,
+ String randomSeed = '0',
+ }) async {
+ lastEnableObservatoryValue = enableObservatory;
+ return exitCode;
+ }
+
}
class FakePackageTest implements TestWrapper {