Files
packages/script/tool/test/common/package_state_utils_test.dart
stuartmorgan 9382257ce7 [ci] Move tool_runner.sh (#6038)
`script/tool_runner.sh` has only been intended for CI usage for quite a while, but it still lives in a prominent non-CI location which has been a source of confusion for developers (e.g., people looking at how CI is running things, and reasonably assuming that since the script isn't in a CI-specific location, it's for general use). While running it for simple cases works, it conflicts with any package selection, which is common thing to want to control when running locally.

This makes the following changes:
- Move the script into the .ci directory
- Adds explicit comments that it's not designed for local use, with a pointer to the corresponding local command
- Removes a stale reference to external-to-the-repo use of tool_runner.sh, as that usage no longer exists
  - Also consolidates and updates the links to the external scripts
- Updates a couple of CONTRIBUTING.md comments that still said to run tool_runner.sh
- Opportunistically cleans up some tooling references to .cirrus.yml, found while cleaning up comments in tool_runner.sh and checking for other references.
2024-02-06 19:31:46 +00:00

458 lines
16 KiB
Dart

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/common/git_version_finder.dart';
import 'package:flutter_plugin_tools/src/common/package_state_utils.dart';
import 'package:test/fake.dart';
import 'package:test/test.dart';
import '../util.dart';
void main() {
late FileSystem fileSystem;
late Directory packagesDir;
setUp(() {
fileSystem = MemoryFileSystem();
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
});
group('checkPackageChangeState', () {
test('reports version change needed for code changes', () async {
final RepositoryPackage package =
createFakePackage('a_package', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_package/lib/plugin.dart',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_package');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test('handles trailing slash on package path', () async {
final RepositoryPackage package =
createFakePackage('a_package', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_package/lib/plugin.dart',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_package/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
expect(state.hasChangelogChange, false);
});
test('does not flag version- and changelog-change-exempt changes',
() async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/CHANGELOG.md',
// Dev-facing docs.
'packages/a_plugin/CONTRIBUTING.md',
// Analysis.
'packages/a_plugin/example/android/lint-baseline.xml',
// Tests.
'packages/a_plugin/example/android/src/androidTest/foo/bar/FooTest.java',
'packages/a_plugin/example/ios/RunnerTests/Foo.m',
'packages/a_plugin/example/ios/RunnerUITests/info.plist',
// Pigeon input.
'packages/a_plugin/pigeons/messages.dart',
// Test scripts.
'packages/a_plugin/run_tests.sh',
'packages/a_plugin/dart_test.yaml',
// Tools.
'packages/a_plugin/tool/a_development_tool.dart',
// Example build files.
'packages/a_plugin/example/android/build.gradle',
'packages/a_plugin/example/android/gradle/wrapper/gradle-wrapper.properties',
'packages/a_plugin/example/ios/Runner.xcodeproj/project.pbxproj',
'packages/a_plugin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme',
'packages/a_plugin/example/linux/flutter/CMakeLists.txt',
'packages/a_plugin/example/macos/Podfile',
'packages/a_plugin/example/macos/Runner.xcodeproj/project.pbxproj',
'packages/a_plugin/example/macos/Runner.xcworkspace/contents.xcworkspacedata',
'packages/a_plugin/example/windows/CMakeLists.txt',
'packages/a_plugin/example/pubspec.yaml',
// Pigeon platform tests, which have an unusual structure.
'packages/a_plugin/platform_tests/shared_test_plugin_code/lib/integration_tests.dart',
'packages/a_plugin/platform_tests/test_plugin/windows/test_plugin.cpp',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, false);
expect(state.needsChangelogChange, false);
expect(state.hasChangelogChange, true);
});
test('only considers a root "tool" folder to be special', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/lib/foo/tool/tool_thing.dart',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test('requires a version change for example/lib/main.dart', () async {
final RepositoryPackage package = createFakePlugin(
'a_plugin', packagesDir,
extraFiles: <String>['example/lib/main.dart']);
const List<String> changedFiles = <String>[
'packages/a_plugin/example/lib/main.dart',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test('requires a version change for example/main.dart', () async {
final RepositoryPackage package = createFakePlugin(
'a_plugin', packagesDir,
extraFiles: <String>['example/main.dart']);
const List<String> changedFiles = <String>[
'packages/a_plugin/example/main.dart',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test('requires a version change for example readme.md', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/example/README.md',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test('requires a version change for example/example.md', () async {
final RepositoryPackage package = createFakePlugin(
'a_plugin', packagesDir,
extraFiles: <String>['example/example.md']);
const List<String> changedFiles = <String>[
'packages/a_plugin/example/example.md',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test(
'requires a changelog change but no version change for '
'lower-priority examples when example.md is present', () async {
final RepositoryPackage package = createFakePlugin(
'a_plugin', packagesDir,
extraFiles: <String>['example/example.md']);
const List<String> changedFiles = <String>[
'packages/a_plugin/example/lib/main.dart',
'packages/a_plugin/example/main.dart',
'packages/a_plugin/example/README.md',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, false);
expect(state.needsChangelogChange, true);
});
test(
'requires a changelog change but no version change for README.md when '
'code example is present', () async {
final RepositoryPackage package = createFakePlugin(
'a_plugin', packagesDir,
extraFiles: <String>['example/lib/main.dart']);
const List<String> changedFiles = <String>[
'packages/a_plugin/example/README.md',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, false);
expect(state.needsChangelogChange, true);
});
test(
'requires neither a changelog nor version change for README.md when '
'code example is present in a federated plugin implementation',
() async {
final RepositoryPackage package = createFakePlugin(
'a_plugin_android', packagesDir.childDirectory('a_plugin'),
extraFiles: <String>['example/lib/main.dart']);
const List<String> changedFiles = <String>[
'packages/a_plugin/a_plugin_android/example/README.md',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/a_plugin_android');
expect(state.hasChanges, true);
expect(state.needsVersionChange, false);
expect(state.needsChangelogChange, false);
});
test(
'does not requires changelog or version change for build.gradle '
'test-dependency-only changes', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/android/build.gradle',
];
final GitVersionFinder git = FakeGitVersionFinder(<String, List<String>>{
'packages/a_plugin/android/build.gradle': <String>[
"- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'",
"- testImplementation 'junit:junit:4.10.0'",
"+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'",
"+ testImplementation 'junit:junit:4.13.2'",
]
});
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/',
git: git);
expect(state.hasChanges, true);
expect(state.needsVersionChange, false);
expect(state.needsChangelogChange, false);
});
test('requires changelog or version change for other build.gradle changes',
() async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/android/build.gradle',
];
final GitVersionFinder git = FakeGitVersionFinder(<String, List<String>>{
'packages/a_plugin/android/build.gradle': <String>[
"- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'",
"- testImplementation 'junit:junit:4.10.0'",
"+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'",
"+ testImplementation 'junit:junit:4.13.2'",
"- implementation 'com.google.android.gms:play-services-maps:18.0.0'",
"+ implementation 'com.google.android.gms:play-services-maps:18.0.2'",
]
});
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/',
git: git);
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test(
'does not requires changelog or version change for '
'non-doc-comment-only changes', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/lib/a_plugin.dart',
];
final GitVersionFinder git = FakeGitVersionFinder(<String, List<String>>{
'packages/a_plugin/lib/a_plugin.dart': <String>[
'- // Old comment.',
'+ // New comment.',
'+ ', // Allow whitespace line changes as part of comment changes.
]
});
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/',
git: git);
expect(state.hasChanges, true);
expect(state.needsVersionChange, false);
expect(state.needsChangelogChange, false);
});
test('requires changelog or version change for doc comment changes',
() async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/lib/a_plugin.dart',
];
final GitVersionFinder git = FakeGitVersionFinder(<String, List<String>>{
'packages/a_plugin/lib/a_plugin.dart': <String>[
'- /// Old doc comment.',
'+ /// New doc comment.',
]
});
final PackageChangeState state = await checkPackageChangeState(
package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/',
git: git,
);
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test('requires changelog or version change for Dart code change', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/lib/a_plugin.dart',
];
final GitVersionFinder git = FakeGitVersionFinder(<String, List<String>>{
'packages/a_plugin/lib/a_plugin.dart': <String>[
// Include inline comments to ensure the comment check doesn't have
// false positives for lines that include comment changes but aren't
// only comment changes.
'- callOldMethod(); // inline comment',
'+ callNewMethod(); // inline comment',
]
});
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/',
git: git);
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test(
'requires changelog or version change if build.gradle diffs cannot '
'be checked', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/android/build.gradle',
];
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/');
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
test(
'requires changelog or version change if build.gradle diffs cannot '
'be determined', () async {
final RepositoryPackage package =
createFakePlugin('a_plugin', packagesDir);
const List<String> changedFiles = <String>[
'packages/a_plugin/android/build.gradle',
];
final GitVersionFinder git = FakeGitVersionFinder(<String, List<String>>{
'packages/a_plugin/android/build.gradle': <String>[]
});
final PackageChangeState state = await checkPackageChangeState(package,
changedPaths: changedFiles,
relativePackagePath: 'packages/a_plugin/',
git: git);
expect(state.hasChanges, true);
expect(state.needsVersionChange, true);
expect(state.needsChangelogChange, true);
});
});
}
class FakeGitVersionFinder extends Fake implements GitVersionFinder {
FakeGitVersionFinder(this.fileDiffs);
final Map<String, List<String>> fileDiffs;
@override
Future<List<String>> getDiffContents({
String? targetPath,
bool includeUncommitted = false,
}) async {
return fileDiffs[targetPath]!;
}
}