| // Copyright 2024 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:isolate'; | |
| import 'dart:ui'; | |
| import 'package:litetest/litetest.dart'; | |
| int counter = 0; | |
| void main() { | |
| test('PlatformIsolate isRunningOnPlatformThread, false cases', () async { | |
| final bool isPlatThread = | |
| await Isolate.run(() => isRunningOnPlatformThread); | |
| expect(isPlatThread, isFalse); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread', () async { | |
| final bool isPlatThread = | |
| await runOnPlatformThread(() => isRunningOnPlatformThread); | |
| expect(isPlatThread, isTrue); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, async operations', () async { | |
| final bool isPlatThread = await runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| return isRunningOnPlatformThread; | |
| }); | |
| expect(isPlatThread, isTrue); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, retains state', () async { | |
| await runOnPlatformThread(() => ++counter); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| await runOnPlatformThread(() => ++counter); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| await runOnPlatformThread(() => ++counter); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| final int counterValue = await runOnPlatformThread(() => counter); | |
| expect(counterValue, 3); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, concurrent jobs', () async { | |
| final Future<int> future1 = runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| return 1; | |
| }); | |
| final Future<int> future2 = runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| return 2; | |
| }); | |
| final Future<int> future3 = runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| return 3; | |
| }); | |
| expect(await future1, 1); | |
| expect(await future2, 2); | |
| expect(await future3, 3); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, send and receive messages', | |
| () async { | |
| // Send numbers 1 to 10 to the platform isolate. The platform isolate | |
| // multiplies them by 100 and sends them back. | |
| int sum = 0; | |
| final RawReceivePort recvPort = RawReceivePort((Object message) { | |
| if (message is SendPort) { | |
| for (int i = 1; i <= 10; ++i) { | |
| message.send(i); | |
| } | |
| } else { | |
| sum += message as int; | |
| } | |
| }); | |
| final SendPort sendPort = recvPort.sendPort; | |
| await runOnPlatformThread(() async { | |
| final Completer<void> completer = Completer<void>(); | |
| final RawReceivePort recvPort = RawReceivePort((Object message) { | |
| sendPort.send((message as int) * 100); | |
| if (message == 10) { | |
| completer.complete(); | |
| } | |
| }); | |
| sendPort.send(recvPort.sendPort); | |
| await completer.future; | |
| recvPort.close(); | |
| }); | |
| expect(sum, 5500); // sum(1 to 10) * 100 | |
| recvPort.close(); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, throws', () async { | |
| bool throws = false; | |
| try { | |
| await runOnPlatformThread(() => throw 'Oh no!'); | |
| } catch (error) { | |
| expect(error, 'Oh no!'); | |
| throws = true; | |
| } | |
| expect(throws, true); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, async throws', () async { | |
| bool throws = false; | |
| try { | |
| await runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| throw 'Oh no!'; | |
| }); | |
| } catch (error) { | |
| expect(error, 'Oh no!'); | |
| throws = true; | |
| } | |
| expect(throws, true); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, disabled on helper isolates', | |
| () async { | |
| await Isolate.run(() { | |
| expect(() => runOnPlatformThread(() => print('Unreachable')), throws); | |
| }); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, on platform isolate', () async { | |
| final int result = await runOnPlatformThread(() => runOnPlatformThread( | |
| () => runOnPlatformThread(() => runOnPlatformThread(() => 123)))); | |
| expect(result, 123); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, exit disabled', () async { | |
| await runOnPlatformThread(() => expect(() => Isolate.exit(), throws)); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, unsendable object', () async { | |
| bool throws = false; | |
| try { | |
| await runOnPlatformThread(() => ReceivePort()); | |
| } catch (error) { | |
| throws = true; | |
| } | |
| expect(throws, true); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, unsendable object async', | |
| () async { | |
| bool throws = false; | |
| try { | |
| await runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| return ReceivePort(); | |
| }); | |
| } catch (error) { | |
| throws = true; | |
| } | |
| expect(throws, true); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, throws unsendable', () async { | |
| bool throws = false; | |
| try { | |
| await runOnPlatformThread(() => throw ReceivePort()); | |
| } catch (error) { | |
| throws = true; | |
| } | |
| expect(throws, true); | |
| }); | |
| test('PlatformIsolate runOnPlatformThread, throws unsendable async', | |
| () async { | |
| bool throws = false; | |
| try { | |
| await runOnPlatformThread(() async { | |
| await Future<void>.delayed(const Duration(milliseconds: 100)); | |
| throw ReceivePort(); | |
| }); | |
| } catch (error) { | |
| throws = true; | |
| } | |
| expect(throws, true); | |
| }); | |
| } |