aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/test/megaco_test_lib.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/test/megaco_test_lib.erl')
-rw-r--r--lib/megaco/test/megaco_test_lib.erl349
1 files changed, 190 insertions, 159 deletions
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 55eee97443..f64743f32a 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -112,101 +112,17 @@ os_based_skip(_) ->
%% {Mod, Fun, ExpectedRes, ActualRes}
%%----------------------------------------------------------------------
-tickets(Case) ->
- Res = lists:flatten(tickets(Case, default_config())),
- %% io:format("~w:tickets(Case = ~w) -> Res: ~p~n", [?MODULE, Case, Res]),
+tickets([Mod]) ->
+ tickets(Mod);
+tickets(Mod) when is_atom(Mod) ->
+ %% p("tickets -> entry with"
+ %% "~n Mod: ~p", [Mod]),
+ Res0 = t({Mod, {group, tickets}, Mod:groups()}, default_config()),
+ Res = lists:flatten(Res0),
+ %% p("tickets(~w) -> Res: ~p~n", [Mod, Res]),
display_result(Res),
Res.
-tickets(Cases, Config) when is_list(Cases) ->
- [tickets(Case, Config) || Case <- Cases];
-tickets(Mod, Config) when is_atom(Mod) ->
- Res = tickets(Mod, tickets, Config),
- %% io:format("~w:tickets(Mod = ~w) -> Res: ~p~n", [?MODULE, Mod, Res]),
- Res;
-tickets(Bad, _Config) ->
- [{badarg, Bad, ok}].
-
-tickets(Mod, Func, Config) ->
- %% io:format("~w:tickets -> entry with"
- %% "~n Mod: ~p"
- %% "~n Func: ~p"
- %% "~n Config: ~p"
- %% "~n", [?MODULE, Mod, Func, Config]),
- case (catch Mod:Func(suite)) of
- [] ->
- io:format("Eval: ~p:", [{Mod, Func}]),
- Res = eval(Mod, Func, Config),
- %% io:format("~w:tickets -> evaluated"
- %% "~n Res: ~p"
- %% "~n", [?MODULE, Res]),
- {R, _, _, _} = Res,
- io:format(" ~p~n", [R]),
- Res;
-
- Cases when is_list(Cases) ->
- io:format("Expand: ~p:~p ... ~n"
- " ~p~n", [Mod, Func, Cases]),
- Map = fun({M,_}) when is_atom(M) ->
- tickets(M, tickets, Config);
- (F) when is_atom(F) ->
- tickets(Mod, F, Config);
- (Case) -> Case
- end,
- lists:map(Map, Cases);
-
- {req, _, {conf, Init, Cases, Finish}} ->
- %% io:format("~w:tickets -> suite result req-conf: "
- %% "~n Init: ~p"
- %% "~n Cases: ~p"
- %% "~n Finish: ~p"
- %% "~n", [?MODULE, Init, Cases, Finish]),
- case (catch Mod:Init(Config)) of
- Conf when is_list(Conf) ->
- io:format("Expand: ~p:~p ...~n", [Mod, Func]),
- Map = fun({M,_}) when is_atom(M) ->
- %% io:format("~w:tickets -> "
- %% "~n M: ~p"
- %% "~n", [?MODULE, M]),
- tickets(M, tickets, Conf);
- (F) when is_atom(F) ->
- %% io:format("~w:tickets -> "
- %% "~n F: ~p"
- %% "~n", [?MODULE, F]),
- tickets(Mod, F, Conf);
- (Case) ->
- %% io:format("~w:tickets -> "
- %% "~n Case: ~p"
- %% "~n", [?MODULE, Case]),
- Case
- end,
- Res = lists:map(Map, Cases),
- %% io:format("~w:tickets -> and now finish when: "
- %% "~n Res: ~p"
- %% "~n", [?MODULE, Res]),
- (catch Mod:Finish(Conf)),
- %% io:format("~w:tickets -> finished"
- %% "~n", [?MODULE]),
- Res;
-
- {'EXIT', {skipped, Reason}} ->
- io:format(" => skipping: ~p~n", [Reason]),
- [{skipped, {Mod, Func}, Reason}];
-
- Error ->
- io:format(" => init failed: ~p~n", [Error]),
- [{failed, {Mod, Func}, Error}]
- end;
-
- {'EXIT', {undef, _}} ->
- io:format("Undefined: ~p~n", [{Mod, Func}]),
- [{nyi, {Mod, Func}, ok}];
-
- Error ->
- io:format("Ignoring: ~p:~p: ~p~n", [Mod, Func, Error]),
- [{failed, {Mod, Func}, Error}]
- end.
-
display_alloc_info() ->
io:format("Allocator memory information:~n", []),
@@ -281,7 +197,13 @@ alloc_instance_mem_info(Key, InstanceInfo) ->
end.
+t([Case]) when is_atom(Case) ->
+ %% p("t -> entry with"
+ %% "~n [Case]: [~p]", [Case]),
+ t(Case);
t(Case) ->
+ %% p("t -> entry with"
+ %% "~n Case: ~p", [Case]),
process_flag(trap_exit, true),
MEM = fun() -> case (catch erlang:memory()) of
{'EXIT', _} ->
@@ -295,12 +217,66 @@ t(Case) ->
Res = lists:flatten(t(Case, default_config())),
Alloc2 = alloc_info(),
Mem2 = MEM(),
- %% io:format("Res: ~p~n", [Res]),
display_result(Res, Alloc1, Mem1, Alloc2, Mem2),
Res.
-t({Mod, Fun}, Config) when is_atom(Mod) andalso is_atom(Fun) ->
- case catch apply(Mod, Fun, [suite]) of
+
+groups(Mod) when is_atom(Mod) ->
+ try Mod:groups() of
+ Groups when is_list(Groups) ->
+ Groups;
+ BadGroups ->
+ exit({bad_groups, Mod, BadGroups})
+ catch
+ _:_ ->
+ []
+ end.
+
+init_suite(Mod, Config) ->
+ Mod:init_per_suite(Config).
+
+end_suite(Mod, Config) ->
+ Mod:end_per_suite(Config).
+
+init_group(Mod, Group, Config) ->
+ Mod:init_per_group(Group, Config).
+
+end_group(Mod, Group, Config) ->
+ Mod:init_per_group(Group, Config).
+
+%% This is for sub-SUITEs
+t({_Mod, {NewMod, all}, _Groups}, _Config) when is_atom(NewMod) ->
+ t(NewMod);
+t({Mod, {group, Name} = Group, Groups}, Config)
+ when is_atom(Mod) andalso is_atom(Name) andalso is_list(Groups) ->
+ case lists:keysearch(Name, 1, Groups) of
+ {value, {Name, _Props, GroupsAndCases}} ->
+ try init_group(Mod, Name, Config) of
+ Config2 when is_list(Config2) ->
+ Res = [t({Mod, Case, Groups}, Config2) ||
+ Case <- GroupsAndCases],
+ (catch end_group(Mod, Name, Config2)),
+ Res;
+ Error ->
+ io:format(" => group (~w) init failed: ~p~n",
+ [Name, Error]),
+ [{failed, {Mod, Group}, Error}]
+ catch
+ exit:{skipped, SkipReason} ->
+ io:format(" => skipping group: ~p~n", [SkipReason]),
+ [{skipped, {Mod, Group}, SkipReason, 0}];
+ error:undef ->
+ [t({Mod, Case, Groups}, Config) ||
+ Case <- GroupsAndCases];
+ T:E ->
+ [{failed, {Mod, Group}, {T,E}, 0}]
+ end;
+ false ->
+ exit({unknown_group, Mod, Name, Groups})
+ end;
+t({Mod, Fun, _}, Config)
+ when is_atom(Mod) andalso is_atom(Fun) ->
+ try apply(Mod, Fun, [suite]) of
[] ->
io:format("Eval: ~p:", [{Mod, Fun}]),
Res = eval(Mod, Fun, Config),
@@ -315,39 +291,57 @@ t({Mod, Fun}, Config) when is_atom(Mod) andalso is_atom(Fun) ->
end,
t(lists:map(Map, Cases), Config);
- {req, _, {conf, Init, Cases, Finish}} ->
- case (catch apply(Mod, Init, [Config])) of
- Conf when is_list(Conf) ->
- io:format("Expand: ~p ...~n", [{Mod, Fun}]),
- Map = fun(Case) when is_atom(Case) -> {Mod, Case};
- (Case) -> Case
- end,
- Res = t(lists:map(Map, Cases), Conf),
- (catch apply(Mod, Finish, [Conf])),
- Res;
-
- {'EXIT', {skipped, Reason}} ->
- io:format(" => skipping: ~p~n", [Reason]),
- [{skipped, {Mod, Fun}, Reason, 0}];
-
- Error ->
- io:format(" => failed: ~p~n", [Error]),
- [{failed, {Mod, Fun}, Error, 0}]
- end;
-
- {'EXIT', {undef, _}} ->
- io:format("Undefined: ~p~n", [{Mod, Fun}]),
- [{nyi, {Mod, Fun}, ok, 0}];
-
Error ->
io:format("Ignoring: ~p: ~p~n", [{Mod, Fun}, Error]),
[{failed, {Mod, Fun}, Error, 0}]
+
+ catch
+ error:undef ->
+ io:format("Undefined: ~p~n", [{Mod, Fun}]),
+ [{nyi, {Mod, Fun}, ok, 0}]
+
+
end;
t(Mod, Config) when is_atom(Mod) ->
- Res = t({Mod, all}, Config),
- Res;
-t(Cases, Config) when is_list(Cases) ->
- [t(Case, Config) || Case <- Cases];
+ %% p("t -> entry with"
+ %% "~n Mod: ~p"
+ %% "~n Config: ~p", [Mod, Config]),
+ %% This is assumed to be a test suite, so we start by calling
+ %% the top test suite function(s) (all/0 and groups/0).
+ try Mod:all() of
+ Cases when is_list(Cases) ->
+ %% The list may contain atoms (actual test cases) and
+ %% group-tuples (a tuple naming a group of test cases).
+ %% A group is defined by the (optional) groups/0 function.
+ Groups = groups(Mod),
+ try init_suite(Mod, Config) of
+ Config2 when is_list(Config2) ->
+ Res = [t({Mod, Case, Groups}, Config2) || Case <- Cases],
+ (catch end_suite(Mod, Config2)),
+ Res;
+ Error ->
+ io:format(" => suite init failed: ~p~n", [Error]),
+ [{failed, {Mod, init_per_suite}, Error}]
+ catch
+ exit:{skipped, SkipReason} ->
+ io:format(" => skipping suite: ~p~n", [SkipReason]),
+ [{skipped, {Mod, init_per_suite}, SkipReason, 0}];
+ error:undef ->
+ [t({Mod, Case, Groups}, Config) || Case <- Cases];
+ T:E ->
+ io:format(" => failed suite: ~p~n", [{T,E}]),
+ [{failed, {Mod, init_per_suite}, {T,E}, 0}]
+ end;
+
+ Crap ->
+ Crap
+
+ catch
+ error:undef ->
+ io:format("Undefined: ~p~n", [{Mod, all}]),
+ [{nyi, {Mod, all}, ok, 0}]
+
+ end;
t(Bad, _Config) ->
[{badarg, Bad, ok, 0}].
@@ -362,7 +356,7 @@ eval(Mod, Fun, Config) ->
Config2 = Mod:init_per_testcase(Fun, Config),
Pid = spawn_link(?MODULE, do_eval, [self(), Mod, Fun, Config2]),
R = wait_for_evaluator(Pid, Mod, Fun, Config2, []),
- Mod:fin_per_testcase(Fun, Config2),
+ Mod:end_per_testcase(Fun, Config2),
erase(megaco_test_server),
global:unregister_name(megaco_test_case_sup),
process_flag(trap_exit, Flag),
@@ -411,15 +405,24 @@ wait_for_evaluator(Pid, Mod, Fun, Config, Errors, AccTime) ->
do_eval(ReplyTo, Mod, Fun, Config) ->
display_system_info("before", Mod, Fun),
- case timer:tc(Mod, Fun, [Config]) of
- {Time, {'EXIT', {skipped, Reason}}} ->
- display_tc_time(Time),
- display_system_info("after (skipped)", Mod, Fun),
- ReplyTo ! {'EXIT', self(), {skipped, Reason}, Time};
- {Time, Other} ->
+ T1 = os:timestamp(),
+ try Mod:Fun(Config) of
+ Res ->
+ T2 = os:timestamp(),
+ Time = timer:now_diff(T2, T1),
display_tc_time(Time),
display_system_info("after", Mod, Fun),
- ReplyTo ! {done, self(), Other, Time}
+ ReplyTo ! {done, self(), Res, Time}
+ catch
+ error:undef ->
+ ReplyTo ! {'EXIT', self(), undef, 0};
+ exit:{skipped, Reason} ->
+ T2 = os:timestamp(),
+ Time = timer:now_diff(T2, T1),
+ display_tc_time(Time),
+ display_system_info("after (skipped)", Mod, Fun),
+ ReplyTo ! {'EXIT', self(), {skipped, Reason}, Time}
+
end,
unlink(ReplyTo),
exit(shutdown).
@@ -524,28 +527,56 @@ do_display_memory([{Key, Mem1}|MemInfo1], MemInfo2) ->
display_result([]) ->
io:format("OK~n", []);
display_result(Res) when is_list(Res) ->
- Ok = [{MF, Time} || {ok, MF, _, Time} <- Res],
- Nyi = [MF || {nyi, MF, _, _Time} <- Res],
- Skipped = [{MF, Reason} || {skipped, MF, Reason, _Time} <- Res],
- Failed = [{MF, Reason} || {failed, MF, Reason, _Time} <- Res],
- Crashed = [{MF, Reason} || {crashed, MF, Reason, _Time} <- Res],
- display_summery(Ok, Nyi, Skipped, Failed, Crashed),
+ Ok = [{MF, Time} || {ok, MF, _, Time} <- Res],
+ Nyi = [MF || {nyi, MF, _, _Time} <- Res],
+ SkippedGrps = [{{M,G}, Reason} ||
+ {skipped, {M, {group, G}}, Reason, _Time} <- Res],
+ SkippedCases = [{MF, Reason} ||
+ {skipped, {_M, F} = MF, Reason, _Time} <- Res,
+ is_atom(F)],
+ FailedGrps = [{{M,G}, Reason} ||
+ {failed, {M, {group, G}}, Reason, _Time} <- Res],
+ FailedCases = [{MF, Reason} ||
+ {failed, {_M, F} = MF, Reason, _Time} <- Res,
+ is_atom(F)],
+ Crashed = [{MF, Reason} || {crashed, MF, Reason, _Time} <- Res],
+ display_summery(Ok, Nyi,
+ SkippedGrps, SkippedCases,
+ FailedGrps, FailedCases,
+ Crashed),
display_ok(Ok),
- display_skipped(Skipped),
- display_failed(Failed),
+ display_skipped("groups", SkippedGrps),
+ display_skipped("test cases", SkippedCases),
+ display_failed("groups", FailedGrps),
+ display_failed("test cases", FailedCases),
display_crashed(Crashed).
-display_summery(Ok, Nyi, Skipped, Failed, Crashed) ->
+display_summery(Ok, Nyi,
+ SkippedGrps, SkippedCases,
+ FailedGrps, FailedCases,
+ Crashed) ->
io:format("~nTest case summery:~n", []),
- display_summery(Ok, "successfull"),
- display_summery(Nyi, "not yet implemented"),
- display_summery(Skipped, "skipped"),
- display_summery(Failed, "failed"),
- display_summery(Crashed, "crashed"),
+ display_summery(Ok, "test case", "successfull"),
+ display_summery(Nyi, "test case", "not yet implemented"),
+ display_summery(SkippedGrps, "group", "skipped"),
+ display_summery(SkippedCases, "test case", "skipped"),
+ display_summery(FailedGrps, "group", "failed"),
+ display_summery(FailedCases, "test case", "failed"),
+ display_summery(Crashed, "test case", "crashed"),
io:format("~n", []).
-display_summery(Res, Info) ->
- io:format(" ~w test cases ~s~n", [length(Res), Info]).
+
+display_summery(Res, Kind, Info) ->
+ Len = length(Res),
+ if
+ Len =:= 1 ->
+ display_summery(Len, Kind ++ " " ++ Info);
+ true ->
+ display_summery(Len, Kind ++ "s " ++ Info)
+ end.
+
+display_summery(Len, Info) ->
+ io:format(" ~w ~s~n", [Len, Info]).
display_ok([]) ->
ok;
@@ -557,20 +588,20 @@ display_ok(Ok) ->
lists:foreach(F, Ok),
io:format("~n", []).
-display_skipped([]) ->
+display_skipped(_, []) ->
ok;
-display_skipped(Skipped) ->
- io:format("Skipped test cases:~n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end,
+display_skipped(Pre, Skipped) ->
+ io:format("Skipped ~s:~n", [Pre]),
+ F = fun({X, Reason}) -> io:format(" ~p => ~p~n", [X, Reason]) end,
lists:foreach(F, Skipped),
io:format("~n", []).
-display_failed([]) ->
+display_failed(_, []) ->
ok;
-display_failed(Failed) ->
- io:format("Failed test cases:~n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p~n", [MF, Reason]) end,
+display_failed(Pre, Failed) ->
+ io:format("Failed ~s:~n", [Pre]),
+ F = fun({X, Reason}) -> io:format(" ~p => ~p~n", [X, Reason]) end,
lists:foreach(F, Failed),
io:format("~n", []).
@@ -706,11 +737,11 @@ init_per_testcase(_Case, Config) ->
end,
set_kill_timer(Config).
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
Name = megaco_global_logger,
case global:whereis_name(Name) of
undefined ->
- io:format("~w:fin_per_testcase -> already un-registered~n",
+ io:format("~w:end_per_testcase -> already un-registered~n",
[?MODULE]),
ok;
Pid when is_pid(Pid) ->
@@ -866,5 +897,5 @@ start_nodes([Node | Nodes], File, Line) ->
start_nodes([], _File, _Line) ->
ok.
-p(F,A) ->
- io:format("~p" ++ F ++ "~n", [self()|A]).
+p(F, A) ->
+ io:format("~p~w:" ++ F ++ "~n", [self(), ?MODULE |A]).