// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. // VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit // VMOptions=--no-enable-isolate-groups // Test that ensures correct exceptions are thrown when misusing // [TransferableTypedData]. import 'dart:async'; import 'dart:collection'; import 'dart:core'; import 'dart:io'; import 'dart:isolate'; import 'dart:typed_data'; import 'dart:math'; import "package:expect/expect.dart"; throwsIfMaterializeAfterSend() async { final completer = Completer(); final rp = ReceivePort() ..listen((e) { completer.complete(true); }); final transferable = TransferableTypedData.fromList([Uint8List(1024)]); rp.sendPort.send(transferable); Expect.throwsArgumentError(() => transferable.materialize()); await completer.future; rp.close(); } throwsIfSendMoreThanOnce() async { final completer = Completer(); final rp = ReceivePort() ..listen((e) { completer.complete(true); }); final bytes = Uint8List(1024); final transferable = TransferableTypedData.fromList([bytes]); rp.sendPort.send(transferable); Expect.throwsArgumentError(() => rp.sendPort.send(transferable)); await completer.future; rp.close(); } throwsIfMaterializeMoreThanOnce() { final transferable = TransferableTypedData.fromList([Uint8List(1024)]); transferable.materialize(); Expect.throwsArgumentError(() => transferable.materialize()); } throwsIfReceiverMaterializesMoreThanOnce() async { final completer = Completer(); final isolateErrors = ReceivePort()..listen((e) => completer.complete(e)); await Isolate.spawn( receiver, TransferableTypedData.fromList([Uint8List(1024)]), onError: isolateErrors.sendPort); final error = await completer.future; Expect.equals( error[0], "Invalid argument(s): Attempt to materialize object that was" " transferred already."); isolateErrors.close(); } void receiver(final transferable) { transferable.materialize(); transferable.materialize(); } throwsIfCummulativeListIsTooLargeOn32bitPlatform() { try { int maxUint8ListSize = pow(2, 30) as int; // Check whether we are on 32-bit or 64-bit platform. new Uint8List(maxUint8ListSize); // On 64-bit platform we will have difficulty allocating large enough // Uint8List to verify "too large" use case, so do nothing. return; } catch (_) {} var halfmax = new Uint8List(pow(2, 29) - 1 as int); Expect.throwsArgumentError( () => TransferableTypedData.fromList([halfmax, halfmax, Uint8List(2)])); } class MyList extends ListBase { @override int length = null as dynamic; @override T operator [](int index) => null as T; @override void operator []=(int index, T value) {} } class MyTypedData implements TypedData { noSuchMethod(_) {} } main() async { await throwsIfMaterializeAfterSend(); await throwsIfSendMoreThanOnce(); throwsIfMaterializeMoreThanOnce(); await throwsIfReceiverMaterializesMoreThanOnce(); throwsIfCummulativeListIsTooLargeOn32bitPlatform(); dynamic myNull; if (hasUnsoundNullSafety) { Expect.throwsArgumentError(() => TransferableTypedData.fromList(myNull)); Expect.throwsArgumentError(() => TransferableTypedData.fromList([myNull])); Expect.throwsArgumentError( () => TransferableTypedData.fromList(MyList())); } else { Expect.throwsTypeError(() => TransferableTypedData.fromList(myNull)); Expect.throwsTypeError(() => TransferableTypedData.fromList([myNull])); Expect.throwsTypeError( () => TransferableTypedData.fromList(MyList())); } Expect.throwsArgumentError( () => TransferableTypedData.fromList([MyTypedData()])); }