mirror of
https://github.com/valitydev/riak_test.git
synced 2024-11-06 00:25:22 +00:00
Add a simple 'smoke test' tool to run eunit/dialyzer on riak source trees
This commit is contained in:
parent
d983476f59
commit
1ec8bda21c
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,6 +2,7 @@ deps
|
||||
ebin
|
||||
log
|
||||
riak_test
|
||||
smoke_test
|
||||
.eunit
|
||||
.DS_Store
|
||||
out
|
||||
|
1
Makefile
1
Makefile
@ -7,6 +7,7 @@ PLT = $(HOME)/.riak-test_dialyzer_plt
|
||||
|
||||
all: deps compile
|
||||
./rebar skip_deps=true escriptize
|
||||
SMOKE_TEST=1 ./rebar skip_deps=true escriptize
|
||||
|
||||
deps:
|
||||
./rebar get-deps
|
||||
|
8
rebar.config.script
Normal file
8
rebar.config.script
Normal file
@ -0,0 +1,8 @@
|
||||
case os:getenv("SMOKE_TEST") of
|
||||
false -> CONFIG;
|
||||
[] -> CONFIG;
|
||||
_ ->
|
||||
C1 = lists:keystore(escript_emu_args, 1, CONFIG,
|
||||
{escript_emu_args, "%%! -escript main smoke_test_escript +K true +P 10000 -env ERL_MAX_PORTS 10000\n"}),
|
||||
lists:keystore(escript_name, 1, C1, {escript_name, smoke_test})
|
||||
end.
|
214
src/smoke_test_escript.erl
Executable file
214
src/smoke_test_escript.erl
Executable file
@ -0,0 +1,214 @@
|
||||
-module(smoke_test_escript).
|
||||
-include_lib("kernel/include/file.hrl").
|
||||
|
||||
-export([main/1, get_version/0, worker/3]).
|
||||
|
||||
get_version() ->
|
||||
list_to_binary(string:strip(os:cmd("git describe"), right, $\n)).
|
||||
|
||||
cli_options() ->
|
||||
%% Option Name, Short Code, Long Code, Argument Spec, Help Message
|
||||
[
|
||||
{project, $p, "project", string, "specifices which project"},
|
||||
{debug, $v, "debug", undefined, "debug?"},
|
||||
{directory, $d, "directory", string, "source tree directory"},
|
||||
{jobs, $j, "jobs", integer, "jobs?"}
|
||||
].
|
||||
|
||||
|
||||
main(Args) ->
|
||||
{ok, {Parsed, _Other}} = getopt:parse(cli_options(), Args),
|
||||
application:start(ibrowse),
|
||||
lager:start(),
|
||||
rt_config:load("default", filename:join([os:getenv("HOME"), ".smoke_test.config"])),
|
||||
case lists:keyfind(project, 1, Parsed) of
|
||||
false ->
|
||||
lager:error("Must specify project!"),
|
||||
application:stop(lager),
|
||||
halt(1);
|
||||
{project, Project} ->
|
||||
rt_config:set(rt_project, Project)
|
||||
end,
|
||||
case lists:keyfind(directory, 1, Parsed) of
|
||||
false ->
|
||||
%% run in current working directory
|
||||
ok;
|
||||
{directory, Dir} ->
|
||||
lager:info("Changing working dir to ~s", [Dir]),
|
||||
ok = file:set_cwd(filename:absname(Dir))
|
||||
end,
|
||||
case lists:member(debug, Parsed) of
|
||||
true ->
|
||||
lager:set_loglevel(lager_console_backend, debug);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
rt_config:set(rt_harness, ?MODULE),
|
||||
lager:debug("ParsedArgs ~p", [Parsed]),
|
||||
Suites = giddyup:get_suite(rt_config:get(platform)),
|
||||
Jobs = case lists:keyfind(jobs, 1, Parsed) of
|
||||
false ->
|
||||
1;
|
||||
{jobs, J} ->
|
||||
J
|
||||
end,
|
||||
|
||||
{ok, PWD} = file:get_cwd(),
|
||||
Rebar = filename:join(PWD, "rebar"),
|
||||
|
||||
|
||||
setup_deps(Rebar, PWD, [filename:join([PWD, "deps", F])
|
||||
|| F <- element(2, file:list_dir(filename:join(PWD, "deps"))),
|
||||
filelib:is_dir(filename:join([PWD, "deps", F]))]),
|
||||
|
||||
case Jobs > 1 of
|
||||
true ->
|
||||
%% partiton the suite list by the number of jobs
|
||||
SplitSuites = dict:to_list(element(2, lists:foldl(fun(S, {Counter, Dict}) ->
|
||||
{Counter + 1, dict:append(Counter rem Jobs, S, Dict)}
|
||||
end, {0, dict:new()}, Suites))),
|
||||
lager:debug("Split into ~p lists", [length(SplitSuites)]),
|
||||
Workers = [spawn_monitor(?MODULE, worker, [Rebar, PWD, SS]) || {_, SS} <- SplitSuites],
|
||||
wait_for_workers(Workers);
|
||||
_ ->
|
||||
worker(Rebar, PWD, Suites)
|
||||
end.
|
||||
|
||||
worker(Rebar, PWD, Suites) ->
|
||||
lists:foreach(fun({Suite, Config}) ->
|
||||
lager:info("Suite ~p config ~p", [Suite, Config]),
|
||||
[Dep, Task] = string:tokens(atom_to_list(Suite), ":"),
|
||||
FDep = filename:join([PWD, deps, Dep]),
|
||||
case filelib:is_dir(FDep) of
|
||||
true ->
|
||||
case Task of
|
||||
"eunit" ->
|
||||
%% set up a symlink so that each dep has deps
|
||||
P = erlang:open_port({spawn_executable, Rebar},
|
||||
[{args, ["eunit", "skip_deps=true"]},
|
||||
{cd, FDep}, exit_status,
|
||||
{line, 1024}, stderr_to_stdout, binary]),
|
||||
{Res, Log} = accumulate(P, []),
|
||||
CleanedLog = cleanup_logs(Log),
|
||||
giddyup:post_result([{test, Suite}, {status, get_status(Res)},
|
||||
{log, CleanedLog} | Config]),
|
||||
Res;
|
||||
"dialyzer" ->
|
||||
P = erlang:open_port({spawn_executable, "/usr/bin/make"},
|
||||
[{args, ["dialyzer"]},
|
||||
{cd, FDep}, exit_status,
|
||||
{line, 1024}, stderr_to_stdout, binary]),
|
||||
{Res, Log} = accumulate(P, []),
|
||||
%% TODO split the logs so that the PLT stuff is elided
|
||||
CleanedLog = cleanup_logs(Log),
|
||||
giddyup:post_result([{test, Suite}, {status, get_status(Res)},
|
||||
{log, CleanedLog} | Config]),
|
||||
Res;
|
||||
_ ->
|
||||
ok
|
||||
|
||||
end;
|
||||
false ->
|
||||
lager:debug("Not a dep: ~p", [FDep])
|
||||
end
|
||||
end, Suites).
|
||||
|
||||
setup_deps(_, _, []) -> ok;
|
||||
setup_deps(Rebar, PWD, [Dep|Deps]) ->
|
||||
%% clean up an old deps dir, if present
|
||||
remove_deps_dir(Dep),
|
||||
%% symlink ALL the deps in
|
||||
file:make_symlink(filename:join(PWD, "deps"), filename:join(Dep, "deps")),
|
||||
lager:debug("ln -sf ~s ~s", [filename:join(PWD, "deps"),
|
||||
filename:join(Dep, "deps")]),
|
||||
%% run rebar list deps, to find out which ones to keep
|
||||
P = erlang:open_port({spawn_executable, Rebar},
|
||||
[{args, ["list-deps"]},
|
||||
{cd, Dep}, exit_status,
|
||||
{line, 1024}, stderr_to_stdout, binary]),
|
||||
{0, Log} = accumulate(P, []),
|
||||
%% find all the deps, amongst the noise
|
||||
case re:run(Log, "([a-zA-Z0-9_]+) (?:BRANCH|TAG|REV)",
|
||||
[global, {capture, all_but_first, list}]) of
|
||||
{match, Matches} ->
|
||||
lager:info("Deps for ~p are ~p", [Dep, Matches]),
|
||||
ok = file:delete(filename:join(Dep, "deps")),
|
||||
ok = filelib:ensure_dir(filename:join(Dep, "deps")++"/"),
|
||||
[file:make_symlink(filename:join([PWD, "deps", M]),
|
||||
filename:join([Dep, "deps", M]))
|
||||
|| M <- Matches];
|
||||
nomatch ->
|
||||
%% remove the symlink
|
||||
file:delete(filename:join(Dep, "deps")),
|
||||
lager:info("~p has no deps", [Dep])
|
||||
end,
|
||||
setup_deps(Rebar, PWD, Deps).
|
||||
|
||||
remove_deps_dir(Dep) ->
|
||||
case filelib:is_dir(filename:join(Dep, "deps")) of
|
||||
true ->
|
||||
%% there should ONLY be a deps dir leftover from a previous run,
|
||||
%% so it should be a directory filled with symlinks
|
||||
{ok, Files} = file:list_dir(filename:join(Dep, "deps")),
|
||||
lists:foreach(fun(F) ->
|
||||
File = filename:join([Dep, "deps", F]),
|
||||
{ok, FI} = file:read_link_info(File),
|
||||
case FI#file_info.type of
|
||||
symlink ->
|
||||
ok = file:delete(File);
|
||||
_ ->
|
||||
ok
|
||||
end
|
||||
end, Files),
|
||||
%% this will fail if the directory is not now empty
|
||||
ok = file:del_dir(filename:join(Dep, "deps")),
|
||||
ok;
|
||||
false ->
|
||||
ok
|
||||
end.
|
||||
|
||||
wait_for_workers([]) ->
|
||||
ok;
|
||||
wait_for_workers(Workers) ->
|
||||
receive
|
||||
{'DOWN', _, _, Pid, normal} ->
|
||||
lager:info("Worker exited normally"),
|
||||
wait_for_workers(Workers -- [Pid]);
|
||||
{'DOWN', _, _, Pid, Reason} ->
|
||||
lager:info("Worker exited abnormally: ~p", [Reason]),
|
||||
wait_for_workers(Workers -- [Pid])
|
||||
end.
|
||||
|
||||
cleanup_logs(Logs) ->
|
||||
case unicode:characters_to_binary(Logs, latin1, unicode) of
|
||||
{error, Bin, Rest} ->
|
||||
lager:error("Bad binary ~p", [Rest]),
|
||||
Bin;
|
||||
{incomplete, Bin, Rest} ->
|
||||
lager:error("Bad binary ~p", [Rest]),
|
||||
Bin;
|
||||
Bin ->
|
||||
Bin
|
||||
end.
|
||||
|
||||
maybe_eol(eol) ->
|
||||
"\n";
|
||||
maybe_eol(noeol) ->
|
||||
"".
|
||||
|
||||
get_status(0) ->
|
||||
pass;
|
||||
get_status(_) ->
|
||||
fail.
|
||||
|
||||
accumulate(P, Acc) ->
|
||||
receive
|
||||
{P, {data, {EOL, Data}}} ->
|
||||
accumulate(P, [[Data,maybe_eol(EOL)]|Acc]);
|
||||
{P, {exit_status, Status}} ->
|
||||
lager:debug("Exited with status ~b", [Status]),
|
||||
{Status, list_to_binary(lists:reverse(Acc))};
|
||||
{P, Other} ->
|
||||
lager:warning("Unexpected return from port: ~p", [Other]),
|
||||
accumulate(P, Acc)
|
||||
end.
|
Loading…
Reference in New Issue
Block a user