Rewrite `getExecutableForCommand` tests to test with an external process. (#4268)
diff --git a/test/embedding/embedding_test.dart b/test/embedding/embedding_test.dart index 20c94d1..faeb17d 100644 --- a/test/embedding/embedding_test.dart +++ b/test/embedding/embedding_test.dart
@@ -14,6 +14,7 @@ import '../golden_file.dart'; import '../test_pub.dart'; import 'ensure_pubspec_resolved.dart'; +import 'get_executable_for_command.dart'; const _commandRunner = 'tool/test-bin/pub_command_runner.dart'; @@ -374,6 +375,7 @@ }); testEnsurePubspecResolved(); + testGetExecutableForCommand(); } String _filter(String input) {
diff --git a/test/embedding/get_executable_for_command.dart b/test/embedding/get_executable_for_command.dart new file mode 100644 index 0000000..de16271 --- /dev/null +++ b/test/embedding/get_executable_for_command.dart
@@ -0,0 +1,563 @@ +// Copyright (c) 2020, 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:path/path.dart' as p; +import 'package:pub/pub.dart'; +import 'package:test/test.dart'; + +import '../descriptor.dart' as d; +import '../test_pub.dart'; +import 'embedding_test.dart'; + +enum ResolutionAttempt { + resolution, + fastPath, + noResolution, +} + +Future<void> testGetExecutable( + String command, + String root, { + bool allowSnapshot = true, + String? executable, + String? packageConfig, + Object? errorMessage, + required ResolutionAttempt resolution, + CommandResolutionIssue? issue, + Map<String, String>? environment, +}) async { + final buffer = StringBuffer(); + await runEmbeddingToBuffer( + [ + 'pub', + '--verbose', + 'get-executable-for-command', + command, + if (allowSnapshot) '--allow-snapshot' else '--no-allow-snapshot', + ], + buffer, + workingDirectory: root, + exitCode: errorMessage == null ? 0 : isNot(0), + environment: environment, + ); + final output = buffer.toString(); + if (errorMessage != null) { + expect(output, errorMessage); + expect(output, contains('Issue: $issue')); + } else { + expect(output, contains(filterUnstableText('Executable: $executable\n'))); + expect( + File(p.join(root, executable)).existsSync(), + true, + reason: '${p.join(root, executable)} should exist', + ); + expect( + output, + contains( + 'Package config: ${filterUnstableText(packageConfig ?? 'No package config')}\n', + ), + ); + } + switch (resolution) { + case ResolutionAttempt.fastPath: + expect(output, contains('[e] FINE: Package Config up to date.')); + case ResolutionAttempt.noResolution: + expect(output, isNot(contains('[e] FINE: Package Config up to date.'))); + expect(output, isNot(contains('MSG : Resolving dependencies'))); + case ResolutionAttempt.resolution: + expect(output, contains('MSG : Resolving dependencies')); + } +} + +void testGetExecutableForCommand() { + group('getExecutableForCommand', () { + test('Finds a direct dart-file without pub get', () async { + await servePackages(); + await d.dir('foo', [ + d.dir('bar', [d.file('bar.dart', 'main() {print(42);}')]), + ]).create(); + final dir = d.path('foo'); + + await testGetExecutable( + 'bar/bar.dart', + dir, + executable: p.join('bar', 'bar.dart'), + resolution: ResolutionAttempt.noResolution, + ); + + await testGetExecutable( + p.join('bar', 'bar.dart'), + dir, + executable: p.join('bar', 'bar.dart'), + resolution: ResolutionAttempt.noResolution, + ); + + await testGetExecutable( + '${p.toUri(dir)}/bar/bar.dart', + dir, + executable: p.join('bar', 'bar.dart'), + resolution: ResolutionAttempt.noResolution, + ); + }); + + test('Looks for file when no pubspec.yaml', () async { + await servePackages(); + await d.dir('foo', [ + d.dir('bar', [d.file('bar.dart', 'main() {print(42);}')]), + ]).create(); + final dir = d.path('foo'); + + await testGetExecutable( + 'bar/m.dart', + dir, + errorMessage: contains('Could not find file `bar/m.dart`'), + issue: CommandResolutionIssue.fileNotFound, + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + p.join('bar', 'm.dart'), + dir, + errorMessage: contains('Could not find file `bar/m.dart`'), + issue: CommandResolutionIssue.fileNotFound, + resolution: ResolutionAttempt.noResolution, + ); + }); + + test('Error message when pubspec is broken', () async { + await servePackages(); + await d.dir('foo', [ + d.pubspec({ + 'name': 'broken name', + }), + ]).create(); + + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'foo': { + 'path': '../foo', + }, + }, + }), + ]).create(); + final dir = d.path(appPath); + await testGetExecutable( + 'foo:app', + dir, + errorMessage: allOf( + contains( + 'Error on line 1, column 9 of ../foo/pubspec.yaml: "name" field must be a valid Dart identifier.', + ), + contains( + '{"name":"broken name","environment":{"sdk":"$defaultSdkConstraint"}}', + ), + ), + issue: CommandResolutionIssue.pubGetFailed, + resolution: ResolutionAttempt.resolution, + ); + }); + + test('Reports file not found if the path looks like a file', () async { + await servePackages(); + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': {'foo': '^1.0.0'}, + }), + d.dir('bin', [ + d.file('myapp.dart', 'main() {print(42);}'), + ]), + ]).create(); + + await servePackages(); + // The solver uses word-wrapping in its error message, so we use \s to + // accommodate. + await testGetExecutable( + 'bar/m.dart', + d.path(appPath), + errorMessage: matches(r'Could not find file `bar/m.dart`'), + issue: CommandResolutionIssue.fileNotFound, + resolution: ResolutionAttempt.noResolution, + ); + }); + + test('Reports parse failure', () async { + await servePackages(); + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + }), + ]).create(); + await testGetExecutable( + '::', + d.path(appPath), + errorMessage: contains(r'cannot contain multiple ":"'), + issue: CommandResolutionIssue.parseError, + resolution: ResolutionAttempt.resolution, + ); + }); + + test('Reports compilation failure', () async { + await servePackages(); + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + }), + d.dir('bin', [ + d.file('foo.dart', 'main() {'), + ]), + ]).create(); + + await servePackages(); + // The solver uses word-wrapping in its error message, so we use \s to + // accommodate. + await testGetExecutable( + ':foo', + d.path(appPath), + errorMessage: matches(r'foo.dart:1:8:'), + issue: CommandResolutionIssue.compilationFailed, + resolution: ResolutionAttempt.resolution, + ); + }); + + test('Finds files', () async { + final server = await servePackages(); + server.serve( + 'foo', + '1.0.0', + deps: { + 'transitive': {'hosted': globalServer.url}, + }, + contents: [ + d.dir('bin', [ + d.file('foo.dart', 'main() {print(42);}'), + d.file('tool.dart', 'main() {print(42);}'), + ]), + ], + ); + + server.serve( + 'transitive', + '1.0.0', + contents: [ + d.dir('bin', [d.file('transitive.dart', 'main() {print(42);}')]), + ], + ); + + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'foo': { + 'hosted': globalServer.url, + 'version': '^1.0.0', + }, + }, + }), + d.dir('bin', [ + d.file('myapp.dart', 'main() {print(42);}'), + d.file('tool.dart', 'main() {print(42);}'), + ]), + ]).create(); + final dir = d.path(appPath); + + await testGetExecutable( + 'myapp', + dir, + executable: p.join( + '.dart_tool', + 'pub', + 'bin', + 'myapp', + 'myapp.dart-3.1.2+3.snapshot', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.resolution, + ); + await testGetExecutable( + 'myapp:myapp', + dir, + executable: p.join( + '.dart_tool', + 'pub', + 'bin', + 'myapp', + 'myapp.dart-3.1.2+3.snapshot', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + ':myapp', + dir, + executable: p.join( + '.dart_tool', + 'pub', + 'bin', + 'myapp', + 'myapp.dart-3.1.2+3.snapshot', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + ':tool', + dir, + executable: p.join( + '.dart_tool', + 'pub', + 'bin', + 'myapp', + 'tool.dart-3.1.2+3.snapshot', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'foo', + dir, + allowSnapshot: false, + executable: p.join( + d.sandbox, + d.hostedCachePath(), + 'foo-1.0.0', + 'bin', + 'foo.dart', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'foo', + dir, + executable: p.join( + '.dart_tool', + 'pub', + 'bin', + 'foo', + 'foo.dart-3.1.2+3.snapshot', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'foo:tool', + dir, + allowSnapshot: false, + executable: p.join( + d.sandbox, + d.hostedCachePath(), + 'foo-1.0.0', + 'bin', + 'tool.dart', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'foo:tool', + dir, + executable: p.join( + '.dart_tool', + 'pub', + 'bin', + 'foo', + 'tool.dart-3.1.2+3.snapshot', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'unknown:tool', + dir, + errorMessage: contains( + 'Could not find package `unknown` or file `unknown:tool`', + ), + issue: CommandResolutionIssue.packageNotFound, + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'foo:unknown', + dir, + errorMessage: contains( + 'Could not find `bin/unknown.dart` in package `foo`.', + ), + issue: CommandResolutionIssue.noBinaryFound, + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'unknownTool', + dir, + errorMessage: contains( + 'Could not find package `unknownTool` or file `unknownTool`', + ), + issue: CommandResolutionIssue.packageNotFound, + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'transitive', + dir, + executable: p.join( + d.sandbox, + d.hostedCachePath(port: globalServer.port), + 'transitive-1.0.0', + 'bin', + 'transitive.dart', + ), + allowSnapshot: false, + packageConfig: p.join('.dart_tool', 'package_config.json'), + resolution: ResolutionAttempt.noResolution, + ); + }); + + test('works with workspace', () async { + final server = await servePackages(); + server.serve( + 'foo', + '1.0.0', + contents: [ + d.dir('bin', [ + d.file('foo.dart', 'main() {print(42);}'), + d.file('tool.dart', 'main() {print(42);}'), + ]), + ], + ); + + await d.dir(appPath, [ + d.libPubspec( + 'myapp', + '1.2.3', + deps: { + 'a': 'any', + 'foo': { + 'hosted': globalServer.url, + 'version': '^1.0.0', + }, + }, + extras: { + 'workspace': ['pkgs/a', 'pkgs/b'], + }, + sdk: '^3.5.0-0', + ), + d.dir('bin', [ + d.file('myapp.dart', 'main() {print(42);}'), + d.file('tool.dart', 'main() {print(42);}'), + ]), + d.dir('pkgs', [ + d.dir('a', [ + d.libPubspec( + 'a', + '1.0.0', + resolutionWorkspace: true, + ), + d.dir('bin', [ + d.file('a.dart', 'main() {print(42);}'), + d.file('tool.dart', 'main() {print(42);}'), + ]), + ]), + d.dir('b', [ + d.libPubspec( + 'b', + '1.0.0', + resolutionWorkspace: true, + ), + d.dir('bin', [ + d.file('b.dart', 'main() {print(42);}'), + d.file('tool.dart', 'main() {print(42);}'), + ]), + ]), + ]), + ]).create(); + await pubGet( + environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, + ); + await testGetExecutable( + 'myapp', + p.join(d.sandbox, appPath, 'pkgs', 'a'), + executable: p.join( + '..', + '..', + '.dart_tool', + 'pub', + 'bin', + 'myapp', + 'myapp.dart-3.5.0.snapshot', + ), + environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, + packageConfig: p.join('..', '..', '.dart_tool', 'package_config.json'), + // TODO(sigurdm): Should be fast-path + resolution: ResolutionAttempt.resolution, + ); + + await testGetExecutable( + 'a', + p.join(d.sandbox, appPath, 'pkgs'), + executable: p.join( + d.sandbox, + appPath, + 'pkgs', + 'a', + 'bin', + 'a.dart', + ), + allowSnapshot: false, + packageConfig: p.join('..', '.dart_tool', 'package_config.json'), + environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, + // TODO(sigurdm): Should be fast-path + resolution: ResolutionAttempt.resolution, + ); + await testGetExecutable( + 'b:tool', + p.join(d.sandbox, appPath), + allowSnapshot: false, + executable: p.join( + d.sandbox, + appPath, + 'pkgs', + 'b', + 'bin', + 'tool.dart', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + 'foo', + p.join(d.sandbox, appPath), + allowSnapshot: false, + executable: p.join( + d.sandbox, + d.hostedCachePath(), + 'foo-1.0.0', + 'bin', + 'foo.dart', + ), + packageConfig: p.join('.dart_tool', 'package_config.json'), + environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, + resolution: ResolutionAttempt.noResolution, + ); + await testGetExecutable( + ':tool', + p.join(d.sandbox, appPath, 'pkgs', 'a'), + allowSnapshot: false, + executable: p.join( + d.sandbox, + appPath, + 'pkgs', + 'a', + 'bin', + 'tool.dart', + ), + packageConfig: p.join('..', '..', '.dart_tool', 'package_config.json'), + environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, + // TODO(sigurdm): Should be fast-path + resolution: ResolutionAttempt.resolution, + ); + }); + }); +}
diff --git a/test/embedding/get_executable_for_command_test.dart b/test/embedding/get_executable_for_command_test.dart deleted file mode 100644 index 5b07871..0000000 --- a/test/embedding/get_executable_for_command_test.dart +++ /dev/null
@@ -1,494 +0,0 @@ -// Copyright (c) 2020, 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:path/path.dart' show separator; -import 'package:path/path.dart' as p; -import 'package:pub/pub.dart'; -import 'package:pub/src/log.dart' as log; - -import 'package:test/test.dart'; - -import '../descriptor.dart' as d; -import '../test_pub.dart'; - -Future<void> testGetExecutable( - String command, - String root, { - bool allowSnapshot = true, - Object? executable, - String? packageConfig, - Object? errorMessage, - CommandResolutionIssue? issue, -}) async { - final cachePath = getPubTestEnvironment()['PUB_CACHE']; - final oldVerbosity = log.verbosity; - log.verbosity = log.Verbosity.none; - if (executable == null) { - expect( - () => getExecutableForCommand( - command, - root: root, - pubCacheDir: cachePath, - allowSnapshot: allowSnapshot, - ), - throwsA( - isA<CommandResolutionFailedException>() - .having((e) => e.message, 'message', errorMessage) - .having((e) => e.issue, 'issue', issue), - ), - ); - } else { - final e = await getExecutableForCommand( - command, - root: root, - pubCacheDir: cachePath, - allowSnapshot: allowSnapshot, - ); - expect( - e, - isA<DartExecutableWithPackageConfig>() - .having((e) => e.executable, 'executable', executable) - .having((e) => e.packageConfig, 'packageConfig', packageConfig), - ); - expect(File(p.join(root, e.executable)).existsSync(), true); - log.verbosity = oldVerbosity; - } -} - -Future<void> main() async { - test('Finds a direct dart-file without pub get', () async { - await d.dir('foo', [ - d.dir('bar', [d.file('bar.dart', 'main() {print(42);}')]), - ]).create(); - final dir = d.path('foo'); - - await testGetExecutable( - 'bar/bar.dart', - dir, - executable: p.join('bar', 'bar.dart'), - ); - - await testGetExecutable( - p.join('bar', 'bar.dart'), - dir, - executable: p.join('bar', 'bar.dart'), - ); - - await testGetExecutable( - '${p.toUri(dir)}/bar/bar.dart', - dir, - executable: p.join('bar', 'bar.dart'), - ); - }); - - test('Looks for file when no pubspec.yaml', () async { - await d.dir('foo', [ - d.dir('bar', [d.file('bar.dart', 'main() {print(42);}')]), - ]).create(); - final dir = d.path('foo'); - - await testGetExecutable( - 'bar/m.dart', - dir, - errorMessage: contains('Could not find file `bar/m.dart`'), - issue: CommandResolutionIssue.fileNotFound, - ); - await testGetExecutable( - p.join('bar', 'm.dart'), - dir, - errorMessage: contains('Could not find file `bar${separator}m.dart`'), - issue: CommandResolutionIssue.fileNotFound, - ); - }); - - test('Error message when pubspec is broken', () async { - await d.dir('foo', [ - d.pubspec({ - 'name': 'broken name', - }), - ]).create(); - - await d.dir(appPath, [ - d.pubspec({ - 'name': 'myapp', - 'environment': {'sdk': '^$_currentVersion'}, - 'dependencies': { - 'foo': { - 'path': '../foo', - }, - }, - }), - ]).create(); - final dir = d.path(appPath); - await testGetExecutable( - 'foo:app', - dir, - errorMessage: allOf( - contains( - 'Error on line 1, column 9 of ${d.sandbox}${p.separator}foo${p.separator}pubspec.yaml: "name" field must be a valid Dart identifier.', - ), - contains( - '{"name":"broken name","environment":{"sdk":"$defaultSdkConstraint"}}', - ), - ), - issue: CommandResolutionIssue.pubGetFailed, - ); - }); - - test('Reports file not found if the path looks like a file', () async { - await d.dir(appPath, [ - d.pubspec({ - 'name': 'myapp', - 'environment': {'sdk': '^$_currentVersion'}, - 'dependencies': {'foo': '^1.0.0'}, - }), - d.dir('bin', [ - d.file('myapp.dart', 'main() {print(42);}'), - ]), - ]).create(); - - await servePackages(); - // The solver uses word-wrapping in its error message, so we use \s to - // accommodate. - await testGetExecutable( - 'bar/m.dart', - d.path(appPath), - errorMessage: matches(r'Could not find file `bar/m.dart`'), - issue: CommandResolutionIssue.fileNotFound, - ); - }); - - test('Reports parse failure', () async { - await d.dir(appPath, [ - d.pubspec({ - 'name': 'myapp', - 'environment': {'sdk': '^$_currentVersion'}, - }), - ]).create(); - await testGetExecutable( - '::', - d.path(appPath), - errorMessage: contains(r'cannot contain multiple ":"'), - issue: CommandResolutionIssue.parseError, - ); - }); - - test('Reports compilation failure', () async { - await d.dir(appPath, [ - d.pubspec({ - 'name': 'myapp', - 'environment': {'sdk': '^$_currentVersion'}, - }), - d.dir('bin', [ - d.file('foo.dart', 'main() {'), - ]), - ]).create(); - - await servePackages(); - // The solver uses word-wrapping in its error message, so we use \s to - // accommodate. - await testGetExecutable( - ':foo', - d.path(appPath), - errorMessage: matches(r'foo.dart:1:8:'), - issue: CommandResolutionIssue.compilationFailed, - ); - }); - - test('Finds files', () async { - final server = await servePackages(); - server.serve( - 'foo', - '1.0.0', - pubspec: { - 'environment': {'sdk': '^$_currentVersion'}, - }, - deps: { - 'transitive': {'hosted': globalServer.url}, - }, - contents: [ - d.dir('bin', [ - d.file('foo.dart', 'main() {print(42);}'), - d.file('tool.dart', 'main() {print(42);}'), - ]), - ], - ); - - server.serve( - 'transitive', - '1.0.0', - pubspec: { - 'environment': {'sdk': '^$_currentVersion'}, - }, - contents: [ - d.dir('bin', [d.file('transitive.dart', 'main() {print(42);}')]), - ], - ); - - await d.dir(appPath, [ - d.pubspec({ - 'name': 'myapp', - 'environment': {'sdk': '^$_currentVersion'}, - 'dependencies': { - 'foo': { - 'hosted': globalServer.url, - 'version': '^1.0.0', - }, - }, - }), - d.dir('bin', [ - d.file('myapp.dart', 'main() {print(42);}'), - d.file('tool.dart', 'main() {print(42);}'), - ]), - ]).create(); - final dir = d.path(appPath); - - await testGetExecutable( - 'myapp', - dir, - executable: p.join( - '.dart_tool', - 'pub', - 'bin', - 'myapp', - 'myapp.dart-$_currentVersion.snapshot', - ), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'myapp:myapp', - dir, - executable: p.join( - '.dart_tool', - 'pub', - 'bin', - 'myapp', - 'myapp.dart-$_currentVersion.snapshot', - ), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - ':myapp', - dir, - executable: p.join( - '.dart_tool', - 'pub', - 'bin', - 'myapp', - 'myapp.dart-$_currentVersion.snapshot', - ), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - ':tool', - dir, - executable: p.join( - '.dart_tool', - 'pub', - 'bin', - 'myapp', - 'tool.dart-$_currentVersion.snapshot', - ), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'foo', - dir, - allowSnapshot: false, - executable: endsWith('foo-1.0.0${separator}bin${separator}foo.dart'), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'foo', - dir, - executable: - '.dart_tool${separator}pub${separator}bin${separator}foo${separator}foo.dart-$_currentVersion.snapshot', - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'foo:tool', - dir, - allowSnapshot: false, - executable: endsWith('foo-1.0.0${separator}bin${separator}tool.dart'), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'foo:tool', - dir, - executable: - '.dart_tool${separator}pub${separator}bin${separator}foo${separator}tool.dart-$_currentVersion.snapshot', - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'unknown:tool', - dir, - errorMessage: 'Could not find package `unknown` or file `unknown:tool`', - issue: CommandResolutionIssue.packageNotFound, - ); - await testGetExecutable( - 'foo:unknown', - dir, - errorMessage: - 'Could not find `bin${separator}unknown.dart` in package `foo`.', - issue: CommandResolutionIssue.noBinaryFound, - ); - await testGetExecutable( - 'unknownTool', - dir, - errorMessage: - 'Could not find package `unknownTool` or file `unknownTool`', - issue: CommandResolutionIssue.packageNotFound, - ); - await testGetExecutable( - 'transitive', - dir, - executable: p.join( - d.sandbox, - d.hostedCachePath(port: globalServer.port), - 'transitive-1.0.0', - 'bin', - 'transitive.dart', - ), - allowSnapshot: false, - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - }); - - test('works with workspace', () async { - final server = await servePackages(); - server.serve( - 'foo', - '1.0.0', - contents: [ - d.dir('bin', [ - d.file('foo.dart', 'main() {print(42);}'), - d.file('tool.dart', 'main() {print(42);}'), - ]), - ], - ); - - await d.dir(appPath, [ - d.libPubspec( - 'myapp', - '1.2.3', - deps: { - 'a': 'any', - 'foo': { - 'hosted': globalServer.url, - 'version': '^1.0.0', - }, - }, - extras: { - 'workspace': ['pkgs/a', 'pkgs/b'], - }, - sdk: '^3.5.0-0', - ), - d.dir('bin', [ - d.file('myapp.dart', 'main() {print(42);}'), - d.file('tool.dart', 'main() {print(42);}'), - ]), - d.dir('pkgs', [ - d.dir('a', [ - d.libPubspec( - 'a', - '1.0.0', - resolutionWorkspace: true, - ), - d.dir('bin', [ - d.file('a.dart', 'main() {print(42);}'), - d.file('tool.dart', 'main() {print(42);}'), - ]), - ]), - d.dir('b', [ - d.libPubspec( - 'b', - '1.0.0', - resolutionWorkspace: true, - ), - d.dir('bin', [ - d.file('b.dart', 'main() {print(42);}'), - d.file('tool.dart', 'main() {print(42);}'), - ]), - ]), - ]), - ]).create(); - await pubGet( - environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'}, - ); - - await testGetExecutable( - 'myapp', - p.join(d.sandbox, appPath, 'pkgs', 'a'), - executable: p.join( - '..', - '..', - '.dart_tool', - 'pub', - 'bin', - 'myapp', - 'myapp.dart-$_currentVersion.snapshot', - ), - packageConfig: p.join('..', '..', '.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'a', - p.join(d.sandbox, appPath, 'pkgs'), - executable: p.join( - d.sandbox, - appPath, - 'pkgs', - 'a', - 'bin', - 'a.dart', - ), - allowSnapshot: false, - packageConfig: p.join('..', '.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'b:tool', - p.join(d.sandbox, appPath), - allowSnapshot: false, - executable: p.join( - d.sandbox, - appPath, - 'pkgs', - 'b', - 'bin', - 'tool.dart', - ), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - 'foo', - p.join(d.sandbox, appPath), - allowSnapshot: false, - executable: p.join( - d.sandbox, - d.hostedCachePath(), - 'foo-1.0.0', - 'bin', - 'foo.dart', - ), - packageConfig: p.join('.dart_tool', 'package_config.json'), - ); - await testGetExecutable( - ':tool', - p.join(d.sandbox, appPath, 'pkgs', 'a'), - allowSnapshot: false, - executable: p.join( - d.sandbox, - appPath, - 'pkgs', - 'a', - 'bin', - 'tool.dart', - ), - packageConfig: p.join('..', '..', '.dart_tool', 'package_config.json'), - ); - }); -} - -final _currentVersion = Platform.version.split(' ').first;
diff --git a/tool/test-bin/pub_command_runner.dart b/tool/test-bin/pub_command_runner.dart index 47dffd5..2665a7b 100644 --- a/tool/test-bin/pub_command_runner.dart +++ b/tool/test-bin/pub_command_runner.dart
@@ -29,6 +29,41 @@ } } +/// A command for testing the [getExecutableForCommand] functionality. +class GetExecutableForCommandCommand extends PubCommand { + @override + String get name => 'get-executable-for-command'; + + @override + String get description => + 'Finds the package config and executable given a command'; + + @override + bool get hidden => true; + + GetExecutableForCommandCommand() { + argParser.addFlag('allow-snapshot'); + } + + @override + Future<void> runProtected() async { + try { + final result = await getExecutableForCommand( + argResults.rest[0], + allowSnapshot: argResults.flag('allow-snapshot'), + ); + log.message('Executable: ${result.executable}'); + log.message( + 'Package config: ${result.packageConfig ?? 'No package config'}', + ); + } on CommandResolutionFailedException catch (e) { + log.message('Error: ${e.message}'); + log.message('Issue: ${e.issue}'); + overrideExitCode(-1); + } + } +} + /// A command for testing the [ensurePubspecResolved] functionality. class EnsurePubspecResolvedCommand extends PubCommand { @override @@ -81,7 +116,8 @@ isVerbose: () => _results.flag('verbose'), ) ..addSubcommand(ThrowingCommand()) - ..addSubcommand(EnsurePubspecResolvedCommand()), + ..addSubcommand(EnsurePubspecResolvedCommand()) + ..addSubcommand(GetExecutableForCommandCommand()), ); addCommand(RunCommand()); argParser.addFlag('verbose');