[coverage] Partial workspace support (#2095)
diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 98e1bb4..997e33f 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml
@@ -56,12 +56,7 @@ fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - sdk: [3.4, dev] - exclude: - # VM service times out on windows before Dart 3.5 - # https://github.com/dart-lang/coverage/issues/490 - - os: windows-latest - sdk: 3.4 + sdk: [3.6, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c @@ -89,7 +84,7 @@ name: Install dependencies run: dart pub get - name: Collect and report coverage - run: dart run bin/test_with_coverage.dart --port=9292 + run: dart run bin/test_with_coverage.dart - name: Upload coverage uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b with:
diff --git a/pkgs/coverage/CHANGELOG.md b/pkgs/coverage/CHANGELOG.md index 6dc80a5..2a680ad 100644 --- a/pkgs/coverage/CHANGELOG.md +++ b/pkgs/coverage/CHANGELOG.md
@@ -1,3 +1,11 @@ +## 1.14.0 + +- Require Dart ^3.6.0 +- Partial support for workspace packages in `test_wth_coverage`. +- Deprecate `test_wth_coverage`'s `--package-name` flag, because it doesn't make + sense for workspaces. +- Change the default `--port` to 0, allowing the VM to choose a free port. + ## 1.13.1 - Fix a bug where the VM service can be shut down while some coverage
diff --git a/pkgs/coverage/README.md b/pkgs/coverage/README.md index 2963c6a..7a90c8e 100644 --- a/pkgs/coverage/README.md +++ b/pkgs/coverage/README.md
@@ -43,6 +43,30 @@ For more complicated use cases, where you want to control each of these stages, see the sections below. +#### Workspaces + +package:coverage has partial support for +[workspaces](https://dart.dev/tools/pub/workspaces). You can run +`test_with_coverage` from the root of the workspace to collect coverage for all +the tests in all the subpackages, but you must specify the test directories to +run. + +For example, in a workspace with subpackages `pkgs/foo` and `pkgs/bar`, you +could run the following command from the root directory of the workspace: + +``` +dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test +``` + +This would output coverage to ./coverage/ as normal. An important caveat is that +the working directory of the tests will be the workspace's root directory. So +this approach won't work if your tests assume that they are being run from the +subpackage directory. + +[Full support](https://github.com/dart-lang/tools/issues/2083) for workspaces +will likely be added in a future version. This will mean you won't need to +explicitly specify the test directories: `dart run coverage:test_with_coverage` + #### Collecting coverage from the VM ```
diff --git a/pkgs/coverage/bin/test_with_coverage.dart b/pkgs/coverage/bin/test_with_coverage.dart index c22e9b8..9f4884d 100644 --- a/pkgs/coverage/bin/test_with_coverage.dart +++ b/pkgs/coverage/bin/test_with_coverage.dart
@@ -7,10 +7,8 @@ import 'package:args/args.dart'; import 'package:coverage/src/coverage_options.dart'; -import 'package:coverage/src/util.dart' - show StandardOutExtension, extractVMServiceUri; +import 'package:coverage/src/util.dart'; import 'package:meta/meta.dart'; -import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as path; import 'collect_coverage.dart' as collect_coverage; @@ -19,37 +17,36 @@ final _allProcesses = <Process>[]; Future<void> _dartRun(List<String> args, - {void Function(String)? onStdout, String? workingDir}) async { - final process = await Process.start( - Platform.executable, - args, - workingDirectory: workingDir, - ); + {required void Function(String) onStdout, + required void Function(String) onStderr}) async { + final process = await Process.start(Platform.executable, args); _allProcesses.add(process); - final broadStdout = process.stdout.asBroadcastStream(); - broadStdout.listen(stdout.add); - if (onStdout != null) { - broadStdout.lines().listen(onStdout); + + void listen( + Stream<List<int>> stream, IOSink sink, void Function(String) onLine) { + final broadStream = stream.asBroadcastStream(); + broadStream.listen(sink.add); + broadStream.lines().listen(onLine); } - process.stderr.listen(stderr.add); + + listen(process.stdout, stdout, onStdout); + listen(process.stderr, stderr, onStderr); + final result = await process.exitCode; if (result != 0) { throw ProcessException(Platform.executable, args, '', result); } } -Future<String?> _packageNameFromConfig(String packageDir) async { - final config = await findPackageConfig(Directory(packageDir)); - return config?.packageOf(Uri.directory(packageDir))?.name; +void _killSubprocessesAndExit(ProcessSignal signal) { + for (final process in _allProcesses) { + process.kill(signal); + } + exit(1); } void _watchExitSignal(ProcessSignal signal) { - signal.watch().listen((sig) { - for (final process in _allProcesses) { - process.kill(sig); - } - exit(1); - }); + signal.watch().listen(_killSubprocessesAndExit); } ArgParser _createArgParser(CoverageOptions defaultOptions) => ArgParser() @@ -61,10 +58,10 @@ ..addOption( 'package-name', help: 'Name of the package to test. ' - 'Deduced from --package if not provided.', - defaultsTo: defaultOptions.packageName, + 'Deduced from --package if not provided. ' + 'DEPRECATED: use --scope-output', ) - ..addOption('port', help: 'VM service port.', defaultsTo: '8181') + ..addOption('port', help: 'VM service port. Defaults to using any free port.') ..addOption( 'out', defaultsTo: defaultOptions.outputDirectory, @@ -93,13 +90,13 @@ defaultsTo: defaultOptions.scopeOutput, help: 'restrict coverage results so that only scripts that start with ' 'the provided package path are considered. Defaults to the name of ' - 'the package under test.') + 'the current package (including all subpackages, if this is a ' + 'workspace).') ..addFlag('help', abbr: 'h', negatable: false, help: 'Show this help.'); class Flags { Flags( this.packageDir, - this.packageName, this.outDir, this.port, this.testScript, @@ -111,7 +108,6 @@ }); final String packageDir; - final String packageName; final String outDir; final String port; final String testScript; @@ -157,25 +153,23 @@ fail('--package is not a valid directory.'); } - final packageName = (args['package-name'] as String?) ?? - await _packageNameFromConfig(packageDir); - if (packageName == null) { + final pubspecPath = getPubspecPath(packageDir); + if (!File(pubspecPath).existsSync()) { fail( - "Couldn't figure out package name from --package. Make sure this is a " - 'package directory, or try passing --package-name explicitly.', + "Couldn't find $pubspecPath. Make sure this command is run in a " + 'package directory, or pass --package to explicitly set the directory.', ); } return Flags( packageDir, - packageName, - (args['out'] as String?) ?? path.join(packageDir, 'coverage'), - args['port'] as String, - args['test'] as String, - args['function-coverage'] as bool, - args['branch-coverage'] as bool, - args['scope-output'] as List<String>, - args['fail-under'] as String?, + args.option('out') ?? path.join(packageDir, 'coverage'), + args.option('port') ?? '0', + args.option('test')!, + args.flag('function-coverage'), + args.flag('branch-coverage'), + args.multiOption('scope-output'), + args.option('fail-under'), rest: args.rest, ); } @@ -215,11 +209,19 @@ } } }, + onStderr: (line) { + if (!serviceUriCompleter.isCompleted) { + if (line.contains('Could not start the VM service')) { + _killSubprocessesAndExit(ProcessSignal.sigkill); + } + } + }, ); final serviceUri = await serviceUriCompleter.future; - final scopes = - flags.scopeOutput.isEmpty ? [flags.packageName] : flags.scopeOutput; + final scopes = flags.scopeOutput.isEmpty + ? getAllWorkspaceNames(flags.packageDir) + : flags.scopeOutput; await collect_coverage.main([ '--wait-paused', '--resume-isolates',
diff --git a/pkgs/coverage/dart_test.yaml b/pkgs/coverage/dart_test.yaml new file mode 100644 index 0000000..f982167 --- /dev/null +++ b/pkgs/coverage/dart_test.yaml
@@ -0,0 +1,5 @@ +tags: + # Tests that start subprocesses, so are slower and can be a bit flaky. + integration: + timeout: 2x + retry: 3
diff --git a/pkgs/coverage/lib/src/collect.dart b/pkgs/coverage/lib/src/collect.dart index 76227ba..1bed28d 100644 --- a/pkgs/coverage/lib/src/collect.dart +++ b/pkgs/coverage/lib/src/collect.dart
@@ -170,6 +170,7 @@ isolateReport, includeDart, functionCoverage, + branchCoverage, coverableLineCache, scopedOutput); allCoverage.addAll(coverage); @@ -244,6 +245,7 @@ SourceReport report, bool includeDart, bool functionCoverage, + bool branchCoverage, Map<String, Set<int>>? coverableLineCache, Set<String> scopedOutput) async { final hitMaps = <Uri, HitMap>{}; @@ -262,7 +264,10 @@ return scripts[scriptRef]; } - HitMap getHitMap(Uri scriptUri) => hitMaps.putIfAbsent(scriptUri, HitMap.new); + HitMap getHitMap(Uri scriptUri) => hitMaps.putIfAbsent( + scriptUri, + () => HitMap.empty( + functionCoverage: functionCoverage, branchCoverage: branchCoverage)); Future<void> processFunction(FuncRef funcRef) async { final func = await service.getObject(isolateRef.id!, funcRef.id!) as Func; @@ -290,8 +295,7 @@ return; } final hits = getHitMap(Uri.parse(script.uri!)); - hits.funcHits ??= <int, int>{}; - (hits.funcNames ??= <int, String>{})[line] = funcName; + hits.funcNames![line] = funcName; } for (var range in report.ranges!) { @@ -385,13 +389,12 @@ hits.funcHits?.putIfAbsent(line, () => 0); }); - final branchCoverage = range.branchCoverage; - if (branchCoverage != null) { - hits.branchHits ??= <int, int>{}; - forEachLine(branchCoverage.hits, (line) { + final branches = range.branchCoverage; + if (branchCoverage && branches != null) { + forEachLine(branches.hits, (line) { hits.branchHits!.increment(line); }); - forEachLine(branchCoverage.misses, (line) { + forEachLine(branches.misses, (line) { hits.branchHits!.putIfAbsent(line, () => 0); }); }
diff --git a/pkgs/coverage/lib/src/coverage_options.dart b/pkgs/coverage/lib/src/coverage_options.dart index a15c31d..87790df 100644 --- a/pkgs/coverage/lib/src/coverage_options.dart +++ b/pkgs/coverage/lib/src/coverage_options.dart
@@ -9,7 +9,6 @@ required this.functionCoverage, required this.branchCoverage, required this.packageDirectory, - this.packageName, required this.testScript, }); @@ -40,8 +39,6 @@ branchCoverage: options.optionalBool('branch_coverage') ?? defaultOptions.branchCoverage, packageDirectory: packageDirectory, - packageName: - options.optionalString('package_name') ?? defaultOptions.packageName, testScript: options.optionalString('test_script') ?? defaultOptions.testScript, ); @@ -52,7 +49,6 @@ final bool functionCoverage; final bool branchCoverage; final String packageDirectory; - final String? packageName; final String testScript; } @@ -119,7 +115,6 @@ functionCoverage: false, branchCoverage: false, packageDirectory: '.', - packageName: null, testScript: 'test', ); }
diff --git a/pkgs/coverage/lib/src/formatter.dart b/pkgs/coverage/lib/src/formatter.dart index a37df73..2680607 100644 --- a/pkgs/coverage/lib/src/formatter.dart +++ b/pkgs/coverage/lib/src/formatter.dart
@@ -151,6 +151,20 @@ ); final buf = StringBuffer(); for (final entry in entries) { + final source = resolver.resolve(entry.key); + if (source == null) { + continue; + } + + if (!pathFilter(source)) { + continue; + } + + final lines = await loader.load(source); + if (lines == null) { + continue; + } + final v = entry.value; if (reportFuncs && v.funcHits == null) { throw StateError( @@ -165,24 +179,12 @@ 'missing branch coverage information. Did you run ' 'collect_coverage with the --branch-coverage flag?'); } + final hits = reportFuncs ? v.funcHits! : reportBranches ? v.branchHits! : v.lineHits; - final source = resolver.resolve(entry.key); - if (source == null) { - continue; - } - - if (!pathFilter(source)) { - continue; - } - - final lines = await loader.load(source); - if (lines == null) { - continue; - } buf.writeln(source); for (var line = 1; line <= lines.length; line++) { var prefix = _prefix;
diff --git a/pkgs/coverage/lib/src/hitmap.dart b/pkgs/coverage/lib/src/hitmap.dart index 4c3b468..133c24b 100644 --- a/pkgs/coverage/lib/src/hitmap.dart +++ b/pkgs/coverage/lib/src/hitmap.dart
@@ -18,6 +18,15 @@ this.branchHits, ]) : lineHits = lineHits ?? {}; + /// Constructs an empty hitmap, optionally with function and branch coverage + /// tables. + HitMap.empty({bool functionCoverage = false, bool branchCoverage = false}) + : this( + null, + functionCoverage ? <int, int>{} : null, + functionCoverage ? <int, String>{} : null, + branchCoverage ? <int, int>{} : null); + /// Map from line to hit count for that line. final Map<int, int> lineHits;
diff --git a/pkgs/coverage/lib/src/util.dart b/pkgs/coverage/lib/src/util.dart index cc7f584..74a1697 100644 --- a/pkgs/coverage/lib/src/util.dart +++ b/pkgs/coverage/lib/src/util.dart
@@ -6,6 +6,8 @@ import 'dart:convert'; import 'dart:io'; +import 'package:path/path.dart' as path; +import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:vm_service/vm_service.dart'; // TODO(cbracken) make generic @@ -57,25 +59,6 @@ return null; } -/// Returns an open port by creating a temporary Socket -Future<int> getOpenPort() async { - ServerSocket socket; - - try { - socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0); - } catch (_) { - // try again v/ V6 only. Slight possibility that V4 is disabled - socket = - await ServerSocket.bind(InternetAddress.loopbackIPv6, 0, v6Only: true); - } - - try { - return socket.port; - } finally { - await socket.close(); - } -} - final muliLineIgnoreStart = RegExp(r'//\s*coverage:ignore-start[\w\d\s]*$'); final muliLineIgnoreEnd = RegExp(r'//\s*coverage:ignore-end[\w\d\s]*$'); final singleLineIgnore = RegExp(r'//\s*coverage:ignore-line[\w\d\s]*$'); @@ -184,3 +167,19 @@ Future<List<IsolateRef>> getAllIsolates(VmService service) async => (await service.getVM()).isolates ?? []; + +String getPubspecPath(String root) => path.join(root, 'pubspec.yaml'); + +List<String> getAllWorkspaceNames(String packageRoot) => + _getAllWorkspaceNames(packageRoot, <String>[]); + +List<String> _getAllWorkspaceNames(String packageRoot, List<String> results) { + final pubspecPath = getPubspecPath(packageRoot); + final yaml = File(pubspecPath).readAsStringSync(); + final pubspec = Pubspec.parse(yaml, sourceUrl: Uri.file(pubspecPath)); + results.add(pubspec.name); + for (final workspace in pubspec.workspace ?? <String>[]) { + _getAllWorkspaceNames(path.join(packageRoot, workspace), results); + } + return results; +}
diff --git a/pkgs/coverage/pubspec.yaml b/pkgs/coverage/pubspec.yaml index 46307b8..e4a229e 100644 --- a/pkgs/coverage/pubspec.yaml +++ b/pkgs/coverage/pubspec.yaml
@@ -1,5 +1,5 @@ name: coverage -version: 1.13.1 +version: 1.14.0 description: Coverage data manipulation and formatting repository: https://github.com/dart-lang/tools/tree/main/pkgs/coverage issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Acoverage @@ -15,6 +15,7 @@ meta: ^1.0.2 package_config: ^2.0.0 path: ^1.8.0 + pubspec_parse: ^1.5.0 source_maps: ^0.10.10 stack_trace: ^1.10.0 vm_service: '>=12.0.0 <16.0.0'
diff --git a/pkgs/coverage/test/collect_coverage_api_test.dart b/pkgs/coverage/test/collect_coverage_api_test.dart index fd3de43..5ccedd8 100644 --- a/pkgs/coverage/test/collect_coverage_api_test.dart +++ b/pkgs/coverage/test/collect_coverage_api_test.dart
@@ -2,6 +2,9 @@ // 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. +@Tags(['integration']) +library; + import 'dart:async'; import 'package:coverage/coverage.dart'; @@ -140,10 +143,8 @@ bool functionCoverage = false, bool branchCoverage = false, Map<String, Set<int>>? coverableLineCache}) async { - final openPort = await getOpenPort(); - // run the sample app, with the right flags - final sampleProcess = await runTestApp(openPort); + final sampleProcess = await runTestApp(); final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream()); final isolateIdSet = isolateIds ? <String>{} : null;
diff --git a/pkgs/coverage/test/collect_coverage_config_test.dart b/pkgs/coverage/test/collect_coverage_config_test.dart index 5f6c460..d2b6b58 100644 --- a/pkgs/coverage/test/collect_coverage_config_test.dart +++ b/pkgs/coverage/test/collect_coverage_config_test.dart
@@ -1,3 +1,7 @@ +// Copyright (c) 2025, 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:coverage/src/coverage_options.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; @@ -35,7 +39,6 @@ expect(path.canonicalize(testCoverage.packageDir), path.canonicalize(defaults.packageDirectory)); - expect(testCoverage.packageName, 'coverage'); expect(path.canonicalize(testCoverage.outDir), path.canonicalize('coverage')); expect(testCoverage.testScript, defaults.testScript); @@ -73,7 +76,6 @@ // Verify test with coverage yaml values expect(path.canonicalize(testCoverage.packageDir), path.canonicalize('test/test_files')); - expect(testCoverage.packageName, 'My Dart Package'); expect(path.canonicalize(testCoverage.outDir), path.canonicalize('var/coverage_data')); expect(testCoverage.testScript, 'test1'); @@ -102,7 +104,6 @@ expect(collectedCoverage.functionCoverage, isFalse); expect(path.canonicalize(formattedCoverage.output!), path.canonicalize('var/coverage_data/custom_coverage/lcov.info')); - expect(testCoverage.packageName, 'Custom Dart Package'); expect(testCoverage.scopeOutput, ['lib', 'test']); }); @@ -133,7 +134,6 @@ path.canonicalize('test/test_coverage_options')); // Verify test with coverage yaml values - expect(testCoverage.packageName, 'coverage'); expect(path.canonicalize(testCoverage.outDir), path.canonicalize('var/coverage_data/custom_lcov')); expect(testCoverage.testScript, 'custom_test'); @@ -178,7 +178,6 @@ expect(formattedCoverage.packagePath, '../code_builder'); // Verify test with coverage command line args - expect(testCoverage.packageName, 'test'); expect(testCoverage.outDir, 'test_coverage.json'); expect(testCoverage.testScript, 'test_test.dart'); expect(testCoverage.functionCoverage, isTrue); @@ -218,7 +217,6 @@ expect(formattedCoverage.packagePath, '../cli_config'); // Verify test with coverage command line args - expect(testCoverage.packageName, 'cli_config'); expect(testCoverage.outDir, 'cli_config_coverage.json'); expect(testCoverage.testScript, 'cli_config_test.dart'); expect(testCoverage.functionCoverage, isTrue);
diff --git a/pkgs/coverage/test/collect_coverage_test.dart b/pkgs/coverage/test/collect_coverage_test.dart index 476fee1..5758b5e 100644 --- a/pkgs/coverage/test/collect_coverage_test.dart +++ b/pkgs/coverage/test/collect_coverage_test.dart
@@ -2,7 +2,7 @@ // 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. -@Retry(3) +@Tags(['integration']) library; import 'dart:async'; @@ -294,10 +294,8 @@ bool functionCoverage, bool branchCoverage) async { expect(FileSystemEntity.isFileSync(testAppPath), isTrue); - final openPort = await getOpenPort(); - // Run the sample app with the right flags. - final sampleProcess = await runTestApp(openPort); + final sampleProcess = await runTestApp(); // Capture the VM service URI. final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream());
diff --git a/pkgs/coverage/test/config_file_locator_test.dart b/pkgs/coverage/test/config_file_locator_test.dart index d46fc86..db131e8 100644 --- a/pkgs/coverage/test/config_file_locator_test.dart +++ b/pkgs/coverage/test/config_file_locator_test.dart
@@ -1,3 +1,7 @@ +// Copyright (c) 2025, 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:io'; import 'package:coverage/src/coverage_options.dart'; import 'package:path/path.dart' as path;
diff --git a/pkgs/coverage/test/function_coverage_test.dart b/pkgs/coverage/test/function_coverage_test.dart index 965d0d0..d8aaa74 100644 --- a/pkgs/coverage/test/function_coverage_test.dart +++ b/pkgs/coverage/test/function_coverage_test.dart
@@ -2,6 +2,9 @@ // 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. +@Tags(['integration']) +library; + import 'dart:async'; import 'dart:convert' show json; import 'dart:io'; @@ -74,14 +77,9 @@ Future<String> _collectCoverage() async { expect(FileSystemEntity.isFileSync(_funcCovApp), isTrue); - final openPort = await getOpenPort(); - // Run the sample app with the right flags. - final sampleProcess = await TestProcess.start(Platform.resolvedExecutable, [ - '--enable-vm-service=$openPort', - '--pause_isolates_on_exit', - _funcCovApp - ]); + final sampleProcess = await TestProcess.start(Platform.resolvedExecutable, + ['--enable-vm-service=0', '--pause_isolates_on_exit', _funcCovApp]); final serviceUri = await serviceUriFromProcess(sampleProcess.stdoutStream());
diff --git a/pkgs/coverage/test/lcov_test.dart b/pkgs/coverage/test/lcov_test.dart index ca62117..a03612c 100644 --- a/pkgs/coverage/test/lcov_test.dart +++ b/pkgs/coverage/test/lcov_test.dart
@@ -2,6 +2,9 @@ // 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. +@Tags(['integration']) +library; + import 'dart:async'; import 'dart:io'; @@ -337,13 +340,10 @@ Future<Map<String, HitMap>> _getHitMap() async { expect(FileSystemEntity.isFileSync(_sampleAppPath), isTrue); - // select service port. - final port = await getOpenPort(); - // start sample app. final sampleAppArgs = [ '--pause-isolates-on-exit', - '--enable-vm-service=$port', + '--enable-vm-service=0', '--branch-coverage', _sampleAppPath ];
diff --git a/pkgs/coverage/test/run_and_collect_test.dart b/pkgs/coverage/test/run_and_collect_test.dart index a538a88..0a45a44 100644 --- a/pkgs/coverage/test/run_and_collect_test.dart +++ b/pkgs/coverage/test/run_and_collect_test.dart
@@ -2,6 +2,9 @@ // 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. +@Tags(['integration']) +library; + import 'package:coverage/coverage.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart';
diff --git a/pkgs/coverage/test/test_coverage_options/pubspec.yaml b/pkgs/coverage/test/test_coverage_options/pubspec.yaml new file mode 100644 index 0000000..9d55a4f --- /dev/null +++ b/pkgs/coverage/test/test_coverage_options/pubspec.yaml
@@ -0,0 +1 @@ +name: test_coverage_options
diff --git a/pkgs/coverage/test/test_files/pubspec.yaml b/pkgs/coverage/test/test_files/pubspec.yaml new file mode 100644 index 0000000..ab2a25b --- /dev/null +++ b/pkgs/coverage/test/test_files/pubspec.yaml
@@ -0,0 +1,5 @@ +name: coverage_test_files + +dev_dependencies: + coverage: + path: ../../
diff --git a/pkgs/coverage/test/test_util.dart b/pkgs/coverage/test/test_util.dart index e0a3edb..6fe89d3 100644 --- a/pkgs/coverage/test/test_util.dart +++ b/pkgs/coverage/test/test_util.dart
@@ -11,12 +11,12 @@ final String testAppPath = p.join('test', 'test_files', 'test_app.dart'); -const Duration timeout = Duration(seconds: 20); +const Duration timeout = Duration(seconds: 30); -Future<TestProcess> runTestApp(int openPort) => TestProcess.start( +Future<TestProcess> runTestApp() => TestProcess.start( Platform.resolvedExecutable, [ - '--enable-vm-service=$openPort', + '--enable-vm-service=0', '--pause_isolates_on_exit', '--branch-coverage', testAppPath
diff --git a/pkgs/coverage/test/test_with_coverage_test.dart b/pkgs/coverage/test/test_with_coverage_test.dart index 53e2253..364510b 100644 --- a/pkgs/coverage/test/test_with_coverage_test.dart +++ b/pkgs/coverage/test/test_with_coverage_test.dart
@@ -2,7 +2,7 @@ // 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. -@Timeout(Duration(seconds: 60)) +@Tags(['integration']) library; import 'dart:convert';
diff --git a/pkgs/coverage/test/util_test.dart b/pkgs/coverage/test/util_test.dart index 6a4e556..75405ba 100644 --- a/pkgs/coverage/test/util_test.dart +++ b/pkgs/coverage/test/util_test.dart
@@ -355,4 +355,22 @@ ]); }); }); + + test('getAllWorkspaceNames', () { + // Uses the workspace_names directory: + // workspace_names + // └── pkgs + // ├── foo + // │ └── foo_example // Not part of foo's workspace. + // └── bar + // └── bar_example // Part of bar's workspace. + expect( + getAllWorkspaceNames('test/workspace_names'), + unorderedEquals([ + 'workspace_names', + 'foo', + 'bar', + 'bar_example', + ])); + }); }
diff --git a/pkgs/coverage/test/workspace_names/pkgs/bar/bar_example/pubspec.yaml b/pkgs/coverage/test/workspace_names/pkgs/bar/bar_example/pubspec.yaml new file mode 100644 index 0000000..e59be7d --- /dev/null +++ b/pkgs/coverage/test/workspace_names/pkgs/bar/bar_example/pubspec.yaml
@@ -0,0 +1,2 @@ +name: bar_example +resolution: workspace
diff --git a/pkgs/coverage/test/workspace_names/pkgs/bar/pubspec.yaml b/pkgs/coverage/test/workspace_names/pkgs/bar/pubspec.yaml new file mode 100644 index 0000000..a003681 --- /dev/null +++ b/pkgs/coverage/test/workspace_names/pkgs/bar/pubspec.yaml
@@ -0,0 +1,4 @@ +name: bar +resolution: workspace +workspace: +- bar_example
diff --git a/pkgs/coverage/test/workspace_names/pkgs/foo/foo_example/pubspec.yaml b/pkgs/coverage/test/workspace_names/pkgs/foo/foo_example/pubspec.yaml new file mode 100644 index 0000000..92033a9 --- /dev/null +++ b/pkgs/coverage/test/workspace_names/pkgs/foo/foo_example/pubspec.yaml
@@ -0,0 +1 @@ +name: foo_example
diff --git a/pkgs/coverage/test/workspace_names/pkgs/foo/pubspec.yaml b/pkgs/coverage/test/workspace_names/pkgs/foo/pubspec.yaml new file mode 100644 index 0000000..e6ffc83 --- /dev/null +++ b/pkgs/coverage/test/workspace_names/pkgs/foo/pubspec.yaml
@@ -0,0 +1,2 @@ +name: foo +resolution: workspace
diff --git a/pkgs/coverage/test/workspace_names/pubspec.yaml b/pkgs/coverage/test/workspace_names/pubspec.yaml new file mode 100644 index 0000000..90e1fbc --- /dev/null +++ b/pkgs/coverage/test/workspace_names/pubspec.yaml
@@ -0,0 +1,4 @@ +name: workspace_names +workspace: +- pkgs/bar +- pkgs/foo