| // 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 'package:args/command_runner.dart'; |
| import 'package:flutter_tools/src/application_package.dart'; |
| import 'package:flutter_tools/src/base/common.dart'; |
| import 'package:flutter_tools/src/build_info.dart'; |
| import 'package:flutter_tools/src/cache.dart'; |
| import 'package:flutter_tools/src/commands/run.dart'; |
| import 'package:flutter_tools/src/device.dart'; |
| import 'package:flutter_tools/src/runner/flutter_command.dart'; |
| import 'package:flutter_tools/src/version.dart'; |
| import 'package:mockito/mockito.dart'; |
| |
| import '../src/common.dart'; |
| import '../src/context.dart'; |
| import '../src/mocks.dart'; |
| |
| void main() { |
| group('run', () { |
| MockApplicationPackageFactory mockApplicationPackageFactory; |
| MockDeviceManager mockDeviceManager; |
| MockFlutterVersion mockStableFlutterVersion; |
| MockFlutterVersion mockUnstableFlutterVersion; |
| |
| setUpAll(() { |
| Cache.disableLocking(); |
| mockApplicationPackageFactory = MockApplicationPackageFactory(); |
| mockDeviceManager = MockDeviceManager(); |
| mockStableFlutterVersion = MockFlutterVersion(isStable: true); |
| mockUnstableFlutterVersion = MockFlutterVersion(isStable: false); |
| }); |
| |
| testUsingContext('fails when target not found', () async { |
| final RunCommand command = RunCommand(); |
| applyMocksToCommand(command); |
| try { |
| await createTestCommandRunner(command).run(<String>['run', '-t', 'abc123']); |
| fail('Expect exception'); |
| } on ToolExit catch (e) { |
| expect(e.exitCode ?? 1, 1); |
| } |
| }); |
| |
| |
| group('dart-flags option', () { |
| setUpAll(() { |
| when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { |
| return Stream<Device>.fromIterable(<Device>[ |
| FakeDevice(), |
| ]); |
| }); |
| }); |
| |
| RunCommand command; |
| List<String> args; |
| setUp(() { |
| command = TestRunCommand(); |
| args = <String> [ |
| 'run', |
| '--dart-flags', '"--observe"', |
| '--no-hot', |
| ]; |
| }); |
| |
| testUsingContext('is not available on stable channel', () async { |
| // Stable branch. |
| try { |
| await createTestCommandRunner(command).run(args); |
| fail('Expect exception'); |
| // ignore: unused_catch_clause |
| } on UsageException catch(e) { |
| // Not available while on stable branch. |
| } |
| }, overrides: <Type, Generator>{ |
| DeviceManager: () => mockDeviceManager, |
| FlutterVersion: () => mockStableFlutterVersion, |
| }); |
| |
| testUsingContext('is populated in debug mode', () async { |
| // FakeDevice.startApp checks that --dart-flags doesn't get dropped and |
| // throws ToolExit with FakeDevice.kSuccess if the flag is populated. |
| try { |
| await createTestCommandRunner(command).run(args); |
| fail('Expect exception'); |
| } on ToolExit catch (e) { |
| expect(e.exitCode, FakeDevice.kSuccess); |
| } |
| }, overrides: <Type, Generator>{ |
| ApplicationPackageFactory: () => mockApplicationPackageFactory, |
| DeviceManager: () => mockDeviceManager, |
| FlutterVersion: () => mockUnstableFlutterVersion, |
| }); |
| |
| testUsingContext('is populated in profile mode', () async { |
| args.add('--profile'); |
| |
| // FakeDevice.startApp checks that --dart-flags doesn't get dropped and |
| // throws ToolExit with FakeDevice.kSuccess if the flag is populated. |
| try { |
| await createTestCommandRunner(command).run(args); |
| fail('Expect exception'); |
| } on ToolExit catch (e) { |
| expect(e.exitCode, FakeDevice.kSuccess); |
| } |
| }, overrides: <Type, Generator>{ |
| ApplicationPackageFactory: () => mockApplicationPackageFactory, |
| DeviceManager: () => mockDeviceManager, |
| FlutterVersion: () => mockUnstableFlutterVersion, |
| }); |
| |
| testUsingContext('is not populated in release mode', () async { |
| args.add('--release'); |
| |
| // FakeDevice.startApp checks that --dart-flags *does* get dropped and |
| // throws ToolExit with FakeDevice.kSuccess if the flag is set to the |
| // empty string. |
| try { |
| await createTestCommandRunner(command).run(args); |
| fail('Expect exception'); |
| } on ToolExit catch (e) { |
| expect(e.exitCode, FakeDevice.kSuccess); |
| } |
| }, overrides: <Type, Generator>{ |
| ApplicationPackageFactory: () => mockApplicationPackageFactory, |
| DeviceManager: () => mockDeviceManager, |
| FlutterVersion: () => mockUnstableFlutterVersion, |
| }); |
| }); |
| |
| testUsingContext('should only request artifacts corresponding to connected devices', () async { |
| when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { |
| return Stream<Device>.fromIterable(<Device>[ |
| MockDevice(TargetPlatform.android_arm), |
| ]); |
| }); |
| |
| expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{ |
| DevelopmentArtifact.universal, |
| DevelopmentArtifact.android, |
| })); |
| |
| when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { |
| return Stream<Device>.fromIterable(<Device>[ |
| MockDevice(TargetPlatform.ios), |
| ]); |
| }); |
| |
| expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{ |
| DevelopmentArtifact.universal, |
| DevelopmentArtifact.iOS, |
| })); |
| |
| when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { |
| return Stream<Device>.fromIterable(<Device>[ |
| MockDevice(TargetPlatform.ios), |
| MockDevice(TargetPlatform.android_arm), |
| ]); |
| }); |
| |
| expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{ |
| DevelopmentArtifact.universal, |
| DevelopmentArtifact.iOS, |
| DevelopmentArtifact.android, |
| })); |
| |
| when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { |
| return Stream<Device>.fromIterable(<Device>[ |
| MockDevice(TargetPlatform.web_javascript), |
| ]); |
| }); |
| |
| expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{ |
| DevelopmentArtifact.universal, |
| DevelopmentArtifact.web, |
| })); |
| }, overrides: <Type, Generator>{ |
| DeviceManager: () => mockDeviceManager, |
| }); |
| }); |
| } |
| |
| class MockDeviceManager extends Mock implements DeviceManager {} |
| class MockDevice extends Mock implements Device { |
| MockDevice(this._targetPlatform); |
| |
| final TargetPlatform _targetPlatform; |
| |
| @override |
| Future<TargetPlatform> get targetPlatform async => _targetPlatform; |
| } |
| |
| class TestRunCommand extends RunCommand { |
| @override |
| // ignore: must_call_super |
| Future<void> validateCommand() async { |
| devices = await deviceManager.getDevices().toList(); |
| } |
| } |
| |
| class MockStableFlutterVersion extends MockFlutterVersion { |
| @override |
| bool get isMaster => false; |
| } |
| |
| class FakeDevice extends Fake implements Device { |
| static const int kSuccess = 1; |
| static const int kFailure = -1; |
| final TargetPlatform _targetPlatform = TargetPlatform.ios; |
| |
| void _throwToolExit(int code) => throwToolExit(null, exitCode: code); |
| |
| @override |
| Future<bool> get isLocalEmulator => Future<bool>.value(false); |
| |
| @override |
| bool get supportsHotReload => false; |
| |
| @override |
| Future<String> get sdkNameAndVersion => Future<String>.value(''); |
| |
| @override |
| DeviceLogReader getLogReader({ ApplicationPackage app }) { |
| return MockDeviceLogReader(); |
| } |
| |
| @override |
| String get name => 'FakeDevice'; |
| |
| @override |
| Future<TargetPlatform> get targetPlatform async => _targetPlatform; |
| |
| @override |
| Future<LaunchResult> startApp( |
| ApplicationPackage package, { |
| String mainPath, |
| String route, |
| DebuggingOptions debuggingOptions, |
| Map<String, dynamic> platformArgs, |
| bool prebuiltApplication = false, |
| bool usesTerminalUi = true, |
| bool ipv6 = false, |
| }) async { |
| final String dartFlags = debuggingOptions.dartFlags; |
| // In release mode, --dart-flags should be set to the empty string and |
| // provided flags should be dropped. In debug and profile modes, |
| // --dart-flags should not be empty. |
| if (debuggingOptions.buildInfo.isRelease) { |
| if (dartFlags.isNotEmpty) { |
| _throwToolExit(kFailure); |
| } |
| _throwToolExit(kSuccess); |
| } else { |
| if (dartFlags.isEmpty) { |
| _throwToolExit(kFailure); |
| } |
| _throwToolExit(kSuccess); |
| } |
| return null; |
| } |
| } |