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).