Unverified Commit e12d1a79 authored by Liam Appelbe's avatar Liam Appelbe Committed by GitHub

Reland `coverableLineCache` optimisation (#136851) (#137385)

Relands #136851, which was rolled back in #137121

package:coverage has been rolled, so the breakages should be fixed.
Also, in this reland I've changed the `coverableLineCache` parameter to
be optional, which is safer.
parent f05bb9a1
......@@ -37,6 +37,7 @@ class CoverageCollector extends TestWatcher {
final coverage.Resolver? resolver;
final Map<String, List<List<int>>?> _ignoredLinesInFilesCache = <String, List<List<int>>?>{};
final Map<String, Set<int>> _coverableLineCache = <String, Set<int>>{};
final TestTimeRecorder? testTimeRecorder;
......@@ -103,7 +104,11 @@ class CoverageCollector extends TestWatcher {
Future<void> collectCoverageIsolate(Uri vmServiceUri) async {
_logMessage('collecting coverage data from $vmServiceUri...');
final Map<String, dynamic> data = await collect(
vmServiceUri, libraryNames, branchCoverage: branchCoverage);
vmServiceUri,
libraryNames,
branchCoverage: branchCoverage,
coverableLineCache: _coverableLineCache,
);
_logMessage('($vmServiceUri): collected coverage data; merging...');
_addHitmap(await coverage.HitMap.parseJson(
......@@ -145,9 +150,12 @@ class CoverageCollector extends TestWatcher {
.then((Uri? vmServiceUri) {
_logMessage('collecting coverage data from $testDevice at $vmServiceUri...');
return collect(
vmServiceUri!, libraryNames, serviceOverride: serviceOverride,
branchCoverage: branchCoverage)
.then<void>((Map<String, dynamic> result) {
vmServiceUri!,
libraryNames,
serviceOverride: serviceOverride,
branchCoverage: branchCoverage,
coverableLineCache: _coverableLineCache,
).then<void>((Map<String, dynamic> result) {
_logMessage('Collected coverage data.');
data = result;
});
......@@ -267,9 +275,12 @@ Future<Map<String, dynamic>> collect(Uri serviceUri, Set<String>? libraryNames,
@visibleForTesting bool forceSequential = false,
@visibleForTesting FlutterVmService? serviceOverride,
bool branchCoverage = false,
Map<String, Set<int>>? coverableLineCache,
}) {
return coverage.collect(
serviceUri, false, false, false, libraryNames,
serviceOverrideForTesting: serviceOverride?.service,
branchCoverage: branchCoverage);
branchCoverage: branchCoverage,
coverableLineCache: coverableLineCache,
);
}
......@@ -53,6 +53,7 @@ void main() {
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{'type': 'CodeCoverage', 'coverage': <Object>[]});
......@@ -123,6 +124,7 @@ void main() {
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{
......@@ -151,6 +153,7 @@ void main() {
Uri(),
null,
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{
......@@ -237,6 +240,7 @@ void main() {
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{
......@@ -311,6 +315,7 @@ void main() {
Uri(),
null,
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{
......@@ -401,6 +406,7 @@ void main() {
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
branchCoverage: true,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{
......@@ -601,6 +607,179 @@ void main() {
tempDir?.deleteSync(recursive: true);
}
});
testWithoutContext('Coverage collector fills coverableLineCache', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[
FakeVmServiceRequest(
method: 'getVM',
jsonResponse: (VM.parse(<String, Object>{})!
..isolates = <IsolateRef>[
IsolateRef.parse(<String, Object>{
'id': '1',
})!,
]
).toJson(),
),
FakeVmServiceRequest(
method: 'getVersion',
jsonResponse: Version(major: 4, minor: 13).toJson(),
),
FakeVmServiceRequest(
method: 'getSourceReport',
args: <String, Object>{
'isolateId': '1',
'reports': <Object>['Coverage'],
'forceCompile': true,
'reportLines': true,
'libraryFilters': <String>['package:foo/'],
'librariesAlreadyCompiled': <String>[],
},
jsonResponse: SourceReport(
ranges: <SourceReportRange>[
SourceReportRange(
scriptIndex: 0,
startPos: 0,
endPos: 0,
compiled: true,
coverage: SourceReportCoverage(
hits: <int>[1, 3],
misses: <int>[2],
),
),
],
scripts: <ScriptRef>[
ScriptRef(
uri: 'package:foo/foo.dart',
id: '1',
),
],
).toJson(),
),
],
);
final Map<String, Set<int>> coverableLineCache = <String, Set<int>>{};
final Map<String, Object?> result = await collect(
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: coverableLineCache,
);
expect(result, <String, Object>{
'type': 'CodeCoverage',
'coverage': <Object>[
<String, Object>{
'source': 'package:foo/foo.dart',
'script': <String, Object>{
'type': '@Script',
'fixedId': true,
'id': 'libraries/1/scripts/package%3Afoo%2Ffoo.dart',
'uri': 'package:foo/foo.dart',
'_kind': 'library',
},
'hits': <Object>[1, 1, 3, 1, 2, 0],
},
],
});
// coverableLineCache should contain every line mentioned in the report.
expect(coverableLineCache, <String, Set<int>>{
'package:foo/foo.dart': <int>{1, 2, 3},
});
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
testWithoutContext('Coverage collector avoids recompiling libraries in coverableLineCache', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[
FakeVmServiceRequest(
method: 'getVM',
jsonResponse: (VM.parse(<String, Object>{})!
..isolates = <IsolateRef>[
IsolateRef.parse(<String, Object>{
'id': '1',
})!,
]
).toJson(),
),
FakeVmServiceRequest(
method: 'getVersion',
jsonResponse: Version(major: 4, minor: 13).toJson(),
),
// This collection sets librariesAlreadyCompiled. The response doesn't
// include any misses.
FakeVmServiceRequest(
method: 'getSourceReport',
args: <String, Object>{
'isolateId': '1',
'reports': <Object>['Coverage'],
'forceCompile': true,
'reportLines': true,
'libraryFilters': <String>['package:foo/'],
'librariesAlreadyCompiled': <String>['package:foo/foo.dart'],
},
jsonResponse: SourceReport(
ranges: <SourceReportRange>[
SourceReportRange(
scriptIndex: 0,
startPos: 0,
endPos: 0,
compiled: true,
coverage: SourceReportCoverage(
hits: <int>[1, 3],
misses: <int>[],
),
),
],
scripts: <ScriptRef>[
ScriptRef(
uri: 'package:foo/foo.dart',
id: '1',
),
],
).toJson(),
),
],
);
final Map<String, Set<int>> coverableLineCache = <String, Set<int>>{
'package:foo/foo.dart': <int>{1, 2, 3},
};
final Map<String, Object?> result2 = await collect(
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: coverableLineCache,
);
// Expect that line 2 is marked as missed, even though it wasn't mentioned
// in the getSourceReport response.
expect(result2, <String, Object>{
'type': 'CodeCoverage',
'coverage': <Object>[
<String, Object>{
'source': 'package:foo/foo.dart',
'script': <String, Object>{
'type': '@Script',
'fixedId': true,
'id': 'libraries/1/scripts/package%3Afoo%2Ffoo.dart',
'uri': 'package:foo/foo.dart',
'_kind': 'library',
},
'hits': <Object>[1, 1, 2, 0, 3, 1],
},
],
});
expect(coverableLineCache, <String, Set<int>>{
'package:foo/foo.dart': <int>{1, 2, 3},
});
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
}
File writeFooBarPackagesJson(Directory tempDir) {
......
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