blob: 7c01cd666b754448847a9e4b39b6d744b49151b4 [file] [log] [blame]
// Copyright (c) 2023, 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.
import 'dart:async';
import 'dart:developer';
// ignore: library_prefixes
import 'dart:isolate' as I;
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'common/test_helper.dart';
// AUTOGENERATED START
//
// Update these constants by running:
//
// dart pkg/vm_service/test/update_line_numbers.dart <test.dart>
//
const LINE_A = 32;
// AUTOGENERATED END
final spawnCount = 4;
final resumeCount = spawnCount ~/ 2;
final isolates = [];
void spawnEntry(int i) {}
Future<void> during() async {
debugger(); // LINE_A
// Spawn spawnCount long lived isolates.
for (int i = 0; i < spawnCount; i++) {
final isolate = await I.Isolate.spawn(spawnEntry, i);
isolates.add(isolate);
}
print('spawned all isolates');
}
Future<int> numPaused(VmService service) async {
final vm = await service.getVM();
int paused = 0;
for (final isolateRef in vm.isolates!) {
final isolate = await service.getIsolate(isolateRef.id!);
if (isolate.pauseEvent != null &&
isolate.pauseEvent!.kind == EventKind.kPauseExit) {
paused++;
}
}
return paused;
}
final tests = <VMTest>[
(VmService service) async {
final vm = await service.getVM();
final isolates = vm.isolates!;
expect(isolates.length, 1);
await hasStoppedAtBreakpoint(service, isolates[0]);
await stoppedAtLine(LINE_A)(service, isolates[0]);
},
(VmService service) async {
int startCount = 0;
int runnableCount = 0;
final completer = Completer<void>();
late final StreamSubscription sub;
sub = service.onIsolateEvent.listen((event) async {
if (event.kind == EventKind.kIsolateStart) {
startCount++;
}
if (event.kind == EventKind.kIsolateRunnable) {
runnableCount++;
}
if (runnableCount == spawnCount) {
await sub.cancel();
await service.streamCancel(EventStreams.kIsolate);
completer.complete();
}
});
await service.streamListen(EventStreams.kIsolate);
VM vm = await service.getVM();
expect(vm.isolates!.length, 1);
// Resume and wait for the isolates to spawn.
await service.resume(vm.isolates![0].id!);
await completer.future;
expect(startCount, spawnCount);
expect(runnableCount, spawnCount);
vm = await service.getVM();
expect(vm.isolates!.length, spawnCount + 1);
},
(VmService service) async {
final completer = Completer<void>();
if (await numPaused(service) < (spawnCount + 1)) {
late final StreamSubscription sub;
sub = service.onDebugEvent.listen((event) async {
if (event.kind == EventKind.kPauseExit) {
if (await numPaused(service) == (spawnCount + 1)) {
await sub.cancel();
await service.streamCancel(EventStreams.kDebug);
completer.complete();
}
}
});
await service.streamListen(EventStreams.kDebug);
await completer.future;
}
expect(await numPaused(service), spawnCount + 1);
},
(VmService service) async {
int resumedReceived = 0;
final completer = Completer<void>();
late final StreamSubscription sub;
sub = service.onIsolateEvent.listen((event) async {
if (event.kind == EventKind.kIsolateExit) {
resumedReceived++;
if (resumedReceived >= resumeCount) {
await sub.cancel();
await service.streamCancel(EventStreams.kIsolate);
completer.complete();
}
}
});
await service.streamListen(EventStreams.kIsolate);
// Resume a subset of the isolates.
int resumesIssued = 0;
final vm = await service.getVM();
final isolateList = vm.isolates!;
for (final isolate in isolateList) {
if (isolate.name!.endsWith('main')) {
continue;
}
try {
resumesIssued++;
await service.resume(isolate.id!);
} catch (_) {}
if (resumesIssued == resumeCount) {
break;
}
}
await completer.future;
},
(VmService service) async {
expect(await numPaused(service), spawnCount + 1 - resumeCount);
},
];
void main([args = const <String>[]]) => runVMTests(
args,
tests,
'isolate_lifecycle_test.dart',
testeeConcurrent: during,
pauseOnExit: true,
);