diff options
author | Björn Gustavsson <[email protected]> | 2010-01-19 11:34:56 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2010-01-19 13:01:29 +0100 |
commit | 74d7b1b942c6f1d984e263f6675a9423197a3215 (patch) | |
tree | 4644ffbb46b3f166507ffa8739e5ecbfccd4aba7 /lib/tools/test/emem_SUITE.erl | |
parent | 81f4b1f7f453e1242d7f81ef2347230a9ff3fb0f (diff) | |
download | otp-74d7b1b942c6f1d984e263f6675a9423197a3215.tar.gz otp-74d7b1b942c6f1d984e263f6675a9423197a3215.tar.bz2 otp-74d7b1b942c6f1d984e263f6675a9423197a3215.zip |
Add test suite for the tools application
Diffstat (limited to 'lib/tools/test/emem_SUITE.erl')
-rw-r--r-- | lib/tools/test/emem_SUITE.erl | 713 |
1 files changed, 713 insertions, 0 deletions
diff --git a/lib/tools/test/emem_SUITE.erl b/lib/tools/test/emem_SUITE.erl new file mode 100644 index 0000000000..430fa86c6c --- /dev/null +++ b/lib/tools/test/emem_SUITE.erl @@ -0,0 +1,713 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(emem_SUITE). + +%%-define(line_trace, 1). + +-export([init_per_suite/1, end_per_suite/1, + receive_and_save_trace/2, send_trace/2]). + + +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). + +-export([live_node/1, + 'sparc_sunos5.8_32b_emt2.0'/1, + 'pc_win2000_32b_emt2.0'/1, + 'pc.smp_linux2.2.19pre17_32b_emt2.0'/1, + 'powerpc_darwin7.7.0_32b_emt2.0'/1, + 'alpha_osf1v5.1_64b_emt2.0'/1, + 'sparc_sunos5.8_64b_emt2.0'/1, + 'sparc_sunos5.8_32b_emt1.0'/1, + 'pc_win2000_32b_emt1.0'/1, + 'powerpc_darwin7.7.0_32b_emt1.0'/1, + 'alpha_osf1v5.1_64b_emt1.0'/1, + 'sparc_sunos5.8_64b_emt1.0'/1]). + +-include_lib("kernel/include/file.hrl"). + +-include("test_server.hrl"). + +-define(DEFAULT_TIMEOUT, ?t:minutes(5)). + +-define(EMEM_64_32_COMMENT, + "64 bit trace; this build of emem can only handle 32 bit traces"). + +-record(emem_res, {nodename, + hostname, + pid, + start_time, + trace_version, + max_word_size, + word_size, + last_values, + maximum, + exit_code}). + +%% +%% +%% Exported suite functions +%% +%% + +all(doc) -> []; +all(suite) -> + case is_debug_compiled() of + true -> {skipped, "Not run when debug compiled"}; + false -> test_cases() + end. + +test_cases() -> + [live_node, + 'sparc_sunos5.8_32b_emt2.0', + 'pc_win2000_32b_emt2.0', + 'pc.smp_linux2.2.19pre17_32b_emt2.0', + 'powerpc_darwin7.7.0_32b_emt2.0', + 'alpha_osf1v5.1_64b_emt2.0', + 'sparc_sunos5.8_64b_emt2.0', + 'sparc_sunos5.8_32b_emt1.0', + 'pc_win2000_32b_emt1.0', + 'powerpc_darwin7.7.0_32b_emt1.0', + 'alpha_osf1v5.1_64b_emt1.0', + 'sparc_sunos5.8_64b_emt1.0']. + +init_per_testcase(Case, Config) when is_list(Config) -> + case maybe_skip(Config) of + {skip, _}=Skip -> Skip; + ok -> + Dog = ?t:timetrap(?DEFAULT_TIMEOUT), + + %% Until emem is completely stable we run these tests in a working + %% directory with an ignore_core_files file which will make the + %% search for core files ignore cores generated by this suite. + ignore_cores:setup(?MODULE, + Case, + [{watchdog, Dog}, {testcase, Case} | Config]) + end. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + ignore_cores:restore(Config), + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +maybe_skip(Config) -> + DataDir = ?config(data_dir, Config), + case filelib:is_dir(DataDir) of + false -> + {skip, "No data directory"}; + true -> + case ?config(emem, Config) of + undefined -> + {skip, "emem not found"}; + _ -> + ok + end + end. + +init_per_suite(Config) when is_list(Config) -> + BinDir = filename:join([code:lib_dir(tools), "bin"]), + Target = erlang:system_info(system_architecture), + Res = (catch begin + case check_dir(filename:join([BinDir, Target])) of + not_found -> ok; + TDir -> + check_emem(TDir, purecov), + check_emem(TDir, purify), + check_emem(TDir, debug), + check_emem(TDir, opt) + end, + check_emem(BinDir, opt), + "" + end), + Res ++ ignore_cores:init(Config). + +end_per_suite(Config) when is_list(Config) -> + Config1 = lists:keydelete(emem, 1, Config), + Config2 = lists:keydelete(emem_comment, 1, Config1), + ignore_cores:fini(Config2). + +%% +%% +%% Test cases +%% +%% + +live_node(doc) -> []; +live_node(suite) -> []; +live_node(Config) when is_list(Config) -> + ?line {ok, EmuFlag, Port} = start_emem(Config), + ?line Nodename = mk_nodename(Config), + ?line {ok, Node} = start_node(Nodename, EmuFlag), + ?line NP = spawn(Node, + fun () -> + receive go -> ok end, + I = spawn(fun () -> ignorer end), + GC = fun () -> + GCP = fun (P) -> + garbage_collect(P) + end, + lists:foreach(GCP, processes()) + end, + Seq = fun () -> I ! lists:seq(1, 1000000) end, + spawn_link(Seq), + B1 = <<0:10000000>>, + spawn_link(Seq), + B2 = <<0:10000000>>, + spawn_link(Seq), + B3 = <<0:10000000>>, + I ! {B1, B2, B3}, + GC(), + GC(), + GC() + end), + ?line MRef = erlang:monitor(process, NP), + NP ! go, + ?line receive + {'DOWN', MRef, process, NP, Reason} -> + ?line spawn(Node, fun () -> halt(17) end), + ?line normal = Reason + end, + ?line Res = get_emem_result(Port), + ?line {ok, Hostname} = inet:gethostname(), + ?line ShortHostname = short_hostname(Hostname), + ?line {true, _} = has_prefix(Nodename, Res#emem_res.nodename), + ?line ShortHostname = short_hostname(Res#emem_res.hostname), + ?line Bits = case erlang:system_info(wordsize) of + 4 -> ?line "32 bits"; + 8 -> ?line "64 bits" + end, + ?line Bits = Res#emem_res.word_size, + ?line "17" = Res#emem_res.exit_code, + ?line emem_comment(Config). + +'sparc_sunos5.8_32b_emt2.0'(doc) -> []; +'sparc_sunos5.8_32b_emt2.0'(suite) -> []; +'sparc_sunos5.8_32b_emt2.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "test_server" = Res#emem_res.nodename, + ?line "gorbag" = Res#emem_res.hostname, + ?line "17074" = Res#emem_res.pid, + ?line "2005-01-14 17:28:37.881980" = Res#emem_res.start_time, + ?line "2.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["15", + "2665739", "8992", "548986", "16131", "539994", + "4334192", "1", "99", "15", "98", + "0", "0", "49", "0", "49"] = Res#emem_res.last_values, + ?line ["5972061", "9662", + "7987824", "5", + "2375680", "3"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + +'pc_win2000_32b_emt2.0'(doc) -> []; +'pc_win2000_32b_emt2.0'(suite) -> []; +'pc_win2000_32b_emt2.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "test_server" = Res#emem_res.nodename, + ?line "E-788FCF5191B54" = Res#emem_res.hostname, + ?line "504" = Res#emem_res.pid, + ?line "2005-01-24 17:27:28.224000" = Res#emem_res.start_time, + ?line "2.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["11", + "2932575", "8615", "641087", "68924", "632472"] + = Res#emem_res.last_values, + ?line ["5434206", "9285"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + +'pc.smp_linux2.2.19pre17_32b_emt2.0'(doc) -> []; +'pc.smp_linux2.2.19pre17_32b_emt2.0'(suite) -> []; +'pc.smp_linux2.2.19pre17_32b_emt2.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "test_server" = Res#emem_res.nodename, + ?line "four-roses" = Res#emem_res.hostname, + ?line "20689" = Res#emem_res.pid, + ?line "2005-01-20 13:11:26.143077" = Res#emem_res.start_time, + ?line "2.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["49", + "2901817", "9011", "521610", "10875", "512599", + "5392096", "2", "120", "10", "118", + "0", "0", "59", "0", "59"] = Res#emem_res.last_values, + ?line ["6182918", "9681", + "9062112", "6", + "2322432", "3"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + + +'powerpc_darwin7.7.0_32b_emt2.0'(doc) -> []; +'powerpc_darwin7.7.0_32b_emt2.0'(suite) -> []; +'powerpc_darwin7.7.0_32b_emt2.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "test_server" = Res#emem_res.nodename, + ?line "grima" = Res#emem_res.hostname, + ?line "13021" = Res#emem_res.pid, + ?line "2005-01-20 15:08:17.568668" = Res#emem_res.start_time, + ?line "2.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["9", + "2784323", "8641", "531105", "15893", "522464"] + = Res#emem_res.last_values, + ?line ["6150376", "9311"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + +'alpha_osf1v5.1_64b_emt2.0'(doc) -> []; +'alpha_osf1v5.1_64b_emt2.0'(suite) -> []; +'alpha_osf1v5.1_64b_emt2.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "test_server" = Res#emem_res.nodename, + ?line "thorin" = Res#emem_res.hostname, + ?line "224630" = Res#emem_res.pid, + ?line "2005-01-20 22:38:01.299632" = Res#emem_res.start_time, + ?line "2.0" = Res#emem_res.trace_version, + ?line "64 bits" = Res#emem_res.word_size, + ?line case Res#emem_res.max_word_size of + "32 bits" -> + ?line emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ?line ["22", + "6591992", "8625", "516785", "14805", "508160", + "11429184", "5", "127", "254", "122", + "0", "0", "61", "0", "61"] = Res#emem_res.last_values, + ?line ["7041775", "9295", + "11593024", "7", + "2097152", "3"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config) + end. + +'sparc_sunos5.8_64b_emt2.0'(doc) -> []; +'sparc_sunos5.8_64b_emt2.0'(suite) -> []; +'sparc_sunos5.8_64b_emt2.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "test_server" = Res#emem_res.nodename, + ?line "gorbag" = Res#emem_res.hostname, + ?line "10907" = Res#emem_res.pid, + ?line "2005-01-20 13:48:34.677068" = Res#emem_res.start_time, + ?line "2.0" = Res#emem_res.trace_version, + ?line "64 bits" = Res#emem_res.word_size, + ?line case Res#emem_res.max_word_size of + "32 bits" -> + ?line emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ?line ["16", + "5032887", "8657", "530635", "14316", "521978", + "8627140", "5", "139", "19", "134", + "0", "0", "67", "0", "67"] = Res#emem_res.last_values, + ?line ["11695070", "9324", + "16360388", "10", + "4136960", "3"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config) + end. + +'sparc_sunos5.8_32b_emt1.0'(doc) -> []; +'sparc_sunos5.8_32b_emt1.0'(suite) -> []; +'sparc_sunos5.8_32b_emt1.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "" = Res#emem_res.nodename, + ?line "" = Res#emem_res.hostname, + ?line "" = Res#emem_res.pid, + ?line "" = Res#emem_res.start_time, + ?line "1.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["11", + "2558261", "8643", "560610", "15325", "551967"] + = Res#emem_res.last_values, + ?line ["2791121", "9317"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + +'pc_win2000_32b_emt1.0'(doc) -> []; +'pc_win2000_32b_emt1.0'(suite) -> []; +'pc_win2000_32b_emt1.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "" = Res#emem_res.nodename, + ?line "" = Res#emem_res.hostname, + ?line "" = Res#emem_res.pid, + ?line "" = Res#emem_res.start_time, + ?line "1.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["6", + "2965248", "8614", "640897", "68903", "632283"] + = Res#emem_res.last_values, + ?line ["3147090", "9283"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + + +'powerpc_darwin7.7.0_32b_emt1.0'(doc) -> []; +'powerpc_darwin7.7.0_32b_emt1.0'(suite) -> []; +'powerpc_darwin7.7.0_32b_emt1.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "" = Res#emem_res.nodename, + ?line "" = Res#emem_res.hostname, + ?line "" = Res#emem_res.pid, + ?line "" = Res#emem_res.start_time, + ?line "1.0" = Res#emem_res.trace_version, + ?line "32 bits" = Res#emem_res.word_size, + ?line ["8", + "2852991", "8608", "529662", "15875", "521054"] + = Res#emem_res.last_values, + ?line ["3173335", "9278"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config). + +'alpha_osf1v5.1_64b_emt1.0'(doc) -> []; +'alpha_osf1v5.1_64b_emt1.0'(suite) -> []; +'alpha_osf1v5.1_64b_emt1.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "" = Res#emem_res.nodename, + ?line "" = Res#emem_res.hostname, + ?line "" = Res#emem_res.pid, + ?line "" = Res#emem_res.start_time, + ?line "1.0" = Res#emem_res.trace_version, + ?line "64 bits" = Res#emem_res.word_size, + ?line case Res#emem_res.max_word_size of + "32 bits" -> + ?line emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ?line ["22", + "6820094", "8612", "515518", "14812", "506906"] + = Res#emem_res.last_values, + ?line ["7292413", "9282"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config) + end. + +'sparc_sunos5.8_64b_emt1.0'(doc) -> []; +'sparc_sunos5.8_64b_emt1.0'(suite) -> []; +'sparc_sunos5.8_64b_emt1.0'(Config) when is_list(Config) -> + ?line Res = run_emem_on_casefile(Config), + ?line "" = Res#emem_res.nodename, + ?line "" = Res#emem_res.hostname, + ?line "" = Res#emem_res.pid, + ?line "" = Res#emem_res.start_time, + ?line "1.0" = Res#emem_res.trace_version, + ?line "64 bits" = Res#emem_res.word_size, + ?line case Res#emem_res.max_word_size of + "32 bits" -> + ?line emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ?line ["15", + "4965746", "8234", "543940", "14443", "535706"] + = Res#emem_res.last_values, + ?line ["11697645", "8908"] = Res#emem_res.maximum, + ?line "0" = Res#emem_res.exit_code, + ?line emem_comment(Config) + end. + +%% +%% +%% Auxiliary functions +%% +%% + +receive_and_save_trace(PortNumber, FileName) when is_integer(PortNumber), + is_list(FileName) -> + {ok, F} = file:open(FileName, [write, compressed]), + {ok, LS} = gen_tcp:listen(PortNumber, [inet, {reuseaddr,true}, binary]), + {ok, S} = gen_tcp:accept(LS), + gen_tcp:close(LS), + receive_loop(S,F). + +receive_loop(Socket, File) -> + receive + {tcp, Socket, Data} -> + ok = file:write(File, Data), + receive_loop(Socket, File); + {tcp_closed, Socket} -> + file:close(File), + ok; + {tcp_error, Socket, Reason} -> + file:close(File), + {error, Reason} + end. + +send_trace({Host, PortNumber}, FileName) when is_list(Host), + is_integer(PortNumber), + is_list(FileName) -> + ?line {ok, F} = file:open(FileName, [read, compressed]), + ?line {ok, S} = gen_tcp:connect(Host, PortNumber, [inet,{packet, 0}]), + ?line send_loop(S, F); +send_trace(EmuFlag, FileName) when is_list(EmuFlag), + is_list(FileName) -> + ?line ["+Mit", IpAddrStr, PortNoStr] = string:tokens(EmuFlag, " :"), + ?line send_trace({IpAddrStr, list_to_integer(PortNoStr)}, FileName). + +send_loop(Socket, File) -> + ?line case file:read(File, 128) of + {ok, Data} -> + ?line case gen_tcp:send(Socket, Data) of + ok -> ?line send_loop(Socket, File); + Error -> + ?line gen_tcp:close(Socket), + ?line file:close(File), + Error + end; + eof -> + ?line gen_tcp:close(Socket), + ?line file:close(File), + ?line ok; + Error -> + ?line gen_tcp:close(Socket), + ?line file:close(File), + ?line Error + end. + +check_emem(Dir, Type) when is_atom(Type) -> + ExeSuffix = case ?t:os_type() of + {win32, _} -> ".exe"; + _ -> "" + end, + TypeSuffix = case Type of + opt -> ""; + _ -> "." ++ atom_to_list(Type) + end, + Emem = "emem" ++ TypeSuffix ++ ExeSuffix, + case check_file(filename:join([Dir, Emem])) of + not_found -> ok; + File -> + Comment = case Type of + opt -> ""; + _ -> "[emem " ++ atom_to_list(Type) ++ " compiled]" + end, + throw([{emem, File}, {emem_comment, Comment}]) + end. + +check_dir(DirName) -> + case file:read_file_info(DirName) of + {ok, #file_info {type = directory, access = A}} when A == read; + A == read_write -> + DirName; + _ -> + not_found + end. + +check_file(FileName) -> + case file:read_file_info(FileName) of + {ok, #file_info {type = regular, access = A}} when A == read; + A == read_write -> + ?line FileName; + _ -> + ?line not_found + end. + +emem_comment(Config) when is_list(Config) -> + emem_comment(Config, ""). + +emem_comment(Config, ExtraComment) + when is_list(Config), is_list(ExtraComment) -> + case {?config(emem_comment, Config), ExtraComment} of + {"", ""} -> ?line ok; + {"", XC} -> ?line {comment, XC}; + {EmemC, ""} -> ?line {comment, EmemC}; + {EmemC, XC} -> ?line {comment, EmemC ++ " " ++ XC} + end. + +run_emem_on_casefile(Config) -> + CaseName = atom_to_list(?config(testcase, Config)), + ?line File = filename:join([?config(data_dir, Config), CaseName ++ ".gz"]), + ?line case check_file(File) of + not_found -> + ?line ?t:fail({error, {filenotfound, File}}); + _ -> + ?line ok + end, + ?line {ok, EmuFlag, Port} = start_emem(Config), + ?line Parent = self(), + ?line Ref = make_ref(), + ?line spawn_link(fun () -> + SRes = send_trace(EmuFlag, File), + Parent ! {Ref, SRes} + end), + ?line Res = get_emem_result(Port), + ?line receive + {Ref, ok} -> + ?line ok; + {Ref, SendError} -> + ?line ?t:format("Send result: ~p~n", [SendError]) + end, + ?line Res. + +get_emem_result(Port) -> + ?line {Res, LV} = get_emem_result(Port, {#emem_res{}, []}), + ?line Res#emem_res{last_values = string:tokens(LV, " ")}. + +get_emem_result(Port, {_EmemRes, _LastValues} = Res) -> + ?line case get_emem_line(Port) of + eof -> + ?line Res; + Line -> + ?line get_emem_result(Port, parse_emem_line(Line, Res)) + end. + +parse_emem_main_header_footer_line(Line, {ER, LV} = Res) -> + + %% Header + ?line case has_prefix("> Nodename:", Line) of + {true, NN} -> + ?line throw({ER#emem_res{nodename = strip(NN)}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Hostname:", Line) of + {true, HN} -> + ?line throw({ER#emem_res{hostname = strip(HN)}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Pid:", Line) of + {true, P} -> + ?line throw({ER#emem_res{pid = strip(P)}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Start time (UTC):", Line) of + {true, ST} -> + ?line throw({ER#emem_res{start_time = strip(ST)}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Actual trace version:", Line) of + {true, TV} -> + ?line throw({ER#emem_res{trace_version = strip(TV)}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Maximum trace word size:", Line) of + {true, MWS} -> + ?line throw({ER#emem_res{max_word_size = strip(MWS)}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Actual trace word size:", Line) of + {true, WS} -> + ?line throw({ER#emem_res{word_size = strip(WS)}, LV}); + false -> ?line ok + end, + + %% Footer + ?line case has_prefix("> Maximum:", Line) of + {true, M} -> + ?line throw({ER#emem_res{maximum = string:tokens(M," ")}, LV}); + false -> ?line ok + end, + ?line case has_prefix("> Emulator exited with code:", Line) of + {true, EC} -> + ?line throw({ER#emem_res{exit_code = strip(EC)}, LV}); + false -> ?line ok + end, + ?line Res. + +parse_emem_header_line(_Line, {_ER, _LV} = Res) -> + ?line Res. + +parse_emem_value_line(Line, {EmemRes, _OldLastValues}) -> + ?line {EmemRes, Line}. + +parse_emem_line("", Res) -> + ?line Res; +parse_emem_line(Line, Res) -> + ?line [Prefix | _] = Line, + case Prefix of + $> -> ?line catch parse_emem_main_header_footer_line(Line, Res); + $| -> ?line catch parse_emem_header_line(Line, Res); + _ -> ?line catch parse_emem_value_line(Line, Res) + end. + +start_emem(Config) when is_list(Config) -> + ?line Emem = ?config(emem, Config), + ?line Cd = case ignore_cores:dir(Config) of + false -> []; + Dir -> [{cd, Dir}] + end, + ?line case open_port({spawn, Emem ++ " -t -n -o -i 1"}, + Cd ++ [{line, 1024}, eof]) of + Port when is_port(Port) -> ?line {ok, read_emu_flag(Port), Port}; + Error -> ?line ?t:fail(Error) + end. + +read_emu_flag(Port) -> + ?line Line = case get_emem_line(Port) of + eof -> ?line ?t:fail(unexpected_end_of_file); + L -> ?line L + end, + ?line case has_prefix("> Emulator command line argument:", Line) of + {true, EmuFlag} -> EmuFlag; + false -> ?line read_emu_flag(Port) + end. + +get_emem_line(Port, Acc) -> + ?line receive + {Port, {data, {eol, Data}}} -> + ?line Res = case Acc of + [] -> ?line Data; + _ -> ?line lists:flatten([Acc|Data]) + end, + ?line ?t:format("~s", [Res]), + ?line Res; + {Port, {data, {noeol, Data}}} -> + ?line get_emem_line(Port, [Acc|Data]); + {Port, eof} -> + ?line port_close(Port), + ?line eof + end. + +get_emem_line(Port) -> + ?line get_emem_line(Port, []). + +short_hostname([]) -> + []; +short_hostname([$.|_]) -> + []; +short_hostname([C|Cs]) -> + [C | short_hostname(Cs)]. + +has_prefix([], List) when is_list(List) -> + {true, List}; +has_prefix([P|Xs], [P|Ys]) -> + has_prefix(Xs, Ys); +has_prefix(_, _) -> + false. + +strip(Str) -> string:strip(Str). + +mk_nodename(Config) -> + {A, B, C} = now(), + atom_to_list(?MODULE) + ++ "-" ++ atom_to_list(?config(testcase, Config)) + ++ "-" ++ integer_to_list(A*1000000000000 + B*1000000 + C). + +start_node(Name, Args) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line ?t:start_node(Name, peer, [{args, Args ++ " -pa " ++ Pa}]). + +% stop_node(Node) -> +% ?t:stop_node(Node). + +is_debug_compiled() -> + is_debug_compiled(erlang:system_info(system_version)). + +is_debug_compiled([$d,$e,$b,$u,$g | _]) -> + true; +is_debug_compiled([ _, _, _, _]) -> + false; +is_debug_compiled([]) -> + false; +is_debug_compiled([_|Rest]) -> + is_debug_compiled(Rest). |