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: -module(bif_SUITE). 21: 22: -include_lib("test_server/include/test_server.hrl"). 23: 24: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 25: init_per_group/2,end_per_group/2, 26: init_per_testcase/2,end_per_testcase/2, 27: display/1, display_huge/0, 28: erl_bif_types/1,guard_bifs_in_erl_bif_types/1, 29: shadow_comments/1, 30: specs/1,improper_bif_stubs/1,auto_imports/1, 31: t_list_to_existing_atom/1,os_env/1,otp_7526/1, 32: binary_to_atom/1,binary_to_existing_atom/1, 33: atom_to_binary/1,min_max/1, erlang_halt/1]). 34: 35: suite() -> [{ct_hooks,[ts_install_cth]}]. 36: 37: all() -> 38: [erl_bif_types, guard_bifs_in_erl_bif_types, shadow_comments, 39: specs, improper_bif_stubs, auto_imports, 40: t_list_to_existing_atom, os_env, otp_7526, 41: display, 42: atom_to_binary, binary_to_atom, binary_to_existing_atom, 43: min_max, erlang_halt]. 44: 45: groups() -> 46: []. 47: 48: init_per_suite(Config) -> 49: Config. 50: 51: end_per_suite(_Config) -> 52: ok. 53: 54: init_per_group(_GroupName, Config) -> 55: Config. 56: 57: end_per_group(_GroupName, Config) -> 58: Config. 59: 60: 61: init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> 62: Dog=?t:timetrap(?t:minutes(1)), 63: [{watchdog, Dog}|Config]. 64: 65: end_per_testcase(_Func, Config) -> 66: Dog=?config(watchdog, Config), 67: ?t:timetrap_cancel(Dog). 68: 69: 70: display(suite) -> 71: []; 72: display(doc) -> 73: ["Uses erlang:display to test that erts_printf does not do deep recursion"]; 74: display(Config) when is_list(Config) -> 75: Pa = filename:dirname(code:which(?MODULE)), 76: {ok, Node} = test_server:start_node(display_huge_term,peer, 77: [{args, "-pa \""++Pa++"\""}]), 78: true = rpc:call(Node,?MODULE,display_huge,[]), 79: test_server:stop_node(Node), 80: ok. 81: 82: display_huge() -> 83: erlang:display(deeep(100000)). 84: 85: deeep(0,Acc) -> 86: Acc; 87: deeep(N,Acc) -> 88: deeep(N-1,[Acc|[]]). 89: 90: deeep(N) -> 91: deeep(N,[hello]). 92: 93: erl_bif_types(Config) when is_list(Config) -> 94: ensure_erl_bif_types_compiled(), 95: 96: List0 = erlang:system_info(snifs), 97: 98: %% Ignore missing type information for hipe BIFs. 99: List = [MFA || {M,_,_}=MFA <- List0, M =/= hipe_bifs], 100: 101: KnownTypes = [MFA || MFA <- List, known_types(MFA)], 102: io:format("There are ~p BIFs with type information in erl_bif_types.", 103: [length(KnownTypes)]), 104: erl_bif_types_2(KnownTypes). 105: 106: erl_bif_types_2(List) -> 107: BadArity = [MFA || {M,F,A}=MFA <- List, 108: begin 109: Types = erl_bif_types:arg_types(M, F, A), 110: length(Types) =/= A 111: end], 112: case BadArity of 113: [] -> 114: erl_bif_types_3(List); 115: [_|_] -> 116: io:put_chars("Bifs with bad arity\n"), 117: io:format("~p\n", [BadArity]), 118: ?line ?t:fail({length(BadArity),bad_arity}) 119: end. 120: 121: erl_bif_types_3(List) -> 122: BadSmokeTest = [MFA || {M,F,A}=MFA <- List, 123: begin 124: try erl_bif_types:type(M, F, A) of 125: Type -> 126: %% Test that type is returned. 127: not erl_types:is_erl_type(Type) 128: catch 129: Class:Error -> 130: io:format("~p: ~p ~p\n", 131: [MFA,Class,Error]), 132: true 133: end 134: end], 135: case BadSmokeTest of 136: [] -> 137: ok; 138: [_|_] -> 139: io:put_chars("Bifs with failing calls to erlang_bif_types:type/3 " 140: "(or with bogus return values):\n"), 141: io:format("~p\n", [BadSmokeTest]), 142: ?line ?t:fail({length(BadSmokeTest),bad_smoke_test}) 143: end. 144: 145: guard_bifs_in_erl_bif_types(_Config) -> 146: ensure_erl_bif_types_compiled(), 147: 148: List0 = erlang:system_info(snifs), 149: List = [{F,A} || {erlang,F,A} <- List0, 150: erl_internal:guard_bif(F, A)], 151: Not = [FA || {F,A}=FA <- List, 152: not erl_bif_types:is_known(erlang, F, A)], 153: case Not of 154: [] -> 155: ok; 156: [_|_] -> 157: io:put_chars( 158: ["Dialyzer requires that all guard BIFs " 159: "have type information in erl_bif_types.\n\n" 160: "The following guard BIFs have no type information " 161: "in erl_bif_types:\n\n", 162: [io_lib:format(" ~p/~p\n", [F,A]) || {F,A} <- Not]]), 163: ?t:fail() 164: end. 165: 166: shadow_comments(_Config) -> 167: ensure_erl_bif_types_compiled(), 168: 169: List0 = erlang:system_info(snifs), 170: List1 = [MFA || {M,_,_}=MFA <- List0, M =/= hipe_bifs], 171: List = [MFA || MFA <- List1, not is_operator(MFA)], 172: HasTypes = [MFA || {M,F,A}=MFA <- List, 173: erl_bif_types:is_known(M, F, A)], 174: Path = get_code_path(), 175: BifRel = sofs:relation(HasTypes, [{m,f,a}]), 176: BifModules = sofs:to_external(sofs:projection(1, BifRel)), 177: AbstrByModule = [extract_abstract(Mod, Path) || Mod <- BifModules], 178: Specs0 = [extract_specs(Mod, Abstr) || 179: {Mod,Abstr} <- AbstrByModule], 180: Specs = lists:append(Specs0), 181: SpecFuns0 = [F || {F,_} <- Specs], 182: SpecFuns = sofs:relation(SpecFuns0, [{m,f,a}]), 183: HasTypesAndSpecs = sofs:intersection(BifRel, SpecFuns), 184: Commented0 = lists:append([extract_comments(Mod, Path) || 185: Mod <- BifModules]), 186: Commented = sofs:relation(Commented0, [{m,f,a}]), 187: {NoComments0,_,NoBifSpecs0} = 188: sofs:symmetric_partition(HasTypesAndSpecs, Commented), 189: NoComments = sofs:to_external(NoComments0), 190: NoBifSpecs = sofs:to_external(NoBifSpecs0), 191: 192: case NoComments of 193: [] -> 194: ok; 195: [_|_] -> 196: io:put_chars( 197: ["If a BIF stub has both a spec and has type information in " 198: "erl_bif_types, there *must*\n" 199: "be a comment in the source file to make that immediately " 200: "obvious.\n\nThe following comments are missing:\n\n", 201: [io_lib:format("%% Shadowed by erl_bif_types: ~p:~p/~p\n", 202: [M,F,A]) || {M,F,A} <- NoComments]]), 203: ?t:fail() 204: end, 205: 206: case NoBifSpecs of 207: [] -> 208: ok; 209: [_|_] -> 210: io:put_chars( 211: ["The following functions have \"shadowed\" comments " 212: "claiming that there is type information in erl_bif_types,\n" 213: "but actually there is no such type information.\n\n" 214: "Therefore, the following comments should be removed:\n\n", 215: [io_lib:format("%% Shadowed by erl_bif_types: ~p:~p/~p\n", 216: [M,F,A]) || {M,F,A} <- NoBifSpecs]]), 217: ?t:fail() 218: end. 219: 220: extract_comments(Mod, Path) -> 221: Beam = which(Mod, Path), 222: SrcDir = filename:join(filename:dirname(filename:dirname(Beam)), "src"), 223: Src = filename:join(SrcDir, atom_to_list(Mod) ++ ".erl"), 224: {ok,Bin} = file:read_file(Src), 225: Lines0 = binary:split(Bin, <<"\n">>, [global]), 226: Lines1 = [T || <<"%% Shadowed by erl_bif_types: ",T/binary>> <- Lines0], 227: {ok,ReMFA} = re:compile("([^:]*):([^/]*)/(\\d*)"), 228: Lines = [L || L <- Lines1, re:run(L, ReMFA, [{capture,[]}]) =:= match], 229: [begin 230: {match,[M,F,A]} = re:run(L, ReMFA, [{capture,all_but_first,list}]), 231: {list_to_atom(M),list_to_atom(F),list_to_integer(A)} 232: end || L <- Lines]. 233: 234: ensure_erl_bif_types_compiled() -> 235: c:l(erl_bif_types), 236: case erlang:function_exported(erl_bif_types, module_info, 0) of 237: false -> 238: %% Fail cleanly. 239: ?t:fail("erl_bif_types not compiled"); 240: true -> 241: ok 242: end. 243: 244: known_types({M,F,A}) -> 245: erl_bif_types:is_known(M, F, A). 246: 247: specs(_) -> 248: List0 = erlang:system_info(snifs), 249: 250: %% Ignore missing type information for hipe BIFs. 251: List1 = [MFA || {M,_,_}=MFA <- List0, M =/= hipe_bifs], 252: 253: %% Ignore all operators. 254: List = [MFA || MFA <- List1, not is_operator(MFA)], 255: 256: %% Extract specs from the abstract code for all BIFs. 257: Path = get_code_path(), 258: BifRel = sofs:relation(List, [{m,f,a}]), 259: BifModules = sofs:to_external(sofs:projection(1, BifRel)), 260: AbstrByModule = [extract_abstract(Mod, Path) || Mod <- BifModules], 261: Specs0 = [extract_specs(Mod, Abstr) || 262: {Mod,Abstr} <- AbstrByModule], 263: Specs = lists:append(Specs0), 264: BifSet = sofs:set(List, [function]), 265: SpecRel0 = sofs:relation(Specs, [{function,spec}]), 266: SpecRel = sofs:restriction(SpecRel0, BifSet), 267: 268: %% Find BIFs without specs. 269: NoSpecs0 = sofs:difference(BifSet, sofs:domain(SpecRel)), 270: NoSpecs = sofs:to_external(NoSpecs0), 271: case NoSpecs of 272: [] -> 273: ok; 274: [_|_] -> 275: io:put_chars("The following BIFs don't have specs:\n"), 276: [print_mfa(MFA) || MFA <- NoSpecs], 277: ?t:fail() 278: end. 279: 280: is_operator({erlang,F,A}) -> 281: erl_internal:arith_op(F, A) orelse 282: erl_internal:bool_op(F, A) orelse 283: erl_internal:comp_op(F, A) orelse 284: erl_internal:list_op(F, A) orelse 285: erl_internal:send_op(F, A); 286: is_operator(_) -> false. 287: 288: extract_specs(M, Abstr) -> 289: [{make_mfa(M, Name),Spec} || {attribute,_,spec,{Name,Spec}} <- Abstr]. 290: 291: make_mfa(M, {F,A}) -> {M,F,A}; 292: make_mfa(M, {M,_,_}=MFA) -> MFA. 293: 294: improper_bif_stubs(_) -> 295: Bifs0 = erlang:system_info(snifs), 296: Bifs = [MFA || {M,_,_}=MFA <- Bifs0, M =/= hipe_bifs], 297: Path = get_code_path(), 298: BifRel = sofs:relation(Bifs, [{m,f,a}]), 299: BifModules = sofs:to_external(sofs:projection(1, BifRel)), 300: AbstrByModule = [extract_abstract(Mod, Path) || Mod <- BifModules], 301: Funcs0 = [extract_functions(Mod, Abstr) || 302: {Mod,Abstr} <- AbstrByModule], 303: Funcs = lists:append(Funcs0), 304: BifSet = sofs:set(Bifs, [function]), 305: FuncRel0 = sofs:relation(Funcs, [{function,code}]), 306: FuncRel = sofs:restriction(FuncRel0, BifSet), 307: [check_stub(MFA, Body) || {MFA,Body} <- sofs:to_external(FuncRel)], 308: ok. 309: 310: auto_imports(_Config) -> 311: Path = get_code_path(), 312: {erlang,Abstr} = extract_abstract(erlang, Path), 313: SpecFuns = [Name || {attribute,_,spec,{Name,_}} <- Abstr], 314: auto_imports(SpecFuns, 0). 315: 316: auto_imports([{F,A}|T], Errors) -> 317: case erl_internal:bif(F, A) of 318: false -> 319: io:format("~p/~p: not auto-imported, but spec claims it " 320: "is auto-imported", [F,A]), 321: auto_imports(T, Errors+1); 322: true -> 323: auto_imports(T, Errors) 324: end; 325: auto_imports([{erlang,F,A}|T], Errors) -> 326: case erl_internal:bif(F, A) of 327: false -> 328: auto_imports(T, Errors); 329: true -> 330: io:format("~p/~p: auto-imported, but " 331: "spec claims it is *not* auto-imported", [F,A]), 332: auto_imports(T, Errors+1) 333: end; 334: auto_imports([], 0) -> 335: ok; 336: auto_imports([], Errors) -> 337: ?t:fail({Errors,inconsistencies}). 338: 339: extract_functions(M, Abstr) -> 340: [{{M,F,A},Body} || {function,_,F,A,Body} <- Abstr]. 341: 342: check_stub({erlang,apply,3}, _) -> 343: ok; 344: check_stub({_,F,A}, B) -> 345: try 346: [{clause,_,Args,[],Body}] = B, 347: A = length(Args), 348: [{call,_,{remote,_,{atom,_,erlang},{atom,_,nif_error}},[_]}] = Body 349: catch 350: _:_ -> 351: io:put_chars("Invalid body for the following BIF stub:\n"), 352: Func = {function,0,F,A,B}, 353: io:put_chars(erl_pp:function(Func)), 354: io:nl(), 355: io:put_chars("The body should be: erlang:nif_error(undef)"), 356: ?t:fail() 357: end. 358: 359: t_list_to_existing_atom(Config) when is_list(Config) -> 360: ?line all = list_to_existing_atom("all"), 361: ?line ?MODULE = list_to_existing_atom(?MODULE_STRING), 362: ?line UnlikelyStr = "dsfj923874390867er869fds9864y97jhg3973qerueoru", 363: try 364: ?line list_to_existing_atom(UnlikelyStr), 365: ?line ?t:fail() 366: catch 367: error:badarg -> ok 368: end, 369: 370: %% The compiler has become smarter! We need the call to id/1 in 371: %% the next line. 372: ?line UnlikelyAtom = list_to_atom(id(UnlikelyStr)), 373: ?line UnlikelyAtom = list_to_existing_atom(UnlikelyStr), 374: ok. 375: 376: os_env(doc) -> 377: []; 378: os_env(suite) -> 379: []; 380: os_env(Config) when is_list(Config) -> 381: ?line EnvVar1 = "MjhgvFDrresdCghN mnjkUYg vfrD", 382: ?line false = os:getenv(EnvVar1), 383: ?line true = os:putenv(EnvVar1, "mors"), 384: ?line "mors" = os:getenv(EnvVar1), 385: ?line true = os:putenv(EnvVar1, ""), 386: ?line case os:getenv(EnvVar1) of 387: "" -> ?line ok; 388: false -> ?line ok; 389: BadVal -> ?line ?t:fail(BadVal) 390: end, 391: true = os:putenv(EnvVar1, "mors"), 392: true = os:unsetenv(EnvVar1), 393: false = os:getenv(EnvVar1), 394: true = os:unsetenv(EnvVar1), % unset unset variable 395: %% os:putenv, os:getenv and os:unsetenv currently use a temp 396: %% buffer of size 1024 for storing key+value 397: ?line os_env_long(1010, 1030, "hej hopp"). 398: 399: os_env_long(Min, Max, _Value) when Min > Max -> 400: ?line ok; 401: os_env_long(Min, Max, Value) -> 402: ?line EnvVar = lists:duplicate(Min, $X), 403: ?line true = os:putenv(EnvVar, Value), 404: ?line Value = os:getenv(EnvVar), 405: true = os:unsetenv(EnvVar), 406: ?line os_env_long(Min+1, Max, Value). 407: 408: otp_7526(doc) -> 409: ["Test that string:to_integer does not Halloc in wrong order."]; 410: otp_7526(Config) when is_list(Config) -> 411: ok = test_7526(256). 412: 413: iterate_7526(0, Acc) -> Acc; 414: iterate_7526(N, Acc) -> 415: iterate_7526(N - 1, 416: [case string:to_integer("9223372036854775808,\n") of 417: {Int, _Foo} -> Int 418: end | Acc]). 419: 420: do_test_7526(N,M) -> 421: {Self, Ref} = {self(), make_ref()}, 422: T = erlang:make_tuple(M,0), 423: spawn_opt(fun()-> 424: L = iterate_7526(N, []), 425: BadList = [X || X <- L, X =/= 9223372036854775808], 426: BadLen = length(BadList), 427: M = length(tuple_to_list(T)), 428: %%io:format("~b bad conversions: ~p~n", [BadLen, BadList]), 429: Self ! {done, Ref, BadLen} 430: end, 431: [link,{fullsweep_after,0}]), 432: receive {done, Ref, Len} -> Len end. 433: 434: 435: test_7526(0) -> 436: ok; 437: test_7526(N) -> 438: case do_test_7526(1000,N) of 439: 0 -> test_7526(N-1); 440: Other -> 441: {error,N,Other} 442: end. 443: 444: -define(BADARG(E), {'EXIT',{badarg,_}} = (catch E)). 445: -define(SYS_LIMIT(E), {'EXIT',{system_limit,_}} = (catch E)). 446: 447: binary_to_atom(Config) when is_list(Config) -> 448: HalfLong = lists:seq(0, 127), 449: HalfLongAtom = list_to_atom(HalfLong), 450: HalfLongBin = list_to_binary(HalfLong), 451: Long = lists:seq(0, 254), 452: LongAtom = list_to_atom(Long), 453: LongBin = list_to_binary(Long), 454: 455: %% latin1 456: ?line '' = test_binary_to_atom(<<>>, latin1), 457: ?line '\377' = test_binary_to_atom(<<255>>, latin1), 458: ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, latin1), 459: ?line LongAtom = test_binary_to_atom(LongBin, latin1), 460: 461: %% utf8 462: ?line '' = test_binary_to_atom(<<>>, utf8), 463: ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, utf8), 464: ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, unicode), 465: ?line [] = [C || C <- lists:seq(128, 255), 466: begin 467: list_to_atom([C]) =/= 468: test_binary_to_atom(<<C/utf8>>, utf8) 469: end], 470: 471: %% badarg failures. 472: ?line fail_binary_to_atom(atom), 473: ?line fail_binary_to_atom(42), 474: ?line fail_binary_to_atom({a,b,c}), 475: ?line fail_binary_to_atom([1,2,3]), 476: ?line fail_binary_to_atom([]), 477: ?line fail_binary_to_atom(42.0), 478: ?line fail_binary_to_atom(self()), 479: ?line fail_binary_to_atom(make_ref()), 480: ?line fail_binary_to_atom(<<0:7>>), 481: ?line fail_binary_to_atom(<<42:13>>), 482: ?line ?BADARG(binary_to_atom(id(<<>>), blurf)), 483: ?line ?BADARG(binary_to_atom(id(<<>>), [])), 484: 485: %% Bad UTF8 sequences. 486: ?line ?BADARG(binary_to_atom(id(<<255>>), utf8)), 487: ?line ?BADARG(binary_to_atom(id(<<255,0>>), utf8)), 488: ?line ?BADARG(binary_to_atom(id(<<16#C0,16#80>>), utf8)), %Overlong 0. 489: ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || 490: C <- lists:seq(256, 16#D7FF)], 491: ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || 492: C <- lists:seq(16#E000, 16#FFFD)], 493: ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || 494: C <- lists:seq(16#10000, 16#8FFFF)], 495: ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || 496: C <- lists:seq(16#90000, 16#10FFFF)], 497: 498: %% system_limit failures. 499: ?line ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255>>), utf8)), 500: ?line ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255,0>>), utf8)), 501: ?line ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, latin1)), 502: ?line ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, latin1)), 503: ?line ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, latin1)), 504: ?line ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, utf8)), 505: ?line ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, utf8)), 506: ?line ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, utf8)), 507: ok. 508: 509: test_binary_to_atom(Bin0, Encoding) -> 510: Res = binary_to_atom(Bin0, Encoding), 511: Res = binary_to_existing_atom(Bin0, Encoding), 512: Bin1 = id(<<7:3,Bin0/binary,32:5>>), 513: Sz = byte_size(Bin0), 514: <<_:3,UnalignedBin:Sz/binary,_:5>> = Bin1, 515: Res = binary_to_atom(UnalignedBin, Encoding). 516: 517: fail_binary_to_atom(Bin) -> 518: try 519: binary_to_atom(Bin, latin1) 520: catch 521: error:badarg -> 522: ok 523: end, 524: try 525: binary_to_atom(Bin, utf8) 526: catch 527: error:badarg -> 528: ok 529: end, 530: try 531: binary_to_existing_atom(Bin, latin1) 532: catch 533: error:badarg -> 534: ok 535: end, 536: try 537: binary_to_existing_atom(Bin, utf8) 538: catch 539: error:badarg -> 540: ok 541: end. 542: 543: 544: binary_to_existing_atom(Config) when is_list(Config) -> 545: ?line UnlikelyBin = <<"ou0897979655678dsfj923874390867er869fds973qerueoru">>, 546: try 547: ?line binary_to_existing_atom(UnlikelyBin, latin1), 548: ?line ?t:fail() 549: catch 550: error:badarg -> ok 551: end, 552: 553: try 554: ?line binary_to_existing_atom(UnlikelyBin, utf8), 555: ?line ?t:fail() 556: catch 557: error:badarg -> ok 558: end, 559: 560: ?line UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1), 561: ?line UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1), 562: ok. 563: 564: 565: atom_to_binary(Config) when is_list(Config) -> 566: HalfLong = lists:seq(0, 127), 567: HalfLongAtom = list_to_atom(HalfLong), 568: HalfLongBin = list_to_binary(HalfLong), 569: Long = lists:seq(0, 254), 570: LongAtom = list_to_atom(Long), 571: LongBin = list_to_binary(Long), 572: 573: %% latin1 574: ?line <<>> = atom_to_binary('', latin1), 575: ?line <<"abc">> = atom_to_binary(abc, latin1), 576: ?line <<127>> = atom_to_binary('\177', latin1), 577: ?line HalfLongBin = atom_to_binary(HalfLongAtom, latin1), 578: ?line LongBin = atom_to_binary(LongAtom, latin1), 579: 580: %% utf8. 581: ?line <<>> = atom_to_binary('', utf8), 582: ?line <<>> = atom_to_binary('', unicode), 583: ?line <<127>> = atom_to_binary('\177', utf8), 584: ?line <<"abcdef">> = atom_to_binary(abcdef, utf8), 585: ?line HalfLongBin = atom_to_binary(HalfLongAtom, utf8), 586: ?line LongAtomBin = atom_to_binary(LongAtom, utf8), 587: ?line verify_long_atom_bin(LongAtomBin, 0), 588: 589: %% Failing cases. 590: ?line fail_atom_to_binary(<<1>>), 591: ?line fail_atom_to_binary(42), 592: ?line fail_atom_to_binary({a,b,c}), 593: ?line fail_atom_to_binary([1,2,3]), 594: ?line fail_atom_to_binary([]), 595: ?line fail_atom_to_binary(42.0), 596: ?line fail_atom_to_binary(self()), 597: ?line fail_atom_to_binary(make_ref()), 598: ?line ?BADARG(atom_to_binary(id(a), blurf)), 599: ?line ?BADARG(atom_to_binary(id(b), [])), 600: ok. 601: 602: verify_long_atom_bin(<<I/utf8,T/binary>>, I) -> 603: verify_long_atom_bin(T, I+1); 604: verify_long_atom_bin(<<>>, 255) -> ok. 605: 606: fail_atom_to_binary(Term) -> 607: try 608: atom_to_binary(Term, latin1) 609: catch 610: error:badarg -> 611: ok 612: end, 613: try 614: atom_to_binary(Term, utf8) 615: catch 616: error:badarg -> 617: ok 618: end. 619: 620: min_max(Config) when is_list(Config) -> 621: ?line a = erlang:min(id(a), a), 622: ?line a = erlang:min(id(a), b), 623: ?line a = erlang:min(id(b), a), 624: ?line b = erlang:min(id(b), b), 625: ?line a = erlang:max(id(a), a), 626: ?line b = erlang:max(id(a), b), 627: ?line b = erlang:max(id(b), a), 628: ?line b = erlang:max(id(b), b), 629: 630: ?line 42.0 = erlang:min(42.0, 42), 631: ?line 42.0 = erlang:max(42.0, 42), 632: %% And now (R14) they are also autoimported! 633: ?line a = min(id(a), a), 634: ?line a = min(id(a), b), 635: ?line a = min(id(b), a), 636: ?line b = min(id(b), b), 637: ?line a = max(id(a), a), 638: ?line b = max(id(a), b), 639: ?line b = max(id(b), a), 640: ?line b = max(id(b), b), 641: 642: ?line 42.0 = min(42.0, 42), 643: ?line 42.0 = max(42.0, 42), 644: 645: ok. 646: 647: 648: 649: erlang_halt(Config) when is_list(Config) -> 650: try erlang:halt(undefined) of 651: _-> ?t:fail({erlang,halt,{undefined}}) 652: catch error:badarg -> ok end, 653: try halt(undefined) of 654: _-> ?t:fail({halt,{undefined}}) 655: catch error:badarg -> ok end, 656: try erlang:halt(undefined, []) of 657: _-> ?t:fail({erlang,halt,{undefined,[]}}) 658: catch error:badarg -> ok end, 659: try halt(undefined, []) of 660: _-> ?t:fail({halt,{undefined,[]}}) 661: catch error:badarg -> ok end, 662: try halt(0, undefined) of 663: _-> ?t:fail({halt,{0,undefined}}) 664: catch error:badarg -> ok end, 665: try halt(0, [undefined]) of 666: _-> ?t:fail({halt,{0,[undefined]}}) 667: catch error:badarg -> ok end, 668: try halt(0, [{undefined,true}]) of 669: _-> ?t:fail({halt,{0,[{undefined,true}]}}) 670: catch error:badarg -> ok end, 671: try halt(0, [{flush,undefined}]) of 672: _-> ?t:fail({halt,{0,[{flush,undefined}]}}) 673: catch error:badarg -> ok end, 674: try halt(0, [{flush,true,undefined}]) of 675: _-> ?t:fail({halt,{0,[{flush,true,undefined}]}}) 676: catch error:badarg -> ok end, 677: H = hostname(), 678: {ok,N1} = slave:start(H, halt_node1), 679: {badrpc,nodedown} = rpc:call(N1, erlang, halt, []), 680: {ok,N2} = slave:start(H, halt_node2), 681: {badrpc,nodedown} = rpc:call(N2, erlang, halt, [0]), 682: {ok,N3} = slave:start(H, halt_node3), 683: {badrpc,nodedown} = rpc:call(N3, erlang, halt, [0,[]]), 684: ok. 685: 686: 687: 688: %% Helpers 689: 690: id(I) -> I. 691: 692: %% Get code path, including the path for the erts application. 693: get_code_path() -> 694: case code:lib_dir(erts) of 695: {error,bad_name} -> 696: Erts = filename:join([code:root_dir(),"erts","preloaded","ebin"]), 697: [Erts|code:get_path()]; 698: _ -> 699: code:get_path() 700: end. 701: 702: which(Mod, Path) -> 703: which_1(atom_to_list(Mod) ++ ".beam", Path). 704: 705: which_1(Base, [D|Ds]) -> 706: Path = filename:join(D, Base), 707: case filelib:is_regular(Path) of 708: true -> Path; 709: false -> which_1(Base, Ds) 710: end. 711: print_mfa({M,F,A}) -> 712: io:format("~p:~p/~p", [M,F,A]). 713: 714: extract_abstract(Mod, Path) -> 715: Beam = which(Mod, Path), 716: {ok,{Mod,[{abstract_code,{raw_abstract_v1,Abstr}}]}} = 717: beam_lib:chunks(Beam, [abstract_code]), 718: {Mod,Abstr}. 719: 720: 721: hostname() -> 722: hostname(atom_to_list(node())). 723: 724: hostname([$@ | Hostname]) -> 725: list_to_atom(Hostname); 726: hostname([_C | Cs]) -> 727: hostname(Cs).