1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 1998-2013. 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(beam_SUITE).
   21: 
   22: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   23: 	 init_per_group/2,end_per_group/2, 
   24: 	 packed_registers/1, apply_last/1, apply_last_bif/1,
   25: 	 buildo_mucho/1, heap_sizes/1, big_lists/1, fconv/1,
   26: 	 select_val/1]).
   27: 
   28: -export([applied/2]).
   29: 
   30: -include_lib("test_server/include/test_server.hrl").
   31: 
   32: suite() -> [{ct_hooks,[ts_install_cth]}].
   33: 
   34: all() -> 
   35:     [packed_registers, apply_last, apply_last_bif,
   36:      buildo_mucho, heap_sizes, big_lists, select_val].
   37: 
   38: groups() -> 
   39:     [].
   40: 
   41: init_per_suite(Config) ->
   42:     Config.
   43: 
   44: end_per_suite(_Config) ->
   45:     ok.
   46: 
   47: init_per_group(_GroupName, Config) ->
   48:     Config.
   49: 
   50: end_per_group(_GroupName, Config) ->
   51:     Config.
   52: 
   53: 
   54: 
   55: %% Verify that apply(M, F, A) is really tail recursive.
   56: apply_last(Config) when is_list(Config) ->
   57:     Pid  = spawn(?MODULE, applied, [self(), 10000]),
   58:     Size =
   59: 	receive
   60: 	    {Pid, finished} ->
   61: 		stack_size(Pid)
   62: 	after 30000 ->
   63: 		?t:fail("applied/2 timed out.")
   64: 	end,
   65:     Pid ! die,
   66:     ?t:format("Size: ~p~n", [Size]),
   67:     if
   68: 	Size < 700 ->
   69: 	    ok;
   70: 	true ->
   71: 	    ?t:fail("10000 apply() grew stack too much.")
   72:     end,
   73:     ok.
   74: 
   75: stack_size(Pid) ->
   76:     {heap_size, HS}=process_info(Pid, heap_size),
   77:     {stack_size,SS}=process_info(Pid, stack_size),
   78:     HS+SS.
   79: 
   80: applied(Starter, 0) ->
   81:     Starter ! {self(), finished},
   82:     receive
   83: 	die ->
   84: 	    ok
   85:     end,
   86:     ok;
   87: applied(Starter, N) ->
   88:     apply(?MODULE, applied, [Starter, N-1]).
   89: 
   90: %% Verify that tail-recursive use of apply(M,F,A) on a Bif works."
   91: apply_last_bif(Config) when is_list(Config) ->
   92:     apply(erlang, abs, [1]).
   93: 
   94: %% Test three high register numbers in a put_list instruction
   95: %% (to test whether packing works properly).
   96: packed_registers(Config) when is_list(Config) ->
   97:     PrivDir = ?config(priv_dir, Config),
   98:     Mod = packed_regs,
   99:     Name = filename:join(PrivDir, atom_to_list(Mod) ++ ".erl"),
  100: 
  101:     %% Generate a module which generates a list of tuples.
  102:     %% put_list(A) -> [{A, 600}, {A, 999}, ... {A, 0}].
  103:     Code = gen_packed_regs(600, ["-module("++atom_to_list(Mod)++").\n",
  104: 				       "-export([put_list/1]).\n",
  105: 				       "put_list(A) ->\n["]),
  106:     ok = file:write_file(Name, Code),
  107: 
  108:     %% Compile the module.
  109:     io:format("Compiling: ~s\n", [Name]),
  110:     CompRc = compile:file(Name, [{outdir, PrivDir}, report]),
  111:     io:format("Result: ~p\n",[CompRc]),
  112:     {ok, Mod} = CompRc,
  113: 
  114:     %% Load it.
  115:     io:format("Loading...\n",[]),
  116:     LoadRc = code:load_abs(filename:join(PrivDir, atom_to_list(Mod))),
  117:     {module,_Module} = LoadRc,
  118: 
  119:     %% Call it and verify result.
  120:     Term = {a, b},
  121:     L = Mod:put_list(Term),
  122:     verify_packed_regs(L, Term, 600),
  123:     ok.
  124: 
  125: gen_packed_regs(0, Acc) ->
  126:     [Acc|"{A,0}].\n"];
  127: gen_packed_regs(N, Acc) ->
  128:     gen_packed_regs(N-1, [Acc,"{A,",integer_to_list(N)|"},\n"]).
  129: 
  130: verify_packed_regs([], _, -1) -> ok;
  131: verify_packed_regs([{Term, N}| T], Term, N) ->
  132:     verify_packed_regs(T, Term, N-1);
  133: verify_packed_regs(L, Term, N) ->
  134:     ok = io:format("Expected [{~p, ~p}|T]; got\n~p\n", [Term, N, L]),
  135:     test_server:fail().
  136: 
  137: buildo_mucho(Config) when is_list(Config) ->
  138:     buildo_mucho_1(),
  139:     ok.
  140: 
  141: buildo_mucho_1() ->
  142:     %% Thanks to Per Gustafsson, HiPE.
  143:     [{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  144:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  145:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  146:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  147:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  148:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  149:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  150:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  151:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  152:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  153:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  154:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  155:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  156:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  157:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  158:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  159:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  160:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  161:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  162:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  163:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  164:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  165:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  166:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  167:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  168:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  169:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  170:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  171:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  172:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  173:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  174:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  175:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  176:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  177:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  178:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  179:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  180:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  181:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  182:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  183:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  184:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  185:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  186:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  187:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  188:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  189:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  190:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  191:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  192:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  193:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  194:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  195:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  196:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  197:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  198:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  199:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  200:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  201:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  202:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  203:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  204:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  205:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},
  206:      {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}].
  207: 
  208: heap_sizes(Config) when is_list(Config) ->
  209:     Sizes = erlang:system_info(heap_sizes),
  210:     io:format("~p heap sizes\n", [length(Sizes)]),
  211:     io:format("~p\n", [Sizes]),
  212: 
  213:     %% Verify that heap sizes increase monotonically.
  214:     Largest = lists:foldl(fun(E, P) when is_integer(P), E > P -> E;
  215: 				   (E, []) -> E
  216: 				end, [], Sizes),
  217: 
  218:     %% Verify that the largest heap size consists of
  219:     %%  - 31 bits of bytes on 32 bits arch
  220:     %%  - atleast 52 bits of bytes (48 is the maximum virtual address)
  221:     %%    and at the most 63 bits on 64 bit archs
  222:     %% heap sizes are in words
  223:     case erlang:system_info(wordsize) of
  224: 	8 ->
  225: 	    0    = (Largest*8) bsr 63,
  226: 	    true = (Largest*8) > (1 bsl 52);
  227: 	4 ->
  228: 	    1 = (Largest*4) bsr 31
  229:     end,
  230:     ok.
  231: 
  232: %% Thanks to Igor Goryachev.
  233: 
  234: big_lists(Config) when is_list(Config) ->
  235:     b(),
  236:     ok.
  237: 
  238: a() ->
  239:     {selected,
  240:      ["uid",
  241:       "nickname",
  242:       "n_family",
  243:       "n_given",
  244:       "email_pref",
  245:       "tel_home_number",
  246:       "tel_cellular_number",
  247:       "adr_home_country",
  248:       "adr_home_locality",
  249:       "adr_home_region",
  250:       "url",
  251:       "gender",
  252:       "bday",
  253:       "constitution",
  254:       "height",
  255:       "weight",
  256:       "hair",
  257:       "routine",
  258:       "smoke",
  259:       "maritalstatus",
  260:       "children",
  261:       "independence",
  262:       "school_number",
  263:       "school_locality",
  264:       "school_title",
  265:       "school_period",
  266:       "org_orgname",
  267:       "title",
  268:       "adr_work_locality",
  269:       "photo_type",
  270:       "photo_binval"],
  271:      [{"test"}]}.
  272: 
  273: b() ->
  274:     case a() of
  275:         {selected,
  276:          ["uid",
  277:           "nickname",
  278:           "n_family",
  279:           "n_given",
  280:           "email_pref",
  281:           "tel_home_number",
  282:           "tel_cellular_number",
  283:           "adr_home_country",
  284:           "adr_home_locality",
  285:           "adr_home_region",
  286:           "url",
  287:           "gender",
  288:           "bday",
  289:           "constitution",
  290:           "height",
  291:           "weight",
  292:           "hair",
  293:           "routine",
  294:           "smoke",
  295:           "maritalstatus",
  296:           "children",
  297:           "independence",
  298:           "school_number",
  299:           "school_locality",
  300:           "school_title",
  301:           "school_period",
  302:           "org_orgname",
  303:           "title",
  304:           "adr_work_locality",
  305:           "photo_type",
  306:           "photo_binval"],
  307:          _} ->
  308: 	    ok
  309:     end.
  310: 
  311: fconv(Config) when is_list(Config) ->
  312:     do_fconv(atom),
  313:     do_fconv(nil),
  314:     do_fconv(tuple_literal),
  315:     3.0 = do_fconv(1.0, 2.0),
  316:     ok.
  317: 
  318: do_fconv(Type) ->
  319:     try
  320: 	do_fconv(Type, 1.0),
  321: 	test_server:fail()
  322:     catch
  323: 	error:badarith ->
  324: 	    ok
  325:     end.
  326: 
  327: do_fconv(atom, Float) when is_float(Float) ->
  328:     Float + a;
  329: do_fconv(nil, Float) when is_float(Float) ->
  330:     Float + [];
  331: do_fconv(tuple_literal, Float) when is_float(Float) ->
  332:     Float + {a,b}.
  333: 
  334: select_val(Config) when is_list(Config) ->
  335:     zero = do_select_val(0),
  336:     big = do_select_val(1 bsl 64),
  337:     integer = do_select_val(42),
  338:     ok.
  339: 
  340: do_select_val(X) ->
  341:     case X of
  342: 	0 ->
  343: 	    zero;
  344: 	1 bsl 64 ->
  345: 	    big;
  346: 	Int when is_integer(Int) ->
  347: 	    integer
  348:     end.