Commit 2dbceafb authored by Devon Carew's avatar Devon Carew

introduce globals scoped to the app's context

parent b2c710dd
......@@ -8,6 +8,8 @@ import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:stack_trace/stack_trace.dart';
import 'src/base/context.dart';
import 'src/base/logger.dart';
import 'src/base/process.dart';
import 'src/commands/analyze.dart';
import 'src/commands/apk.dart';
......@@ -27,6 +29,7 @@ import 'src/commands/stop.dart';
import 'src/commands/test.dart';
import 'src/commands/trace.dart';
import 'src/commands/upgrade.dart';
import 'src/device.dart';
import 'src/runner/flutter_command_runner.dart';
/// Main entry point for commands.
......@@ -62,7 +65,12 @@ Future main(List<String> args) async {
if (args.isNotEmpty && args[0] == 'init')
args[0] = 'create';
// Initialize globals.
context[Logger] = new StdoutLogger();
context[DeviceManager] = new DeviceManager();
dynamic result = await runner.run(args);
if (result is int)
exit(result);
}, onError: (error, Chain chain) {
......
......@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:io';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
// https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT
......
......@@ -10,7 +10,7 @@ import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/os.dart';
import '../base/process.dart';
import '../build_configuration.dart';
......
......@@ -8,7 +8,7 @@ import 'dart:io';
import 'package:archive/archive.dart';
import 'package:path/path.dart' as path;
import 'base/context.dart';
import 'base/globals.dart';
import 'base/os.dart';
import 'base/process.dart';
import 'build_configuration.dart';
......
......@@ -3,9 +3,8 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
final AppContext _defaultContext = new _DefaultAppContext();
final AppContext _defaultContext = new AppContext();
/// A singleton for application functionality. This singleton can be different
/// on a per-Zone basis.
......@@ -14,57 +13,42 @@ AppContext get context {
return currentContext == null ? _defaultContext : currentContext;
}
/// Display an error level message to the user. Commands should use this if they
/// fail in some way.
void printError(String message, [StackTrace stackTrace]) => context.printError(message, stackTrace);
class AppContext {
Map<Type, dynamic> _instances = <Type, dynamic>{};
/// Display normal output of the command. This should be used for things like
/// progress messages, success messages, or just normal command output.
void printStatus(String message) => context.printStatus(message);
dynamic getVariable(Type type) {
if (_instances.containsKey(type))
return _instances[type];
/// Use this for verbose tracing output. Users can turn this output on in order
/// to help diagnose issues with the toolchain or with their setup.
void printTrace(String message) => context.printTrace(message);
abstract class AppContext {
bool get verbose;
set verbose(bool value);
void printError(String message, [StackTrace stackTrace]);
void printStatus(String message);
void printTrace(String message);
}
class _DefaultAppContext implements AppContext {
DateTime _startTime = new DateTime.now();
AppContext parent = _calcParent(Zone.current);
return parent?.getVariable(type);
}
bool _verbose = false;
void setVariable(Type type, dynamic instance) {
_instances[type] = instance;
}
bool get verbose => _verbose;
dynamic operator[](Type type) => getVariable(type);
set verbose(bool value) {
_verbose = value;
}
void operator[]=(Type type, dynamic instance) => setVariable(type, instance);
void printError(String message, [StackTrace stackTrace]) {
stderr.writeln(_prefix + message);
if (stackTrace != null)
stderr.writeln(stackTrace);
}
AppContext _calcParent(Zone zone) {
if (this == _defaultContext)
return null;
void printStatus(String message) {
print(_prefix + message);
}
Zone parentZone = zone.parent;
if (parentZone == null)
return _defaultContext;
void printTrace(String message) {
if (_verbose)
print('$_prefix- $message');
AppContext deps = parentZone['context'];
if (deps == this) {
return _calcParent(parentZone);
} else {
return deps != null ? deps : _defaultContext;
}
}
String get _prefix {
if (!_verbose)
return '';
Duration elapsed = new DateTime.now().difference(_startTime);
return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
dynamic runInZone(dynamic method()) {
return runZoned(method, zoneValues: {'context': this});
}
}
// Copyright 2016 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 '../device.dart';
import 'context.dart';
import 'logger.dart';
DeviceManager get deviceManager => context[DeviceManager];
Logger get logger => context[Logger];
/// Display an error level message to the user. Commands should use this if they
/// fail in some way.
void printError(String message, [StackTrace stackTrace]) => logger.printError(message, stackTrace);
/// Display normal output of the command. This should be used for things like
/// progress messages, success messages, or just normal command output.
void printStatus(String message) => logger.printStatus(message);
/// Use this for verbose tracing output. Users can turn this output on in order
/// to help diagnose issues with the toolchain or with their setup.
void printTrace(String message) => logger.printTrace(message);
// Copyright 2016 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 'dart:io';
abstract class Logger {
bool verbose = false;
/// Display an error level message to the user. Commands should use this if they
/// fail in some way.
void printError(String message, [StackTrace stackTrace]);
/// Display normal output of the command. This should be used for things like
/// progress messages, success messages, or just normal command output.
void printStatus(String message);
/// Use this for verbose tracing output. Users can turn this output on in order
/// to help diagnose issues with the toolchain or with their setup.
void printTrace(String message);
}
class StdoutLogger implements Logger {
DateTime _startTime = new DateTime.now();
bool verbose = false;
void printError(String message, [StackTrace stackTrace]) {
stderr.writeln(_prefix + message);
if (stackTrace != null)
stderr.writeln(stackTrace);
}
void printStatus(String message) {
print(_prefix + message);
}
void printTrace(String message) {
if (verbose)
print('$_prefix- $message');
}
String get _prefix {
if (!verbose)
return '';
Duration elapsed = new DateTime.now().difference(_startTime);
return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
}
}
class BufferLogger implements Logger {
StringBuffer _error = new StringBuffer();
StringBuffer _status = new StringBuffer();
StringBuffer _trace = new StringBuffer();
bool verbose = false;
String get errorText => _error.toString();
String get statusText => _status.toString();
String get traceText => _trace.toString();
void printError(String message, [StackTrace stackTrace]) => _error.writeln(message);
void printStatus(String message) => _status.writeln(message);
void printTrace(String message) => _trace.writeln(message);
}
......@@ -6,7 +6,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'context.dart';
import 'globals.dart';
typedef String StringConverter(String string);
......
......@@ -6,7 +6,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'base/context.dart';
import 'base/globals.dart';
enum BuildType {
prebuilt,
......
......@@ -11,7 +11,7 @@ import 'package:den_api/den_api.dart';
import 'package:path/path.dart' as path;
import '../artifacts.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../runner/flutter_command.dart';
......
......@@ -12,8 +12,8 @@ import 'package:yaml/yaml.dart';
import '../android/device_android.dart';
import '../application_package.dart';
import '../artifacts.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
......
......@@ -4,7 +4,7 @@
import 'dart:async';
import '../base/context.dart';
import '../base/globals.dart';
import '../flx.dart';
import '../runner/flutter_command.dart';
import '../toolchain.dart';
......
......@@ -11,7 +11,7 @@ import 'package:path/path.dart' as path;
import '../android/android.dart' as android;
import '../artifacts.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
class CreateCommand extends Command {
......
......@@ -9,6 +9,8 @@ import 'dart:io';
import '../android/adb.dart';
import '../android/device_android.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/logger.dart';
import '../device.dart';
import '../ios/device_ios.dart';
import '../ios/simulator.dart';
......@@ -33,9 +35,11 @@ class DaemonCommand extends FlutterCommand {
Future<int> runInProject() {
printStatus('Starting device daemon...');
NotifyingAppContext appContext = new NotifyingAppContext();
AppContext appContext = new AppContext();
NotifyingLogger notifyingLogger = new NotifyingLogger();
appContext[Logger] = notifyingLogger;
return runZoned(() {
return appContext.runInZone(() {
Stream<Map<String, dynamic>> commandStream = stdin
.transform(UTF8.decoder)
.transform(const LineSplitter())
......@@ -47,10 +51,10 @@ class DaemonCommand extends FlutterCommand {
Daemon daemon = new Daemon(commandStream, (Map command) {
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
}, daemonCommand: this, appContext: appContext);
}, daemonCommand: this, notifyingLogger: notifyingLogger);
return daemon.onExit;
}, zoneValues: {'context': appContext});
});
}
dynamic _jsonEncodeObject(dynamic object) {
......@@ -67,7 +71,7 @@ typedef Future<dynamic> CommandHandler(dynamic args);
class Daemon {
Daemon(Stream<Map> commandStream, this.sendCommand, {
this.daemonCommand,
this.appContext
this.notifyingLogger
}) {
// Set up domains.
_registerDomain(new DaemonDomain(this));
......@@ -83,7 +87,7 @@ class Daemon {
final DispatchComand sendCommand;
final DaemonCommand daemonCommand;
final NotifyingAppContext appContext;
final NotifyingLogger notifyingLogger;
final Completer<int> _onExitCompleter = new Completer<int>();
final Map<String, Domain> _domainMap = <String, Domain>{};
......@@ -185,7 +189,7 @@ class DaemonDomain extends Domain {
registerHandler('version', version);
registerHandler('shutdown', shutdown);
_subscription = daemon.appContext.onMessage.listen((LogMessage message) {
_subscription = daemon.notifyingLogger.onMessage.listen((LogMessage message) {
if (message.stackTrace != null) {
sendEvent('daemon.logMessage', {
'level': message.level,
......@@ -467,13 +471,11 @@ dynamic _toJsonable(dynamic obj) {
return '$obj';
}
class NotifyingAppContext implements AppContext {
class NotifyingLogger extends Logger {
StreamController<LogMessage> _messageController = new StreamController<LogMessage>.broadcast();
Stream<LogMessage> get onMessage => _messageController.stream;
bool verbose = false;
void printError(String message, [StackTrace stackTrace]) {
_messageController.add(new LogMessage('error', message, stackTrace));
}
......
......@@ -8,7 +8,7 @@ import "dart:io";
import "package:path/path.dart" as path;
import "../artifacts.dart";
import "../base/context.dart";
import "../base/globals.dart";
import "../base/process.dart";
import "../runner/flutter_command.dart";
import "../runner/flutter_command_runner.dart";
......
......@@ -4,7 +4,7 @@
import 'dart:async';
import '../base/context.dart';
import '../base/globals.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
......@@ -15,9 +15,7 @@ class ListCommand extends FlutterCommand {
bool get requiresProjectRoot => false;
Future<int> runInProject() async {
DeviceManager deviceManager = new DeviceManager();
List<Device> devices = await deviceManager.getDevices();
List<Device> devices = await deviceManager.getAllConnectedDevices();
if (devices.isEmpty) {
printStatus('No connected devices.');
......
......@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:io';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
import 'start.dart';
......
......@@ -4,7 +4,7 @@
import 'dart:async';
import '../base/context.dart';
import '../base/globals.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
......@@ -24,21 +24,14 @@ class LogsCommand extends FlutterCommand {
Future<int> runInProject() async {
DeviceManager deviceManager = new DeviceManager();
List<Device> devices;
deviceManager.specifiedDeviceId = globalResults['device-id'];
String deviceId = globalResults['device-id'];
if (deviceId != null) {
Device device = await deviceManager.getDeviceById(deviceId);
if (device == null) {
printError("No device found with id '$deviceId'.");
return 1;
}
devices = <Device>[device];
} else {
devices = await deviceManager.getDevices();
}
List<Device> devices = await deviceManager.getDevices();
if (devices.isEmpty) {
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
printError("No device found with id '${deviceManager.specifiedDeviceId}'.");
return 1;
} else if (devices.isEmpty) {
printStatus('No connected devices.');
return 0;
}
......
......@@ -7,7 +7,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import '../base/context.dart';
import '../base/globals.dart';
import '../flx.dart';
import '../runner/flutter_command.dart';
......
......@@ -8,7 +8,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import '../artifacts.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../flx.dart' as flx;
......@@ -118,7 +118,7 @@ class RunMojoCommand extends FlutterCommand {
if (useDevtools) {
final String buildFlag = argResults['mojo-debug'] ? '--debug' : '--release';
args.add(buildFlag);
if (context.verbose)
if (logger.verbose)
args.add('--verbose');
}
......
......@@ -9,7 +9,7 @@ import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../build_configuration.dart';
import '../device.dart';
import '../flx.dart';
......
......@@ -9,7 +9,7 @@ import 'package:path/path.dart' as path;
import 'package:test/src/executable.dart' as executable;
import '../artifacts.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../build_configuration.dart';
import '../runner/flutter_command.dart';
import '../test/loader.dart' as loader;
......
......@@ -6,7 +6,7 @@ import 'dart:async';
import '../android/device_android.dart';
import '../application_package.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../runner/flutter_command.dart';
class TraceCommand extends FlutterCommand {
......
......@@ -5,7 +5,7 @@
import 'dart:async';
import '../artifacts.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
import '../runner/flutter_command.dart';
import '../runner/version.dart';
......
......@@ -7,33 +7,48 @@ import 'dart:async';
import 'android/device_android.dart';
import 'application_package.dart';
import 'base/common.dart';
import 'base/context.dart';
import 'base/globals.dart';
import 'build_configuration.dart';
import 'ios/device_ios.dart';
import 'toolchain.dart';
/// A class to get all available devices.
class DeviceManager {
/// Constructing DeviceManagers is cheap; they only do expensive work if some
/// of their methods are invoked.
DeviceManager() {
// Init the known discoverers.
// Register the known discoverers.
_deviceDiscoverers.add(new AndroidDeviceDiscovery());
_deviceDiscoverers.add(new IOSDeviceDiscovery());
_deviceDiscoverers.add(new IOSSimulatorDiscovery());
}
Future _init() {
if (_initedCompleter == null) {
_initedCompleter = new Completer();
Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) {
if (!discoverer.supportsPlatform)
return null;
return discoverer.init();
}).then((_) {
_initedCompleter.complete();
}).catchError((error, stackTrace) {
_initedCompleter.completeError(error, stackTrace);
});
}
Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) {
if (!discoverer.supportsPlatform)
return null;
return discoverer.init();
}).then((_) {
_initedCompleter.complete();
}).catchError((error, stackTrace) {
_initedCompleter.completeError(error, stackTrace);
});
return _initedCompleter.future;
}
List<DeviceDiscovery> _deviceDiscoverers = <DeviceDiscovery>[];
Completer _initedCompleter = new Completer();
/// A user-specified device ID.
String specifiedDeviceId;
Completer _initedCompleter;
bool get hasSpecifiedDeviceId => specifiedDeviceId != null;
/// Return the device with the matching ID; else, complete the Future with
/// `null`.
......@@ -41,15 +56,26 @@ class DeviceManager {
/// This does a case insentitive compare with `deviceId`.
Future<Device> getDeviceById(String deviceId) async {
deviceId = deviceId.toLowerCase();
List<Device> devices = await getDevices();
List<Device> devices = await getAllConnectedDevices();
return devices.firstWhere(
(Device device) => device.id.toLowerCase() == deviceId,
orElse: () => null
);
}
/// Return the list of connected devices, filtered by any user-specified device id.
Future<List<Device>> getDevices() async {
await _initedCompleter.future;
if (specifiedDeviceId == null) {
return getAllConnectedDevices();
} else {
Device device = await getDeviceById(specifiedDeviceId);
return device == null ? <Device>[] : <Device>[device];
}
}
/// Return the list of all connected devices.
Future<List<Device>> getAllConnectedDevices() async {
await _init();
return _deviceDiscoverers
.where((DeviceDiscovery discoverer) => discoverer.supportsPlatform)
......
......@@ -13,7 +13,7 @@ import 'package:flx/signing.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';
import 'base/context.dart';
import 'base/globals.dart';
import 'base/file_system.dart';
import 'toolchain.dart';
......
......@@ -9,7 +9,7 @@ import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
......
......@@ -6,7 +6,7 @@ import 'dart:async';
import 'dart:convert' show JSON;
import 'dart:io';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
const String _xcrunPath = '/usr/bin/xcrun';
......
......@@ -8,9 +8,9 @@ import 'dart:io';
import 'package:args/command_runner.dart';
import '../application_package.dart';
import '../base/context.dart';
import '../build_configuration.dart';
import '../artifacts.dart';
import '../base/globals.dart';
import '../build_configuration.dart';
import '../device.dart';
import '../toolchain.dart';
import 'flutter_command_runner.dart';
......
......@@ -10,7 +10,7 @@ import 'package:args/command_runner.dart';
import 'package:path/path.dart' as path;
import '../artifacts.dart';
import '../base/context.dart';
import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import 'version.dart';
......@@ -158,10 +158,15 @@ class FlutterCommandRunner extends CommandRunner {
}
Future<int> runCommand(ArgResults globalResults) {
_globalResults = globalResults;
// Check for verbose.
if (globalResults['verbose'])
context.verbose = true;
logger.verbose = true;
// See if the user specified a specific device.
deviceManager.specifiedDeviceId = globalResults['device-id'];
_globalResults = globalResults;
ArtifactStore.flutterRoot = path.normalize(path.absolute(globalResults['flutter-root']));
if (globalResults.wasParsed('package-root'))
ArtifactStore.packageRoot = path.normalize(path.absolute(globalResults['package-root']));
......
......@@ -5,11 +5,13 @@
import 'package:flutter_tools/src/android/device_android.dart';
import 'package:test/test.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('android_device', () {
test('stores the requested id', () {
testUsingContext('stores the requested id', () {
String deviceId = '1234';
AndroidDevice device = new AndroidDevice(deviceId);
expect(device.id, equals(deviceId));
......
......@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/context.dart' hide context;
import 'package:flutter_tools/src/base/globals.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:test/test.dart';
main() => defineTests();
......@@ -12,55 +12,45 @@ main() => defineTests();
defineTests() {
group('DeviceManager', () {
test('error', () async {
MockContext mockContext = new MockContext();
AppContext context = new AppContext();
BufferLogger mockLogger = new BufferLogger();
context[Logger] = mockLogger;
runZoned(() {
context.runInZone(() {
printError('foo bar');
}, zoneValues: {'context': mockContext});
});
expect(mockContext.errorText, 'foo bar\n');
expect(mockContext.statusText, '');
expect(mockContext.traceText, '');
expect(mockLogger.errorText, 'foo bar\n');
expect(mockLogger.statusText, '');
expect(mockLogger.traceText, '');
});
test('status', () async {
MockContext mockContext = new MockContext();
AppContext context = new AppContext();
BufferLogger mockLogger = new BufferLogger();
context[Logger] = mockLogger;
runZoned(() {
context.runInZone(() {
printStatus('foo bar');
}, zoneValues: {'context': mockContext});
});
expect(mockContext.errorText, '');
expect(mockContext.statusText, 'foo bar\n');
expect(mockContext.traceText, '');
expect(mockLogger.errorText, '');
expect(mockLogger.statusText, 'foo bar\n');
expect(mockLogger.traceText, '');
});
test('trace', () async {
MockContext mockContext = new MockContext();
AppContext context = new AppContext();
BufferLogger mockLogger = new BufferLogger();
context[Logger] = mockLogger;
runZoned(() {
context.runInZone(() {
printTrace('foo bar');
}, zoneValues: {'context': mockContext});
});
expect(mockContext.errorText, '');
expect(mockContext.statusText, '');
expect(mockContext.traceText, 'foo bar\n');
expect(mockLogger.errorText, '');
expect(mockLogger.statusText, '');
expect(mockLogger.traceText, 'foo bar\n');
});
});
}
class MockContext implements AppContext {
bool verbose = false;
StringBuffer _error = new StringBuffer();
StringBuffer _status = new StringBuffer();
StringBuffer _trace = new StringBuffer();
String get errorText => _error.toString();
String get statusText => _status.toString();
String get traceText => _trace.toString();
void printError(String message, [StackTrace stackTrace]) => _error.writeln(message);
void printStatus(String message) => _status.writeln(message);
void printTrace(String message) => _trace.writeln(message);
}
......@@ -11,6 +11,8 @@ import 'package:flutter_tools/src/commands/create.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
......@@ -31,7 +33,7 @@ defineTests() {
// TODO(devoncarew): https://github.com/flutter/flutter/issues/1709
if (Platform.isLinux) {
// Verify that we create a project that is well-formed.
test('flutter-simple', () async {
testUsingContext('flutter-simple', () async {
ArtifactStore.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = new CommandRunner('test_flutter', '')
......
......@@ -5,6 +5,8 @@
import 'dart:async';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/globals.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/commands/daemon.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
......@@ -16,10 +18,13 @@ main() => defineTests();
defineTests() {
group('daemon', () {
Daemon daemon;
NotifyingAppContext appContext;
AppContext appContext;
NotifyingLogger notifyingLogger;
setUp(() {
appContext = new NotifyingAppContext();
appContext = new AppContext();
notifyingLogger = new NotifyingLogger();
appContext[Logger] = notifyingLogger;
});
tearDown(() {
......@@ -33,7 +38,7 @@ defineTests() {
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
notifyingLogger: notifyingLogger
);
commands.add({'id': 0, 'method': 'daemon.version'});
Map response = await responses.stream.where(_notEvent).first;
......@@ -43,13 +48,13 @@ defineTests() {
});
test('daemon.logMessage', () {
return runZoned(() async {
return appContext.runInZone(() async {
StreamController<Map<String, dynamic>> commands = new StreamController();
StreamController<Map<String, dynamic>> responses = new StreamController();
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
notifyingLogger: notifyingLogger
);
printError('daemon.logMessage test');
Map<String, dynamic> response = await responses.stream.where((Map<String, dynamic> map) {
......@@ -60,7 +65,7 @@ defineTests() {
Map<String, String> logMessage = response['params'];
expect(logMessage['level'], 'error');
expect(logMessage['message'], 'daemon.logMessage test');
}, zoneValues: {'context': appContext});
});
});
test('daemon.shutdown', () async {
......@@ -69,7 +74,7 @@ defineTests() {
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
notifyingLogger: notifyingLogger
);
commands.add({'id': 0, 'method': 'daemon.shutdown'});
return daemon.onExit.then((int code) {
......@@ -87,7 +92,7 @@ defineTests() {
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
daemonCommand: command,
appContext: appContext
notifyingLogger: notifyingLogger
);
MockDeviceStore mockDevices = command.devices;
......@@ -113,7 +118,7 @@ defineTests() {
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
notifyingLogger: notifyingLogger
);
commands.add({'id': 0, 'method': 'device.getDevices'});
Map response = await responses.stream.where(_notEvent).first;
......
......@@ -5,11 +5,13 @@
import 'package:flutter_tools/src/device.dart';
import 'package:test/test.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('DeviceManager', () {
test('getDevices', () async {
testUsingContext('getDevices', () async {
// Test that DeviceManager.getDevices() doesn't throw.
DeviceManager deviceManager = new DeviceManager();
List<Device> devices = await deviceManager.getDevices();
......
......@@ -33,7 +33,7 @@ defineTests() {
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['install']).then((int code) => expect(code, equals(0)));
return runner.run(['install']).then((int code) => expect(code, equals(0)));
});
test('returns 0 when iOS is connected and ready for an install', () {
......@@ -55,7 +55,7 @@ defineTests() {
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['install']).then((int code) => expect(code, equals(0)));
return runner.run(['install']).then((int code) => expect(code, equals(0)));
});
});
}
......@@ -10,12 +10,13 @@ import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('list', () {
test('returns 0 when called', () {
testUsingContext('returns 0 when called', () {
final String mockCommand = Platform.isWindows ? 'cmd /c echo' : 'echo';
ListCommand command = new ListCommand();
......@@ -36,9 +37,8 @@ defineTests() {
// Instead, cause the test to run the echo command.
when(mockDevices.iOSSimulator.xcrunPath).thenReturn(mockCommand);
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['list']).then((int code) => expect(code, equals(0)));
CommandRunner runner = new CommandRunner('test_flutter', '')..addCommand(command);
return runner.run(['list']).then((int code) => expect(code, equals(0)));
});
});
}
......@@ -9,12 +9,13 @@ import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('listen', () {
test('returns 0 when no device is connected', () {
testUsingContext('returns 0 when no device is connected', () {
ListenCommand command = new ListenCommand(singleRun: true);
applyMocksToCommand(command);
MockDeviceStore mockDevices = command.devices;
......@@ -24,7 +25,7 @@ defineTests() {
when(mockDevices.iOSSimulator.isConnected()).thenReturn(false);
CommandRunner runner = new FlutterCommandRunner()..addCommand(command);
runner.run(['listen']).then((int code) => expect(code, equals(0)));
return runner.run(['listen']).then((int code) => expect(code, equals(0)));
});
});
}
......@@ -8,16 +8,17 @@ import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('logs', () {
test('fail with a bad device id', () {
testUsingContext('fail with a bad device id', () {
LogsCommand command = new LogsCommand();
applyMocksToCommand(command);
CommandRunner runner = new FlutterCommandRunner()..addCommand(command);
runner.run(<String>['-d', 'abc123', 'logs']).then((int code) {
return runner.run(<String>['-d', 'abc123', 'logs']).then((int code) {
expect(code, equals(1));
});
});
......
// Copyright 2016 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 'dart:async';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:test/test.dart';
void testUsingContext(String description, dynamic testMethod(), { Timeout timeout }) {
test(description, () {
AppContext testContext = new AppContext();
testContext[Logger] = new BufferLogger();
testContext[DeviceManager] = new MockDeviceManager();
return testContext.runInZone(testMethod);
}, timeout: timeout);
}
class MockDeviceManager implements DeviceManager {
String specifiedDeviceId;
bool get hasSpecifiedDeviceId => specifiedDeviceId != null;
Future<List<Device>> getAllConnectedDevices() => new Future.value(<Device>[]);
Future<Device> getDeviceById(String deviceId) => new Future.value(null);
Future<List<Device>> getDevices() => getAllConnectedDevices();
}
......@@ -29,7 +29,7 @@ defineTests() {
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['stop']).then((int code) => expect(code, equals(0)));
return runner.run(['stop']).then((int code) => expect(code, equals(0)));
});
test('returns 0 when iOS is connected and ready to be stopped', () {
......@@ -48,7 +48,7 @@ defineTests() {
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['stop']).then((int code) => expect(code, equals(0)));
return runner.run(['stop']).then((int code) => expect(code, equals(0)));
});
});
}
......@@ -8,12 +8,13 @@ import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('trace', () {
test('returns 1 when no Android device is connected', () {
testUsingContext('returns 1 when no Android device is connected', () {
TraceCommand command = new TraceCommand();
applyMocksToCommand(command);
MockDeviceStore mockDevices = command.devices;
......@@ -22,7 +23,7 @@ defineTests() {
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['trace']).then((int code) => expect(code, equals(1)));
return runner.run(['trace']).then((int code) => expect(code, equals(1)));
});
});
}
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