| // 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<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) { |
| closeDown(); |
| final result = jsonEncode({'type': 'foobar'}); |
| return Future.value(ServiceExtensionResponse.result(result)); |
| } |
| |
| Future<ServiceExtensionResponse> 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<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) { |
| process3!.stdin.close(); |
| return process3!.exitCode.then<ServiceExtensionResponse>((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 = <IsolateTest>[ |
| // 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 <String>[]]) async => runIsolateTests( |
| args, |
| processTests, |
| 'process_service_test.dart', |
| testeeBefore: setupProcesses, |
| ); |