blob: 012e800b6859636bf1326041b8e86810e3a733b0 [file] [log] [blame]
// Copyright 2019 The Chromium 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('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');
final File pubspec = File(path.join(pluginADirectory.path, 'pubspec.yaml'));
String content = await pubspec.readAsString();
content = content.replaceFirst(
'\ndependencies:\n',
'\ndependencies:\n'
' plugin_b:\n'
' path: ${pluginBDirectory.path}\n',
);
await pubspec.writeAsString(content, 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\"]'
'},'
'{'
'\"name\":\"plugin_b\",'
'\"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);
}
});
}