Commit c74225e0 authored by xster's avatar xster Committed by GitHub

Report timing on failed executions too (#9661)

* handle errors

* review notes
parent 3012cce1
...@@ -34,13 +34,11 @@ enum ExitStatus { ...@@ -34,13 +34,11 @@ enum ExitStatus {
/// provide a [FlutterCommandResult] to furnish additional information for /// provide a [FlutterCommandResult] to furnish additional information for
/// analytics. /// analytics.
class FlutterCommandResult { class FlutterCommandResult {
FlutterCommandResult( const FlutterCommandResult(
this.exitStatus, { this.exitStatus, {
this.analyticsParameters, this.analyticsParameters,
this.endTimeOverride, this.endTimeOverride,
}) { });
assert(exitStatus != null);
}
final ExitStatus exitStatus; final ExitStatus exitStatus;
...@@ -153,10 +151,15 @@ abstract class FlutterCommand extends Command<Null> { ...@@ -153,10 +151,15 @@ abstract class FlutterCommand extends Command<Null> {
if (flutterUsage.isFirstRun) if (flutterUsage.isFirstRun)
flutterUsage.printWelcome(); flutterUsage.printWelcome();
final FlutterCommandResult commandResult = await verifyThenRunCommand(); FlutterCommandResult commandResult;
try {
commandResult = await verifyThenRunCommand();
} on ToolExit {
commandResult = const FlutterCommandResult(ExitStatus.fail);
rethrow;
} finally {
final DateTime endTime = clock.now(); final DateTime endTime = clock.now();
printTrace("'flutter $name' took ${getElapsedAsMilliseconds(endTime.difference(startTime))}."); printTrace('"flutter $name" took ${getElapsedAsMilliseconds(endTime.difference(startTime))}.');
if (usagePath != null) { if (usagePath != null) {
final List<String> labels = <String>[]; final List<String> labels = <String>[];
if (commandResult?.exitStatus != null) if (commandResult?.exitStatus != null)
...@@ -180,6 +183,8 @@ abstract class FlutterCommand extends Command<Null> { ...@@ -180,6 +183,8 @@ abstract class FlutterCommand extends Command<Null> {
} }
} }
}
/// Perform validation then call [runCommand] to execute the command. /// Perform validation then call [runCommand] to execute the command.
/// Return a [Future] that completes with an exit code /// Return a [Future] that completes with an exit code
/// indicating whether execution was successful. /// indicating whether execution was successful.
...@@ -202,7 +207,7 @@ abstract class FlutterCommand extends Command<Null> { ...@@ -202,7 +207,7 @@ abstract class FlutterCommand extends Command<Null> {
final String commandPath = await usagePath; final String commandPath = await usagePath;
if (commandPath != null) if (commandPath != null)
flutterUsage.sendCommand(commandPath); flutterUsage.sendCommand(commandPath);
return runCommand(); return await runCommand();
} }
/// Subclasses must implement this to execute the command. /// Subclasses must implement this to execute the command.
......
...@@ -6,6 +6,7 @@ import 'dart:async'; ...@@ -6,6 +6,7 @@ import 'dart:async';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/usage.dart'; import 'package:flutter_tools/src/usage.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:quiver/time.dart'; import 'package:quiver/time.dart';
...@@ -88,14 +89,15 @@ void main() { ...@@ -88,14 +89,15 @@ void main() {
mockTimes = <int>[1000, 2000]; mockTimes = <int>[1000, 2000];
final FlutterCommandResult commandResult = new FlutterCommandResult( final FlutterCommandResult commandResult = new FlutterCommandResult(
ExitStatus.fail, ExitStatus.success,
// nulls should be cleaned up. // nulls should be cleaned up.
analyticsParameters: <String> ['blah1', 'blah2', null, 'blah3'], analyticsParameters: <String> ['blah1', 'blah2', null, 'blah3'],
endTimeOverride: new DateTime.fromMillisecondsSinceEpoch(1500) endTimeOverride: new DateTime.fromMillisecondsSinceEpoch(1500)
); );
final DummyFlutterCommand flutterCommand = final DummyFlutterCommand flutterCommand = new DummyFlutterCommand(
new DummyFlutterCommand(flutterCommandResult: commandResult); commandFunction: () async => commandResult
);
await flutterCommand.run(); await flutterCommand.run();
verify(clock.now()).called(2); verify(clock.now()).called(2);
expect( expect(
...@@ -104,7 +106,7 @@ void main() { ...@@ -104,7 +106,7 @@ void main() {
'flutter', 'flutter',
'dummy', 'dummy',
const Duration(milliseconds: 500), // FlutterCommandResult's end time used instead. const Duration(milliseconds: 500), // FlutterCommandResult's end time used instead.
'fail-blah1-blah2-blah3', 'success-blah1-blah2-blah3',
], ],
); );
}, },
...@@ -113,20 +115,47 @@ void main() { ...@@ -113,20 +115,47 @@ void main() {
Usage: () => usage, Usage: () => usage,
}); });
testUsingContext('report failed execution timing too', () async {
// Crash if called a third time which is unexpected.
mockTimes = <int>[1000, 2000];
final DummyFlutterCommand flutterCommand =
new DummyFlutterCommand(commandFunction: () async { throwToolExit('fail'); });
try {
await flutterCommand.run();
fail('Mock should make this fail');
} on ToolExit {
// Should have still checked time twice.
verify(clock.now()).called(2);
expect(
verify(usage.sendTiming(captureAny, captureAny, captureAny, label: captureAny)).captured,
<dynamic>['flutter', 'dummy', const Duration(milliseconds: 1000), 'fail']
);
}
},
overrides: <Type, Generator>{
Clock: () => clock,
Usage: () => usage,
});
}); });
} }
typedef Future<FlutterCommandResult> CommandFunction();
class DummyFlutterCommand extends FlutterCommand { class DummyFlutterCommand extends FlutterCommand {
DummyFlutterCommand({ DummyFlutterCommand({
this.shouldUpdateCache : false, this.shouldUpdateCache : false,
this.noUsagePath : false, this.noUsagePath : false,
this.flutterCommandResult this.commandFunction,
}); });
final bool noUsagePath; final bool noUsagePath;
final FlutterCommandResult flutterCommandResult; final CommandFunction commandFunction;
@override @override
final bool shouldUpdateCache; final bool shouldUpdateCache;
...@@ -142,7 +171,7 @@ class DummyFlutterCommand extends FlutterCommand { ...@@ -142,7 +171,7 @@ class DummyFlutterCommand extends FlutterCommand {
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
return flutterCommandResult; return commandFunction == null ? null : commandFunction();
} }
} }
......
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