| // Copyright (c) 2023, 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 'dart:developer'; |
| |
| import 'package:test/test.dart'; |
| import 'package:vm_service/vm_service.dart'; |
| |
| import 'common/service_test_common.dart'; |
| import 'common/test_helper.dart'; |
| import 'get_source_report_const_coverage_lib.dart' as lib; |
| |
| const filename = 'get_source_report_const_coverage_test'; |
| const expectedLinesHit = <int>{LINE_A, LINE_B, LINE_D}; |
| const expectedLinesNotHit = <int>{LINE_C}; |
| |
| // AUTOGENERATED START |
| // |
| // Update these constants by running: |
| // |
| // dart pkg/vm_service/test/update_line_numbers.dart <test.dart> |
| // |
| const LINE_A = 34; |
| const LINE_B = 36; |
| const LINE_C = 38; |
| const LINE_D = 40; |
| const LINE_E = 55; |
| // AUTOGENERATED END |
| |
| class Foo { |
| final int x; |
| // Expect this constructor to be coverage by coverage. |
| const Foo([int? x]) : x = x ?? 42; // LINE_A |
| // Expect this constructor to be coverage by coverage too. |
| const Foo.named1([int? x]) : x = x ?? 42; // LINE_B |
| // Expect this constructor to *NOT* be coverage by coverage. |
| const Foo.named2([int? x]) : x = x ?? 42; // LINE_C |
| // Expect this constructor to be coverage by coverage too (from lib). |
| const Foo.named3([int? x]) : x = x ?? 42; // LINE_D |
| } |
| |
| void testFunction() { |
| const foo = Foo(); |
| const foo2 = Foo(); |
| const fooIdentical = identical(foo, foo2); |
| print(fooIdentical); |
| |
| const namedFoo = Foo.named1(); |
| const namedFoo2 = Foo.named1(); |
| // ignore: unused_local_variable |
| const namedIdentical = identical(namedFoo, namedFoo2); |
| print(fooIdentical); |
| |
| debugger(); // LINE_E |
| |
| // That this is called after (or at all) is not relevent for the code |
| // coverage of constants. |
| lib.testFunction(); |
| |
| print('Done'); |
| } |
| |
| final tests = <IsolateTest>[ |
| hasStoppedAtBreakpoint, |
| stoppedAtLine(LINE_E), |
| (VmService service, IsolateRef isolateRef) async { |
| final isolateId = isolateRef.id!; |
| final isolate = await service.getIsolate(isolateId); |
| final rootLibId = isolate.rootLib!.id!; |
| final rootLib = await service.getObject(isolateId, rootLibId) as Library; |
| Script? foundScript; |
| for (ScriptRef script in rootLib.scripts!) { |
| if (script.uri!.contains(filename)) { |
| foundScript = await service.getObject(isolateId, script.id!) as Script; |
| break; |
| } |
| } |
| |
| if (foundScript == null) { |
| fail('Failed to find script'); |
| } |
| |
| Set<int> hits; |
| { |
| // Get report for everything; then collect for this library. |
| final coverage = await service.getSourceReport( |
| isolateId, |
| [SourceReportKind.kCoverage], |
| ); |
| hits = getHitsFor(coverage, filename); |
| final lines = <int>{}; |
| for (int hit in hits) { |
| // We expect every hit to be translatable to line |
| // (i.e. tokenToLine to return non-null). |
| final line = foundScript.getLineNumberFromTokenPos(hit); |
| lines.add(line!); |
| } |
| print('Token position hits: $hits --- line hits: $lines'); |
| expect(lines.intersection(expectedLinesHit), expectedLinesHit); |
| expect(lines.intersection(expectedLinesNotHit), isEmpty); |
| } |
| { |
| // Now get report for the this file only. |
| final coverage = await service.getSourceReport( |
| isolateId, |
| [SourceReportKind.kCoverage], |
| scriptId: foundScript.id!, |
| ); |
| final localHits = getHitsFor(coverage, filename); |
| expect(localHits.length, hits.length); |
| expect(hits.toList()..sort(), localHits.toList()..sort()); |
| print(localHits); |
| } |
| }, |
| ]; |
| |
| Set<int> getHitsFor(SourceReport coverage, String uriContains) { |
| final scripts = coverage.scripts!; |
| final scriptIdsWanted = <int>{}; |
| for (int i = 0; i < scripts.length; i++) { |
| final script = scripts[i]; |
| final scriptUri = script.uri!; |
| if (scriptUri.contains(uriContains)) { |
| scriptIdsWanted.add(i); |
| } |
| } |
| final ranges = coverage.ranges!; |
| final hits = <int>{}; |
| for (final range in ranges) { |
| if (scriptIdsWanted.contains(range.scriptIndex!)) { |
| if (range.coverage != null) { |
| for (int hit in range.coverage!.hits!) { |
| hits.add(hit); |
| } |
| } |
| } |
| } |
| return hits; |
| } |
| |
| void main([args = const <String>[]]) => runIsolateTests( |
| args, |
| tests, |
| 'get_source_report_const_coverage_test.dart', |
| testeeConcurrent: testFunction, |
| ); |