%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(binary_module_SUITE).
-export([all/0, suite/0,
interesting/1,scope_return/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1,
check_no_invalid_read_bug/1]).
-export([random_number/1, make_unaligned/1]).
-include_lib("common_test/include/ct.hrl").
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,10}}].
all() ->
[scope_return,interesting, random_ref_fla_comp, random_ref_sr_comp,
random_ref_comp, parts, bin_to_list, list_to_bin, copy,
referenced, guard, encode_decode, badargs,
longest_common_trap, check_no_invalid_read_bug].
-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
%% Test various badarg exceptions in the module.
badargs(Config) when is_list(Config) ->
badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3:3>>])),
badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3>>|<<1,2>>])),
badarg = ?MASK_ERROR(binary:compile_pattern(<<1,2,3:3>>)),
badarg = ?MASK_ERROR(binary:compile_pattern(<<>>)),
badarg = ?MASK_ERROR(binary:match(<<1,2,3:3>>,<<1>>)),
badarg = ?MASK_ERROR(binary:matches(<<1,2,3:3>>,<<1>>)),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
[{scope,{0,1},1}])),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
[{scape,{0,1}}])),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
[{scope,{0,1,1}}])),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,0,1}])),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,[0,1]}])),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
[{scope,{0.1,1}}])),
badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
[{scope,{1,1.1}}])),
badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,<<1>>,
[{scope,{16#FF,
16#FFFFFFFFFFFFFFFF}}])),
badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,<<1>>,
[{scope,{16#FFFFFFFFFFFFFFFF,
-16#7FFFFFFFFFFFFFFF-1}}])),
badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,<<1>>,
[{scope,{16#FFFFFFFFFFFFFFFF,
16#7FFFFFFFFFFFFFFF}}])),
badarg =
?MASK_ERROR(
binary:part(<<1,2,3>>,{16#FF,
16#FFFFFFFFFFFFFFFF})),
badarg =
?MASK_ERROR(
binary:part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
-16#7FFFFFFFFFFFFFFF-1})),
badarg =
?MASK_ERROR(
binary:part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
16#7FFFFFFFFFFFFFFF})),
badarg =
?MASK_ERROR(
binary:part(make_unaligned(<<1,2,3>>),{1,1,1})),
badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{1,1,1})),
badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFF,
-16#7FFFFFFFFFFFFFFF-1})),
badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FF,
16#FFFFFFFFFFFFFFFF})),
badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFF,
16#7FFFFFFFFFFFFFFF})),
badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFFFF,
-16#7FFF})),
badarg =
?MASK_ERROR(
binary_part(make_unaligned(<<1,2,3>>),{16#FF,
-16#7FFF})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{16#FF,
16#FFFFFFFFFFFFFFFF})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
-16#7FFFFFFFFFFFFFFF-1})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
16#7FFFFFFFFFFFFFFF})),
[1,2,3] =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>)),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,[])),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{1,2,3})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{1.0,1})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3>>,{1,1.0})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3:3>>,{1,1})),
badarg =
?MASK_ERROR(
binary:bin_to_list(<<1,2,3:3>>)),
badarg =
?MASK_ERROR(
binary:bin_to_list([1,2,3])),
nomatch =
?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,{0,0}}])),
badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{bm,<<>>},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,[],[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{ac,<<>>},[{scope,{0,1}}])),
{bm,BMMagic} = binary:compile_pattern([<<1,2,3>>]),
{ac,ACMagic} = binary:compile_pattern([<<1,2,3>>,<<4,5>>]),
badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{bm,ACMagic},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:match(<<1,2,3>>,{ac,BMMagic},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,
{bm,ets:match_spec_compile([{'_',[],['$_']}])},
[{scope,{0,1}}])),
badarg =
?MASK_ERROR(
binary:match(<<1,2,3>>,
{ac,ets:match_spec_compile([{'_',[],['$_']}])},
[{scope,{0,1}}])),
[] =
?MASK_ERROR(binary:matches(<<1,2,3>>,<<1>>,[{scope,{0,0}}])),
badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{bm,<<>>},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,[],[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{ac,<<>>},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{bm,ACMagic},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(binary:matches(<<1,2,3>>,{ac,BMMagic},[{scope,{0,1}}])),
badarg =
?MASK_ERROR(
binary:matches(<<1,2,3>>,
{bm,ets:match_spec_compile([{'_',[],['$_']}])},
[{scope,{0,1}}])),
badarg =
?MASK_ERROR(
binary:matches(<<1,2,3>>,
{ac,ets:match_spec_compile([{'_',[],['$_']}])},
[{scope,{0,1}}])),
%% OTP-11350
badarg = ?MASK_ERROR(
binary:matches(<<"foo">>,
[<<>>, <<"f">>])),
badarg =
?MASK_ERROR(binary:longest_common_prefix(
[<<0:10000,1,2,4,1:3>>,
<<0:10000,1,2,3>>])),
badarg =
?MASK_ERROR(binary:longest_common_suffix(
[<<0:10000,1,2,4,1:3>>,
<<0:10000,1,2,3>>])),
badarg =
?MASK_ERROR(binary:encode_unsigned(-1)),
badarg =
?MASK_ERROR(
binary:encode_unsigned(-16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
badarg =
?MASK_ERROR(
binary:first(<<1,2,4,1:3>>)),
badarg =
?MASK_ERROR(
binary:first([1,2,4])),
badarg =
?MASK_ERROR(
binary:last(<<1,2,4,1:3>>)),
badarg =
?MASK_ERROR(
binary:last([1,2,4])),
badarg =
?MASK_ERROR(
binary:at(<<1,2,4,1:3>>,2)),
badarg =
?MASK_ERROR(
binary:at(<<>>,2)),
badarg =
?MASK_ERROR(
binary:at([1,2,4],2)),
ok.
%% Whitebox test to force special trap conditions in
%% longest_common_{prefix,suffix}.
longest_common_trap(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state,true),
io:format("oldlimit: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,10)]),
erlang:bump_reductions(10000000),
_ = binary:longest_common_prefix(
[<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0:10000,1,3,3>>,
<<0:10000,1,2,4>>]),
_ = binary:longest_common_prefix(
[<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
<<0:10000,1,2,4>>]),
erlang:bump_reductions(10000000),
_ = binary:longest_common_suffix(
[<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,3,3,0:10000,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
<<1,2,4,0:10000>>]),
_ = binary:longest_common_suffix(
[<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<1,2,4,0:10000>>,
<<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
<<1,2,4,0:10000>>]),
Subj = subj(),
Len = byte_size(Subj),
Len = binary:longest_common_suffix(
[Subj,Subj,Subj]),
io:format("limit was: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,
default)]),
erts_debug:set_internal_state(available_internal_state,false),
ok.
subj() ->
Me = self(),
spawn(fun() ->
X0 = iolist_to_binary([
"1234567890",
lists:duplicate(100, $x)
]),
Me ! X0,
receive X -> X end
end),
X0 = receive A -> A end,
<<X1:32/binary,_/binary>> = X0,
Subject= <<X1/binary>>,
Subject.
%% Test correct return values for scopes (OTP-9701).
scope_return(Config) when is_list(Config) ->
N=10000,
Bin=binary:copy(<<"a">>,N),
scope_loop(Bin,0,N).
scope_loop(_,N,N) ->
ok;
scope_loop(Bin,N,M) ->
{N,1} = binary:match(Bin,<<"a">>,[{scope,{N,1}}]),
{N,1} = binary:match(Bin,[<<"a">>,<<"b">>],[{scope,{N,1}}]),
scope_loop(Bin,N+1,M).
%% Try some interesting patterns.
interesting(Config) when is_list(Config) ->
X = do_interesting(binary),
X = do_interesting(binref).
do_interesting(Module) ->
{0,4} = Module:match(<<"123456">>,
Module:compile_pattern([<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>])),
[{0,4},{5,1}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>])),
[{0,4}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>])),
[{0,2},{2,2}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"12">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>])),
{1,4} = Module:match(<<"123456">>,
Module:compile_pattern([<<"34">>,<<"34">>,
<<"12347">>,<<"2345">>])),
[{1,4}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"34">>,<<"34">>,
<<"12347">>,<<"2345">>])),
[{2,2}] = Module:matches(<<"123456">>,
Module:compile_pattern([<<"34">>,<<"34">>,
<<"12347">>,<<"2346">>])),
{0,4} = Module:match(<<"123456">>,
[<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>]),
[{0,4},{5,1}] = Module:matches(<<"123456">>,
[<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>,<<"6">>]),
[{0,4}] = Module:matches(<<"123456">>,
[<<"12">>,<<"1234">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>]),
[{0,2},{2,2}] = Module:matches(<<"123456">>,
[<<"12">>,
<<"23">>,<<"3">>,
<<"34">>,<<"456">>,
<<"45">>]),
{1,4} = Module:match(<<"123456">>,
[<<"34">>,<<"34">>,
<<"12347">>,<<"2345">>]),
[{1,4}] = Module:matches(<<"123456">>,
[<<"34">>,<<"34">>,
<<"12347">>,<<"2345">>]),
[{2,2}] = Module:matches(<<"123456">>,
[<<"34">>,<<"34">>,
<<"12347">>,<<"2346">>]),
nomatch = Module:match(<<1,2,3,4>>,<<2>>,[{scope,{0,1}}]),
{1,1} = Module:match(<<1,2,3,4>>,<<2>>,[{scope,{0,2}}]),
nomatch = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,2}}]),
{1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,3}}]),
{1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{0,4}}]),
badarg = ?MASK_ERROR(Module:match(<<1,2,3,4>>,<<2,3>>,
[{scope,{0,5}}])),
{1,2} = Module:match(<<1,2,3,4>>,<<2,3>>,[{scope,{4,-4}}]),
{0,3} = Module:match(<<1,2,3,4>>,<<1,2,3>>,[{scope,{4,-4}}]),
{0,4} = Module:match(<<1,2,3,4>>,<<1,2,3,4>>,[{scope,{4,-4}}]),
badarg = ?MASK_ERROR(Module:match(<<1,2,3,4>>,<<1,2,3,4>>,
[{scope,{3,-4}}])),
[] = Module:matches(<<1,2,3,4>>,<<2>>,[{scope,{0,1}}]),
[{1,1}] = Module:matches(<<1,2,3,4>>,[<<2>>,<<3>>],[{scope,{0,2}}]),
[] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,2}}]),
[{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,3}}]),
[{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{0,4}}]),
[{1,2}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
[{scope,{0,3}}]),
[{1,2},{3,1}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
[{scope,{0,4}}]),
badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,<<2,3>>,
[{scope,{0,5}}])),
[{1,2}] = Module:matches(<<1,2,3,4>>,<<2,3>>,[{scope,{4,-4}}]),
[{1,2},{3,1}] = Module:matches(<<1,2,3,4>>,[<<2,3>>,<<4>>],
[{scope,{4,-4}}]),
[{0,3}] = Module:matches(<<1,2,3,4>>,<<1,2,3>>,[{scope,{4,-4}}]),
[{0,4}] = Module:matches(<<1,2,3,4>>,<<1,2,3,4>>,[{scope,{4,-4}}]),
badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,<<1,2,3,4>>,
[{scope,{3,-4}}])),
badarg = ?MASK_ERROR(Module:matches(<<1,2,3,4>>,[<<1,2,3,4>>],
[{scope,{3,-4}}])),
[<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,<<4,5>>),
[<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>]),
[<<1,2,3>>,<<6>>,<<8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>],[global]),
[<<1,2,3>>,<<6>>,<<>>,<<>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
[global]),
[<<1,2,3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
[global,trim]),
[<<1,2,3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
[global,trim_all]),
[<<1,2,3,4,5,6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
[global,trim,{scope,{0,4}}]),
[<<1,2,3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
[global,trim,{scope,{0,5}}]),
[<<>>,<<>>,<<3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<1>>,<<2>>,<<4,5>>],
[global,trim]),
[<<3>>,<<6,7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<1>>,<<2>>,<<4,5>>],
[global,trim_all]),
[<<1,2,3>>,<<>>,<<7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<6>>],
[global,trim]),
[<<1,2,3>>,<<7,8>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<6>>],
[global,trim_all]),
[<<>>,<<>>,<<3>>,<<>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
[global,trim]),
[<<3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
[global,trim_all]),
[<<>>] = binary:split(<<>>, <<",">>, []),
[] = binary:split(<<>>, <<",">>, [trim]),
[] = binary:split(<<>>, <<",">>, [trim_all]),
[] = binary:split(<<>>, <<",">>, [global,trim]),
[] = binary:split(<<>>, <<",">>, [global,trim_all]),
badarg = ?MASK_ERROR(
Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global,trim,{scope,{0,5}}])),
<<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,[]),
<<1,2,3,99,6,99,99>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global]),
<<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global,{scope,{0,5}}]),
<<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global,{scope,{0,5}}]),
<<1,2,3,99,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global,{scope,{0,5}}]),
badarg = ?MASK_ERROR(Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global,{scope,{0,5}},
{insert,1}])),
<<1,2,3,99,4,5,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
[global,{scope,{0,5}},
{insert_replaced,1}]),
<<1,2,3,9,4,5,9,6,7,8>> = Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],
<<9,9>>,
[global,{scope,{0,5}},
{insert_replaced,1}]),
badarg = ?MASK_ERROR(Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<>>,
[global,{scope,{0,5}},
{insert_replaced,1}])),
2 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>]),
2 = Module:longest_common_prefix([<<1,2,4>>,<<1,2>>]),
1 = Module:longest_common_prefix([<<1,2,4>>,<<1>>]),
0 = Module:longest_common_prefix([<<1,2,4>>,<<>>]),
1 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>,<<1,3,3>>]),
1 = Module:longest_common_prefix([<<1,2,4>>,<<1,2,3>>,<<1,3,3>>,<<1,2,4>>]),
1251 = Module:longest_common_prefix([<<0:10000,1,2,4>>,
<<0:10000,1,2,3>>,
<<0:10000,1,3,3>>,
<<0:10000,1,2,4>>]),
12501 = Module:longest_common_prefix([<<0:100000,1,2,4>>,
<<0:100000,1,2,3>>,
<<0:100000,1,3,3>>,
<<0:100000,1,2,4>>]),
1251 = Module:longest_common_prefix(
[make_unaligned(<<0:10000,1,2,4>>),
<<0:10000,1,2,3>>,
make_unaligned(<<0:10000,1,3,3>>),
<<0:10000,1,2,4>>]),
12501 = Module:longest_common_prefix(
[<<0:100000,1,2,4>>,
make_unaligned(<<0:100000,1,2,3>>),
<<0:100000,1,3,3>>,
make_unaligned(<<0:100000,1,2,4>>)]),
1250001 = Module:longest_common_prefix([<<0:10000000,1,2,4>>,
<<0:10000000,1,2,3>>,
<<0:10000000,1,3,3>>,
<<0:10000000,1,2,4>>]),
if % Too cruel for the reference implementation
Module =:= binary ->
erts_debug:set_internal_state(available_internal_state,true),
io:format("oldlimit: ~p~n",
[erts_debug:set_internal_state(
binary_loop_limit,100)]),
1250001 = Module:longest_common_prefix(
[<<0:10000000,1,2,4>>,
<<0:10000000,1,2,3>>,
<<0:10000000,1,3,3>>,
<<0:10000000,1,2,4>>]),
io:format("limit was: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,
default)]),
erts_debug:set_internal_state(available_internal_state,
false);
true ->
ok
end,
1 = Module:longest_common_suffix([<<0:100000000,1,2,4,5>>,
<<0:100000000,1,2,3,5>>,
<<0:100000000,1,3,3,5>>,
<<0:100000000,1,2,4,5>>]),
1 = Module:longest_common_suffix([<<1,2,4,5>>,
<<0:100000000,1,2,3,5>>,
<<0:100000000,1,3,3,5>>,
<<0:100000000,1,2,4,5>>]),
1 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5>>]),
0 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4>>]),
2 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5,5>>,
<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5,5>>]),
1 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<5>>,
<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5,5>>]),
0 = Module:longest_common_suffix([<<1,2,4,5,5>>,<<>>,
<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5,5>>]),
0 = Module:longest_common_suffix([<<>>,<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5,5>>]),
0 = Module:longest_common_suffix([<<>>,<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5,5>>]),
2 = Module:longest_common_suffix([<<5,5>>,<<0:100000000,1,3,3,5,5>>,
<<0:100000000,1,2,4,5,5>>]),
2 = Module:longest_common_suffix([<<5,5>>,<<5,5>>,<<4,5,5>>]),
2 = Module:longest_common_suffix([<<5,5>>,<<5,5>>,<<5,5>>]),
3 = Module:longest_common_suffix([<<4,5,5>>,<<4,5,5>>,<<4,5,5>>]),
0 = Module:longest_common_suffix([<<>>]),
badarg = ?MASK_ERROR(Module:longest_common_suffix([])),
badarg = ?MASK_ERROR(Module:longest_common_suffix([apa])),
badarg = ?MASK_ERROR(Module:longest_common_suffix([[<<>>]])),
badarg = ?MASK_ERROR(Module:longest_common_suffix([[<<0>>,
<<1:9>>]])),
0 = Module:longest_common_prefix([<<>>]),
badarg = ?MASK_ERROR(Module:longest_common_prefix([])),
badarg = ?MASK_ERROR(Module:longest_common_prefix([apa])),
badarg = ?MASK_ERROR(Module:longest_common_prefix([[<<>>]])),
badarg = ?MASK_ERROR(Module:longest_common_prefix([[<<0>>,
<<1:9>>]])),
<<1:6,Bin:3/binary,_:2>> = <<1:6,1,2,3,1:2>>,
<<1,2,3>> = Bin,
1 = Module:first(Bin),
1 = Module:first(<<1>>),
1 = Module:first(<<1,2,3>>),
badarg = ?MASK_ERROR(Module:first(<<>>)),
badarg = ?MASK_ERROR(Module:first(apa)),
3 = Module:last(Bin),
1 = Module:last(<<1>>),
3 = Module:last(<<1,2,3>>),
badarg = ?MASK_ERROR(Module:last(<<>>)),
badarg = ?MASK_ERROR(Module:last(apa)),
1 = Module:at(Bin,0),
1 = Module:at(<<1>>,0),
1 = Module:at(<<1,2,3>>,0),
2 = Module:at(<<1,2,3>>,1),
3 = Module:at(<<1,2,3>>,2),
badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,3)),
badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,-1)),
badarg = ?MASK_ERROR(Module:at(<<1,2,3>>,apa)),
"hejsan" = [ Module:at(<<"hejsan">>,I) || I <- lists:seq(0,5) ],
badarg = ?MASK_ERROR(Module:bin_to_list(<<1,2,3>>,3,-4)),
[1,2,3] = ?MASK_ERROR(Module:bin_to_list(<<1,2,3>>,3,-3)),
badarg = ?MASK_ERROR(Module:decode_unsigned(<<1,2,1:2>>,big)),
badarg = ?MASK_ERROR(Module:decode_unsigned(<<1,2,1:2>>,little)),
badarg = ?MASK_ERROR(Module:decode_unsigned(apa)),
badarg = ?MASK_ERROR(Module:decode_unsigned(125,little)),
0 = ?MASK_ERROR(Module:decode_unsigned(<<>>,little)),
0 = ?MASK_ERROR(Module:decode_unsigned(<<>>,big)),
0 = ?MASK_ERROR(Module:decode_unsigned(<<0>>,little)),
0 = ?MASK_ERROR(Module:decode_unsigned(<<0>>,big)),
0 = ?MASK_ERROR(Module:decode_unsigned(make_unaligned(<<0>>),
little)),
0 = ?MASK_ERROR(Module:decode_unsigned(make_unaligned(<<0>>),big)),
badarg = ?MASK_ERROR(Module:encode_unsigned(apa)),
badarg = ?MASK_ERROR(Module:encode_unsigned(125.3,little)),
badarg = ?MASK_ERROR(Module:encode_unsigned({1},little)),
badarg = ?MASK_ERROR(Module:encode_unsigned([1],little)),
<<0>> = ?MASK_ERROR(Module:encode_unsigned(0,little)),
<<0>> = ?MASK_ERROR(Module:encode_unsigned(0,big)),
ok.
%% Test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2.
encode_decode(Config) when is_list(Config) ->
rand:seed(exsplus, {1271,769940,559934}),
ok = encode_decode_loop({1,200},1000), % Need to be long enough
% to create offheap binaries
ok.
encode_decode_loop(_Range,0) ->
ok;
encode_decode_loop(Range, X) ->
N = random_number(Range),
A = binary:encode_unsigned(N),
B = binary:encode_unsigned(N,big),
C = binref:encode_unsigned(N),
D = binref:encode_unsigned(N,big),
E = binary:encode_unsigned(N,little),
F = binref:encode_unsigned(N,little),
G = binary:decode_unsigned(A),
H = binary:decode_unsigned(A,big),
I = binref:decode_unsigned(A),
J = binary:decode_unsigned(E,little),
K = binref:decode_unsigned(E,little),
L = binary:decode_unsigned(make_unaligned(A)),
M = binary:decode_unsigned(make_unaligned(E),little),
PaddedBig = <<0:48,A/binary>>,
PaddedLittle = <<E/binary,0:48>>,
O = binary:decode_unsigned(PaddedBig),
P = binary:decode_unsigned(make_unaligned(PaddedBig)),
Q = binary:decode_unsigned(PaddedLittle,little),
R = binary:decode_unsigned(make_unaligned(PaddedLittle),little),
S = binref:decode_unsigned(PaddedLittle,little),
T = binref:decode_unsigned(PaddedBig),
case (((A =:= B) and (B =:= C) and (C =:= D)) and
((E =:= F)) and
((N =:= G) and (G =:= H) and (H =:= I) and
(I =:= J) and (J =:= K) and (K =:= L) and (L =:= M)) and
((M =:= O) and (O =:= P) and (P =:= Q) and (Q =:= R) and
(R =:= S) and (S =:= T)))of
true ->
encode_decode_loop(Range,X-1);
_ ->
io:format("Failed to encode/decode ~w~n(Results ~p)~n",
[N,[A,B,C,D,E,F,G,H,I,J,K,L,M,x,O,P,Q,R,S,T]]),
exit(mismatch)
end.
%% Smoke test of the guard BIFs binary_part/2,3.
guard(Config) when is_list(Config) ->
{comment, "Guard tests are run in emulator test suite"}.
%% Test referenced_byte_size/1 bif.
referenced(Config) when is_list(Config) ->
badarg = ?MASK_ERROR(binary:referenced_byte_size([])),
badarg = ?MASK_ERROR(binary:referenced_byte_size(apa)),
badarg = ?MASK_ERROR(binary:referenced_byte_size({})),
badarg = ?MASK_ERROR(binary:referenced_byte_size(1)),
A = <<0:(1024 * 8)>>,
B = binary:copy(A, 1000),
1024 = binary:referenced_byte_size(A),
1024000 = binary:referenced_byte_size(B),
<<_:8,C:1023/binary>> = A,
1024 = binary:referenced_byte_size(C),
1023 = binary:referenced_byte_size(binary:copy(C)),
<<_:7,D:1023/binary,_:1>> = A,
1023 = binary:referenced_byte_size(binary:copy(D)),
1024 = binary:referenced_byte_size(D),
<<_:8,E:128/binary,_/binary>> = B,
1024000 = binary:referenced_byte_size(E),
128 = binary:referenced_byte_size(binary:copy(E)),
<<_:7,F:128/binary,_:1,_/binary>> = B,
128 = binary:referenced_byte_size(binary:copy(F)),
1024000 = binary:referenced_byte_size(F),
ok.
%% Test list_to_bin/1 BIF.
list_to_bin(Config) when is_list(Config) ->
%% Just some smoke_tests first, then go nuts with random cases
badarg = ?MASK_ERROR(binary:list_to_bin({})),
badarg = ?MASK_ERROR(binary:list_to_bin(apa)),
badarg = ?MASK_ERROR(binary:list_to_bin(<<"apa">>)),
F1 = fun(L) ->
?MASK_ERROR(binref:list_to_bin(L))
end,
F2 = fun(L) ->
?MASK_ERROR(binary:list_to_bin(L))
end,
random_iolist:run(1000,F1,F2),
ok.
%% Test copy/1,2 BIFs.
copy(Config) when is_list(Config) ->
<<1,2,3>> = binary:copy(<<1,2,3>>),
RS = random_string({1,10000}),
RS2 = binary:copy(RS),
true = RS =:= RS2,
false = erts_debug:same(RS, RS2),
<<>> = ?MASK_ERROR(binary:copy(<<1,2,3>>,0)),
badarg = ?MASK_ERROR(binary:copy(<<1,2,3:3>>,2)),
badarg = ?MASK_ERROR(binary:copy([],0)),
<<>> = ?MASK_ERROR(binary:copy(<<>>,0)),
badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,1.0)),
badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,
16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
<<>> = binary:copy(<<>>,10000),
rand:seed(exsplus, {1271,769940,559934}),
ok = random_copy(3000),
erts_debug:set_internal_state(available_internal_state,true),
io:format("oldlimit: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,10)]),
Subj = subj(),
XX = binary:copy(Subj,1000),
XX = binref:copy(Subj,1000),
ok = random_copy(1000),
kill_copy_loop(1000),
io:format("limit was: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,
default)]),
erts_debug:set_internal_state(available_internal_state,false),
ok.
kill_copy_loop(0) ->
ok;
kill_copy_loop(N) ->
{Pid,Ref} = spawn_monitor(fun() ->
ok = random_copy(1000)
end),
receive
after 10 ->
ok
end,
exit(Pid,kill),
receive
{'DOWN',Ref,process,Pid,_} ->
kill_copy_loop(N-1)
after 1000 ->
exit(did_not_die)
end.
random_copy(0) ->
ok;
random_copy(N) ->
Str = random_string({0,N}),
Num = rand:uniform(N div 10+1),
A = ?MASK_ERROR(binary:copy(Str,Num)),
B = ?MASK_ERROR(binref:copy(Str,Num)),
C = ?MASK_ERROR(binary:copy(make_unaligned(Str),Num)),
case {(A =:= B), (B =:= C)} of
{true,true} ->
random_copy(N-1);
_ ->
io:format("Failed to pick copy ~s ~p times~n",
[Str,Num]),
io:format("A:~p,~nB:~p,~n,C:~p.~n",
[A,B,C]),
exit(mismatch)
end.
%% Test bin_to_list/1,2,3 BIFs.
bin_to_list(Config) when is_list(Config) ->
%% Just some smoke_tests first, then go nuts with random cases
X = <<1,2,3,4,0:1000000,5>>,
Y = make_unaligned(X),
LX = binary:bin_to_list(X),
LX = binary:bin_to_list(X,0,byte_size(X)),
LX = binary:bin_to_list(X,byte_size(X),-byte_size(X)),
LX = binary:bin_to_list(X,{0,byte_size(X)}),
LX = binary:bin_to_list(X,{byte_size(X),-byte_size(X)}),
LY = binary:bin_to_list(Y),
LY = binary:bin_to_list(Y,0,byte_size(Y)),
LY = binary:bin_to_list(Y,byte_size(Y),-byte_size(Y)),
LY = binary:bin_to_list(Y,{0,byte_size(Y)}),
LY = binary:bin_to_list(Y,{byte_size(Y),-byte_size(Y)}),
1 = hd(LX),
5 = lists:last(LX),
1 = hd(LY),
5 = lists:last(LY),
X = list_to_binary(LY),
Y = list_to_binary(LY),
X = list_to_binary(LY),
[5] = lists:nthtail(byte_size(X)-1,LX),
[0,5] = lists:nthtail(byte_size(X)-2,LX),
[0,5] = lists:nthtail(byte_size(Y)-2,LY),
rand:seed(exsplus, {1271,769940,559934}),
ok = random_bin_to_list(5000),
ok.
random_bin_to_list(0) ->
ok;
random_bin_to_list(N) ->
Str = random_string({1,N}),
Parts0 = random_parts(10,N),
Parts1 = Parts0 ++ [ {X+Y,-Y} || {X,Y} <- Parts0 ],
[ begin
try
true = ?MASK_ERROR(binary:bin_to_list(Str,Z)) =:=
?MASK_ERROR(binref:bin_to_list(Str,Z)),
true = ?MASK_ERROR(binary:bin_to_list(Str,Z)) =:=
?MASK_ERROR(binary:bin_to_list(make_unaligned(Str),Z))
catch
_:_ ->
io:format("Error, Str = <<\"~s\">>.~nZ = ~p.~n",
[Str,Z]),
exit(badresult)
end
end || Z <- Parts1 ],
[ begin
try
true = ?MASK_ERROR(binary:bin_to_list(Str,A,B)) =:=
?MASK_ERROR(binref:bin_to_list(Str,A,B)),
true = ?MASK_ERROR(binary:bin_to_list(Str,A,B)) =:=
?MASK_ERROR(binary:bin_to_list(make_unaligned(Str),A,B))
catch
_:_ ->
io:format("Error, Str = <<\"~s\">>.~nA = ~p.~nB = ~p.~n",
[Str,A,B]),
exit(badresult)
end
end || {A,B} <- Parts1 ],
random_bin_to_list(N-1).
%% Test the part/2,3 BIFs.
parts(Config) when is_list(Config) ->
%% Some simple smoke tests to begin with
Simple = <<1,2,3,4,5,6,7,8>>,
<<1,2>> = binary:part(Simple,0,2),
<<1,2>> = binary:part(Simple,{0,2}),
Simple = binary:part(Simple,0,8),
Simple = binary:part(Simple,{0,8}),
badarg = ?MASK_ERROR(binary:part(Simple,0,9)),
badarg = ?MASK_ERROR(binary:part(Simple,{0,9})),
badarg = ?MASK_ERROR(binary:part(Simple,1,8)),
badarg = ?MASK_ERROR(binary:part(Simple,{1,8})),
badarg = ?MASK_ERROR(binary:part(Simple,{3,-4})),
badarg = ?MASK_ERROR(binary:part(Simple,{3.0,1})),
badarg = ?MASK_ERROR(
binary:part(Simple,{16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFF
,1})),
<<2,3,4,5,6,7,8>> = binary:part(Simple,{1,7}),
<<2,3,4,5,6,7,8>> = binary:part(Simple,{8,-7}),
Simple = binary:part(Simple,{8,-8}),
badarg = ?MASK_ERROR(binary:part(Simple,{1,-8})),
badarg = ?MASK_ERROR(binary:part(Simple,{8,-9})),
badarg = ?MASK_ERROR(binary:part(Simple,{0,-1})),
<<>> = binary:part(Simple,{8,0}),
badarg = ?MASK_ERROR(binary:part(Simple,{9,0})),
badarg = ?MASK_ERROR(binary:part(Simple,{-1,0})),
badarg = ?MASK_ERROR(binary:part(Simple,{7,2})),
<<8>> = binary:part(Simple,{7,1}),
rand:seed(exsplus, {1271,769940,559934}),
random_parts(5000),
ok.
random_parts(0) ->
ok;
random_parts(N) ->
Str = random_string({1,N}),
Parts0 = random_parts(10,N),
Parts1 = Parts0 ++ [ {X+Y,-Y} || {X,Y} <- Parts0 ],
[ begin
true = ?MASK_ERROR(binary:part(Str,Z)) =:=
?MASK_ERROR(binref:part(Str,Z)),
true = ?MASK_ERROR(binary:part(Str,Z)) =:=
?MASK_ERROR(erlang:binary_part(Str,Z)),
true = ?MASK_ERROR(binary:part(Str,Z)) =:=
?MASK_ERROR(binary:part(make_unaligned(Str),Z))
end || Z <- Parts1 ],
random_parts(N-1).
random_parts(0,_) ->
[];
random_parts(X,N) ->
Pos = rand:uniform(N),
Len = rand:uniform((Pos * 12) div 10),
[{Pos,Len} | random_parts(X-1,N)].
%% Test pseudorandomly generated cases against reference implementation.
random_ref_comp(Config) when is_list(Config) ->
ct:timetrap({minutes,30}), %% valgrind needs a lot of time
put(success_counter,0),
rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
I2 = 5,
do_random_match_comp(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_match_comp2(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_match_comp3(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_match_comp4(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_matches_comp(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_matches_comp2(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_matches_comp3(I2,Nr,Hr),
erts_debug:set_internal_state(available_internal_state,true),
io:format("oldlimit: ~p~n",[ erts_debug:set_internal_state(binary_loop_limit,100)]),
do_random_match_comp(I1,Nr,Hr),
do_random_matches_comp3(I2,Nr,Hr),
io:format("limit was: ~p~n",[ erts_debug:set_internal_state(binary_loop_limit,default)]),
erts_debug:set_internal_state(available_internal_state,false),
ok.
%% Test pseudorandomly generated cases against reference implementation
%% of split and replace.
random_ref_sr_comp(Config) when is_list(Config) ->
ct:timetrap({minutes,30}), %% valgrind needs a lot
put(success_counter,0),
rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
do_random_split_comp(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_replace_comp(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_split_comp2(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
do_random_replace_comp2(I1,Nr,Hr),
io:format("Number of successes: ~p~n",[get(success_counter)]),
ok.
%% Test pseudorandomly generated cases against reference implementation
%% of split and replace.
random_ref_fla_comp(Config) when is_list(Config) ->
put(success_counter,0),
rand:seed(exsplus, {1271,769940,559934}),
do_random_first_comp(5000,{1,1000}),
do_random_last_comp(5000,{1,1000}),
do_random_at_comp(5000,{1,1000}),
io:format("Number of successes: ~p~n",[get(success_counter)]),
ok.
do_random_first_comp(0,_) ->
ok;
do_random_first_comp(N,Range) ->
S = random_string(Range),
A = ?MASK_ERROR(binref:first(S)),
B = ?MASK_ERROR(binary:first(S)),
C = ?MASK_ERROR(binary:first(make_unaligned(S))),
case {(A =:= B), (B =:= C)} of
{true,true} ->
do_random_first_comp(N-1,Range);
_ ->
io:format("Failed to pick first of ~s~n",
[S]),
io:format("A:~p,~nB:~p,~n,C:~p.~n",
[A,B,C]),
exit(mismatch)
end.
do_random_last_comp(0,_) ->
ok;
do_random_last_comp(N,Range) ->
S = random_string(Range),
A = ?MASK_ERROR(binref:last(S)),
B = ?MASK_ERROR(binary:last(S)),
C = ?MASK_ERROR(binary:last(make_unaligned(S))),
case {(A =:= B), (B =:= C)} of
{true,true} ->
do_random_last_comp(N-1,Range);
_ ->
io:format("Failed to pick last of ~s~n",
[S]),
io:format("A:~p,~nB:~p,~n,C:~p.~n",
[A,B,C]),
exit(mismatch)
end.
do_random_at_comp(0,_) ->
ok;
do_random_at_comp(N,{Min,Max}=Range) ->
S = random_string(Range),
XMax = Min + ((Max - Min) * 3) div 4,
Pos = random_length({Min,XMax}), %% some out of range
A = ?MASK_ERROR(binref:at(S,Pos)),
B = ?MASK_ERROR(binary:at(S,Pos)),
C = ?MASK_ERROR(binary:at(make_unaligned(S),Pos)),
if
A =/= badarg ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
case {(A =:= B), (B =:= C)} of
{true,true} ->
do_random_at_comp(N-1,Range);
_ ->
io:format("Failed to pick last of ~s~n",
[S]),
io:format("A:~p,~nB:~p,~n,C:~p.~n",
[A,B,C]),
exit(mismatch)
end.
do_random_matches_comp(0,_,_) ->
ok;
do_random_matches_comp(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Needles = [random_string(NeedleRange) ||
_ <- lists:duplicate(NumNeedles,a)],
Haystack = random_string(HaystackRange),
true = do_matches_comp(Needles,Haystack),
do_random_matches_comp(N-1,NeedleRange,HaystackRange).
do_random_matches_comp2(0,_,_) ->
ok;
do_random_matches_comp2(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Haystack = random_string(HaystackRange),
Needles = [random_substring(NeedleRange,Haystack) ||
_ <- lists:duplicate(NumNeedles,a)],
true = do_matches_comp(Needles,Haystack),
do_random_matches_comp2(N-1,NeedleRange,HaystackRange).
do_random_matches_comp3(0,_,_) ->
ok;
do_random_matches_comp3(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Haystack = random_string(HaystackRange),
Needles = [random_substring(NeedleRange,Haystack) ||
_ <- lists:duplicate(NumNeedles,a)],
RefRes = binref:matches(Haystack,Needles),
RefRes = binary:matches(Haystack,Needles),
Compiled = binary:compile_pattern(Needles),
true = do_matches_comp_loop(10000,Compiled,Haystack, RefRes),
do_random_matches_comp3(N-1,NeedleRange,HaystackRange).
do_matches_comp_loop(0,_,_,_) ->
true;
do_matches_comp_loop(N, Needles, Haystack0,RR) ->
DummySize=N*8,
Haystack1 = <<0:DummySize,Haystack0/binary>>,
RR1=[{X+N,Y} || {X,Y} <- RR],
true = do_matches_comp2(Needles,Haystack1,RR1),
Haystack2 = <<Haystack0/binary,Haystack1/binary>>,
RR2 = RR ++ [{X2+N+byte_size(Haystack0),Y2} || {X2,Y2} <- RR],
true = do_matches_comp2(Needles,Haystack2,RR2),
do_matches_comp_loop(N-1, Needles, Haystack0,RR).
do_matches_comp2(N,H,A) ->
C = ?MASK_ERROR(binary:matches(H,N)),
case (A =:= C) of
true ->
true;
_ ->
io:format("Failed to match ~p (needle) against ~s (haystack)~n",
[N,H]),
io:format("A:~p,~n,C:~p.~n",
[A,C]),
exit(mismatch)
end.
do_matches_comp(N,H) ->
A = ?MASK_ERROR(binref:matches(H,N)),
B = ?MASK_ERROR(binary:matches(H,N)),
C = ?MASK_ERROR(binary:matches(make_unaligned(H),
binary:compile_pattern([make_unaligned2(X) || X <- N]))),
if
A =/= nomatch ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
case {(A =:= B), (B =:= C)} of
{true,true} ->
true;
_ ->
io:format("Failed to match ~p (needle) against ~s (haystack)~n",
[N,H]),
io:format("A:~p,~nB:~p,~n,C:~p,~n",
[A,B,C]),
exit(mismatch)
end.
do_random_match_comp(0,_,_) ->
ok;
do_random_match_comp(N,NeedleRange,HaystackRange) ->
Needle = random_string(NeedleRange),
Haystack = random_string(HaystackRange),
true = do_match_comp(Needle,Haystack),
do_random_match_comp(N-1,NeedleRange,HaystackRange).
do_random_match_comp2(0,_,_) ->
ok;
do_random_match_comp2(N,NeedleRange,HaystackRange) ->
Haystack = random_string(HaystackRange),
Needle = random_substring(NeedleRange,Haystack),
true = do_match_comp(Needle,Haystack),
do_random_match_comp2(N-1,NeedleRange,HaystackRange).
do_random_match_comp3(0,_,_) ->
ok;
do_random_match_comp3(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Haystack = random_string(HaystackRange),
Needles = [random_substring(NeedleRange,Haystack) ||
_ <- lists:duplicate(NumNeedles,a)],
true = do_match_comp3(Needles,Haystack),
do_random_match_comp3(N-1,NeedleRange,HaystackRange).
do_random_match_comp4(0,_,_) ->
ok;
do_random_match_comp4(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Haystack = random_string(HaystackRange),
Needles = [random_string(NeedleRange) ||
_ <- lists:duplicate(NumNeedles,a)],
true = do_match_comp3(Needles,Haystack),
do_random_match_comp4(N-1,NeedleRange,HaystackRange).
do_match_comp(N,H) ->
A = ?MASK_ERROR(binref:match(H,N)),
B = ?MASK_ERROR(binary:match(make_unaligned(H),N)),
C = ?MASK_ERROR(binary:match(H,binary:compile_pattern([N]))),
D = ?MASK_ERROR(binary:match(H,binary:compile_pattern(make_unaligned(N)))),
if
A =/= nomatch ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
case {(A =:= B), (B =:= C),(C =:= D)} of
{true,true,true} ->
true;
_ ->
io:format("Failed to match ~s (needle) against ~s (haystack)~n",
[N,H]),
io:format("A:~p,~nB:~p,~n,C:~p,~n,D:~p.~n",
[A,B,C,D]),
exit(mismatch)
end.
do_match_comp3(N,H) ->
A = ?MASK_ERROR(binref:match(H,N)),
B = ?MASK_ERROR(binary:match(H,N)),
C = ?MASK_ERROR(binary:match(H,binary:compile_pattern(N))),
if
A =/= nomatch ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
case {(A =:= B),(B =:= C)} of
{true,true} ->
true;
_ ->
io:format("Failed to match ~s (needle) against ~s (haystack)~n",
[N,H]),
io:format("A:~p,~nB:~p,~n,C:~p.~n",
[A,B,C]),
exit(mismatch)
end.
do_random_split_comp(0,_,_) ->
ok;
do_random_split_comp(N,NeedleRange,HaystackRange) ->
Haystack = random_string(HaystackRange),
Needle = random_substring(NeedleRange,Haystack),
true = do_split_comp(Needle,Haystack,[]),
true = do_split_comp(Needle,Haystack,[global]),
true = do_split_comp(Needle,Haystack,[global,trim]),
true = do_split_comp(Needle,Haystack,[global,trim_all]),
true = do_split_comp(Needle,Haystack,[global,trim,trim_all]),
do_random_split_comp(N-1,NeedleRange,HaystackRange).
do_random_split_comp2(0,_,_) ->
ok;
do_random_split_comp2(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Haystack = random_string(HaystackRange),
Needles = [random_substring(NeedleRange,Haystack) ||
_ <- lists:duplicate(NumNeedles,a)],
true = do_split_comp(Needles,Haystack,[]),
true = do_split_comp(Needles,Haystack,[global]),
true = do_split_comp(Needles,Haystack,[global,trim]),
true = do_split_comp(Needles,Haystack,[global,trim_all]),
true = do_split_comp(Needles,Haystack,[global,trim,trim_all]),
do_random_split_comp2(N-1,NeedleRange,HaystackRange).
do_split_comp(N,H,Opts) ->
A = ?MASK_ERROR(binref:split(H,N,Opts)),
D = ?MASK_ERROR(binary:split(H,binary:compile_pattern(N),Opts)),
if
(A =/= [N]) and is_list(A) ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
case (A =:= D) of
true ->
true;
_ ->
io:format("Failed to split ~n~p ~n(haystack) with ~n~p ~n(needle) "
"~nand options ~p~n",
[H,N,Opts]),
io:format("A:~p,D:~p.~n",
[A,D]),
exit(mismatch)
end.
do_random_replace_comp(0,_,_) ->
ok;
do_random_replace_comp(N,NeedleRange,HaystackRange) ->
Haystack = random_string(HaystackRange),
Needle = random_substring(NeedleRange,Haystack),
Repl = random_string(NeedleRange),
Insertat = random_length(NeedleRange), %Sometimes larger than Repl
true = do_replace_comp(Needle,Haystack,Repl,[]),
true = do_replace_comp(Needle,Haystack,Repl,[global]),
true = do_replace_comp(Needle,Haystack,Repl,
[global,{insert_replaced,Insertat}]),
do_random_replace_comp(N-1,NeedleRange,HaystackRange).
do_random_replace_comp2(0,_,_) ->
ok;
do_random_replace_comp2(N,NeedleRange,HaystackRange) ->
NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
Haystack = random_string(HaystackRange),
Needles = [random_substring(NeedleRange,Haystack) ||
_ <- lists:duplicate(NumNeedles,a)],
Repl = random_string(NeedleRange),
Insertat = random_length(NeedleRange), %Sometimes larger than Repl
true = do_replace_comp(Needles,Haystack,Repl,[]),
true = do_replace_comp(Needles,Haystack,Repl,[global]),
true = do_replace_comp(Needles,Haystack,Repl,
[global,{insert_replaced,Insertat}]),
do_random_replace_comp2(N-1,NeedleRange,HaystackRange).
do_replace_comp(N,H,R,Opts) ->
A = ?MASK_ERROR(binref:replace(H,N,R,Opts)),
D = ?MASK_ERROR(binary:replace(H,binary:compile_pattern(N),R,Opts)),
if
(A =/= N) and is_binary(A) ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
case (A =:= D) of
true ->
true;
_ ->
io:format("Failed to replace ~s (haystack) by ~s (needle) "
"inserting ~s (replacement) and options ~p~n",
[H,N,R,Opts]),
io:format("A:~p,D:~p.~n",
[A,D]),
exit(mismatch)
end.
one_random_number(N) ->
M = ((N - 1) rem 10) + 1,
element(M,{$0,$1,$2,$3,$4,$5,$6,$7,$8,$9}).
one_random(N) ->
M = ((N - 1) rem 68) + 1,
element(M,{$a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,
$u,$v,$w,$x,$y,$z,$å,$ä,$ö,$A,$B,$C,$D,$E,$F,$G,$H,
$I,$J,$K,$L,$M,$N,$O,$P,$Q,$R,$S,$T,$U,$V,$W,$X,$Y,$Z,$Å,
$Ä,$Ö,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9}).
random_number({Min,Max}) -> % Min and Max are *length* of number in
% decimal positions
X = rand:uniform(Max - Min + 1) + Min - 1,
list_to_integer([one_random_number(rand:uniform(10)) || _ <- lists:seq(1,X)]).
random_length({Min,Max}) ->
rand:uniform(Max - Min + 1) + Min - 1.
random_string({Min,Max}) ->
X = rand:uniform(Max - Min + 1) + Min - 1,
list_to_binary([one_random(rand:uniform(68)) || _ <- lists:seq(1,X)]).
random_substring({Min,Max},Hay) ->
X = rand:uniform(Max - Min + 1) + Min - 1,
Y = byte_size(Hay),
Z = if
X > Y -> Y;
true -> X
end,
PMax = Y - Z,
Pos = rand:uniform(PMax + 1) - 1,
<<_:Pos/binary,Res:Z/binary,_/binary>> = Hay,
Res.
mask_error({'EXIT',{Err,_}}) ->
Err;
mask_error(Else) ->
Else.
make_unaligned(Bin0) when is_binary(Bin0) ->
Bin1 = <<0:3,Bin0/binary,31:5>>,
Sz = byte_size(Bin0),
<<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
Bin.
make_unaligned2(Bin0) when is_binary(Bin0) ->
Bin1 = <<31:5,Bin0/binary,0:3>>,
Sz = byte_size(Bin0),
<<31:5,Bin:Sz/binary,0:3>> = id(Bin1),
Bin.
id(I) -> I.
check_no_invalid_read_bug(Config) when is_list(Config) ->
check_no_invalid_read_bug(24);
check_no_invalid_read_bug(60) ->
ok;
check_no_invalid_read_bug(I) ->
N = 1 bsl I,
binary:encode_unsigned(N+N),
binary:encode_unsigned(N+N, little),
check_no_invalid_read_bug(I+1).