1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2005-2012. 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: 20: %%%------------------------------------------------------------------- 21: %%% File : erl_print_SUITE.erl 22: %%% Author : Rickard Green <rickard.s.green@ericsson.com> 23: %%% Description : 24: %%% 25: %%% Created : 10 Mar 2005 by Rickard Green <rickard.s.green@ericsson.com> 26: %%%------------------------------------------------------------------- 27: -module(erl_print_SUITE). 28: -author('rickard.s.green@ericsson.com'). 29: 30: 31: %-define(line_trace, 1). 32: 33: -define(DEFAULT_TIMEOUT, ?t:minutes(10)). 34: 35: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 36: init_per_group/2,end_per_group/2, 37: init_per_testcase/2, end_per_testcase/2]). 38: 39: -export([erlang_display/1, integer/1, float/1, 40: string/1, character/1, snprintf/1, quote/1]). 41: 42: -include_lib("test_server/include/test_server.hrl"). 43: 44: suite() -> [{ct_hooks,[ts_install_cth]}]. 45: 46: all() -> 47: test_cases(). 48: 49: groups() -> 50: []. 51: 52: init_per_suite(Config) -> 53: Config. 54: 55: end_per_suite(_Config) -> 56: ok. 57: 58: init_per_group(_GroupName, Config) -> 59: Config. 60: 61: end_per_group(_GroupName, Config) -> 62: Config. 63: 64: 65: %% 66: %% 67: %% Test cases 68: %% 69: %% 70: 71: test_cases() -> 72: [erlang_display, integer, float, string, character, 73: snprintf, quote]. 74: 75: erlang_display(doc) -> []; 76: erlang_display(suite) -> []; 77: erlang_display(Config) when is_list(Config) -> 78: ?line put(erlang_display_test, ok), 79: OAIS = erts_debug:set_internal_state(available_internal_state, true), 80: 81: %% atoms 82: ?line chk_display(atom, "atom"), 83: ?line chk_display(true, "true"), 84: ?line chk_display(false, "false"), 85: ?line chk_display('DOWN', "'DOWN'"), 86: ?line chk_display('EXIT', "'EXIT'"), 87: ?line chk_display('asdDofw $@{}][', "'asdDofw $@{}]['"), 88: 89: %% integers 90: ?line chk_display(0, "0"), 91: ?line chk_display(1, "1"), 92: ?line chk_display(4711, "4711"), 93: ?line chk_display(((1 bsl 27) - 1), "134217727"), 94: ?line chk_display((1 bsl 27), "134217728"), 95: ?line chk_display((1 bsl 32), "4294967296"), 96: ?line chk_display(11111111111, "11111111111"), 97: ?line chk_display((1 bsl 59) - 1, "576460752303423487"), 98: ?line chk_display(1 bsl 59, "576460752303423488"), 99: ?line chk_display(111111111111111111111, "111111111111111111111"), 100: ?line chk_display(123456789012345678901234567890, 101: "123456789012345678901234567890"), 102: ?line chk_display(1 bsl 10000, str_1_bsl_10000()), 103: ?line chk_display(-1, "-1"), 104: ?line chk_display(-4711, "-4711"), 105: ?line chk_display(-(1 bsl 27), "-134217728"), 106: ?line chk_display(-((1 bsl 27) + 1), "-134217729"), 107: ?line chk_display(-(1 bsl 32), "-4294967296"), 108: ?line chk_display(-11111111111, "-11111111111"), 109: ?line chk_display(-(1 bsl 59), "-576460752303423488"), 110: ?line chk_display(-((1 bsl 59) + 1), "-576460752303423489"), 111: ?line chk_display(-111111111111111111111, "-111111111111111111111"), 112: ?line chk_display(-123456789012345678901234567890, 113: "-123456789012345678901234567890"), 114: ?line chk_display(-(1 bsl 10000), [$- | str_1_bsl_10000()]), 115: 116: ?line MyCre = my_cre(), 117: 118: %% pids 119: ?line chk_display(mk_pid_xstr({node(), MyCre}, 4711, 42)), 120: ?line chk_display(mk_pid_xstr({node(), oth_cre(MyCre)}, 4711, 42)), 121: ?line chk_display(mk_pid_xstr({node(), oth_cre(oth_cre(MyCre))}, 4711, 42)), 122: 123: ?line chk_display(mk_pid_xstr({a@b, MyCre}, 4711, 42)), 124: ?line chk_display(mk_pid_xstr({a@b, oth_cre(MyCre)}, 4711, 42)), 125: ?line chk_display(mk_pid_xstr({a@b, oth_cre(oth_cre(MyCre))}, 4711, 42)), 126: 127: %% ports 128: ?line chk_display(mk_port_xstr({node(), MyCre}, 4711)), 129: ?line chk_display(mk_port_xstr({node(), oth_cre(MyCre)}, 4711)), 130: ?line chk_display(mk_port_xstr({node(), oth_cre(oth_cre(MyCre))}, 4711)), 131: 132: ?line chk_display(mk_port_xstr({c@d, MyCre}, 4711)), 133: ?line chk_display(mk_port_xstr({c@d, oth_cre(MyCre)}, 4711)), 134: ?line chk_display(mk_port_xstr({c@d, oth_cre(oth_cre(MyCre))}, 4711)), 135: 136: %% refs 137: ?line chk_display(mk_ref_xstr({node(), MyCre}, [1,2,3])), 138: ?line chk_display(mk_ref_xstr({node(), oth_cre(MyCre)}, [1,2,3])), 139: ?line chk_display(mk_ref_xstr({node(), oth_cre(oth_cre(MyCre))}, [1,2,3])), 140: 141: ?line chk_display(mk_ref_xstr({e@f, MyCre},[1,2,3] )), 142: ?line chk_display(mk_ref_xstr({e@f, oth_cre(MyCre)}, [1,2,3])), 143: ?line chk_display(mk_ref_xstr({e@f, oth_cre(oth_cre(MyCre))}, [1,2,3])), 144: 145: %% Compund terms 146: ?line {Pid, PidStr} = mk_pid_xstr({x@y, oth_cre(MyCre)}, 4712, 41), 147: ?line {Port, PortStr} = mk_port_xstr({x@y, oth_cre(MyCre)}, 4712), 148: ?line {Ref, RefStr} = mk_ref_xstr({e@f, oth_cre(MyCre)}, [11,12,13]), 149: 150: ?line chk_display({atom,-4711,Ref,{"hej",[Pid,222222222222222222222222,Port,4711]}}, 151: "{atom,-4711,"++RefStr++",{\"hej\",["++PidStr++",222222222222222222222222,"++PortStr++",4711]}}"), 152: ?line chk_display({{{{{{{{{{{{{{{{{{{{{{{hi}}}}}}}}}}}}}}}}}}}}}}}, 153: "{{{{{{{{{{{{{{{{{{{{{{{hi}}}}}}}}}}}}}}}}}}}}}}}"), 154: ?line chk_display([[[[[[[[[[[[[[[[[[[[[[[yo]]]]]]]]]]]]]]]]]]]]]]], 155: "[[[[[[[[[[[[[[[[[[[[[[[yo]]]]]]]]]]]]]]]]]]]]]]]"), 156: ?line chk_display({[{[{[{[{[{[{[{[{[{[{[{[ii]}]}]}]}]}]}]}]}]}]}]}]}, 157: "{[{[{[{[{[{[{[{[{[{[{[{[ii]}]}]}]}]}]}]}]}]}]}]}]}"), 158: ?line chk_display([], "[]"), % Not really a compound term :) 159: ?line chk_display([a|b], "[a|b]"), 160: ?line chk_display([a,b,c|z], "[a,b,c|z]"), 161: ?line chk_display([a,b,c], "[a,b,c]"), 162: ?line chk_display([Pid,Port,Ref], 163: "["++PidStr++","++PortStr++","++RefStr++"]"), 164: ?line chk_display("abcdefghijklmnopqrstuvwxyz", 165: "\"abcdefghijklmnopqrstuvwxyz\""), 166: ?line chk_display("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 167: "\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""), 168: ?line chk_display("H E J", "\"H E J\""), 169: ?line chk_display("asdDofw $@{}][", "\"asdDofw $@{}][\""), 170: 171: %% 172: %% TODO: Check binaries, fun and floats... 173: %% 174: 175: erts_debug:set_internal_state(available_internal_state, OAIS), 176: ?line ok = get(erlang_display_test). 177: 178: get_chnl_no(NodeName) when is_atom(NodeName) -> 179: erts_debug:get_internal_state({channel_number, NodeName}). 180: 181: chk_display(Term, Expect) when is_list(Expect) -> 182: Dstr = erts_debug:display(Term), 183: case Expect ++ io_lib:nl() of 184: Dstr -> 185: ?t:format("Test of \"~p\" succeeded.~n" 186: " Expected and got: ~s~n", 187: [Term, io_lib:write_string(Dstr)]); 188: DoExpect -> 189: ?t:format("***~n" 190: "*** Test of \"~p\" failed!~n" 191: "*** Expected: ~s~n" 192: "*** Got: ~s~n" 193: "***~n", 194: [Term, 195: io_lib:write_string(DoExpect), 196: io_lib:write_string(Dstr)]), 197: put(erlang_display_test, failed) 198: end. 199: 200: chk_display({Term, Expect}) -> 201: chk_display(Term, Expect). 202: 203: mk_pid_xstr({NodeName, Creation}, Number, Serial) -> 204: Pid = mk_pid({NodeName, Creation}, Number, Serial), 205: XStr = "<" ++ integer_to_list(get_chnl_no(NodeName)) 206: ++ "." ++ integer_to_list(Number) 207: ++ "." ++ integer_to_list(Serial) ++ ">", 208: {Pid, XStr}. 209: 210: mk_port_xstr({NodeName, Creation}, Number) -> 211: Port = mk_port({NodeName, Creation}, Number), 212: XStr = "#Port<" ++ integer_to_list(get_chnl_no(NodeName)) 213: ++ "." ++ integer_to_list(Number) ++ ">", 214: {Port, XStr}. 215: 216: mk_ref_xstr({NodeName, Creation}, Numbers) -> 217: Ref = mk_ref({NodeName, Creation}, Numbers), 218: XStr = "#Ref<" ++ integer_to_list(get_chnl_no(NodeName)) 219: ++ ref_numbers_xstr(Numbers) ++ ">", 220: {Ref, XStr}. 221: 222: ref_numbers_xstr([]) -> 223: []; 224: ref_numbers_xstr([N | Ns]) -> 225: ref_numbers_xstr(Ns) ++ "." ++ integer_to_list(N). 226: 227: -define(TESTCASE_IMPL(T), T(A) -> default_testcase_impl(A)). 228: 229: ?TESTCASE_IMPL(integer). 230: ?TESTCASE_IMPL(float). 231: ?TESTCASE_IMPL(string). 232: ?TESTCASE_IMPL(character). 233: ?TESTCASE_IMPL(snprintf). 234: ?TESTCASE_IMPL(quote). 235: 236: %% 237: %% 238: %% Auxiliary functions 239: %% 240: %% 241: 242: default_testcase_impl(doc) -> []; 243: default_testcase_impl(suite) -> []; 244: default_testcase_impl(Config) when is_list(Config) -> ?line run_case(Config). 245: 246: init_per_testcase(Case, Config) -> 247: Dog = ?t:timetrap(?DEFAULT_TIMEOUT), 248: [{testcase, Case}, {watchdog, Dog} |Config]. 249: 250: end_per_testcase(_Case, Config) -> 251: Dog = ?config(watchdog, Config), 252: ?t:timetrap_cancel(Dog), 253: ok. 254: 255: -define(TESTPROG, "erl_print_tests"). 256: -define(FAILED_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$F,$A,$I,$L,$U,$R,$E). 257: -define(SKIPPED_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$S,$K,$I,$P). 258: -define(SUCCESS_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$S,$U,$C,$C,$E,$S,$S). 259: -define(PID_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$P,$I,$D). 260: 261: port_prog_killer(EProc, OSProc) when is_pid(EProc), is_list(OSProc) -> 262: ?line process_flag(trap_exit, true), 263: ?line Ref = erlang:monitor(process, EProc), 264: ?line receive 265: {'DOWN', Ref, _, _, Reason} when is_tuple(Reason), 266: element(1, Reason) 267: == timetrap_timeout -> 268: ?line Cmd = "kill -9 " ++ OSProc, 269: ?line ?t:format("Test case timed out. " 270: "Trying to kill port program.~n" 271: " Executing: ~p~n", [Cmd]), 272: ?line case os:cmd(Cmd) of 273: [] -> 274: ok; 275: OsCmdRes -> 276: ?line ?t:format(" ~s", [OsCmdRes]) 277: end; 278: {'DOWN', Ref, _, _, _} -> 279: %% OSProc is assumed to have terminated by itself 280: ?line ok 281: end. 282: 283: get_line(_Port, eol, Data) -> 284: ?line Data; 285: get_line(Port, noeol, Data) -> 286: ?line receive 287: {Port, {data, {Flag, NextData}}} -> 288: ?line get_line(Port, Flag, Data ++ NextData); 289: {Port, eof} -> 290: ?line ?t:fail(port_prog_unexpectedly_closed) 291: end. 292: 293: read_case_data(Port, TestCase) -> 294: ?line receive 295: {Port, {data, {eol, [?SUCCESS_MARKER]}}} -> 296: ?line ok; 297: {Port, {data, {Flag, [?SUCCESS_MARKER | CommentStart]}}} -> 298: ?line {comment, get_line(Port, Flag, CommentStart)}; 299: {Port, {data, {Flag, [?SKIPPED_MARKER | CommentStart]}}} -> 300: ?line {skipped, get_line(Port, Flag, CommentStart)}; 301: {Port, {data, {Flag, [?FAILED_MARKER | ReasonStart]}}} -> 302: ?line ?t:fail(get_line(Port, Flag, ReasonStart)); 303: {Port, {data, {eol, [?PID_MARKER | PidStr]}}} -> 304: ?line ?t:format("Port program pid: ~s~n", [PidStr]), 305: ?line CaseProc = self(), 306: ?line _ = list_to_integer(PidStr), % Sanity check 307: spawn_opt(fun () -> 308: port_prog_killer(CaseProc, PidStr) 309: end, 310: [{priority, max}, link]), 311: read_case_data(Port, TestCase); 312: {Port, {data, {Flag, LineStart}}} -> 313: ?line ?t:format("~s~n", [get_line(Port, Flag, LineStart)]), 314: read_case_data(Port, TestCase); 315: {Port, eof} -> 316: ?line ?t:fail(port_prog_unexpectedly_closed) 317: end. 318: 319: run_case(Config) -> 320: run_case(Config, ""). 321: 322: run_case(Config, TestArgs) -> 323: run_case(Config, TestArgs, fun (_Port) -> ok end). 324: 325: run_case(Config, TestArgs, Fun) -> 326: Test = atom_to_list(?config(testcase, Config)), 327: TestProg = filename:join([?config(data_dir, Config), 328: ?TESTPROG 329: ++ "." 330: ++ atom_to_list(erlang:system_info(threads))]), 331: Cmd = TestProg ++ " " ++ Test ++ " " ++ TestArgs, 332: case catch open_port({spawn, Cmd}, [stream, 333: use_stdio, 334: stderr_to_stdout, 335: eof, 336: {line, 1024}]) of 337: Port when is_port(Port) -> 338: ?line Fun(Port), 339: ?line CaseResult = read_case_data(Port, Test), 340: ?line receive 341: {Port, eof} -> 342: ?line ok 343: end, 344: ?line CaseResult; 345: Error -> 346: ?line ?t:fail({open_port_failed, Error}) 347: end. 348: 349: 350: -define(VERSION_MAGIC, 131). 351: 352: -define(ATOM_EXT, 100). 353: -define(REFERENCE_EXT, 101). 354: -define(PORT_EXT, 102). 355: -define(PID_EXT, 103). 356: -define(NEW_REFERENCE_EXT, 114). 357: 358: uint32_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 32 -> 359: [(Uint bsr 24) band 16#ff, 360: (Uint bsr 16) band 16#ff, 361: (Uint bsr 8) band 16#ff, 362: Uint band 16#ff]; 363: uint32_be(Uint) -> 364: exit({badarg, uint32_be, [Uint]}). 365: 366: 367: uint16_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 16 -> 368: [(Uint bsr 8) band 16#ff, 369: Uint band 16#ff]; 370: uint16_be(Uint) -> 371: exit({badarg, uint16_be, [Uint]}). 372: 373: uint8(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 8 -> 374: Uint band 16#ff; 375: uint8(Uint) -> 376: exit({badarg, uint8, [Uint]}). 377: 378: 379: 380: mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) -> 381: mk_pid({atom_to_list(NodeName), Creation}, Number, Serial); 382: mk_pid({NodeName, Creation}, Number, Serial) -> 383: case catch binary_to_term(list_to_binary([?VERSION_MAGIC, 384: ?PID_EXT, 385: ?ATOM_EXT, 386: uint16_be(length(NodeName)), 387: NodeName, 388: uint32_be(Number), 389: uint32_be(Serial), 390: uint8(Creation)])) of 391: Pid when is_pid(Pid) -> 392: Pid; 393: {'EXIT', {badarg, _}} -> 394: exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]}); 395: Other -> 396: exit({unexpected_binary_to_term_result, Other}) 397: end. 398: 399: mk_port({NodeName, Creation}, Number) when is_atom(NodeName) -> 400: mk_port({atom_to_list(NodeName), Creation}, Number); 401: mk_port({NodeName, Creation}, Number) -> 402: case catch binary_to_term(list_to_binary([?VERSION_MAGIC, 403: ?PORT_EXT, 404: ?ATOM_EXT, 405: uint16_be(length(NodeName)), 406: NodeName, 407: uint32_be(Number), 408: uint8(Creation)])) of 409: Port when is_port(Port) -> 410: Port; 411: {'EXIT', {badarg, _}} -> 412: exit({badarg, mk_port, [{NodeName, Creation}, Number]}); 413: Other -> 414: exit({unexpected_binary_to_term_result, Other}) 415: end. 416: 417: mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName), 418: is_integer(Creation), 419: is_list(Numbers) -> 420: mk_ref({atom_to_list(NodeName), Creation}, Numbers); 421: mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName), 422: is_integer(Creation), 423: is_integer(Number) -> 424: case catch binary_to_term(list_to_binary([?VERSION_MAGIC, 425: ?REFERENCE_EXT, 426: ?ATOM_EXT, 427: uint16_be(length(NodeName)), 428: NodeName, 429: uint32_be(Number), 430: uint8(Creation)])) of 431: Ref when is_reference(Ref) -> 432: Ref; 433: {'EXIT', {badarg, _}} -> 434: exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]}); 435: Other -> 436: exit({unexpected_binary_to_term_result, Other}) 437: end; 438: mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName), 439: is_integer(Creation), 440: is_list(Numbers) -> 441: case catch binary_to_term(list_to_binary([?VERSION_MAGIC, 442: ?NEW_REFERENCE_EXT, 443: uint16_be(length(Numbers)), 444: ?ATOM_EXT, 445: uint16_be(length(NodeName)), 446: NodeName, 447: uint8(Creation), 448: lists:map(fun (N) -> 449: uint32_be(N) 450: end, 451: Numbers)])) of 452: Ref when is_reference(Ref) -> 453: Ref; 454: {'EXIT', {badarg, _}} -> 455: exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]}); 456: Other -> 457: exit({unexpected_binary_to_term_result, Other}) 458: end. 459: 460: my_cre() -> erlang:system_info(creation). 461: 462: oth_cre(0) -> 1; 463: oth_cre(1) -> 2; 464: oth_cre(2) -> 3; 465: oth_cre(3) -> 1; 466: oth_cre(N) -> exit({invalid_creation, N}). 467: 468: str_1_bsl_10000() -> 469: "19950631168807583848837421626835850838234968318861924548520089498529438830221946631919961684036194597899331129423209124271556491349413781117593785932096323957855730046793794526765246551266059895520550086918193311542508608460618104685509074866089624888090489894838009253941633257850621568309473902556912388065225096643874441046759871626985453222868538161694315775629640762836880760732228535091641476183956381458969463899410840960536267821064621427333394036525565649530603142680234969400335934316651459297773279665775606172582031407994198179607378245683762280037302885487251900834464581454650557929601414833921615734588139257095379769119277800826957735674444123062018757836325502728323789270710373802866393031428133241401624195671690574061419654342324638801248856147305207431992259611796250130992860241708340807605932320161268492288496255841312844061536738951487114256315111089745514203313820202931640957596464756010405845841566072044962867016515061920631004186422275908670900574606417856951911456055068251250406007519842261898059237118054444788072906395242548339221982707404473162376760846613033778706039803413197133493654622700563169937455508241780972810983291314403571877524768509857276937926433221599399876886660808368837838027643282775172273657572744784112294389733810861607423253291974813120197604178281965697475898164531258434135959862784130128185406283476649088690521047580882615823961985770122407044330583075869039319604603404973156583208672105913300903752823415539745394397715257455290510212310947321610753474825740775273986348298498340756937955646638621874569499279016572103701364433135817214311791398222983845847334440270964182851005072927748364550578634501100852987812389473928699540834346158807043959118985815145779177143619698728131459483783202081474982171858011389071228250905826817436220577475921417653715687725614904582904992461028630081535583308130101987675856234343538955409175623400844887526162643568648833519463720377293240094456246923254350400678027273837755376406726898636241037491410966718557050759098100246789880178271925953381282421954028302759408448955014676668389697996886241636313376393903373455801407636741877711055384225739499110186468219696581651485130494222369947714763069155468217682876200362777257723781365331611196811280792669481887201298643660768551639860534602297871557517947385246369446923087894265948217008051120322365496288169035739121368338393591756418733850510970271613915439590991598154654417336311656936031122249937969999226781732358023111862644575299135758175008199839236284615249881088960232244362173771618086357015468484058622329792853875623486556440536962622018963571028812361567512543338303270029097668650568557157505516727518899194129711337690149916181315171544007728650573189557450920330185304847113818315407324053319038462084036421763703911550639789000742853672196280903477974533320468368795868580237952218629120080742819551317948157624448298518461509704888027274721574688131594750409732115080498190455803416826949787141316063210686391511681774304792596709376".