Skip to content
Browse files

EWTS initial import

  • Loading branch information...
1 parent 8c2b0d3 commit 71dba5166f2d479d977285e191640249e4e80659 Michal Ptaszek committed Oct 13, 2009
View
7 Emakefile
@@ -42,3 +42,10 @@
debug_info,
strict_record_tests,
netload]}.
+
+{'lib/ewts-1.0/src/*', [
+ {outdir, "lib/ewts-1.0/ebin"},
+ {i, "lib/ewts-1.0/include"},
+ debug_info,
+ strict_record_tests,
+ netload]}.
View
2 lib/eptic-1.3/Emakefile
@@ -1,4 +1,4 @@
{'src/*',[{outdir, "ebin"},
{i, "include"},
- {i, "../yaws-1.79/include"},
+ {i, "../yaws-1.80/include"},
debug_info, strict_record_tests, netload]}.
View
3 lib/ewts-1.0/Emakefile
@@ -0,0 +1,3 @@
+{'src/*',[{outdir, "ebin"},
+ {i, "include"},
+ debug_info, strict_record_tests, netload]}.
View
5 lib/ewts-1.0/Makefile
@@ -0,0 +1,5 @@
+include ../../make/apps-defs.mk
+
+%: force
+ @$(MAKE) --no-print-directory -f ../../make/apps-common.mk $@
+force: ;
View
0 lib/ewts-1.0/doc/overview.edoc
No changes.
View
16 lib/ewts-1.0/ebin/ewts.app
@@ -0,0 +1,16 @@
+{application, ewts,
+ [
+ {description, "Erlang Web Test Suite"},
+ {vsn, "1.0"},
+ {modules, [e_mod_ewts,
+ ewts_client,
+ ewts_dbg,
+ ewts_sup,
+ ewts_app,
+ ewts]},
+ {registered, []},
+ {applications, [kernel, stdlib, eptic]},
+ {build_dependencies, []},
+ {mod, {ewts_app, []}},
+ {env, []}
+ ]}.
View
37 lib/ewts-1.0/include/request.hrl
@@ -0,0 +1,37 @@
+-type(string_proplist() :: list({string(), string()})).
+
+-record(request, {
+ url :: string(),
+ cookies = [] :: string_proplist(),
+ post_args = [] :: list({string(), string()}),
+ get_args = [] :: list({string(), string()}),
+ protocol = http :: http | https
+%% TODO - add multipart?
+ }).
+
+-record(response, {
+ headers :: list({string(), string()}),
+ code = 200 :: integer(),
+ cookies :: list({string(), string()}),
+ body = "" :: string(),
+ req_dict :: list()
+ }).
+
+-undef(assertDbg).
+-define(assertDbg(Expr, MinPassed),
+ (fun() ->
+ case Expr of
+ {0, 0} ->
+ ewts_dbg:clear();
+ {N, 0} when MinPassed =< N ->
+ ewts_dbg:clear();
+ {N, M} ->
+ ewts_dbg:clear(),
+ erlang:error({assertDbg_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {dbg_tests_failed, (??M)},
+ {dbg_tests_passed, (??N)}]})
+ end
+ end)()).
View
163 lib/ewts-1.0/src/e_mod_ewts.erl
@@ -0,0 +1,163 @@
+-module(e_mod_ewts).
+
+-export([handle_request/1]).
+
+-include_lib("ewts/include/request.hrl").
+-include_lib("eptic/include/eptic.hrl").
+
+-spec(handle_request/1 :: (tuple()) -> tuple()).
+handle_request(Request) ->
+ e_dict:init_state([{"get", Request#request.get_args},
+ {"post", Request#request.post_args}]),
+
+ ClientCookie = cookie_up(Request#request.cookies),
+
+ e_dict:fset("__https", Request#request.protocol == https),
+ e_dict:fset("__cookie_key", ClientCookie),
+ e_dict:fset("__ip", {0, 0, 0, 0}),
+ e_dict:fset("__path", Request#request.url),
+ e_dict:fset("__cookies", Request#request.cookies),
+
+ ControllerFun = fun() ->
+ case e_mod_gen:handle_request(Request#request.url) of
+ {ret_view, Ret, View} ->
+ controller_exec(Ret, View);
+ [_Status, _Html] = Error ->
+ Error;
+ {html, HTML} ->
+ controller_exec({content, html, HTML}, []);
+ enoent ->
+ enoent;
+ Else ->
+ controller_exec(Else, "")
+ end
+ end,
+
+ Response = with_formatted_error(ControllerFun),
+
+ CookieHeader = cookie_bind(ClientCookie),
+ {ok, Dict} = e_dict:get_state(),
+ cleanup(),
+
+ Response#response{cookies = [CookieHeader],
+ req_dict = Dict}.
+
+-spec(cookie_up/1 :: (list(tuple())) -> term()).
+cookie_up(Cookies) ->
+ case proplists:get_value(?COOKIE, Cookies) of
+ undefiend ->
+ ClientCookie = e_session:new_session([]),
+ e_mod_gen:restore_session(ClientCookie),
+ ClientCookie;
+ ClientCookie ->
+ {ok, Session} = e_session:get_session(ClientCookie),
+ if
+ Session == undefined ->
+ NewCookie = e_session:new_session([]),
+ e_mod_gen:restore_session(NewCookie),
+ NewCookie;
+ true ->
+ e_mod_gen:restore_session(ClientCookie),
+ ClientCookie
+ end
+ end.
+
+-spec(controller_exec/2 :: (e_mod_gen:controller_response(), string()) ->
+ {list(tuple()), string()}).
+controller_exec(Ret, View) ->
+ case Ret of
+ template ->
+ format_response(e_mod_gen:template(e_mod_gen:template_file(View), [],
+ e_conf:template_expander()));
+ {redirect, URL} ->
+ #response{code = 302,
+ headers = [{"location", URL},
+ {"content_length", "0"}]};
+ {content, html, Data} ->
+ Length = {"content_length", integer_to_list(erlang:iolist_size(Data))},
+ #response{headers = [{"content_type", "text/html"},
+ Length],
+ body = Data};
+ {content, xml, Data} ->
+ Length = {"content_length", integer_to_list(erlang:iolist_size(Data))},
+ #response{headers = [{"content_type", "text/xml"},
+ Length],
+ body = Data};
+ {content, text, Data} ->
+ Length = {"content_length", integer_to_list(erlang:iolist_size(Data))},
+ #response{headers = [{"content_type", "text/plain"},
+ Length],
+ body = Data};
+ {content, pdf, Data} ->
+ Length = {"content_length", integer_to_list(erlang:iolist_size(Data))},
+ #response{headers = [{"content_type", "application/pdf"},
+ Length],
+ body = Data};
+ {json, Data} ->
+ Content = e_json:encode(Data),
+ Length = {"content_length", integer_to_list(erlang:iolist_size(Content))},
+ #response{headers = [{"content_type", "application/json"},
+ Length],
+ body = Content};
+ {template, Template} ->
+ format_response(e_mod_gen:template(Template, [],
+ e_conf:template_expander()));
+ {custom, Custom} ->
+ Custom;
+ {headers, Headers, NewRet} ->
+ Res = controller_exec(NewRet, View),
+ ReadyHeaders = create_headers(Headers, []),
+ #response{body = Res#response.body,
+ headers = ReadyHeaders ++ Res#response.headers};
+ {error, Code} ->
+ format_response(e_mod_gen:error_page(Code, e_dict:fget("__path")))
+ end.
+
+-spec(format_response/1 :: (term()) -> term()).
+format_response({html, HTML}) ->
+ Length = {"content_length", integer_to_list(erlang:iolist_size(HTML))},
+ #response{headers = [{"content_type", "text/html"},
+ Length],
+ body = HTML};
+format_response([{status, Code}, {html, HTML}]) ->
+ Length = {"content_length", integer_to_list(erlang:iolist_size(HTML))},
+ #response{headers = [{"content_type", "text/html"},
+ Length],
+ body = HTML,
+ code = Code};
+format_response(Else) ->
+ Else.
+
+-spec(with_formatted_error/1 :: (fun()) -> term()).
+with_formatted_error(F) ->
+ case catch F() of
+ {'EXIT', Reason} ->
+ format_response(e_mod_gen:error_page(501, e_dict:fget("__path"), Reason));
+ Response ->
+ format_response(Response)
+ end.
+
+-spec(create_headers/2 :: (list(tuple()), list(tuple())) -> list(tuple())).
+create_headers([], Acc) ->
+ Acc;
+create_headers([{cookie, CookieName, CookieVal} | Rest], Acc) ->
+ create_headers(Rest, [{"Set-cookie", CookieName ++ [$= | CookieVal ++ "; path=/"]} | Acc]);
+create_headers([{cookie, CookieName, CookieVal, CookiePath} | Rest], Acc) ->
+ create_headers(Rest, [{"Set-cookie", CookieName ++ [$= | CookieVal ++ "; path=" ++ CookiePath]} | Acc]);
+create_headers([{cookie, CookieName, CookieVal, CookiePath, CookieExpDate} | Rest], Acc) ->
+ create_headers(Rest, [{"Set-cookie", CookieName ++ [$= | CookieVal ++ "; path=" ++ CookiePath ++ "; expires=" ++ CookieExpDate]} | Acc]);
+create_headers([{content_length, Len} | Rest], Acc) when is_integer(Len) ->
+ create_headers(Rest, [{"Content-Length", integer_to_list(Len)} | Acc]);
+create_headers([{content_length, Len} | Rest], Acc) when is_list(Len) ->
+ create_headers(Rest, [{"Content-Length", Len} | Acc]);
+create_headers([_ | Rest], Acc) ->
+ create_headers(Rest, Acc).
+
+-spec(cookie_bind/1 :: (string()) -> {string(), string()}).
+cookie_bind(ClientCookie) ->
+ e_mod_gen:bind_session(ClientCookie),
+ {?COOKIE, ClientCookie}.
+
+-spec(cleanup/0 :: () -> any()).
+cleanup() ->
+ e_dict:terminate_state().
View
12 lib/ewts-1.0/src/ewts.app.src
@@ -0,0 +1,12 @@
+%% -*- mode: erlang; -*-
+{application, ewts,
+ [
+ {description, "Erlang Web Testing Suite"},
+ {vsn, "@VSN@"},
+ {modules, [@MODULES@]},
+ {registered, []},
+ {applications, [kernel, stdlib]},
+ {build_dependencies, []},
+ {mod, {ewts_app, []}},
+ {env, []}
+ ]}.
View
159 lib/ewts-1.0/src/ewts.erl
@@ -0,0 +1,159 @@
+-module(ewts).
+
+-export([start_tests/1, fget/2]).
+
+-spec(start_tests/1 :: (string()) -> any()).
+start_tests(Outdir) ->
+ error_logger:tty(false),
+ Modules = lists:concat(lists:map(
+ fun(Application) ->
+ Result = cover:compile_directory(filename:join(["../../apps/", Application, "src"]),
+ [{i, filename:join(["/../../apps/", Application, "include"])}]),
+ if
+ is_list(Result) ->
+ lists:foldl(fun({ok, M}, Acc) -> [M | Acc];
+ (_, Acc) -> Acc end, [], Result);
+ true ->
+ []
+ end
+ end, get_apps())),
+ TestModules = [list_to_atom(filename:basename(F, ".erl")) ||
+ F <- filelib:wildcard(filename:join("../../apps/*/test/", "*.erl"))],
+ EUnitResult = eunit:test(TestModules),
+
+ if
+ EUnitResult == ok ->
+ TotalPercentage = html_report(Outdir, Modules),
+ io:format("All tests passed. ~B% line coverage.~n", [TotalPercentage]),
+
+ %% Taken from http://idlingspace.com/game/perfect_lemmings/lemmingology_mathe/
+ Needed = 70,
+ Rescued = TotalPercentage,
+ Msg =
+ if Rescued == 0 ->
+ "ROCK BOTTOM! I hope for your sake that you nuked that level.";
+ Rescued < (Needed div 2) ->
+ "Better rethink your strategy before you try this level again!";
+ Rescued < (Needed - 5) ->
+ "A little more practice on this level is definitely recommended.";
+ Rescued < (Needed - 1) ->
+ "You got pretty close that time. Now try again for that few percent extra.";
+ Rescued == (Needed - 1) ->
+ "OH NO, So near and yet so far (teehee) Maybe this time.....";
+ Rescued == Needed ->
+ "SPOT ON. You can't get much closer than that. Let's try the next....";
+ Rescued < (Needed + 20), Rescued < 100 ->
+ "That level seemed no problem to you on that attempt. Onto the next....";
+ Rescued < 100 ->
+ "You totally stormed that level! Let's see if you can storm the next...";
+ Rescued == 100 ->
+ "Superb! You rescued every lemming on that level. Can you do it again....?"
+ end,
+ io:format("~s~n", [Msg]);
+ true ->
+ io:format("Wow! Hold your horses mighty cowboy - eunit has failed, hasn't it?~n")
+ end,
+ init:stop().
+
+-spec(fget/2 :: (string(), term()) -> undefined | term()).
+fget(Key0, Dict) ->
+ case string:tokens(Key0, ":") of
+ [List, Key] ->
+ fget0(List, Key, Dict);
+ [Key] ->
+ fget0(Key, Dict)
+ end.
+
+-spec(fget0/2 :: (string(), term()) -> undefined | term()).
+fget0(Key, Dict) ->
+ case dict:find(Key, Dict) of
+ {ok, Val} ->
+ Val;
+ error ->
+ undefined
+ end.
+
+-spec(fget0/3 :: (string(), string(), term()) -> undefined | term()).
+fget0(List, Key, Dict) ->
+ case fget0(List, Dict) of
+ PropList when is_list(PropList) ->
+ case proplists:get_all_values(Key, PropList) of
+ [] -> undefined;
+ [Value] -> Value;
+ Values -> Values
+ end;
+ Result ->
+ Result
+ end.
+
+-spec(get_apps/0 :: () -> (list(string()))).
+get_apps() ->
+ element(2, file:list_dir("../../apps/")) -- ["yaws", "eptic", "eptic_fe", "wpart",
+ "wparts", "ewts"].
+
+html_report(Path, Modules) ->
+ Results = lists:map(fun(Module) ->
+ case cover:analyse(Module, module) of
+ {ok, Result} -> Result;
+ {error, Reason} -> exit({invalid_module, Reason})
+ end
+ end, Modules),
+ case filelib:ensure_dir(filename:join(Path, "index.html")) of
+ ok -> ok;
+ {error, Reason} -> exit({invalid_dir, Reason})
+ end,
+ Files = lists:map(fun(Module) ->
+ File = filename:join(Path, ["mod_", Module, ".html"]),
+ {ok, File} = cover:analyse_to_file(Module, File, [html]),
+ filename:basename(File)
+ end, Modules),
+ output_index(Path, lists:zip3(Modules, Files, percentage_per_file(Results))),
+ percentage_total(Results).
+
+percentage_total(Results) ->
+ {Covered, Total} =
+ lists:foldl(
+ fun({_Module, {C, NC}}, {Covered, Total}) ->
+ {Covered + C, Total + C + NC}
+ end, {0, 0}, Results),
+ case Total of
+ 0 -> 0;
+ _ -> round(100 * Covered / Total)
+ end.
+
+percentage_per_file(Results) ->
+ lists:map(fun({_Module, {Covered, NotCovered}}) ->
+ Total = Covered + NotCovered,
+ round(100 * Covered / Total)
+ end, Results).
+
+output_index(Path, Info) ->
+ IndexFile = filename:join(Path, "index.html"),
+ IoDevice = case file:open(IndexFile, [write]) of
+ {ok, IoD} -> IoD;
+ {error, Reason} -> exit({invalid_file, Reason})
+ end,
+ output_header(IoDevice),
+ lists:foreach(fun({Module, File, Percentage}) ->
+ io:format(IoDevice, "~s~n", [
+ [
+ "<li><a href=\"",
+ File,
+ "\">",
+ atom_to_list(Module),
+ "</a> Covered: ",
+ integer_to_list(Percentage),
+ "%",
+ "</a>"
+ ]
+ ])
+ end, Info),
+ output_footer(IoDevice),
+ file:close(IoDevice),
+ IndexFile.
+
+output_header(IoDevice) ->
+ io:format(IoDevice, "<html>~n<head></head><body>", []).
+
+output_footer(IoDevice) ->
+ io:format(IoDevice, "</body>~n</html>~n", []).
View
45 lib/ewts-1.0/src/ewts_app.erl
@@ -0,0 +1,45 @@
+%%%-------------------------------------------------------------------
+%%% File : ewts_app.erl
+%%% Author : michalptaszek <michalptaszek@paulgray>
+%%% Description : Main application of Erlang Web Testing Suite.
+%%%
+%%% Created : 16 Jun 2009 by michalptaszek <michalptaszek@paulgray>
+%%%-------------------------------------------------------------------
+-module(ewts_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+%%====================================================================
+%% Application callbacks
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start(Type, StartArgs) -> {ok, Pid} |
+%% {ok, Pid, State} |
+%% {error, Reason}
+%% Description: This function is called whenever an application
+%% is started using application:start/1,2, and should start the processes
+%% of the application. If the application is structured according to the
+%% OTP design principles as a supervision tree, this means starting the
+%% top supervisor of the tree.
+%%--------------------------------------------------------------------
+-spec(start/2 :: (term(), list()) ->
+ {ok, pid()} | {ok, pid(), term()} | {error, term()}).
+start(_Type, StartArgs) ->
+ ewts_sup:start_link(StartArgs).
+
+%%--------------------------------------------------------------------
+%% Function: stop(State) -> void()
+%% Description: This function is called whenever an application
+%% has stopped. It is intended to be the opposite of Module:start/2 and
+%% should do any necessary cleaning up. The return value is ignored.
+%%--------------------------------------------------------------------
+-spec(stop/1 :: (term()) -> ok).
+stop(_State) ->
+ ok.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
View
197 lib/ewts-1.0/src/ewts_client.erl
@@ -0,0 +1,197 @@
+%%%-------------------------------------------------------------------
+%%% File : ewts_client.erl
+%%% Author : michalptaszek <michalptaszek@paulgray>
+%%% Description :
+%%%
+%%% Created : 18 Jun 2009 by michalptaszek <michalptaszek@paulgray>
+%%%-------------------------------------------------------------------
+-module(ewts_client).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+-export([request/1, request/2, request/3, request/4, request/5, do_request/1]).
+-export([direct_request/1, direct_request/2, direct_request/3,
+ direct_request/4, direct_request/5, do_direct_request/1]).
+-export([clear/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-include_lib("eptic/include/eptic.hrl").
+-include_lib("ewts/include/request.hrl").
+
+-record(state, {eptic_cookie = ""}).
+
+%%====================================================================
+%% API
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+-spec(start_link/0 :: () -> any()).
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+-spec(request/1 :: (string()) -> tuple()).
+request(Url) ->
+ do_request(#request{url = Url}).
+
+-spec(request/2 :: (string(), string_proplist()) -> tuple()).
+request(Url, Get) ->
+ do_request(#request{url = Url, get_args = Get}).
+
+-spec(request/3 :: (string(), string_proplist(), string_proplist()) ->
+ tuple()).
+request(Url, Get, Post) ->
+ do_request(#request{url = Url, get_args = Get, post_args = Post}).
+
+-spec(request/4 :: (string(), string_proplist(), string_proplist(),
+ string_proplist()) -> tuple()).
+request(Url, Get, Post, Cookies) ->
+ do_request(#request{url = Url, get_args = Get, post_args = Post,
+ cookies = Cookies}).
+
+-spec(request/5 :: (string(), string_proplist(), string_proplist(),
+ string_proplist(), http | https) -> tuple()).
+request(Url, Get, Post, Cookies, Protocol) ->
+ do_request(#request{url = Url, get_args = Get, post_args = Post,
+ cookies = Cookies, protocol = Protocol}).
+
+-spec(direct_request/1 :: (string()) -> tuple()).
+direct_request(Url) ->
+ do_direct_request(#request{url = Url}).
+
+-spec(direct_request/2 :: (string(), string_proplist()) -> tuple()).
+direct_request(Url, Get) ->
+ do_direct_request(#request{url = Url, get_args = Get}).
+
+-spec(direct_request/3 :: (string(), string_proplist(), string_proplist()) ->
+ tuple()).
+direct_request(Url, Get, Post) ->
+ do_direct_request(#request{url = Url, get_args = Get, post_args = Post}).
+
+-spec(direct_request/4 :: (string(), string_proplist(), string_proplist(),
+ string_proplist()) -> tuple()).
+direct_request(Url, Get, Post, Cookies) ->
+ do_direct_request(#request{url = Url, get_args = Get, post_args = Post,
+ cookies = Cookies}).
+
+-spec(direct_request/5 :: (string(), string_proplist(), string_proplist(),
+ string_proplist(), http | https) -> tuple()).
+direct_request(Url, Get, Post, Cookies, Protocol) ->
+ do_direct_request(#request{url = Url, get_args = Get, post_args = Post,
+ cookies = Cookies, protocol = Protocol}).
+
+-spec(do_request/1 :: (tuple()) -> tuple()).
+do_request(Req) ->
+ Response = gen_server:call(?MODULE, {request, Req}),
+ Response#response{body = normalize_body(Response#response.body)}.
+
+-spec(do_direct_request/1 :: (tuple()) -> tuple()).
+do_direct_request(Req) ->
+ Response = e_mod_ewts:handle_request(Req),
+ Response#response{body = normalize_body(Response#response.body)}.
+
+-spec(clear/0 :: () -> ok).
+clear() ->
+ gen_server:cast(?MODULE, clear).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+-spec(init/1 :: (nil()) -> {ok, tuple()}).
+init([]) ->
+ {ok, #state{}}.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+-spec(handle_call/3 :: (term(), term(), tuple()) -> tuple()).
+handle_call({request, Req}, _From, State) ->
+ Request = case Req#request.cookies of
+ [] ->
+ Req#request{cookies = State#state.eptic_cookie};
+ _ ->
+ Req
+ end,
+ Response = e_mod_ewts:handle_request(Request),
+
+ {reply, Response,
+ State#state{eptic_cookie = get_eptic_cookie(Response)}}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+-spec(handle_cast/2 :: (term(), tuple()) -> tuple()).
+handle_cast(clear, State) ->
+ {noreply, State#state{eptic_cookie = []}}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+-spec(handle_info/2 :: (term(), tuple()) -> tuple()).
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+-spec(terminate/2 :: (term(), tuple()) -> ok).
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+-spec(code_change/3 :: (term(), tuple(), term()) -> tuple()).
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+-spec(get_eptic_cookie/1 :: (tuple()) -> none | tuple()).
+get_eptic_cookie(#response{cookies = Cookies}) ->
+ case proplists:lookup(?COOKIE, Cookies) of
+ none ->
+ [];
+ Val ->
+ [Val]
+ end.
+
+-spec(normalize_body/1 :: (list()) -> string()).
+normalize_body(Body) ->
+ lists:flatten(lists:map(fun(Part) when is_binary(Part) ->
+ binary_to_list(Part);
+ (Else) ->
+ Else
+ end, lists:flatten(Body))).
View
132 lib/ewts-1.0/src/ewts_dbg.erl
@@ -0,0 +1,132 @@
+%%%-------------------------------------------------------------------
+%%% File : ewts_dbg.erl
+%%% Author : michalptaszek <michalptaszek@paulgray>
+%%% Description : DBG callback module for EWTS
+%%%
+%%% Created : 29 Jun 2009 by michalptaszek <michalptaszek@paulgray>
+%%%-------------------------------------------------------------------
+-module(ewts_dbg).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+-export([add_case/1, results/0, clear/0]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-record(state, {events = [],
+ passed = 0,
+ failed = 0}).
+
+-include_lib("stdlib/include/ms_transform.hrl").
+
+-define(TEST_FAILED(Test, Exp, Got),
+ io:format("EWTS ~w test has failed. Expected ~p, got ~p~n~n",
+ [Test, Exp, Got])).
+
+-spec(start_link/0 :: () -> any()).
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+-spec(results/0 :: () -> {integer(), integer()}).
+results() ->
+ gen_server:call(?MODULE, results).
+
+-spec(clear/0 :: () -> any()).
+clear() ->
+ dbg:ctpl(),
+ dbg:tp(?MODULE, clear, 0, []),
+ dbg:tpl(?MODULE, add_to_registered_funs, 3, []),
+ gen_server:cast(?MODULE, clear).
+
+-spec(add_case/1 :: (tuple()) -> ok).
+add_case({dispatcher_result, _} = Case) ->
+ dbg:tp(e_dispatcher, dispatch, 1,
+ dbg:fun2ms(fun(_) -> return_trace() end)),
+
+ gen_server:cast(?MODULE, {add_case, Case});
+add_case({function_response, {M, F, A}, Res}) ->
+ dbg:tp(M, F, A,
+ dbg:fun2ms(fun(_) -> return_trace() end)),
+
+ gen_server:cast(?MODULE, {add_case, {{function_response, {M, F, A}}, Res}}),
+ add_to_registered_funs(M, F, A).
+
+
+-spec(dbg_handler/2 :: (tuple(), term()) -> term()).
+dbg_handler({trace, _, return_from, {e_dispatcher, dispatch, 1}, Result}, Data) ->
+ gen_server:cast(?MODULE, {check_case, {dispatcher_result, Result}}),
+ Data;
+dbg_handler({trace, _, call, {?MODULE, clear, []}}, _) ->
+ [];
+dbg_handler({trace, _, call, {?MODULE, add_to_registered_funs, [M, F, A]}}, Data) ->
+ [{M, F, A} | Data];
+dbg_handler({trace, _, return_from, {M, F, A}, Result}, Data) ->
+ case lists:member({M, F, A}, Data) of
+ true ->
+ gen_server:cast(?MODULE,
+ {check_case, {{function_response, {M, F, A}}, Result}});
+ false ->
+ ok
+ end,
+ Data;
+dbg_handler(_Event, Data) ->
+ Data.
+
+add_to_registered_funs(_, _, _) ->
+ ok.
+
+-spec(init/1 :: (nil()) -> {ok, tuple()}).
+init([]) ->
+ HandlerSpec = {fun dbg_handler/2, []},
+ dbg:tracer(process, HandlerSpec),
+ dbg:p(all, call),
+ dbg:ctpl(),
+ dbg:tp(?MODULE, clear, 0, []),
+ dbg:tpl(?MODULE, add_to_registered_funs, 3, []),
+
+ {ok, #state{}}.
+
+-spec(handle_call/3 :: (term(), term(), tuple()) -> tuple()).
+handle_call(results, _From, State) ->
+ Reply = {State#state.passed, State#state.failed},
+
+ {reply, Reply, State}.
+
+-spec(handle_cast/2 :: (term(), tuple()) -> tuple()).
+handle_cast(clear, _State) ->
+ {noreply, #state{}};
+
+handle_cast({add_case, Case}, State) ->
+ {noreply, State#state{events = [Case | State#state.events]}};
+
+handle_cast({check_case, {Key, Val}}, State) ->
+ case proplists:get_value(Key, State#state.events, Val) of
+ Val ->
+ {noreply, inc_passed(State)};
+ Other ->
+ ?TEST_FAILED(Key, Other, Val),
+ {noreply, inc_failed(State)}
+ end.
+
+
+-spec(handle_info/2 :: (term(), tuple()) -> tuple()).
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+-spec(terminate/2 :: (term(), tuple()) -> ok).
+terminate(_Reason, _State) ->
+ ok.
+
+-spec(code_change/3 :: (term(), tuple(), term()) -> tuple()).
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+-spec(inc_passed/1 :: (tuple()) -> tuple()).
+inc_passed(#state{passed = N} = State) ->
+ State#state{passed = N+1}.
+
+-spec(inc_failed/1 :: (tuple()) -> tuple()).
+inc_failed(#state{failed = N} = State) ->
+ State#state{failed = N+1}.
View
54 lib/ewts-1.0/src/ewts_sup.erl
@@ -0,0 +1,54 @@
+%%%-------------------------------------------------------------------
+%%% File : ewts_sup.erl
+%%% Author : michalptaszek <michalptaszek@paulgray>
+%%% Description : Main supervisor of Erlang Web Testing Suite
+%%%
+%%% Created : 16 Jun 2009 by michalptaszek <michalptaszek@paulgray>
+%%%-------------------------------------------------------------------
+-module(ewts_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/1]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%====================================================================
+%% API functions
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the supervisor
+%%--------------------------------------------------------------------
+-spec(start_link/1 :: (list()) -> {ok, pid()} | ignore | {error, term()}).
+start_link(StartArgs) ->
+ supervisor:start_link({local, ?SERVER}, ?MODULE, StartArgs).
+
+%%====================================================================
+%% Supervisor callbacks
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
+%% ignore |
+%% {error, Reason}
+%% Description: Whenever a supervisor is started using
+%% supervisor:start_link/[2,3], this function is called by the new process
+%% to find out about restart strategy, maximum restart frequency and child
+%% specifications.
+%%--------------------------------------------------------------------
+-spec(init/1 :: (list()) -> {ok, {tuple(), list()}}).
+init(_) ->
+ Client = {client, {ewts_client, start_link, []},
+ permanent, 2000, worker, dynamic},
+ Dbg = {dbg_tester, {ewts_dbg, start_link, []},
+ permanent, 2000, worker, dynamic},
+
+ {ok,{{one_for_one,2,5000}, [Client, Dbg]}}.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
View
1 lib/ewts-1.0/vsn.mk
@@ -0,0 +1 @@
+VSN=0.1

0 comments on commit 71dba51

Please sign in to comment.
Something went wrong with that request. Please try again.