blob: 6bb7980e905cb9e702533c39050aaccd7e32a923 [file]
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'common/file_filters.dart';
import 'common/package_looping_command.dart';
import 'common/pub_utils.dart';
import 'common/repository_package.dart';
/// A command to run dart fix tests for packages that have a test_fixes
/// directory.
class TestDartFixesCommand extends PackageLoopingCommand {
/// Creates an instance of the test dart fixes command.
TestDartFixesCommand(super.packagesDir, {super.processRunner, super.platform, super.gitDir});
/// A map of the test directory used for each package passed to runForPackage.
@visibleForTesting
final testDirectories = <String, Directory>{};
@override
final String name = 'test-dart-fixes';
@override
final String description =
'Runs the Dart fix tests for all packages.\n\n'
'This command requires "flutter" to be in your path.';
@override
bool shouldIgnoreFile(String path) {
return isRepoLevelNonCodeImpactingFile(path) ||
isNativeCodeFile(path) ||
isPackageSupportFile(path);
}
@override
Future<PackageResult> runForPackage(RepositoryPackage package) async {
// Only run for packages that have a fix_tests directory.
if (!package.dartFixTestDirectory.existsSync()) {
final String localDartFixPath = p.relative(
package.dartFixTestDirectory.path,
from: package.directory.path,
);
return PackageResult.skip('No $localDartFixPath directory.');
}
final Directory testDirectory;
try {
testDirectory = await _createTestDirectory(package);
} catch (error) {
return PackageResult.fail(['Failed to create temporary test directory: $error']);
}
PackageResult result;
try {
final int exitCode = await _runDartFixTests(testDirectory);
result = exitCode == 0
? PackageResult.success()
: PackageResult.fail(['Dart fix tests failed.']);
} catch (error) {
result = PackageResult.fail(['Dart fix tests failed: $error']);
}
if (testDirectory.existsSync()) {
await testDirectory.delete(recursive: true);
}
testDirectories[package.displayName] = testDirectory;
return result;
}
/// Create and prepare a temporary directory in which to run the dart fix
/// tests.
///
/// It is the responsibility of the caller to delete this directory and its
/// contents when done.
static Future<Directory> _createTestDirectory(RepositoryPackage package) async {
final FileSystem fileSystem = package.directory.fileSystem;
final Directory testDirectory = await fileSystem.systemTempDirectory.createTemp();
// Copy from `test_fixes/` to the temp directory.
for (final FileSystemEntity entity in package.dartFixTestDirectory.listSync(recursive: true)) {
final String relativePath = fileSystem.path.relative(
entity.path,
from: package.dartFixTestDirectory.path,
);
final String destPath = fileSystem.path.join(testDirectory.path, relativePath);
if (entity is Directory) {
fileSystem.directory(destPath).createSync(recursive: true);
} else if (entity is File) {
fileSystem.file(destPath).parent.createSync(recursive: true);
entity.copySync(destPath);
}
}
// The pubspec.yaml file to create.
final File targetPubspecFile = fileSystem.file(
fileSystem.path.join(testDirectory.path, 'pubspec.yaml'),
);
final targetYaml =
'''
name: test_fixes
publish_to: "none"
version: 1.0.0
environment:
sdk: ">=2.18.0 <4.0.0"
flutter: ">=3.3.0"
dependencies:
flutter:
sdk: flutter
${package.directory.basename}:
path: ${package.directory.path}
''';
await targetPubspecFile.writeAsString(targetYaml);
return testDirectory;
}
/// Run the dart fix tests for the package in the given temporary directory.
///
/// Resolves with the exit code of the command.
Future<int> _runDartFixTests(Directory testDirectory) async {
// Run flutter pub get in the temp directory to set it up.
final bool success = await runPubGet(RepositoryPackage(testDirectory), processRunner, platform);
if (!success) {
throw Exception('Pub get failed.');
}
// Run dart fix --compare-to-golden in the temp directory.
return processRunner.runAndStream('dart', <String>[
'fix',
'--compare-to-golden',
], workingDir: testDirectory);
}
}