Files
packages/script/tool/test/lint_android_command_test.dart
stuartmorgan ff00264ec5 [ci] Add partial LUCI Android platform tests (#4381)
Adds an initial Android platform tests LUCI script, and initial targets in bringup mode (using 6 shards instead of the 8 we have in Cirrus since the added shards were to try to address what in retrospect was likely a device availability issue, and since for now this will be running fewer tests; once everything is migrated we can evaluate whether we need more shards).

Rather than wait for emulator and/or FTL support in LUCI to do the migration of this target, this will partially migrate; the script currently does only the parts that don't require any kind of device. That will let us set up a baseline of LUCI Android platform tests bots to easily expand from as we figure out those pieces, and we can turn down these parts of the tests in Cirrus once these come out of bringup mode to minimize duplication.

To avoid having to run a full `flutter build` for both versions, this also updates the repo tooling to use the new `flutter build apk --config-only` option to create `gradlew` without doing a full build.

Part of https://github.com/flutter/flutter/issues/114373
2023-07-06 22:48:01 +00:00

246 lines
7.6 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:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/common/core.dart';
import 'package:flutter_plugin_tools/src/common/plugin_utils.dart';
import 'package:flutter_plugin_tools/src/lint_android_command.dart';
import 'package:test/test.dart';
import 'mocks.dart';
import 'util.dart';
void main() {
group('LintAndroidCommand', () {
FileSystem fileSystem;
late Directory packagesDir;
late CommandRunner<void> runner;
late MockPlatform mockPlatform;
late RecordingProcessRunner processRunner;
setUp(() {
fileSystem = MemoryFileSystem();
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
mockPlatform = MockPlatform();
processRunner = RecordingProcessRunner();
final LintAndroidCommand command = LintAndroidCommand(
packagesDir,
processRunner: processRunner,
platform: mockPlatform,
);
runner = CommandRunner<void>(
'lint_android_test', 'Test for $LintAndroidCommand');
runner.addCommand(command);
});
test('runs gradle lint', () async {
final RepositoryPackage plugin =
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
'example/android/gradlew',
], platformSupport: <String, PlatformDetails>{
platformAndroid: const PlatformDetails(PlatformSupport.inline)
});
final Directory androidDir =
plugin.getExamples().first.platformDirectory(FlutterPlatform.android);
final List<String> output =
await runCapturingPrint(runner, <String>['lint-android']);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
androidDir.childFile('gradlew').path,
const <String>['plugin1:lintDebug'],
androidDir.path,
),
]),
);
expect(
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin1'),
contains('No issues found!'),
]));
});
test('runs on all examples', () async {
final List<String> examples = <String>['example1', 'example2'];
final RepositoryPackage plugin = createFakePlugin('plugin1', packagesDir,
examples: examples,
extraFiles: <String>[
'example/example1/android/gradlew',
'example/example2/android/gradlew',
],
platformSupport: <String, PlatformDetails>{
platformAndroid: const PlatformDetails(PlatformSupport.inline)
});
final Iterable<Directory> exampleAndroidDirs = plugin.getExamples().map(
(RepositoryPackage example) =>
example.platformDirectory(FlutterPlatform.android));
final List<String> output =
await runCapturingPrint(runner, <String>['lint-android']);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
for (final Directory directory in exampleAndroidDirs)
ProcessCall(
directory.childFile('gradlew').path,
const <String>['plugin1:lintDebug'],
directory.path,
),
]),
);
expect(
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin1'),
contains('No issues found!'),
]));
});
test('runs --config-only build if gradlew is missing', () async {
final RepositoryPackage plugin = createFakePlugin('plugin1', packagesDir,
platformSupport: <String, PlatformDetails>{
platformAndroid: const PlatformDetails(PlatformSupport.inline)
});
final Directory androidDir =
plugin.getExamples().first.platformDirectory(FlutterPlatform.android);
final List<String> output =
await runCapturingPrint(runner, <String>['lint-android']);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>['build', 'apk', '--config-only'],
plugin.getExamples().first.directory.path,
),
ProcessCall(
androidDir.childFile('gradlew').path,
const <String>['plugin1:lintDebug'],
androidDir.path,
),
]),
);
expect(
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin1'),
contains('No issues found!'),
]));
});
test('fails if gradlew generation fails', () async {
createFakePlugin('plugin1', packagesDir,
platformSupport: <String, PlatformDetails>{
platformAndroid: const PlatformDetails(PlatformSupport.inline)
});
processRunner
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
<FakeProcessInfo>[
FakeProcessInfo(MockProcess(exitCode: 1)),
];
Error? commandError;
final List<String> output = await runCapturingPrint(
runner, <String>['lint-android'], errorHandler: (Error e) {
commandError = e;
});
expect(commandError, isA<ToolExit>());
expect(
output,
containsAllInOrder(
<Matcher>[
contains('Unable to configure Gradle project'),
],
));
});
test('fails if linting finds issues', () async {
final RepositoryPackage plugin =
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
'example/android/gradlew',
], platformSupport: <String, PlatformDetails>{
platformAndroid: const PlatformDetails(PlatformSupport.inline)
});
final String gradlewPath = plugin
.getExamples()
.first
.platformDirectory(FlutterPlatform.android)
.childFile('gradlew')
.path;
processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[
FakeProcessInfo(MockProcess(exitCode: 1)),
];
Error? commandError;
final List<String> output = await runCapturingPrint(
runner, <String>['lint-android'], errorHandler: (Error e) {
commandError = e;
});
expect(commandError, isA<ToolExit>());
expect(
output,
containsAllInOrder(
<Matcher>[
contains('The following packages had errors:'),
],
));
});
test('skips non-Android plugins', () async {
createFakePlugin('plugin1', packagesDir);
final List<String> output =
await runCapturingPrint(runner, <String>['lint-android']);
expect(
output,
containsAllInOrder(
<Matcher>[
contains(
'SKIPPING: Plugin does not have an Android implementation.')
],
));
});
test('skips non-inline plugins', () async {
createFakePlugin('plugin1', packagesDir,
platformSupport: <String, PlatformDetails>{
platformAndroid: const PlatformDetails(PlatformSupport.federated)
});
final List<String> output =
await runCapturingPrint(runner, <String>['lint-android']);
expect(
output,
containsAllInOrder(
<Matcher>[
contains(
'SKIPPING: Plugin does not have an Android implementation.')
],
));
});
});
}