From a0b2878e760fb6bcfb2f50bd0dbea756573afe08 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 27 Jun 2019 11:17:58 -0700 Subject: [PATCH] Make tool coverage collection resilient to sentinel coverage data (#35186) --- .../lib/src/test/coverage_collector.dart | 17 +++++-- .../test/coverage_collector_test.dart | 51 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 packages/flutter_tools/test/coverage_collector_test.dart diff --git a/packages/flutter_tools/lib/src/test/coverage_collector.dart b/packages/flutter_tools/lib/src/test/coverage_collector.dart index c166d07e62c..6aa7c847631 100644 --- a/packages/flutter_tools/lib/src/test/coverage_collector.dart +++ b/packages/flutter_tools/lib/src/test/coverage_collector.dart @@ -184,13 +184,17 @@ class CoverageCollector extends TestWatcher { } } -Future> collect(Uri serviceUri, bool Function(String) libraryPredicate) async { - final VMService vmService = await VMService.connect(serviceUri, compression: CompressionOptions.compressionOff); +Future _defaultConnect(Uri serviceUri) { + return VMService.connect(serviceUri, compression: CompressionOptions.compressionOff); +} + +Future> collect(Uri serviceUri, bool Function(String) libraryPredicate, + [Future Function(Uri) connector = _defaultConnect]) async { + final VMService vmService = await connector(serviceUri); await vmService.getVM(); return _getAllCoverage(vmService, libraryPredicate); } - Future> _getAllCoverage(VMService service, bool Function(String) libraryPredicate) async { await service.getVM(); final List> coverage = >[]; @@ -203,6 +207,13 @@ Future> _getAllCoverage(VMService service, bool Function(St final Map> sourceReports = >{}; // For each ScriptRef loaded into the VM, load the corresponding Script and // SourceReport object. + + // We may receive such objects as + // {type: Sentinel, kind: Collected, valueAsString: } + // that need to be skipped. + if (scriptList['scripts'] == null) { + continue; + } for (Map script in scriptList['scripts']) { if (!libraryPredicate(script['uri'])) { continue; diff --git a/packages/flutter_tools/test/coverage_collector_test.dart b/packages/flutter_tools/test/coverage_collector_test.dart new file mode 100644 index 00000000000..12705c5165f --- /dev/null +++ b/packages/flutter_tools/test/coverage_collector_test.dart @@ -0,0 +1,51 @@ +// Copyright 2019 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/io.dart'; +import 'package:flutter_tools/src/test/coverage_collector.dart'; +import 'package:flutter_tools/src/vmservice.dart'; +import 'package:mockito/mockito.dart'; + +import 'src/common.dart'; + +void main() { + MockVMService mockVMService; + + setUp(() { + mockVMService = MockVMService(); + }); + + test('Coverage collector Can handle coverage sentinenl data', () async { + when(mockVMService.vm.isolates.first.invokeRpcRaw('getScripts', params: anyNamed('params'))) + .thenAnswer((Invocation invocation) async { + return {'type': 'Sentinel', 'kind': 'Collected', 'valueAsString': ''}; + }); + final Map result = await collect(null, (String predicate) => true, (Uri uri) async { + return mockVMService; + }); + + expect(result, {'type': 'CodeCoverage', 'coverage': []}); + }); +} + +class MockVMService extends Mock implements VMService { + @override + final MockVM vm = MockVM(); +} + +class MockVM extends Mock implements VM { + @override + final List isolates = [ MockIsolate() ]; +} + +class MockIsolate extends Mock implements Isolate {} + +class MockProcess extends Mock implements Process { + final Completercompleter = Completer(); + + @override + Future get exitCode => completer.future; +} \ No newline at end of file