diff options
author | Patrik Nyblom <[email protected]> | 2010-04-20 17:32:48 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2010-05-17 15:51:49 +0200 |
commit | f06f499690ef1f5c8659128095a82d6c9b834d68 (patch) | |
tree | a7a6430214c9e1a23f7181730425b140d28a0610 | |
parent | ba8c9c7c1594b4870936814caf3520a0f4e312f7 (diff) | |
download | otp-f06f499690ef1f5c8659128095a82d6c9b834d68.tar.gz otp-f06f499690ef1f5c8659128095a82d6c9b834d68.tar.bz2 otp-f06f499690ef1f5c8659128095a82d6c9b834d68.zip |
Add random compare testcase
Fix heap-hole when trapping in binary.c
Fix boyer more segfaulting when searchstring is longer than haystack
-rw-r--r-- | erts/emulator/beam/binary.c | 30 | ||||
-rw-r--r-- | lib/stdlib/test/Makefile | 2 | ||||
-rw-r--r-- | lib/stdlib/test/binary_module_SUITE.erl | 72 | ||||
-rw-r--r-- | lib/stdlib/test/binref.erl | 34 |
4 files changed, 100 insertions, 38 deletions
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index 2b110e8b82..f51815d615 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -782,7 +782,6 @@ typedef struct _ac_trie { } ACTrie; typedef struct _bm_data { - int ret_tuple; byte *x; Sint len; Sint *goodshift; @@ -868,7 +867,6 @@ static BMData *create_bmdata(MyAllocator *my, byte *x, Uint len, Binary **the_bi memcpy(bmd->x,x,len); bmd->len = len; bmd->goodshift = my_alloc(my,sizeof(Uint) * len); - bmd->ret_tuple = 0; *the_bin = mb; return bmd; } @@ -1304,7 +1302,7 @@ static void compute_goodshifts(BMData *bmd) typedef struct { Sint pos; - Uint len; + Sint len; } BMFindFirstState; #define BM_OK 0 /* used only for find_all */ @@ -1315,14 +1313,14 @@ typedef struct { static void bm_init_find_first_match(BMFindFirstState *state, Sint startpos, Uint len) { state->pos = startpos; - state->len = len; + state->len = (Sint) len; } static Sint bm_find_first_match(BMFindFirstState *state, BMData *bmd, byte *haystack, Uint reductions) { Sint blen = bmd->len; - Uint len = state->len; + Sint len = state->len; Sint *gs = bmd->goodshift; Sint *bs = bmd->badshift; byte *needle = bmd->x; @@ -1347,7 +1345,7 @@ static Sint bm_find_first_match(BMFindFirstState *state, BMData *bmd, byte *hays typedef struct { Sint pos; - Uint len; + Sint len; Uint m; Uint allocated; FindallData *out; @@ -1356,7 +1354,7 @@ typedef struct { static void bm_init_find_all(BMFindAllState *state, Sint startpos, Uint len) { state->pos = startpos; - state->len = len; + state->len = (Sint) len; state->m = 0; state->allocated = 0; state->out = NULL; @@ -1396,7 +1394,7 @@ static Sint bm_find_all_non_overlapping(BMFindAllState *state, BMData *bmd, byte *haystack, Uint reductions) { Sint blen = bmd->len; - Uint len = state->len; + Sint len = state->len; Sint *gs = bmd->goodshift; Sint *bs = bmd->badshift; byte *needle = bmd->x; @@ -1454,13 +1452,11 @@ static int do_binary_match_compile(Eterm argument, Eterm *tag, Binary **binp) Eterm t, b, comp_term = NIL; Uint characters; Uint words; - int return_tuple = 0; characters = 0; words = 0; if (is_list(argument)) { - return_tuple = 1; t = argument; while (is_list(t)) { b = CAR(list_val(t)); @@ -1509,7 +1505,6 @@ static int do_binary_match_compile(Eterm argument, Eterm *tag, Binary **binp) bytes = erts_get_aligned_binary_bytes(comp_term, &temp_alloc); } bmd = create_bmdata(&my, bytes, characters, &bin); - bmd->ret_tuple = return_tuple; compute_badshifts(bmd); compute_goodshifts(bmd); erts_free_aligned_binary_bytes(temp_alloc); @@ -1625,12 +1620,10 @@ static int do_binary_match(Process *p, Eterm subject, Uint hsstart, Uint hslen, erts_free_aligned_binary_bytes(temp_alloc); return DO_BIN_MATCH_RESTART; } else { + Eterm erlen = erts_make_integer((Uint) bm->len, p); ret = erts_make_integer(pos,p); - if (bm->ret_tuple) { - Eterm erlen = erts_make_integer((Uint) bm->len, p); - hp = HAlloc(p,3); - ret = TUPLE2(hp, ret, erlen); - } + hp = HAlloc(p,3); + ret = TUPLE2(hp, ret, erlen); } erts_free_aligned_binary_bytes(temp_alloc); *res_term = ret; @@ -1927,7 +1920,7 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3) } runres = do_binary_match(BIF_P,BIF_ARG_1,hsstart,hslen,type,bin,NIL,&result); if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) { - Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE+3); + Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE); bin_term = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), bin); } else if (bin_term == NIL) { erts_bin_free(bin); @@ -2014,7 +2007,7 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3) } runres = do_binary_matches(BIF_P,BIF_ARG_1,hsstart,hslen,type,bin,NIL,&result); if (runres == DO_BIN_MATCH_RESTART && bin_term == NIL) { - Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE+3); + Eterm *hp = HAlloc(BIF_P, PROC_BIN_SIZE); bin_term = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), bin); } else if (bin_term == NIL) { erts_bin_free(bin); @@ -2054,7 +2047,6 @@ static void dump_bm_data(BMData *bm) int i,j; erts_printf("Dumping Boyer-More structure.\n"); erts_printf("=============================\n"); - erts_printf("Return tuple: %d\n",bm->ret_tuple); erts_printf("Searchstring [%ld]:\n", bm->len); erts_printf("<<"); for (i = 0; i < bm->len; ++i) { diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index 9beac93eb8..3bbd9ce318 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -9,6 +9,8 @@ MODULES= \ array_SUITE \ base64_SUITE \ beam_lib_SUITE \ + binary_module_SUITE \ + binref \ c_SUITE \ calendar_SUITE \ dets_SUITE \ diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl index 31d0812cfc..b6d3dde1d4 100644 --- a/lib/stdlib/test/binary_module_SUITE.erl +++ b/lib/stdlib/test/binary_module_SUITE.erl @@ -1,6 +1,6 @@ -module(binary_module_SUITE). --export([all/1, interesting/1]). +-export([all/1, interesting/1,random_ref_comp/1]). -define(STANDALONE,1). @@ -24,7 +24,7 @@ run() -> -endif. -all(suite) -> [interesting]. +all(suite) -> [interesting,random_ref_comp]. interesting(doc) -> @@ -94,3 +94,71 @@ do_interesting(Module) -> [<<"34">>,<<"34">>, <<"12347">>,<<"2346">>]), ok. + +random_ref_comp(doc) -> + ["Test pseudorandomly generated cases against reference imlementation"]; +random_ref_comp(Config) when is_list(Config) -> + put(success_counter,0), + random:seed({1271,769940,559934}), + do_random_match_comp(5000,{1,40},{30,1000}), + io:format("Number of successes: ~p~n",[get(success_counter)]), + do_random_match_comp2(5000,{1,40},{30,1000}), + io:format("Number of successes: ~p~n",[get(success_counter)]), + ok. + +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_match_comp(N,H) -> + A = binref:match(H,N), + B = binref:match(H,binref:compile_pattern([N])), + C = binary:match(H,N), + D = 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),(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. + +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_string({Min,Max}) -> + X = random:uniform(Max - Min + 1) + Min - 1, + list_to_binary([one_random(random:uniform(68)) || _ <- lists:seq(1,X)]). +random_substring({Min,Max},Hay) -> + X = random:uniform(Max - Min + 1) + Min - 1, + Y = byte_size(Hay), + Z = if + X > Y -> Y; + true -> X + end, + PMax = Y - Z, + Pos = random:uniform(PMax + 1) - 1, + <<_:Pos/binary,Res:Z/binary,_/binary>> = Hay, + Res. diff --git a/lib/stdlib/test/binref.erl b/lib/stdlib/test/binref.erl index 270796c8f9..d93f82fda9 100644 --- a/lib/stdlib/test/binref.erl +++ b/lib/stdlib/test/binref.erl @@ -33,8 +33,8 @@ match(Haystack,{Needles},Options) -> match(Haystack,Needles,Options) -> try true = is_binary(Haystack) and is_list(Needles), % badarg, not function_clause - case get_opts_match(Options,no) of - no -> + case get_opts_match(Options,nomatch) of + nomatch -> mloop(Haystack,Needles); {A,B} when B > 0 -> <<_:A/binary,SubStack:B/binary,_/binary>> = Haystack, @@ -45,7 +45,7 @@ match(Haystack,Needles,Options) -> <<_:Start/binary,SubStack:Len/binary,_/binary>> = Haystack, mloop(SubStack,Needles,Start,Len+Start); _ -> - no + nomatch end catch _:_ -> @@ -60,8 +60,8 @@ matches(Haystack,{Needles},Options) -> matches(Haystack,Needles,Options) -> try true = is_binary(Haystack) and is_list(Needles), % badarg, not function_clause - case get_opts_match(Options,no) of - no -> + case get_opts_match(Options,nomatch) of + nomatch -> msloop(Haystack,Needles); {A,B} when B > 0 -> <<_:A/binary,SubStack:B/binary,_/binary>> = Haystack, @@ -83,10 +83,10 @@ mloop(Haystack,Needles) -> mloop(Haystack,Needles,0,byte_size(Haystack)). mloop(_Haystack,_Needles,N,M) when N >= M -> - no; + nomatch; mloop(Haystack,Needles,N,M) -> - case mloop2(Haystack,Needles,N,no) of - no -> + case mloop2(Haystack,Needles,N,nomatch) of + nomatch -> % Not found <<_:8,NewStack/binary>> = Haystack, mloop(NewStack,Needles,N+1,M); @@ -100,8 +100,8 @@ msloop(Haystack,Needles) -> msloop(_Haystack,_Needles,N,M) when N >= M -> []; msloop(Haystack,Needles,N,M) -> - case mloop2(Haystack,Needles,N,no) of - no -> + case mloop2(Haystack,Needles,N,nomatch) of + nomatch -> % Not found <<_:8,NewStack/binary>> = Haystack, msloop(NewStack,Needles,N+1,M); @@ -123,7 +123,7 @@ mloop2(Haystack,[Needle|Tail],N,Candidate) -> case Haystack of <<Needle:NS/binary,_/binary>> -> NewCandidate = case Candidate of - no -> + nomatch -> {N,NS}; {N,ONS} when ONS < NS -> {N,NS}; @@ -145,10 +145,10 @@ split(Haystack,{Needles},Options) -> split(Haystack, Needles, Options); split(Haystack,Needles,Options) -> try - {Part,Global,Trim} = get_opts_split(Options,{no,false,false}), + {Part,Global,Trim} = get_opts_split(Options,{nomatch,false,false}), {Start,End,NewStack} = case Part of - no -> + nomatch -> {0,byte_size(Haystack),Haystack}; {A,B} when B >= 0 -> <<_:A/binary,SubStack:B/binary,_/binary>> = Haystack, @@ -164,7 +164,7 @@ split(Haystack,Needles,Options) -> msloop(NewStack,Needles,Start,End); true -> case mloop(NewStack,Needles,Start,End) of - no -> + nomatch -> []; X -> [X] @@ -206,10 +206,10 @@ replace(Haystack,{Needles},Replacement,Options) -> replace(Haystack,Needles,Replacement,Options) -> try true = is_binary(Replacement), % Make badarg instead of function clause - {Part,Global,Insert} = get_opts_replace(Options,{no,false,[]}), + {Part,Global,Insert} = get_opts_replace(Options,{nomatch,false,[]}), {Start,End,NewStack} = case Part of - no -> + nomatch -> {0,byte_size(Haystack),Haystack}; {A,B} when B >= 0 -> <<_:A/binary,SubStack:B/binary,_/binary>> = Haystack, @@ -225,7 +225,7 @@ replace(Haystack,Needles,Replacement,Options) -> msloop(NewStack,Needles,Start,End); true -> case mloop(NewStack,Needles,Start,End) of - no -> + nomatch -> []; X -> [X] |