// Copyright (c) 2020, 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:convert'; import 'dart:developer'; import 'dart:io' as io; import 'package:process/process.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'common/test_helper.dart'; Future setupProcesses() async { final dir = await io.Directory.systemTemp.createTemp('file_service'); final args = [ ...io.Platform.executableArguments, '--pause_isolates_on_start', io.Platform.script.toFilePath(), ]; io.Process? process1; io.Process? process2; io.Process? process3; void closeDown() { if (process1 != null) { process1!.kill(); } if (process2 != null) { process2!.kill(); } if (process3 != null) { process3!.kill(); } dir.deleteSync(recursive: true); } Future cleanup(ignored_a, ignored_b) { closeDown(); final result = jsonEncode({'type': 'foobar'}); return Future.value(ServiceExtensionResponse.result(result)); } Future setup(ignored_a, ignored_b) async { final processManager = LocalProcessManager(); try { process1 = await processManager.start( [io.Platform.resolvedExecutable, ...args], ); process2 = await processManager.start([ io.Platform.resolvedExecutable, ...(args..add('foobar')), ]); final codeFilePath = dir.path + io.Platform.pathSeparator + "other_file"; final codeFile = io.File(codeFilePath); await codeFile.writeAsString(''' import "dart:io"; void main() async { await stdin.drain(); } '''); process3 = await processManager.start( [ io.Platform.resolvedExecutable, ...io.Platform.executableArguments, codeFilePath ], ); } catch (_) { closeDown(); rethrow; } final result = jsonEncode({ 'type': 'foobar', 'pids': [process1!.pid, process2!.pid, process3!.pid] }); return Future.value(ServiceExtensionResponse.result(result)); } Future closeStdin(ignored_a, ignored_b) { process3!.stdin.close(); return process3!.exitCode.then((int exit) { final result = jsonEncode({'type': 'foobar'}); return ServiceExtensionResponse.result(result); }); } registerExtension('ext.dart.io.cleanup', cleanup); registerExtension('ext.dart.io.setup', setup); registerExtension('ext.dart.io.closeStdin', closeStdin); } final processTests = [ // Initial. (VmService service, IsolateRef isolate) async { final isolateId = isolate.id!; final setup = await service.callServiceExtension( 'ext.dart.io.setup', isolateId: isolateId, ); try { SpawnedProcessList all = await service.getSpawnedProcesses(isolateId); expect(all.processes.length, equals(3)); final first = await service.getSpawnedProcessById( isolateId, all.processes[0].id, ); expect(io.Platform.resolvedExecutable, contains(first.name.trim())); expect(first.pid, equals(setup.json!['pids']![0])); expect(first.arguments.contains('foobar'), isFalse); expect(first.startedAt, greaterThan(0)); final second = await service.getSpawnedProcessById( isolateId, all.processes[1].id, ); expect(io.Platform.resolvedExecutable, contains(second.name.trim())); expect(second.pid, equals(setup.json!['pids']![1])); expect(second.arguments.contains('foobar'), isTrue); expect(second.pid != first.pid, isTrue); expect(second.startedAt, greaterThan(0)); expect(second.startedAt, greaterThanOrEqualTo(first.startedAt)); final third = await service.getSpawnedProcessById( isolateId, all.processes[2].id, ); expect(io.Platform.resolvedExecutable, contains(third.name.trim())); expect(third.pid, equals(setup.json!['pids']![2])); expect(third.pid != first.pid, isTrue); expect(third.pid != second.pid, isTrue); expect(third.startedAt, greaterThanOrEqualTo(second.startedAt)); await service.callServiceExtension( 'ext.dart.io.closeStdin', isolateId: isolateId, ); all = await service.getSpawnedProcesses(isolateId); expect(all.processes.length, equals(2)); } finally { await service.callServiceExtension( 'ext.dart.io.cleanup', isolateId: isolateId, ); } }, ]; main([args = const []]) async => runIsolateTests( args, processTests, 'process_service_test.dart', testeeBefore: setupProcesses, );