1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2000-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(bs_construct_SUITE).
   21: 
   22: %% Copied from bs_construct_SUITE in the emulator test suite.
   23: %% The following test cases have been omitted since they don't
   24: %% make much sense for the debugger:
   25: %%  bs_add
   26: %%  kostis
   27: 
   28: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
   29: 	 init_per_testcase/2,end_per_testcase/2,
   30: 	 init_per_suite/1,end_per_suite/1,
   31: 	 test1/1, test2/1, test3/1, test4/1, test5/1, testf/1,
   32: 	 not_used/1, in_guard/1,
   33: 	 mem_leak/1, coerce_to_float/1, bjorn/1,
   34: 	 huge_float_field/1, huge_binary/1, system_limit/1, badarg/1,
   35: 	 copy_writable_binary/1, dynamic/1,
   36: 	 otp_7422/1, zero_width/1]).
   37: 
   38: -include_lib("test_server/include/test_server.hrl").
   39: 
   40: suite() -> [{ct_hooks,[ts_install_cth]}].
   41: 
   42: all() -> 
   43:     [test1, test2, test3, test4, test5, testf, not_used,
   44:      in_guard, mem_leak, coerce_to_float, bjorn,
   45:      huge_float_field, huge_binary, system_limit, badarg,
   46:      copy_writable_binary, dynamic, otp_7422, zero_width].
   47: 
   48: groups() -> 
   49:     [].
   50: 
   51: init_per_group(_GroupName, Config) ->
   52:     Config.
   53: 
   54: end_per_group(_GroupName, Config) ->
   55:     Config.
   56: 
   57: init_per_testcase(_Case, Config) ->
   58:     test_lib:interpret(?MODULE),
   59:     Dog = test_server:timetrap(?t:minutes(15)),
   60:     [{watchdog,Dog}|Config].
   61: 
   62: end_per_testcase(_Case, Config) ->
   63:     Dog = ?config(watchdog, Config),
   64:     ?t:timetrap_cancel(Dog),
   65:     ok.
   66: 
   67: init_per_suite(Config) when is_list(Config) ->
   68:     ?line test_lib:interpret(?MODULE),
   69:     ?line true = lists:member(?MODULE, int:interpreted()),
   70:     Config.
   71: 
   72: end_per_suite(Config) when is_list(Config) ->
   73:     ok.
   74: 
   75: big(1) ->
   76:     57285702734876389752897683.
   77: 
   78: i(X) -> X.
   79: 
   80: r(L) ->
   81:     lists:reverse(L).
   82: 
   83: -define(T(B, L), {B, ??B, L}).
   84: -define(N(B), {B, ??B, unknown}).
   85: 
   86: -define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])).
   87: 
   88: -define(FAIL_VARS(Expr, Vars), ?line fail_check(catch Expr, ??Expr, Vars)).
   89: 
   90: l(I_13, I_big1) ->
   91:     [
   92:      ?T(<<-43>>,
   93: 	[256-43]),
   94:      ?T(<<56>>,
   95: 	[56]),
   96:      ?T(<<1,2>>,
   97: 	[1, 2]),
   98:      ?T(<<4:4, 7:4>>,
   99: 	[4*16+7]),
  100:      ?T(<<777:16/big>>,
  101: 	[3, 9]),
  102:      ?T(<<777:16/little>>,
  103: 	[9, 3]),
  104:      ?T(<<0.0:32/float>>,
  105: 	[0,0,0,0]),
  106:      ?T(<<0.125:32/float>>,
  107: 	[62,0,0,0]),
  108:      ?T(<<0.125:32/little-float>>,
  109: 	[0,0,0,62]),
  110:      ?T(<<I_big1:32>>,
  111: 	[138, 99, 0, 147]),
  112:      ?T(<<57285702734876389752897684:32>>,
  113: 	[138, 99, 0, 148]),
  114:      ?T(<<I_big1:32/little>>,
  115: 	r([138, 99, 0, 147])),
  116:      ?T(<<-1:17/unit:8>>,
  117: 	lists:duplicate(17, 255)),
  118: 
  119:      ?T(<<I_13>>,
  120: 	[13]),
  121: 
  122:      ?T(<<4:8/unit:2,5:2/unit:8>>,
  123: 	[0, 4, 0, 5]),
  124: 
  125:      ?T(<<1:1, 0:6, 1:1>>,
  126: 	[129]),
  127:      ?T(<<1:1/little, 0:6/little, 1:1/little>>,
  128: 	[129]),
  129: 
  130:      ?T(<<<<1,2>>/binary>>,
  131: 	[1, 2]),
  132:      ?T(<<<<1,2>>:1/binary>>,
  133: 	[1]),
  134:      ?T(<<4,3,<<1,2>>:1/binary>>,
  135: 	[4,3,1]),
  136: 
  137:      ?T(<<(256*45+47)>>,
  138: 	[47]),
  139: 
  140:      ?T(<<57:0>>,
  141: 	[]),
  142: 
  143:      ?T(<<"apa">>,
  144: 	"apa"),
  145: 
  146:      ?T(<<1:3,"string",9:5>>,
  147: 	[46,110,142,77,45,204,233]),
  148: 
  149:      ?T(<<>>,
  150: 	[]),
  151: 
  152:      ?T(<<37.98:64/native-float>>,
  153: 	native_3798()),
  154: 
  155:      ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>,
  156: 	native_bignum()),
  157: 
  158:      %% Unit tests.
  159:      ?T(<<<<5:3>>/bitstring>>, <<5:3>>),
  160:      ?T(<<42,<<7:4>>/binary-unit:4>>, <<42,7:4>>),
  161:      ?T(<<<<344:17>>/binary-unit:17>>, <<344:17>>),
  162:      ?T(<<<<42,3,7656:16>>/binary-unit:16>>, <<42,3,7656:16>>)
  163: 
  164:      ].
  165: 
  166: native_3798() ->
  167:     case <<1:16/native>> of
  168: 	<<0,1>> -> [64,66,253,112,163,215,10,61];
  169: 	<<1,0>> -> [61,10,215,163,112,253,66,64]
  170:     end.
  171: 
  172: native_bignum() ->
  173:     case <<1:16/native>> of
  174: 	<<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217];
  175: 	<<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129]
  176:     end.
  177: 
  178: evaluate(Str, Vars) ->
  179:     {ok,Tokens,_} =
  180: 	erl_scan:string(Str ++ " . "),
  181:     {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
  182:     case erl_eval:expr(Expr, Vars) of
  183: 	{value, Result, _} ->
  184: 	    Result
  185:     end.
  186: 
  187: eval_list([], _Vars) ->
  188:     [];
  189: eval_list([{C_bin, Str, Bytes} | Rest], Vars) ->
  190:     case catch evaluate(Str, Vars) of
  191: 	{'EXIT', Error} ->
  192: 	    io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]),
  193: 	    exit(Error);
  194: 	E_bin ->
  195: 	    [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)]
  196:     end.
  197: 
  198: one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
  199:     io:format("  ~s, ~p~n", [Str, Bytes]),
  200:     Bin = list_to_binary(Bytes),
  201:     if
  202: 	C_bin == Bin ->
  203: 	    ok;
  204: 	true ->
  205: 	    io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n",
  206: 		      [Str, Bytes, binary_to_list(C_bin)]),
  207: 	    test_server:fail(comp)
  208:     end,
  209:     if
  210: 	E_bin == Bin ->
  211: 	    ok;
  212: 	true ->
  213: 	    io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n",
  214: 		      [Str, Bytes, binary_to_list(E_bin)]),
  215: 	    test_server:fail(comp)
  216:     end;
  217: one_test({C_bin, E_bin, Str, Result}) ->
  218:     io:format("  ~s ~p~n", [Str, C_bin]),
  219:     if
  220: 	C_bin == E_bin ->
  221: 	    ok;
  222: 	true ->
  223: 	    Arbitrary = case Result of
  224: 			    unknown ->
  225: 				size(C_bin);
  226: 			    _ ->
  227: 				Result
  228: 			end,
  229: 	    case equal_lists(binary_to_list(C_bin),
  230: 			     binary_to_list(E_bin),
  231: 			     Arbitrary) of
  232: 		false ->
  233: 		    io:format("ERROR: Compiled not equal to interpreted:"
  234: 			      "~n ~p, ~p.~n",
  235: 			      [binary_to_list(C_bin), binary_to_list(E_bin)]),
  236: 		    test_server:fail(comp);
  237: 		0 ->
  238: 		    ok;
  239: 		%% For situations where the final bits may not matter, like
  240: 		%% for floats:
  241: 		N when is_integer(N) ->
  242: 		    io:format("Info: compiled and interpreted differ in the"
  243: 			      " last bytes:~n ~p, ~p.~n",
  244: 			      [binary_to_list(C_bin), binary_to_list(E_bin)]),
  245: 		    ok
  246: 	    end
  247:     end.
  248: 
  249: equal_lists([], [], _) ->
  250:     0;
  251: equal_lists([], _, _) ->
  252:     false;
  253: equal_lists(_, [], _) ->
  254:     false;
  255: equal_lists([A|AR], [A|BR], R) ->
  256:     equal_lists(AR, BR, R);
  257: equal_lists(A, B, R) ->
  258:     if
  259: 	length(A) /= length(B) ->
  260: 	    false;
  261: 	length(A) =< R ->
  262: 	    R;
  263: 	true ->
  264: 	    false
  265:     end.
  266: 
  267: fail_check({'EXIT',{badarg,_}}, Str, Vars) ->
  268:     try	evaluate(Str, Vars) of
  269: 	Res ->
  270: 	    io:format("Interpreted result: ~p", [Res]),
  271: 	    ?t:fail(did_not_fail_in_intepreted_code)
  272:     catch
  273: 	error:badarg ->
  274: 	    ok
  275:     end;
  276: fail_check(Res, _, _) ->
  277:     io:format("Compiled result: ~p", [Res]),
  278:     ?t:fail(did_not_fail_in_compiled_code).
  279: 
  280: %%% Simple working cases
  281: test1(suite) -> [];
  282: test1(Config) when is_list(Config) ->
  283:     ?line I_13 = i(13),
  284:     ?line I_big1 = big(1),
  285:     ?line Vars = [{'I_13', I_13},
  286: 		  {'I_big1', I_big1}],
  287:     ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)).
  288: 
  289: %%% Misc
  290: 
  291: %%% <<A:S, A:(N-S)>>
  292: comp(N, A, S) ->
  293:     M1 = (1 bsl S) - 1,
  294:     M2 = (1 bsl (N-S)) - 1,
  295:     [((A band M1) bsl (N-S)) bor (A band M2)].
  296: 
  297: gen(N, S, A) ->
  298:     [?T(<<A:S, A:(N-S)>>, comp(N, A, S))].
  299: 
  300: gen_l(N, S, A) ->
  301:     [?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))].
  302: 
  303: test2(suite) -> [];
  304: test2(Config) when is_list(Config) ->
  305:     ?line test2(0, 8, 2#10101010101010101),
  306:     ?line test2(0, 8, 2#1111111111).
  307: 
  308: test2(End, End, _) ->
  309:     ok;
  310: test2(I, End, A) ->
  311:     test2(I, A),
  312:     test2(I+1, End, A).
  313: 
  314: test2(S, A) ->
  315:     N = 8,
  316:     Vars = [{'A',A}, {'N',N}, {'S',S}],
  317:     io:format("Vars: ~p\n", [Vars]),
  318:     lists:foreach(fun one_test/1, eval_list(gen(N, S, A), Vars)),
  319:     lists:foreach(fun one_test/1, eval_list(gen_l(N, S, A), Vars)).
  320: 
  321: %%% Tests without facit
  322: 
  323: t3() ->
  324:     [?N(<<4711:13, 9876:13, 3:6>>),
  325:      ?N(<<4.57:64/float>>),
  326:      ?N(<<4.57:32/float>>),
  327: 
  328:      ?N(<<>>)
  329:     ].
  330: 
  331: test3(suite) -> [];
  332: test3(Config) when is_list(Config) ->
  333:     ?line Vars = [],
  334:     ?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)).
  335: 
  336: gen_u(N, S, A) ->
  337:     [?N(<<A:S, A:(N-S)>>)].
  338: 
  339: gen_u_l(N, S, A) ->
  340:     [?N(<<A:S/little, A:(N-S)/little>>)].
  341: 
  342: test4(suite) -> [];
  343: test4(Config) when is_list(Config) ->
  344:     ?line test4(0, 16, 2#10101010101010101),
  345:     ?line test4(0, 16, 2#1111111111).
  346: 
  347: test4(End, End, _) ->
  348:     ok;
  349: test4(I, End, A) ->
  350:     test4(I, A),
  351:     test4(I+1, End, A).
  352: 
  353: test4(S, A) ->
  354:     N = 16,
  355:     Vars = [{'A', A}, {'N', 16}, {'S', S}],
  356:     lists:foreach(fun one_test/1, eval_list(gen_u(N, S, A), Vars)),
  357:     lists:foreach(fun one_test/1, eval_list(gen_u_l(N, S, A), Vars)).
  358: 
  359: gen_b(N, S, A) ->
  360:     [?T(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>,
  361: 	binary_to_list(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>))].
  362: 
  363: test5(suite) -> [];
  364: test5(doc) -> ["OTP-3995"];
  365: test5(Config) when is_list(Config) ->
  366:     ?line test5(0, 8, <<73>>),
  367:     ?line test5(0, 8, <<68>>).
  368: 
  369: test5(End, End, _) ->
  370:     ok;
  371: test5(I, End, A) ->
  372:     test5(I, A),
  373:     test5(I+1, End, A).
  374: 
  375: test5(S, A) ->
  376:     N = 8,
  377:     Vars = [{'A', A}, {'N', 8}, {'S', S}],
  378:     lists:foreach(fun one_test/1, eval_list(gen_b(N, S, A), Vars)).
  379: 
  380: %%% Failure cases
  381: testf(suite) -> [];
  382: testf(Config) when is_list(Config) ->
  383:     ?line ?FAIL(<<3.14>>),
  384:     ?line ?FAIL(<<<<1,2>>>>),
  385: 
  386:     ?line ?FAIL(<<2.71/binary>>),
  387:     ?line ?FAIL(<<24334/binary>>),
  388:     ?line ?FAIL(<<24334344294788947129487129487219847/binary>>),
  389:     BigInt = id(24334344294788947129487129487219847),
  390:     ?line ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]),
  391:     ?line ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]),
  392:     ?line ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]),
  393: 
  394:     %% One negative field size, but the sum of field sizes will be 1 byte.
  395:     %% Make sure that we reject that properly.
  396:     I_minus_777 = id(-777),
  397:     I_minus_2047 = id(-2047),
  398:     ?line ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>,
  399: 		     ordsets:from_list([{'I_minus_777',I_minus_777},
  400: 					{'I_minus_2047',I_minus_2047}])),
  401:     ?line ?FAIL(<<<<1,2,3>>/float>>),
  402: 
  403:     %% Negative field widths.
  404:     ?line testf_1(-8, <<1,2,3,4,5>>),
  405:     ?line ?FAIL(<<0:(-(1 bsl 100))>>),
  406: 
  407:     ?line ?FAIL(<<42:(-16)>>),
  408:     ?line ?FAIL(<<3.14:(-8)/float>>),
  409:     ?line ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
  410:     ?line ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
  411:     ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
  412:     ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
  413: 
  414:     %% Unit failures.
  415:     ?line ?FAIL(<<<<1:1>>/binary>>),
  416:     Sz = id(1),
  417:     ?line ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]),
  418:     ?line {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>),
  419:     ?line ?FAIL(<<<<7,8,9>>/binary-unit:16>>),
  420:     ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>),
  421:     ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>),
  422: 
  423:     ok.
  424: 
  425: testf_1(W, B) ->
  426:     Vars = [{'W',W}],
  427:     ?FAIL_VARS(<<42:W>>, Vars),
  428:     ?FAIL_VARS(<<3.14:W/float>>, Vars),
  429:     ?FAIL_VARS(<<B:W/binary>>, [{'B',B}|Vars]).
  430: 
  431: not_used(doc) ->
  432:     "Test that constructed binaries that are not used will still give an exception.";
  433: not_used(Config) when is_list(Config) ->
  434:     ?line ok = not_used1(3, <<"dum">>),
  435:     ?line {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")),
  436:     ?line {'EXIT',{badarg,_}} = (catch not_used2(444, -2)),
  437:     ?line {'EXIT',{badarg,_}} = (catch not_used2(444, anka)),
  438:     ?line {'EXIT',{badarg,_}} = (catch not_used3(444)),
  439:     ok.
  440: 
  441: not_used1(I, BinString) ->
  442:     <<I:32,BinString/binary>>,
  443:     ok.
  444: 
  445: not_used2(I, Sz) ->
  446:     <<I:Sz>>,
  447:     ok.
  448: 
  449: not_used3(I) ->
  450:     <<I:(-8)>>,
  451:     ok.
  452: 
  453: in_guard(Config) when is_list(Config) ->
  454:     ?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5),
  455:     ?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>),
  456:     ?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415),
  457:     ?line 3 = in_guard(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3),
  458:     ?line 3 = in_guard(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226),
  459:     nope = in_guard(<<1>>, 42, b),
  460:     nope = in_guard(<<1>>, a, b),
  461:     nope = in_guard(<<1,2>>, 1, 1),
  462:     nope = in_guard(<<4,5>>, 1, 2.71),
  463:     nope = in_guard(<<4,5>>, 1, <<12,13>>),
  464:     ok.
  465: 
  466: in_guard(Bin, A, B) when <<A:13,B:3>> == Bin -> 1;
  467: in_guard(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2;
  468: in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3;
  469: in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen;
  470: in_guard(_, _, _) -> nope.
  471: 
  472: mem_leak(doc) -> "Make sure that construction has no memory leak";
  473: mem_leak(Config) when is_list(Config) ->
  474:     ?line B = make_bin(16, <<0>>),
  475:     ?line mem_leak(1024, B),
  476:     ok.
  477: 
  478: mem_leak(0, _) -> ok;
  479: mem_leak(N, B) ->
  480:     ?line big_bin(B, <<23>>),
  481:     ?line {'EXIT',{badarg,_}} = (catch big_bin(B, bad)),
  482:     mem_leak(N-1, B).
  483: 
  484: big_bin(B1, B2) ->
  485:     <<B1/binary,B1/binary,B1/binary,B1/binary,
  486:       B1/binary,B1/binary,B1/binary,B1/binary,
  487:       B1/binary,B1/binary,B1/binary,B1/binary,
  488:       B1/binary,B1/binary,B1/binary,B1/binary,
  489:       B2/binary>>.
  490: 
  491: make_bin(0, Acc) -> Acc;
  492: make_bin(N, Acc) -> make_bin(N-1, <<Acc/binary,Acc/binary>>).
  493: 
  494: -define(COF(Int0),
  495: 	?line (fun(Int) ->
  496: 		       true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
  497: 		       true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
  498: 			   end)(nonliteral(Int0)),
  499: 	?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>,
  500: 	?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
  501: 
  502: -define(COF64(Int0),
  503: 	?line (fun(Int) ->
  504: 		       true = <<Int:64/float>> =:= <<(float(Int)):64/float>>
  505: 			   end)(nonliteral(Int0)),
  506: 	?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>).
  507: 
  508: nonliteral(X) -> X.
  509: 
  510: coerce_to_float(Config) when is_list(Config) ->
  511:     ?COF(0),
  512:     ?COF(-1),
  513:     ?COF(1),
  514:     ?COF(42),
  515:     ?COF(255),
  516:     ?COF(-255),
  517:     ?COF(38474),
  518:     ?COF(387498738948729893849444444443),
  519:     ?COF(-37489378937773899999999999999993),
  520:     ?COF64(298748888888888888888888888883478264866528467367364766666666666666663),
  521:     ?COF64(-367546729879999999999947826486652846736736476555566666663),
  522:     ok.
  523: 
  524: bjorn(Config) when is_list(Config) ->
  525:     ?line error = bjorn_1(),
  526:     ok.
  527: 
  528: bjorn_1() ->
  529:     Bitstr = <<7:13>>,
  530:     try
  531: 	do_something()
  532:     catch
  533: 	throw:blurf ->
  534: 	    ignore
  535:     end,
  536:     do_more(Bitstr, 13).
  537: 
  538: do_more(Bin, Sz) ->
  539:     %% Previous bug in the bs_bits_to_bytes instruction: The exeption code
  540:     %% was not set - the previous exception (throw:blurf) would be used,
  541:     %% causing the catch to slip.
  542:     try <<Bin:Sz/binary>> of
  543: 	_V -> ok
  544:     catch
  545: 	error:_ ->
  546: 	    error
  547:     end.
  548: 
  549: do_something() ->
  550:     throw(blurf).
  551: 
  552: huge_float_field(Config) when is_list(Config) ->
  553:     ?line {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>),
  554:     ?line huge_float_check(catch <<0.0:67108865/float-unit:64>>),
  555:     ?line huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>),
  556:     ?line huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>),
  557: %%  ?line huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>),
  558:     ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>),
  559: %%  ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>),
  560:     ok.
  561: 
  562: huge_float_check({'EXIT',{system_limit,_}}) -> ok;
  563: huge_float_check({'EXIT',{badarg,_}}) -> ok.
  564: 
  565: huge_binary(Config) when is_list(Config) ->
  566:     ?line 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>),
  567:     ok.
  568: 
  569: system_limit(Config) when is_list(Config) ->
  570:     WordSize = erlang:system_info(wordsize),
  571:     BitsPerWord = WordSize * 8,
  572:     ?line {'EXIT',{system_limit,_}} =
  573: 	(catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>),
  574:     ?line {'EXIT',{system_limit,_}} =
  575: 	(catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>),
  576:     ?line {'EXIT',{system_limit,_}} =
  577: 	(catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>),
  578: 
  579:     case WordSize of
  580: 	4 ->
  581: 	    system_limit_32();
  582: 	8 ->
  583: 	    ok
  584:     end.
  585: 
  586: system_limit_32() ->
  587:     ?line {'EXIT',{badarg,_}} = (catch <<42:(-1)>>),
  588:     ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>),
  589:     ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>),
  590:     ?line {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>),
  591:     ?line {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>),
  592:     ?line {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
  593:     ?line {'EXIT',{system_limit,_}} =
  594: 	(catch <<0:(id(8)),42:(id(536870912))/unit:8>>),
  595:     ok.
  596: 
  597: badarg(Config) when is_list(Config) ->
  598:     %% BEAM will generate a badarg exception for:
  599:     %%   <<0:(id(1 bsl 100)),0:(id(-1))>>
  600:     %% but the debugger will generate a system_limit exception.
  601:     %% It does not seems worthwhile to fix the debugger.
  602: 
  603:     ?line {'EXIT',{badarg,_}} =
  604: 	(catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>),
  605: 
  606:     ok.
  607: 
  608: copy_writable_binary(Config) when is_list(Config) ->
  609:     ?line [copy_writable_binary_1(I) || I <- lists:seq(0, 256)],
  610:     ok.
  611: 
  612: copy_writable_binary_1(_) ->
  613:     ?line Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>,
  614:     ?line SubBin = make_sub_bin(Bin0),
  615:     ?line id(<<42,34,55,Bin0/binary>>),		%Make reallocation likelier.
  616:     ?line Pid = spawn(fun() ->
  617: 			      copy_writable_binary_holder(Bin0, SubBin)
  618: 		      end),
  619:     ?line Tab = ets:new(holder, []),
  620:     ?line ets:insert(Tab, {17,Bin0}),
  621:     ?line ets:insert(Tab, {42,SubBin}),
  622:     ?line id(<<Bin0/binary,0:(64*1024*8)>>),
  623:     ?line Pid ! self(),
  624:     ?line [{17,Bin0}] = ets:lookup(Tab, 17),
  625:     ?line [{42,Bin0}] = ets:lookup(Tab, 42),
  626:     receive
  627: 	{Pid,Bin0,Bin0} -> ok;
  628: 	Other ->
  629: 	    io:format("Unexpected message: ~p", [Other]),
  630: 	    ?line ?t:fail()
  631:     end,
  632:     ok.
  633: 
  634: copy_writable_binary_holder(Bin, SubBin) ->
  635:     receive
  636: 	Pid ->
  637: 	    Pid ! {self(),Bin,SubBin}
  638:     end.
  639: 
  640: make_sub_bin(Bin0) ->
  641:     N = bit_size(Bin0),
  642:     <<_:17,Bin:N/bitstring,_:5>> = <<(-1):17,Bin0/bitstring,(-1):5>>,
  643:     Bin = Bin0,					%Assertion.
  644:     Bin.
  645: 
  646: %% Test that different ways of using bit syntax instructions
  647: %% give the same result.
  648: 
  649: dynamic(Config) when is_list(Config) ->
  650:     ?line dynamic_1(fun dynamic_big/5),
  651:     ?line dynamic_1(fun dynamic_little/5),
  652:     ok.
  653: 
  654: dynamic_1(Dynamic) ->
  655:     <<Lpad:128>> = erlang:md5([0]),
  656:     <<Rpad:128>> = erlang:md5([1]),
  657:     <<Int:128>> = erlang:md5([2]),
  658:     8385 = dynamic_2(0, {Int,Lpad,Rpad,Dynamic}, 0).
  659: 
  660: dynamic_2(129, _, Count) -> Count;
  661: dynamic_2(Bef, Data, Count0) ->
  662:     Count = dynamic_3(Bef, 128-Bef, Data, Count0),
  663:     dynamic_2(Bef+1, Data, Count).
  664: 
  665: dynamic_3(_, -1, _, Count) -> Count;
  666: dynamic_3(Bef, N, {Int0,Lpad,Rpad,Dynamic}=Data, Count) ->
  667:     Int1 = Int0 band ((1 bsl (N+3))-1),
  668:     Dynamic(Bef, N, Int1, Lpad, Rpad),
  669:     Dynamic(Bef, N, -Int1, Lpad, Rpad),
  670: 
  671:     %% OTP-7085: Test a small number in a wide field.
  672:     Int2 = Int0 band 16#FFFFFF,
  673:     Dynamic(Bef, N, Int2, Lpad, Rpad),
  674:     Dynamic(Bef, N, -Int2, Lpad, Rpad),
  675:     dynamic_3(Bef, N-1, Data, Count+1).
  676: 
  677: dynamic_big(Bef, N, Int, Lpad, Rpad) ->
  678:     NumBin = id(<<Int:N>>),
  679:     MaskedInt = Int band ((1 bsl N) - 1),
  680:     <<MaskedInt:N>> = NumBin,
  681: 
  682:     %% Construct the binary in two different ways.
  683:     Bin = id(<<Lpad:Bef,NumBin/bitstring,Rpad:(128-Bef-N)>>),
  684:     Bin = <<Lpad:Bef,Int:N,Rpad:(128-Bef-N)>>,
  685: 
  686:     %% Further verify the result by matching.
  687:     LpadMasked = Lpad band ((1 bsl Bef) - 1),
  688:     RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1),
  689:     Rbits = (128-Bef-N),
  690:     <<LpadMasked:Bef,MaskedInt:N,RpadMasked:Rbits>> = id(Bin),
  691:     ok.
  692: 
  693: dynamic_little(Bef, N, Int, Lpad, Rpad) ->
  694:     NumBin = id(<<Int:N/little>>),
  695:     MaskedInt = Int band ((1 bsl N) - 1),
  696:     <<MaskedInt:N/little>> = NumBin,
  697: 
  698:     %% Construct the binary in two different ways.
  699:     Bin = id(<<Lpad:Bef/little,NumBin/bitstring,Rpad:(128-Bef-N)/little>>),
  700:     Bin = <<Lpad:Bef/little,Int:N/little,Rpad:(128-Bef-N)/little>>,
  701: 
  702:     %% Further verify the result by matching.
  703:     LpadMasked = Lpad band ((1 bsl Bef) - 1),
  704:     RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1),
  705:     Rbits = (128-Bef-N),
  706:     <<LpadMasked:Bef/little,MaskedInt:N/little,RpadMasked:Rbits/little>> = id(Bin),
  707:     ok.
  708: 
  709: otp_7422(Config) when is_list(Config) ->
  710:     otp_7422_int(0),
  711:     otp_7422_bin(0).
  712: 
  713: otp_7422_int(N) when N < 512 ->
  714:     T = erlang:make_tuple(N, []),
  715:     spawn_link(fun() ->
  716: 		       id(T),
  717: 		       %% A size of field 0 would write one byte beyond
  718: 		       %% the current position in the binary. It could
  719: 		       %% overwrite the continuation pointer stored on
  720: 		       %% the stack if HTOP was equal to E (the stack pointer).
  721: 		       id(<<0:(id(0))>>)
  722: 	       end),
  723:     otp_7422_int(N+1);
  724: otp_7422_int(_) -> ok.
  725: 
  726: otp_7422_bin(N) when N < 512 ->
  727:     T = erlang:make_tuple(N, []),
  728:     Z = id(<<>>),
  729:     spawn_link(fun() ->
  730: 		       id(T),
  731: 		       id(<<Z:(id(0))/bits>>)
  732: 	       end),
  733:     otp_7422_bin(N+1);
  734: otp_7422_bin(_) -> ok.
  735: 
  736: zero_width(Config) when is_list(Config) ->
  737:     ?line Z = id(0),
  738:     Small = id(42),
  739:     Big = id(1 bsl 128),
  740:     ?line <<>> = <<Small:Z>>,
  741:     ?line <<>> = <<Small:0>>,
  742:     ?line <<>> = <<Big:Z>>,
  743:     ?line <<>> = <<Big:0>>,
  744: 
  745:     ?line {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
  746:     ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):Z>>),
  747:     ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>),
  748: 
  749:     ok.
  750: 
  751: id(I) -> I.