// Copyright (c) 2015, 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:observatory/service_io.dart'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; import 'test_helper.dart'; final dartJITBinary = path.join(path.dirname(io.Platform.resolvedExecutable), 'dart' + path.extension(io.Platform.resolvedExecutable)); 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 { try { process1 = await io.Process.start(io.Platform.executable, args); process2 = await io.Process.start(io.Platform.executable, 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 io.Process.start( dartJITBinary, [...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. (Isolate isolate) async { final setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {}); try { var all = await isolate .invokeRpcNoUpgrade('ext.dart.io.getSpawnedProcesses', {}); expect(all['type'], equals('SpawnedProcessList')); expect(all['processes'].length, equals(3)); final first = await isolate.invokeRpcNoUpgrade( 'ext.dart.io.getSpawnedProcessById', {'id': all['processes'][0]['id']}); expect(first['name'], io.Platform.executable); expect(first['pid'], equals(setup['pids'][0])); expect(first['arguments'].contains('foobar'), isFalse); expect(first['startedAt'], greaterThan(0)); final second = await isolate.invokeRpcNoUpgrade( 'ext.dart.io.getSpawnedProcessById', {'id': all['processes'][1]['id']}); expect(second['name'], io.Platform.executable); expect(second['pid'], equals(setup['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 isolate.invokeRpcNoUpgrade( 'ext.dart.io.getSpawnedProcessById', {'id': all['processes'][2]['id']}); expect(third['name'], dartJITBinary); expect(third['pid'], equals(setup['pids'][2])); expect(third['pid'] != first['pid'], isTrue); expect(third['pid'] != second['pid'], isTrue); expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt'])); await isolate.invokeRpcNoUpgrade('ext.dart.io.closeStdin', {}); all = await isolate .invokeRpcNoUpgrade('ext.dart.io.getSpawnedProcesses', {}); expect(all['type'], equals('SpawnedProcessList')); expect(all['processes'].length, equals(2)); } finally { await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {}); } }, ]; main(args) async => runIsolateTests(args, processTests, testeeBefore: setupProcesses);