Fix tests to use Ahem, and helpful changes around that (#9332) * Fix tests to use Ahem, and helpful changes around that - Fix fonts that had metric-specific behaviours. - LiveTestWidgetsFlutterBinding.allowAllFrames has been renamed to LiveTestWidgetsFlutterBinding.framePolicy. - LiveTestWidgetsFlutterBinding now defaults to using a frame policy that pumps slightly more frames, to animate the pointer crosshairs. - Added "flutter run --use-test-fonts" to enable Ahem on devices. - Changed how idle() works to be more effective in live mode. - Display the test name in live mode (unless ahem fonts are enabled). - Added a toString to TextSelectionPoint. - Style nit fixes. * Roll engine to get Ahem changes. * Update tests for dartdoc changes. * Fix flutter_tools tests
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 2e1bf5e..9bc7f22 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -337,7 +337,7 @@ if (debuggingOptions.debuggingEnabled) { // TODO(devoncarew): Remember the forwarding information (so we can later remove the - // port forwarding). + // port forwarding or set it up again when adb fails on us). observatoryDiscovery = new ProtocolDiscovery.observatory( getLogReader(), portForwarder: portForwarder, hostPort: debuggingOptions.observatoryPort); diagnosticDiscovery = new ProtocolDiscovery.diagnosticService( @@ -363,6 +363,8 @@ cmd.addAll(<String>['--ez', 'enable-checked-mode', 'true']); if (debuggingOptions.startPaused) cmd.addAll(<String>['--ez', 'start-paused', 'true']); + if (debuggingOptions.useTestFonts) + cmd.addAll(<String>['--ez', 'use-test-fonts', 'true']); } cmd.add(apk.launchActivity); final String result = runCheckedSync(cmd); @@ -372,9 +374,8 @@ return new LaunchResult.failed(); } - if (!debuggingOptions.debuggingEnabled) { + if (!debuggingOptions.debuggingEnabled) return new LaunchResult.succeeded(); - } // Wait for the service protocol port here. This will complete once the // device has printed "Observatory is listening on...".
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 16da917..50483fe 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -296,6 +296,7 @@ final String deviceId = _getStringArg(args, 'deviceId', required: true); final String projectDirectory = _getStringArg(args, 'projectDirectory', required: true); final bool startPaused = _getBoolArg(args, 'startPaused') ?? false; + final bool useTestFonts = _getBoolArg(args, 'useTestFonts') ?? false; final String route = _getStringArg(args, 'route'); final String mode = _getStringArg(args, 'mode'); final String target = _getStringArg(args, 'target'); @@ -309,10 +310,25 @@ throw "'$projectDirectory' does not exist"; final BuildMode buildMode = getBuildModeForName(mode) ?? BuildMode.debug; + DebuggingOptions options; + if (buildMode == BuildMode.release) { + options = new DebuggingOptions.disabled(buildMode); + } else { + options = new DebuggingOptions.enabled( + buildMode, + startPaused: startPaused, + useTestFonts: useTestFonts, + ); + } final AppInstance app = await startApp( - device, projectDirectory, target, route, - buildMode, startPaused, enableHotReload); + device, + projectDirectory, + target, + route, + options, + enableHotReload, + ); return <String, dynamic>{ 'appId': app.id, @@ -324,28 +340,14 @@ Future<AppInstance> startApp( Device device, String projectDirectory, String target, String route, - BuildMode buildMode, bool startPaused, bool enableHotReload, { + DebuggingOptions options, bool enableHotReload, { String applicationBinary, String projectRootPath, String packagesFilePath, String projectAssets, }) async { - DebuggingOptions options; - - switch (buildMode) { - case BuildMode.debug: - case BuildMode.profile: - options = new DebuggingOptions.enabled(buildMode, startPaused: startPaused); - break; - case BuildMode.release: - options = new DebuggingOptions.disabled(buildMode); - break; - default: - throw 'unhandle build mode: $buildMode'; - } - - if (device.isLocalEmulator && !isEmulatorBuildMode(buildMode)) - throw '${toTitleCase(getModeName(buildMode))} mode is not supported for emulators.'; + if (device.isLocalEmulator && !isEmulatorBuildMode(options.buildMode)) + throw '${toTitleCase(getModeName(options.buildMode))} mode is not supported for emulators.'; // We change the current working directory for the duration of the `start` command. final Directory cwd = fs.currentDirectory;
diff --git a/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart b/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart index dcce29e..e399fc6 100644 --- a/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart +++ b/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart
@@ -25,21 +25,6 @@ // -g //lib/flutter/examples/flutter_gallery:flutter_gallery class FuchsiaReloadCommand extends FlutterCommand { - String _fuchsiaRoot; - String _projectRoot; - String _projectName; - String _binaryName; - String _fuchsiaProjectPath; - String _target; - String _address; - String _dotPackagesPath; - - @override - final String name = 'fuchsia_reload'; - - @override - final String description = 'Hot reload on Fuchsia.'; - FuchsiaReloadCommand() { addBuildModeFlags(defaultToRelease: false); argParser.addOption('address', @@ -58,7 +43,7 @@ help: 'GN target of the application, e.g //path/to/app:app'); argParser.addOption('name-override', abbr: 'n', - help: 'On-device name of the application binary'); + help: 'On-device name of the application binary.'); argParser.addOption('target', abbr: 't', defaultsTo: flx.defaultMainPath, @@ -67,6 +52,21 @@ } @override + final String name = 'fuchsia_reload'; + + @override + final String description = 'Hot reload on Fuchsia.'; + + String _fuchsiaRoot; + String _projectRoot; + String _projectName; + String _binaryName; + String _fuchsiaProjectPath; + String _target; + String _address; + String _dotPackagesPath; + + @override Future<Null> runCommand() async { Cache.releaseLockEarly(); @@ -74,37 +74,34 @@ // Find the network ports used on the device by VM service instances. final List<int> servicePorts = await _getServicePorts(); - if (servicePorts.isEmpty) { - throwToolExit("Couldn't find any running Observatory instances."); - } - for (int port in servicePorts) { - printTrace("Fuchsia service port: $port"); - } + if (servicePorts.isEmpty) + throwToolExit('Couldn\'t find any running Observatory instances.'); + for (int port in servicePorts) + printTrace('Fuchsia service port: $port'); // Check that there are running VM services on the returned // ports, and find the Isolates that are running the target app. - final String isolateName = "$_binaryName\$main"; + final String isolateName = '$_binaryName\$main'; final List<int> targetPorts = await _filterPorts(servicePorts, isolateName); - if (targetPorts.isEmpty) { - throwToolExit("No VMs found running $_binaryName"); - } - for (int port in targetPorts) { - printTrace("Found $_binaryName at $port"); - } + if (targetPorts.isEmpty) + throwToolExit('No VMs found running $_binaryName.'); + for (int port in targetPorts) + printTrace('Found $_binaryName at $port'); // Set up a device and hot runner and attach the hot runner to the first // vm service we found. final int firstPort = targetPorts[0]; - final String fullAddress = "$_address:$firstPort"; + final String fullAddress = '$_address:$firstPort'; final FuchsiaDevice device = new FuchsiaDevice(fullAddress); final HotRunner hotRunner = new HotRunner( - device, - debuggingOptions: new DebuggingOptions.enabled(getBuildMode()), - target: _target, - projectRootPath: _fuchsiaProjectPath, - packagesFilePath: _dotPackagesPath); - final Uri observatoryUri = Uri.parse("http://$fullAddress"); - printStatus("Connecting to $_binaryName at $observatoryUri"); + device, + debuggingOptions: new DebuggingOptions.enabled(getBuildMode()), + target: _target, + projectRootPath: _fuchsiaProjectPath, + packagesFilePath: _dotPackagesPath, + ); + final Uri observatoryUri = Uri.parse('http://$fullAddress'); + printStatus('Connecting to $_binaryName at $observatoryUri'); await hotRunner.attach(observatoryUri, isolateFilter: isolateName); } @@ -112,20 +109,19 @@ Future<List<int>> _filterPorts(List<int> ports, String isolateFilter) async { final List<int> result = <int>[]; for (int port in ports) { - final String addr = "http://$_address:$port"; + final String addr = 'http://$_address:$port'; final Uri uri = Uri.parse(addr); final VMService vmService = VMService.connect(uri); await vmService.getVM(); await vmService.waitForViews(); if (vmService.vm.firstView == null) { - printTrace("Found no views at $addr"); + printTrace('Found no views at $addr'); continue; } for (FlutterView v in vmService.vm.views) { - printTrace("At $addr, found view: ${v.uiIsolate.name}"); - if (v.uiIsolate.name.indexOf(isolateFilter) == 0) { + printTrace('At $addr, found view: ${v.uiIsolate.name}'); + if (v.uiIsolate.name.indexOf(isolateFilter) == 0) result.add(port); - } } } return result; @@ -133,48 +129,36 @@ void _validateArguments() { _fuchsiaRoot = argResults['fuchsia-root']; - if (_fuchsiaRoot == null) { - throwToolExit( - "Please give the location of the Fuchsia tree with --fuchsia-root"); - } - if (!_directoryExists(_fuchsiaRoot)) { - throwToolExit("Specified --fuchsia-root '$_fuchsiaRoot' does not exist"); - } + if (_fuchsiaRoot == null) + throwToolExit('Please give the location of the Fuchsia tree with --fuchsia-root.'); + if (!_directoryExists(_fuchsiaRoot)) + throwToolExit('Specified --fuchsia-root "$_fuchsiaRoot" does not exist.'); _address = argResults['address']; - if (_address == null) { - throwToolExit( - "Give the address of the device running Fuchsia with --address"); - } + if (_address == null) + throwToolExit('Give the address of the device running Fuchsia with --address.'); final List<String> gnTarget = _extractPathAndName(argResults['gn-target']); _projectRoot = gnTarget[0]; _projectName = gnTarget[1]; - _fuchsiaProjectPath = "$_fuchsiaRoot/$_projectRoot"; - if (!_directoryExists(_fuchsiaProjectPath)) { - throwToolExit( - "Target does not exist in the Fuchsia tree: $_fuchsiaProjectPath"); - } + _fuchsiaProjectPath = '$_fuchsiaRoot/$_projectRoot'; + if (!_directoryExists(_fuchsiaProjectPath)) + throwToolExit('Target does not exist in the Fuchsia tree: $_fuchsiaProjectPath.'); final String relativeTarget = argResults['target']; - if (relativeTarget == null) { - throwToolExit('Give the application entry point with --target'); - } - _target = "$_fuchsiaProjectPath/$relativeTarget"; - if (!_fileExists(_target)) { - throwToolExit("Couldn't find application entry point at $_target"); - } + if (relativeTarget == null) + throwToolExit('Give the application entry point with --target.'); + _target = '$_fuchsiaProjectPath/$relativeTarget'; + if (!_fileExists(_target)) + throwToolExit('Couldn\'t find application entry point at $_target.'); final String buildType = argResults['build-type']; - if (buildType == null) { - throwToolExit("Give the build type with --build-type"); - } - final String packagesFileName = "${_projectName}_dart_package.packages"; - _dotPackagesPath = - "$_fuchsiaRoot/out/$buildType/gen/$_projectRoot/$packagesFileName"; - if (!_fileExists(_dotPackagesPath)) { - throwToolExit("Couldn't find .packages file at $_dotPackagesPath"); - } + if (buildType == null) + throwToolExit('Give the build type with --build-type.'); + final String packagesFileName = '${_projectName}_dart_package.packages'; + _dotPackagesPath = '$_fuchsiaRoot/out/$buildType/gen/$_projectRoot/$packagesFileName'; + if (!_fileExists(_dotPackagesPath)) + throwToolExit('Couldn\'t find .packages file at $_dotPackagesPath.'); final String nameOverride = argResults['name-override']; if (nameOverride == null) { @@ -186,26 +170,23 @@ List<String> _extractPathAndName(String gnTarget) { final String errorMessage = - "fuchsia_reload --target '$gnTarget' should have the form: " - "'//path/to/app:name'"; + 'fuchsia_reload --target "$gnTarget" should have the form: ' + '"//path/to/app:name"'; // Separate strings like //path/to/target:app into [path/to/target, app] final int lastColon = gnTarget.lastIndexOf(':'); - if (lastColon < 0) { + if (lastColon < 0) throwToolExit(errorMessage); - } final String name = gnTarget.substring(lastColon + 1); // Skip '//' and chop off after : - if ((gnTarget.length < 3) || (gnTarget[0] != '/') || (gnTarget[1] != '/')) { + if ((gnTarget.length < 3) || (gnTarget[0] != '/') || (gnTarget[1] != '/')) throwToolExit(errorMessage); - } final String path = gnTarget.substring(2, lastColon); return <String>[path, name]; } Future<List<int>> _getServicePorts() async { - final FuchsiaDeviceCommandRunner runner = - new FuchsiaDeviceCommandRunner(_fuchsiaRoot); - final List<String> lsOutput = await runner.run("ls /tmp/dart.services"); + final FuchsiaDeviceCommandRunner runner = new FuchsiaDeviceCommandRunner(_fuchsiaRoot); + final List<String> lsOutput = await runner.run('ls /tmp/dart.services'); final List<int> ports = <int>[]; for (String s in lsOutput) { final String trimmed = s.trim(); @@ -213,9 +194,8 @@ final String lastWord = trimmed.substring(lastSpace + 1); if ((lastWord != '.') && (lastWord != '..')) { final int value = int.parse(lastWord, onError: (_) => null); - if (value != null) { + if (value != null) ports.add(value); - } } } return ports; @@ -242,26 +222,24 @@ Future<List<String>> run(String command) async { final int tag = _rng.nextInt(999999); - const String kNetRunCommand = "out/build-magenta/tools/netruncmd"; + const String kNetRunCommand = 'out/build-magenta/tools/netruncmd'; final String netruncmd = fs.path.join(_fuchsiaRoot, kNetRunCommand); - const String kNetCP = "out/build-magenta/tools/netcp"; + const String kNetCP = 'out/build-magenta/tools/netcp'; final String netcp = fs.path.join(_fuchsiaRoot, kNetCP); - final String remoteStdout = "/tmp/netruncmd.$tag"; - final String localStdout = "${fs.systemTempDirectory.path}/netruncmd.$tag"; - final String redirectedCommand = "$command > $remoteStdout"; + final String remoteStdout = '/tmp/netruncmd.$tag'; + final String localStdout = '${fs.systemTempDirectory.path}/netruncmd.$tag'; + final String redirectedCommand = '$command > $remoteStdout'; // Run the command with output directed to a tmp file. ProcessResult result = - await Process.run(netruncmd, <String>[":", redirectedCommand]); - if (result.exitCode != 0) { + await Process.run(netruncmd, <String>[':', redirectedCommand]); + if (result.exitCode != 0) return null; - } // Copy that file to the local filesystem. - result = await Process.run(netcp, <String>[":$remoteStdout", localStdout]); + result = await Process.run(netcp, <String>[':$remoteStdout', localStdout]); // Try to delete the remote file. Don't care about the result; - Process.run(netruncmd, <String>[":", "rm $remoteStdout"]); - if (result.exitCode != 0) { + Process.run(netruncmd, <String>[':', 'rm $remoteStdout']); + if (result.exitCode != 0) return null; - } // Read the local file. final File f = fs.file(localStdout); List<String> lines;
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index e159780..50fe3ed 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -88,6 +88,14 @@ defaultsTo: false, negatable: false, help: 'Start in a paused mode and wait for a debugger to connect.'); + argParser.addFlag('use-test-fonts', + negatable: true, + defaultsTo: false, + help: 'Enable (and default to) the "Ahem" font. This is a special font\n' + 'used in tests to remove any dependencies on the font metrics. It\n' + 'is enabled when you use "flutter test". Set this flag when running\n' + 'a test using "flutter run" for debugging purposes. This flag is\n' + 'only available when running in debug mode.'); argParser.addFlag('build', defaultsTo: true, help: 'If necessary, build the app before running.'); @@ -126,18 +134,19 @@ hide: !verboseHelp, help: 'Stay resident after launching the application.'); - // Hidden option to enable a benchmarking mode. This will run the given - // application, measure the startup time and the app restart time, write the - // results out to 'refresh_benchmark.json', and exit. This flag is intended - // for use in generating automated flutter benchmarks. - argParser.addFlag('benchmark', negatable: false, hide: !verboseHelp); + argParser.addFlag('benchmark', + negatable: false, + hide: !verboseHelp, + help: 'Enable a benchmarking mode. This will run the given application,\n' + 'measure the startup time and the app restart time, write the\n' + 'results out to "refresh_benchmark.json", and exit. This flag is\n' + 'intended for use in generating automated flutter benchmarks.'); commandValidator = () { - if (!runningWithPrebuiltApplication) - commonCommandValidator(); - // When running with a prebuilt application, no command validation is // necessary. + if (!runningWithPrebuiltApplication) + commonCommandValidator(); }; } @@ -196,6 +205,20 @@ return super.verifyThenRunCommand(); } + DebuggingOptions _createDebuggingOptions() { + if (getBuildMode() == BuildMode.release) { + return new DebuggingOptions.disabled(getBuildMode()); + } else { + return new DebuggingOptions.enabled( + getBuildMode(), + startPaused: argResults['start-paused'], + useTestFonts: argResults['use-test-fonts'], + observatoryPort: observatoryPort, + diagnosticPort: diagnosticPort, + ); + } + } + @override Future<Null> runCommand() async { @@ -212,7 +235,7 @@ try { app = await daemon.appDomain.startApp( device, fs.currentDirectory.path, targetFile, route, - getBuildMode(), argResults['start-paused'], hotMode, + _createDebuggingOptions(), hotMode, applicationBinary: argResults['use-application-binary'], projectRootPath: argResults['project-root'], packagesFilePath: argResults['packages'], @@ -229,19 +252,6 @@ if (device.isLocalEmulator && !isEmulatorBuildMode(getBuildMode())) throwToolExit('${toTitleCase(getModeName(getBuildMode()))} mode is not supported for emulators.'); - DebuggingOptions options; - - if (getBuildMode() == BuildMode.release) { - options = new DebuggingOptions.disabled(getBuildMode()); - } else { - options = new DebuggingOptions.enabled( - getBuildMode(), - startPaused: argResults['start-paused'], - observatoryPort: observatoryPort, - diagnosticPort: diagnosticPort, - ); - } - if (hotMode) { if (!device.supportsHotMode) throwToolExit('Hot mode is not supported by this device. Run with --no-hot.'); @@ -258,7 +268,7 @@ runner = new HotRunner( device, target: targetFile, - debuggingOptions: options, + debuggingOptions: _createDebuggingOptions(), benchmarkMode: argResults['benchmark'], applicationBinary: argResults['use-application-binary'], kernelFilePath: argResults['kernel'], @@ -271,7 +281,7 @@ runner = new ColdRunner( device, target: targetFile, - debuggingOptions: options, + debuggingOptions: _createDebuggingOptions(), traceStartup: traceStartup, applicationBinary: argResults['use-application-binary'], stayResident: stayResident,
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index a69951e..7489153 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -279,12 +279,14 @@ class DebuggingOptions { DebuggingOptions.enabled(this.buildMode, { this.startPaused: false, + this.useTestFonts: false, this.observatoryPort, this.diagnosticPort }) : debuggingEnabled = true; DebuggingOptions.disabled(this.buildMode) : debuggingEnabled = false, + useTestFonts = false, startPaused = false, observatoryPort = null, diagnosticPort = null; @@ -293,6 +295,7 @@ final BuildMode buildMode; final bool startPaused; + final bool useTestFonts; final int observatoryPort; final int diagnosticPort;
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 8f642db..f9cd43b 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -228,6 +228,9 @@ if (debuggingOptions.startPaused) launchArguments.add("--start-paused"); + if (debuggingOptions.useTestFonts) + launchArguments.add("--use-test-fonts"); + if (debuggingOptions.debuggingEnabled) { launchArguments.add("--enable-checked-mode");
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index 3ecd761..fbd99dd 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -455,6 +455,8 @@ args.add('--enable-checked-mode'); if (debuggingOptions.startPaused) args.add('--start-paused'); + if (debuggingOptions.useTestFonts) + args.add('--use-test-fonts'); final int observatoryPort = await debuggingOptions.findBestObservatoryPort(); args.add('--observatory-port=$observatoryPort');
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 94ab4bc3..d843fee 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -210,9 +210,8 @@ } Future<Null> connectToServiceProtocol(Uri uri, {String isolateFilter}) async { - if (!debuggingOptions.debuggingEnabled) { + if (!debuggingOptions.debuggingEnabled) return new Future<Null>.error('Error the service protocol is not enabled.'); - } vmService = VMService.connect(uri); printTrace('Connected to service protocol: $uri'); await vmService.getVM();
diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart index 7bd6ced..a31a326 100644 --- a/packages/flutter_tools/lib/src/run_cold.dart +++ b/packages/flutter_tools/lib/src/run_cold.dart
@@ -100,9 +100,8 @@ startTime.stop(); // Connect to observatory. - if (debuggingOptions.debuggingEnabled) { + if (debuggingOptions.debuggingEnabled) await connectToServiceProtocol(_result.observatoryUri); - } if (_result.hasObservatory) { connectionInfoCompleter?.complete(new DebugConnectionInfo(