Subversion Repositories SE.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12 7u83 1
-module(mochiweb_tests).
2
 
3
-include_lib("eunit/include/eunit.hrl").
4
 
5
-include("mochiweb_test_util.hrl").
6
 
7
with_server(Transport, ServerFun, ClientFun) ->
8
    mochiweb_test_util:with_server(Transport, ServerFun,
9
				   ClientFun).
10
 
11
request_test() ->
12
    R = mochiweb_request:new(z, z,
13
			     "//foo///bar/baz%20wibble+quux?qs=2", z, []),
14
    "/foo/bar/baz wibble quux" = mochiweb_request:get(path,
15
						      R),
16
    ok.
17
 
18
-define(LARGE_TIMEOUT, 60).
19
 
20
single_http_GET_test() -> do_GET(plain, 1).
21
 
22
single_https_GET_test() -> do_GET(ssl, 1).
23
 
24
multiple_http_GET_test() -> do_GET(plain, 3).
25
 
26
multiple_https_GET_test() -> do_GET(ssl, 3).
27
 
28
hundred_http_GET_test_() ->
29
    % note the underscore
30
    {timeout, ?LARGE_TIMEOUT,
31
     fun () -> ?assertEqual(ok, (do_GET(plain, 100))) end}.
32
 
33
hundred_https_GET_test_() ->
34
    % note the underscore
35
    {timeout, ?LARGE_TIMEOUT,
36
     fun () -> ?assertEqual(ok, (do_GET(ssl, 100))) end}.
37
 
38
single_128_http_POST_test() -> do_POST(plain, 128, 1).
39
 
40
single_128_https_POST_test() -> do_POST(ssl, 128, 1).
41
 
42
single_2k_http_POST_test() -> do_POST(plain, 2048, 1).
43
 
44
single_2k_https_POST_test() -> do_POST(ssl, 2048, 1).
45
 
46
single_100k_http_POST_test_() ->
47
    % note the underscore
48
    {timeout, ?LARGE_TIMEOUT,
49
     fun () -> ?assertEqual(ok, (do_POST(plain, 102400, 1)))
50
     end}.
51
 
52
single_100k_https_POST_test_() ->
53
    % note the underscore
54
    {timeout, ?LARGE_TIMEOUT,
55
     fun () -> ?assertEqual(ok, (do_POST(ssl, 102400, 1)))
56
     end}.
57
 
58
multiple_100k_http_POST_test() ->
59
    {timeout, ?LARGE_TIMEOUT,
60
     fun () -> ?assertEqual(ok, (do_POST(plain, 102400, 3)))
61
     end}.
62
 
63
multiple_100K_https_POST_test() ->
64
    {timeout, ?LARGE_TIMEOUT,
65
     fun () -> ?assertEqual(ok, (do_POST(ssl, 102400, 3)))
66
     end}.
67
 
68
hundred_128_http_POST_test_() ->
69
    % note the underscore
70
    {timeout, ?LARGE_TIMEOUT,
71
     fun () -> ?assertEqual(ok, (do_POST(plain, 128, 100)))
72
     end}.
73
 
74
hundred_128_https_POST_test_() ->
75
    % note the underscore
76
    {timeout, ?LARGE_TIMEOUT,
77
     fun () -> ?assertEqual(ok, (do_POST(ssl, 128, 100)))
78
     end}.
79
 
80
single_GET_scheme_test_() ->
81
    [{"ssl", ?_assertEqual(ok, (do_GET("derp", ssl, 1)))},
82
     {"plain",
83
      ?_assertEqual(ok, (do_GET("derp", plain, 1)))}].
84
 
85
single_GET_absoluteURI_test_() ->
86
    Uri = "https://example.com:123/x/",
87
    ServerFun = fun (Req) ->
88
			mochiweb_request:ok({"text/plain",
89
					     mochiweb_request:get(path, Req)},
90
					    Req)
91
		end,
92
    %% Note that all the scheme/host/port information is discarded from path
