end to end connect test for websocket
diff --git a/test/mochiweb_test_util.erl b/test/mochiweb_test_util.erl
index ccfc611..690f134 100644
--- a/test/mochiweb_test_util.erl
+++ b/test/mochiweb_test_util.erl
@@ -1,5 +1,5 @@
 -module(mochiweb_test_util).
--export([with_server/3, client_request/4]).
+-export([with_server/3, client_request/4, sock_fun/2]).
 -include("mochiweb_test_util.hrl").
 
 ssl_cert_opts() ->
@@ -23,9 +23,9 @@
     mochiweb_http:stop(Server),
     Res.
 
-client_request(Transport, Port, Method, TestReqs) ->
+sock_fun(Transport, Port) ->
     Opts = [binary, {active, false}, {packet, http}],
-    SockFun = case Transport of
+    case Transport of
         plain ->
             {ok, Socket} = gen_tcp:connect("127.0.0.1", Port, Opts),
             fun (recv) ->
@@ -48,8 +48,10 @@
                 ({setopts, L}) ->
                     ssl:setopts(Socket, L)
             end
-    end,
-    client_request(SockFun, Method, TestReqs).
+    end.
+
+client_request(Transport, Port, Method, TestReqs) ->
+    client_request(sock_fun(Transport, Port), Method, TestReqs).
 
 client_request(SockFun, _Method, []) ->
     {the_end, {error, closed}} = {the_end, SockFun(recv)},
diff --git a/test/mochiweb_websocket_tests.erl b/test/mochiweb_websocket_tests.erl
index 890aa17..20967fb 100644
--- a/test/mochiweb_websocket_tests.erl
+++ b/test/mochiweb_websocket_tests.erl
@@ -82,3 +82,70 @@
        mochiweb_websocket:parse_hixie_frames(
          <<0,102,111,111,255,0,98,97,114,255>>,
          [])).
+
+end_to_end_test_factory(ServerTransport) ->
+    mochiweb_test_util:with_server(
+      ServerTransport,
+      fun end_to_end_server/1,
+      fun (Transport, Port) ->
+              end_to_end_client(mochiweb_test_util:sock_fun(Transport, Port))
+      end).
+
+end_to_end_server(Req) ->
+    ?assertEqual("Upgrade", Req:get_header_value("connection")),
+    ?assertEqual("websocket", Req:get_header_value("upgrade")),
+    {ReentryWs, _ReplyChannel} = mochiweb_websocket:upgrade_connection(
+                                   Req,
+                                   fun end_to_end_ws_loop/3),
+    ReentryWs(ok).
+
+end_to_end_ws_loop(_Payload, State, _ReplyChannel) ->
+    State.
+
+end_to_end_client(S) ->
+    UpgradeReq = string:join(
+                   ["GET / HTTP/1.1",
+                    "Host: localhost",
+                    "Upgrade: websocket",
+                    "Connection: Upgrade",
+                    "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==",
+                    "",
+                    ""], "\r\n"),
+    ok = S({send, UpgradeReq}),
+    {ok, {http_response, {1,1}, 101, _}} = S(recv),
+    ok = S({setopts, [{packet, httph}]}),
+    D = read_expected_headers(
+          S,
+          gb_from_list(
+            [{'Upgrade', "websocket"},
+             {'Connection', "Upgrade"},
+             {'Content-Length', "0"},
+             {"Sec-Websocket-Accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}])),
+    ?assertEqual([], gb_trees:to_list(D)),
+    ok = S({setopts, [{packet, raw}]}),
+    ok.
+
+gb_from_list(L) ->
+    lists:foldl(
+      fun ({K, V}, D) -> gb_trees:insert(K, V, D) end,
+      gb_trees:empty(),
+      L).
+
+read_expected_headers(S, D) ->
+    case S(recv) of
+        {ok, http_eoh} ->
+            D;
+        {ok, {http_header, _, K, _, V}} ->
+            case gb_trees:lookup(K, D) of
+                {value, V1} ->
+                    ?assertEqual({K, V}, {K, V1}),
+                    read_expected_headers(S, gb_trees:delete(K, D));
+                none ->
+                    read_expected_headers(S, D)
+            end
+    end.
+
+end_to_end_test_() ->
+    [{"http", ?_assertEqual(ok, end_to_end_test_factory(plain))}
+    ,{"https", ?_assertEqual(ok, end_to_end_test_factory(ssl))}
+    ].