diff --git a/pkgs/test/test/runner/json_reporter_utils.dart b/pkgs/test/test/runner/json_reporter_utils.dart index 7416c0a4a..eec2808aa 100644 --- a/pkgs/test/test/runner/json_reporter_utils.dart +++ b/pkgs/test/test/runner/json_reporter_utils.dart @@ -6,7 +6,6 @@ import 'dart:convert'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import 'package:test_core/src/runner/version.dart'; import 'package:test_descriptor/test_descriptor.dart' as d; /// Asserts that the outputs from running tests with a JSON reporter match the @@ -41,7 +40,8 @@ Future expectJsonReport( final start = { 'type': 'start', 'protocolVersion': '0.1.1', - 'runnerVersion': testVersion, + // Runner version cannot be read in the synthetic package + 'runnerVersion': null, 'pid': testPid, }; expect(decoded.first, equals(start)); diff --git a/pkgs/test_core/CHANGELOG.md b/pkgs/test_core/CHANGELOG.md index 74d7fb713..69a33623a 100644 --- a/pkgs/test_core/CHANGELOG.md +++ b/pkgs/test_core/CHANGELOG.md @@ -3,6 +3,7 @@ * Restrict to latest version of analyzer package. * Require Dart 3.7 * Add `--coverage-path` and `--branch-coverage` options to `dart test`. +* Add support for reading test package version within pub workspaces. ## 0.6.12 diff --git a/pkgs/test_core/lib/src/runner/version.dart b/pkgs/test_core/lib/src/runner/version.dart index aff679111..05054ce9a 100644 --- a/pkgs/test_core/lib/src/runner/version.dart +++ b/pkgs/test_core/lib/src/runner/version.dart @@ -2,60 +2,92 @@ // 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:convert'; import 'dart:io'; +import 'package:collection/collection.dart'; +import 'package:path/path.dart' as p; import 'package:yaml/yaml.dart'; /// The version number of the test runner, or `null` if it couldn't be loaded. /// /// This is a semantic version, optionally followed by a space and additional /// data about its source. -final String? testVersion = - (() { - dynamic lockfile; - try { - lockfile = loadYaml(File('pubspec.lock').readAsStringSync()); - } on FormatException catch (_) { - return null; - } on IOException catch (_) { - return null; - } - - if (lockfile is! Map) return null; - var packages = lockfile['packages']; - if (packages is! Map) return null; - var package = packages['test']; - if (package is! Map) return null; - - var source = package['source']; - if (source is! String) return null; - - switch (source) { - case 'hosted': - var version = package['version']; - return (version is String) ? version : null; - - case 'git': - var version = package['version']; - if (version is! String) return null; - var description = package['description']; - if (description is! Map) return null; - var ref = description['resolved-ref']; - if (ref is! String) return null; - - return '$version (${ref.substring(0, 7)})'; - - case 'path': - var version = package['version']; - if (version is! String) return null; - var description = package['description']; - if (description is! Map) return null; - var path = description['path']; - if (path is! String) return null; - - return '$version (from $path)'; - - default: - return null; - } - })(); +final String? testVersion = _readWorkspaceRef() ?? _readPubspecLock(); + +String? _readWorkspaceRef() { + try { + final pubDirectory = p.join('.dart_tool', 'pub'); + final workspaceRefFile = File(p.join(pubDirectory, 'workspace_ref.json')); + if (!workspaceRefFile.existsSync()) return null; + final workspaceRef = jsonDecode(workspaceRefFile.readAsStringSync()); + if (workspaceRef is! Map) return null; + final relativeRoot = workspaceRef['workspaceRoot']; + if (relativeRoot is! String) return null; + final packageGraphPath = p.normalize( + p.join(pubDirectory, relativeRoot, '.dart_tool', 'package_graph.json'), + ); + final packageGraph = jsonDecode(File(packageGraphPath).readAsStringSync()); + if (packageGraph is! Map) return null; + final packages = packageGraph['packages']; + if (packages is! List) return null; + final testPackage = packages.firstWhereOrNull( + (p) => p is Map && p['name'] == 'test', + ); + if (testPackage == null) return null; + return (testPackage as Map)['version'] as String; + } on FormatException { + return null; + } on IOException { + return null; + } +} + +String? _readPubspecLock() { + dynamic lockfile; + try { + lockfile = loadYaml(File('pubspec.lock').readAsStringSync()); + } on FormatException { + return null; + } on IOException { + return null; + } + + if (lockfile is! Map) return null; + var packages = lockfile['packages']; + if (packages is! Map) return null; + var package = packages['test']; + if (package is! Map) return null; + + var source = package['source']; + if (source is! String) return null; + + switch (source) { + case 'hosted': + var version = package['version']; + return (version is String) ? version : null; + + case 'git': + var version = package['version']; + if (version is! String) return null; + var description = package['description']; + if (description is! Map) return null; + var ref = description['resolved-ref']; + if (ref is! String) return null; + + return '$version (${ref.substring(0, 7)})'; + + case 'path': + var version = package['version']; + if (version is! String) return null; + var description = package['description']; + if (description is! Map) return null; + var path = description['path']; + if (path is! String) return null; + + return '$version (from $path)'; + + default: + return null; + } +}