blob: c102bf3117227b079657901becc53385600b0876 [file] [log] [blame]
// 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:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:dartdev/src/experiments.dart';
import 'package:pub/pub.dart';
import '../core.dart';
import '../native_assets.dart';
import '../vm_interop_handler.dart';
/// Implement `dart test`.
///
/// This command largely delegates to `pub run test`.
class TestCommand extends DartdevCommand {
static const String cmdName = 'test';
final bool nativeAssetsExperimentEnabled;
TestCommand({this.nativeAssetsExperimentEnabled = false})
: super(cmdName, 'Run tests for a project.', false);
// This argument parser is here solely to ensure that VM specific flags are
// provided before any command and to provide a more consistent help message
// with the rest of the tool.
@override
ArgParser createArgParser() {
return ArgParser.allowAnything();
}
@override
void printUsage() {
print('''Usage: dart test [arguments]
Note: flags and options for this command are provided by the project's package:test dependency.
If package:test is not included as a dev_dependency in the project's pubspec.yaml, no flags or options will be listed.
Run "${runner!.executableName} help" to see global options.''');
}
@override
FutureOr<int> run() async {
final args = argResults!;
String? nativeAssets;
final packageConfig = await DartNativeAssetsBuilder.ensurePackageConfig(
Directory.current.uri,
);
if (packageConfig != null) {
final runPackageName = await DartNativeAssetsBuilder.findRootPackageName(
Directory.current.uri,
);
if (runPackageName != null) {
final pubspecUri =
await DartNativeAssetsBuilder.findWorkspacePubspec(packageConfig);
final builder = DartNativeAssetsBuilder(
pubspecUri: pubspecUri,
packageConfigUri: packageConfig,
runPackageName: runPackageName,
verbose: verbose,
);
if (!nativeAssetsExperimentEnabled) {
if (await builder.warnOnNativeAssets()) {
return DartdevCommand.errorExitCode;
}
} else {
final assetsYamlFileUri =
await builder.compileNativeAssetsJitYamlFile();
if (assetsYamlFileUri == null) {
log.stderr('Error: Compiling native assets failed.');
return DartdevCommand.errorExitCode;
}
// TODO(https://github.com/dart-lang/sdk/issues/60489): Add a way to
// package:test to explicitly provide the native_assets.yaml path
// instead of copying to the workspace .dart_tool.
final expectedPackageTestLocation =
packageConfig.resolve('native_assets.yaml');
if (expectedPackageTestLocation != assetsYamlFileUri) {
await File.fromUri(assetsYamlFileUri)
.copy(expectedPackageTestLocation.toFilePath());
}
nativeAssets = expectedPackageTestLocation.toFilePath();
}
}
}
try {
final testExecutable = await getExecutableForCommand('test:test',
nativeAssets: nativeAssets);
final argsRestNoExperimentOrSuppressAnalytics = args.rest
.where((e) =>
!e.startsWith('--$experimentFlagName=') &&
e != '--suppress-analytics')
.toList();
log.trace(
'dart $testExecutable ${argsRestNoExperimentOrSuppressAnalytics.join(' ')}');
VmInteropHandler.run(
testExecutable.executable,
argsRestNoExperimentOrSuppressAnalytics,
packageConfigOverride: testExecutable.packageConfig!,
// TODO(bkonyi): remove once DartDev moves to AOT and this flag can be
// provided directly to the process spawned by `dart run` and
// `dart test`.
//
// See https://github.com/dart-lang/sdk/issues/53576
markMainIsolateAsSystemIsolate: true,
);
return 0;
} on CommandResolutionFailedException catch (e) {
if (project.hasPubspecFile) {
print(e.message);
if (e.issue == CommandResolutionIssue.packageNotFound) {
print('You need to add a dev_dependency on package:test.');
print('Try running `dart pub add --dev test`.');
}
} else {
print(
'No pubspec.yaml file found - run this command in your project folder.');
}
if (args.rest.contains('-h') || args.rest.contains('--help')) {
print('');
printUsage();
}
return DartdevCommand.errorExitCode;
}
}
}