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;
|
Directory testDirectory;
|
||||||
CoverageCollector collector;
|
CoverageCollector collector;
|
||||||
if (argResults['coverage'] as bool) {
|
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(
|
collector = CoverageCollector(
|
||||||
packagesPath: globals.fs.path.normalize(globals.fs.path.absolute(argResults[_kOptionPackages] as String)),
|
packagesPath: globals.fs.path.normalize(globals.fs.path.absolute(argResults[_kOptionPackages] as String)),
|
||||||
libraryPredicate: (String libraryName) {
|
libraryNames: libraryNames);
|
||||||
// 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);
|
|
||||||
});
|
|
||||||
if (!argResults.options.contains(_kOptionTestDirectory)) {
|
if (!argResults.options.contains(_kOptionTestDirectory)) {
|
||||||
throwToolExit('Use of --coverage requires setting --test-directory');
|
throwToolExit('Use of --coverage requires setting --test-directory');
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
|||||||
final String projectName = flutterProject.manifest.appName;
|
final String projectName = flutterProject.manifest.appName;
|
||||||
collector = CoverageCollector(
|
collector = CoverageCollector(
|
||||||
verbose: !machine,
|
verbose: !machine,
|
||||||
libraryPredicate: (String libraryName) => libraryName.contains(projectName),
|
libraryNames: <String>{projectName},
|
||||||
packagesPath: buildInfo.packagesPath
|
packagesPath: buildInfo.packagesPath
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import 'watcher.dart';
|
|||||||
|
|
||||||
/// A class that collects code coverage data during test runs.
|
/// A class that collects code coverage data during test runs.
|
||||||
class CoverageCollector extends TestWatcher {
|
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.
|
/// True when log messages should be emitted.
|
||||||
final bool verbose;
|
final bool verbose;
|
||||||
@ -31,9 +31,9 @@ class CoverageCollector extends TestWatcher {
|
|||||||
/// Map of file path to coverage hit map for that file.
|
/// Map of file path to coverage hit map for that file.
|
||||||
Map<String, coverage.HitMap> _globalHitmap;
|
Map<String, coverage.HitMap> _globalHitmap;
|
||||||
|
|
||||||
/// Predicate function that returns true if the specified library URI should
|
/// The names of the libraries to gather coverage for. If null, all libraries
|
||||||
/// be included in the computed coverage.
|
/// will be accepted.
|
||||||
bool Function(String) libraryPredicate;
|
Set<String> libraryNames;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> handleFinishedTest(TestDevice testDevice) async {
|
Future<void> handleFinishedTest(TestDevice testDevice) async {
|
||||||
@ -83,7 +83,7 @@ class CoverageCollector extends TestWatcher {
|
|||||||
Future<void> collectCoverageIsolate(Uri observatoryUri) async {
|
Future<void> collectCoverageIsolate(Uri observatoryUri) async {
|
||||||
assert(observatoryUri != null);
|
assert(observatoryUri != null);
|
||||||
_logMessage('collecting coverage data from $observatoryUri...');
|
_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) {
|
if (data == null) {
|
||||||
throw Exception('Failed to collect coverage.');
|
throw Exception('Failed to collect coverage.');
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ class CoverageCollector extends TestWatcher {
|
|||||||
final Future<void> collectionComplete = testDevice.observatoryUri
|
final Future<void> collectionComplete = testDevice.observatoryUri
|
||||||
.then((Uri observatoryUri) {
|
.then((Uri observatoryUri) {
|
||||||
_logMessage('collecting coverage data from $testDevice at $observatoryUri...');
|
_logMessage('collecting coverage data from $testDevice at $observatoryUri...');
|
||||||
return collect(observatoryUri, libraryPredicate)
|
return collect(observatoryUri, libraryNames)
|
||||||
.then<void>((Map<String, dynamic> result) {
|
.then<void>((Map<String, dynamic> result) {
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
throw Exception('Failed to collect coverage.');
|
throw Exception('Failed to collect coverage.');
|
||||||
@ -237,77 +237,94 @@ Future<FlutterVmService> _defaultConnect(Uri serviceUri) {
|
|||||||
serviceUri, compression: CompressionOptions.compressionOff, logger: globals.logger,);
|
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,
|
bool waitPaused = false,
|
||||||
String debugName,
|
String debugName,
|
||||||
Future<FlutterVmService> Function(Uri) connector = _defaultConnect,
|
Future<FlutterVmService> Function(Uri) connector = _defaultConnect,
|
||||||
@visibleForTesting bool forceSequential = false,
|
@visibleForTesting bool forceSequential = false,
|
||||||
}) async {
|
}) async {
|
||||||
final FlutterVmService vmService = await connector(serviceUri);
|
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();
|
await vmService.dispose();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> _getAllCoverage(
|
Future<Map<String, dynamic>> _getAllCoverage(
|
||||||
vm_service.VmService service,
|
vm_service.VmService service,
|
||||||
bool Function(String) libraryPredicate,
|
Set<String> libraryNames,
|
||||||
bool forceSequential,
|
bool forceSequential,
|
||||||
) async {
|
) async {
|
||||||
final vm_service.Version version = await service.getVersion();
|
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 vm_service.VM vm = await service.getVM();
|
||||||
final List<Map<String, dynamic>> coverage = <Map<String, dynamic>>[];
|
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) {
|
for (final vm_service.IsolateRef isolateRef in vm.isolates) {
|
||||||
if (isolateRef.isSystemIsolate) {
|
if (isolateRef.isSystemIsolate) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vm_service.ScriptList scriptList;
|
if (libraryFilters) {
|
||||||
try {
|
final vm_service.SourceReport sourceReport = await service.getSourceReport(
|
||||||
scriptList = await service.getScripts(isolateRef.id);
|
isolateRef.id,
|
||||||
} on vm_service.SentinelException {
|
<String>['Coverage'],
|
||||||
continue;
|
forceCompile: true,
|
||||||
}
|
reportLines: true,
|
||||||
|
libraryFilters: libraryNames == null ? null : List<String>.from(
|
||||||
final List<Future<void>> futures = <Future<void>>[];
|
libraryNames.map((String name) => 'package:$name/')),
|
||||||
final Map<String, vm_service.Script> scripts = <String, vm_service.Script>{};
|
);
|
||||||
final Map<String, vm_service.SourceReport> sourceReports = <String, vm_service.SourceReport>{};
|
_buildCoverageMap(
|
||||||
// For each ScriptRef loaded into the VM, load the corresponding Script and
|
<String, vm_service.Script>{},
|
||||||
// SourceReport object.
|
<vm_service.SourceReport>[sourceReport],
|
||||||
|
coverage,
|
||||||
for (final vm_service.ScriptRef script in scriptList.scripts) {
|
);
|
||||||
final String libraryUri = script.uri;
|
} else {
|
||||||
if (!libraryPredicate(libraryUri)) {
|
vm_service.ScriptList scriptList;
|
||||||
|
try {
|
||||||
|
scriptList = await service.getScripts(isolateRef.id);
|
||||||
|
} on vm_service.SentinelException {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final String scriptId = script.id;
|
|
||||||
final Future<void> getSourceReport = service.getSourceReport(
|
final List<Future<void>> futures = <Future<void>>[];
|
||||||
isolateRef.id,
|
final Map<String, vm_service.Script> scripts = <String, vm_service.Script>{};
|
||||||
<String>['Coverage'],
|
final List<vm_service.SourceReport> sourceReports = <vm_service.SourceReport>[];
|
||||||
scriptId: scriptId,
|
|
||||||
forceCompile: true,
|
// For each ScriptRef loaded into the VM, load the corresponding Script
|
||||||
reportLines: reportLines ? true : null,
|
// and SourceReport object.
|
||||||
)
|
for (final vm_service.ScriptRef script in scriptList.scripts) {
|
||||||
.then((vm_service.SourceReport report) {
|
final String libraryUri = script.uri;
|
||||||
sourceReports[scriptId] = report;
|
if (!libraryPredicate(libraryUri)) {
|
||||||
});
|
continue;
|
||||||
if (forceSequential) {
|
}
|
||||||
await null;
|
final String scriptId = script.id;
|
||||||
}
|
final Future<void> getSourceReport = service.getSourceReport(
|
||||||
futures.add(getSourceReport);
|
isolateRef.id,
|
||||||
if (reportLines) {
|
<String>['Coverage'],
|
||||||
continue;
|
scriptId: scriptId,
|
||||||
}
|
forceCompile: true,
|
||||||
final Future<void> getObject = service
|
reportLines: true,
|
||||||
.getObject(isolateRef.id, scriptId)
|
)
|
||||||
.then((vm_service.Obj response) {
|
.then((vm_service.SourceReport report) {
|
||||||
final vm_service.Script script = response as vm_service.Script;
|
sourceReports.add(report);
|
||||||
scripts[scriptId] = script;
|
|
||||||
});
|
});
|
||||||
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};
|
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.
|
// Build a hitmap of Uri -> Line -> Hit Count for each script object.
|
||||||
void _buildCoverageMap(
|
void _buildCoverageMap(
|
||||||
Map<String, vm_service.Script> scripts,
|
Map<String, vm_service.Script> scripts,
|
||||||
Map<String, vm_service.SourceReport> sourceReports,
|
List<vm_service.SourceReport> sourceReports,
|
||||||
List<Map<String, dynamic>> coverage,
|
List<Map<String, dynamic>> coverage,
|
||||||
bool reportLines,
|
|
||||||
) {
|
) {
|
||||||
final Map<String, Map<int, int>> hitMaps = <String, Map<int, int>>{};
|
final Map<String, Map<int, int>> hitMaps = <String, Map<int, int>>{};
|
||||||
for (final String scriptId in sourceReports.keys) {
|
for (final vm_service.SourceReport sourceReport in sourceReports) {
|
||||||
final vm_service.SourceReport sourceReport = sourceReports[scriptId];
|
|
||||||
for (final vm_service.SourceReportRange range in sourceReport.ranges) {
|
for (final vm_service.SourceReportRange range in sourceReport.ranges) {
|
||||||
final vm_service.SourceReportCoverage coverage = range.coverage;
|
final vm_service.SourceReportCoverage coverage = range.coverage;
|
||||||
// Coverage reports may sometimes be null for a Script.
|
// Coverage reports may sometimes be null for a Script.
|
||||||
@ -335,24 +350,14 @@ void _buildCoverageMap(
|
|||||||
final Map<int, int> hitMap = hitMaps[uri];
|
final Map<int, int> hitMap = hitMaps[uri];
|
||||||
final List<int> hits = coverage.hits;
|
final List<int> hits = coverage.hits;
|
||||||
final List<int> misses = coverage.misses;
|
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) {
|
if (hits != null) {
|
||||||
for (final int hit in hits) {
|
for (final int line in hits) {
|
||||||
final int line =
|
|
||||||
reportLines ? hit : _lineAndColumn(hit, tokenPositions)[0];
|
|
||||||
final int current = hitMap[line] ?? 0;
|
final int current = hitMap[line] ?? 0;
|
||||||
hitMap[line] = current + 1;
|
hitMap[line] = current + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (misses != null) {
|
if (misses != null) {
|
||||||
for (final int miss in misses) {
|
for (final int line in misses) {
|
||||||
final int line =
|
|
||||||
reportLines ? miss : _lineAndColumn(miss, tokenPositions)[0];
|
|
||||||
hitMap[line] ??= 0;
|
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.
|
// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs.
|
||||||
Map<String, dynamic> _toScriptCoverageJson(String scriptUri, Map<int, int> hitMap) {
|
Map<String, dynamic> _toScriptCoverageJson(String scriptUri, Map<int, int> hitMap) {
|
||||||
final Map<String, dynamic> json = <String, dynamic>{};
|
final Map<String, dynamic> json = <String, dynamic>{};
|
||||||
|
@ -16,7 +16,7 @@ void main() {
|
|||||||
requests: <VmServiceExpectation>[
|
requests: <VmServiceExpectation>[
|
||||||
FakeVmServiceRequest(
|
FakeVmServiceRequest(
|
||||||
method: 'getVersion',
|
method: 'getVersion',
|
||||||
jsonResponse: Version(major: 3, minor: 50).toJson(),
|
jsonResponse: Version(major: 3, minor: 51).toJson(),
|
||||||
),
|
),
|
||||||
FakeVmServiceRequest(
|
FakeVmServiceRequest(
|
||||||
method: 'getVM',
|
method: 'getVM',
|
||||||
@ -42,7 +42,7 @@ void main() {
|
|||||||
|
|
||||||
final Map<String, Object> result = await collect(
|
final Map<String, Object> result = await collect(
|
||||||
null,
|
null,
|
||||||
(String predicate) => true,
|
<String>{'foo'},
|
||||||
connector: (Uri uri) async {
|
connector: (Uri uri) async {
|
||||||
return fakeVmServiceHost.vmService;
|
return fakeVmServiceHost.vmService;
|
||||||
},
|
},
|
||||||
@ -53,104 +53,6 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('Coverage collector processes coverage and script data', () async {
|
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(
|
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||||
requests: <VmServiceExpectation>[
|
requests: <VmServiceExpectation>[
|
||||||
FakeVmServiceRequest(
|
FakeVmServiceRequest(
|
||||||
@ -173,7 +75,8 @@ void main() {
|
|||||||
'isolateId': '1',
|
'isolateId': '1',
|
||||||
},
|
},
|
||||||
jsonResponse: ScriptList(scripts: <ScriptRef>[
|
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(),
|
]).toJson(),
|
||||||
),
|
),
|
||||||
FakeVmServiceRequest(
|
FakeVmServiceRequest(
|
||||||
@ -200,7 +103,7 @@ void main() {
|
|||||||
],
|
],
|
||||||
scripts: <ScriptRef>[
|
scripts: <ScriptRef>[
|
||||||
ScriptRef(
|
ScriptRef(
|
||||||
uri: 'foo.dart',
|
uri: 'package:foo/foo.dart',
|
||||||
id: '1',
|
id: '1',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -211,7 +114,7 @@ void main() {
|
|||||||
|
|
||||||
final Map<String, Object> result = await collect(
|
final Map<String, Object> result = await collect(
|
||||||
null,
|
null,
|
||||||
(String predicate) => true,
|
<String>{'foo'},
|
||||||
connector: (Uri uri) async {
|
connector: (Uri uri) async {
|
||||||
return fakeVmServiceHost.vmService;
|
return fakeVmServiceHost.vmService;
|
||||||
},
|
},
|
||||||
@ -221,12 +124,293 @@ void main() {
|
|||||||
'type': 'CodeCoverage',
|
'type': 'CodeCoverage',
|
||||||
'coverage': <Object>[
|
'coverage': <Object>[
|
||||||
<String, Object>{
|
<String, Object>{
|
||||||
'source': 'foo.dart',
|
'source': 'package:foo/foo.dart',
|
||||||
'script': <String, Object>{
|
'script': <String, Object>{
|
||||||
'type': '@Script',
|
'type': '@Script',
|
||||||
'fixedId': true,
|
'fixedId': true,
|
||||||
'id': 'libraries/1/scripts/foo.dart',
|
'id': 'libraries/1/scripts/package%3Afoo%2Ffoo.dart',
|
||||||
'uri': 'foo.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',
|
'_kind': 'library',
|
||||||
},
|
},
|
||||||
'hits': <Object>[1, 1, 3, 1, 2, 0],
|
'hits': <Object>[1, 1, 3, 1, 2, 0],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user