| Index: test/source_report_test.dart
|
| diff --git a/test/source_report_test.dart b/test/source_report_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1734da44079b46fd3c91296e8b7f24f2c13156c2
|
| --- /dev/null
|
| +++ b/test/source_report_test.dart
|
| @@ -0,0 +1,220 @@
|
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| +// 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 'package:source_span/source_span.dart';
|
| +import 'package:test/test.dart';
|
| +import 'package:vm_service_client/vm_service_client.dart';
|
| +
|
| +import 'utils.dart';
|
| +
|
| +const _mainContent = r"""
|
| + print("one");
|
| + print("two");
|
| +
|
| + if (false) {
|
| + print("three");
|
| + print("four");
|
| + }
|
| +
|
| + Isolate.current.kill();
|
| +""";
|
| +
|
| +void main() {
|
| + VMServiceClient client;
|
| + VMIsolateRef isolate;
|
| +
|
| + tearDown(() {
|
| + if (client != null) client.close();
|
| + });
|
| +
|
| + group('getSourceReport for a script with one range', () {
|
| + setUp(() async {
|
| + client = await runAndConnect(main: _mainContent);
|
| +
|
| + isolate = (await client.getVM()).isolates.single;
|
| +
|
| + await isolate.waitUntilPaused();
|
| + });
|
| +
|
| + test("returns a valid source report", () async {
|
| + var report = await isolate.getSourceReport(
|
| + includeCoverageReport: false, includePossibleBreakpoints: false);
|
| +
|
| + expect(report.ranges, hasLength(greaterThan(1)));
|
| +
|
| + var range = report.ranges.singleWhere((range) =>
|
| + range.script.uri.toString().startsWith('data:application/dart'));
|
| +
|
| + expect(range.compiled, isTrue);
|
| +
|
| + var script = await range.script.load();
|
| +
|
| + var runnableIsolate = await isolate.loadRunnable();
|
| +
|
| + var rootLib = await runnableIsolate.rootLibrary.load();
|
| + var mainFunction = await rootLib.functions['main'].load();
|
| +
|
| + var mainLocation = script.sourceSpan(mainFunction.location);
|
| +
|
| + var startLocation = script.sourceLocation(range.location.token);
|
| + expect(startLocation, mainLocation.start);
|
| +
|
| + var endLocation = script.sourceLocation(range.location.end);
|
| + expect(endLocation, mainLocation.end);
|
| +
|
| + expect(range.hits, isNull);
|
| + expect(range.misses, isNull);
|
| + expect(range.possibleBreakpoints, isNull);
|
| + });
|
| +
|
| + test("reports accurate coverage information", () async {
|
| + var report =
|
| + await isolate.getSourceReport(includePossibleBreakpoints: false);
|
| +
|
| + var range = report.ranges.singleWhere((range) =>
|
| + range.script.uri.toString().startsWith('data:application/dart'));
|
| + expect(range.possibleBreakpoints, isNull);
|
| +
|
| + var script = await range.script.load();
|
| +
|
| + var hitLines =
|
| + range.hits.map((token) => script.sourceLocation(token).line).toSet();
|
| + expect(hitLines, [
|
| + 6, // new ReceivePort();
|
| + 7, // print("one");
|
| + 8, // print("two");
|
| + 15, // Isolate.current.kill();
|
| + 17 // VM inserts an extra hit on the last line of an async function
|
| + ]);
|
| +
|
| + // The line that are not executed – two within the `if (false)` block
|
| + var missedLines =
|
| + range.misses.map((token) => script.sourceLocation(token).line);
|
| + expect(missedLines, [11, 12]);
|
| + });
|
| +
|
| + test("reports accurate breakpoint information", () async {
|
| + var report = await isolate.getSourceReport(includeCoverageReport: false);
|
| +
|
| + var range = report.ranges.singleWhere((range) =>
|
| + range.script.uri.toString().startsWith('data:application/dart'));
|
| +
|
| + expect(range.hits, isNull);
|
| + expect(range.misses, isNull);
|
| +
|
| + var script = await range.script.load();
|
| + expect(range.possibleBreakpoints, isNotEmpty);
|
| +
|
| + // represents the unique set of lines that can have breakpoints
|
| + var breakPointLines = range.possibleBreakpoints
|
| + .map((token) => script.sourceLocation(token).line)
|
| + .toSet();
|
| + expect(breakPointLines, [
|
| + 4, // main entry point
|
| + 6, // new ReceivePort();
|
| + 7, // print("one");
|
| + 8, // print("two");
|
| + 11, // print("three");
|
| + 12, // print("four");
|
| + 15, // Isolate.current.kill();
|
| + 17 // VM considers the last line of an async function breakpoint-able
|
| + ]);
|
| + });
|
| +
|
| + test("behaves correctly including coverage and breakpoints", () async {
|
| + var report = await isolate.getSourceReport(
|
| + includeCoverageReport: true, includePossibleBreakpoints: true);
|
| +
|
| + var range = report.ranges.singleWhere((range) =>
|
| + range.script.uri.toString().startsWith('data:application/dart'));
|
| +
|
| + expect(range.hits, isNotEmpty);
|
| + expect(range.misses, isNotEmpty);
|
| + expect(range.possibleBreakpoints, isNotEmpty);
|
| + });
|
| + });
|
| +
|
| + group('getSourceReport with a multi-range script', () {
|
| + VMScript script;
|
| + VMLibrary rootLib;
|
| + VMSourceLocation mainLocation;
|
| + FileSpan mainFunctionSpan;
|
| + VMSourceLocation unusedFieldLocation;
|
| +
|
| + setUp(() async {
|
| + client = await runAndConnect(
|
| + topLevel: r'''final unusedField = 5;
|
| +
|
| +int unusedFunction(a, b) {
|
| + return a + b;
|
| +}
|
| +
|
| +void unusedFunction2(value) {
|
| + print(value);
|
| +}''',
|
| + main: _mainContent);
|
| +
|
| + isolate = (await client.getVM()).isolates.single;
|
| +
|
| + await isolate.waitUntilPaused();
|
| +
|
| + var runnableIsolate = await isolate.loadRunnable();
|
| + rootLib = await runnableIsolate.rootLibrary.load();
|
| + script = await rootLib.scripts.single.load();
|
| +
|
| + var mainFunction = await rootLib.functions['main'].load();
|
| + mainLocation = mainFunction.location;
|
| + mainFunctionSpan = script.sourceSpan(mainLocation);
|
| +
|
| + var unusedFieldRef = rootLib.fields['unusedField'];
|
| + var unusedField = await unusedFieldRef.load();
|
| + unusedFieldLocation = unusedField.location;
|
| + });
|
| +
|
| + test("reports valid data with default arguments", () async {
|
| + var report = await script.getSourceReport();
|
| +
|
| + expect(report.ranges, hasLength(3));
|
| +
|
| + var firstRange = report.ranges.first;
|
| + expect(firstRange.compiled, isFalse);
|
| + expect(firstRange.hits, isNull);
|
| + expect(firstRange.misses, isNull);
|
| + expect(firstRange.possibleBreakpoints, isNull);
|
| +
|
| + // TODO(kevmoo): it'd be nice if pkg/matcher had isBefore, isAfter
|
| + // https://github.com/dart-lang/matcher/issues/34
|
| + expect(script.sourceSpan(firstRange.location).compareTo(mainFunctionSpan),
|
| + isNegative);
|
| +
|
| + var lastRange = report.ranges.last;
|
| + expect(lastRange.compiled, isTrue);
|
| + expect(script.sourceSpan(lastRange.location), equals(mainFunctionSpan));
|
| + });
|
| +
|
| + test("reports all ranged compiled with forceCompile: true", () async {
|
| + var report = await script.getSourceReport(forceCompile: true);
|
| +
|
| + expect(report.ranges, hasLength(3));
|
| +
|
| + var firstRange = report.ranges.first;
|
| + expect(firstRange.compiled, isTrue);
|
| +
|
| + var secondRange = report.ranges.last;
|
| + expect(secondRange.compiled, isTrue);
|
| + });
|
| +
|
| + test("reports a valid subrange with the location argument", () async {
|
| + var report = await script.getSourceReport(location: mainLocation);
|
| +
|
| + expect(script.sourceSpan(report.ranges.single.location),
|
| + equals(mainFunctionSpan));
|
| + });
|
| +
|
| + test("throws if a zero-length location is used", () async {
|
| + expect(script.getSourceReport(location: unusedFieldLocation),
|
| + throwsArgumentError);
|
| + });
|
| + });
|
| +}
|
|
|