Skip to content

Commit 55ccf91

Browse files
authored
Merge branch 'main' into oauth2-readme
2 parents fc6a803 + 04c6849 commit 55ccf91

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2076
-140
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pkgs/mime @lrhn
2828
pkgs/oauth2 @dart-lang/dart-pub-team
2929
pkgs/package_config @dart-lang/dart-ecosystem-team
3030
pkgs/pool @dart-lang/dart-ecosystem-team
31+
pkgs/process @dart-lang/dart-ecosystem-team
3132
pkgs/pub_semver @dart-lang/dart-pub-team
3233
pkgs/pubspec_parse @dart-lang/dart-bat
3334
pkgs/source_maps @dart-lang/dart-ecosystem-team

.github/ISSUE_TEMPLATE/process.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
name: "package:process"
3+
about: "Create a bug or file a feature request against package:process."
4+
labels: "package:process"
5+
---

.github/labeler.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@
9696
- changed-files:
9797
- any-glob-to-any-file: 'pkgs/pool/**'
9898

99+
'package:process':
100+
- changed-files:
101+
- any-glob-to-any-file: 'pkgs/process/**'
102+
99103
'package:pub_semver':
100104
- changed-files:
101105
- any-glob-to-any-file: 'pkgs/pub_semver/**'

.github/workflows/benchmark_harness.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
sdk: ${{ matrix.sdk }}
6464
# Node 22 has wasmGC enabled, which allows the wasm tests to run!
6565
- name: Setup Node.js 22
66-
uses: actions/setup-node@v3
66+
uses: actions/setup-node@v4
6767
with:
6868
node-version: 22
6969
- id: install

.github/workflows/coverage.yaml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,7 @@ jobs:
5656
fail-fast: false
5757
matrix:
5858
os: [ubuntu-latest, macos-latest, windows-latest]
59-
sdk: [3.4, dev]
60-
exclude:
61-
# VM service times out on windows before Dart 3.5
62-
# https://github.com/dart-lang/coverage/issues/490
63-
- os: windows-latest
64-
sdk: 3.4
59+
sdk: [3.6, dev]
6560
steps:
6661
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
6762
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
@@ -89,7 +84,7 @@ jobs:
8984
name: Install dependencies
9085
run: dart pub get
9186
- name: Collect and report coverage
92-
run: dart run bin/test_with_coverage.dart --port=9292
87+
run: dart run bin/test_with_coverage.dart
9388
- name: Upload coverage
9489
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b
9590
with:

.github/workflows/process.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: package:process
2+
permissions: read-all
3+
4+
on:
5+
schedule:
6+
# “At 00:00 (UTC) on Sunday.”
7+
- cron: '0 0 * * 0'
8+
push:
9+
branches: [ main ]
10+
paths:
11+
- '.github/workflows/process.yaml'
12+
- 'pkgs/process/**'
13+
pull_request:
14+
branches: [ main ]
15+
paths:
16+
- '.github/workflows/process.yaml'
17+
- 'pkgs/process/**'
18+
19+
defaults:
20+
run:
21+
working-directory: pkgs/process/
22+
23+
jobs:
24+
build:
25+
runs-on: ubuntu-latest
26+
strategy:
27+
matrix:
28+
os: [ubuntu-latest]
29+
sdk: [stable, dev]
30+
steps:
31+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
32+
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
33+
34+
- run: dart pub get
35+
- run: dart format --output=none --set-exit-if-changed .
36+
if: ${{ matrix.sdk == 'stable' }}
37+
- run: dart analyze --fatal-infos
38+
- run: dart test

.github/workflows/test_reflective_loader.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
strategy:
2727
fail-fast: false
2828
matrix:
29-
sdk: [dev, 3.1]
29+
sdk: [dev, 3.5]
3030

