Switch the way we retrieve the vm_service_port from /hub to iquery, on device. (#114834)
This commit is contained in:
parent
a84e369bd2
commit
1725a26e29
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:process/process.dart';
|
||||
@ -506,6 +507,39 @@ class FuchsiaRemoteConnection {
|
||||
_pollDartVms = true;
|
||||
}
|
||||
|
||||
/// Helper for getDeviceServicePorts() to extract the vm_service_port from
|
||||
/// json response.
|
||||
List<int> getVmServicePortFromInspectSnapshot(dynamic inspectSnapshot) {
|
||||
final List<Map<String, dynamic>> snapshot =
|
||||
List<Map<String, dynamic>>.from(inspectSnapshot as List<dynamic>);
|
||||
final List<int> ports = <int>[];
|
||||
|
||||
for (final Map<String, dynamic> item in snapshot) {
|
||||
if (!item.containsKey('payload') || item['payload'] == null) {
|
||||
continue;
|
||||
}
|
||||
final Map<String, dynamic> payload =
|
||||
Map<String, dynamic>.from(item['payload'] as Map<String, dynamic>);
|
||||
|
||||
if (!payload.containsKey('root') || payload['root'] == null) {
|
||||
continue;
|
||||
}
|
||||
final Map<String, dynamic> root =
|
||||
Map<String, dynamic>.from(payload['root'] as Map<String, dynamic>);
|
||||
|
||||
if (!root.containsKey('vm_service_port') ||
|
||||
root['vm_service_port'] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int? port = int.tryParse(root['vm_service_port'] as String);
|
||||
if (port != null) {
|
||||
ports.add(port);
|
||||
}
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
||||
/// Gets the open Dart VM service ports on a remote Fuchsia device.
|
||||
///
|
||||
/// The method attempts to get service ports through an SSH connection. Upon
|
||||
@ -514,24 +548,14 @@ class FuchsiaRemoteConnection {
|
||||
/// found. An exception is thrown in the event of an actual error when
|
||||
/// attempting to acquire the ports.
|
||||
Future<List<int>> getDeviceServicePorts() async {
|
||||
final List<String> portPaths = await _sshCommandRunner
|
||||
.run('/bin/find /hub -name vmservice-port');
|
||||
final List<int> ports = <int>[];
|
||||
for (final String path in portPaths) {
|
||||
if (path == '') {
|
||||
continue;
|
||||
}
|
||||
final List<String> lsOutput =
|
||||
await _sshCommandRunner.run('/bin/ls $path');
|
||||
for (final String line in lsOutput) {
|
||||
if (line == '') {
|
||||
continue;
|
||||
}
|
||||
final int? port = int.tryParse(line);
|
||||
if (port != null) {
|
||||
ports.add(port);
|
||||
}
|
||||
}
|
||||
final List<String> inspectResult = await _sshCommandRunner
|
||||
.run("iquery --format json show '**:root:vm_service_port'");
|
||||
final dynamic inspectOutputJson = jsonDecode(inspectResult.join('\n'));
|
||||
final List<int> ports =
|
||||
getVmServicePortFromInspectSnapshot(inspectOutputJson);
|
||||
|
||||
if (ports.length > 1) {
|
||||
throw StateError('More than one Flutter observatory port found');
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ void main() {
|
||||
restoreVmServiceConnectionFunction();
|
||||
});
|
||||
|
||||
test('end-to-end with three vm connections and flutter view query', () async {
|
||||
test('end-to-end with one vm connection and flutter view query', () async {
|
||||
int port = 0;
|
||||
Future<PortForwarder> fakePortForwardingFunction(
|
||||
String address,
|
||||
@ -102,54 +102,72 @@ void main() {
|
||||
fuchsiaPortForwardingFunction = fakePortForwardingFunction;
|
||||
final FakeSshCommandRunner fakeRunner = FakeSshCommandRunner();
|
||||
// Adds some extra junk to make sure the strings will be cleaned up.
|
||||
fakeRunner.findResponse = <String>['/hub/blah/blah/blah/vmservice-port\n'];
|
||||
fakeRunner.lsResponse = <String>['123\n\n\n', '456 ', '789'];
|
||||
fakeRunner.iqueryResponse = <String>[
|
||||
'[',
|
||||
' {',
|
||||
' "data_source": "Inspect",',
|
||||
' "metadata": {',
|
||||
' "filename": "fuchsia.inspect.Tree",',
|
||||
' "component_url": "fuchsia-pkg://fuchsia.com/flutter_runner#meta/flutter_runner.cm",',
|
||||
' "timestamp": 12345678901234',
|
||||
' },',
|
||||
' "moniker": "core/session-manager/session/flutter_runner",',
|
||||
' "payload": {',
|
||||
' "root": {',
|
||||
' "vm_service_port": "12345",',
|
||||
' "16859221": {',
|
||||
' "empty_tree": "this semantic tree is empty"',
|
||||
' },',
|
||||
' "build_info": {',
|
||||
' "dart_sdk_git_revision": "77e83fcc14fa94049f363d554579f48fbd6bb7a1",',
|
||||
' "dart_sdk_semantic_version": "2.19.0-317.0.dev",',
|
||||
' "flutter_engine_git_revision": "563b8e830c697a543bf0a8a9f4ae3edfad86ea86",',
|
||||
' "fuchsia_sdk_version": "10.20221018.0.1"',
|
||||
' },',
|
||||
' "vm": {',
|
||||
' "dst_status": 1,',
|
||||
' "get_profile_status": 0,',
|
||||
' "num_get_profile_calls": 1,',
|
||||
' "num_intl_provider_errors": 0,',
|
||||
' "num_on_change_calls": 0,',
|
||||
' "timezone_content_status": 0,',
|
||||
' "tz_data_close_status": -1,',
|
||||
' "tz_data_status": -1',
|
||||
' }',
|
||||
' }',
|
||||
' },',
|
||||
' "version": 1',
|
||||
' }',
|
||||
' ]'
|
||||
];
|
||||
fakeRunner.address = 'fe80::8eae:4cff:fef4:9247';
|
||||
fakeRunner.interface = 'eno1';
|
||||
|
||||
final FuchsiaRemoteConnection connection =
|
||||
await FuchsiaRemoteConnection.connectWithSshCommandRunner(fakeRunner);
|
||||
|
||||
// [fakePortForwardingFunction] will have returned three different
|
||||
// forwarded ports, incrementing the port each time by one. (Just a sanity
|
||||
// check that the forwarding port was called).
|
||||
expect(forwardedPorts.length, 3);
|
||||
expect(forwardedPorts[0].remotePort, 123);
|
||||
expect(forwardedPorts[1].remotePort, 456);
|
||||
expect(forwardedPorts[2].remotePort, 789);
|
||||
expect(forwardedPorts[0].port, 0);
|
||||
expect(forwardedPorts[1].port, 1);
|
||||
expect(forwardedPorts[2].port, 2);
|
||||
expect(forwardedPorts.length, 1);
|
||||
expect(forwardedPorts[0].remotePort, 12345);
|
||||
|
||||
// VMs should be accessed via localhost ports given by
|
||||
// [fakePortForwardingFunction].
|
||||
expect(uriConnections[0],
|
||||
Uri(scheme:'ws', host:'[::1]', port:0, path:'/ws'));
|
||||
expect(uriConnections[1],
|
||||
Uri(scheme:'ws', host:'[::1]', port:1, path:'/ws'));
|
||||
expect(uriConnections[2],
|
||||
Uri(scheme:'ws', host:'[::1]', port:2, path:'/ws'));
|
||||
Uri(scheme: 'ws', host: '[::1]', port: 0, path: '/ws'));
|
||||
|
||||
final List<FlutterView> views = await connection.getFlutterViews();
|
||||
expect(views, isNot(null));
|
||||
expect(views.length, 3);
|
||||
expect(views.length, 1);
|
||||
// Since name can be null, check for the ID on all of them.
|
||||
expect(views[0].id, 'flutterView0');
|
||||
expect(views[1].id, 'flutterView1');
|
||||
expect(views[2].id, 'flutterView2');
|
||||
|
||||
expect(views[0].name, equals(null));
|
||||
expect(views[1].name, 'file://flutterBinary1');
|
||||
expect(views[2].name, 'file://flutterBinary2');
|
||||
|
||||
// Ensure the ports are all closed after stop was called.
|
||||
await connection.stop();
|
||||
expect(forwardedPorts[0].stopped, true);
|
||||
expect(forwardedPorts[1].stopped, true);
|
||||
expect(forwardedPorts[2].stopped, true);
|
||||
});
|
||||
|
||||
test('end-to-end with three vms and remote open port', () async {
|
||||
test('end-to-end with one vm and remote open port', () async {
|
||||
int port = 0;
|
||||
Future<PortForwarder> fakePortForwardingFunction(
|
||||
String address,
|
||||
@ -170,53 +188,71 @@ void main() {
|
||||
fuchsiaPortForwardingFunction = fakePortForwardingFunction;
|
||||
final FakeSshCommandRunner fakeRunner = FakeSshCommandRunner();
|
||||
// Adds some extra junk to make sure the strings will be cleaned up.
|
||||
fakeRunner.findResponse = <String>['/hub/blah/blah/blah/vmservice-port\n'];
|
||||
fakeRunner.lsResponse = <String>['123\n\n\n', '456 ', '789'];
|
||||
fakeRunner.iqueryResponse = <String>[
|
||||
'[',
|
||||
' {',
|
||||
' "data_source": "Inspect",',
|
||||
' "metadata": {',
|
||||
' "filename": "fuchsia.inspect.Tree",',
|
||||
' "component_url": "fuchsia-pkg://fuchsia.com/flutter_runner#meta/flutter_runner.cm",',
|
||||
' "timestamp": 12345678901234',
|
||||
' },',
|
||||
' "moniker": "core/session-manager/session/flutter_runner",',
|
||||
' "payload": {',
|
||||
' "root": {',
|
||||
' "vm_service_port": "12345",',
|
||||
' "16859221": {',
|
||||
' "empty_tree": "this semantic tree is empty"',
|
||||
' },',
|
||||
' "build_info": {',
|
||||
' "dart_sdk_git_revision": "77e83fcc14fa94049f363d554579f48fbd6bb7a1",',
|
||||
' "dart_sdk_semantic_version": "2.19.0-317.0.dev",',
|
||||
' "flutter_engine_git_revision": "563b8e830c697a543bf0a8a9f4ae3edfad86ea86",',
|
||||
' "fuchsia_sdk_version": "10.20221018.0.1"',
|
||||
' },',
|
||||
' "vm": {',
|
||||
' "dst_status": 1,',
|
||||
' "get_profile_status": 0,',
|
||||
' "num_get_profile_calls": 1,',
|
||||
' "num_intl_provider_errors": 0,',
|
||||
' "num_on_change_calls": 0,',
|
||||
' "timezone_content_status": 0,',
|
||||
' "tz_data_close_status": -1,',
|
||||
' "tz_data_status": -1',
|
||||
' }',
|
||||
' }',
|
||||
' },',
|
||||
' "version": 1',
|
||||
' }',
|
||||
' ]'
|
||||
];
|
||||
fakeRunner.address = 'fe80::8eae:4cff:fef4:9247';
|
||||
fakeRunner.interface = 'eno1';
|
||||
final FuchsiaRemoteConnection connection =
|
||||
await FuchsiaRemoteConnection.connectWithSshCommandRunner(fakeRunner);
|
||||
|
||||
// [fakePortForwardingFunction] will have returned three different
|
||||
// forwarded ports, incrementing the port each time by one. (Just a sanity
|
||||
// check that the forwarding port was called).
|
||||
expect(forwardedPorts.length, 3);
|
||||
expect(forwardedPorts[0].remotePort, 123);
|
||||
expect(forwardedPorts[1].remotePort, 456);
|
||||
expect(forwardedPorts[2].remotePort, 789);
|
||||
expect(forwardedPorts[0].port, 0);
|
||||
expect(forwardedPorts[1].port, 1);
|
||||
expect(forwardedPorts[2].port, 2);
|
||||
expect(forwardedPorts.length, 1);
|
||||
expect(forwardedPorts[0].remotePort, 12345);
|
||||
|
||||
// VMs should be accessed via the alternate address given by
|
||||
// [fakePortForwardingFunction].
|
||||
expect(uriConnections[0],
|
||||
Uri(scheme:'ws', host:'[fe80::1:2%25eno2]', port:0, path:'/ws'));
|
||||
expect(uriConnections[1],
|
||||
Uri(scheme:'ws', host:'[fe80::1:2%25eno2]', port:1, path:'/ws'));
|
||||
expect(uriConnections[2],
|
||||
Uri(scheme:'ws', host:'[fe80::1:2%25eno2]', port:2, path:'/ws'));
|
||||
Uri(scheme: 'ws', host: '[fe80::1:2%25eno2]', port: 0, path: '/ws'));
|
||||
|
||||
final List<FlutterView> views = await connection.getFlutterViews();
|
||||
expect(views, isNot(null));
|
||||
expect(views.length, 3);
|
||||
expect(views.length, 1);
|
||||
// Since name can be null, check for the ID on all of them.
|
||||
expect(views[0].id, 'flutterView0');
|
||||
expect(views[1].id, 'flutterView1');
|
||||
expect(views[2].id, 'flutterView2');
|
||||
|
||||
expect(views[0].name, equals(null));
|
||||
expect(views[1].name, 'file://flutterBinary1');
|
||||
expect(views[2].name, 'file://flutterBinary2');
|
||||
|
||||
// Ensure the ports are all closed after stop was called.
|
||||
await connection.stop();
|
||||
expect(forwardedPorts[0].stopped, true);
|
||||
expect(forwardedPorts[1].stopped, true);
|
||||
expect(forwardedPorts[2].stopped, true);
|
||||
});
|
||||
|
||||
test('end-to-end with three vms and ipv4', () async {
|
||||
test('end-to-end with one vm and ipv4', () async {
|
||||
int port = 0;
|
||||
Future<PortForwarder> fakePortForwardingFunction(
|
||||
String address,
|
||||
@ -236,49 +272,67 @@ void main() {
|
||||
fuchsiaPortForwardingFunction = fakePortForwardingFunction;
|
||||
final FakeSshCommandRunner fakeRunner = FakeSshCommandRunner();
|
||||
// Adds some extra junk to make sure the strings will be cleaned up.
|
||||
fakeRunner.findResponse = <String>['/hub/blah/blah/blah/vmservice-port\n'];
|
||||
fakeRunner.lsResponse = <String>['123\n\n\n', '456 ', '789'];
|
||||
fakeRunner.iqueryResponse = <String>[
|
||||
'[',
|
||||
' {',
|
||||
' "data_source": "Inspect",',
|
||||
' "metadata": {',
|
||||
' "filename": "fuchsia.inspect.Tree",',
|
||||
' "component_url": "fuchsia-pkg://fuchsia.com/flutter_runner#meta/flutter_runner.cm",',
|
||||
' "timestamp": 12345678901234',
|
||||
' },',
|
||||
' "moniker": "core/session-manager/session/flutter_runner",',
|
||||
' "payload": {',
|
||||
' "root": {',
|
||||
' "vm_service_port": "12345",',
|
||||
' "16859221": {',
|
||||
' "empty_tree": "this semantic tree is empty"',
|
||||
' },',
|
||||
' "build_info": {',
|
||||
' "dart_sdk_git_revision": "77e83fcc14fa94049f363d554579f48fbd6bb7a1",',
|
||||
' "dart_sdk_semantic_version": "2.19.0-317.0.dev",',
|
||||
' "flutter_engine_git_revision": "563b8e830c697a543bf0a8a9f4ae3edfad86ea86",',
|
||||
' "fuchsia_sdk_version": "10.20221018.0.1"',
|
||||
' },',
|
||||
' "vm": {',
|
||||
' "dst_status": 1,',
|
||||
' "get_profile_status": 0,',
|
||||
' "num_get_profile_calls": 1,',
|
||||
' "num_intl_provider_errors": 0,',
|
||||
' "num_on_change_calls": 0,',
|
||||
' "timezone_content_status": 0,',
|
||||
' "tz_data_close_status": -1,',
|
||||
' "tz_data_status": -1',
|
||||
' }',
|
||||
' }',
|
||||
' },',
|
||||
' "version": 1',
|
||||
' }',
|
||||
' ]'
|
||||
];
|
||||
fakeRunner.address = '196.168.1.4';
|
||||
|
||||
final FuchsiaRemoteConnection connection =
|
||||
await FuchsiaRemoteConnection.connectWithSshCommandRunner(fakeRunner);
|
||||
|
||||
// [fakePortForwardingFunction] will have returned three different
|
||||
// forwarded ports, incrementing the port each time by one. (Just a sanity
|
||||
// check that the forwarding port was called).
|
||||
expect(forwardedPorts.length, 3);
|
||||
expect(forwardedPorts[0].remotePort, 123);
|
||||
expect(forwardedPorts[1].remotePort, 456);
|
||||
expect(forwardedPorts[2].remotePort, 789);
|
||||
expect(forwardedPorts[0].port, 0);
|
||||
expect(forwardedPorts[1].port, 1);
|
||||
expect(forwardedPorts[2].port, 2);
|
||||
expect(forwardedPorts.length, 1);
|
||||
expect(forwardedPorts[0].remotePort, 12345);
|
||||
|
||||
// VMs should be accessed via the ipv4 loopback.
|
||||
expect(uriConnections[0],
|
||||
Uri(scheme:'ws', host:'127.0.0.1', port:0, path:'/ws'));
|
||||
expect(uriConnections[1],
|
||||
Uri(scheme:'ws', host:'127.0.0.1', port:1, path:'/ws'));
|
||||
expect(uriConnections[2],
|
||||
Uri(scheme:'ws', host:'127.0.0.1', port:2, path:'/ws'));
|
||||
Uri(scheme: 'ws', host: '127.0.0.1', port: 0, path: '/ws'));
|
||||
|
||||
final List<FlutterView> views = await connection.getFlutterViews();
|
||||
expect(views, isNot(null));
|
||||
expect(views.length, 3);
|
||||
expect(views.length, 1);
|
||||
// Since name can be null, check for the ID on all of them.
|
||||
expect(views[0].id, 'flutterView0');
|
||||
expect(views[1].id, 'flutterView1');
|
||||
expect(views[2].id, 'flutterView2');
|
||||
|
||||
expect(views[0].name, equals(null));
|
||||
expect(views[1].name, 'file://flutterBinary1');
|
||||
expect(views[2].name, 'file://flutterBinary2');
|
||||
|
||||
// Ensure the ports are all closed after stop was called.
|
||||
await connection.stop();
|
||||
expect(forwardedPorts[0].stopped, true);
|
||||
expect(forwardedPorts[1].stopped, true);
|
||||
expect(forwardedPorts[2].stopped, true);
|
||||
});
|
||||
|
||||
test('env variable test without remote addr', () async {
|
||||
@ -294,15 +348,11 @@ void main() {
|
||||
}
|
||||
|
||||
class FakeSshCommandRunner extends Fake implements SshCommandRunner {
|
||||
List<String>? findResponse;
|
||||
List<String>? lsResponse;
|
||||
List<String>? iqueryResponse;
|
||||
@override
|
||||
Future<List<String>> run(String command) async {
|
||||
if (command.startsWith('/bin/find')) {
|
||||
return findResponse!;
|
||||
}
|
||||
if (command.startsWith('/bin/ls')) {
|
||||
return lsResponse!;
|
||||
if (command.startsWith('iquery --format json show')) {
|
||||
return iqueryResponse!;
|
||||
}
|
||||
throw UnimplementedError(command);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user