blob: a3f87b2a979b51544ef52907c87268b828c89b27 [file] [log] [blame]
// 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 'dart:ffi';
import 'dart:isolate';
import 'dart:ui';
import 'package:ffi/ffi.dart';
import 'package:litetest/litetest.dart';
// This import is used in a test, but not in a way that the analyzer can understand.
// ignore: unused_import
import 'spawn_helper.dart';
@Native<Handle Function(Pointer<Utf8>)>(symbol: 'LoadLibraryFromKernel')
external Object _loadLibraryFromKernel(Pointer<Utf8> path);
@Native<Handle Function(Pointer<Utf8>, Pointer<Utf8>)>(symbol: 'LookupEntryPoint')
external Object _lookupEntryPoint(Pointer<Utf8> library, Pointer<Utf8> name);
@Native<Void Function(Pointer<Utf8>, Pointer<Utf8>)>(symbol: 'Spawn')
external void _spawn(Pointer<Utf8> entrypoint, Pointer<Utf8> route);
void spawn({
required SendPort port,
String entrypoint = 'main',
String route = '/',
}) {
assert(
entrypoint != 'main' || route != '/',
'Spawn should not be used to spawn main with the default route name',
);
IsolateNameServer.registerPortWithName(port, route);
final Pointer<Utf8> nativeEntrypoint = entrypoint.toNativeUtf8();
final Pointer<Utf8> nativeRoute = route.toNativeUtf8();
_spawn(nativeEntrypoint, nativeRoute);
malloc.free(nativeEntrypoint);
malloc.free(nativeRoute);
}
const String kTestEntrypointRouteName = 'testEntrypoint';
@pragma('vm:entry-point')
void testEntrypoint() {
expect(PlatformDispatcher.instance.defaultRouteName, kTestEntrypointRouteName);
IsolateNameServer.lookupPortByName(kTestEntrypointRouteName)!.send(null);
}
void main() {
const bool kReleaseMode = bool.fromEnvironment('dart.vm.product');
const bool kProfileMode = bool.fromEnvironment('dart.vm.profile');
test('Spawn a different entrypoint with a special route name', () async {
final ReceivePort port = ReceivePort();
spawn(port: port.sendPort, entrypoint: 'testEntrypoint', route: kTestEntrypointRouteName);
expect(await port.first, isNull);
port.close();
});
test('Lookup entrypoint and execute', () {
final Pointer<Utf8> libraryPath = 'file://${const String.fromEnvironment('kFlutterSrcDirectory')}/testing/dart/spawn_helper.dart'.toNativeUtf8();
final Pointer<Utf8> entryPoint = 'echoInt'.toNativeUtf8();
expect(
(_lookupEntryPoint(
libraryPath,
entryPoint,
) as int Function(int))(42),
42,
);
malloc.free(libraryPath);
malloc.free(entryPoint);
});
test('Load from kernel', () {
final Pointer<Utf8> kernelPath = '${const String.fromEnvironment('kFlutterBuildDirectory')}/spawn_helper.dart.dill'.toNativeUtf8();
expect(
_loadLibraryFromKernel(kernelPath) is void Function(),
true,
);
malloc.free(kernelPath);
final Pointer<Utf8> fakePath = 'fake-path'.toNativeUtf8();
expect(_loadLibraryFromKernel(fakePath), null);
malloc.free(fakePath);
}, skip: kProfileMode || kReleaseMode); // ignore: avoid_redundant_argument_values
}