1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2005-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: -module(emem_SUITE). 20: 21: %%-define(line_trace, 1). 22: 23: -export([init_per_suite/1, end_per_suite/1, 24: receive_and_save_trace/2, send_trace/2]). 25: 26: 27: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 28: init_per_testcase/2, end_per_testcase/2]). 29: 30: -export([live_node/1, 31: 'sparc_sunos5.8_32b_emt2.0'/1, 32: 'pc_win2000_32b_emt2.0'/1, 33: 'pc.smp_linux2.2.19pre17_32b_emt2.0'/1, 34: 'powerpc_darwin7.7.0_32b_emt2.0'/1, 35: 'alpha_osf1v5.1_64b_emt2.0'/1, 36: 'sparc_sunos5.8_64b_emt2.0'/1, 37: 'sparc_sunos5.8_32b_emt1.0'/1, 38: 'pc_win2000_32b_emt1.0'/1, 39: 'powerpc_darwin7.7.0_32b_emt1.0'/1, 40: 'alpha_osf1v5.1_64b_emt1.0'/1, 41: 'sparc_sunos5.8_64b_emt1.0'/1]). 42: 43: -include_lib("kernel/include/file.hrl"). 44: 45: -include_lib("test_server/include/test_server.hrl"). 46: 47: -define(DEFAULT_TIMEOUT, ?t:minutes(5)). 48: 49: -define(EMEM_64_32_COMMENT, 50: "64 bit trace; this build of emem can only handle 32 bit traces"). 51: 52: -record(emem_res, {nodename, 53: hostname, 54: pid, 55: start_time, 56: trace_version, 57: max_word_size, 58: word_size, 59: last_values, 60: maximum, 61: exit_code}). 62: 63: %% 64: %% 65: %% Exported suite functions 66: %% 67: %% 68: 69: suite() -> [{ct_hooks,[ts_install_cth]}]. 70: 71: all() -> 72: case is_debug_compiled() of 73: true -> {skip, "Not run when debug compiled"}; 74: false -> test_cases() 75: end. 76: 77: groups() -> 78: []. 79: 80: init_per_group(_GroupName, Config) -> 81: Config. 82: 83: end_per_group(_GroupName, Config) -> 84: Config. 85: 86: 87: test_cases() -> 88: [live_node, 'sparc_sunos5.8_32b_emt2.0', 89: 'pc_win2000_32b_emt2.0', 90: 'pc.smp_linux2.2.19pre17_32b_emt2.0', 91: 'powerpc_darwin7.7.0_32b_emt2.0', 92: 'alpha_osf1v5.1_64b_emt2.0', 93: 'sparc_sunos5.8_64b_emt2.0', 94: 'sparc_sunos5.8_32b_emt1.0', 'pc_win2000_32b_emt1.0', 95: 'powerpc_darwin7.7.0_32b_emt1.0', 96: 'alpha_osf1v5.1_64b_emt1.0', 97: 'sparc_sunos5.8_64b_emt1.0']. 98: 99: init_per_testcase(Case, Config) when is_list(Config) -> 100: case maybe_skip(Config) of 101: {skip, _}=Skip -> Skip; 102: ok -> 103: Dog = ?t:timetrap(?DEFAULT_TIMEOUT), 104: 105: %% Until emem is completely stable we run these tests in a working 106: %% directory with an ignore_core_files file which will make the 107: %% search for core files ignore cores generated by this suite. 108: ignore_cores:setup(?MODULE, 109: Case, 110: [{watchdog, Dog}, {testcase, Case} | Config]) 111: end. 112: 113: end_per_testcase(_Case, Config) when is_list(Config) -> 114: ignore_cores:restore(Config), 115: Dog = ?config(watchdog, Config), 116: ?t:timetrap_cancel(Dog), 117: ok. 118: 119: maybe_skip(Config) -> 120: DataDir = ?config(data_dir, Config), 121: case filelib:is_dir(DataDir) of 122: false -> 123: {skip, "No data directory"}; 124: true -> 125: case ?config(emem, Config) of 126: undefined -> 127: {skip, "emem not found"}; 128: _ -> 129: ok 130: end 131: end. 132: 133: init_per_suite(Config) when is_list(Config) -> 134: BinDir = filename:join([code:lib_dir(tools), "bin"]), 135: Target = erlang:system_info(system_architecture), 136: Res = (catch begin 137: case check_dir(filename:join([BinDir, Target])) of 138: not_found -> ok; 139: TDir -> 140: check_emem(TDir, purecov), 141: check_emem(TDir, purify), 142: check_emem(TDir, debug), 143: check_emem(TDir, opt) 144: end, 145: check_emem(BinDir, opt), 146: "" 147: end), 148: Res ++ ignore_cores:init(Config). 149: 150: end_per_suite(Config) when is_list(Config) -> 151: Config1 = lists:keydelete(emem, 1, Config), 152: Config2 = lists:keydelete(emem_comment, 1, Config1), 153: ignore_cores:fini(Config2). 154: 155: %% 156: %% 157: %% Test cases 158: %% 159: %% 160: 161: live_node(doc) -> []; 162: live_node(suite) -> []; 163: live_node(Config) when is_list(Config) -> 164: ?line {ok, EmuFlag, Port} = start_emem(Config), 165: ?line Nodename = mk_nodename(Config), 166: ?line {ok, Node} = start_node(Nodename, EmuFlag), 167: ?line NP = spawn(Node, 168: fun () -> 169: receive go -> ok end, 170: I = spawn(fun () -> ignorer end), 171: GC = fun () -> 172: GCP = fun (P) -> 173: garbage_collect(P) 174: end, 175: lists:foreach(GCP, processes()) 176: end, 177: Seq = fun () -> I ! lists:seq(1, 1000000) end, 178: spawn_link(Seq), 179: B1 = <<0:10000000>>, 180: spawn_link(Seq), 181: B2 = <<0:10000000>>, 182: spawn_link(Seq), 183: B3 = <<0:10000000>>, 184: I ! {B1, B2, B3}, 185: GC(), 186: GC(), 187: GC() 188: end), 189: ?line MRef = erlang:monitor(process, NP), 190: NP ! go, 191: ?line receive 192: {'DOWN', MRef, process, NP, Reason} -> 193: ?line spawn(Node, fun () -> halt(17) end), 194: ?line normal = Reason 195: end, 196: ?line Res = get_emem_result(Port), 197: ?line {ok, Hostname} = inet:gethostname(), 198: ?line ShortHostname = short_hostname(Hostname), 199: ?line {true, _} = has_prefix(Nodename, Res#emem_res.nodename), 200: ?line ShortHostname = short_hostname(Res#emem_res.hostname), 201: ?line Bits = case erlang:system_info(wordsize) of 202: 4 -> ?line "32 bits"; 203: 8 -> ?line "64 bits" 204: end, 205: ?line Bits = Res#emem_res.word_size, 206: ?line "17" = Res#emem_res.exit_code, 207: ?line emem_comment(Config). 208: 209: 'sparc_sunos5.8_32b_emt2.0'(doc) -> []; 210: 'sparc_sunos5.8_32b_emt2.0'(suite) -> []; 211: 'sparc_sunos5.8_32b_emt2.0'(Config) when is_list(Config) -> 212: ?line Res = run_emem_on_casefile(Config), 213: ?line "test_server" = Res#emem_res.nodename, 214: ?line "gorbag" = Res#emem_res.hostname, 215: ?line "17074" = Res#emem_res.pid, 216: ?line "2005-01-14 17:28:37.881980" = Res#emem_res.start_time, 217: ?line "2.0" = Res#emem_res.trace_version, 218: ?line "32 bits" = Res#emem_res.word_size, 219: ?line ["15", 220: "2665739", "8992", "548986", "16131", "539994", 221: "4334192", "1", "99", "15", "98", 222: "0", "0", "49", "0", "49"] = Res#emem_res.last_values, 223: ?line ["5972061", "9662", 224: "7987824", "5", 225: "2375680", "3"] = Res#emem_res.maximum, 226: ?line "0" = Res#emem_res.exit_code, 227: ?line emem_comment(Config). 228: 229: 'pc_win2000_32b_emt2.0'(doc) -> []; 230: 'pc_win2000_32b_emt2.0'(suite) -> []; 231: 'pc_win2000_32b_emt2.0'(Config) when is_list(Config) -> 232: ?line Res = run_emem_on_casefile(Config), 233: ?line "test_server" = Res#emem_res.nodename, 234: ?line "E-788FCF5191B54" = Res#emem_res.hostname, 235: ?line "504" = Res#emem_res.pid, 236: ?line "2005-01-24 17:27:28.224000" = Res#emem_res.start_time, 237: ?line "2.0" = Res#emem_res.trace_version, 238: ?line "32 bits" = Res#emem_res.word_size, 239: ?line ["11", 240: "2932575", "8615", "641087", "68924", "632472"] 241: = Res#emem_res.last_values, 242: ?line ["5434206", "9285"] = Res#emem_res.maximum, 243: ?line "0" = Res#emem_res.exit_code, 244: ?line emem_comment(Config). 245: 246: 'pc.smp_linux2.2.19pre17_32b_emt2.0'(doc) -> []; 247: 'pc.smp_linux2.2.19pre17_32b_emt2.0'(suite) -> []; 248: 'pc.smp_linux2.2.19pre17_32b_emt2.0'(Config) when is_list(Config) -> 249: ?line Res = run_emem_on_casefile(Config), 250: ?line "test_server" = Res#emem_res.nodename, 251: ?line "four-roses" = Res#emem_res.hostname, 252: ?line "20689" = Res#emem_res.pid, 253: ?line "2005-01-20 13:11:26.143077" = Res#emem_res.start_time, 254: ?line "2.0" = Res#emem_res.trace_version, 255: ?line "32 bits" = Res#emem_res.word_size, 256: ?line ["49", 257: "2901817", "9011", "521610", "10875", "512599", 258: "5392096", "2", "120", "10", "118", 259: "0", "0", "59", "0", "59"] = Res#emem_res.last_values, 260: ?line ["6182918", "9681", 261: "9062112", "6", 262: "2322432", "3"] = Res#emem_res.maximum, 263: ?line "0" = Res#emem_res.exit_code, 264: ?line emem_comment(Config). 265: 266: 267: 'powerpc_darwin7.7.0_32b_emt2.0'(doc) -> []; 268: 'powerpc_darwin7.7.0_32b_emt2.0'(suite) -> []; 269: 'powerpc_darwin7.7.0_32b_emt2.0'(Config) when is_list(Config) -> 270: ?line Res = run_emem_on_casefile(Config), 271: ?line "test_server" = Res#emem_res.nodename, 272: ?line "grima" = Res#emem_res.hostname, 273: ?line "13021" = Res#emem_res.pid, 274: ?line "2005-01-20 15:08:17.568668" = Res#emem_res.start_time, 275: ?line "2.0" = Res#emem_res.trace_version, 276: ?line "32 bits" = Res#emem_res.word_size, 277: ?line ["9", 278: "2784323", "8641", "531105", "15893", "522464"] 279: = Res#emem_res.last_values, 280: ?line ["6150376", "9311"] = Res#emem_res.maximum, 281: ?line "0" = Res#emem_res.exit_code, 282: ?line emem_comment(Config). 283: 284: 'alpha_osf1v5.1_64b_emt2.0'(doc) -> []; 285: 'alpha_osf1v5.1_64b_emt2.0'(suite) -> []; 286: 'alpha_osf1v5.1_64b_emt2.0'(Config) when is_list(Config) -> 287: ?line Res = run_emem_on_casefile(Config), 288: ?line "test_server" = Res#emem_res.nodename, 289: ?line "thorin" = Res#emem_res.hostname, 290: ?line "224630" = Res#emem_res.pid, 291: ?line "2005-01-20 22:38:01.299632" = Res#emem_res.start_time, 292: ?line "2.0" = Res#emem_res.trace_version, 293: ?line "64 bits" = Res#emem_res.word_size, 294: ?line case Res#emem_res.max_word_size of 295: "32 bits" -> 296: ?line emem_comment(Config, ?EMEM_64_32_COMMENT); 297: "64 bits" -> 298: ?line ["22", 299: "6591992", "8625", "516785", "14805", "508160", 300: "11429184", "5", "127", "254", "122", 301: "0", "0", "61", "0", "61"] = Res#emem_res.last_values, 302: ?line ["7041775", "9295", 303: "11593024", "7", 304: "2097152", "3"] = Res#emem_res.maximum, 305: ?line "0" = Res#emem_res.exit_code, 306: ?line emem_comment(Config) 307: end. 308: 309: 'sparc_sunos5.8_64b_emt2.0'(doc) -> []; 310: 'sparc_sunos5.8_64b_emt2.0'(suite) -> []; 311: 'sparc_sunos5.8_64b_emt2.0'(Config) when is_list(Config) -> 312: ?line Res = run_emem_on_casefile(Config), 313: ?line "test_server" = Res#emem_res.nodename, 314: ?line "gorbag" = Res#emem_res.hostname, 315: ?line "10907" = Res#emem_res.pid, 316: ?line "2005-01-20 13:48:34.677068" = Res#emem_res.start_time, 317: ?line "2.0" = Res#emem_res.trace_version, 318: ?line "64 bits" = Res#emem_res.word_size, 319: ?line case Res#emem_res.max_word_size of 320: "32 bits" -> 321: ?line emem_comment(Config, ?EMEM_64_32_COMMENT); 322: "64 bits" -> 323: ?line ["16", 324: "5032887", "8657", "530635", "14316", "521978", 325: "8627140", "5", "139", "19", "134", 326: "0", "0", "67", "0", "67"] = Res#emem_res.last_values, 327: ?line ["11695070", "9324", 328: "16360388", "10", 329: "4136960", "3"] = Res#emem_res.maximum, 330: ?line "0" = Res#emem_res.exit_code, 331: ?line emem_comment(Config) 332: end. 333: 334: 'sparc_sunos5.8_32b_emt1.0'(doc) -> []; 335: 'sparc_sunos5.8_32b_emt1.0'(suite) -> []; 336: 'sparc_sunos5.8_32b_emt1.0'(Config) when is_list(Config) -> 337: ?line Res = run_emem_on_casefile(Config), 338: ?line "" = Res#emem_res.nodename, 339: ?line "" = Res#emem_res.hostname, 340: ?line "" = Res#emem_res.pid, 341: ?line "" = Res#emem_res.start_time, 342: ?line "1.0" = Res#emem_res.trace_version, 343: ?line "32 bits" = Res#emem_res.word_size, 344: ?line ["11", 345: "2558261", "8643", "560610", "15325", "551967"] 346: = Res#emem_res.last_values, 347: ?line ["2791121", "9317"] = Res#emem_res.maximum, 348: ?line "0" = Res#emem_res.exit_code, 349: ?line emem_comment(Config). 350: 351: 'pc_win2000_32b_emt1.0'(doc) -> []; 352: 'pc_win2000_32b_emt1.0'(suite) -> []; 353: 'pc_win2000_32b_emt1.0'(Config) when is_list(Config) -> 354: ?line Res = run_emem_on_casefile(Config), 355: ?line "" = Res#emem_res.nodename, 356: ?line "" = Res#emem_res.hostname, 357: ?line "" = Res#emem_res.pid, 358: ?line "" = Res#emem_res.start_time, 359: ?line "1.0" = Res#emem_res.trace_version, 360: ?line "32 bits" = Res#emem_res.word_size, 361: ?line ["6", 362: "2965248", "8614", "640897", "68903", "632283"] 363: = Res#emem_res.last_values, 364: ?line ["3147090", "9283"] = Res#emem_res.maximum, 365: ?line "0" = Res#emem_res.exit_code, 366: ?line emem_comment(Config). 367: 368: 369: 'powerpc_darwin7.7.0_32b_emt1.0'(doc) -> []; 370: 'powerpc_darwin7.7.0_32b_emt1.0'(suite) -> []; 371: 'powerpc_darwin7.7.0_32b_emt1.0'(Config) when is_list(Config) -> 372: ?line Res = run_emem_on_casefile(Config), 373: ?line "" = Res#emem_res.nodename, 374: ?line "" = Res#emem_res.hostname, 375: ?line "" = Res#emem_res.pid, 376: ?line "" = Res#emem_res.start_time, 377: ?line "1.0" = Res#emem_res.trace_version, 378: ?line "32 bits" = Res#emem_res.word_size, 379: ?line ["8", 380: "2852991", "8608", "529662", "15875", "521054"] 381: = Res#emem_res.last_values, 382: ?line ["3173335", "9278"] = Res#emem_res.maximum, 383: ?line "0" = Res#emem_res.exit_code, 384: ?line emem_comment(Config). 385: 386: 'alpha_osf1v5.1_64b_emt1.0'(doc) -> []; 387: 'alpha_osf1v5.1_64b_emt1.0'(suite) -> []; 388: 'alpha_osf1v5.1_64b_emt1.0'(Config) when is_list(Config) -> 389: ?line Res = run_emem_on_casefile(Config), 390: ?line "" = Res#emem_res.nodename, 391: ?line "" = Res#emem_res.hostname, 392: ?line "" = Res#emem_res.pid, 393: ?line "" = Res#emem_res.start_time, 394: ?line "1.0" = Res#emem_res.trace_version, 395: ?line "64 bits" = Res#emem_res.word_size, 396: ?line case Res#emem_res.max_word_size of 397: "32 bits" -> 398: ?line emem_comment(Config, ?EMEM_64_32_COMMENT); 399: "64 bits" -> 400: ?line ["22", 401: "6820094", "8612", "515518", "14812", "506906"] 402: = Res#emem_res.last_values, 403: ?line ["7292413", "9282"] = Res#emem_res.maximum, 404: ?line "0" = Res#emem_res.exit_code, 405: ?line emem_comment(Config) 406: end. 407: 408: 'sparc_sunos5.8_64b_emt1.0'(doc) -> []; 409: 'sparc_sunos5.8_64b_emt1.0'(suite) -> []; 410: 'sparc_sunos5.8_64b_emt1.0'(Config) when is_list(Config) -> 411: ?line Res = run_emem_on_casefile(Config), 412: ?line "" = Res#emem_res.nodename, 413: ?line "" = Res#emem_res.hostname, 414: ?line "" = Res#emem_res.pid, 415: ?line "" = Res#emem_res.start_time, 416: ?line "1.0" = Res#emem_res.trace_version, 417: ?line "64 bits" = Res#emem_res.word_size, 418: ?line case Res#emem_res.max_word_size of 419: "32 bits" -> 420: ?line emem_comment(Config, ?EMEM_64_32_COMMENT); 421: "64 bits" -> 422: ?line ["15", 423: "4965746", "8234", "543940", "14443", "535706"] 424: = Res#emem_res.last_values, 425: ?line ["11697645", "8908"] = Res#emem_res.maximum, 426: ?line "0" = Res#emem_res.exit_code, 427: ?line emem_comment(Config) 428: end. 429: 430: %% 431: %% 432: %% Auxiliary functions 433: %% 434: %% 435: 436: receive_and_save_trace(PortNumber, FileName) when is_integer(PortNumber), 437: is_list(FileName) -> 438: {ok, F} = file:open(FileName, [write, compressed]), 439: {ok, LS} = gen_tcp:listen(PortNumber, [inet, {reuseaddr,true}, binary]), 440: {ok, S} = gen_tcp:accept(LS), 441: gen_tcp:close(LS), 442: receive_loop(S,F). 443: 444: receive_loop(Socket, File) -> 445: receive 446: {tcp, Socket, Data} -> 447: ok = file:write(File, Data), 448: receive_loop(Socket, File); 449: {tcp_closed, Socket} -> 450: file:close(File), 451: ok; 452: {tcp_error, Socket, Reason} -> 453: file:close(File), 454: {error, Reason} 455: end. 456: 457: send_trace({Host, PortNumber}, FileName) when is_list(Host), 458: is_integer(PortNumber), 459: is_list(FileName) -> 460: ?line {ok, F} = file:open(FileName, [read, compressed]), 461: ?line {ok, S} = gen_tcp:connect(Host, PortNumber, [inet,{packet, 0}]), 462: ?line send_loop(S, F); 463: send_trace(EmuFlag, FileName) when is_list(EmuFlag), 464: is_list(FileName) -> 465: ?line ["+Mit", IpAddrStr, PortNoStr] = string:tokens(EmuFlag, " :"), 466: ?line send_trace({IpAddrStr, list_to_integer(PortNoStr)}, FileName). 467: 468: send_loop(Socket, File) -> 469: ?line case file:read(File, 128) of 470: {ok, Data} -> 471: ?line case gen_tcp:send(Socket, Data) of 472: ok -> ?line send_loop(Socket, File); 473: Error -> 474: ?line gen_tcp:close(Socket), 475: ?line file:close(File), 476: Error 477: end; 478: eof -> 479: ?line gen_tcp:close(Socket), 480: ?line file:close(File), 481: ?line ok; 482: Error -> 483: ?line gen_tcp:close(Socket), 484: ?line file:close(File), 485: ?line Error 486: end. 487: 488: check_emem(Dir, Type) when is_atom(Type) -> 489: ExeSuffix = case ?t:os_type() of 490: {win32, _} -> ".exe"; 491: _ -> "" 492: end, 493: TypeSuffix = case Type of 494: opt -> ""; 495: _ -> "." ++ atom_to_list(Type) 496: end, 497: Emem = "emem" ++ TypeSuffix ++ ExeSuffix, 498: case check_file(filename:join([Dir, Emem])) of 499: not_found -> ok; 500: File -> 501: Comment = case Type of 502: opt -> ""; 503: _ -> "[emem " ++ atom_to_list(Type) ++ " compiled]" 504: end, 505: throw([{emem, File}, {emem_comment, Comment}]) 506: end. 507: 508: check_dir(DirName) -> 509: case file:read_file_info(DirName) of 510: {ok, #file_info {type = directory, access = A}} when A == read; 511: A == read_write -> 512: DirName; 513: _ -> 514: not_found 515: end. 516: 517: check_file(FileName) -> 518: case file:read_file_info(FileName) of 519: {ok, #file_info {type = regular, access = A}} when A == read; 520: A == read_write -> 521: ?line FileName; 522: _ -> 523: ?line not_found 524: end. 525: 526: emem_comment(Config) when is_list(Config) -> 527: emem_comment(Config, ""). 528: 529: emem_comment(Config, ExtraComment) 530: when is_list(Config), is_list(ExtraComment) -> 531: case {?config(emem_comment, Config), ExtraComment} of 532: {"", ""} -> ?line ok; 533: {"", XC} -> ?line {comment, XC}; 534: {EmemC, ""} -> ?line {comment, EmemC}; 535: {EmemC, XC} -> ?line {comment, EmemC ++ " " ++ XC} 536: end. 537: 538: run_emem_on_casefile(Config) -> 539: CaseName = atom_to_list(?config(testcase, Config)), 540: ?line File = filename:join([?config(data_dir, Config), CaseName ++ ".gz"]), 541: ?line case check_file(File) of 542: not_found -> 543: ?line ?t:fail({error, {filenotfound, File}}); 544: _ -> 545: ?line ok 546: end, 547: ?line {ok, EmuFlag, Port} = start_emem(Config), 548: ?line Parent = self(), 549: ?line Ref = make_ref(), 550: ?line spawn_link(fun () -> 551: SRes = send_trace(EmuFlag, File), 552: Parent ! {Ref, SRes} 553: end), 554: ?line Res = get_emem_result(Port), 555: ?line receive 556: {Ref, ok} -> 557: ?line ok; 558: {Ref, SendError} -> 559: ?line ?t:format("Send result: ~p~n", [SendError]) 560: end, 561: ?line Res. 562: 563: get_emem_result(Port) -> 564: ?line {Res, LV} = get_emem_result(Port, {#emem_res{}, []}), 565: ?line Res#emem_res{last_values = string:tokens(LV, " ")}. 566: 567: get_emem_result(Port, {_EmemRes, _LastValues} = Res) -> 568: ?line case get_emem_line(Port) of 569: eof -> 570: ?line Res; 571: Line -> 572: ?line get_emem_result(Port, parse_emem_line(Line, Res)) 573: end. 574: 575: parse_emem_main_header_footer_line(Line, {ER, LV} = Res) -> 576: 577: %% Header 578: ?line case has_prefix("> Nodename:", Line) of 579: {true, NN} -> 580: ?line throw({ER#emem_res{nodename = strip(NN)}, LV}); 581: false -> ?line ok 582: end, 583: ?line case has_prefix("> Hostname:", Line) of 584: {true, HN} -> 585: ?line throw({ER#emem_res{hostname = strip(HN)}, LV}); 586: false -> ?line ok 587: end, 588: ?line case has_prefix("> Pid:", Line) of 589: {true, P} -> 590: ?line throw({ER#emem_res{pid = strip(P)}, LV}); 591: false -> ?line ok 592: end, 593: ?line case has_prefix("> Start time (UTC):", Line) of 594: {true, ST} -> 595: ?line throw({ER#emem_res{start_time = strip(ST)}, LV}); 596: false -> ?line ok 597: end, 598: ?line case has_prefix("> Actual trace version:", Line) of 599: {true, TV} -> 600: ?line throw({ER#emem_res{trace_version = strip(TV)}, LV}); 601: false -> ?line ok 602: end, 603: ?line case has_prefix("> Maximum trace word size:", Line) of 604: {true, MWS} -> 605: ?line throw({ER#emem_res{max_word_size = strip(MWS)}, LV}); 606: false -> ?line ok 607: end, 608: ?line case has_prefix("> Actual trace word size:", Line) of 609: {true, WS} -> 610: ?line throw({ER#emem_res{word_size = strip(WS)}, LV}); 611: false -> ?line ok 612: end, 613: 614: %% Footer 615: ?line case has_prefix("> Maximum:", Line) of 616: {true, M} -> 617: ?line throw({ER#emem_res{maximum = string:tokens(M," ")}, LV}); 618: false -> ?line ok 619: end, 620: ?line case has_prefix("> Emulator exited with code:", Line) of 621: {true, EC} -> 622: ?line throw({ER#emem_res{exit_code = strip(EC)}, LV}); 623: false -> ?line ok 624: end, 625: ?line Res. 626: 627: parse_emem_header_line(_Line, {_ER, _LV} = Res) -> 628: ?line Res. 629: 630: parse_emem_value_line(Line, {EmemRes, _OldLastValues}) -> 631: ?line {EmemRes, Line}. 632: 633: parse_emem_line("", Res) -> 634: ?line Res; 635: parse_emem_line(Line, Res) -> 636: ?line [Prefix | _] = Line, 637: case Prefix of 638: $> -> ?line catch parse_emem_main_header_footer_line(Line, Res); 639: $| -> ?line catch parse_emem_header_line(Line, Res); 640: _ -> ?line catch parse_emem_value_line(Line, Res) 641: end. 642: 643: start_emem(Config) when is_list(Config) -> 644: ?line Emem = ?config(emem, Config), 645: ?line Cd = case ignore_cores:dir(Config) of 646: false -> []; 647: Dir -> [{cd, Dir}] 648: end, 649: ?line case open_port({spawn, Emem ++ " -t -n -o -i 1"}, 650: Cd ++ [{line, 1024}, eof]) of 651: Port when is_port(Port) -> ?line {ok, read_emu_flag(Port), Port}; 652: Error -> ?line ?t:fail(Error) 653: end. 654: 655: read_emu_flag(Port) -> 656: ?line Line = case get_emem_line(Port) of 657: eof -> ?line ?t:fail(unexpected_end_of_file); 658: L -> ?line L 659: end, 660: ?line case has_prefix("> Emulator command line argument:", Line) of 661: {true, EmuFlag} -> EmuFlag; 662: false -> ?line read_emu_flag(Port) 663: end. 664: 665: get_emem_line(Port, Acc) -> 666: ?line receive 667: {Port, {data, {eol, Data}}} -> 668: ?line Res = case Acc of 669: [] -> ?line Data; 670: _ -> ?line lists:flatten([Acc|Data]) 671: end, 672: ?line ?t:format("~s", [Res]), 673: ?line Res; 674: {Port, {data, {noeol, Data}}} -> 675: ?line get_emem_line(Port, [Acc|Data]); 676: {Port, eof} -> 677: ?line port_close(Port), 678: ?line eof 679: end. 680: 681: get_emem_line(Port) -> 682: ?line get_emem_line(Port, []). 683: 684: short_hostname([]) -> 685: []; 686: short_hostname([$.|_]) -> 687: []; 688: short_hostname([C|Cs]) -> 689: [C | short_hostname(Cs)]. 690: 691: has_prefix([], List) when is_list(List) -> 692: {true, List}; 693: has_prefix([P|Xs], [P|Ys]) -> 694: has_prefix(Xs, Ys); 695: has_prefix(_, _) -> 696: false. 697: 698: strip(Str) -> string:strip(Str). 699: 700: mk_nodename(Config) -> 701: {A, B, C} = now(), 702: atom_to_list(?MODULE) 703: ++ "-" ++ atom_to_list(?config(testcase, Config)) 704: ++ "-" ++ integer_to_list(A*1000000000000 + B*1000000 + C). 705: 706: start_node(Name, Args) -> 707: ?line Pa = filename:dirname(code:which(?MODULE)), 708: ?line ?t:start_node(Name, peer, [{args, Args ++ " -pa " ++ Pa}]). 709: 710: % stop_node(Node) -> 711: % ?t:stop_node(Node). 712: 713: is_debug_compiled() -> 714: is_debug_compiled(erlang:system_info(system_version)). 715: 716: is_debug_compiled([$d,$e,$b,$u,$g | _]) -> 717: true; 718: is_debug_compiled([ _, _, _, _]) -> 719: false; 720: is_debug_compiled([]) -> 721: false; 722: is_debug_compiled([_|Rest]) -> 723: is_debug_compiled(Rest).