Commit ba4bba74 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Support IPv6 in test platform (#9795)

parent 2b04e300
...@@ -41,9 +41,6 @@ export 'dart:io' ...@@ -41,9 +41,6 @@ export 'dart:io'
// File NO! Use `file_system.dart` // File NO! Use `file_system.dart`
// FileSystemEntity NO! Use `file_system.dart` // FileSystemEntity NO! Use `file_system.dart`
GZIP, GZIP,
InternetAddress,
IOException,
IOSink,
HttpClient, HttpClient,
HttpClientRequest, HttpClientRequest,
HttpClientResponse, HttpClientResponse,
...@@ -51,6 +48,10 @@ export 'dart:io' ...@@ -51,6 +48,10 @@ export 'dart:io'
HttpRequest, HttpRequest,
HttpServer, HttpServer,
HttpStatus, HttpStatus,
InternetAddress,
InternetAddressType,
IOException,
IOSink,
// Link NO! Use `file_system.dart` // Link NO! Use `file_system.dart`
pid, pid,
// Platform NO! use `platform.dart` // Platform NO! use `platform.dart`
......
...@@ -43,6 +43,11 @@ class TestCommand extends FlutterCommand { ...@@ -43,6 +43,11 @@ class TestCommand extends FlutterCommand {
help: 'Whether to merge converage data with "coverage/lcov.base.info".\n' help: 'Whether to merge converage data with "coverage/lcov.base.info".\n'
'Implies collecting coverage data. (Requires lcov)' 'Implies collecting coverage data. (Requires lcov)'
); );
argParser.addFlag('ipv6',
negatable: false,
hide: true,
help: 'Whether to use IPv6 for the test harness server socket.'
);
argParser.addOption('coverage-path', argParser.addOption('coverage-path',
defaultsTo: 'coverage/lcov.info', defaultsTo: 'coverage/lcov.info',
help: 'Where to store coverage information (if coverage is enabled).' help: 'Where to store coverage information (if coverage is enabled).'
...@@ -197,6 +202,10 @@ class TestCommand extends FlutterCommand { ...@@ -197,6 +202,10 @@ class TestCommand extends FlutterCommand {
} }
testArgs.addAll(files); testArgs.addAll(files);
final InternetAddressType serverType = argResults['ipv6']
? InternetAddressType.IP_V6
: InternetAddressType.IP_V4;
final String shellPath = artifacts.getArtifactPath(Artifact.flutterTester); final String shellPath = artifacts.getArtifactPath(Artifact.flutterTester);
if (!fs.isFileSync(shellPath)) if (!fs.isFileSync(shellPath))
throwToolExit('Cannot find Flutter shell at $shellPath'); throwToolExit('Cannot find Flutter shell at $shellPath');
...@@ -204,6 +213,7 @@ class TestCommand extends FlutterCommand { ...@@ -204,6 +213,7 @@ class TestCommand extends FlutterCommand {
shellPath: shellPath, shellPath: shellPath,
collector: collector, collector: collector,
debuggerMode: argResults['start-paused'], debuggerMode: argResults['start-paused'],
serverType: serverType,
); );
Cache.releaseLockEarly(); Cache.releaseLockEarly();
......
...@@ -40,7 +40,10 @@ const String _kStartTimeoutTimerMessage = 'sky_shell test process has entered ma ...@@ -40,7 +40,10 @@ const String _kStartTimeoutTimerMessage = 'sky_shell test process has entered ma
/// The address at which our WebSocket server resides and at which the sky_shell /// The address at which our WebSocket server resides and at which the sky_shell
/// processes will host the Observatory server. /// processes will host the Observatory server.
final InternetAddress _kHost = InternetAddress.LOOPBACK_IP_V4; final Map<InternetAddressType, InternetAddress> _kHosts = <InternetAddressType, InternetAddress>{
InternetAddressType.IP_V4: InternetAddress.LOOPBACK_IP_V4,
InternetAddressType.IP_V6: InternetAddress.LOOPBACK_IP_V6,
};
/// Configure the `test` package to work with Flutter. /// Configure the `test` package to work with Flutter.
/// ///
...@@ -53,6 +56,7 @@ void installHook({ ...@@ -53,6 +56,7 @@ void installHook({
bool debuggerMode: false, bool debuggerMode: false,
int observatoryPort, int observatoryPort,
int diagnosticPort, int diagnosticPort,
InternetAddressType serverType: InternetAddressType.IP_V4,
}) { }) {
hack.registerPlatformPlugin( hack.registerPlatformPlugin(
<TestPlatform>[TestPlatform.vm], <TestPlatform>[TestPlatform.vm],
...@@ -62,6 +66,7 @@ void installHook({ ...@@ -62,6 +66,7 @@ void installHook({
debuggerMode: debuggerMode, debuggerMode: debuggerMode,
explicitObservatoryPort: observatoryPort, explicitObservatoryPort: observatoryPort,
explicitDiagnosticPort: diagnosticPort, explicitDiagnosticPort: diagnosticPort,
host: _kHosts[serverType],
), ),
); );
} }
...@@ -77,6 +82,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -77,6 +82,7 @@ class _FlutterPlatform extends PlatformPlugin {
this.debuggerMode, this.debuggerMode,
this.explicitObservatoryPort, this.explicitObservatoryPort,
this.explicitDiagnosticPort, this.explicitDiagnosticPort,
this.host,
}) { }) {
assert(shellPath != null); assert(shellPath != null);
} }
...@@ -86,6 +92,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -86,6 +92,7 @@ class _FlutterPlatform extends PlatformPlugin {
final bool debuggerMode; final bool debuggerMode;
final int explicitObservatoryPort; final int explicitObservatoryPort;
final int explicitDiagnosticPort; final int explicitDiagnosticPort;
final InternetAddress host;
// Each time loadChannel() is called, we spin up a local WebSocket server, // Each time loadChannel() is called, we spin up a local WebSocket server,
// then spin up the engine in a subprocess. We pass the engine a Dart file // then spin up the engine in a subprocess. We pass the engine a Dart file
...@@ -123,7 +130,10 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -123,7 +130,10 @@ class _FlutterPlatform extends PlatformPlugin {
return remoteChannel; return remoteChannel;
} }
Future<Null> _startTest(String testPath, StreamChannel<dynamic> controller, int ourTestCount) async { Future<Null> _startTest(
String testPath,
StreamChannel<dynamic> controller,
int ourTestCount) async {
printTrace('test $ourTestCount: starting test $testPath'); printTrace('test $ourTestCount: starting test $testPath');
dynamic outOfBandError; // error that we couldn't send to the harness that we need to send via our future dynamic outOfBandError; // error that we couldn't send to the harness that we need to send via our future
...@@ -135,7 +145,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -135,7 +145,7 @@ class _FlutterPlatform extends PlatformPlugin {
controller.sink.done.whenComplete(() { controllerSinkClosed = true; }); controller.sink.done.whenComplete(() { controllerSinkClosed = true; });
// Prepare our WebSocket server to talk to the engine subproces. // Prepare our WebSocket server to talk to the engine subproces.
final HttpServer server = await HttpServer.bind(_kHost, 0); final HttpServer server = await HttpServer.bind(host, 0);
finalizers.add(() async { finalizers.add(() async {
printTrace('test $ourTestCount: shutting down test harness socket server'); printTrace('test $ourTestCount: shutting down test harness socket server');
await server.close(force: true); await server.close(force: true);
...@@ -171,7 +181,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -171,7 +181,7 @@ class _FlutterPlatform extends PlatformPlugin {
listenerFile.createSync(); listenerFile.createSync();
listenerFile.writeAsStringSync(_generateTestMain( listenerFile.writeAsStringSync(_generateTestMain(
testUrl: fs.path.toUri(fs.path.absolute(testPath)).toString(), testUrl: fs.path.toUri(fs.path.absolute(testPath)).toString(),
encodedWebsocketUrl: Uri.encodeComponent("ws://${_kHost.address}:${server.port}"), encodedWebsocketUrl: Uri.encodeComponent(_getWebSocketUrl(server)),
)); ));
// Start the engine subprocess. // Start the engine subprocess.
...@@ -215,7 +225,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -215,7 +225,7 @@ class _FlutterPlatform extends PlatformPlugin {
if (debuggerMode) { if (debuggerMode) {
printStatus('The test process has been started.'); printStatus('The test process has been started.');
printStatus('You can now connect to it using observatory. To connect, load the following Web site in your browser:'); printStatus('You can now connect to it using observatory. To connect, load the following Web site in your browser:');
printStatus(' http://${_kHost.address}:$detectedPort/'); printStatus(' http://${host.address}:$detectedPort/');
printStatus('You should first set appropriate breakpoints, then resume the test in the debugger.'); printStatus('You should first set appropriate breakpoints, then resume the test in the debugger.');
} else { } else {
printTrace('test $ourTestCount: using observatory port $detectedPort from pid ${process.pid} to collect coverage'); printTrace('test $ourTestCount: using observatory port $detectedPort from pid ${process.pid} to collect coverage');
...@@ -333,7 +343,7 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -333,7 +343,7 @@ class _FlutterPlatform extends PlatformPlugin {
if (subprocessActive && collector != null) { if (subprocessActive && collector != null) {
printTrace('test $ourTestCount: collecting coverage'); printTrace('test $ourTestCount: collecting coverage');
await collector.collectCoverage(process, _kHost, processObservatoryPort); await collector.collectCoverage(process, host, processObservatoryPort);
} }
} catch (error, stack) { } catch (error, stack) {
printTrace('test $ourTestCount: error caught during test; ${controllerSinkClosed ? "reporting to console" : "sending to test framework"}'); printTrace('test $ourTestCount: error caught during test; ${controllerSinkClosed ? "reporting to console" : "sending to test framework"}');
...@@ -374,6 +384,12 @@ class _FlutterPlatform extends PlatformPlugin { ...@@ -374,6 +384,12 @@ class _FlutterPlatform extends PlatformPlugin {
return null; return null;
} }
String _getWebSocketUrl(HttpServer server) {
return host.type == InternetAddressType.IP_V4
? "ws://${host.address}:${server.port}"
: "ws://[${host.address}]:${server.port}";
}
String _generateTestMain({ String _generateTestMain({
String testUrl, String testUrl,
String encodedWebsocketUrl, String encodedWebsocketUrl,
...@@ -475,14 +491,14 @@ void main() { ...@@ -475,14 +491,14 @@ void main() {
return processManager.start(command, environment: environment); return processManager.start(command, environment: environment);
} }
String get observatoryPortString => 'Observatory listening on http://${_kHost.address}:';
String get diagnosticPortString => 'Diagnostic server listening on http://${_kHost.address}:';
void _pipeStandardStreamsToConsole( void _pipeStandardStreamsToConsole(
Process process, { Process process, {
void startTimeoutTimer(), void startTimeoutTimer(),
void reportObservatoryPort(int port), void reportObservatoryPort(int port),
}) { }) {
final String observatoryPortString = 'Observatory listening on http://${host.address}:';
final String diagnosticPortString = 'Diagnostic server listening on http://${host.address}:';
for (Stream<List<int>> stream in for (Stream<List<int>> stream in
<Stream<List<int>>>[process.stderr, process.stdout]) { <Stream<List<int>>>[process.stderr, process.stdout]) {
stream.transform(UTF8.decoder) stream.transform(UTF8.decoder)
......
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