// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// 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.
//
// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write

import "package:expect/expect.dart";
import "dart:async";
import "dart:io";


testEmptyProtocol() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      WebSocketTransformer.upgrade(request).then((websocket) {
        websocket.close();
      });
    });
    WebSocket.connect("ws://127.0.0.1:${server.port}/",
                      protocols: []).then((client) {
      Expect.isNull(client.protocol);
      client.close();
      server.close();
    });
  });
}


testProtocol(List<String> protocols, String used) {
  selector(List<String> receivedProtocols) {
    Expect.listEquals(protocols, receivedProtocols);
    return used;
  }
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      WebSocketTransformer.upgrade(request,
                                   protocolSelector: selector)
        .then((websocket) {
          Expect.equals(used, websocket.protocol);
          websocket.close();
        });
    });
    WebSocket.connect("ws://127.0.0.1:${server.port}/",
                      protocols: protocols).then((client) {
      Expect.equals(used, client.protocol);
      client.close();
      server.close();
    });
  });
}


testProtocolHandler() {
  // Test throwing an error.
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      selector(List<String> receivedProtocols) {
        throw "error";
      }
      WebSocketTransformer.upgrade(request,
                                   protocolSelector: selector)
        .then((websocket) {
          Expect.fail('error expected');
        }, onError: (error) {
          Expect.equals('error', error);
        });
    });
    WebSocket.connect("ws://127.0.0.1:${server.port}/",
                      protocols: ["v1.example.com"])
      .then((client) {
        Expect.fail('error expected');
      }, onError: (error) {
        server.close();
      });
  });

  // Test returning another protocol.
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      selector(List<String> receivedProtocols) => "v2.example.com";
      WebSocketTransformer.upgrade(request,
                                   protocolSelector: selector)
        .then((websocket) {
          Expect.fail('error expected');
        }, onError: (error) {
          Expect.isTrue(error is WebSocketException);
        });
    });
    WebSocket.connect("ws://127.0.0.1:${server.port}/",
                      protocols: ["v1.example.com"])
      .then((client) {
        Expect.fail('error expected');
      }, onError: (error) {
        server.close();
      });
  });
}


void main() {
  testEmptyProtocol();
  testProtocol(["v1.example.com", "v2.example.com"], "v1.example.com");
  testProtocol(["v1.example.com", "v2.example.com"], "v2.example.com");
  testProtocolHandler();
}

