1: %%
    2: %% %CopyrightBegin%
    3: %% 
    4: %% Copyright Ericsson AB 2006-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: %% Originally based on Per Gustafsson's test suite.
   21: %%
   22: 
   23: -module(bs_bit_binaries_no_opt_SUITE).
   24: 
   25: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   26: 	 init_per_group/2,end_per_group/2,
   27: 	 misc/1,horrid_match/1,test_bitstr/1,test_bit_size/1,asymmetric_tests/1,
   28: 	 big_asymmetric_tests/1,binary_to_and_from_list/1,
   29: 	 big_binary_to_and_from_list/1,send_and_receive/1,
   30: 	 send_and_receive_alot/1,append/1]).
   31: 
   32: -include_lib("test_server/include/test_server.hrl").
   33: 
   34: suite() -> [{ct_hooks,[ts_install_cth]}].
   35: 
   36: all() -> 
   37:     [misc, horrid_match, test_bitstr, test_bit_size,
   38:      asymmetric_tests, big_asymmetric_tests,
   39:      binary_to_and_from_list, big_binary_to_and_from_list,
   40:      send_and_receive, send_and_receive_alot, append].
   41: 
   42: groups() -> 
   43:     [].
   44: 
   45: init_per_suite(Config) ->
   46:     Config.
   47: 
   48: end_per_suite(_Config) ->
   49:     ok.
   50: 
   51: init_per_group(_GroupName, Config) ->
   52:     Config.
   53: 
   54: end_per_group(_GroupName, Config) ->
   55:     Config.
   56: 
   57: 
   58: misc(Config) when is_list(Config) ->
   59:     ?line <<1:100>> = id(<<1:100>>),
   60:     ?line {ok,ok} = {match(7),match(9)},
   61:     ?line {ok,ok} = {match1(15),match1(31)},
   62:     ok.
   63: 
   64: 
   65: match(N) ->
   66:     %% Move N to a Y register to cover another instruction.
   67:     <<0:N>> = id(<<0:N>>),
   68:     <<0:N,0:1>> = id(<<0:N,0:1>>),
   69:     ok.
   70: 
   71: match1(N) ->
   72:     %% Putting the binary inside a list will force another
   73:     %% instruction to be used.
   74:     [<<42:N/little>>] = id([<<42:N/little>>]),
   75:     ok.
   76: 
   77: test_bit_size(Config) when is_list(Config) ->
   78:     ?line 101 = bit_size(<<1:101>>),
   79:     ?line 1001 = bit_size(<<1:1001>>),
   80:     ?line 80 = bit_size(<<1:80>>),
   81:     ?line 800 = bit_size(<<1:800>>),
   82:     ?line Bin = <<0:16#1000000>>,
   83:     ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
   84:     ?line 16#10000001 = erlang:bit_size(BigBin),
   85:     %% Only run these on computers with lots of memory
   86:     %% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]),
   87:     %% 16#100000011 = bit_size(HugeBin), 
   88:     ?line 0 = bit_size(<<>>),
   89:     ok.
   90: 
   91: horrid_match(Config) when is_list(Config) ->
   92:     ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>,
   93:     ?line <<42:24/little>> = B, 
   94:     ok.
   95: 			 
   96: test_bitstr(Config) when is_list(Config) ->
   97:     ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>,
   98:     ?line <<1:1,6>> = B,
   99:     ?line B = <<1:1,6>>,
  100:   ok.
  101: 		      
  102: asymmetric_tests(Config) when is_list(Config) ->
  103:     ?line <<1:12>> = <<0,1:4>>,
  104:     ?line <<0,1:4>> = <<1:12>>,
  105:     ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>,
  106:     ?line <<1,254,0,0:1>> = X,
  107:     ?line X = <<1,254,0,0:1>>,
  108:     ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>,
  109:     ?line <<1,254,0,0:1>> = X1,
  110:     ?line X1 = <<1,254,0,0:1>>,
  111:     ok.
  112: 
  113: big_asymmetric_tests(Config) when is_list(Config) ->
  114:     ?line <<1:875,1:12>> = <<1:875,0,1:4>>,
  115:     ?line <<1:875,0,1:4>> = <<1:875,1:12>>,
  116:     ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>,
  117:     ?line <<1,254,0,0:1,1:875>> = X,
  118:     ?line X = <<1,254,0,0:1,1:875>>,
  119:     ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>,
  120:     ?line <<1,254,0,0:1,1:875>> = X1,
  121:     ?line X1 = <<1,254,0,0:1,1:875>>,
  122:   ok.
  123: 
  124: binary_to_and_from_list(Config) when is_list(Config) ->
  125:     ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)),
  126:     ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>),
  127:     ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]),
  128:     ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>),
  129:     ok.
  130:  
  131: big_binary_to_and_from_list(Config) when is_list(Config) ->
  132:     ?line <<1:800,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)),
  133:     ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>),
  134:     ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]),
  135:     ok.  
  136: 
  137: send_and_receive(Config) when is_list(Config) -> 
  138:     ?line Bin = <<1,2:7>>,
  139:     Pid = spawn_link(fun() -> receiver(Bin) end),
  140:     ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
  141:     ?line receive
  142: 	      ok ->
  143: 		  ok
  144: 	  end.
  145: 
  146: receiver(Bin) ->	 
  147:     receive
  148: 	{Pid,<<1:7,8:5,Bin/bitstring>>} ->
  149: 	    Pid ! ok
  150:   end.
  151: 	    
  152: send_and_receive_alot(Config) when is_list(Config) -> 
  153:     Bin = <<1:1000001>>,
  154:     Pid = spawn_link(fun() -> receiver_alot(Bin) end),
  155:     spamalot(100,Bin,Pid).
  156: 
  157: spamalot(N,Bin,Pid) when N > 0 ->
  158:     Pid ! {self(),<<1:7,8:5,Bin/bitstring>>},
  159:     receive
  160: 	ok ->
  161: 	    ok
  162:     end,
  163:     spamalot(N-1,Bin,Pid);
  164: spamalot(0,_Bin,Pid) ->
  165:     Pid ! no_more,
  166:     ok.
  167: 
  168: receiver_alot(Bin) ->	 
  169:     receive
  170: 	{Pid,<<1:7,8:5,Bin/bitstring>>} ->
  171: 	    Pid ! ok;
  172: 	no_more -> ok
  173:     end,
  174:     receiver_alot(Bin).
  175: 
  176: append(Config) when is_list(Config) ->
  177:     cs_init(),
  178:     ?line <<(-1):256/signed-unit:8>> = cs(do_append(id(<<>>), 256*8)),
  179:     ?line <<(-1):256/signed-unit:8>> = cs(do_append2(id(<<>>), 256*4)),
  180:     <<(-1):256/signed-unit:8>> = cs(do_append3(id(<<>>), 256*8)),
  181:     cs_end().
  182:     
  183: do_append(Bin, N) when N > 0 -> do_append(<<Bin/bits,1:1>>, N-1);
  184: do_append(Bin, 0) -> Bin.
  185: 
  186: do_append2(Bin, N) when N > 0 -> do_append2(<<Bin/binary-unit:2,3:2>>, N-1);
  187: do_append2(Bin, 0) -> Bin.
  188: 
  189: do_append3(Bin, N) when N > 0 ->
  190:     Bits = bit_size(Bin),
  191:     if
  192: 	Bits rem 2 =:= 0 ->
  193: 	    do_append3(<<Bin/binary-unit:2,1:1>>, N-1);
  194: 	Bits rem 3 =:= 0 ->
  195: 	    do_append3(<<Bin/binary-unit:3,1:1>>, N-1);
  196: 	Bits rem 4 =:= 0 ->
  197: 	    do_append3(<<Bin/binary-unit:4,1:1>>, N-1);
  198: 	Bits rem 5 =:= 0 ->
  199: 	    do_append3(<<Bin/binary-unit:5,1:1>>, N-1);
  200: 	Bits rem 6 =:= 0 ->
  201: 	    do_append3(<<Bin/binary-unit:6,1:1>>, N-1);
  202: 	Bits rem 7 =:= 0 ->
  203: 	    do_append3(<<Bin/binary-unit:7,1:1>>, N-1);
  204: 	Bits rem 8 =:= 0 ->
  205: 	    do_append3(<<Bin/binary-unit:8,1:1>>, N-1);
  206: 	Bits rem 9 =:= 0 ->
  207: 	    do_append3(<<Bin/binary-unit:9,1:1>>, N-1);
  208: 	Bits rem 10 =:= 0 ->
  209: 	    do_append3(<<Bin/binary-unit:10,1:1>>, N-1);
  210: 	Bits rem 11 =:= 0 ->
  211: 	    do_append3(<<Bin/binary-unit:11,1:1>>, N-1);
  212: 	Bits rem 12 =:= 0 ->
  213: 	    do_append3(<<Bin/binary-unit:12,1:1>>, N-1);
  214: 	Bits rem 13 =:= 0 ->
  215: 	    do_append3(<<Bin/binary-unit:13,1:1>>, N-1);
  216: 	Bits rem 14 =:= 0 ->
  217: 	    do_append3(<<Bin/binary-unit:14,1:1>>, N-1);
  218: 	Bits rem 15 =:= 0 ->
  219: 	    do_append3(<<Bin/binary-unit:15,1:1>>, N-1);
  220: 	Bits rem 16 =:= 0 ->
  221: 	    do_append3(<<Bin/binary-unit:16,1:1>>, N-1);
  222: 	Bits rem 17 =:= 0 ->
  223: 	    do_append3(<<Bin/binary-unit:17,1:1>>, N-1);
  224: 	true ->
  225: 	    do_append3(<<Bin/binary-unit:1,1:1>>, N-1)
  226:     end;
  227: do_append3(Bin, 0) -> Bin.
  228: 
  229: cs_init() ->
  230:     erts_debug:set_internal_state(available_internal_state, true),
  231:     ok.
  232: 
  233: cs_end() ->
  234:     erts_debug:set_internal_state(available_internal_state, false),
  235:     ok.
  236: 
  237: %% Verify that the allocated size is exact (rounded up to the nearest byte).
  238: cs(Bin) ->
  239:     ByteSize = byte_size(Bin),
  240:     {refc_binary,ByteSize,{binary,ByteSize},_} = 
  241: 	erts_debug:get_internal_state({binary_info,Bin}),
  242:     Bin.
  243: 
  244: id(I) -> I.