Chromium Code Reviews| Index: dart/tests/standalone/io/secure_socket_alpn_test.dart |
| diff --git a/dart/tests/standalone/io/secure_socket_alpn_test.dart b/dart/tests/standalone/io/secure_socket_alpn_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d2f276871564eeccb12321514e272bcb4f05c068 |
| --- /dev/null |
| +++ b/dart/tests/standalone/io/secure_socket_alpn_test.dart |
| @@ -0,0 +1,221 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
|
Søren Gjesse
2014/11/10 11:38:00
2014
kustermann
2014/11/10 12:30:21
Done.
|
| +// 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. |
| +// |
| +// This test tests TLS session resume, by making multiple client connections |
|
Søren Gjesse
2014/11/10 11:38:00
This description does not fit with what is being t
kustermann
2014/11/10 12:30:21
Done.
|
| +// on the same port to the same server, with a delay of 200 ms between them. |
| +// The unmodified secure_server_test creates all sessions simultaneously, |
| +// which means that no handshake completes and caches its keys in the session |
| +// cache in time for other connections to use it. |
| + |
| +import 'dart:io'; |
| +import 'dart:convert'; |
| + |
| +import 'package:expect/expect.dart'; |
| +import 'package:async_helper/async_helper.dart'; |
| + |
| +const String MAX_LEN_ERROR = |
| + 'Length of protocol must be between 1 and 255'; |
| + |
| +const String MAX_MSG_LEN_ERROR = |
| + 'The maximum message length supported is 2^15-1'; |
| + |
| +void InitializeSSL() { |
| + var testPkcertDatabase = Platform.script.resolve('pkcert').toFilePath(); |
| + SecureSocket.initialize(database: testPkcertDatabase, |
| + password: 'dartdart'); |
| +} |
| + |
| + |
| +// Tests that client/server with same protocol can securly establish a |
| +// connection, negogiate the protocol and can send data to each other. |
| +void testSuccessfulAlpnNegogiationConnection(List<String> clientProtocols, |
| + List<String> serverProtocols, |
| + String selectedProtocol) { |
| + asyncStart(); |
| + SecureServerSocket.bind('localhost', 0, 'localhost_cert', |
| + supportedProtocols: serverProtocols).then((SecureServerSocket server) { |
| + |
| + asyncStart(); |
| + server.first.then((SecureSocket socket) { |
| + Expect.equals(selectedProtocol, socket.selectedProtocol); |
| + socket..write('server message')..close(); |
| + socket.transform(ASCII.decoder).join('').then((String s) { |
| + Expect.equals('client message', s); |
| + asyncEnd(); |
| + }); |
| + }); |
| + |
| + asyncStart(); |
| + SecureSocket.connect('localhost', server.port, |
| + supportedProtocols: clientProtocols).then((socket) { |
| + Expect.equals(selectedProtocol, socket.selectedProtocol); |
| + socket..write('client message')..close(); |
| + socket.transform(ASCII.decoder).join('').then((String s) { |
| + Expect.equals('server message', s); |
| + server.close(); |
| + asyncEnd(); |
| + }); |
| + }); |
| + |
| + asyncEnd(); |
| + }); |
| +} |
| + |
| +void testFailedAlpnNegogiationConnection(List<String> clientProtocols, |
| + List<String> serverProtocols) { |
| + asyncStart(); |
| + SecureServerSocket.bind('localhost', 0, 'localhost_cert', |
| + supportedProtocols: serverProtocols).then((SecureServerSocket server) { |
| + |
| + asyncStart(); |
| + server.first.catchError((error, stack) { |
|
Søren Gjesse
2014/11/10 11:38:00
Add a test of the error type?
kustermann
2014/11/10 12:30:21
Added
Expect.isTrue(error is HandshakeException);
|
| + asyncEnd(); |
| + }); |
| + |
| + asyncStart(); |
| + SecureSocket.connect('localhost', |
| + server.port, |
| + supportedProtocols: clientProtocols) |
| + .catchError((error, stack) { |
|
Søren Gjesse
2014/11/10 11:38:00
Ditto.
kustermann
2014/11/10 12:30:21
ditto
|
| + asyncEnd(); |
| + }); |
| + |
| + asyncEnd(); |
| + }); |
| +} |
| + |
| + |
| +void testInvalidArgumentsLongName(List<String> protocols, |
| + bool isLenError, |
| + bool isMsgLenError) { |
| + asyncStart(); |
| + SecureServerSocket.bind('localhost', 0, 'localhost_cert', |
| + supportedProtocols: protocols).then((SecureServerSocket server) { |
| + |
| + asyncStart(); |
| + server.first.catchError((error, stack) { |
| + String errorString = '${(error as ArgumentError)}'; |
| + if (isLenError) { |
| + Expect.isTrue(errorString.contains(MAX_LEN_ERROR)); |
| + } else if (isMsgLenError) { |
| + Expect.isTrue(errorString.contains(MAX_MSG_LEN_ERROR)); |
| + } else { |
| + throw 'unreachable'; |
| + } |
| + asyncEnd(); |
| + }); |
| + |
| + asyncStart(); |
| + SecureSocket.connect('localhost', |
| + server.port, |
| + supportedProtocols: protocols) |
| + .catchError((error, stack) { |
| + String errorString = '${(error as ArgumentError)}'; |
| + if (isLenError) { |
| + Expect.isTrue(errorString.contains(MAX_LEN_ERROR)); |
| + } else if (isMsgLenError) { |
| + Expect.isTrue(errorString.contains(MAX_MSG_LEN_ERROR)); |
| + } else { |
| + throw 'unreachable'; |
| + } |
| + asyncEnd(); |
| + }); |
| + |
| + asyncEnd(); |
| + }); |
| +} |
| + |
| + |
| +main() { |
| + InitializeSSL(); |
| + final longname256 = 'p' * 256; |
| + final String longname255 = 'p' * 255; |
| + final String strangelongname255 = 'ø' + 'p' * 253; |
| + final String strangelongname256 = 'ø' + 'p' * 254; |
| + |
| + // This produces a message of (1 << 15)-2 bytes (1 length and 1 ascii byte). |
| + final List<String> allProtocols = new Iterable.generate( |
| + (1 << 14) - 1, (i) => '0').toList(); |
| + |
| + // This produces a message of (1 << 15) bytes (1 length and 1 ascii byte). |
| + final List<String> allProtocolsPlusOne = new Iterable.generate( |
| + (1 << 14), (i) => '0').toList(); |
| + |
| + // Protocols are in order of decreasing priority. First matching protocol |
| + // will be taken. |
| + |
| + // Test successfull negotiation, including priority. |
| + testSuccessfulAlpnNegogiationConnection(['a'], |
| + ['a'], |
| + 'a'); |
| + |
| + testSuccessfulAlpnNegogiationConnection([longname255], |
| + [longname255], |
| + longname255); |
| + |
| + testSuccessfulAlpnNegogiationConnection([strangelongname255], |
| + [strangelongname255], |
| + strangelongname255); |
| + |
| + testSuccessfulAlpnNegogiationConnection(allProtocols, |
| + allProtocols, |
| + '0'); |
| + |
| + testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'], |
| + ['a', 'b', 'c'], |
| + 'a'); |
| + |
| + testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'], |
| + ['c'], |
| + 'c'); |
| + |
| + // Server precedence. |
| + testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'], |
| + ['c', 'b', 'a'], |
| + 'a'); |
| + |
| + testSuccessfulAlpnNegogiationConnection(['c'], |
| + ['a', 'b', 'c'], |
| + 'c'); |
| + |
| + testSuccessfulAlpnNegogiationConnection(['s1', 'b', 'e1'], |
| + ['s2', 'b', 'e2'], |
| + 'b'); |
| + |
| + // Test no protocol negotiation support |
| + testSuccessfulAlpnNegogiationConnection(null, |
| + null, |
| + null); |
| + |
| + testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'], |
| + null, |
| + null); |
| + |
| + testSuccessfulAlpnNegogiationConnection(null, |
| + ['a', 'b', 'c'], |
| + null); |
| + |
| + testSuccessfulAlpnNegogiationConnection([], |
| + [], |
| + null); |
| + |
| + testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'], |
| + [], |
| + null); |
| + |
| + testSuccessfulAlpnNegogiationConnection([], |
| + ['a', 'b', 'c'], |
| + null); |
| + |
| + // Test non-overlapping protocols. |
| + testFailedAlpnNegogiationConnection(['a'], ['b']); |
| + |
| + |
| + // Test too short / too long protocol names. |
| + testInvalidArgumentsLongName([longname256], true, false); |
| + testInvalidArgumentsLongName([strangelongname256], true, false); |
| + testInvalidArgumentsLongName([''], true, false); |
| + testInvalidArgumentsLongName(allProtocolsPlusOne, false, true); |
| + testInvalidArgumentsLongName(allProtocolsPlusOne, false, true); |
| +} |