Skip to content

Commit

Permalink
[fuchsia] Get Dart VM service ports from The Hub (#25332)
Browse files Browse the repository at this point in the history
  • Loading branch information
zanderso committed Dec 17, 2018
1 parent 9619b53 commit b18a2b1
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 72 deletions.
17 changes: 7 additions & 10 deletions packages/flutter_driver/lib/src/common/fuchsia_compat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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>[];
}
Expand Down
52 changes: 22 additions & 30 deletions packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,35 @@ 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.
Future<String> shell(String command) async {
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;
}
Expand Down Expand Up @@ -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;
}
29 changes: 15 additions & 14 deletions packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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', () {
Expand All @@ -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('');
Expand All @@ -78,17 +68,28 @@ 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 {
await device.servicePorts();
} 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,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down

0 comments on commit b18a2b1

Please sign in to comment.