mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
246 lines
6.9 KiB
Dart
246 lines
6.9 KiB
Dart
// Copyright 2014 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 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter_devicelab/framework/framework.dart';
|
|
import 'package:flutter_devicelab/framework/utils.dart';
|
|
import 'package:path/path.dart' as path;
|
|
|
|
/// Tests that a plugin A can depend on platform code from a plugin B
|
|
/// as long as plugin B is defined as a pub dependency of plugin A.
|
|
///
|
|
/// This test fails when `flutter build apk` fails and the stderr from this command
|
|
/// contains "Unresolved reference: plugin_b".
|
|
Future<void> main() async {
|
|
await task(() async {
|
|
|
|
section('Find Java');
|
|
|
|
final String javaHome = await findJavaHome();
|
|
if (javaHome == null) {
|
|
return TaskResult.failure('Could not find Java');
|
|
}
|
|
|
|
print('\nUsing JAVA_HOME=$javaHome');
|
|
|
|
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_plugin_dependencies.');
|
|
try {
|
|
|
|
section('Create plugin A');
|
|
|
|
final Directory pluginADirectory = Directory(path.join(tempDir.path, 'plugin_a'));
|
|
await inDirectory(tempDir, () async {
|
|
await flutter(
|
|
'create',
|
|
options: <String>[
|
|
'--org',
|
|
'io.flutter.devicelab.plugin_a',
|
|
'--template=plugin',
|
|
pluginADirectory.path,
|
|
],
|
|
);
|
|
});
|
|
|
|
section('Create plugin B');
|
|
|
|
final Directory pluginBDirectory = Directory(path.join(tempDir.path, 'plugin_b'));
|
|
await inDirectory(tempDir, () async {
|
|
await flutter(
|
|
'create',
|
|
options: <String>[
|
|
'--org',
|
|
'io.flutter.devicelab.plugin_b',
|
|
'--template=plugin',
|
|
pluginBDirectory.path,
|
|
],
|
|
);
|
|
});
|
|
|
|
section('Create plugin C without android/ directory');
|
|
|
|
final Directory pluginCDirectory = Directory(path.join(tempDir.path, 'plugin_c'));
|
|
await inDirectory(tempDir, () async {
|
|
await flutter(
|
|
'create',
|
|
options: <String>[
|
|
'--org',
|
|
'io.flutter.devicelab.plugin_c',
|
|
'--template=plugin',
|
|
pluginCDirectory.path,
|
|
],
|
|
);
|
|
});
|
|
|
|
File(path.join(pluginCDirectory.path, 'android')).deleteSync(recursive: true);
|
|
|
|
final File pluginCpubspec = File(path.join(pluginCDirectory.path, 'pubspec.yaml'));
|
|
await pluginCpubspec.writeAsString('''
|
|
name: plugin_c
|
|
version: 0.0.1
|
|
|
|
flutter:
|
|
plugin:
|
|
platforms:
|
|
ios:
|
|
pluginClass: Plugin_cPlugin
|
|
|
|
dependencies:
|
|
flutter:
|
|
sdk: flutter
|
|
|
|
environment:
|
|
sdk: ">=2.0.0-dev.28.0 <3.0.0"
|
|
flutter: ">=1.5.0 <2.0.0"
|
|
''', flush: true);
|
|
|
|
section('Write dummy Kotlin code in plugin B');
|
|
|
|
final File pluginBKotlinClass = File(path.join(
|
|
pluginBDirectory.path,
|
|
'android',
|
|
'src',
|
|
'main',
|
|
'kotlin',
|
|
'DummyPluginBClass.kt',
|
|
));
|
|
|
|
await pluginBKotlinClass.writeAsString('''
|
|
package io.flutter.devicelab.plugin_b
|
|
|
|
public class DummyPluginBClass {
|
|
companion object {
|
|
fun dummyStaticMethod() {
|
|
}
|
|
}
|
|
}
|
|
''', flush: true);
|
|
|
|
section('Make plugin A depend on plugin B and plugin C');
|
|
|
|
final File pluginApubspec = File(path.join(pluginADirectory.path, 'pubspec.yaml'));
|
|
String pluginApubspecContent = await pluginApubspec.readAsString();
|
|
pluginApubspecContent = pluginApubspecContent.replaceFirst(
|
|
'\ndependencies:\n',
|
|
'\ndependencies:\n'
|
|
' plugin_b:\n'
|
|
' path: ${pluginBDirectory.path}\n'
|
|
' plugin_c:\n'
|
|
' path: ${pluginCDirectory.path}\n',
|
|
);
|
|
await pluginApubspec.writeAsString(pluginApubspecContent, flush: true);
|
|
|
|
section('Write Kotlin code in plugin A that references Kotlin code from plugin B');
|
|
|
|
final File pluginAKotlinClass = File(path.join(
|
|
pluginADirectory.path,
|
|
'android',
|
|
'src',
|
|
'main',
|
|
'kotlin',
|
|
'DummyPluginAClass.kt',
|
|
));
|
|
|
|
await pluginAKotlinClass.writeAsString('''
|
|
package io.flutter.devicelab.plugin_a
|
|
|
|
import io.flutter.devicelab.plugin_b.DummyPluginBClass
|
|
|
|
public class DummyPluginAClass {
|
|
constructor() {
|
|
// Call a method from plugin b.
|
|
DummyPluginBClass.dummyStaticMethod();
|
|
}
|
|
}
|
|
''', flush: true);
|
|
|
|
section('Verify .flutter-plugins-dependencies');
|
|
|
|
final Directory exampleApp = Directory(path.join(pluginADirectory.path, 'example'));
|
|
|
|
await inDirectory(exampleApp, () async {
|
|
await flutter(
|
|
'packages',
|
|
options: <String>['get'],
|
|
);
|
|
});
|
|
|
|
final File flutterPluginsDependenciesFile =
|
|
File(path.join(exampleApp.path, '.flutter-plugins-dependencies'));
|
|
|
|
if (!flutterPluginsDependenciesFile.existsSync()) {
|
|
return TaskResult.failure('${flutterPluginsDependenciesFile.path} doesn\'t exist');
|
|
}
|
|
|
|
final String flutterPluginsDependenciesFileContent = flutterPluginsDependenciesFile.readAsStringSync();
|
|
const String kExpectedPluginsDependenciesContent =
|
|
'{'
|
|
'\"_info\":\"// This is a generated file; do not edit or check into version control.\",'
|
|
'\"dependencyGraph\":['
|
|
'{'
|
|
'\"name\":\"plugin_a\",'
|
|
'\"dependencies\":[\"plugin_b\",\"plugin_c\"]'
|
|
'},'
|
|
'{'
|
|
'\"name\":\"plugin_b\",'
|
|
'\"dependencies\":[]'
|
|
'},'
|
|
'{'
|
|
'\"name\":\"plugin_c\",'
|
|
'\"dependencies\":[]'
|
|
'}'
|
|
']'
|
|
'}';
|
|
|
|
if (flutterPluginsDependenciesFileContent != kExpectedPluginsDependenciesContent) {
|
|
return TaskResult.failure(
|
|
'Unexpected file content in ${flutterPluginsDependenciesFile.path}: '
|
|
'Found "$flutterPluginsDependenciesFileContent" instead of '
|
|
'"$kExpectedPluginsDependenciesContent"'
|
|
);
|
|
}
|
|
|
|
section('Build plugin A example app');
|
|
|
|
final StringBuffer stderr = StringBuffer();
|
|
await inDirectory(exampleApp, () async {
|
|
await evalFlutter(
|
|
'build',
|
|
options: <String>['apk', '--target-platform', 'android-arm'],
|
|
canFail: true,
|
|
stderr: stderr,
|
|
);
|
|
});
|
|
|
|
if (stderr.toString().contains('Unresolved reference: plugin_b')) {
|
|
return TaskResult.failure('plugin_a cannot reference plugin_b');
|
|
}
|
|
|
|
final bool pluginAExampleApk = exists(File(path.join(
|
|
pluginADirectory.path,
|
|
'example',
|
|
'build',
|
|
'app',
|
|
'outputs',
|
|
'apk',
|
|
'release',
|
|
'app-release.apk',
|
|
)));
|
|
|
|
if (!pluginAExampleApk) {
|
|
return TaskResult.failure('Failed to build plugin A example APK');
|
|
}
|
|
|
|
return TaskResult.success(null);
|
|
} on TaskResult catch (taskResult) {
|
|
return taskResult;
|
|
} catch (e) {
|
|
return TaskResult.failure(e.toString());
|
|
} finally {
|
|
rmTree(tempDir);
|
|
}
|
|
});
|
|
}
|