Unverified Commit d208ce2d authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tool] Usage refactor cleanup (#37186)

parent a9aea962
...@@ -334,6 +334,15 @@ class GroupedValidator extends DoctorValidator { ...@@ -334,6 +334,15 @@ class GroupedValidator extends DoctorValidator {
final List<DoctorValidator> subValidators; final List<DoctorValidator> subValidators;
List<ValidationResult> _subResults;
/// Subvalidator results.
///
/// To avoid losing information when results are merged, the subresults are
/// cached on this field when they are available. The results are in the same
/// order as the subvalidator list.
List<ValidationResult> get subResults => _subResults;
@override @override
String get slowWarning => _currentSlowWarning; String get slowWarning => _currentSlowWarning;
String _currentSlowWarning = 'Initializing...'; String _currentSlowWarning = 'Initializing...';
...@@ -356,6 +365,7 @@ class GroupedValidator extends DoctorValidator { ...@@ -356,6 +365,7 @@ class GroupedValidator extends DoctorValidator {
ValidationResult _mergeValidationResults(List<ValidationResult> results) { ValidationResult _mergeValidationResults(List<ValidationResult> results) {
assert(results.isNotEmpty, 'Validation results should not be empty'); assert(results.isNotEmpty, 'Validation results should not be empty');
_subResults = results;
ValidationType mergedType = results[0].type; ValidationType mergedType = results[0].type;
final List<ValidationMessage> mergedMessages = <ValidationMessage>[]; final List<ValidationMessage> mergedMessages = <ValidationMessage>[];
String statusInfo; String statusInfo;
......
...@@ -90,12 +90,27 @@ class HotEvent extends UsageEvent { ...@@ -90,12 +90,27 @@ class HotEvent extends UsageEvent {
/// An event that reports the result of a [DoctorValidator] /// An event that reports the result of a [DoctorValidator]
class DoctorResultEvent extends UsageEvent { class DoctorResultEvent extends UsageEvent {
DoctorResultEvent({ DoctorResultEvent({
@required DoctorValidator validator, @required this.validator,
@required ValidationResult result @required this.result,
}) : super('doctorResult.${validator.runtimeType.toString()}', }) : super('doctorResult.${validator.runtimeType}',
result.typeStr); result.typeStr);
// TODO(zra): Override send() to detect a GroupedValidator and send separate
// events for each sub-validator. final DoctorValidator validator;
final ValidationResult result;
@override
void send() {
if (validator is! GroupedValidator) {
flutterUsage.sendEvent(category, parameter);
return;
}
final GroupedValidator group = validator;
for (int i = 0; i < group.subValidators.length; i++) {
final DoctorValidator v = group.subValidators[i];
final ValidationResult r = group.subResults[i];
DoctorResultEvent(validator: v, result: r).send();
}
}
} }
/// An event that reports success or failure of a pub get. /// An event that reports success or failure of a pub get.
......
...@@ -276,6 +276,22 @@ void main() { ...@@ -276,6 +276,22 @@ void main() {
Platform: _kNoColorOutputPlatform, Platform: _kNoColorOutputPlatform,
Usage: () => mockUsage, Usage: () => mockUsage,
}); });
testUsingContext('events for grouped validators are properly decomposed', () async {
await FakeGroupedDoctor().diagnose(verbose: false);
expect(
verify(mockUsage.sendEvent('doctorResult.PassingGroupedValidator', captureAny)).captured,
<dynamic>['installed', 'installed', 'installed'],
);
expect(
verify(mockUsage.sendEvent('doctorResult.MissingGroupedValidator', captureAny)).captured,
<dynamic>['missing'],
);
}, overrides: <Type, Generator>{
Platform: _kNoColorOutputPlatform,
Usage: () => mockUsage,
});
}); });
group('doctor with fake validators', () { group('doctor with fake validators', () {
......
...@@ -52,6 +52,7 @@ void main() { ...@@ -52,6 +52,7 @@ void main() {
// DevFS Mocks // DevFS Mocks
when(mockDevFS.lastCompiled).thenReturn(DateTime(2000)); when(mockDevFS.lastCompiled).thenReturn(DateTime(2000));
when(mockDevFS.sources).thenReturn(<Uri>[]); when(mockDevFS.sources).thenReturn(<Uri>[]);
when(mockDevFS.baseUri).thenReturn(Uri());
when(mockDevFS.destroy()).thenAnswer((Invocation invocation) async { }); when(mockDevFS.destroy()).thenAnswer((Invocation invocation) async { });
when(mockDevFS.assetPathsToEvict).thenReturn(<String>{}); when(mockDevFS.assetPathsToEvict).thenReturn(<String>{});
// FlutterDevice Mocks. // FlutterDevice Mocks.
...@@ -80,6 +81,7 @@ void main() { ...@@ -80,6 +81,7 @@ void main() {
]); ]);
when(mockFlutterDevice.device).thenReturn(mockDevice); when(mockFlutterDevice.device).thenReturn(mockDevice);
when(mockFlutterView.uiIsolate).thenReturn(mockIsolate); when(mockFlutterView.uiIsolate).thenReturn(mockIsolate);
when(mockFlutterView.runFromSource(any, any, any)).thenAnswer((Invocation invocation) async {});
when(mockFlutterDevice.stopEchoingDeviceLog()).thenAnswer((Invocation invocation) async { }); when(mockFlutterDevice.stopEchoingDeviceLog()).thenAnswer((Invocation invocation) async { });
when(mockFlutterDevice.observatoryUris).thenReturn(<Uri>[ when(mockFlutterDevice.observatoryUris).thenReturn(<Uri>[
testUri, testUri,
...@@ -189,9 +191,6 @@ void main() { ...@@ -189,9 +191,6 @@ void main() {
Usage: () => MockUsage(), Usage: () => MockUsage(),
})); }));
// Need one for hot restart as well.
test('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async { test('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async {
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async { when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
return 'Example'; return 'Example';
...@@ -221,6 +220,36 @@ void main() { ...@@ -221,6 +220,36 @@ void main() {
Usage: () => MockUsage(), Usage: () => MockUsage(),
})); }));
test('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async {
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
return 'Example';
});
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
return TargetPlatform.android_arm;
});
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
return false;
});
when(mockDevice.supportsHotRestart).thenReturn(true);
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
final Completer<void> onAppStart = Completer<void>.sync();
unawaited(residentRunner.attach(
appStartedCompleter: onAppStart,
connectionInfoCompleter: onConnectionInfo,
));
final OperationResult result = await residentRunner.restart(fullRestart: true);
expect(result.fatal, false);
expect(result.code, 0);
expect(verify(flutterUsage.sendEvent('hot', 'restart',
parameters: captureAnyNamed('parameters'))).captured[0],
containsPair(cdKey(CustomDimensions.hotEventTargetPlatform),
getNameForTargetPlatform(TargetPlatform.android_arm))
);
}, overrides: <Type, Generator>{
Usage: () => MockUsage(),
}));
test('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async { test('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async {
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async { when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
return 'Example'; return 'Example';
......
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