diff --git a/.github/workflows/erlang.yml b/.github/workflows/erlang.yml index 11921d7..692d05d 100644 --- a/.github/workflows/erlang.yml +++ b/.github/workflows/erlang.yml @@ -2,7 +2,7 @@ name: Build, Test, Dialyze on: pull_request: - types: [ opened, synchronize ] + types: [ opened, reopened, synchronize ] push: branches: - 'master' diff --git a/rebar.lock b/rebar.lock index 3c10088..3677cf4 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,8 +1,8 @@ {"1.2.0", -[{<<"argparse">>,{pkg,<<"argparse">>,<<"1.1.4">>},0}]}. +[{<<"argparse">>,{pkg,<<"argparse">>,<<"1.2.2">>},0}]}. [ {pkg_hash,[ - {<<"argparse">>, <<"A9F83748FABB1AF2A329484434E542FA02ADE6B6FEE58F5EDA15E3E471359992">>}]}, + {<<"argparse">>, <<"7383D68E0CC88120FD25EAAF43647EA7BE8E50DFA6AAB5649B32F524E6E30C9E">>}]}, {pkg_hash_ext,[ - {<<"argparse">>, <<"AC825D3B52CA64F25A4867D70324FBE940ED9BFC2CB9C8826E0B88D7BF7F73F3">>}]} + {<<"argparse">>, <<"32FEB588D92B53FD06136FC8B3C014F9D2B658CD8DE81AE9B07D663637BA5485">>}]} ]. diff --git a/src/ep_job.erl b/src/ep_job.erl index a71268f..8da5535 100644 --- a/src/ep_job.erl +++ b/src/ep_job.erl @@ -280,7 +280,9 @@ set_concurrency_impl(Concurrency, #state{workers = Workers, init_runner = InitRu runner = Runner, cref = CRef}) when length(Workers) < Concurrency -> Hired = [spawn_link( - fun () -> runner_impl(Runner, call(InitRunner, IR), CRef) end) + fun () -> + runner_impl(Runner, call(InitRunner, IR), CRef) + end) || _ <- lists:seq(length(Workers) + 1, Concurrency)], Workers ++ Hired; diff --git a/src/erlperf.erl b/src/erlperf.erl index 93607e8..6c2c72b 100644 --- a/src/erlperf.erl +++ b/src/erlperf.erl @@ -347,7 +347,7 @@ main_impl(RunOpts, SqueezeOpts, Codes) -> NeedLogger = maps:get(verbose, RunOpts, false), application:set_env(erlperf, start_monitor, NeedLogger), ok = logger:set_handler_config(default, level, warning), - {ok, NeedToStop} = application:ensure_all_started(erlperf), + {ok, Sup} = erlperf_sup:start_link(), % verbose? Logger = if NeedLogger -> @@ -360,7 +360,7 @@ main_impl(RunOpts, SqueezeOpts, Codes) -> run_main(RunOpts, SqueezeOpts, Codes) after Logger =/= undefined andalso ep_file_log:stop(Logger), - [application:stop(App) || App <- NeedToStop] + gen:stop(Sup) end. % profile diff --git a/test/ep_cluster_history_SUITE.erl b/test/ep_cluster_history_SUITE.erl index fa0d8f8..92cb202 100644 --- a/test/ep_cluster_history_SUITE.erl +++ b/test/ep_cluster_history_SUITE.erl @@ -82,7 +82,7 @@ monitor_cluster(Config) -> % start cluster monitor for [time, sched_util, jobs] only {ok, Pid} = ep_cluster_monitor:start({?MODULE, handle_update, [Control]}, [time, sched_util, jobs]), % - {IoProc, GL} = test_helpers:redirect_io(), + ok = ct:capture_start(), {ok, ClusterMonPid} = ep_cluster_monitor:start(), LogFile = filename:join(proplists:get_value(priv_dir, Config), "cluster_log.txt"), {ok, ClusterFilePid} = ep_cluster_monitor:start(LogFile, [time, jobs]), @@ -105,7 +105,8 @@ monitor_cluster(Config) -> % ?assertNotEqual([], History), % - Console = test_helpers:collect_io({IoProc, GL}), + ct:capture_stop(), + Console = ct:capture_get(), % ok = ep_cluster_monitor:stop(ClusterFilePid), ok = ep_cluster_monitor:stop(ClusterMonPid), diff --git a/test/ep_file_log_SUITE.erl b/test/ep_file_log_SUITE.erl index 0de485a..52d8521 100644 --- a/test/ep_file_log_SUITE.erl +++ b/test/ep_file_log_SUITE.erl @@ -55,11 +55,12 @@ console() -> [{doc, "Tests console logging"}]. console(_Config) -> - {IoProc, GL} = test_helpers:redirect_io(), - {ok, Pid} = ep_file_log:start(IoProc), + ok = ct:capture_start(), + {ok, Pid} = ep_file_log:start(erlang:group_leader()), erlperf:run({timer, sleep, [1]}), ep_file_log:stop(Pid), - Console = test_helpers:collect_io({IoProc, GL}), + ok = ct:capture_stop(), + Console = ct:capture_get(), ?assertNotEqual([], Console). % test that we do *not* handle unknown stuff diff --git a/test/erlperf_SUITE.erl b/test/erlperf_SUITE.erl index 13c01be..20a6617 100644 --- a/test/erlperf_SUITE.erl +++ b/test/erlperf_SUITE.erl @@ -142,6 +142,14 @@ start_link() -> {ok, Pid} = gen_server:start_link(?MODULE, [], []), Pid. +%%-------------------------------------------------------------------- +%% helper functions +capture_io(Fun) -> + ok = ct:capture_start(), + Fun(), + ok = ct:capture_stop(), + lists:flatten(ct:capture_get()). + %%-------------------------------------------------------------------- %% TEST CASES %% Permutations: @@ -305,7 +313,7 @@ mfa_squeeze(_Config) -> % erlperf 'timer:sleep(1). -d 100' cmd_line_simple(_Config) -> Code = "timer:sleep(1).", - Out = test_helpers:capture_io(fun () -> erlperf:main([Code, "-d", "100"]) end), + Out = capture_io(fun() -> erlperf:main([Code, "-d", "100"]) end), [LN1, LN2] = string:split(Out, "\n"), ?assertEqual(["Code", "||", "QPS", "Rel"], string:lexemes(LN1, " ")), ?assertMatch([Code, "1", _, "100%\n"], string:lexemes(LN2, " ")), @@ -314,14 +322,14 @@ cmd_line_simple(_Config) -> % erlperf 'timer:sleep(1). -v' cmd_line_verbose(_Config) -> Code = "timer:sleep(1).", - Out = test_helpers:capture_io(fun () -> erlperf:main([Code, "-v"]) end), + Out = capture_io(fun () -> erlperf:main([Code, "-v"]) end), Lines = string:lexemes(Out, "\n"), ?assert(length(Lines) > 3), ok. % erlperf 'rand:uniform().' 'crypto:strong_rand_bytes(2).' -d 100 -s 5 -w 1 -c 2 cmd_line_compare(_Config) -> - Out = test_helpers:capture_io( + Out = capture_io( fun () -> erlperf:main(["timer:sleep(1).", "timer:sleep(2).", "-s", "5", "-d", "100", "-w", "1", "-c", "2"]) end), ?assertNotEqual([], Out), % Code Concurrency Throughput Relative @@ -334,24 +342,24 @@ cmd_line_squeeze() -> % erlperf 'timer:sleep(1).' --sample_duration 50 --squeeze --min 2 --max 4 --threshold 2 cmd_line_squeeze(_Config) -> - Out = test_helpers:capture_io( + Out = capture_io( fun () -> erlperf:main(["timer:sleep(1).", "--sample_duration", "50", "--squeeze", "--min", "2", "--max", "4", "--threshold", "2"]) end), ?assertNotEqual([], Out), ok. % erlperf -q cmd_line_usage(_Config) -> - Out = test_helpers:capture_io(fun () -> erlperf:main(["-q"]) end), + Out = capture_io(fun () -> erlperf:main(["-q"]) end), Line1 = "error: erlperf: required argument missing: code", ?assertEqual(Line1, lists:sublist(Out, length(Line1))), - Out2 = test_helpers:capture_io(fun () -> erlperf:main(["--un code"]) end), + Out2 = capture_io(fun () -> erlperf:main(["--un code"]) end), ?assertEqual("error: erlperf: unrecognised argument: --un code", lists:sublist(Out2, 48)), ok. % erlperf '{file,_}=code:is_loaded(slave).' --init 'code:ensure_loaded(slave).' --done 'code:purge(slave), code:delete(slave).' cmd_line_init(_Config) -> Code = "{file,_}=code:is_loaded(slave).", - Out = test_helpers:capture_io(fun () -> erlperf:main( + Out = capture_io(fun () -> erlperf:main( [Code, "--init", "code:ensure_loaded(slave).", "--done", "code:purge(slave), code:delete(slave)."]) end), % verify 'done' was done @@ -365,7 +373,7 @@ cmd_line_init(_Config) -> % erlperf 'runner(X) -> timer:sleep(X).' --init '1.' 'runner(Y) -> timer:sleep(Y).' --init '2.' -s 2 --duration 100 cmd_line_double(_Config) -> Code = "runner(X)->timer:sleep(X).", - Out = test_helpers:capture_io(fun () -> erlperf:main([Code, "--init", "1.", Code, "--init", "2.", "-s", "2", + Out = capture_io(fun () -> erlperf:main([Code, "--init", "1.", Code, "--init", "2.", "-s", "2", "--duration", "100"]) end), [LN1, LN2, _LN3 | _] = string:split(Out, "\n", all), ?assertEqual(["Code", "||", "QPS", "Rel"], string:lexemes(LN1, " ")), @@ -373,7 +381,7 @@ cmd_line_double(_Config) -> ok. cmd_line_triple(_Config) -> - Out = test_helpers:capture_io(fun () -> erlperf:main(["timer:sleep(1).", "-s", "2", "--duration", "100", + Out = capture_io(fun () -> erlperf:main(["timer:sleep(1).", "-s", "2", "--duration", "100", "timer:sleep(2).", "timer:sleep(3)."]) end), [LN1, _LN2, _LN3, LN4 | _] = string:split(Out, "\n", all), ?assertEqual(["Code", "||", "QPS", "Rel"], string:lexemes(LN1, " ")), @@ -392,7 +400,7 @@ cmd_line_pg(_Config) -> _ -> ?assertEqual(undefined, whereis(scope)), %% ensure scope is not left Code = "runner(S)->ok=pg:join(S,self()),ok=pg:leave(S,self()).", - Out = test_helpers:capture_io(fun () -> erlperf:main( + Out = capture_io(fun () -> erlperf:main( [Code, "--init_runner", "{ok,Scope}=pg:start_link(scope),Scope."]) end), [LN1, LN2] = string:split(Out, "\n"), @@ -404,7 +412,7 @@ cmd_line_pg(_Config) -> % erlperf '{rand, uniform, [100]}' cmd_line_mfa(_Config) -> Code = "{rand,uniform,[4]}", - Out = test_helpers:capture_io(fun () -> erlperf:main([Code]) end), + Out = capture_io(fun () -> erlperf:main([Code]) end), [LN1, LN2] = string:split(Out, "\n"), ?assertEqual(["Code", "||", "QPS", "Rel"], string:lexemes(LN1, " ")), ?assertMatch([Code, "1" | _], string:lexemes(LN2, " ")), @@ -427,7 +435,7 @@ cmd_line_recorded(Config) -> {ets, delete, [test_ets_tab, 100]} ])), % - Out = test_helpers:capture_io(fun () -> erlperf:main( + Out = capture_io(fun () -> erlperf:main( [RecFile, "--init", "ets:file2tab(\"" ++ EtsFile ++ "\")."]) end), [LN1, LN2] = string:split(Out, "\n"), @@ -443,7 +451,7 @@ cmd_line_profile(_Config) -> _ -> ?assertEqual(undefined, whereis(scope)), %% ensure runner is not left from the last run Code = "runner(Arg)->ok=pg:join(Arg,1,self()),ok=pg:leave(Arg,1,self()).", - Out = test_helpers:capture_io(fun () -> erlperf:main( + Out = capture_io(fun () -> erlperf:main( [Code, "--init_runner", "element(2, pg:start_link(scope)).", "--profile"]) end), ?assertEqual(undefined, whereis(scope)), %% ensure runner exited diff --git a/test/test_helpers.erl b/test/test_helpers.erl index 4d10ccc..3a85572 100644 --- a/test/test_helpers.erl +++ b/test/test_helpers.erl @@ -13,10 +13,7 @@ ensure_distributed/1, ensure_started/2, ensure_stopped/1, - maybe_undistribute/1, - redirect_io/0, - collect_io/1, - capture_io/1 + maybe_undistribute/1 ]). ensure_started(App, Config) -> @@ -60,47 +57,3 @@ maybe_undistribute(Config) -> net_kernel:stop(), proplists:delete(distribution, Config) end. - -redirect_io() -> - OldGL = group_leader(), - IoProc = spawn( - fun() -> - collect_io(undefined, []) - end), - group_leader(IoProc, self()), - {IoProc, OldGL}. - -collect_io({IoProc, OldGL}) -> - group_leader(OldGL, self()), - IoProc ! {flush, self()}, - receive - {flush, Data} -> - Data - end. - -capture_io(Fun) when is_function(Fun) -> - Pid = spawn(fun() -> - receive run -> ok end, - Fun() - end), - Mref = erlang:monitor(process,Pid), - group_leader(self(), Pid), - Pid ! run, - collect_io(Mref, []). - -collect_io(Mref, Ack) -> - receive - {'DOWN', Mref, _,_,_} -> - lists:flatten(io_lib:format("~s", [lists:reverse(Ack)])); - {io_request, From, Me, {put_chars, M, F, A}} -> - From ! {io_reply, Me, ok}, - collect_io(Mref, [apply(M,F, A) | Ack]); - {io_request, From, Me, {put_chars, latin1, Binary}} -> - From ! {io_reply, Me, ok}, - collect_io(Mref, [Binary | Ack]); - {io_request, From, Me, {put_chars, unicode, M, F, A}} -> - From ! {io_reply, Me, ok}, - collect_io(Mref, [apply(M,F, A) | Ack]); - {flush, WhereTo} -> - WhereTo ! {flush, lists:reverse(Ack)} - end.