Unverified Commit 24f8f799 authored by Dan Field's avatar Dan Field Committed by GitHub

add an --enable-vmservice flag (#50663)

parent 58a4122b
...@@ -142,7 +142,8 @@ Future<void> run(List<String> args) async { ...@@ -142,7 +142,8 @@ Future<void> run(List<String> args) async {
tests[source] = dill; tests[source] = dill;
} }
exitCode = await runTests( // TODO(dnfield): This should be injected.
exitCode = await const FlutterTestRunner().runTests(
const TestWrapper(), const TestWrapper(),
tests.keys.toList(), tests.keys.toList(),
workDir: testDirectory, workDir: testDirectory,
......
...@@ -27,6 +27,7 @@ class TestCommand extends FastFlutterCommand { ...@@ -27,6 +27,7 @@ class TestCommand extends FastFlutterCommand {
TestCommand({ TestCommand({
bool verboseHelp = false, bool verboseHelp = false,
this.testWrapper = const TestWrapper(), this.testWrapper = const TestWrapper(),
this.testRunner = const FlutterTestRunner(),
}) : assert(testWrapper != null) { }) : assert(testWrapper != null) {
requiresPubspecYaml(); requiresPubspecYaml();
usesPubOption(); usesPubOption();
...@@ -110,6 +111,15 @@ class TestCommand extends FastFlutterCommand { ...@@ -110,6 +111,15 @@ class TestCommand extends FastFlutterCommand {
'test cases (must be a 32bit unsigned integer).\n' 'test cases (must be a 32bit unsigned integer).\n'
'If "random", pick a random seed to use.\n' 'If "random", pick a random seed to use.\n'
'If 0 or not set, do not randomize test case execution order.', '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); usesTrackWidgetCreation(verboseHelp: verboseHelp);
} }
...@@ -117,6 +127,9 @@ class TestCommand extends FastFlutterCommand { ...@@ -117,6 +127,9 @@ class TestCommand extends FastFlutterCommand {
/// The interface for starting and configuring the tester. /// The interface for starting and configuring the tester.
final TestWrapper testWrapper; final TestWrapper testWrapper;
/// Interface for running the tester process.
final FlutterTestRunner testRunner;
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async { Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{}; final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{};
...@@ -235,14 +248,14 @@ class TestCommand extends FastFlutterCommand { ...@@ -235,14 +248,14 @@ class TestCommand extends FastFlutterCommand {
final bool disableServiceAuthCodes = final bool disableServiceAuthCodes =
boolArg('disable-service-auth-codes'); boolArg('disable-service-auth-codes');
final int result = await runTests( final int result = await testRunner.runTests(
testWrapper, testWrapper,
files, files,
workDir: workDir, workDir: workDir,
names: names, names: names,
plainNames: plainNames, plainNames: plainNames,
watcher: watcher, watcher: watcher,
enableObservatory: collector != null || startPaused, enableObservatory: collector != null || startPaused || boolArg('enable-vmservice'),
startPaused: startPaused, startPaused: startPaused,
disableServiceAuthCodes: disableServiceAuthCodes, disableServiceAuthCodes: disableServiceAuthCodes,
ipv6: boolArg('ipv6'), ipv6: boolArg('ipv6'),
......
...@@ -20,141 +20,177 @@ import 'flutter_web_platform.dart'; ...@@ -20,141 +20,177 @@ import 'flutter_web_platform.dart';
import 'test_wrapper.dart'; import 'test_wrapper.dart';
import 'watcher.dart'; import 'watcher.dart';
/// Runs tests using package:test and the Flutter engine. /// A class that abstracts launching the test process from the test runner.
Future<int> runTests( abstract class FlutterTestRunner {
TestWrapper testWrapper, const factory FlutterTestRunner() = _FlutterTestRunnerImpl;
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. /// Runs tests using package:test and the Flutter engine.
final List<String> testArgs = <String>[ Future<int> runTests(
if (!globals.terminal.supportsColor) TestWrapper testWrapper,
'--no-color', List<String> testFiles, {
if (startPaused) Directory workDir,
'--pause-after-load', List<String> names = const <String>[],
if (machine) List<String> plainNames = const <String>[],
...<String>['-r', 'json'] bool enableObservatory = false,
else bool startPaused = false,
...<String>['-r', 'compact'], bool disableServiceAuthCodes = false,
'--concurrency=$concurrency', bool ipv6 = false,
for (final String name in names) bool machine = false,
...<String>['--name', name], String precompiledDillPath,
for (final String plainName in plainNames) Map<String, String> precompiledDillFiles,
...<String>['--plain-name', plainName], @required BuildMode buildMode,
'--test-randomize-ordering-seed=$randomSeed', bool trackWidgetCreation = false,
]; bool updateGoldens = false,
if (web) { TestWatcher watcher,
final String tempBuildDir = globals.fs.systemTempDirectory @required int concurrency,
.createTempSync('flutter_test.') bool buildTestAssets = false,
.absolute FlutterProject flutterProject,
.uri String icudtlPath,
.toFilePath(); Directory coverageDirectory,
final bool result = await webCompilationProxy.initialize( bool web = false,
projectDirectory: flutterProject.directory, String randomSeed = '0',
testOutputDir: tempBuildDir, });
testFiles: testFiles, }
projectName: flutterProject.manifest.appName,
initializePlatform: true, class _FlutterTestRunnerImpl implements FlutterTestRunner {
); const _FlutterTestRunnerImpl();
if (!result) {
throwToolExit('Failed to compile tests'); @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 testArgs
..add('--platform=chrome')
..add('--precompiled=$tempBuildDir')
..add('--') ..add('--')
..addAll(testFiles); ..addAll(testFiles);
testWrapper.registerPlatformPlugin(
<Runtime>[Runtime.chrome], final InternetAddressType serverType =
() { ipv6 ? InternetAddressType.IPv6 : InternetAddressType.IPv4;
return FlutterWebPlatform.start(
flutterProject.directory.path, final loader.FlutterPlatform platform = loader.installHook(
updateGoldens: updateGoldens, testWrapper: testWrapper,
shellPath: shellPath, shellPath: shellPath,
flutterProject: flutterProject, watcher: watcher,
pauseAfterLoad: startPaused, 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 // Make the global packages path absolute.
..add('--') // (Makes sure it still works after we change the current directory.)
..addAll(testFiles); 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;
final loader.FlutterPlatform platform = loader.installHook( try {
testWrapper: testWrapper, if (workDir != null) {
shellPath: shellPath, globals.printTrace('switching to directory $workDir to run tests');
watcher: watcher, globals.fs.currentDirectory = workDir;
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,
);
// 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));
// 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;
}
globals.printTrace('running test package with arguments: $testArgs'); globals.printTrace('running test package with arguments: $testArgs');
await testWrapper.main(testArgs); await testWrapper.main(testArgs);
// test.main() sets dart:io's exitCode global. // test.main() sets dart:io's exitCode global.
globals.printTrace('test package returned with exit code $exitCode'); globals.printTrace('test package returned with exit code $exitCode');
return exitCode; return exitCode;
} finally { } finally {
globals.fs.currentDirectory = saved; globals.fs.currentDirectory = saved;
await platform.close(); await platform.close();
}
} }
} }
...@@ -7,9 +7,13 @@ import 'dart:async'; ...@@ -7,9 +7,13 @@ import 'dart:async';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.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/cache.dart';
import 'package:flutter_tools/src/commands/test.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/test_wrapper.dart';
import 'package:flutter_tools/src/test/watcher.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../../src/common.dart'; import '../../src/common.dart';
...@@ -73,6 +77,92 @@ void main() { ...@@ -73,6 +77,92 @@ void main() {
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
Cache: () => FakeCache(), 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 { class FakePackageTest implements TestWrapper {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment