summaryrefslogtreecommitdiff
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.erl1128
1 files changed, 953 insertions, 175 deletions
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 8e7c3bec68..1eab21ef5a 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -50,7 +50,7 @@
display_system_info/1, display_system_info/2, display_system_info/3,
executor/1, executor/2,
- try_tc/6,
+ try_tc/6, try_tc/7,
prepare_test_case/5,
@@ -62,6 +62,7 @@
stop_nodes/3,
stop_node/3,
+ ping/1, ping/2,
is_socket_backend/1,
inet_backend_opts/1,
@@ -75,9 +76,12 @@
-export([proxy_init/2]).
+%% Convenient exports...
+-export([analyze_and_print_host_info/0]).
+
-include("megaco_test_lib.hrl").
--record('REASON', {mod, line, desc}).
+%% -record('REASON', {mod, line, desc}).
%% ----------------------------------------------------------------
@@ -363,19 +367,11 @@ display_system_info(WhenStr, ModFuncStr) ->
%% Stores the result in the process dictionary if mismatch
error(Actual, Mod, Line) ->
- global:send(megaco_global_logger, {failed, Mod, Line}),
log("<ERROR> Bad result: ~p~n", [Actual], Mod, Line),
Label = lists:concat([Mod, "(", Line, ") unexpected result"]),
megaco:report_event(60, Mod, Mod, Label,
[{line, Mod, Line}, {error, Actual}]),
- case global:whereis_name(megaco_test_case_sup) of
- undefined ->
- ignore;
- Pid ->
- Fail = #'REASON'{mod = Mod, line = Line, desc = Actual},
- Pid ! {fail, self(), Fail}
- end,
- Actual.
+ exit(Actual).
log(Format, Args, Mod, Line) ->
case global:whereis_name(megaco_global_logger) of
@@ -717,43 +713,421 @@ num_schedulers_to_factor() ->
end.
-
+ts_extra_platform_label() ->
+ case os:getenv("TS_EXTRA_PLATFORM_LABEL") of
+ false -> "-";
+ Val -> Val
+ end.
+
+ts_scale_factor() ->
+ case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
+ _ ->
+ 0
+ end.
+
+simplify_label("Systemtap" ++ _) ->
+ {host, systemtap};
+simplify_label("Meamax" ++ _) ->
+ {host, meamax};
+simplify_label("Cover" ++ _) ->
+ {host, cover};
+simplify_label(Label) ->
+ case string:find(string:to_lower(Label), "docker") of
+ "docker" ++ _ ->
+ docker;
+ _ ->
+ {host, undefined}
+ end.
+
+label2factor(docker) ->
+ 4;
+label2factor({host, meamax}) ->
+ 2;
+label2factor({host, cover}) ->
+ 6;
+label2factor({host, _}) ->
+ 0.
+
linux_which_distro(Version) ->
- case file:read_file_info("/etc/issue") of
+ Label = ts_extra_platform_label(),
+ Checks =
+ [fun() -> do_linux_which_distro_os_release(Version, Label) end,
+ fun() -> do_linux_which_distro_suse_release(Version, Label) end,
+ fun() -> do_linux_which_distro_fedora_release(Version, Label) end,
+ fun() -> do_linux_which_distro_issue(Version, Label) end],
+ try linux_which_distro("", Version, Label, Checks)
+ catch
+ throw:{distro, Distro} ->
+ Distro
+ end.
+
+linux_which_distro("", Version, Label, []) ->
+ io:format("Linux: ~s"
+ "~n Label: ~s"
+ "~n Product Name: ~s"
+ "~n", [Version, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)};
+linux_which_distro(DestroStr, Version, Label, []) ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Label: ~s"
+ "~n Product Name: ~s"
+ "~n", [Version, DestroStr, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)};
+linux_which_distro(Default, Version, Label, [Check|Checks]) ->
+ try Check() of
+ DistroStr when is_list(DistroStr) ->
+ linux_which_distro(DistroStr, Version, Label, Checks);
+ retry ->
+ linux_which_distro(Default, Version, Label, Checks);
+ {error, _Reason} ->
+ linux_which_distro(Default, Version, Label, Checks)
+ catch
+ throw:{error, _Reason} ->
+ linux_which_distro(Default, Version, Label, Checks)
+ end.
+
+
+do_linux_which_distro_os_release(Version, Label) ->
+ case file:read_file_info("/etc/os-release") of
+ {ok, _} ->
+ %% We want to 'catch' if our processing is wrong,
+ %% that's why we catch and re-throw the distro.
+ %% Actual errors will be returned as 'ignore'.
+ try
+ begin
+ Info = linux_process_os_release(),
+ {value, {_, DistroStr}} = lists:keysearch(name, 1, Info),
+ {value, {_, VersionNo}} = lists:keysearch(version, 1, Info),
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, VersionNo, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_distro_str_to_distro_id(DistroStr),
+ simplify_label(Label)}})
+ end
+ catch
+ throw:{distro, _} = DISTRO ->
+ throw(DISTRO);
+ _:_ ->
+ retry
+ end;
+ _ ->
+ retry
+ end.
+
+
+linux_process_os_release() ->
+ %% Read the "raw" file
+ Raw = os:cmd("cat /etc/os-release"),
+ %% Split it into lines
+ Lines1 = string:tokens(Raw, [$\n]),
+ %% Just in case, skip any lines starting with '#'.
+ Lines2 = linux_process_os_release1(Lines1),
+ %% Each (remaining) line *should* be: <TAG>=<VALUE>
+ %% Both sides will be strings, the value side will be a quoted string...
+ %% Convert those into a 2-tuple list: [{Tag, Value}]
+ linux_process_os_release2(Lines2).
+
+linux_process_os_release1(Lines) ->
+ linux_process_os_release1(Lines, []).
+
+linux_process_os_release1([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release1([H|T], Acc) ->
+ case H of
+ "#" ++ _ ->
+ linux_process_os_release1(T, Acc);
+ _ ->
+ linux_process_os_release1(T, [H|Acc])
+ end.
+
+linux_process_os_release2(Lines) ->
+ linux_process_os_release2(Lines, []).
+
+linux_process_os_release2([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release2([H|T], Acc) ->
+ case linux_process_os_release3(H) of
+ {value, Value} ->
+ linux_process_os_release2(T, [Value|Acc]);
+ false ->
+ linux_process_os_release2(T, Acc)
+ end.
+
+linux_process_os_release3(H) ->
+ case [string:strip(S) || S <- string:tokens(H, [$=])] of
+ [Tag, Value] ->
+ Tag2 = list_to_atom(string:to_lower(Tag)),
+ Value2 = string:strip(Value, both, $"),
+ linux_process_os_release4(Tag2, Value2);
+ _ ->
+ false
+ end.
+
+linux_process_os_release4(name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version_id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(pretty_name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(_Tag, _Value) ->
+ false.
+
+linux_distro_str_to_distro_id("Debian" ++ _) ->
+ debian;
+linux_distro_str_to_distro_id("Fedora" ++ _) ->
+ fedora;
+linux_distro_str_to_distro_id("Linux Mint" ++ _) ->
+ linux_mint;
+linux_distro_str_to_distro_id("MontaVista" ++ _) ->
+ montavista;
+linux_distro_str_to_distro_id("openSUSE" ++ _) ->
+ suse;
+linux_distro_str_to_distro_id("SLES" ++ _) ->
+ sles;
+linux_distro_str_to_distro_id("Ubuntu" ++ _) ->
+ ubuntu;
+linux_distro_str_to_distro_id("Wind River Linux" ++ _) ->
+ wind_river;
+linux_distro_str_to_distro_id("Yellow Dog" ++ _) ->
+ yellow_dog;
+linux_distro_str_to_distro_id(X) ->
+ X.
+
+
+do_linux_which_distro_fedora_release(Version, Label) ->
+ %% Check if fedora
+ case file:read_file_info("/etc/fedora-release") of
{ok, _} ->
case [string:trim(S) ||
- S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
- [DistroStr|_] ->
+ S <- string:tokens(os:cmd("cat /etc/fedora-release"),
+ [$\n])] of
+ [DistroStr | _] ->
io:format("Linux: ~s"
- "~n ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
"~n",
- [Version, DistroStr]),
+ [Version, DistroStr, Label,
+ linux_product_name()]);
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Fedora", Label,
+ linux_product_name()])
+ end,
+ throw({distro, {fedora, simplify_label(Label)}});
+ _ ->
+ throw({error, not_found})
+ end.
+
+do_linux_which_distro_suse_release(Version, Label) ->
+ %% Check if its a SuSE
+ case file:read_file_info("/etc/SUSE-brand") of
+ {ok, _} ->
+ case file:read_file_info("/etc/SuSE-release") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/SuSE-release"),
+ [$\n])] of
+ ["SUSE Linux Enterprise Server" ++ _ = DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {sles, simplify_label(Label)}});
+ [DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "SuSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ case string:tokens(os:cmd("cat /etc/SUSE-brand"), [$\n]) of
+ ["SLE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}})
+ end;
+ ["openSUSE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Unknown SUSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end
+ end;
+ _ ->
+ throw({error, not_found})
+ end.
+
+do_linux_which_distro_issue(Version, Label) ->
+ case file:read_file_info("/etc/issue") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
+ [DistroStr | _] ->
case DistroStr of
"Wind River Linux" ++ _ ->
- wind_river;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {wind_river, simplify_label(Label)}});
"MontaVista" ++ _ ->
- montavista;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {montavista, simplify_label(Label)}});
"Yellow Dog" ++ _ ->
- yellow_dog;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {yellow_dog, simplify_label(Label)}});
+ "Ubuntu" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {ubuntu, simplify_label(Label)}});
+ "Linux Mint" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_mint, simplify_label(Label)}});
+ "Debian" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {debian, simplify_label(Label)}});
_ ->
- other
+ DistroStr
end;
X ->
- io:format("Linux: ~s"
- "~n ~p"
- "~n",
- [Version, X]),
- other
+ X
end;
_ ->
- io:format("Linux: ~s"
- "~n", [Version]),
- other
+ throw({error, not_found})
end.
+
-
analyze_and_print_linux_host_info(Version) ->
- Distro = linux_which_distro(Version),
+ {Distro, Label} = linux_which_distro(Version),
+ %% 'VirtFactor' will be 0 unless virtual
+ VirtFactor = linux_virt_factor(),
Factor =
case (catch linux_which_cpuinfo(Distro)) of
{ok, {CPU, BogoMIPS}} ->
@@ -765,14 +1139,18 @@ analyze_and_print_linux_host_info(Version) ->
if
(BogoMIPS > 50000) ->
1;
- (BogoMIPS > 30000) ->
+ (BogoMIPS > 40000) ->
2;
- (BogoMIPS > 10000) ->
+ (BogoMIPS > 30000) ->
3;
- (BogoMIPS > 5000) ->
+ (BogoMIPS > 20000) ->
+ 4;
+ (BogoMIPS > 10000) ->
5;
- (BogoMIPS > 3000) ->
+ (BogoMIPS > 5000) ->
8;
+ (BogoMIPS > 3000) ->
+ 12;
true ->
10
end;
@@ -805,21 +1183,53 @@ analyze_and_print_linux_host_info(Version) ->
_ ->
5
end,
+ AddLabelFactor = label2factor(Label),
%% Check if we need to adjust the factor because of the memory
- try linux_which_meminfo() of
- AddFactor ->
- {Factor + AddFactor, []}
- catch
- _:_:_ ->
- {Factor, []}
- end.
+ AddMemFactor = try linux_which_meminfo()
+ catch _:_:_ -> 0
+ end,
+ TSScaleFactor = case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
+ _ ->
+ 0
+ end,
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n Virtual Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n", [Factor, AddLabelFactor, AddMemFactor, VirtFactor,
+ TSScaleFactor]),
+ {Factor + AddLabelFactor + AddMemFactor + VirtFactor + TSScaleFactor,
+ [{label, Label}]}.
+
+
+linux_virt_factor() ->
+ linux_virt_factor(linux_product_name()).
+
+linux_virt_factor("VMware" ++ _) ->
+ 2;
+linux_virt_factor("VirtualBox" ++ _) ->
+ 4;
+linux_virt_factor(_) ->
+ 0.
linux_cpuinfo_lookup(Key) when is_list(Key) ->
linux_info_lookup(Key, "/proc/cpuinfo").
linux_cpuinfo_bogomips() ->
- case linux_cpuinfo_lookup("bogomips") of
+ case linux_cpuinfo_bogomips("bogomips") of
+ "-" ->
+ linux_cpuinfo_bogomips("BogoMIPS");
+ Res ->
+ Res
+ end.
+
+linux_cpuinfo_bogomips(Key) ->
+ case linux_cpuinfo_lookup(Key) of
[] ->
"-";
BMips when is_list(BMips) ->
@@ -864,7 +1274,14 @@ linux_cpuinfo_model() ->
[M] ->
M;
_ ->
- "-"
+ %% Note that some distros/platforms,
+ %% the first char is Capital, that is: Model...
+ case linux_cpuinfo_lookup("Model") of
+ [M] ->
+ M;
+ _ ->
+ "-"
+ end
end.
linux_cpuinfo_platform() ->
@@ -907,6 +1324,14 @@ linux_cpuinfo_processor() ->
"-"
end.
+linux_cpuinfo_machine() ->
+ case linux_cpuinfo_lookup("machine") of
+ [M] ->
+ M;
+ _ ->
+ "-"
+ end.
+
linux_cpuinfo_clock() ->
%% This is written as: "3783.000000MHz"
%% So, check unit MHz (handle nothing else).
@@ -991,6 +1416,52 @@ linux_which_cpuinfo(wind_river) ->
{ok, {CPU, BMips}}
end;
+linux_which_cpuinfo(Distro) when (Distro =:= debian) orelse
+ (Distro =:= fedora) orelse
+ (Distro =:= linux_mint) orelse
+ (Distro =:= sles) orelse
+ (Distro =:= suse) orelse
+ (Distro =:= ubuntu) orelse
+ (Distro =:= other) ->
+ CPU =
+ case linux_cpuinfo_model_name() of
+ "-" ->
+ %% This is for POWER9
+ case linux_cpuinfo_cpu() of
+ "POWER9" ++ _ = PowerCPU ->
+ Machine =
+ case linux_cpuinfo_machine() of
+ "-" ->
+ "";
+ M ->
+ " (" ++ M ++ ")"
+ end,
+ PowerCPU ++ Machine;
+ _X ->
+ %% ARM (at least some distros...)
+ case linux_cpuinfo_processor() of
+ "-" ->
+ case linux_cpuinfo_model() of
+ "-" ->
+ %% Ok, we give up
+ throw(noinfo);
+ Model ->
+ Model
+ end;
+ Proc ->
+ Proc
+ end
+ end;
+ ModelName ->
+ ModelName
+ end,
+ case linux_cpuinfo_bogomips() of
+ "-" ->
+ {ok, CPU};
+ BMips ->
+ {ok, {CPU, BMips}}
+ end;
+
linux_which_cpuinfo(other) ->
%% Check for x86 (Intel or AMD or Power)
CPU =
@@ -1072,6 +1543,22 @@ linux_which_meminfo() ->
end.
+linux_product_name() ->
+ ProductNameFile = "/sys/devices/virtual/dmi/id/product_name",
+ case file:read_file_info(ProductNameFile) of
+ {ok, _} ->
+ case os:cmd("cat " ++ ProductNameFile) of
+ false ->
+ "-";
+ Info ->
+ string:trim(Info)
+ end;
+ _ ->
+ "-"
+ end.
+
+
+
%% Just to be clear: This is ***not*** scientific...
analyze_and_print_openbsd_host_info(Version) ->
io:format("OpenBSD:"
@@ -1120,45 +1607,78 @@ analyze_and_print_openbsd_host_info(Version) ->
"~n", [CPU, CPUSpeed, NCPU, Memory]),
CPUFactor =
if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
+ (CPUSpeed >= 3000) ->
if
- (NCPU >= 4) ->
+ (NCPU >= 8) ->
1;
+ (NCPU >= 6) ->
+ 2;
+ (NCPU >= 4) ->
+ 3;
(NCPU >= 2) ->
+ 4;
+ true ->
+ 10
+ end;
+ (CPUSpeed >= 2000) ->
+ if
+ (NCPU >= 8) ->
2;
+ (NCPU >= 6) ->
+ 3;
+ (NCPU >= 4) ->
+ 4;
+ (NCPU >= 2) ->
+ 5;
true ->
- 3
+ 12
+ end;
+ (CPUSpeed >= 1000) ->
+ if
+ (NCPU >= 8) ->
+ 3;
+ (NCPU >= 6) ->
+ 4;
+ (NCPU >= 4) ->
+ 5;
+ (NCPU >= 2) ->
+ 6;
+ true ->
+ 14
end;
true ->
if
+ (NCPU >= 8) ->
+ 4;
+ (NCPU >= 6) ->
+ 6;
(NCPU >= 4) ->
- 2;
+ 8;
(NCPU >= 2) ->
- 3;
+ 10;
true ->
- 4
+ 20
end
end,
MemAddFactor =
if
- (Memory =:= -1) ->
+ (Memory >= 16777216) ->
0;
(Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
1;
+ (Memory >= 4194304) ->
+ 3;
(Memory >= 2097152) ->
- 2;
+ 5;
true ->
- 3
+ 10
end,
{CPUFactor + MemAddFactor, []}
end
catch
_:_:_ ->
- {5, []}
+ io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
+ {10, []}
end.
@@ -1449,47 +1969,57 @@ analyze_and_print_darwin_host_info(Version) ->
%% we need to find some other way to find some info...
%% Also, I suppose its possible that we for some other
%% reason *fail* to get the info...
- case analyze_darwin_software_info() of
- [] ->
- io:format("Darwin:"
- "~n Version: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [Version, str_num_schedulers()]),
- {num_schedulers_to_factor(), []};
- SwInfo when is_list(SwInfo) ->
- SystemVersion = analyze_darwin_sw_system_version(SwInfo),
- KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
- HwInfo = analyze_darwin_hardware_info(),
- ModelName = analyze_darwin_hw_model_name(HwInfo),
- ModelId = analyze_darwin_hw_model_identifier(HwInfo),
- ProcName = analyze_darwin_hw_processor_name(HwInfo),
- ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
- NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
- NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
- Memory = analyze_darwin_hw_memory(HwInfo),
- io:format("Darwin:"
- "~n System Version: ~s"
- "~n Kernel Version: ~s"
- "~n Model: ~s (~s)"
- "~n Processor: ~s (~s, ~s, ~s)"
- "~n Memory: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [SystemVersion, KernelVersion,
- ModelName, ModelId,
- ProcName, ProcSpeed, NumProc, NumCores,
- Memory,
- str_num_schedulers()]),
- CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
- ProcSpeed,
- NumProc,
- NumCores),
- MemFactor = analyze_darwin_memory_to_factor(Memory),
- if (MemFactor =:= 1) ->
- {CPUFactor, []};
- true ->
- {CPUFactor + MemFactor, []}
- end
- end.
+ Label = ts_extra_platform_label(),
+ {BaseFactor, MemFactor} =
+ case analyze_darwin_software_info() of
+ [] ->
+ io:format("Darwin:"
+ "~n Version: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n", [Version, str_num_schedulers(), Label]),
+ {num_schedulers_to_factor(), 1};
+ SwInfo when is_list(SwInfo) ->
+ SystemVersion = analyze_darwin_sw_system_version(SwInfo),
+ KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
+ HwInfo = analyze_darwin_hardware_info(),
+ ModelName = analyze_darwin_hw_model_name(HwInfo),
+ ModelId = analyze_darwin_hw_model_identifier(HwInfo),
+ {Processor, CPUFactor} = analyze_darwin_hw_processor(HwInfo),
+ Memory = analyze_darwin_hw_memory(HwInfo),
+ io:format("Darwin:"
+ "~n System Version: ~s"
+ "~n Kernel Version: ~s"
+ "~n Model: ~s (~s)"
+ "~n Processor: ~s"
+ "~n Memory: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n~n",
+ [SystemVersion, KernelVersion,
+ ModelName, ModelId,
+ Processor,
+ Memory,
+ str_num_schedulers(), Label]),
+ {CPUFactor, analyze_darwin_memory_to_factor(Memory)}
+ end,
+ AddLabelFactor = label2factor(simplify_label(Label)),
+ AddMemFactor = if
+ (MemFactor > 0) ->
+ MemFactor - 1;
+ true ->
+ 0
+ end,
+ TSScaleFactor = ts_scale_factor(),
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n~n",
+ [BaseFactor, AddLabelFactor, AddMemFactor, TSScaleFactor]),
+ {BaseFactor + AddLabelFactor + AddMemFactor + TSScaleFactor,
+ [{label, Label}]}.
analyze_darwin_sw_system_version(SwInfo) ->
proplists:get_value("system version", SwInfo, "-").
@@ -1500,12 +2030,38 @@ analyze_darwin_sw_kernel_version(SwInfo) ->
analyze_darwin_software_info() ->
analyze_darwin_system_profiler("SPSoftwareDataType").
+analyze_darwin_hw_chip(HwInfo) ->
+ proplists:get_value("chip", HwInfo, "-").
+
analyze_darwin_hw_model_name(HwInfo) ->
proplists:get_value("model name", HwInfo, "-").
analyze_darwin_hw_model_identifier(HwInfo) ->
proplists:get_value("model identifier", HwInfo, "-").
+analyze_darwin_hw_processor(HwInfo) ->
+ case analyze_darwin_hw_processor_name(HwInfo) of
+ "-" -> % Maybe Apple Chip
+ case analyze_darwin_hw_chip(HwInfo) of
+ "-" ->
+ "-";
+ Chip ->
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(Chip, NumCores),
+ {f("~s [~s]", [Chip, NumCores]), CPUFactor}
+ end;
+ ProcName ->
+ ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
+ NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
+ ProcSpeed,
+ NumProc,
+ NumCores),
+ {f("~s [~s, ~s, ~s]",
+ [ProcName, ProcSpeed, NumProc, NumCores]), CPUFactor}
+ end.
+
analyze_darwin_hw_processor_name(HwInfo) ->
case proplists:get_value("processor name", HwInfo, "-") of
"-" ->
@@ -1540,17 +2096,25 @@ analyze_darwin_hardware_info() ->
%% "Key: Value1:Value2"
analyze_darwin_system_profiler(DataType) ->
%% First, make sure the program actually exist:
- case os:cmd("which system_profiler") of
+ case string:trim(os:cmd("which system_profiler")) of
[] ->
- [];
- _ ->
- D0 = os:cmd("system_profiler " ++ DataType),
- D1 = string:tokens(D0, [$\n]),
- D2 = [string:trim(S1) || S1 <- D1],
- D3 = [string:tokens(S2, [$:]) || S2 <- D2],
- analyze_darwin_system_profiler2(D3)
+ case string:trim(os:cmd("which /usr/sbin/system_profiler")) of
+ [] ->
+ [];
+ Cmd1 ->
+ analyze_darwin_system_profiler(Cmd1, DataType)
+ end;
+ Cmd2 ->
+ analyze_darwin_system_profiler(Cmd2, DataType)
end.
+analyze_darwin_system_profiler(Cmd, DataType) ->
+ D0 = os:cmd(Cmd ++ " " ++ DataType),
+ D1 = string:tokens(D0, [$\n]),
+ D2 = [string:trim(S1) || S1 <- D1],
+ D3 = [string:tokens(S2, [$:]) || S2 <- D2],
+ analyze_darwin_system_profiler2(D3).
+
analyze_darwin_system_profiler2(L) ->
analyze_darwin_system_profiler2(L, []).
@@ -1600,6 +2164,12 @@ analyze_darwin_memory_to_factor(Mem) ->
end.
+analyze_darwin_cpu_to_factor("Apple" ++ _ = _Chip, _NumCores) ->
+ 1;
+analyze_darwin_cpu_to_factor(_Chip, _NumCores) ->
+ 8.
+
+
%% The speed is a string: "<speed> <unit>"
%% the speed may be a float, which we transforms into an integer of MHz.
%% To calculate a factor based on processor speed, number of procs
@@ -2133,68 +2703,199 @@ executor(Fun, Timeout)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-try_tc(TCName, Name, Verbosity, Pre, Case, Post)
- when is_function(Pre, 0) andalso
+try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
+ Cond = fun() -> ok end,
+ try_tc(TCName, Name, Verbosity, Cond, Pre, Case, Post).
+
+try_tc(TCName, Name, Verbosity, Cond, Pre, Case, Post)
+ when is_function(Cond, 0) andalso
+ is_function(Pre, 0) andalso
is_function(Case, 1) andalso
is_function(Post, 1) ->
- process_flag(trap_exit, true),
- put(verbosity, Verbosity),
- put(sname, Name),
- put(tc, TCName),
- p("try_tc -> starting: try pre"),
- try Pre() of
- State ->
- p("try_tc -> pre done: try test case"),
- try Case(State) of
- Res ->
- p("try_tc -> test case done: try post"),
- _ = executor(fun() -> Post(State) end),
- p("try_tc -> done"),
- Res
+ tc_begin(TCName, Name, Verbosity),
+ try Cond() of
+ ok ->
+ tc_print("starting: try pre"),
+ try Pre() of
+ State ->
+ tc_print("pre done: try test case"),
+ try
+ begin
+ Res = Case(State),
+ sleep(seconds(1)),
+ tc_print("test case done: try post"),
+ _ = executor(fun() ->
+ put(verbosity, Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end("ok"),
+ Res
+ end
+ catch
+ C:{skip, _} = SKIP:_ when (C =:= throw) orelse
+ (C =:= exit) ->
+ tc_print("test case (~w) skip: try post", [C]),
+ _ = executor(fun() ->
+ put(verbosity, Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end( f("skipping(caught,~w,tc)", [C]) ),
+ SKIP;
+ C:E:S ->
+ %% We always check the system events
+ %% before we accept a failure.
+ %% We do *not* run the Post here because it might
+ %% generate sys events itself...
+ p("try_tc -> test case failed: try post"),
+ _ = executor(fun() -> Post(State) end),
+ case megaco_test_global_sys_monitor:events() of
+ [] ->
+ tc_print("test case failed: try post"),
+ _ = executor(fun() ->
+ put(verbosity,
+ Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end( f("failed(caught,~w,tc)", [C]) ),
+ erlang:raise(C, E, S);
+ SysEvs ->
+ tc_print("System Events "
+ "received during tc: "
+ "~n ~p"
+ "~nwhen tc failed:"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [SysEvs, C, E, S]),
+ _ = executor(fun() ->
+ put(verbosity,
+ Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end( f("skipping(catched-sysevs,~w,tc)",
+ [C]) ),
+ SKIP =
+ {skip, "TC failure with system events"},
+ SKIP
+ end
+ end
catch
- throw:{skip, _} = SKIP:_ ->
- p("try_tc -> test case (throw) skip: try post"),
- _ = executor(fun() -> Post(State) end),
- p("try_tc -> test case (throw) skip: done"),
- SKIP;
- exit:{skip, _} = SKIP:_ ->
- p("try_tc -> test case (exit) skip: try post"),
- _ = executor(fun() -> Post(State) end),
- p("try_tc -> test case (exit) skip: done"),
+ C:{skip, _} = SKIP:_ when (C =:= throw) orelse
+ (C =:= exit) ->
+ tc_end( f("skipping(caught,~w,tc-pre)", [C]) ),
SKIP;
C:E:S ->
- p("try_tc -> test case failed: try post"),
- _ = executor(fun() -> Post(State) end),
case megaco_test_global_sys_monitor:events() of
[] ->
- p("try_tc -> test case failed: done"),
- exit({case_catched, C, E, S});
+ tc_print("tc-pre failed: auto-skip"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [C, E, S]),
+ tc_end( f("auto-skip(caught,~w,tc-pre)", [C]) ),
+ SKIP = {skip, f("TC-Pre failure (~w)", [C])},
+ SKIP;
SysEvs ->
- p("try_tc -> test case failed with system event(s): "
- "~n ~p", [SysEvs]),
- {skip, "TC failure with system events"}
+ tc_print("System Events received: "
+ "~n ~p"
+ "~nwhen tc-pre failed:"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [SysEvs, C, E, S], "", ""),
+ tc_end( f("skipping(catched-sysevs,~w,tc-pre)",
+ [C]) ),
+ SKIP = {skip, "TC-Pre failure with system events"},
+ SKIP
end
- end
- catch
- throw:{skip, _} = SKIP:_ ->
- p("try_tc -> pre (throw) skip"),
+ end;
+ {skip, _} = SKIP ->
+ tc_end("skipping(cond)"),
SKIP;
- exit:{skip, _} = SKIP:_ ->
- p("try_tc -> pre (exit) skip"),
+ {error, Reason} ->
+ tc_end("failed(cond)"),
+ exit({tc_cond_failed, Reason})
+ catch
+ C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
+ tc_end( f("skipping(caught,~w,cond)", [C]) ),
SKIP;
C:E:S ->
+ %% We always check the system events before we accept a failure
case megaco_test_global_sys_monitor:events() of
[] ->
- p("try_tc -> pre failed: done"),
- exit({pre_catched, C, E, S});
+ tc_end( f("failed(caught,~w,cond)", [C]) ),
+ erlang:raise(C, E, S);
SysEvs ->
- p("try_tc -> pre failed with system event(s): "
- "~n ~p", [SysEvs]),
- {skip, "TC pre failure with system events"}
+ tc_print("System Events received: "
+ "~n ~p", [SysEvs], "", ""),
+ tc_end( f("skipping(catched-sysevs,~w,cond)", [C]) ),
+ SKIP = {skip, "TC cond failure with system events"},
+ SKIP
end
end.
+tc_set_name(N) when is_atom(N) ->
+ tc_set_name(atom_to_list(N));
+tc_set_name(N) when is_list(N) ->
+ put(tc_name, N).
+
+tc_get_name() ->
+ get(tc_name).
+
+tc_begin(TC, Name, Verbosity) ->
+ OldVal = process_flag(trap_exit, true),
+ put(old_trap_exit, OldVal),
+ tc_set_name(TC),
+ put(sname, Name),
+ put(verbosity, Verbosity),
+ tc_print("begin ***",
+ "~n----------------------------------------------------~n", "").
+
+tc_end(Result) when is_list(Result) ->
+ OldVal = erase(old_trap_exit),
+ process_flag(trap_exit, OldVal),
+ tc_print("done: ~s", [Result],
+ "", "----------------------------------------------------~n~n"),
+ ok.
+
+tc_print(F) ->
+ tc_print(F, [], "", "").
+
+tc_print(F, A) ->
+ tc_print(F, A, "", "").
+
+tc_print(F, Before, After) ->
+ tc_print(F, [], Before, After).
+
+tc_print(F, A, Before, After) ->
+ Name = tc_which_name(),
+ FStr = f("*** [~s][~s][~p] " ++ F ++ "~n",
+ [formated_timestamp(), Name, self() | A]),
+ io:format(user, Before ++ FStr ++ After, []),
+ io:format(standard_io, Before ++ FStr ++ After, []).
+
+tc_which_name() ->
+ case tc_get_name() of
+ undefined ->
+ case get(sname) of
+ undefined ->
+ "";
+ SName when is_list(SName) ->
+ SName
+ end;
+ Name when is_list(Name) ->
+ Name
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2234,20 +2935,24 @@ lookup_config(Key,Config) ->
[]
end.
-mk_nodes(N) when (N > 0) ->
- mk_nodes(N, []).
-mk_nodes(0, Nodes) ->
+mk_nodes(1 = _N) ->
+ [node()];
+mk_nodes(N) when is_integer(N) andalso (N > 1) ->
+ OwnNode = node(),
+ [Name0, Host] = node_to_name_and_host(OwnNode),
+ Uniq = erlang:unique_integer([positive]),
+ Name =
+ list_to_atom(lists:concat([Name0, "_", integer_to_list(Uniq)])),
+ [OwnNode | mk_nodes(N-1, Name, Host, [])].
+
+mk_nodes(0, _BaseName, _Host, Nodes) ->
Nodes;
-mk_nodes(N, []) ->
- mk_nodes(N - 1, [node()]);
-mk_nodes(N, Nodes) when N > 0 ->
- Head = hd(Nodes),
- [Name, Host] = node_to_name_and_host(Head),
- Nodes ++ [mk_node(I, Name, Host) || I <- lists:seq(1, N)].
-
-mk_node(N, Name, Host) ->
- list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])).
+mk_nodes(N, BaseName, Host, Nodes) ->
+ mk_nodes(N-1, BaseName, Host, [mk_node(N, BaseName, Host)|Nodes]).
+
+mk_node(N, BaseName, Host) ->
+ list_to_atom(lists:concat([BaseName, "_", integer_to_list(N), "@", Host])).
%% Returns [Name, Host]
node_to_name_and_host(Node) ->
@@ -2284,10 +2989,11 @@ start_node(Node, Force, File, Line)
start_node(Node, Force, false, File, Line).
start_node(Node, Force, Retry, File, Line) ->
- case net_adm:ping(Node) of
+ p("start_node -> check if node ~p already running", [Node]),
+ case ping(Node, ?SECS(5)) of
%% Do not require a *new* node
pong when (Force =:= false) ->
- p("node ~p already running", [Node]),
+ p("start_node -> node ~p already running", [Node]),
ok;
%% Do require a *new* node, so kill this one and try again
@@ -2308,26 +3014,40 @@ start_node(Node, Force, Retry, File, Line) ->
% Not (yet) running
pang ->
+ p("start_node -> node ~p not running - create args", [Node]),
[Name, Host] = node_to_name_and_host(Node),
Pa = filename:dirname(code:which(?MODULE)),
- Args = " -pa " ++ Pa ++
+ Args0 = " -pa " ++ Pa ++
" -s " ++ atom_to_list(megaco_test_sys_monitor) ++ " start" ++
" -s global sync",
- p("try start node ~p", [Node]),
- case slave:start_link(Host, Name, Args) of
- {ok, NewNode} when NewNode =:= Node ->
+ Args = string:tokens(Args0, [$\ ]),
+ p("start_node -> try start node ~p", [Node]),
+ PeerOpts = #{name => Name,
+ host => Host,
+ args => Args},
+ case peer:start(PeerOpts) of
+ {ok, _Peer, NewNode} when NewNode =:= Node ->
p("node ~p started - now set path, cwd and sync", [Node]),
- Path = code:get_path(),
+ Path = code:get_path(),
{ok, Cwd} = file:get_cwd(),
- true = rpc:call(Node, code, set_path, [Path]),
- ok = rpc:call(Node, file, set_cwd, [Cwd]),
- true = rpc:call(Node, code, set_path, [Path]),
- {_, []} = rpc:multicall(global, sync, []),
+ true = rpc:call(Node, code, set_path, [Path]),
+ ok = rpc:call(Node, file, set_cwd, [Cwd]),
+ true = rpc:call(Node, code, set_path, [Path]),
+ {_, []} = rpc:multicall(global, sync, []),
ok;
+ {ok, _Peer, NewNode} ->
+ e("wrong node started: "
+ "~n Expected: ~p"
+ "~n Got: ~p", [Node, NewNode]),
+ stop_node(NewNode),
+ fatal_skip({invalid_node_start, NewNode, Node}, File, Line);
Other ->
e("failed starting node ~p: ~p", [Node, Other]),
- fatal_skip({cannot_start_node, Node, Other}, File, Line)
- end
+ fatal_skip({cannot_start_node, Node, Other}, File, Line)
+ end;
+
+ timeout ->
+ fatal_skip({ping_timeout, Node}, File, Line)
end.
@@ -2379,12 +3099,24 @@ stop_node(Node) ->
end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+timetrap_scale_factor() ->
+ case (catch test_server:timetrap_scale_factor()) of
+ {'EXIT', _} ->
+ 1;
+ N ->
+ N
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f(F, A) ->
lists:flatten(io_lib:format(F, A)).
+e(F) ->
+ e(F, []).
e(F, A) ->
print("ERROR", F, A).
@@ -2470,3 +3202,49 @@ connect(Config, Ref, Opts)
InetBackendOpts = inet_backend_opts(Config),
megaco_tcp:connect(Ref, InetBackendOpts ++ Opts).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% The point of this cludge is to make it possible to specify a
+%% timeout for the ping, since it can actually hang.
+ping(Node) ->
+ ping(Node, infinity).
+
+ping(Node, Timeout)
+ when is_atom(Node) andalso
+ ((is_integer(Timeout) andalso (Timeout > 0)) orelse
+ (Timeout =:= infinity)) ->
+ {Pid, Mon} = erlang:spawn_monitor(fun() -> exit(net_adm:ping(Node)) end),
+ receive
+ {'DOWN', Mon, process, Pid, Info} when (Info =:= pong) orelse
+ (Info =:= pang) ->
+ Info;
+ {'DOWN', Mon, process, Pid, Info} ->
+ e("unexpected ping result: "
+ "~n ~p", [Info]),
+ exit({unexpected_ping_result, Info});
+ {'EXIT', TCPid, {timetrap_timeout, TCTimeout, TCSTack}} ->
+ p("received timetrap timeout (~w ms) from ~p => Kill ping process"
+ "~n TC Stack: ~p", [TCTimeout, TCPid, TCSTack]),
+ kill_and_wait(Pid, Mon, "ping"),
+ timeout
+ after Timeout ->
+ e("unexpected ping timeout"),
+ kill_and_wait(Pid, Mon, "ping"),
+ timeout
+ end.
+
+
+kill_and_wait(Pid, MRef, PStr) ->
+ exit(Pid, kill),
+ %% We do this in case we get some info about 'where'
+ %% the process is hanging...
+ receive
+ {'DOWN', MRef, process, Pid, Info} ->
+ p("~s process terminated (forced) with"
+ "~n ~p", [PStr, Info]),
+ ok
+ after 100 -> % Give it a second...
+ ok
+ end.
+