Merge branch 'master' of github.com:dart-lang/coverage
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index ab225ad..2606b39 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -23,9 +23,9 @@
sdk: [dev]
steps:
- uses: actions/checkout@v2
- - uses: dart-lang/setup-dart@v0.1
+ - uses: dart-lang/setup-dart@v1.0
with:
- channel: ${{ matrix.sdk }}
+ sdk: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
@@ -47,27 +47,27 @@
matrix:
# Add macos-latest and/or windows-latest if relevant for this package.
os: [ubuntu-latest]
- sdk: [dev]
+ sdk: [2.12.0, dev]
steps:
- uses: actions/checkout@v2
- - uses: dart-lang/setup-dart@v0.1
+ - uses: dart-lang/setup-dart@v1.0
with:
- channel: ${{ matrix.sdk }}
+ sdk: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
- name: Run VM tests
run: dart test --platform vm
if: always() && steps.install.outcome == 'success'
-
+
coverage:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - uses: dart-lang/setup-dart@v0.1
+ - uses: dart-lang/setup-dart@v1.0
with:
- channel: dev
+ sdk: dev
- id: install
name: Install dependencies
run: dart pub get
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1256f4b..2da8fe8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,19 @@
from using `Map<int, int>` to represent line coverage to using `HitMap`
(which contains both line and function coverage).
+## 1.0.4 - 2021-06-08
+
+* Ensure `createHitmap` returns a sorted hitmap. This fixes a potential issue with
+ ignore line annotations.
+
+## 1.0.3 - 2021-05-25
+
+* Updated dependency on `vm_service` package from `^6.1.0` to `>=6.1.0 <8.0.0`.
+
+## 1.0.2 - 2021-03-15
+
+* Fix an issue where the `--packages` argument wasn't passed to `format_coverage`.
+
## 1.0.1 - 2021-02-25
* Allow the chrome `sourceUriProvider` to return `null`.
@@ -19,6 +32,7 @@
## 1.0.0 - 2021-02-25
* Migrate to null safety.
+* Removed support for SDK `1.x.x`.
## 0.15.2 - 2021-02-08
diff --git a/bin/format_coverage.dart b/bin/format_coverage.dart
index 49c6a65..0ca57fb 100644
--- a/bin/format_coverage.dart
+++ b/bin/format_coverage.dart
@@ -62,6 +62,7 @@
files,
env.workers,
checkIgnoredLines: env.checkIgnore,
+ packagesPath: env.packagesPath,
);
// All workers are done. Process the data.
diff --git a/lib/src/hitmap.dart b/lib/src/hitmap.dart
index 2b048ed..40bd2c9 100644
--- a/lib/src/hitmap.dart
+++ b/lib/src/hitmap.dart
@@ -8,6 +8,7 @@
import 'package:coverage/src/resolver.dart';
import 'package:coverage/src/util.dart';
+
/// Contains line and function hit information for a single script.
class HitMap {
/// Map from line to hit count for that line.
@@ -18,6 +19,20 @@
/// Map from function definition line to function name.
final funcNames = <int, String>{};
+
+/// Class containing information about a coverage hit.
+class _HitInfo {
+ _HitInfo(this.firstLine, this.hitRange, this.hitCount);
+
+ /// The line number of the first line of this hit range.
+ final int firstLine;
+
+ /// A hit range is either a number (1 line) or a String of the form
+ /// "start-end" (multi-line range).
+ final dynamic hitRange;
+
+ /// How many times this hit range was executed.
+ final int hitCount;
}
/// Creates a single hitmap from a raw json object. Throws away all entries that
@@ -86,6 +101,7 @@
return false;
}
+<<<<<<< HEAD
void addToMap(Map<int, int> map, int line, int count) {
final oldCount = map.putIfAbsent(line, () => 0);
map[line] = count + oldCount;
@@ -115,6 +131,32 @@
}
} else {
throw StateError('Expected value of type int or String');
+=======
+ final sourceHitMap = globalHitMap.putIfAbsent(source, () => <int, int>{});
+ var hits = e['hits'] as List;
+ // Ignore line annotations require hits to be sorted.
+ hits = _sortHits(hits);
+ // hits is a flat array of the following format:
+ // [ <line|linerange>, <hitcount>,...]
+ // line: number.
+ // linerange: '<line>-<line>'.
+ for (var i = 0; i < hits.length; i += 2) {
+ final k = hits[i];
+ if (k is int) {
+ // Single line.
+ if (_shouldIgnoreLine(ignoredLines, k)) continue;
+
+ addToMap(sourceHitMap, k, hits[i + 1] as int);
+ } else if (k is String) {
+ // Linerange. We expand line ranges to actual lines at this point.
+ final splitPos = k.indexOf('-');
+ final start = int.parse(k.substring(0, splitPos));
+ final end = int.parse(k.substring(splitPos + 1));
+ for (var j = start; j <= end; j++) {
+ if (_shouldIgnoreLine(ignoredLines, j)) continue;
+
+ addToMap(sourceHitMap, j, hits[i + 1] as int);
+>>>>>>> 4cf2e67b027b1e940b2019c463e7f9947f6a1b66
}
}
}
@@ -167,6 +209,7 @@
Iterable<File> files,
int _, {
bool checkIgnoredLines = false,
+ String? packagesPath,
}) async {
final globalHitmap = <String, HitMap>{};
for (var file in files) {
@@ -178,6 +221,7 @@
await createHitmap(
jsonResult.cast<Map<String, dynamic>>(),
checkIgnoredLines: checkIgnoredLines,
+ packagesPath: packagesPath,
),
globalHitmap,
);
@@ -186,6 +230,7 @@
return globalHitmap;
}
+<<<<<<< HEAD
/// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs.
Map<String, dynamic> toScriptCoverageJson(Uri scriptUri, HitMap hits) {
final json = <String, dynamic>{};
@@ -211,4 +256,21 @@
json['funcHits'] = flattenMap<int>(hits.funcHits);
json['funcNames'] = flattenMap<dynamic>(hits.funcNames);
return json;
+=======
+/// Sorts the hits array based on the line numbers.
+List _sortHits(List hits) {
+ final structuredHits = <_HitInfo>[];
+ for (var i = 0; i < hits.length - 1; i += 2) {
+ final lineOrLineRange = hits[i];
+ final firstLineInRange = lineOrLineRange is int
+ ? lineOrLineRange
+ : int.parse(lineOrLineRange.split('-')[0] as String);
+ structuredHits.add(_HitInfo(firstLineInRange, hits[i], hits[i + 1] as int));
+ }
+ structuredHits.sort((a, b) => a.firstLine.compareTo(b.firstLine));
+ return structuredHits
+ .map((item) => [item.hitRange, item.hitCount])
+ .expand((item) => item)
+ .toList();
+>>>>>>> 4cf2e67b027b1e940b2019c463e7f9947f6a1b66
}
diff --git a/pubspec.yaml b/pubspec.yaml
index a118e91..f8898ab 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
name: coverage
-version: 1.0.1
+version: 1.0.4
description: Coverage data manipulation and formatting
homepage: https://github.com/dart-lang/coverage
environment:
- sdk: '>=2.12.0-0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
args: ^2.0.0
@@ -13,7 +13,7 @@
path: ^1.8.0
source_maps: ^0.10.10
stack_trace: ^1.10.0
- vm_service: ^6.1.0
+ vm_service: ">=6.1.0 <8.0.0"
dev_dependencies:
pedantic: ^1.10.0
test: ^1.16.0
@@ -21,7 +21,3 @@
executables:
collect_coverage:
format_coverage:
-
-dependency_overrides:
- test: ^1.16.0
- test_core: ^0.3.14
diff --git a/test/collect_coverage_api_test.dart b/test/collect_coverage_api_test.dart
index 49d4efb..6bb6ce1 100644
--- a/test/collect_coverage_api_test.dart
+++ b/test/collect_coverage_api_test.dart
@@ -74,8 +74,8 @@
final testAppCoverage = _getScriptCoverage(coverage, 'test_app.dart')!;
var hits = testAppCoverage['hits'] as List<int>;
- _expectHitCount(hits, 44, 0);
- _expectHitCount(hits, 48, 0);
+ _expectHitCount(hits, 46, 0);
+ _expectHitCount(hits, 50, 0);
final isolateCoverage =
_getScriptCoverage(coverage, 'test_app_isolate.dart')!;
diff --git a/test/collect_coverage_test.dart b/test/collect_coverage_test.dart
index 6dd8ea1..b96f768 100644
--- a/test/collect_coverage_test.dart
+++ b/test/collect_coverage_test.dart
@@ -49,32 +49,75 @@
}
});
+ test('createHitmap returns a sorted hitmap', () async {
+ final coverage = [
+ {
+ 'source': 'foo',
+ 'script': '{type: @Script, fixedId: true, '
+ 'id: bar.dart, uri: bar.dart, _kind: library}',
+ 'hits': [
+ 45,
+ 1,
+ 46,
+ 1,
+ 49,
+ 0,
+ 50,
+ 0,
+ 15,
+ 1,
+ 16,
+ 2,
+ 17,
+ 2,
+ ]
+ }
+ ];
+ final hitMap = await createHitmap(
+ coverage.cast<Map<String, dynamic>>(),
+ );
+ final expectedHits = {15: 1, 16: 2, 17: 2, 45: 1, 46: 1, 49: 0, 50: 0};
+ expect(hitMap['foo'], expectedHits);
+ });
+
test('createHitmap', () async {
final resultString = await _getCoverageResult();
final jsonResult = json.decode(resultString) as Map<String, dynamic>;
final coverage = jsonResult['coverage'] as List;
final hitMap = await createHitmap(
coverage.cast<Map<String, dynamic>>(),
- checkIgnoredLines: true,
);
expect(hitMap, contains(_sampleAppFileUri));
final isolateFile = hitMap[_isolateLibFileUri];
- final expectedLineHits = {
+ final expectedHits = {
+ 11: 1,
12: 1,
13: 1,
15: 0,
+ 28: 1,
+ 29: 1,
+ 31: 1,
+ 32: 3,
+ 38: 1,
+ 41: 1,
+ 42: 1,
+ 43: 1,
+ 46: 1,
+ 47: 1,
+ 49: 1,
+ 50: 1,
+ 51: 1,
+ 53: 1,
+ 54: 1,
+ 55: 1,
+ 18: 1,
19: 1,
20: 1,
22: 0,
- 29: 1,
- 31: 1,
- 32: 2,
33: 1,
34: 3,
- 35: 1,
- 46: 1,
- 47: 1,
+ 35: 1
};
if (Platform.version.startsWith('1.')) {
// Dart VMs prior to 2.0.0-dev.5.0 contain a bug that emits coverage on the
@@ -110,6 +153,26 @@
await tempDir.delete(recursive: true);
}
});
+
+ test('parseCoverage with packagesPath and checkIgnoredLines', () async {
+ final tempDir = await Directory.systemTemp.createTemp('coverage.test.');
+
+ try {
+ final outputFile = File(p.join(tempDir.path, 'coverage.json'));
+
+ final coverageResults = await _getCoverageResult();
+ await outputFile.writeAsString(coverageResults, flush: true);
+
+ final parsedResult = await parseCoverage([outputFile], 1,
+ packagesPath: '.packages', checkIgnoredLines: true);
+
+ // This file has ignore:coverage-file.
+ expect(parsedResult, isNot(contains(_sampleAppFileUri)));
+ expect(parsedResult, contains(_isolateLibFileUri));
+ } finally {
+ await tempDir.delete(recursive: true);
+ }
+ });
}
String? _coverageData;
diff --git a/test/lcov_test.dart b/test/lcov_test.dart
index c9ace53..1788512 100644
--- a/test/lcov_test.dart
+++ b/test/lcov_test.dart
@@ -27,11 +27,11 @@
final sampleAppHitMap = hitmap[_sampleAppFileUri];
- expect(sampleAppHitMap, containsPair(44, greaterThanOrEqualTo(1)),
+ expect(sampleAppHitMap, containsPair(46, greaterThanOrEqualTo(1)),
reason: 'be careful if you modify the test file');
- expect(sampleAppHitMap, containsPair(48, 0),
+ expect(sampleAppHitMap, containsPair(50, 0),
reason: 'be careful if you modify the test file');
- expect(sampleAppHitMap, isNot(contains(30)),
+ expect(sampleAppHitMap, isNot(contains(32)),
reason: 'be careful if you modify the test file');
});
diff --git a/test/run_and_collect_test.dart b/test/run_and_collect_test.dart
index aa0fe2a..99b0e92 100644
--- a/test/run_and_collect_test.dart
+++ b/test/run_and_collect_test.dart
@@ -2,8 +2,6 @@
// for details. 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:io';
-
import 'package:coverage/coverage.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
@@ -40,42 +38,30 @@
expect(sampleCoverageData['hits'], isNotEmpty);
}
- final hitMap = await createHitmap(
- coverage,
- checkIgnoredLines: true,
- );
- expect(hitMap, contains(_sampleAppFileUri));
+ final hitMap = await createHitmap(coverage, checkIgnoredLines: true);
+ expect(hitMap, isNot(contains(_sampleAppFileUri)));
final actualHits = hitMap[_isolateLibFileUri];
final expectedHits = {
+ 11: 1,
12: 1,
13: 1,
15: 0,
+ 28: 1,
+ 29: 1,
+ 31: 1,
+ 32: 3,
+ 46: 1,
+ 47: 1,
+ 18: 1,
19: 1,
20: 1,
22: 0,
- 29: 1,
- 31: 1,
- 32: 2,
33: 1,
34: 3,
- 35: 1,
- 46: 1,
- 47: 1,
+ 35: 1
};
- // Dart VMs prior to 2.0.0-dev.5.0 contain a bug that emits coverage on the
- // closing brace of async function blocks.
- // See: https://github.com/dart-lang/coverage/issues/196
- if (Platform.version.startsWith('1.')) {
- expectedHits[23] = 0;
- } else {
- // Dart VMs version 2.0.0-dev.6.0 mark the opening brace of a function as
- // coverable.
- expectedHits[11] = 1;
- expectedHits[18] = 1;
- expectedHits[28] = 1;
- expectedHits[32] = 3;
- }
+
expect(actualHits, expectedHits);
});
}
diff --git a/test/test_files/test_app.dart b/test/test_files/test_app.dart
index 79c5f2a..bf9256f 100644
--- a/test/test_files/test_app.dart
+++ b/test/test_files/test_app.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// coverage:ignore-file
+
import 'dart:async';
import 'dart:developer';
import 'dart:isolate';