| // 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:test/test.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/receive messages', () async { |
| late SendPort toPlatformThread; |
| var sumOfReceivedMessages = 0; |
| var countofReceivedMessages = 0; |
| final recvPort = RawReceivePort((Object message) { |
| switch (message) { |
| case final SendPort sendPort: |
| toPlatformThread = sendPort; |
| for (int i = 1; i <= 10; i++) { |
| sendPort.send(i); |
| } |
| case final int value: |
| sumOfReceivedMessages += value; |
| countofReceivedMessages++; |
| if (countofReceivedMessages == 10) { |
| toPlatformThread.send(true); |
| } |
| default: |
| fail('Unexpected message: $message'); |
| } |
| }); |
| |
| final sendPort = recvPort.sendPort; |
| await runOnPlatformThread(() async { |
| final completer = Completer<void>(); |
| final recvPort = RawReceivePort((Object message) { |
| switch (message) { |
| case final int value: |
| sendPort.send(value * 100); |
| case true: |
| completer.complete(); |
| default: |
| fail('Unexpected message: $message'); |
| } |
| }); |
| sendPort.send(recvPort.sendPort); |
| await completer.future; |
| recvPort.close(); |
| }); |
| |
| expect(sumOfReceivedMessages, 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 expectLater(() async { |
| await Isolate.run(() { |
| return 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 expectLater(runOnPlatformThread(() => 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); |
| }); |
| } |