| % Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| % use this file except in compliance with the License. You may obtain a copy of |
| % the License at |
| % |
| % http://www.apache.org/licenses/LICENSE-2.0 |
| % |
| % Unless required by applicable law or agreed to in writing, software |
| % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| % License for the specific language governing permissions and limitations under |
| % the License. |
| |
| -module(test_web). |
| -behaviour(gen_server). |
| |
| -include_lib("couch/include/couch_eunit.hrl"). |
| |
| -export([start_link/0, stop/0, loop/1, get_port/0, set_assert/1, check_last/0]). |
| -export([init/1, terminate/2, code_change/3]). |
| -export([handle_call/3, handle_cast/2, handle_info/2]). |
| |
| -define(SERVER, test_web_server). |
| -define(HANDLER, test_web_handler). |
| -define(DELAY, 500). |
| |
| start_link() -> |
| gen_server:start({local, ?HANDLER}, ?MODULE, [], []), |
| mochiweb_http:start([ |
| {name, ?SERVER}, |
| {loop, {?MODULE, loop}}, |
| {port, 0} |
| ]). |
| |
| loop(Req) -> |
| %?debugFmt("Handling request: ~p", [Req]), |
| case gen_server:call(?HANDLER, {check_request, Req}) of |
| {ok, RespInfo} -> |
| {ok, Req:respond(RespInfo)}; |
| {raw, {Status, Headers, BodyChunks}} -> |
| Resp = Req:start_response({Status, Headers}), |
| lists:foreach(fun(C) -> Resp:send(C) end, BodyChunks), |
| erlang:put(mochiweb_request_force_close, true), |
| {ok, Resp}; |
| {chunked, {Status, Headers, BodyChunks}} -> |
| Resp = Req:respond({Status, Headers, chunked}), |
| timer:sleep(?DELAY), |
| lists:foreach(fun(C) -> Resp:write_chunk(C) end, BodyChunks), |
| Resp:write_chunk([]), |
| {ok, Resp}; |
| {error, Reason} -> |
| ?debugFmt("Error: ~p", [Reason]), |
| Body = lists:flatten(io_lib:format("Error: ~p", [Reason])), |
| {ok, Req:respond({200, [], Body})} |
| end. |
| |
| get_port() -> |
| mochiweb_socket_server:get(?SERVER, port). |
| |
| set_assert(Fun) -> |
| ?assertEqual(ok, gen_server:call(?HANDLER, {set_assert, Fun})). |
| |
| check_last() -> |
| gen_server:call(?HANDLER, last_status). |
| |
| init(_) -> |
| {ok, nil}. |
| |
| terminate(_Reason, _State) -> |
| ok. |
| |
| stop() -> |
| mochiweb_http:stop(?SERVER). |
| |
| |
| handle_call({check_request, Req}, _From, State) when is_function(State, 1) -> |
| Resp2 = case (catch State(Req)) of |
| {ok, Resp} -> |
| {reply, {ok, Resp}, was_ok}; |
| {raw, Resp} -> |
| {reply, {raw, Resp}, was_ok}; |
| {chunked, Resp} -> |
| {reply, {chunked, Resp}, was_ok}; |
| Error -> |
| {reply, {error, Error}, not_ok} |
| end, |
| Req:cleanup(), |
| Resp2; |
| handle_call({check_request, _Req}, _From, _State) -> |
| {reply, {error, no_assert_function}, not_ok}; |
| handle_call(last_status, _From, State) when is_atom(State) -> |
| {reply, State, nil}; |
| handle_call(last_status, _From, State) -> |
| {reply, {error, not_checked}, State}; |
| handle_call({set_assert, Fun}, _From, nil) -> |
| {reply, ok, Fun}; |
| handle_call({set_assert, _}, _From, State) -> |
| {reply, {error, assert_function_set}, State}; |
| handle_call(Msg, _From, State) -> |
| {reply, {ignored, Msg}, State}. |
| |
| handle_cast(stop, State) -> |
| {stop, normal, State}; |
| handle_cast(Msg, State) -> |
| ?debugFmt("Ignoring cast message: ~p", [Msg]), |
| {noreply, State}. |
| |
| handle_info(Msg, State) -> |
| ?debugFmt("Ignoring info message: ~p", [Msg]), |
| {noreply, State}. |
| |
| code_change(_OldVsn, State, _Extra) -> |
| {ok, State}. |