From 3419068cb3aa1d31ea4a66dd0169a136c2a7ea92 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Mon, 9 Nov 2015 00:30:45 -0800 Subject: [PATCH] Port test logic to Dart. --- CONTRIBUTING.md | 38 +++-- dev/run_tests | 43 ----- packages/flutter_tools/bin/sky_test.dart | 11 -- .../lib/src/application_package.dart | 2 + packages/flutter_tools/lib/src/artifacts.dart | 23 ++- .../lib/src/build_configuration.dart | 16 +- .../lib/src/commands/flutter_command.dart | 9 +- .../src/commands/flutter_command_runner.dart | 161 ++++++++++++------ .../flutter_tools/lib/src/commands/test.dart | 68 +++++--- packages/flutter_tools/lib/src/device.dart | 1 + travis/test.sh | 2 +- 11 files changed, 220 insertions(+), 154 deletions(-) delete mode 100755 dev/run_tests delete mode 100644 packages/flutter_tools/bin/sky_test.dart diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f1766e8dc..09a29cdb02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,25 +87,27 @@ Testing the `flutter` package is currently a bit harder because we don't yet support testing the `flutter` package with pre-built binaries. To test the package, you'll need to follow the [instructions below](#working-on-the-engine-and-the-framework-at-the-same-time) for working with this repository and the Flutter engine repository -simultaneously and then run the following command: +simultaneously and then run the following command (assuming the `flutter/bin` +directory is in your path): - * `./dev/run_tests --debug` + * `flutter test --debug` Creating a workflow for running the test with a prebuilt binary is -[Issue #56](https://github.com/flutter/flutter/issues/56). If you want to run -a single test individually: +[Issue #56](https://github.com/flutter/flutter/issues/56). If you want +to run a single test individually: - * `./dev/run_tests --debug test/harness/trivial_test.dart` + * `flutter test --debug trivial_test.dart` -Note: The tests are headless, you won't see any UI. You can use `print` to -generate console output or you can interact with the DartVM via observatory at [http://localhost:8181/](http://localhost:8181/). +Note: The tests are headless, you won't see any UI. You can use +`print` to generate console output or you can interact with the DartVM +via observatory at [http://localhost:8181/](http://localhost:8181/). Adding a test ------------- -To add a test, simply create a file whose name ends with `_test.dart` in the -`packags/unit/test` directory. The test should have a `main` function and use -the `test` package. +To add a test, simply create a file whose name ends with `_test.dart` +in the `packages/unit/test` directory. The test should have a `main` +function and use the `test` package. Contributing code ----------------- @@ -120,7 +122,7 @@ To start working on a patch: and [design principles](https://github.com/flutter/engine/blob/master/sky/specs/design.md) before working on anything non-trivial. These guidelines are intended to keep the code consistent and avoid common pitfalls. - * `git commit -a -m ""` + * `git commit -a -m ""` * `git push origin name_of_your_branch` To send us a pull request: @@ -163,15 +165,15 @@ the following steps. (e.g., `out/Debug`). To run examples on Android, build one of the Android configurations (e.g., `out/android_Debug`). -You should now be able to run the tests against your locally built engine using -the `./dev/run_tests` script. To run one of the examples on your device using -your locally built engine, use the `--engine-src-path` option to the `flutter` -tool: +You should now be able to run the tests against your locally built +engine using the `flutter test --debug` command. To run one of the +examples on your device using your locally built engine, use the +`--debug` option to the `flutter` tool: - * `flutter start --engine-src-path /foo/bar/engine/src` + * `flutter start --debug` -Eventually, the `--local-build` flag for the `flutter` command will -automatically set the correct engine src path (see [Issue #57](https://github.com/flutter/flutter/issues/57)). +If you want to test the release version instead of the debug version, +use `--release` instead of `--debug`. Making a breaking change to the engine -------------------------------------- diff --git a/dev/run_tests b/dev/run_tests deleted file mode 100755 index ff0ff364aa..0000000000 --- a/dev/run_tests +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015 The Chromium 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 os -import sys -import subprocess -import argparse - -FLUTTER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -FLUTTER = os.path.join(FLUTTER_ROOT, 'bin', 'flutter') - -UNIT_DIR = os.path.join(FLUTTER_ROOT, 'packages', 'unit') -TESTS_DIR = os.path.join(UNIT_DIR, 'test') -DEFAULT_ENGINE_DIR = os.path.abspath(os.path.join(FLUTTER_ROOT, '..', 'engine', 'src')) - -def main(): - parser = argparse.ArgumentParser(description='Runs Flutter unit tests') - parser.add_argument('--engine-src-path', default=DEFAULT_ENGINE_DIR) - parser.add_argument('--config', default='Debug') - parser.add_argument('--debug', dest='config', action='store_const', const='Debug') - parser.add_argument('--release', dest='config', action='store_const', const='Release') - args, remaining = parser.parse_known_args() - - build_dir = os.path.join(os.path.abspath(args.engine_src_path), 'out', args.config) - - if not remaining: - for root, dirs, files in os.walk(TESTS_DIR): - remaining.extend(os.path.join(root, f) - for f in files if f.endswith("_test.dart")) - - if os.environ['TERM'] == 'dumb': - remaining = [ '--no-color' ] + remaining - - return subprocess.call([ - FLUTTER, - 'test', - '--build-dir=%s' % build_dir - ] + remaining, cwd=UNIT_DIR) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/packages/flutter_tools/bin/sky_test.dart b/packages/flutter_tools/bin/sky_test.dart deleted file mode 100644 index a5e08f626a..0000000000 --- a/packages/flutter_tools/bin/sky_test.dart +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2015 The Chromium 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:sky_tools/src/test/loader.dart' as loader; -import 'package:test/src/executable.dart' as executable; - -main(List args) { - loader.installHook(); - return executable.main(args); -} diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index f705622d57..fbe7e53d88 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart @@ -74,6 +74,7 @@ class ApplicationPackageStore { return iOS; case TargetPlatform.iOSSimulator: return iOSSimulator; + case TargetPlatform.mac: case TargetPlatform.linux: return null; } @@ -110,6 +111,7 @@ class ApplicationPackageStore { iOSSimulator = new IOSApp(localPath: path.join(config.buildDir, IOSApp._defaultName)); break; + case TargetPlatform.mac: case TargetPlatform.linux: break; } diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 17da362ded..0fb7c351b6 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -34,6 +34,8 @@ String _getNameForTargetPlatform(TargetPlatform platform) { return 'ios-arm'; case TargetPlatform.iOSSimulator: return 'ios-x64'; + case TargetPlatform.mac: + return 'darwin-x64'; case TargetPlatform.linux: return 'linux-x64'; } @@ -158,12 +160,31 @@ class ArtifactStore { // These values are initialized by FlutterCommandRunner on startup. static String flutterRoot; - static String packageRoot; + static String packageRoot = 'packages'; + + static bool get isPackageRootValid { + return FileSystemEntity.isDirectorySync(packageRoot); + } + + static void ensurePackageRootIsValid() { + if (!isPackageRootValid) { + String message = '$packageRoot is not a valid directory.'; + if (packageRoot == 'packages') { + if (FileSystemEntity.isFileSync('pubspec.yaml')) + message += '\nDid you run `pub get` in this directory?'; + else + message += '\nDid you run this command from the same directory as your pubspec.yaml file?'; + } + stderr.writeln(message); + throw new ProcessExit(2); + } + } static String _engineRevision; static String get engineRevision { if (_engineRevision == null) { + ensurePackageRootIsValid(); File revisionFile = new File(path.join(packageRoot, 'sky_engine', 'REVISION')); if (revisionFile.existsSync()) _engineRevision = revisionFile.readAsStringSync(); diff --git a/packages/flutter_tools/lib/src/build_configuration.dart b/packages/flutter_tools/lib/src/build_configuration.dart index 1d74bd2e9a..5ac291c8a6 100644 --- a/packages/flutter_tools/lib/src/build_configuration.dart +++ b/packages/flutter_tools/lib/src/build_configuration.dart @@ -24,6 +24,7 @@ enum TargetPlatform { android, iOS, iOSSimulator, + mac, linux, } @@ -36,12 +37,21 @@ HostPlatform getCurrentHostPlatform() { return HostPlatform.linux; } +TargetPlatform getCurrentHostPlatformAsTarget() { + if (Platform.isMacOS) + return TargetPlatform.mac; + if (Platform.isLinux) + return TargetPlatform.linux; + _logging.warning('Unsupported host platform, defaulting to Linux'); + return TargetPlatform.linux; +} + class BuildConfiguration { BuildConfiguration.prebuilt({ this.hostPlatform, this.targetPlatform, this.deviceId - }) : type = BuildType.prebuilt, buildDir = null; + }) : type = BuildType.prebuilt, buildDir = null, testable = false; BuildConfiguration.local({ this.type, @@ -49,7 +59,8 @@ class BuildConfiguration { this.targetPlatform, String enginePath, String buildPath, - this.deviceId + this.deviceId, + this.testable: false }) : buildDir = path.normalize(path.join(enginePath, buildPath)) { assert(type == BuildType.debug || type == BuildType.release); } @@ -59,4 +70,5 @@ class BuildConfiguration { final TargetPlatform targetPlatform; final String buildDir; final String deviceId; + final bool testable; } diff --git a/packages/flutter_tools/lib/src/commands/flutter_command.dart b/packages/flutter_tools/lib/src/commands/flutter_command.dart index 917ece301f..f31ad565c9 100644 --- a/packages/flutter_tools/lib/src/commands/flutter_command.dart +++ b/packages/flutter_tools/lib/src/commands/flutter_command.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:args/command_runner.dart'; import '../application_package.dart'; +import '../build_configuration.dart'; import '../device.dart'; import '../toolchain.dart'; import 'flutter_command_runner.dart'; @@ -18,19 +19,21 @@ abstract class FlutterCommand extends Command { /// Whether this command needs to be run from the root of a project. bool get requiresProjectRoot => true; + List get buildConfigurations => runner.buildConfigurations; + Future downloadApplicationPackages() async { if (applicationPackages == null) - applicationPackages = await ApplicationPackageStore.forConfigs(runner.buildConfigurations); + applicationPackages = await ApplicationPackageStore.forConfigs(buildConfigurations); } Future downloadToolchain() async { if (toolchain == null) - toolchain = await Toolchain.forConfigs(runner.buildConfigurations); + toolchain = await Toolchain.forConfigs(buildConfigurations); } void connectToDevices() { if (devices == null) - devices = new DeviceStore.forConfigs(runner.buildConfigurations); + devices = new DeviceStore.forConfigs(buildConfigurations); } Future downloadApplicationPackagesAndConnectToDevices() async { diff --git a/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart b/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart index 4895fb0949..ee1760836d 100644 --- a/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart @@ -16,6 +16,12 @@ import '../process.dart'; final Logger _logging = new Logger('sky_tools.flutter_command_runner'); +const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo) +const String kFlutterEngineEnvironmentVariableName = 'FLUTTER_ENGINE'; // should point to //engine/src/ (root of flutter/engine repo) +const String kSnapshotFileName = 'flutter_tools.snapshot'; // in //flutter/bin/cache/ +const String kFlutterToolsScriptFileName = 'sky_tools.dart'; // in //flutter/packages/flutter_tools/bin/ +const String kFlutterEnginePackageName = 'sky_engine'; + class FlutterCommandRunner extends CommandRunner { FlutterCommandRunner() : super('flutter', 'Manage your Flutter app development.') { @@ -27,67 +33,76 @@ class FlutterCommandRunner extends CommandRunner { negatable: false, help: 'Very noisy logging, including the output of all ' 'shell commands executed.'); + String packagesHelp; + if (ArtifactStore.isPackageRootValid) + packagesHelp = '\n(defaults to "${ArtifactStore.packageRoot}")'; + else + packagesHelp = '\n(required, since the current directory does not contain a "packages" subdirectory)'; argParser.addOption('package-root', - help: 'Path to your packages directory.', defaultsTo: 'packages'); - argParser.addOption('flutter-root', hide: true, - help: 'The root directory of the Flutter repository.'); + help: 'Path to your packages directory.$packagesHelp'); + argParser.addOption('flutter-root', + help: 'The root directory of the Flutter repository. Defaults to \$$kFlutterRootEnvironmentVariableName if set,\n' + 'otherwise defaults to a value derived from the location of this tool.', defaultsTo: defaultFlutterRoot); + argParser.addOption('android-device-id', help: 'Serial number of the target Android device.'); - argParser.addSeparator('Local build selection options:'); + argParser.addSeparator('Local build selection options (not normally required):'); argParser.addFlag('debug', negatable: false, help: - 'Set this if you are building Flutter locally and want to use the debug build products. ' - 'When set, attempts to automaticaly determine engine-src-path if engine-src-path is ' - 'not set. Not normally required.'); + 'Set this if you are building Flutter locally and want to use the debug build products.\n' + 'Defaults to true if --engine-src-path is specified and --release is not, otherwise false.'); argParser.addFlag('release', negatable: false, help: - 'Set this if you are building Flutter locally and want to use the release build products. ' - 'When set, attempts to automaticaly determine engine-src-path if engine-src-path is ' - 'not set. Note that release is not compatible with the listen command ' - 'on iOS devices and simulators. Not normally required.'); - argParser.addFlag('local-build', - negatable: false, - hide: true, - help: - 'Automatically detect your engine src directory from an overridden Flutter package. ' - 'Useful if you are building Flutter locally and are using a dependency_override for' - 'the Flutter package that points to your engine src directory.'); + 'Set this if you are building Flutter locally and want to use the release build products.\n' + 'The --release option is not compatible with the listen command on iOS devices and simulators.'); argParser.addOption('engine-src-path', help: - 'Path to your engine src directory, if you are building Flutter locally. ' - 'Ignored if neither debug nor release is set. Not normally required.'); + 'Path to your engine src directory, if you are building Flutter locally.\n' + 'Defaults to \$$kFlutterEngineEnvironmentVariableName if set, otherwise defaults to the path given in your pubspec.yaml\n' + 'dependency_overrides for $kFlutterEnginePackageName, if any, or, failing that, tries to guess at the location\n' + 'based on the value of the --flutter-root option.'); + argParser.addOption('host-debug-build-path', hide: true, + help: + 'Path to your host Debug out directory (i.e. the one that runs on your workstation, not a device), if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', + defaultsTo: 'out/Debug/'); + argParser.addOption('host-release-build-path', hide: true, + help: + 'Path to your host Release out directory (i.e. the one that runs on your workstation, not a device), if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', + defaultsTo: 'out/Release/'); argParser.addOption('android-debug-build-path', hide: true, help: - 'Path to your Android Debug out directory, if you are building Flutter locally. ' - 'This path is relative to engine-src-path. Not normally required.', + 'Path to your Android Debug out directory, if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', defaultsTo: 'out/android_Debug/'); argParser.addOption('android-release-build-path', hide: true, help: - 'Path to your Android Release out directory, if you are building Flutter locally. ' - 'This path is relative to engine-src-path. Not normally required.', + 'Path to your Android Release out directory, if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', defaultsTo: 'out/android_Release/'); argParser.addOption('ios-debug-build-path', hide: true, help: - 'Path to your iOS Debug out directory, if you are building Flutter locally. ' - 'This path is relative to engine-src-path. Not normally required.', + 'Path to your iOS Debug out directory, if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', defaultsTo: 'out/ios_Debug/'); argParser.addOption('ios-release-build-path', hide: true, help: - 'Path to your iOS Release out directory, if you are building Flutter locally. ' - 'This path is relative to engine-src-path. Not normally required.', + 'Path to your iOS Release out directory, if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', defaultsTo: 'out/ios_Release/'); argParser.addOption('ios-sim-debug-build-path', hide: true, help: - 'Path to your iOS Simulator Debug out directory, if you are building Sky locally. ' - 'This path is relative to engine-src-path. Not normally required.', + 'Path to your iOS Simulator Debug out directory, if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', defaultsTo: 'out/ios_sim_Debug/'); argParser.addOption('ios-sim-release-build-path', hide: true, help: - 'Path to your iOS Simulator Release out directory, if you are building Sky locally. ' - 'This path is relative to engine-src-path. Not normally required.', + 'Path to your iOS Simulator Release out directory, if you are building Flutter locally.\n' + 'This path is relative to --engine-src-path. Not normally required.', defaultsTo: 'out/ios_sim_Release/'); } @@ -100,6 +115,17 @@ class FlutterCommandRunner extends CommandRunner { ArgResults _globalResults; + String get defaultFlutterRoot { + String script = Platform.script.toFilePath(); + if (Platform.environment.containsKey(kFlutterRootEnvironmentVariableName)) + return Platform.environment[kFlutterRootEnvironmentVariableName]; + if (path.basename(script) == kSnapshotFileName) + return path.dirname(path.dirname(path.dirname(script))); + if (path.basename(script) == kFlutterToolsScriptFileName) + return path.dirname(path.dirname(path.dirname(path.dirname(script)))); + return '.'; + } + Future runCommand(ArgResults globalResults) { if (globalResults['verbose']) Logger.root.level = Level.INFO; @@ -108,39 +134,44 @@ class FlutterCommandRunner extends CommandRunner { Logger.root.level = Level.FINE; _globalResults = globalResults; - ArtifactStore.flutterRoot = globalResults['flutter-root'] ?? Platform.environment['FLUTTER_ROOT']; - ArtifactStore.packageRoot = globalResults['package-root']; + ArtifactStore.flutterRoot = globalResults['flutter-root']; + if (globalResults.wasParsed('package-root')) + ArtifactStore.packageRoot = globalResults['package-root']; return super.runCommand(globalResults); } List _createBuildConfigurations(ArgResults globalResults) { - if (!FileSystemEntity.isDirectorySync(ArtifactStore.packageRoot)) { - String message = '${ArtifactStore.packageRoot} is not a valid directory.'; - if (ArtifactStore.packageRoot == 'packages') { - if (FileSystemEntity.isFileSync('pubspec.yaml')) - message += '\nDid you run `pub get` in this directory?'; - else - message += '\nDid you run this command from the same directory as your pubspec.yaml file?'; - } - stderr.writeln(message); - throw new ProcessExit(2); - } - - String enginePath = globalResults['engine-src-path']; + String enginePath = globalResults['engine-src-path'] ?? Platform.environment[kFlutterEngineEnvironmentVariableName]; bool isDebug = globalResults['debug']; bool isRelease = globalResults['release']; HostPlatform hostPlatform = getCurrentHostPlatform(); + TargetPlatform hostPlatformAsTarget = getCurrentHostPlatformAsTarget(); - if (enginePath == null && globalResults['local-build']) { - Directory flutterDir = new Directory(path.join(globalResults['package-root'], 'flutter')); - String realFlutterPath = flutterDir.resolveSymbolicLinksSync(); - - enginePath = path.dirname(path.dirname(path.dirname(path.dirname(realFlutterPath)))); - bool dirExists = FileSystemEntity.isDirectorySync(path.join(enginePath, 'out')); - if (enginePath == '/' || enginePath.isEmpty || !dirExists) { - stderr.writeln('Unable to detect local build in $enginePath.\n' - 'Do you have a dependency override for the flutter package?'); + if (enginePath == null && (isDebug || isRelease)) { + if (ArtifactStore.isPackageRootValid) { + Directory engineDir = new Directory(path.join(ArtifactStore.packageRoot, kFlutterEnginePackageName)); + try { + String realEnginePath = engineDir.resolveSymbolicLinksSync(); + enginePath = path.dirname(path.dirname(path.dirname(path.dirname(realEnginePath)))); + bool dirExists = FileSystemEntity.isDirectorySync(path.join(enginePath, 'out')); + if (enginePath == '/' || enginePath.isEmpty || !dirExists) + enginePath = null; + } on FileSystemException { } + } + if (enginePath == null) { + String tryEnginePath(String enginePath) { + if (FileSystemEntity.isDirectorySync(path.join(enginePath, 'out'))) + return enginePath; + return null; + } + enginePath = tryEnginePath(path.join(ArtifactStore.flutterRoot, '../engine/src')); + } + if (enginePath == null) { + stderr.writeln('Unable to detect local Flutter engine build directory.\n' + 'Either specify a dependency_override for the $kFlutterEnginePackageName package in your pubspec.yaml and\n' + 'ensure --package-root is set if necessary, or set the \$$kFlutterEngineEnvironmentVariableName environment variable, or\n' + 'use --engine-src-path to specify the path to the root of your flutter/engine repository.'); throw new ProcessExit(2); } } @@ -161,6 +192,15 @@ class FlutterCommandRunner extends CommandRunner { isDebug = true; if (isDebug) { + configs.add(new BuildConfiguration.local( + type: BuildType.debug, + hostPlatform: hostPlatform, + targetPlatform: hostPlatformAsTarget, + enginePath: enginePath, + buildPath: globalResults['host-debug-build-path'], + testable: true + )); + configs.add(new BuildConfiguration.local( type: BuildType.debug, hostPlatform: hostPlatform, @@ -190,6 +230,15 @@ class FlutterCommandRunner extends CommandRunner { } if (isRelease) { + configs.add(new BuildConfiguration.local( + type: BuildType.release, + hostPlatform: hostPlatform, + targetPlatform: hostPlatformAsTarget, + enginePath: enginePath, + buildPath: globalResults['host-release-build-path'], + testable: true + )); + configs.add(new BuildConfiguration.local( type: BuildType.release, hostPlatform: hostPlatform, diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index ac10a12b09..6cbc9a92be 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -9,36 +9,66 @@ import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import 'package:test/src/executable.dart' as executable; -import 'flutter_command.dart'; +import '../artifacts.dart'; +import '../build_configuration.dart'; import '../test/loader.dart' as loader; +import 'flutter_command.dart'; final Logger _logging = new Logger('sky_tools.test'); class TestCommand extends FlutterCommand { - final String name = 'test'; - final String description = 'Runs Flutter unit tests for the current project (requires a local build of the engine).'; + String get name => 'test'; + String get description => 'Runs Flutter unit tests for the current project. At least one of --debug and --release must be set.'; - TestCommand() { - argParser.addOption('build-dir', help: 'The directory in which to find a prebuilt engine'); - } + bool get requiresProjectRoot => false; - String get _shellPath { - if (Platform.isLinux) - return path.join(argResults['build-dir'], 'sky_shell'); - if (Platform.isMacOS) - return path.join(argResults['build-dir'], 'SkyShell.app', 'Contents', 'MacOS', 'SkyShell'); - throw new Exception('Unsupported platform.'); + String getShellPath(TargetPlatform platform, String buildPath) { + switch (platform) { + case TargetPlatform.linux: + return path.join(buildPath, 'sky_shell'); + case TargetPlatform.mac: + return path.join(buildPath, 'SkyShell.app', 'Contents', 'MacOS', 'SkyShell'); + default: + throw new Exception('Unsupported platform.'); + } } @override Future runInProject() async { - loader.shellPath = _shellPath; - if (!FileSystemEntity.isFileSync(loader.shellPath)) { - _logging.severe('Cannot find Flutter Shell at ${loader.shellPath}'); + List testArgs = argResults.rest.toList(); + Directory testDir = new Directory(path.join(ArtifactStore.flutterRoot, 'packages/unit/test')); + if (testArgs.isEmpty) { + testArgs.addAll(testDir.listSync(recursive: true, followLinks: false) + .where((FileSystemEntity entity) => entity.path.endsWith('_test.dart') && FileSystemEntity.isFileSync(entity.path)) + .map((FileSystemEntity entity) => path.absolute(entity.path))); + } + testArgs.insert(0, '--'); + if (Platform.environment['TERM'] == 'dumb') + testArgs.insert(0, '--no-color'); + List configs = buildConfigurations; + bool foundOne = false; + String currentDirectory = Directory.current.path; + Directory.current = testDir.path; + // TODO(ianh): Verify that this directory has had 'pub get' run in it at least once. + loader.installHook(); + for (BuildConfiguration config in configs) { + if (!config.testable) + continue; + foundOne = true; + loader.shellPath = path.join(currentDirectory, getShellPath(config.targetPlatform, config.buildDir)); + if (!FileSystemEntity.isFileSync(loader.shellPath)) { + _logging.severe('Cannot find Flutter shell at ${loader.shellPath}'); + return 1; + } + await executable.main(testArgs); + if (exitCode != 0) + return exitCode; + } + if (!foundOne) { + stderr.writeln('At least one of --debug or --release must be set, to specify the local build products to test.'); return 1; } - loader.installHook(); - await executable.main(argResults.rest); - return exitCode; + + return 0; } -} +} \ No newline at end of file diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index d92cf9613e..2f01eea4e4 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -920,6 +920,7 @@ class DeviceStore { assert(iOSSimulator == null); iOSSimulator = new IOSSimulator(); break; + case TargetPlatform.mac: case TargetPlatform.linux: break; } diff --git a/travis/test.sh b/travis/test.sh index d2fd71154a..45d8db63eb 100755 --- a/travis/test.sh +++ b/travis/test.sh @@ -6,4 +6,4 @@ set -ex (cd packages/flx; pub global run tuneup check; pub run test -j1) (cd packages/newton; pub global run tuneup check; pub run test -j1) -./dev/run_tests --engine-src-path bin/cache/travis +./bin/flutter test --engine-src-path bin/cache/travis