blob: edae67ea4050e2a861850bbd7b42cafaa0d53b10 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. 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:convert' show jsonEncode;
import 'dart:io' show Directory, File;
import 'package:coverage/coverage.dart' show HitMap;
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart' show FileSystem;
import 'package:flutter_tools/src/test/coverage_collector.dart';
import 'package:flutter_tools/src/test/test_device.dart' show TestDevice;
import 'package:flutter_tools/src/test/test_time_recorder.dart';
import 'package:stream_channel/stream_channel.dart' show StreamChannel;
import 'package:vm_service/vm_service.dart';
import '../src/common.dart';
import '../src/context.dart';
import '../src/fake_vm_services.dart';
import '../src/logging_logger.dart';
void main() {
testWithoutContext('Coverage collector Can handle coverage SentinelException', () 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: 3, minor: 51).toJson(),
),
const FakeVmServiceRequest(
method: 'getScripts',
args: <String, Object>{
'isolateId': '1',
},
jsonResponse: <String, Object>{
'type': 'Sentinel',
},
),
],
);
final Map<String, Object?> result = await collect(
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
expect(result, <String, Object>{'type': 'CodeCoverage', 'coverage': <Object>[]});
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
testWithoutContext('Coverage collector processes coverage and script data', () 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: 3, minor: 51).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(),
),
],
);
final Map<String, Object?> result = await collect(
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
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 null libraryNames accepts all libraries', () async {
final FakeVmServiceHost fakeVmServiceHost = createFakeVmServiceHostWithFooAndBar();
final Map<String, Object?> result = await collect(
Uri(),
null,
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
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: 'getVM',
jsonResponse: (VM.parse(<String, Object>{})!
..isolates = <IsolateRef>[
IsolateRef.parse(<String, Object>{
'id': '1',
})!,
]
).toJson(),
),
FakeVmServiceRequest(
method: 'getVersion',
jsonResponse: Version(major: 3, minor: 57).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(
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
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: 'getVM',
jsonResponse: (VM.parse(<String, Object>{})!
..isolates = <IsolateRef>[
IsolateRef.parse(<String, Object>{
'id': '1',
})!,
]
).toJson(),
),
FakeVmServiceRequest(
method: 'getVersion',
jsonResponse: Version(major: 3, minor: 57).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(
Uri(),
null,
serviceOverride: fakeVmServiceHost.vmService,
coverableLineCache: <String, Set<int>>{},
);
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 branch coverage', () 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: 3, minor: 56).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', 'BranchCoverage'],
'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],
),
branchCoverage: SourceReportCoverage(
hits: <int>[4, 6],
misses: <int>[5],
),
),
],
scripts: <ScriptRef>[
ScriptRef(
uri: 'package:foo/foo.dart',
id: '1',
),
],
).toJson(),
),
],
);
final Map<String, Object?> result = await collect(
Uri(),
<String>{'foo'},
serviceOverride: fakeVmServiceHost.vmService,
branchCoverage: true,
coverableLineCache: <String, Set<int>>{},
);
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],
'branchHits': <Object>[4, 1, 6, 1, 5, 0],
},
],
});
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
testWithoutContext('Coverage collector caches read files', () async {
Directory? tempDir;
try {
tempDir = Directory.systemTemp.createTempSync('flutter_coverage_collector_test.');
final File packagesFile = writeFooBarPackagesJson(tempDir);
final Directory fooDir = Directory('${tempDir.path}/foo/');
fooDir.createSync();
final File fooFile = File('${fooDir.path}/foo.dart');
fooFile.writeAsStringSync('hit\nnohit but ignored // coverage:ignore-line\nhit\n');
final String packagesPath = packagesFile.path;
final CoverageCollector collector = CoverageCollector(
libraryNames: <String>{'foo', 'bar'},
verbose: false,
packagesPath: packagesPath,
resolver: await CoverageCollector.getResolver(packagesPath)
);
await collector.collectCoverage(
TestTestDevice(),
serviceOverride: createFakeVmServiceHostWithFooAndBar(libraryFilters: <String>['package:foo/', 'package:bar/']).vmService,
);
Future<void> getHitMapAndVerify() async {
final Map<String, HitMap> gottenHitmap = <String, HitMap>{};
await collector.finalizeCoverage(formatter: (Map<String, HitMap> hitmap) {
gottenHitmap.addAll(hitmap);
return '';
});
expect(gottenHitmap.keys.toList()..sort(), <String>['package:bar/bar.dart', 'package:foo/foo.dart']);
expect(gottenHitmap['package:foo/foo.dart']!.lineHits, <int, int>{1: 1, /* 2: 0, is ignored in file */ 3: 1});
expect(gottenHitmap['package:bar/bar.dart']!.lineHits, <int, int>{21: 1, 32: 0, 47: 1, 86: 0});
}
Future<void> verifyHitmapEmpty() async {
final Map<String, HitMap> gottenHitmap = <String, HitMap>{};
await collector.finalizeCoverage(formatter: (Map<String, HitMap> hitmap) {
gottenHitmap.addAll(hitmap);
return '';
});
expect(gottenHitmap.isEmpty, isTrue);
}
// Get hit map the first time.
await getHitMapAndVerify();
// Getting the hitmap clears it so we now doesn't get any data.
await verifyHitmapEmpty();
// Collecting again gets us the same data even though the foo file has been deleted.
// This means that the fact that line 2 was ignored has been cached.
fooFile.deleteSync();
await collector.collectCoverage(
TestTestDevice(),
serviceOverride: createFakeVmServiceHostWithFooAndBar(libraryFilters: <String>['package:foo/', 'package:bar/']).vmService,
);
await getHitMapAndVerify();
} finally {
tempDir?.deleteSync(recursive: true);
}
});
testWithoutContext('Coverage collector respects ignore whole file', () async {
Directory? tempDir;
try {
tempDir = Directory.systemTemp.createTempSync('flutter_coverage_collector_test.');
final File packagesFile = writeFooBarPackagesJson(tempDir);
final Directory fooDir = Directory('${tempDir.path}/foo/');
fooDir.createSync();
final File fooFile = File('${fooDir.path}/foo.dart');
fooFile.writeAsStringSync('hit\nnohit but ignored // coverage:ignore-file\nhit\n');
final String packagesPath = packagesFile.path;
final CoverageCollector collector = CoverageCollector(
libraryNames: <String>{'foo', 'bar'},
verbose: false,
packagesPath: packagesPath,
resolver: await CoverageCollector.getResolver(packagesPath)
);
await collector.collectCoverage(
TestTestDevice(),
serviceOverride: createFakeVmServiceHostWithFooAndBar(libraryFilters: <String>['package:foo/', 'package:bar/']).vmService,
);
final Map<String, HitMap> gottenHitmap = <String, HitMap>{};
await collector.finalizeCoverage(formatter: (Map<String, HitMap> hitmap) {
gottenHitmap.addAll(hitmap);
return '';
});
expect(gottenHitmap.keys.toList()..sort(), <String>['package:bar/bar.dart']);
expect(gottenHitmap['package:bar/bar.dart']!.lineHits, <int, int>{21: 1, 32: 0, 47: 1, 86: 0});
} finally {
tempDir?.deleteSync(recursive: true);
}
});
testUsingContext('Coverage collector respects libraryNames in finalized report', () async {
Directory? tempDir;
try {
tempDir = Directory.systemTemp.createTempSync('flutter_coverage_collector_test.');
final File packagesFile = writeFooBarPackagesJson(tempDir);
File('${tempDir.path}/foo/foo.dart').createSync(recursive: true);
File('${tempDir.path}/bar/bar.dart').createSync(recursive: true);
final String packagesPath = packagesFile.path;
CoverageCollector collector = CoverageCollector(
libraryNames: <String>{'foo', 'bar'},
verbose: false,
packagesPath: packagesPath,
resolver: await CoverageCollector.getResolver(packagesPath)
);
await collector.collectCoverage(
TestTestDevice(),
serviceOverride: createFakeVmServiceHostWithFooAndBar(libraryFilters: <String>['package:foo/', 'package:bar/']).vmService,
);
String? report = await collector.finalizeCoverage();
expect(report, contains('foo.dart'));
expect(report, contains('bar.dart'));
collector = CoverageCollector(
libraryNames: <String>{'foo'},
verbose: false,
packagesPath: packagesPath,
resolver: await CoverageCollector.getResolver(packagesPath)
);
await collector.collectCoverage(
TestTestDevice(),
serviceOverride: createFakeVmServiceHostWithFooAndBar(libraryFilters: <String>['package:foo/']).vmService,
);
report = await collector.finalizeCoverage();
expect(report, contains('foo.dart'));
expect(report, isNot(contains('bar.dart')));
} finally {
tempDir?.deleteSync(recursive: true);
}
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
});
testWithoutContext('Coverage collector records test timings when provided TestTimeRecorder', () async {
Directory? tempDir;
try {
tempDir = Directory.systemTemp.createTempSync('flutter_coverage_collector_test.');
final File packagesFile = writeFooBarPackagesJson(tempDir);
final Directory fooDir = Directory('${tempDir.path}/foo/');
fooDir.createSync();
final File fooFile = File('${fooDir.path}/foo.dart');
fooFile.writeAsStringSync('hit\nnohit but ignored // coverage:ignore-line\nhit\n');
final String packagesPath = packagesFile.path;
final LoggingLogger logger = LoggingLogger();
final TestTimeRecorder testTimeRecorder = TestTimeRecorder(logger);
final CoverageCollector collector = CoverageCollector(
libraryNames: <String>{'foo', 'bar'},
verbose: false,
packagesPath: packagesPath,
resolver: await CoverageCollector.getResolver(packagesPath),
testTimeRecorder: testTimeRecorder
);
await collector.collectCoverage(
TestTestDevice(),
serviceOverride: createFakeVmServiceHostWithFooAndBar(libraryFilters: <String>['package:foo/', 'package:bar/']).vmService,
);
// Expect one message for each phase.
final List<String> logPhaseMessages = testTimeRecorder.getPrintAsListForTesting().where((String m) => m.startsWith('Runtime for phase ')).toList();
expect(logPhaseMessages, hasLength(TestTimePhases.values.length));
// Several phases actually does something, but here we just expect at
// least one phase to take a non-zero amount of time.
final List<String> logPhaseMessagesNonZero = logPhaseMessages.where((String m) => !m.contains(Duration.zero.toString())).toList();
expect(logPhaseMessagesNonZero, isNotEmpty);
} finally {
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) {
final File file = File('${tempDir.path}/packages.json');
file.writeAsStringSync(jsonEncode(<String, dynamic>{
'configVersion': 2,
'packages': <Map<String, String>>[
<String, String>{
'name': 'foo',
'rootUri': 'foo',
},
<String, String>{
'name': 'bar',
'rootUri': 'bar',
},
],
}));
return file;
}
FakeVmServiceHost createFakeVmServiceHostWithFooAndBar({
List<String>? libraryFilters,
}) {
return 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: 3, minor: 61).toJson(),
),
FakeVmServiceRequest(
method: 'getSourceReport',
args: <String, Object>{
'isolateId': '1',
'reports': <Object>['Coverage'],
'forceCompile': true,
'reportLines': true,
if (libraryFilters != null) 'libraryFilters': libraryFilters,
},
jsonResponse: SourceReport(
ranges: <SourceReportRange>[
SourceReportRange(
scriptIndex: 0,
startPos: 0,
endPos: 0,
compiled: true,
coverage: SourceReportCoverage(
hits: <int>[1, 3],
misses: <int>[2],
),
),
SourceReportRange(
scriptIndex: 1,
startPos: 0,
endPos: 0,
compiled: true,
coverage: SourceReportCoverage(
hits: <int>[47, 21],
misses: <int>[32, 86],
),
),
],
scripts: <ScriptRef>[
ScriptRef(
uri: 'package:foo/foo.dart',
id: '1',
),
ScriptRef(
uri: 'package:bar/bar.dart',
id: '2',
),
],
).toJson(),
),
],
);
}
class TestTestDevice extends TestDevice {
@override
Future<void> get finished => Future<void>.delayed(const Duration(seconds: 1));
@override
Future<void> kill() => Future<void>.value();
@override
Future<Uri?> get vmServiceUri => Future<Uri?>.value(Uri());
@override
Future<StreamChannel<String>> start(String entrypointPath) {
throw UnimplementedError();
}
}