Use libraryFilters flag to speed up coverage collection (#104122)
* Use libraryFilters flag to speed up coverage collection * Allow libraryNames to be null * Unconditionally enable the reportLines flag * Fix analysis errors
This commit is contained in:
parent
d9f3acb13a
commit
d2ba83d421
@ -112,16 +112,13 @@ Future<void> run(List<String> args) async {
|
||||
Directory testDirectory;
|
||||
CoverageCollector collector;
|
||||
if (argResults['coverage'] as bool) {
|
||||
// If we have a specified coverage directory then accept all libraries by
|
||||
// setting libraryNames to null.
|
||||
final Set<String> libraryNames = coverageDirectory != null ? null :
|
||||
<String>{FlutterProject.current().manifest.appName};
|
||||
collector = CoverageCollector(
|
||||
packagesPath: globals.fs.path.normalize(globals.fs.path.absolute(argResults[_kOptionPackages] as String)),
|
||||
libraryPredicate: (String libraryName) {
|
||||
// If we have a specified coverage directory then accept all libraries.
|
||||
if (coverageDirectory != null) {
|
||||
return true;
|
||||
}
|
||||
final String projectName = FlutterProject.current().manifest.appName;
|
||||
return libraryName.contains(projectName);
|
||||
});
|
||||
libraryNames: libraryNames);
|
||||
if (!argResults.options.contains(_kOptionTestDirectory)) {
|
||||
throwToolExit('Use of --coverage requires setting --test-directory');
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
||||
final String projectName = flutterProject.manifest.appName;
|
||||
collector = CoverageCollector(
|
||||
verbose: !machine,
|
||||
libraryPredicate: (String libraryName) => libraryName.contains(projectName),
|
||||
libraryNames: <String>{projectName},
|
||||
packagesPath: buildInfo.packagesPath
|
||||
);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import 'watcher.dart';
|
||||
|
||||
/// A class that collects code coverage data during test runs.
|
||||
class CoverageCollector extends TestWatcher {
|
||||
CoverageCollector({this.libraryPredicate, this.verbose = true, @required this.packagesPath});
|
||||
CoverageCollector({this.libraryNames, this.verbose = true, @required this.packagesPath});
|
||||
|
||||
/// True when log messages should be emitted.
|
||||
final bool verbose;
|
||||
@ -31,9 +31,9 @@ class CoverageCollector extends TestWatcher {
|
||||
/// Map of file path to coverage hit map for that file.
|
||||
Map<String, coverage.HitMap> _globalHitmap;
|
||||
|
||||
/// Predicate function that returns true if the specified library URI should
|
||||
/// be included in the computed coverage.
|
||||
bool Function(String) libraryPredicate;
|
||||
/// The names of the libraries to gather coverage for. If null, all libraries
|
||||
/// will be accepted.
|
||||
Set<String> libraryNames;
|
||||
|
||||
@override
|
||||
Future<void> handleFinishedTest(TestDevice testDevice) async {
|
||||
@ -83,7 +83,7 @@ class CoverageCollector extends TestWatcher {
|
||||
Future<void> collectCoverageIsolate(Uri observatoryUri) async {
|
||||
assert(observatoryUri != null);
|
||||
_logMessage('collecting coverage data from $observatoryUri...');
|
||||
final Map<String, dynamic> data = await collect(observatoryUri, libraryPredicate);
|
||||
final Map<String, dynamic> data = await collect(observatoryUri, libraryNames);
|
||||
if (data == null) {
|
||||
throw Exception('Failed to collect coverage.');
|
||||
}
|
||||
@ -121,7 +121,7 @@ class CoverageCollector extends TestWatcher {
|
||||
final Future<void> collectionComplete = testDevice.observatoryUri
|
||||
.then((Uri observatoryUri) {
|
||||
_logMessage('collecting coverage data from $testDevice at $observatoryUri...');
|
||||
return collect(observatoryUri, libraryPredicate)
|
||||
return collect(observatoryUri, libraryNames)
|
||||
.then<void>((Map<String, dynamic> result) {
|
||||
if (result == null) {
|
||||
throw Exception('Failed to collect coverage.');
|
||||
@ -237,77 +237,94 @@ Future<FlutterVmService> _defaultConnect(Uri serviceUri) {
|
||||
serviceUri, compression: CompressionOptions.compressionOff, logger: globals.logger,);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> collect(Uri serviceUri, bool Function(String) libraryPredicate, {
|
||||
Future<Map<String, dynamic>> collect(Uri serviceUri, Set<String> libraryNames, {
|
||||
bool waitPaused = false,
|
||||
String debugName,
|
||||
Future<FlutterVmService> Function(Uri) connector = _defaultConnect,
|
||||
@visibleForTesting bool forceSequential = false,
|
||||
}) async {
|
||||
final FlutterVmService vmService = await connector(serviceUri);
|
||||
final Map<String, dynamic> result = await _getAllCoverage(vmService.service, libraryPredicate, forceSequential);
|
||||
final Map<String, dynamic> result = await _getAllCoverage(vmService.service, libraryNames, forceSequential);
|
||||
await vmService.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _getAllCoverage(
|
||||
vm_service.VmService service,
|
||||
bool Function(String) libraryPredicate,
|
||||
Set<String> libraryNames,
|
||||
bool forceSequential,
|
||||
) async {
|
||||
final vm_service.Version version = await service.getVersion();
|
||||
final bool reportLines = (version.major == 3 && version.minor >= 51) || version.major > 3;
|
||||
final bool libraryFilters = (version.major == 3 && version.minor >= 57) || version.major > 3;
|
||||
final vm_service.VM vm = await service.getVM();
|
||||
final List<Map<String, dynamic>> coverage = <Map<String, dynamic>>[];
|
||||
bool libraryPredicate(String libraryName) {
|
||||
if (libraryNames == null) {
|
||||
return true;
|
||||
}
|
||||
final Uri uri = Uri.parse(libraryName);
|
||||
if (uri.scheme != 'package') {
|
||||
return false;
|
||||
}
|
||||
final String scope = uri.path.split('/').first;
|
||||
return libraryNames.contains(scope);
|
||||
}
|
||||
for (final vm_service.IsolateRef isolateRef in vm.isolates) {
|
||||
if (isolateRef.isSystemIsolate) {
|
||||
continue;
|
||||
}
|
||||
vm_service.ScriptList scriptList;
|
||||
try {
|
||||
scriptList = await service.getScripts(isolateRef.id);
|
||||
} on vm_service.SentinelException {
|
||||
continue;
|
||||
}
|
||||
|
||||
final List<Future<void>> futures = <Future<void>>[];
|
||||
final Map<String, vm_service.Script> scripts = <String, vm_service.Script>{};
|
||||
final Map<String, vm_service.SourceReport> sourceReports = <String, vm_service.SourceReport>{};
|
||||
// For each ScriptRef loaded into the VM, load the corresponding Script and
|
||||
// SourceReport object.
|
||||
|
||||
for (final vm_service.ScriptRef script in scriptList.scripts) {
|
||||
final String libraryUri = script.uri;
|
||||
if (!libraryPredicate(libraryUri)) {
|
||||
if (libraryFilters) {
|
||||
final vm_service.SourceReport sourceReport = await service.getSourceReport(
|
||||
isolateRef.id,
|
||||
<String>['Coverage'],
|
||||
forceCompile: true,
|
||||
reportLines: true,
|
||||
libraryFilters: libraryNames == null ? null : List<String>.from(
|
||||
libraryNames.map((String name) => 'package:$name/')),
|
||||
);
|
||||
_buildCoverageMap(
|
||||
<String, vm_service.Script>{},
|
||||
<vm_service.SourceReport>[sourceReport],
|
||||
coverage,
|
||||
);
|
||||
} else {
|
||||
vm_service.ScriptList scriptList;
|
||||
try {
|
||||
scriptList = await service.getScripts(isolateRef.id);
|
||||
} on vm_service.SentinelException {
|
||||
continue;
|
||||
}
|
||||
final String scriptId = script.id;
|
||||
final Future<void> getSourceReport = service.getSourceReport(
|
||||
isolateRef.id,
|
||||
<String>['Coverage'],
|
||||
scriptId: scriptId,
|
||||
forceCompile: true,
|
||||
reportLines: reportLines ? true : null,
|
||||
)
|
||||
.then((vm_service.SourceReport report) {
|
||||
sourceReports[scriptId] = report;
|
||||
});
|
||||
if (forceSequential) {
|
||||
await null;
|
||||
}
|
||||
futures.add(getSourceReport);
|
||||
if (reportLines) {
|
||||
continue;
|
||||
}
|
||||
final Future<void> getObject = service
|
||||
.getObject(isolateRef.id, scriptId)
|
||||
.then((vm_service.Obj response) {
|
||||
final vm_service.Script script = response as vm_service.Script;
|
||||
scripts[scriptId] = script;
|
||||
|
||||
final List<Future<void>> futures = <Future<void>>[];
|
||||
final Map<String, vm_service.Script> scripts = <String, vm_service.Script>{};
|
||||
final List<vm_service.SourceReport> sourceReports = <vm_service.SourceReport>[];
|
||||
|
||||
// For each ScriptRef loaded into the VM, load the corresponding Script
|
||||
// and SourceReport object.
|
||||
for (final vm_service.ScriptRef script in scriptList.scripts) {
|
||||
final String libraryUri = script.uri;
|
||||
if (!libraryPredicate(libraryUri)) {
|
||||
continue;
|
||||
}
|
||||
final String scriptId = script.id;
|
||||
final Future<void> getSourceReport = service.getSourceReport(
|
||||
isolateRef.id,
|
||||
<String>['Coverage'],
|
||||
scriptId: scriptId,
|
||||
forceCompile: true,
|
||||
reportLines: true,
|
||||
)
|
||||
.then((vm_service.SourceReport report) {
|
||||
sourceReports.add(report);
|
||||
});
|
||||
futures.add(getObject);
|
||||
if (forceSequential) {
|
||||
await null;
|
||||
}
|
||||
futures.add(getSourceReport);
|
||||
}
|
||||
await Future.wait(futures);
|
||||
_buildCoverageMap(scripts, sourceReports, coverage);
|
||||
}
|
||||
await Future.wait(futures);
|
||||
_buildCoverageMap(scripts, sourceReports, coverage, reportLines);
|
||||
}
|
||||
return <String, dynamic>{'type': 'CodeCoverage', 'coverage': coverage};
|
||||
}
|
||||
@ -315,13 +332,11 @@ Future<Map<String, dynamic>> _getAllCoverage(
|
||||
// Build a hitmap of Uri -> Line -> Hit Count for each script object.
|
||||
void _buildCoverageMap(
|
||||
Map<String, vm_service.Script> scripts,
|
||||
Map<String, vm_service.SourceReport> sourceReports,
|
||||
List<vm_service.SourceReport> sourceReports,
|
||||
List<Map<String, dynamic>> coverage,
|
||||
bool reportLines,
|
||||
) {
|
||||
final Map<String, Map<int, int>> hitMaps = <String, Map<int, int>>{};
|
||||
for (final String scriptId in sourceReports.keys) {
|
||||
final vm_service.SourceReport sourceReport = sourceReports[scriptId];
|
||||
for (final vm_service.SourceReport sourceReport in sourceReports) {
|
||||
for (final vm_service.SourceReportRange range in sourceReport.ranges) {
|
||||
final vm_service.SourceReportCoverage coverage = range.coverage;
|
||||
// Coverage reports may sometimes be null for a Script.
|
||||
@ -335,24 +350,14 @@ void _buildCoverageMap(
|
||||
final Map<int, int> hitMap = hitMaps[uri];
|
||||
final List<int> hits = coverage.hits;
|
||||
final List<int> misses = coverage.misses;
|
||||
final List<dynamic> tokenPositions = scripts[scriptRef.id]?.tokenPosTable;
|
||||
// The token positions can be null if the script has no lines that may be
|
||||
// covered. It will also be null if reportLines is true.
|
||||
if (tokenPositions == null && !reportLines) {
|
||||
continue;
|
||||
}
|
||||
if (hits != null) {
|
||||
for (final int hit in hits) {
|
||||
final int line =
|
||||
reportLines ? hit : _lineAndColumn(hit, tokenPositions)[0];
|
||||
for (final int line in hits) {
|
||||
final int current = hitMap[line] ?? 0;
|
||||
hitMap[line] = current + 1;
|
||||
}
|
||||
}
|
||||
if (misses != null) {
|
||||
for (final int miss in misses) {
|
||||
final int line =
|
||||
reportLines ? miss : _lineAndColumn(miss, tokenPositions)[0];
|
||||
for (final int line in misses) {
|
||||
hitMap[line] ??= 0;
|
||||
}
|
||||
}
|
||||
@ -363,29 +368,6 @@ void _buildCoverageMap(
|
||||
});
|
||||
}
|
||||
|
||||
// Binary search the token position table for the line and column which
|
||||
// corresponds to each token position.
|
||||
// The format of this table is described in https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#script
|
||||
List<int> _lineAndColumn(int position, List<dynamic> tokenPositions) {
|
||||
int min = 0;
|
||||
int max = tokenPositions.length;
|
||||
while (min < max) {
|
||||
final int mid = min + ((max - min) >> 1);
|
||||
final List<int> row = (tokenPositions[mid] as List<dynamic>).cast<int>();
|
||||
if (row[1] > position) {
|
||||
max = mid;
|
||||
} else {
|
||||
for (int i = 1; i < row.length; i += 2) {
|
||||
if (row[i] == position) {
|
||||
return <int>[row.first, row[i + 1]];
|
||||
}
|
||||
}
|
||||
min = mid + 1;
|
||||
}
|
||||
}
|
||||
throw StateError('Unreachable');
|
||||
}
|
||||
|
||||
// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs.
|
||||
Map<String, dynamic> _toScriptCoverageJson(String scriptUri, Map<int, int> hitMap) {
|
||||
final Map<String, dynamic> json = <String, dynamic>{};
|
||||
|
@ -16,7 +16,7 @@ void main() {
|
||||
requests: <VmServiceExpectation>[
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVersion',
|
||||
jsonResponse: Version(major: 3, minor: 50).toJson(),
|
||||
jsonResponse: Version(major: 3, minor: 51).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVM',
|
||||
@ -42,7 +42,7 @@ void main() {
|
||||
|
||||
final Map<String, Object> result = await collect(
|
||||
null,
|
||||
(String predicate) => true,
|
||||
<String>{'foo'},
|
||||
connector: (Uri uri) async {
|
||||
return fakeVmServiceHost.vmService;
|
||||
},
|
||||
@ -53,104 +53,6 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('Coverage collector processes coverage and script data', () async {
|
||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: <VmServiceExpectation>[
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVersion',
|
||||
jsonResponse: Version(major: 3, minor: 50).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVM',
|
||||
jsonResponse: (VM.parse(<String, Object>{})
|
||||
..isolates = <IsolateRef>[
|
||||
IsolateRef.parse(<String, Object>{
|
||||
'id': '1',
|
||||
}),
|
||||
]
|
||||
).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getScripts',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
},
|
||||
jsonResponse: ScriptList(scripts: <ScriptRef>[
|
||||
ScriptRef(uri: 'foo.dart', id: '1'),
|
||||
]).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getSourceReport',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
'reports': <Object>['Coverage'],
|
||||
'scriptId': '1',
|
||||
'forceCompile': true,
|
||||
},
|
||||
jsonResponse: SourceReport(
|
||||
ranges: <SourceReportRange>[
|
||||
SourceReportRange(
|
||||
scriptIndex: 0,
|
||||
startPos: 0,
|
||||
endPos: 0,
|
||||
compiled: true,
|
||||
coverage: SourceReportCoverage(
|
||||
hits: <int>[],
|
||||
misses: <int>[],
|
||||
),
|
||||
),
|
||||
],
|
||||
scripts: <ScriptRef>[
|
||||
ScriptRef(
|
||||
uri: 'foo.dart',
|
||||
id: '1',
|
||||
),
|
||||
],
|
||||
).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getObject',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
'objectId': '1',
|
||||
},
|
||||
jsonResponse: Script(
|
||||
uri: 'foo.dart',
|
||||
id: '1',
|
||||
library: LibraryRef(name: '', id: '1111', uri: 'foo.dart'),
|
||||
tokenPosTable: <List<int>>[],
|
||||
).toJson(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final Map<String, Object> result = await collect(
|
||||
null,
|
||||
(String predicate) => true,
|
||||
connector: (Uri uri) async {
|
||||
return fakeVmServiceHost.vmService;
|
||||
},
|
||||
);
|
||||
|
||||
expect(result, <String, Object>{
|
||||
'type': 'CodeCoverage',
|
||||
'coverage': <Object>[
|
||||
<String, Object>{
|
||||
'source': 'foo.dart',
|
||||
'script': <String, Object>{
|
||||
'type': '@Script',
|
||||
'fixedId': true,
|
||||
'id': 'libraries/1/scripts/foo.dart',
|
||||
'uri': 'foo.dart',
|
||||
'_kind': 'library',
|
||||
},
|
||||
'hits': <Object>[],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Coverage collector skips loading Script objects when reportLines is available', () async {
|
||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: <VmServiceExpectation>[
|
||||
FakeVmServiceRequest(
|
||||
@ -173,7 +75,8 @@ void main() {
|
||||
'isolateId': '1',
|
||||
},
|
||||
jsonResponse: ScriptList(scripts: <ScriptRef>[
|
||||
ScriptRef(uri: 'foo.dart', id: '1'),
|
||||
ScriptRef(uri: 'package:foo/foo.dart', id: '1'),
|
||||
ScriptRef(uri: 'package:bar/bar.dart', id: '2'),
|
||||
]).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
@ -200,7 +103,7 @@ void main() {
|
||||
],
|
||||
scripts: <ScriptRef>[
|
||||
ScriptRef(
|
||||
uri: 'foo.dart',
|
||||
uri: 'package:foo/foo.dart',
|
||||
id: '1',
|
||||
),
|
||||
],
|
||||
@ -211,7 +114,7 @@ void main() {
|
||||
|
||||
final Map<String, Object> result = await collect(
|
||||
null,
|
||||
(String predicate) => true,
|
||||
<String>{'foo'},
|
||||
connector: (Uri uri) async {
|
||||
return fakeVmServiceHost.vmService;
|
||||
},
|
||||
@ -221,12 +124,293 @@ void main() {
|
||||
'type': 'CodeCoverage',
|
||||
'coverage': <Object>[
|
||||
<String, Object>{
|
||||
'source': 'foo.dart',
|
||||
'source': 'package:foo/foo.dart',
|
||||
'script': <String, Object>{
|
||||
'type': '@Script',
|
||||
'fixedId': true,
|
||||
'id': 'libraries/1/scripts/foo.dart',
|
||||
'uri': 'foo.dart',
|
||||
'id': 'libraries/1/scripts/package%3Afoo%2Ffoo.dart',
|
||||
'uri': 'package:foo/foo.dart',
|
||||
'_kind': 'library',
|
||||
},
|
||||
'hits': <Object>[1, 1, 3, 1, 2, 0],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Coverage collector with null libraryNames accepts all libraries', () async {
|
||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: <VmServiceExpectation>[
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVersion',
|
||||
jsonResponse: Version(major: 3, minor: 51).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVM',
|
||||
jsonResponse: (VM.parse(<String, Object>{})
|
||||
..isolates = <IsolateRef>[
|
||||
IsolateRef.parse(<String, Object>{
|
||||
'id': '1',
|
||||
}),
|
||||
]
|
||||
).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getScripts',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
},
|
||||
jsonResponse: ScriptList(scripts: <ScriptRef>[
|
||||
ScriptRef(uri: 'package:foo/foo.dart', id: '1'),
|
||||
ScriptRef(uri: 'package:bar/bar.dart', id: '2'),
|
||||
]).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getSourceReport',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
'reports': <Object>['Coverage'],
|
||||
'scriptId': '1',
|
||||
'forceCompile': true,
|
||||
'reportLines': true,
|
||||
},
|
||||
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(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getSourceReport',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
'reports': <Object>['Coverage'],
|
||||
'scriptId': '2',
|
||||
'forceCompile': true,
|
||||
'reportLines': true,
|
||||
},
|
||||
jsonResponse: SourceReport(
|
||||
ranges: <SourceReportRange>[
|
||||
SourceReportRange(
|
||||
scriptIndex: 0,
|
||||
startPos: 0,
|
||||
endPos: 0,
|
||||
compiled: true,
|
||||
coverage: SourceReportCoverage(
|
||||
hits: <int>[47, 21],
|
||||
misses: <int>[32, 86],
|
||||
),
|
||||
),
|
||||
],
|
||||
scripts: <ScriptRef>[
|
||||
ScriptRef(
|
||||
uri: 'package:bar/bar.dart',
|
||||
id: '2',
|
||||
),
|
||||
],
|
||||
).toJson(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final Map<String, Object> result = await collect(
|
||||
null,
|
||||
null,
|
||||
connector: (Uri uri) async {
|
||||
return fakeVmServiceHost.vmService;
|
||||
},
|
||||
);
|
||||
|
||||
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],
|
||||
},
|
||||
<String, Object>{
|
||||
'source': 'package:bar/bar.dart',
|
||||
'script': <String, Object>{
|
||||
'type': '@Script',
|
||||
'fixedId': true,
|
||||
'id': 'libraries/1/scripts/package%3Abar%2Fbar.dart',
|
||||
'uri': 'package:bar/bar.dart',
|
||||
'_kind': 'library',
|
||||
},
|
||||
'hits': <Object>[47, 1, 21, 1, 32, 0, 86, 0],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Coverage collector with libraryFilters', () async {
|
||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: <VmServiceExpectation>[
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVersion',
|
||||
jsonResponse: Version(major: 3, minor: 57).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVM',
|
||||
jsonResponse: (VM.parse(<String, Object>{})
|
||||
..isolates = <IsolateRef>[
|
||||
IsolateRef.parse(<String, Object>{
|
||||
'id': '1',
|
||||
}),
|
||||
]
|
||||
).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getSourceReport',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
'reports': <Object>['Coverage'],
|
||||
'forceCompile': true,
|
||||
'reportLines': true,
|
||||
'libraryFilters': <Object>['package:foo/'],
|
||||
},
|
||||
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, Object> result = await collect(
|
||||
null,
|
||||
<String>{'foo'},
|
||||
connector: (Uri uri) async {
|
||||
return fakeVmServiceHost.vmService;
|
||||
},
|
||||
);
|
||||
|
||||
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],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(fakeVmServiceHost.hasRemainingExpectations, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Coverage collector with libraryFilters and null libraryNames', () async {
|
||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: <VmServiceExpectation>[
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVersion',
|
||||
jsonResponse: Version(major: 3, minor: 57).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getVM',
|
||||
jsonResponse: (VM.parse(<String, Object>{})
|
||||
..isolates = <IsolateRef>[
|
||||
IsolateRef.parse(<String, Object>{
|
||||
'id': '1',
|
||||
}),
|
||||
]
|
||||
).toJson(),
|
||||
),
|
||||
FakeVmServiceRequest(
|
||||
method: 'getSourceReport',
|
||||
args: <String, Object>{
|
||||
'isolateId': '1',
|
||||
'reports': <Object>['Coverage'],
|
||||
'forceCompile': true,
|
||||
'reportLines': true,
|
||||
},
|
||||
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, Object> result = await collect(
|
||||
null,
|
||||
null,
|
||||
connector: (Uri uri) async {
|
||||
return fakeVmServiceHost.vmService;
|
||||
},
|
||||
);
|
||||
|
||||
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],
|
||||
|
Loading…
x
Reference in New Issue
Block a user