From cd8e74d4c9d4c09d79d5fa9cdd15d914fb608e12 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 4 Sep 2025 23:39:14 +0000 Subject: [PATCH 1/4] Support --version in pub workspace Closes #2535 Add a check for the `workspace_ref.json` file in place of the `pubspec.lock` file that exists for single package pub solutions. When the workspace ref exists, follow it and read the `package_graph.json` file from the workspace root. --- pkgs/test_core/CHANGELOG.md | 1 + pkgs/test_core/lib/src/runner/version.dart | 137 +++++++++++++-------- 2 files changed, 89 insertions(+), 49 deletions(-) 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..350fc89a3 100644 --- a/pkgs/test_core/lib/src/runner/version.dart +++ b/pkgs/test_core/lib/src/runner/version.dart @@ -2,60 +2,99 @@ // 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 workspaceRefPath = p.join('.dart_tool', 'pub', 'workspace_ref.json'); + final workspaceRefFile = File(workspaceRefPath); + if (!workspaceRefFile.existsSync()) return null; + final ref = jsonDecode(workspaceRefFile.readAsStringSync()); + if (ref is! Map) return null; + final relativeRoot = ref['workspaceRoot']; + if (relativeRoot is! String) return null; + final packageGraphPath = p.normalize( + p.join( + '.dart_tool', + 'pub', + relativeRoot, + '.dart_tool', + 'package_graph.json', + ), + ); + final packageGraphFile = File(packageGraphPath); + final packageGraph = jsonDecode(packageGraphFile.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; + } +} From 57f28399ec1b0523a44cb41081e65176d6dfc3b3 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 5 Sep 2025 18:32:01 +0000 Subject: [PATCH 2/4] Store pub directory for reuse --- pkgs/test_core/lib/src/runner/version.dart | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/pkgs/test_core/lib/src/runner/version.dart b/pkgs/test_core/lib/src/runner/version.dart index 350fc89a3..05054ce9a 100644 --- a/pkgs/test_core/lib/src/runner/version.dart +++ b/pkgs/test_core/lib/src/runner/version.dart @@ -17,24 +17,17 @@ final String? testVersion = _readWorkspaceRef() ?? _readPubspecLock(); String? _readWorkspaceRef() { try { - final workspaceRefPath = p.join('.dart_tool', 'pub', 'workspace_ref.json'); - final workspaceRefFile = File(workspaceRefPath); + final pubDirectory = p.join('.dart_tool', 'pub'); + final workspaceRefFile = File(p.join(pubDirectory, 'workspace_ref.json')); if (!workspaceRefFile.existsSync()) return null; - final ref = jsonDecode(workspaceRefFile.readAsStringSync()); - if (ref is! Map) return null; - final relativeRoot = ref['workspaceRoot']; + 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( - '.dart_tool', - 'pub', - relativeRoot, - '.dart_tool', - 'package_graph.json', - ), + p.join(pubDirectory, relativeRoot, '.dart_tool', 'package_graph.json'), ); - final packageGraphFile = File(packageGraphPath); - final packageGraph = jsonDecode(packageGraphFile.readAsStringSync()); + final packageGraph = jsonDecode(File(packageGraphPath).readAsStringSync()); if (packageGraph is! Map) return null; final packages = packageGraph['packages']; if (packages is! List) return null; From 3e805504060531d5fd2ebdf2cb4dd8ad337e1d07 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sat, 6 Sep 2025 00:06:14 +0000 Subject: [PATCH 3/4] Remove non-null version in a test The test had been passing because the `testVersion` variable was null in the pub workspace which matched the behavior of the test_descriptor package within the test.. --- pkgs/test/test/runner/json_reporter_utils.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/test/test/runner/json_reporter_utils.dart b/pkgs/test/test/runner/json_reporter_utils.dart index 7416c0a4a..b960c94fe 100644 --- a/pkgs/test/test/runner/json_reporter_utils.dart +++ b/pkgs/test/test/runner/json_reporter_utils.dart @@ -41,7 +41,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)); From 31effd2f59f2acb9fc445c17c75f7f5079f94bc6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sat, 6 Sep 2025 00:16:44 +0000 Subject: [PATCH 4/4] Unused import --- pkgs/test/test/runner/json_reporter_utils.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/test/test/runner/json_reporter_utils.dart b/pkgs/test/test/runner/json_reporter_utils.dart index b960c94fe..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