3131
steps:
3232
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ don't naturally belong to other topic monorepos (like
3737
| [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![issues](https://img.shields.io/badge/issues-4774bc)][oauth2_issues] | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) |
3838
| [package_config](pkgs/package_config/) | Support for reading and writing Dart Package Configuration files. | [![issues](https://img.shields.io/badge/issues-4774bc)][package_config_issues] | [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) |
3939
| [pool](pkgs/pool/) | Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. | [![issues](https://img.shields.io/badge/issues-4774bc)][pool_issues] | [![pub package](https://img.shields.io/pub/v/pool.svg)](https://pub.dev/packages/pool) |
40+
| [process](pkgs/process/) | A pluggable, mockable process invocation abstraction for Dart. | [![issues](https://img.shields.io/badge/issues-4774bc)][process_issues] | [![pub package](https://img.shields.io/pub/v/process.svg)](https://pub.dev/packages/process) |
4041
| [pub_semver](pkgs/pub_semver/) | Versions and version constraints implementing pub's versioning policy. This is very similar to vanilla semver, with a few corner cases. | [![issues](https://img.shields.io/badge/issues-4774bc)][pub_semver_issues] | [![pub package](https://img.shields.io/pub/v/pub_semver.svg)](https://pub.dev/packages/pub_semver) |
4142
| [pubspec_parse](pkgs/pubspec_parse/) | Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. | [![issues](https://img.shields.io/badge/issues-4774bc)][pubspec_parse_issues] | [![pub package](https://img.shields.io/pub/v/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse) |
4243
| [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![issues](https://img.shields.io/badge/issues-4774bc)][source_map_stack_trace_issues] | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) |
@@ -78,6 +79,7 @@ don't naturally belong to other topic monorepos (like
7879
[oauth2_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2
7980
[package_config_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apackage_config
8081
[pool_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apool
82+
[process_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aprocess
8183
[pub_semver_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apub_semver
8284
[pubspec_parse_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apubspec_parse
8385
[source_map_stack_trace_issues]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace

pkgs/coverage/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
## 1.14.1-wip
2+
3+
- Remove dependency on `package:pubspec_parse`.
4+
5+
## 1.14.0
6+
7+
- Require Dart ^3.6.0
8+
- Partial support for workspace packages in `test_wth_coverage`.
9+
- Deprecate `test_wth_coverage`'s `--package-name` flag, because it doesn't make
10+
sense for workspaces.
11+
- Change the default `--port` to 0, allowing the VM to choose a free port.
12+
113
## 1.13.1
214

315
- Fix a bug where the VM service can be shut down while some coverage

pkgs/coverage/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,30 @@ dart pub global run coverage:format_coverage --packages=.dart_tool/package_confi
4343
For more complicated use cases, where you want to control each of these stages,
4444
see the sections below.
4545

46+
#### Workspaces
47+
48+
package:coverage has partial support for
49+
[workspaces](https://dart.dev/tools/pub/workspaces). You can run
50+
`test_with_coverage` from the root of the workspace to collect coverage for all
51+
the tests in all the subpackages, but you must specify the test directories to
52+
run.
53+
54+
For example, in a workspace with subpackages `pkgs/foo` and `pkgs/bar`, you
55+
could run the following command from the root directory of the workspace:
56+
57+
```
58+
dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test
59+
```
60+
61+
This would output coverage to ./coverage/ as normal. An important caveat is that
62+
the working directory of the tests will be the workspace's root directory. So
63+
this approach won't work if your tests assume that they are being run from the
64+
subpackage directory.
65+
66+
[Full support](https://github.com/dart-lang/tools/issues/2083) for workspaces
67+
will likely be added in a future version. This will mean you won't need to
68+
explicitly specify the test directories: `dart run coverage:test_with_coverage`
69+
4670
#### Collecting coverage from the VM
4771

4872
```

pkgs/coverage/bin/test_with_coverage.dart

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ import 'dart:io';
77

88
import 'package:args/args.dart';
99
import 'package:coverage/src/coverage_options.dart';
10-
import 'package:coverage/src/util.dart'
11-
show StandardOutExtension, extractVMServiceUri;
10+
import 'package:coverage/src/util.dart';
1211
import 'package:meta/meta.dart';
13-
import 'package:package_config/package_config.dart';
1412
import 'package:path/path.dart' as path;
1513

1614
import 'collect_coverage.dart' as collect_coverage;
@@ -19,37 +17,36 @@ import 'format_coverage.dart' as format_coverage;
1917
final _allProcesses = <Process>[];
2018

2119
Future<void> _dartRun(List<String> args,
22-
{void Function(String)? onStdout, String? workingDir}) async {
23-
final process = await Process.start(
24-
Platform.executable,
25-
args,
26-
workingDirectory: workingDir,
27-
);
20+
{required void Function(String) onStdout,
21+
required void Function(String) onStderr}) async {
22+
final process = await Process.start(Platform.executable, args);
2823
_allProcesses.add(process);
29-
final broadStdout = process.stdout.asBroadcastStream();
30-
broadStdout.listen(stdout.add);
31-
if (onStdout != null) {
32-
broadStdout.lines().listen(onStdout);
24+
25+
void listen(
26+
Stream<List<int>> stream, IOSink sink, void Function(String) onLine) {
27+
final broadStream = stream.asBroadcastStream();
28+
broadStream.listen(sink.add);
29+
broadStream.lines().listen(onLine);
3330
}
34-
process.stderr.listen(stderr.add);
31+
32+
listen(process.stdout, stdout, onStdout);
33+
listen(process.stderr, stderr, onStderr);
34+
3535
final result = await process.exitCode;
3636
if (result != 0) {
3737
throw ProcessException(Platform.executable, args, '', result);
3838
}
3939
}
4040

41-
Future<String?> _packageNameFromConfig(String packageDir) async {
42-
final config = await findPackageConfig(Directory(packageDir));
43-
return config?.packageOf(Uri.directory(packageDir))?.name;
41+
void _killSubprocessesAndExit(ProcessSignal signal) {
42+
for (final process in _allProcesses) {
43+
process.kill(signal);
44+
}
45+
exit(1);
4446
}
4547

4648
void _watchExitSignal(ProcessSignal signal) {
47-
signal.watch().listen((sig) {
48-
for (final process in _allProcesses) {
49-
process.kill(sig);
50-
}
51-
exit(1);
52-
});
49+
signal.watch().listen(_killSubprocessesAndExit);
5350
}
5451

5552
ArgParser _createArgParser(CoverageOptions defaultOptions) => ArgParser()
@@ -61,10 +58,10 @@ ArgParser _createArgParser(CoverageOptions defaultOptions) => ArgParser()
6158
..addOption(
6259
'package-name',
6360
help: 'Name of the package to test. '
64-
'Deduced from --package if not provided.',
65-
defaultsTo: defaultOptions.packageName,
61+
'Deduced from --package if not provided. '
62+
'DEPRECATED: use --scope-output',
6663
)
67-
..addOption('port', help: 'VM service port.', defaultsTo: '8181')
64+
..addOption('port', help: 'VM service port. Defaults to using any free port.')
6865
..addOption(
6966
'out',
7067
defaultsTo: defaultOptions.outputDirectory,
@@ -93,13 +90,13 @@ ArgParser _createArgParser(CoverageOptions defaultOptions) => ArgParser()
9390
defaultsTo: defaultOptions.scopeOutput,
9491
help: 'restrict coverage results so that only scripts that start with '
9592
'the provided package path are considered. Defaults to the name of '
96-
'the package under test.')
93+
'the current package (including all subpackages, if this is a '
94+
'workspace).')
9795
..addFlag('help', abbr: 'h', negatable: false, help: 'Show this help.');
9896

9997
class Flags {
10098
Flags(
10199
this.packageDir,
102-
this.packageName,
103100
this.outDir,
104101
this.port,
105102
this.testScript,
@@ -111,7 +108,6 @@ class Flags {
111108
});
112109

113110
final String packageDir;
114-
final String packageName;
115111
final String outDir;
116112
final String port;
117113
final String testScript;
@@ -157,25 +153,23 @@ ${parser.usage}
157153
fail('--package is not a valid directory.');
158154
}
159155

160-
final packageName = (args['package-name'] as String?) ??
161-
await _packageNameFromConfig(packageDir);
162-
if (packageName == null) {
156+
final pubspecPath = getPubspecPath(packageDir);
157+
if (!File(pubspecPath).existsSync()) {
163158
fail(
164-
"Couldn't figure out package name from --package. Make sure this is a "
165-
'package directory, or try passing --package-name explicitly.',
159+
"Couldn't find $pubspecPath. Make sure this command is run in a "
160+
'package directory, or pass --package to explicitly set the directory.',
166161
);
167162
}
168163

169164
return Flags(
170165
packageDir,
171-
packageName,
172-
(args['out'] as String?) ?? path.join(packageDir, 'coverage'),
173-
args['port'] as String,
174-
args['test'] as String,
175-
args['function-coverage'] as bool,
176-
args['branch-coverage'] as bool,
177-
args['scope-output'] as List<String>,
178-
args['fail-under'] as String?,
166+
args.option('out') ?? path.join(packageDir, 'coverage'),
167+
args.option('port') ?? '0',
168+
args.option('test')!,
169+
args.flag('function-coverage'),
170+
args.flag('branch-coverage'),
171+
args.multiOption('scope-output'),
172+
args.option('fail-under'),
179173
rest: args.rest,
180174
);
181175
}
@@ -215,11 +209,19 @@ Future<void> main(List<String> arguments) async {
215209
}
216210
}
217211
},
212+
onStderr: (line) {
213+
if (!serviceUriCompleter.isCompleted) {
214+
if (line.contains('Could not start the VM service')) {
215+
_killSubprocessesAndExit(ProcessSignal.sigkill);
216+
}
217+
}
218+
},
218219
);
219220
final serviceUri = await serviceUriCompleter.future;
220221

221-
final scopes =
222-
flags.scopeOutput.isEmpty ? [flags.packageName] : flags.scopeOutput;
222+
final scopes = flags.scopeOutput.isEmpty
223+
? getAllWorkspaceNames(flags.packageDir)
224+
: flags.scopeOutput;
223225
await collect_coverage.main([
224226
'--wait-paused',
225227
'--resume-isolates',

pkgs/coverage/dart_test.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
tags:
2+
# Tests that start subprocesses, so are slower and can be a bit flaky.
3+
integration:
4+
timeout: 2x
5+
retry: 3

pkgs/coverage/lib/src/collect.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ Future<Map<String, dynamic>> _getAllCoverage(
170170
isolateReport,
171171
includeDart,
172172
functionCoverage,
173+
branchCoverage,
173174
coverableLineCache,
174175
scopedOutput);
175176
allCoverage.addAll(coverage);
@@ -244,6 +245,7 @@ Future<List<Map<String, dynamic>>> _processSourceReport(
244245
SourceReport report,
245246
bool includeDart,
246247
bool functionCoverage,
248+
bool branchCoverage,
247249
Map<String, Set<int>>? coverableLineCache,
248250
Set<String> scopedOutput) async {
249251
final hitMaps = <Uri, HitMap>{};
@@ -262,7 +264,10 @@ Future<List<Map<String, dynamic>>> _processSourceReport(
262264
return scripts[scriptRef];
263265
}
264266

265-
HitMap getHitMap(Uri scriptUri) => hitMaps.putIfAbsent(scriptUri, HitMap.new);
267+
HitMap getHitMap(Uri scriptUri) => hitMaps.putIfAbsent(
268+
scriptUri,
269+
() => HitMap.empty(
270+
functionCoverage: functionCoverage, branchCoverage: branchCoverage));
266271

267272
Future<void> processFunction(FuncRef funcRef) async {
268273
final func = await service.getObject(isolateRef.id!, funcRef.id!) as Func;
@@ -290,8 +295,7 @@ Future<List<Map<String, dynamic>>> _processSourceReport(
290295
return;
291296
}
292297
final hits = getHitMap(Uri.parse(script.uri!));
293-
hits.funcHits ??= <int, int>{};
294-
(hits.funcNames ??= <int, String>{})[line] = funcName;
298+
hits.funcNames![line] = funcName;
295299
}
296300

297301
for (var range in report.ranges!) {
@@ -385,13 +389,12 @@ Future<List<Map<String, dynamic>>> _processSourceReport(
385389
hits.funcHits?.putIfAbsent(line, () => 0);
386390
});
387391

388-
final branchCoverage = range.branchCoverage;
389-
if (branchCoverage != null) {
390-
hits.branchHits ??= <int, int>{};
391-
forEachLine(branchCoverage.hits, (line) {
392+
final branches = range.branchCoverage;
393+
if (branchCoverage && branches != null) {
394+
forEachLine(branches.hits, (line) {
392395
hits.branchHits!.increment(line);
393396
});
394-
forEachLine(branchCoverage.misses, (line) {
397+
forEachLine(branches.misses, (line) {
395398
hits.branchHits!.putIfAbsent(line, () => 0);
396399
});
397400
}

0 commit comments

Comments
 (0)