blob: c6bd4fd56879098e82f11c23177f3131d0dbe36b [file] [log] [blame]
// 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:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import '../framework/framework.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';
TaskFunction dartPluginRegistryTest({
String? deviceIdOverride,
Map<String, String>? environment,
}) {
final Directory tempDir = Directory.systemTemp
.createTempSync('flutter_devicelab_dart_plugin_test.');
return () async {
try {
section('Create implementation plugin');
await inDirectory(tempDir, () async {
await flutter(
'create',
options: <String>[
'--template=plugin',
'--org',
'io.flutter.devicelab',
'--platforms',
'macos',
'aplugin_platform_implementation',
],
environment: environment,
);
});
final File pluginMain = File(path.join(
tempDir.absolute.path,
'aplugin_platform_implementation',
'lib',
'aplugin_platform_implementation.dart',
));
if (!pluginMain.existsSync()) {
return TaskResult.failure('${pluginMain.path} does not exist');
}
// Patch plugin main dart file.
await pluginMain.writeAsString('''
class ApluginPlatformInterfaceMacOS {
static void registerWith() {
print('ApluginPlatformInterfaceMacOS.registerWith() was called');
}
}
''', flush: true);
// Patch plugin main pubspec file.
final File pluginImplPubspec = File(path.join(
tempDir.absolute.path,
'aplugin_platform_implementation',
'pubspec.yaml',
));
String pluginImplPubspecContent = await pluginImplPubspec.readAsString();
pluginImplPubspecContent = pluginImplPubspecContent.replaceFirst(
' pluginClass: ApluginPlatformImplementationPlugin',
' pluginClass: ApluginPlatformImplementationPlugin\n'
' dartPluginClass: ApluginPlatformInterfaceMacOS\n',
);
pluginImplPubspecContent = pluginImplPubspecContent.replaceFirst(
' platforms:\n',
' implements: aplugin_platform_interface\n'
' platforms:\n');
await pluginImplPubspec.writeAsString(pluginImplPubspecContent,
flush: true);
section('Create interface plugin');
await inDirectory(tempDir, () async {
await flutter(
'create',
options: <String>[
'--template=plugin',
'--org',
'io.flutter.devicelab',
'--platforms',
'macos',
'aplugin_platform_interface',
],
environment: environment,
);
});
final File pluginInterfacePubspec = File(path.join(
tempDir.absolute.path,
'aplugin_platform_interface',
'pubspec.yaml',
));
String pluginInterfacePubspecContent =
await pluginInterfacePubspec.readAsString();
pluginInterfacePubspecContent =
pluginInterfacePubspecContent.replaceFirst(
' pluginClass: ApluginPlatformInterfacePlugin',
' default_package: aplugin_platform_implementation\n');
pluginInterfacePubspecContent =
pluginInterfacePubspecContent.replaceFirst(
'dependencies:',
'dependencies:\n'
' aplugin_platform_implementation:\n'
' path: ../aplugin_platform_implementation\n');
await pluginInterfacePubspec.writeAsString(pluginInterfacePubspecContent,
flush: true);
section('Create app');
await inDirectory(tempDir, () async {
await flutter(
'create',
options: <String>[
'--template=app',
'--org',
'io.flutter.devicelab',
'--platforms',
'macos',
'app',
],
environment: environment,
);
});
final File appPubspec = File(path.join(
tempDir.absolute.path,
'app',
'pubspec.yaml',
));
String appPubspecContent = await appPubspec.readAsString();
appPubspecContent = appPubspecContent.replaceFirst(
'dependencies:',
'dependencies:\n'
' aplugin_platform_interface:\n'
' path: ../aplugin_platform_interface\n');
await appPubspec.writeAsString(appPubspecContent, flush: true);
section('Flutter run for macos');
late Process run;
await inDirectory(path.join(tempDir.path, 'app'), () async {
run = await startProcess(
path.join(flutterDirectory.path, 'bin', 'flutter'),
flutterCommandArgs('run', <String>['-d', 'macos', '-v']),
);
});
Completer<void> registryExecutedCompleter = Completer<void>();
final StreamSubscription<void> stdoutSub = run.stdout
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter())
.listen((String line) {
if (line.contains('ApluginPlatformInterfaceMacOS.registerWith() was called')) {
registryExecutedCompleter.complete();
}
print('stdout: $line');
});
final StreamSubscription<void> stderrSub = run.stderr
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter())
.listen((String line) {
print('stderr: $line');
});
final Future<void> stdoutDone = stdoutSub.asFuture<void>();
final Future<void> stderrDone = stderrSub.asFuture<void>();
Future<void> waitForStreams() {
return Future.wait<void>(<Future<void>>[stdoutDone, stderrDone]);
}
Future<void> waitOrExit(Future<void> future) async {
final dynamic result = await Future.any<dynamic>(
<Future<dynamic>>[
future,
run.exitCode,
],
);
if (result is int) {
await waitForStreams();
throw 'process exited with code $result';
}
}
section('Wait for registry execution');
await waitOrExit(registryExecutedCompleter.future);
// Hot restart.
run.stdin.write('R');
await run.stdin.flush();
await run.stdin.close();
registryExecutedCompleter = Completer<void>();
section('Wait for registry execution after hot restart');
await waitOrExit(registryExecutedCompleter.future);
run.kill();
section('Wait for stdout/stderr streams');
await waitForStreams();
unawaited(stdoutSub.cancel());
unawaited(stderrSub.cancel());
return TaskResult.success(null);
} finally {
rmTree(tempDir);
}
};
}