93
    ClientFun = new_client_fun('GET',
94
			       [#treq{path = Uri, xreply = <<"/x/">>}]),
95
    [{atom_to_list(Transport),
96
      ?_assertEqual(ok,
97
		    (with_server(Transport, ServerFun, ClientFun)))}
98
     || Transport <- [ssl, plain]].
99
 
100
single_CONNECT_test_() ->
101
    [{"ssl", ?_assertEqual(ok, (do_CONNECT(ssl, 1)))},
102
     {"plain", ?_assertEqual(ok, (do_CONNECT(plain, 1)))}].
103
 
104
single_GET_any_test_() ->
105
    ServerFun = fun (Req) ->
106
			mochiweb_request:ok({"text/plain",
107
					     mochiweb_request:get(path, Req)},
108
					    Req)
109
		end,
110
    ClientFun = new_client_fun('GET',
111
			       [#treq{path = "*", xreply = <<"*">>}]),
112
    [{atom_to_list(Transport),
113
      ?_assertEqual(ok,
114
		    (with_server(Transport, ServerFun, ClientFun)))}
115
     || Transport <- [ssl, plain]].
116
 
117
cookie_header_test() ->
118
    ReplyPrefix = "You requested: ",
119
    ExHeaders = [{"Set-Cookie", "foo=bar"},
120
		 {"Set-Cookie", "foo=baz"}],
121
    ServerFun = fun (Req) ->
122
			Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
123
			mochiweb_request:ok({"text/plain", ExHeaders, Reply},
124
					    Req)
125
		end,
126
    Path = "cookie_header",
127
    ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
128
    TestReqs = [#treq{path = Path, xreply = ExpectedReply,
129
		      xheaders = ExHeaders}],
130
    ClientFun = new_client_fun('GET', TestReqs),
131
    ok = with_server(plain, ServerFun, ClientFun),
132
    ok.
133
 
134
do_CONNECT(Transport, Times) ->
135
    PathPrefix = "example.com:",
136
    ReplyPrefix = "You requested: ",
137
    ServerFun = fun (Req) ->
138
			Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
139
			mochiweb_request:ok({"text/plain", Reply}, Req)
140
		end,
141
    TestReqs = [begin
142
		  Path = PathPrefix ++ integer_to_list(N),
143
		  ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
144
		  #treq{path = Path, xreply = ExpectedReply}
145
		end
146
		|| N <- lists:seq(1, Times)],
147
    ClientFun = new_client_fun('CONNECT', TestReqs),
148
    ok = with_server(Transport, ServerFun, ClientFun),
149
    ok.
150
 
151
do_GET(Transport, Times) ->
152
    do_GET("/whatever/", Transport, Times).
153
 
154
do_GET(PathPrefix, Transport, Times) ->
155
    ReplyPrefix = "You requested: ",
156
    ServerFun = fun (Req) ->
157
			Reply = ReplyPrefix ++ mochiweb_request:get(path, Req),
158
			mochiweb_request:ok({"text/plain", Reply}, Req)
159
		end,
160
    TestReqs = [begin
161
		  Path = PathPrefix ++ integer_to_list(N),
162
		  ExpectedReply = list_to_binary(ReplyPrefix ++ Path),
163
		  #treq{path = Path, xreply = ExpectedReply}
164
		end
165
		|| N <- lists:seq(1, Times)],
166
    ClientFun = new_client_fun('GET', TestReqs),
167
    ok = with_server(Transport, ServerFun, ClientFun),
168
    ok.
169
 
170
do_POST(Transport, Size, Times) ->
171
    ServerFun = fun (Req) ->
172
			Body = mochiweb_request:recv_body(Req),
173
			Headers = [{"Content-Type",
174
				    "application/octet-stream"}],
175
			mochiweb_request:respond({201, Headers, Body}, Req)
176
		end,
177
    TestReqs = [begin
178
		  Path = "/stuff/" ++ integer_to_list(N),
179
		  Body = crypto:strong_rand_bytes(Size),
180
		  #treq{path = Path, body = Body, xreply = Body}
181
		end
182
		|| N <- lists:seq(1, Times)],
183
    ClientFun = new_client_fun('POST', TestReqs),
184
    ok = with_server(Transport, ServerFun, ClientFun),
185
    ok.
186
 
187
new_client_fun(Method, TestReqs) ->
188
    fun (Transport, Port) ->
189
	    mochiweb_test_util:client_request(Transport, Port,
190
					      Method, TestReqs)
191
    end.
192
 
193
close_on_unread_data_test() ->
194
    ok = with_server(plain,
195
		     fun mochiweb_request:not_found/1,
196
		     fun close_on_unread_data_client/2).
197
 
198
close_on_unread_data_client(Transport, Port) ->
199
    SockFun = mochiweb_test_util:sock_fun(Transport, Port),
200
    %% A normal GET request should not trigger this behavior
201
    Request0 = string:join(["GET / HTTP/1.1",
202
			    "Host: localhost", "", ""],
203
			   "\r\n"),
204
    ok = SockFun({setopts, [{packet, http}]}),
205
    ok = SockFun({send, Request0}),
206
    ?assertMatch({ok, {http_response, {1, 1}, 404, _}},
207
		 (SockFun(recv))),
208
    Headers0 =
209
	mochiweb_test_util:read_server_headers(SockFun),
210
    ?assertEqual(undefined,
211
		 (mochiweb_headers:get_value("Connection", Headers0))),
212
    Len0 =
213
	list_to_integer(mochiweb_headers:get_value("Content-Length",
214
						   Headers0)),
215
    _Body0 = mochiweb_test_util:drain_reply(SockFun, Len0,
216
					    <<>>),
217
    %% Re-use same socket
218
    Request = string:join(["POST / HTTP/1.1",
219
			   "Host: localhost", "Content-Type: application/json",
220
			   "Content-Length: 2", "", "{}"],
221
			  "\r\n"),
222
    ok = SockFun({setopts, [{packet, http}]}),
223
    ok = SockFun({send, Request}),
224
    ?assertMatch({ok, {http_response, {1, 1}, 404, _}},
225
		 (SockFun(recv))),
226
    Headers =
227
	mochiweb_test_util:read_server_headers(SockFun),
228
    %% Expect to see a Connection: close header when we know the
229
    %% server will close the connection re #146
230
    ?assertEqual("close",
231
		 (mochiweb_headers:get_value("Connection", Headers))),
232
    Len =
233
	list_to_integer(mochiweb_headers:get_value("Content-Length",
234
						   Headers)),
235
    _Body = mochiweb_test_util:drain_reply(SockFun, Len,
236
					   <<>>),
237
    ?assertEqual({error, closed}, (SockFun(recv))),
238
    ok.