Unverified Commit b18a2b17 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[fuchsia] Get Dart VM service ports from The Hub (#25332)

parent 9619b53d
......@@ -13,9 +13,6 @@ import 'package:fuchsia_remote_debug_protocol/fuchsia_remote_debug_protocol.dart
import 'error.dart';
// TODO(awdavies): Update this to use the hub.
final Directory _kDartPortDir = Directory('/tmp/dart.services');
class _DummyPortForwarder implements PortForwarder {
_DummyPortForwarder(this._port, this._remotePort);
......@@ -49,13 +46,13 @@ class _DummySshCommandRunner implements SshCommandRunner {
@override
Future<List<String>> run(String command) async {
try {
return List<String>.of(_kDartPortDir
.listSync(recursive: false, followLinks: false)
.map((FileSystemEntity entity) => entity.path
.replaceAll(entity.parent.path, '')
.replaceFirst(Platform.pathSeparator, '')));
} on FileSystemException catch (e) {
_log.warning('Error listing directory: $e');
final List<String> splitCommand = command.split(' ');
final String exe = splitCommand[0];
final List<String> args = splitCommand.skip(1).toList();
final ProcessResult r = Process.runSync(exe, args);
return r.stdout.split('\n');
} on ProcessException catch (e) {
_log.warning("Error running '$command': $e");
}
return <String>[];
}
......
......@@ -216,8 +216,28 @@ class FuchsiaDevice extends Device {
/// List the ports currently running a dart observatory.
Future<List<int>> servicePorts() async {
final String lsOutput = await shell('ls /tmp/dart.services');
return parseFuchsiaDartPortOutput(lsOutput);
final String findOutput = await shell('find /hub -name vmservice-port');
if (findOutput.trim() == '') {
throwToolExit('No Dart Observatories found. Are you running a debug build?');
return null;
}
final List<int> ports = <int>[];
for (String path in findOutput.split('\n')) {
if (path == '') {
continue;
}
final String lsOutput = await shell('ls $path');
for (String line in lsOutput.split('\n')) {
if (line == '') {
continue;
}
final int port = int.tryParse(line);
if (port != null) {
ports.add(port);
}
}
}
return ports;
}
/// Run `command` on the Fuchsia device shell.
......@@ -225,9 +245,6 @@ class FuchsiaDevice extends Device {
final RunResult result = await runAsync(<String>[
'ssh', '-F', fuchsiaArtifacts.sshConfig.absolute.path, id, command]);
if (result.exitCode != 0) {
if (result.stderr.contains('/tmp/dart.services: No such file or directory')) {
throwToolExit('No Dart Observatories found. Are you running a debug build?');
}
throwToolExit('Command failed: $command\nstdout: ${result.stdout}\nstderr: ${result.stderr}');
return null;
}
......@@ -336,28 +353,3 @@ class FuchsiaModulePackage extends ApplicationPackage {
@override
final String name;
}
/// Parses output from `dart.services` output on a fuchsia device.
///
/// Example output:
/// $ ls /tmp/dart.services
/// > d 2 0 .
/// > - 1 0 36780
@visibleForTesting
List<int> parseFuchsiaDartPortOutput(String text) {
final List<int> ports = <int>[];
if (text == null)
return ports;
for (String line in text.split('\n')) {
final String trimmed = line.trim();
final int lastSpace = trimmed.lastIndexOf(' ');
final String lastWord = trimmed.substring(lastSpace + 1);
if ((lastWord != '.') && (lastWord != '..')) {
final int value = int.tryParse(lastWord);
if (value != null) {
ports.add(value);
}
}
}
return ports;
}
......@@ -36,16 +36,6 @@ void main() {
expect(names.length, 1);
expect(names.first, 'lilia-shore-only-last');
});
test('parse ls tmp/dart.servies output', () {
const String example = '''
d 2 0 .
'- 1 0 36780
''';
final List<int> ports = parseFuchsiaDartPortOutput(example);
expect(ports.length, 1);
expect(ports.single, 36780);
});
});
group('displays friendly error when', () {
......@@ -60,7 +50,7 @@ d 2 0 .
)).thenAnswer((Invocation invocation) => Future<ProcessResult>.value(mockProcessResult));
when(mockProcessResult.exitCode).thenReturn(1);
when<String>(mockProcessResult.stdout).thenReturn('');
when<String>(mockProcessResult.stderr).thenReturn('ls: lstat /tmp/dart.services: No such file or directory');
when<String>(mockProcessResult.stderr).thenReturn('');
when(mockFuchsiaArtifacts.sshConfig).thenReturn(mockFile);
when(mockFile.absolute).thenReturn(mockFile);
when(mockFile.path).thenReturn('');
......@@ -78,7 +68,18 @@ d 2 0 .
ProcessManager: () => mockProcessManager,
});
testUsingContext('with BUILD_DIR set', () async {
final MockProcessManager emptyStdoutProcessManager = MockProcessManager();
final MockProcessResult emptyStdoutProcessResult = MockProcessResult();
when(emptyStdoutProcessManager.run(
any,
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((Invocation invocation) => Future<ProcessResult>.value(emptyStdoutProcessResult));
when(emptyStdoutProcessResult.exitCode).thenReturn(0);
when<String>(emptyStdoutProcessResult.stdout).thenReturn('');
when<String>(emptyStdoutProcessResult.stderr).thenReturn('');
testUsingContext('No vmservices found', () async {
final FuchsiaDevice device = FuchsiaDevice('id');
ToolExit toolExit;
try {
......@@ -86,9 +87,9 @@ d 2 0 .
} on ToolExit catch (err) {
toolExit = err;
}
expect(toolExit.message, 'No Dart Observatories found. Are you running a debug build?');
expect(toolExit.message, contains('No Dart Observatories found. Are you running a debug build?'));
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
ProcessManager: () => emptyStdoutProcessManager,
FuchsiaArtifacts: () => mockFuchsiaArtifacts,
});
......
......@@ -523,24 +523,21 @@ 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 {
// TODO(awdavies): This is using a temporary workaround rather than a
// well-defined service, and will be deprecated in the near future.
final List<String> lsOutput =
await _sshCommandRunner.run('ls /tmp/dart.services');
final List<String> portPaths =
await _sshCommandRunner.run('find /hub -name vmservice-port');
final List<int> ports = <int>[];
// The output of lsOutput is a list of available ports as the Fuchsia dart
// service advertises. An example lsOutput would look like:
//
// [ '31782\n', '1234\n', '11967' ]
for (String s in lsOutput) {
final String trimmed = s.trim();
final int lastSpace = trimmed.lastIndexOf(' ');
final String lastWord = trimmed.substring(lastSpace + 1);
if ((lastWord != '.') && (lastWord != '..')) {
final int value = int.tryParse(lastWord);
if (value != null) {
ports.add(value);
for (String path in portPaths) {
if (path == '') {
continue;
}
final List<String> lsOutput = await _sshCommandRunner.run('ls $path');
for (String line in lsOutput) {
if (line == '') {
continue;
}
final int port = int.tryParse(line);
if (port != null) {
ports.add(port);
}
}
}
......
......@@ -21,7 +21,9 @@ void main() {
setUp(() {
mockRunner = MockSshCommandRunner();
// Adds some extra junk to make sure the strings will be cleaned up.
when(mockRunner.run(any)).thenAnswer((_) =>
when(mockRunner.run(argThat(startsWith('find')))).thenAnswer((_) =>
Future<List<String>>.value(<String>['/hub/blah/blah/blah/vmservice-port\n']));
when(mockRunner.run(argThat(startsWith('ls')))).thenAnswer((_) =>
Future<List<String>>.value(<String>['123\n\n\n', '456 ', '789']));
const String address = 'fe80::8eae:4cff:fef4:9247';
const String interface = 'eno1';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment