Commit 02685104 authored by Christopher Fujino's avatar Christopher Fujino Committed by Flutter GitHub Bot

Fix analytics regression (#46242)

parent a4f7a0df
...@@ -284,6 +284,10 @@ class RunCommand extends RunCommandBase { ...@@ -284,6 +284,10 @@ class RunCommand extends RunCommandBase {
if (!runningWithPrebuiltApplication) { if (!runningWithPrebuiltApplication) {
await super.validateCommand(); await super.validateCommand();
} }
devices = await findAllTargetDevices();
if (devices == null) {
throwToolExit(null);
}
if (deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) { if (deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
throwToolExit('Using -d all with --use-application-binary is not supported'); throwToolExit('Using -d all with --use-application-binary is not supported');
} }
...@@ -332,11 +336,6 @@ class RunCommand extends RunCommandBase { ...@@ -332,11 +336,6 @@ class RunCommand extends RunCommandBase {
writePidFile(stringArg('pid-file')); writePidFile(stringArg('pid-file'));
devices = await findAllTargetDevices();
if (devices == null) {
throwToolExit(null);
}
if (boolArg('machine')) { if (boolArg('machine')) {
if (devices.length > 1) { if (devices.length > 1) {
throwToolExit('--machine does not support -d all.'); throwToolExit('--machine does not support -d all.');
......
...@@ -588,8 +588,6 @@ abstract class FlutterCommand extends Command<void> { ...@@ -588,8 +588,6 @@ abstract class FlutterCommand extends Command<void> {
/// rather than calling [runCommand] directly. /// rather than calling [runCommand] directly.
@mustCallSuper @mustCallSuper
Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async { Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async {
await validateCommand();
// Populate the cache. We call this before pub get below so that the // Populate the cache. We call this before pub get below so that the
// sky_engine package is available in the flutter cache for pub to find. // sky_engine package is available in the flutter cache for pub to find.
if (shouldUpdateCache) { if (shouldUpdateCache) {
...@@ -600,6 +598,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -600,6 +598,8 @@ abstract class FlutterCommand extends Command<void> {
await cache.updateAll(await requiredArtifacts); await cache.updateAll(await requiredArtifacts);
} }
await validateCommand();
if (shouldRunPub) { if (shouldRunPub) {
await pub.get(context: PubContext.getVerifyContext(name)); await pub.get(context: PubContext.getVerifyContext(name));
final FlutterProject project = FlutterProject.current(); final FlutterProject project = FlutterProject.current();
......
...@@ -8,14 +8,17 @@ import 'package:file/file.dart'; ...@@ -8,14 +8,17 @@ import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/build_info.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/run.dart'; import 'package:flutter_tools/src/commands/run.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/features.dart'; import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/resident_runner.dart'; import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/version.dart'; import 'package:flutter_tools/src/version.dart';
...@@ -53,14 +56,18 @@ void main() { ...@@ -53,14 +56,18 @@ void main() {
} }
}); });
group('cache', () { group('run app', () {
MemoryFileSystem fs; MemoryFileSystem fs;
MockArtifacts mockArtifacts;
MockCache mockCache; MockCache mockCache;
MockProcessManager mockProcessManager; MockProcessManager mockProcessManager;
MockUsage mockUsage;
Directory tempDir; Directory tempDir;
setUpAll(() { setUpAll(() {
mockArtifacts = MockArtifacts();
mockCache = MockCache(); mockCache = MockCache();
mockUsage = MockUsage();
fs = MemoryFileSystem(); fs = MemoryFileSystem();
mockProcessManager = MockProcessManager(); mockProcessManager = MockProcessManager();
...@@ -80,15 +87,46 @@ void main() { ...@@ -80,15 +87,46 @@ void main() {
when(mockDeviceManager.hasSpecifiedAllDevices).thenReturn(false); when(mockDeviceManager.hasSpecifiedAllDevices).thenReturn(false);
}); });
testUsingContext('updates before checking for devices', () async { testUsingContext('exits with a user message when no supported devices attached', () async {
final RunCommand command = RunCommand(); final RunCommand command = RunCommand();
applyMocksToCommand(command); applyMocksToCommand(command);
// No devices are attached, we just want to verify update the cache const List<Device> noDevices = <Device>[];
// BEFORE checking for devices when(mockDeviceManager.getDevices()).thenAnswer(
(Invocation invocation) => Stream<Device>.fromIterable(noDevices)
);
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(noDevices)
);
try {
await createTestCommandRunner(command).run(<String>[
'run',
'--no-pub',
'--no-hot',
]);
fail('Expect exception');
} on ToolExit catch (e) {
expect(e.message, null);
}
expect(testLogger.statusText, contains(userMessages.flutterNoSupportedDevices));
}, overrides: <Type, Generator>{
DeviceManager: () => mockDeviceManager,
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
});
testUsingContext('updates cache before checking for devices', () async {
final RunCommand command = RunCommand();
applyMocksToCommand(command);
// Called as part of requiredArtifacts()
when(mockDeviceManager.getDevices()).thenAnswer( when(mockDeviceManager.getDevices()).thenAnswer(
(Invocation invocation) => Stream<Device>.fromIterable(<Device>[]) (Invocation invocation) => Stream<Device>.fromIterable(<Device>[])
); );
// No devices are attached, we just want to verify update the cache
// BEFORE checking for devices
when(mockDeviceManager.findTargetDevices(any)).thenAnswer( when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(<Device>[]) (Invocation invocation) => Future<List<Device>>.value(<Device>[])
); );
...@@ -107,7 +145,11 @@ void main() { ...@@ -107,7 +145,11 @@ void main() {
} }
verifyInOrder(<void>[ verifyInOrder(<void>[
// cache update
mockCache.updateAll(<DevelopmentArtifact>{DevelopmentArtifact.universal}), mockCache.updateAll(<DevelopmentArtifact>{DevelopmentArtifact.universal}),
// as part of gathering `requiredArtifacts`
mockDeviceManager.getDevices(),
// in validateCommand()
mockDeviceManager.findTargetDevices(any), mockDeviceManager.findTargetDevices(any),
]); ]);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
...@@ -117,6 +159,67 @@ void main() { ...@@ -117,6 +159,67 @@ void main() {
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
}); });
testUsingContext('passes device target platform to usage', () async {
final RunCommand command = RunCommand();
applyMocksToCommand(command);
final MockDevice mockDevice = MockDevice(TargetPlatform.ios);
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) => Future<bool>.value(false));
when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(MockDeviceLogReader());
// App fails to start because we're only interested in usage
when(mockDevice.startApp(
any,
mainPath: anyNamed('mainPath'),
debuggingOptions: anyNamed('debuggingOptions'),
platformArgs: anyNamed('platformArgs'),
route: anyNamed('route'),
prebuiltApplication: anyNamed('prebuiltApplication'),
ipv6: anyNamed('ipv6'),
)).thenAnswer((Invocation invocation) => Future<LaunchResult>.value(LaunchResult.failed()));
when(mockArtifacts.getArtifactPath(
Artifact.flutterPatchedSdkPath,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
)).thenReturn('/path/to/sdk');
when(mockDeviceManager.getDevices()).thenAnswer(
(Invocation invocation) => Stream<Device>.fromIterable(<Device>[mockDevice]),
);
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(<Device>[mockDevice])
);
try {
await createTestCommandRunner(command).run(<String>[
'run',
'--no-pub',
'--no-hot',
]);
fail('Exception expected');
} on ToolExit catch (e) {
// We expect a ToolExit because app does not start
expect(e.message, null);
} catch (e) {
fail('ToolExit expected');
}
final List<dynamic> captures = verify(mockUsage.sendCommand(
captureAny,
parameters: captureAnyNamed('parameters'),
)).captured;
expect(captures[0], 'run');
final Map<String, String> parameters = captures[1] as Map<String, String>;
expect(parameters['cd4'], 'ios');
}, overrides: <Type, Generator>{
ApplicationPackageFactory: () => mockApplicationPackageFactory,
Artifacts: () => mockArtifacts,
Cache: () => mockCache,
DeviceManager: () => mockDeviceManager,
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
});
}); });
group('dart-flags option', () { group('dart-flags option', () {
...@@ -351,7 +454,9 @@ void main() { ...@@ -351,7 +454,9 @@ void main() {
}); });
} }
class MockArtifacts extends Mock implements Artifacts {}
class MockCache extends Mock implements Cache {} class MockCache extends Mock implements Cache {}
class MockUsage extends Mock implements Usage {}
class MockDeviceManager extends Mock implements DeviceManager {} class MockDeviceManager extends Mock implements DeviceManager {}
class MockDevice extends Mock implements Device { class MockDevice extends Mock implements Device {
...@@ -360,7 +465,7 @@ class MockDevice extends Mock implements Device { ...@@ -360,7 +465,7 @@ class MockDevice extends Mock implements Device {
final TargetPlatform _targetPlatform; final TargetPlatform _targetPlatform;
@override @override
Future<TargetPlatform> get targetPlatform async => _targetPlatform; Future<TargetPlatform> get targetPlatform async => Future<TargetPlatform>.value(_targetPlatform);
} }
class TestRunCommand extends RunCommand { class TestRunCommand extends RunCommand {
......
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