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.