blob: b9a0f0fa18d10ce7693eada76db2e22326a0da7f [file] [log] [blame]
// Copyright (c) 2025, 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.
//
// Tests IsolateGroup.runSync - what works, what doesn't.
//
// VMOptions=--experimental-shared-data
// VMOptions=--experimental-shared-data --use-slow-path
// VMOptions=--experimental-shared-data --use-slow-path --stacktrace-every=100
// VMOptions=--experimental-shared-data --dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
// VMOptions=--experimental-shared-data --test_il_serialization
// VMOptions=--experimental-shared-data --profiler --profile_vm=true
// VMOptions=--experimental-shared-data --profiler --profile_vm=false
import 'dart:async';
import 'dart:concurrent';
import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';
import 'package:dart_internal/isolate_group.dart' show IsolateGroup;
import "package:expect/async_helper.dart";
import "package:expect/expect.dart";
import 'package:ffi/ffi.dart';
@pragma('vm:shared')
late final Mutex mutex;
@pragma('vm:shared')
late final String shared_late_final_string = () {
return "${int.parse('123') + 42}";
}();
@pragma('vm:shared')
late final String shared_late_final_throw = () {
throw "${int.parse('123') + 42}";
}();
@pragma('vm:shared')
late final String foo = () {
return "${int.parse('123') + 42}";
}();
testInitStrings() async {
const int nWorkers = 100;
mutex = Mutex();
final rp = ReceivePort();
final rpExitAndErrors = ReceivePort()
..listen((e) {
print('e: $e');
});
final completer = Completer();
int counter = 0;
rp.listen((data) {
counter++;
print('got $data, counter: $counter');
Expect.equals("165", data);
if (counter == nWorkers) {
completer.complete(data);
}
});
for (int i = 0; i < nWorkers; i++) {
Isolate.spawn(
(sendPort) {
IsolateGroup.runSync(() {
sendPort.send(shared_late_final_string);
});
},
rp.sendPort,
onExit: rpExitAndErrors.sendPort,
onError: rpExitAndErrors.sendPort,
);
print("spawned isolate #$i");
}
Expect.equals("165", await completer.future);
rpExitAndErrors.close();
rp.close();
}
testInitThrows() async {
const int nWorkers = 100;
final rp = ReceivePort();
int exitCounter = 0;
final completer = Completer();
ReceivePort rpExits = ReceivePort()
..listen((e) {
exitCounter++;
print('exitCounter: $exitCounter, exit: $e');
if (exitCounter == nWorkers) {
completer.complete(true);
}
});
int errorCounter = 0;
ReceivePort rpErrors = ReceivePort()
..listen((e) {
errorCounter++;
Expect.equals("165", e[0]);
print('errorCounter: $errorCounter, error: $e');
});
for (int i = 0; i < nWorkers; i++) {
Isolate.spawn(
(sendPort) {
IsolateGroup.runSync(() {
try {
sendPort.send(shared_late_final_throw);
} catch (e) {
Expect.equals("165", e);
rethrow;
}
});
},
rp.sendPort,
onExit: rpExits.sendPort,
onError: rpErrors.sendPort,
);
print("spawned isolate #$i");
}
await completer.future;
Expect.equals(nWorkers, errorCounter);
rpErrors.close();
rpExits.close();
rp.close();
}
@pragma('vm:shared')
late final String foo_bar = () {
return "${int.parse('123') + 42} $foo";
}();
testNestedInitCall() {
Expect.equals("165 165", foo_bar);
}
main() async {
asyncStart();
await testInitStrings();
await testInitThrows();
testNestedInitCall();
asyncEnd();
}