1: %% -*- coding: utf-8 -*- 2: %% 3: %% %CopyrightBegin% 4: %% 5: %% Copyright Ericsson AB 2008-2012. All Rights Reserved. 6: %% 7: %% The contents of this file are subject to the Erlang Public License, 8: %% Version 1.1, (the "License"); you may not use this file except in 9: %% compliance with the License. You should have received a copy of the 10: %% Erlang Public License along with this software. If not, it can be 11: %% retrieved online at http://www.erlang.org/. 12: %% 13: %% Software distributed under the License is distributed on an "AS IS" 14: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15: %% the License for the specific language governing rights and limitations 16: %% under the License. 17: %% 18: %% %CopyrightEnd% 19: %% 20: -module(re_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, pcre/1,compile_options/1, 24: run_options/1,combined_options/1,replace_autogen/1, 25: global_capture/1,replace_input_types/1,replace_return/1, 26: split_autogen/1,split_options/1,split_specials/1, 27: error_handling/1,pcre_cve_2008_2371/1, 28: pcre_compile_workspace_overflow/1,re_infinite_loop/1]). 29: 30: -include_lib("test_server/include/test_server.hrl"). 31: -include_lib("kernel/include/file.hrl"). 32: 33: suite() -> [{ct_hooks,[ts_install_cth]}]. 34: 35: all() -> 36: [pcre, compile_options, run_options, combined_options, 37: replace_autogen, global_capture, replace_input_types, 38: replace_return, split_autogen, split_options, 39: split_specials, error_handling, pcre_cve_2008_2371, 40: pcre_compile_workspace_overflow, re_infinite_loop]. 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: pcre(doc) -> 59: ["Run all applicable tests from the PCRE testsuites."]; 60: pcre(Config) when is_list(Config) -> 61: Dog = ?t:timetrap(?t:minutes(3)), 62: RootDir = ?config(data_dir, Config), 63: Res = run_pcre_tests:test(RootDir), 64: 0 = lists:sum([ X || {X,_,_} <- Res ]), 65: ?t:timetrap_cancel(Dog), 66: {comment,Res}. 67: 68: compile_options(doc) -> 69: ["Test all documented compile options"]; 70: compile_options(Config) when is_list(Config) -> 71: ?line ok = ctest("ABDabcdABCD","abcd",[],true,{match,[{3,4}]}), 72: ?line ok = ctest("ABDabcdABCD","abcd",[anchored],true,nomatch), 73: ?line ok = ctest("ABDabcdABCD",".*abcd",[anchored],true,{match,[{0,7}]}), 74: ?line ok = ctest("ABCabcdABC","ABCD",[],true,nomatch), 75: ?line ok = ctest("ABCabcdABC","ABCD",[caseless],true,{match,[{3,4}]}), 76: ?line ok = ctest("abcdABC\n","ABC$",[],true,{match,[{4,3}]}), 77: ?line ok = ctest("abcdABC\n","ABC$",[dollar_endonly],true,nomatch), 78: ?line ok = ctest("abcdABC\n","ABC.",[],true,nomatch), 79: ?line ok = ctest("abcdABC\n","ABC.",[dotall],true,{match,[{4,4}]}), 80: ?line ok = ctest("abcdABCD","ABC .",[],true,nomatch), 81: ?line ok = ctest("abcdABCD","ABC .",[extended],true,{match,[{4,4}]}), 82: ?line ok = ctest("abcd\nABCD","ABC",[],true,{match,[{5,3}]}), 83: ?line ok = ctest("abcd\nABCD","ABC",[firstline],true,nomatch), 84: ?line ok = ctest("abcd\nABCD","^ABC",[],true,nomatch), 85: ?line ok = ctest("abcd\nABCD","^ABC",[multiline],true,{match,[{5,3}]}), 86: ?line ok = ctest("abcdABCD","(ABC)",[],true,{match,[{4,3},{4,3}]}), 87: ?line ok = ctest("abcdABCD","(ABC)",[no_auto_capture],true,{match,[{4,3}]}), 88: ?line ok = ctest(notused,"(?<FOO>ABC)|(?<FOO>DEF)",[],false,notused), 89: ?line ok = ctest("abcdABCD","(?<FOO>ABC)|(?<FOO>DEF)",[dupnames],true,{match,[{4,3},{4,3}]}), 90: ?line ok = ctest("abcdABCDabcABCD","abcd.*D",[],true,{match,[{0,15}]}), 91: ?line ok = ctest("abcdABCDabcABCD","abcd.*D",[ungreedy],true,{match,[{0,8}]}), 92: ?line ok = ctest("abcdABCabcABC\nD","abcd.*D",[],true,nomatch), 93: ?line ok = ctest("abcdABCabcABC\nD","abcd.*D",[{newline,cr}],true,{match,[{0,15}]}), 94: ?line ok = ctest("abcdABCabcABC\rD","abcd.*D",[],true,{match,[{0,15}]}), 95: ?line ok = ctest("abcdABCabcABC\rD","abcd.*D",[{newline,lf}],true,{match,[{0,15}]}), 96: ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,lf}],true,nomatch), 97: ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,cr}],true,nomatch), 98: ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,crlf}],true,{match,[{7,4}]}), 99: 100: ?line ok = ctest("abcdABCabcd\r","abcd$",[{newline,crlf}],true,nomatch), 101: ?line ok = ctest("abcdABCabcd\n","abcd$",[{newline,crlf}],true,nomatch), 102: ?line ok = ctest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}), 103: 104: ?line ok = ctest("abcdABCabcd\r","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}), 105: ?line ok = ctest("abcdABCabcd\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}), 106: ok. 107: 108: run_options(doc) -> 109: ["Test all documented run specific options"]; 110: run_options(Config) when is_list(Config) -> 111: ?line rtest("ABCabcdABC","abc",[],[],true), 112: ?line rtest("ABCabcdABC","abc",[anchored],[],false), 113: % Anchored in run overrides unanchored in compilation 114: ?line rtest("ABCabcdABC","abc",[],[anchored],false), 115: 116: ?line rtest("","a?b?",[],[],true), 117: ?line rtest("","a?b?",[],[notempty],false), 118: 119: ?line rtest("abc","^a",[],[],true), 120: ?line rtest("abc","^a",[],[notbol],false), 121: ?line rtest("ab\nc","^a",[multiline],[],true), 122: ?line rtest("ab\nc","^a",[multiline],[notbol],false), 123: ?line rtest("ab\nc","^c",[multiline],[notbol],true), 124: 125: ?line rtest("abc","c$",[],[],true), 126: ?line rtest("abc","c$",[],[noteol],false), 127: 128: ?line rtest("ab\nc","b$",[multiline],[],true), 129: ?line rtest("ab\nc","c$",[multiline],[],true), 130: ?line rtest("ab\nc","b$",[multiline],[noteol],true), 131: ?line rtest("ab\nc","c$",[multiline],[noteol],false), 132: 133: ?line rtest("abc","ab",[],[{offset,0}],true), 134: ?line rtest("abc","ab",[],[{offset,1}],false), 135: 136: ?line rtest("abcdABCabcABC\nD","abcd.*D",[],[],false), 137: ?line rtest("abcdABCabcABC\nD","abcd.*D",[],[{newline,cr}],true), 138: ?line rtest("abcdABCabcABC\rD","abcd.*D",[],[],true), 139: ?line rtest("abcdABCabcABC\rD","abcd.*D",[{newline,cr}],[{newline,lf}],true), 140: ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,lf}],false), 141: ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,cr}],false), 142: ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,crlf}],true), 143: 144: ?line rtest("abcdABCabcd\r","abcd$",[],[{newline,crlf}],false), 145: ?line rtest("abcdABCabcd\n","abcd$",[],[{newline,crlf}],false), 146: ?line rtest("abcdABCabcd\r\n","abcd$",[],[{newline,anycrlf}],true), 147: 148: ?line rtest("abcdABCabcd\r","abcd$",[],[{newline,anycrlf}],true), 149: ?line rtest("abcdABCabcd\n","abcd$",[],[{newline,anycrlf}],true), 150: 151: ?line {ok,MP} = re:compile(".*(abcd).*"), 152: ?line {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[]), 153: ?line {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all}]), 154: ?line {match,[{0,10},{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all,index}]), 155: ?line {match,["ABCabcdABC","abcd"]} = re:run("ABCabcdABC",MP,[{capture,all,list}]), 156: ?line {match,[<<"ABCabcdABC">>,<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all,binary}]), 157: ?line {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first}]), 158: ?line {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first,index}]), ?line {match,["ABCabcdABC"]} = re:run("ABCabcdABC",MP,[{capture,first,list}]), 159: ?line {match,[<<"ABCabcdABC">>]} = re:run("ABCabcdABC",MP,[{capture,first,binary}]), 160: 161: ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first}]), 162: ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,index}]), 163: ?line {match,["abcd"]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,list}]), 164: ?line {match,[<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all_but_first,binary}]), 165: 166: ?line match = re:run("ABCabcdABC",MP,[{capture,none}]), 167: ?line match = re:run("ABCabcdABC",MP,[{capture,none,index}]), 168: ?line match = re:run("ABCabcdABC",MP,[{capture,none,list}]), 169: ?line match = re:run("ABCabcdABC",MP,[{capture,none,binary}]), 170: 171: ?line {ok,MP2} = re:compile(".*(?<FOO>abcd).*"), 172: ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,[1]}]), 173: ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,['FOO']}]), 174: ?line {match,[{3,4}]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"]}]), 175: ?line {match,["abcd"]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"],list}]), 176: ?line {match,[<<"abcd">>]} = re:run("ABCabcdABC",MP2,[{capture,["FOO"],binary}]), 177: 178: ?line {match,[{-1,0}]} = re:run("ABCabcdABC",MP2,[{capture,[200]}]), 179: ?line {match,[{-1,0}]} = re:run("ABCabcdABC",MP2,[{capture,['BAR']}]), 180: ?line {match,[""]} = re:run("ABCabcdABC",MP2,[{capture,[200],list}]), 181: ?line {match,[""]} = re:run("ABCabcdABC",MP2,[{capture,['BAR'],list}]), 182: ?line {match,[<<>>]} = re:run("ABCabcdABC",MP2,[{capture,[200],binary}]), 183: ?line {match,[<<>>]} = re:run("ABCabcdABC",MP2,[{capture,['BAR'],binary}]), 184: 185: ?line {ok, MP3} = re:compile(".*((?<FOO>abdd)|a(..d)).*"), 186: ?line {match,[{0,10},{3,4},{-1,0},{4,3}]} = re:run("ABCabcdABC",MP3,[]), 187: ?line {match,[{0,10},{3,4},{-1,0},{4,3}]} = re:run("ABCabcdABC",MP3,[{capture,all,index}]), 188: ?line {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]} = re:run("ABCabcdABC",MP3,[{capture,all,binary}]), 189: ?line {match,["ABCabcdABC","abcd",[],"bcd"]} = re:run("ABCabcdABC",MP3,[{capture,all,list}]), 190: ok. 191: 192: 193: 194: combined_options(doc) -> 195: ["Test compile options given directly to run"]; 196: combined_options(Config) when is_list(Config) -> 197: ?line ok = crtest("ABDabcdABCD","abcd",[],true,{match,[{3,4}]}), 198: ?line ok = crtest("ABDabcdABCD","abcd",[anchored],true,nomatch), 199: ?line ok = crtest("ABDabcdABCD",".*abcd",[anchored],true,{match,[{0,7}]}), 200: ?line ok = crtest("ABCabcdABC","ABCD",[],true,nomatch), 201: ?line ok = crtest("ABCabcdABC","ABCD",[caseless],true,{match,[{3,4}]}), 202: ?line ok = crtest("abcdABC\n","ABC$",[],true,{match,[{4,3}]}), 203: ?line ok = crtest("abcdABC\n","ABC$",[dollar_endonly],true,nomatch), 204: ?line ok = crtest("abcdABC\n","ABC.",[],true,nomatch), 205: ?line ok = crtest("abcdABC\n","ABC.",[dotall],true,{match,[{4,4}]}), 206: ?line ok = crtest("abcdABCD","ABC .",[],true,nomatch), 207: ?line ok = crtest("abcdABCD","ABC .",[extended],true,{match,[{4,4}]}), 208: ?line ok = crtest("abcd\nABCD","ABC",[],true,{match,[{5,3}]}), 209: ?line ok = crtest("abcd\nABCD","ABC",[firstline],true,nomatch), 210: ?line ok = crtest("abcd\nABCD","^ABC",[],true,nomatch), 211: ?line ok = crtest("abcd\nABCD","^ABC",[multiline],true,{match,[{5,3}]}), 212: ?line ok = crtest("abcdABCD","(ABC)",[],true,{match,[{4,3},{4,3}]}), 213: ?line ok = crtest("abcdABCD","(ABC)",[no_auto_capture],true,{match,[{4,3}]}), 214: ?line ok = crtest(notused,"(?<FOO>ABC)|(?<FOO>DEF)",[],false,notused), 215: ?line ok = crtest("abcdABCD","(?<FOO>ABC)|(?<FOO>DEF)",[dupnames],true,{match,[{4,3},{4,3}]}), 216: ?line ok = crtest("abcdABCDabcABCD","abcd.*D",[],true,{match,[{0,15}]}), 217: ?line ok = crtest("abcdABCDabcABCD","abcd.*D",[ungreedy],true,{match,[{0,8}]}), 218: ?line ok = ctest("abcdABCabcABC\nD","abcd.*D",[],true,nomatch), 219: ?line ok = crtest("abcdABCabcABC\nD","abcd.*D",[{newline,cr}],true,{match,[{0,15}]}), 220: ?line ok = crtest("abcdABCabcABC\rD","abcd.*D",[],true,{match,[{0,15}]}), 221: ?line ok = crtest("abcdABCabcABC\rD","abcd.*D",[{newline,lf}],true,{match,[{0,15}]}), 222: ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,lf}],true,nomatch), 223: ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,cr}],true,nomatch), 224: ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,crlf}],true,{match,[{7,4}]}), 225: 226: ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,crlf}],true,nomatch), 227: ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,crlf}],true,nomatch), 228: ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}), 229: 230: ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}), 231: ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf}],true,{match,[{7,4}]}), 232: 233: ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}), 234: 235: ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}), 236: 237: ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf},{capture,all,list}],true,{match,["abcd"]}), 238: 239: ?line ok = crtest("abcdABCabcd\r\n","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}), 240: 241: ?line ok = crtest("abcdABCabcd\r","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}), 242: ?line ok = crtest("abcdABCabcd\n","abcd$",[{newline,anycrlf},{capture,all,binary}],true,{match,[<<"abcd">>]}), 243: 244: % Check that unique run-options fail in compile only case: 245: ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},{capture,all,binary}])), 246: ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},{offset,3}])), 247: ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},notempty])), 248: ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},notbol])), 249: ?line {'EXIT',{badarg,_}} = (catch re:compile("abcd$",[{newline,anycrlf},noteol])), 250: 251: 252: ?line {match,_} = re:run("abcdABCabcd\r\n","abcd$",[{newline,crlf}]), 253: ?line nomatch = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf}]), 254: ?line {match,_} = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf},multiline]), 255: ?line nomatch = re:run("abcdABCabcd\r\nefgh","efgh$",[{newline,crlf},multiline,noteol]), 256: ?line {match,_} = re:run("abcdABCabcd\r\nefgh","abcd$",[{newline,crlf},multiline,noteol]), 257: ?line {match,_} = re:run("abcdABCabcd\r\nefgh","^abcd",[{newline,crlf},multiline,noteol]), 258: ?line nomatch = re:run("abcdABCabcd\r\nefgh","^abcd",[{newline,crlf},multiline,notbol]), 259: ?line {match,_} = re:run("abcdABCabcd\r\nefgh","^efgh",[{newline,crlf},multiline,notbol]), 260: ?line {match,_} = re:run("ABC\nD","[a-z]*",[{newline,crlf}]), 261: ?line nomatch = re:run("ABC\nD","[a-z]*",[{newline,crlf},notempty]), 262: ok. 263: 264: replace_autogen(doc) -> 265: ["Test replace with autogenerated erlang module"]; 266: replace_autogen(Config) when is_list(Config) -> 267: Dog = ?t:timetrap(?t:minutes(3)), 268: re_testoutput1_replacement_test:run(), 269: ?t:timetrap_cancel(Dog), 270: ok. 271: 272: global_capture(doc) -> 273: ["Tests capture options together with global searching"]; 274: global_capture(Config) when is_list(Config) -> 275: Dog = ?t:timetrap(?t:minutes(3)), 276: ?line {match,[{3,4}]} = re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]), 277: ?line {match,[{10,4}]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[{capture,[1]}]), 278: ?line {match,[[{10,4}]]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[global,{capture,[1]}]), 279: ?line {match,[{3,4}]} = re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]), 280: ?line {match,[{10,4}]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[{capture,['FOO']}]), 281: ?line {match,[[{10,4}]]} = re:run("ABCabcdABCabcdA",".*(?<FOO>abcd).*",[global,{capture,['FOO']}]), 282: ?line {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global]), 283: ?line {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all}]), 284: ?line {match,[[{3,4},{3,4}],[{10,4},{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all,index}]), 285: ?line {match,[[{3,4}],[{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,first}]), 286: ?line {match,[[{3,4}],[{10,4}]]} = re:run("ABCabcdABCabcdA","(?<FOO>abcd)",[global,{capture,all_but_first}]), 287: ?line {match,[[<<"bcd">>],[<<"bcd">>]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all_but_first,binary}]), 288: ?line {match,[["bcd"],["bcd"]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all_but_first,list}]), 289: ?line {match,[["abcd","bcd"],["abcd","bcd"]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,list}]), 290: ?line {match,[[<<"abcd">>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,binary}]), 291: ?line {match,[[{3,4},{4,3}],[{10,4},{11,3}]]} = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,all,index}]), 292: ?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,index}]), 293: ?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,binary}]), 294: ?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,list}]), 295: ?line {match,[[<<195,133,98,99,100>>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,binary},unicode]), 296: ?line {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run(<<"ABC",8#303,8#205,"bcdABCabcdA">>,".(?<FOO>bcd)",[global,{capture,all,list},unicode]), 297: ?line {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,list},unicode]), 298: ?line {match,[[{3,5},{5,3}],[{11,4},{12,3}]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,index},unicode]), 299: ?t:timetrap_cancel(Dog), 300: ok. 301: 302: replace_input_types(doc) -> 303: ["Tests replace with different input types"]; 304: replace_input_types(Config) when is_list(Config) -> 305: Dog = ?t:timetrap(?t:minutes(3)), 306: ?line <<"abcd">> = re:replace("abcd","Z","X",[{return,binary},unicode]), 307: ?line <<"abcd">> = re:replace("abcd","\x{400}","X",[{return,binary},unicode]), 308: ?line <<"a",208,128,"cd">> = re:replace(<<"abcd">>,"b","\x{400}",[{return,binary},unicode]), 309: ?t:timetrap_cancel(Dog), 310: ok. 311: 312: replace_return(doc) -> 313: ["Tests return options of replace together with global searching"]; 314: replace_return(Config) when is_list(Config) -> 315: Dog = ?t:timetrap(?t:minutes(3)), 316: ?line {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")), 317: ?line <<"nasse">> = re:replace(<<"nisse">>,"i","a",[{return,binary}]), 318: ?line <<"ABCÅXABCXA">> = re:replace("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}]), 319: 320: ?line [<<"ABCÅ">>, 321: <<"X">>, 322: <<"ABC">>, 323: <<"X">> | 324: <<"A">> ] = 325: re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}]), 326: ?line "ABCÅXABCXA" = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode]), 327: ?line <<65,66,67,195,133,88,65,66,67,88,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode]), 328: ?line <<65,66,67,195,133,88,65,66,67,97,98,99,100,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode]), 329: ?line <<"iXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}]), 330: ?line <<"jXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}]), 331: ?line <<"Xk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}]), 332: ?line <<"9X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}]), 333: ?line <<"0X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}]), 334: ?line <<"X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}]), 335: ?line <<"971">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}]), 336: ?line <<"071">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}]), 337: ?line <<"71">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}]), 338: ?line "a\x{400}bcX" = re:replace("a\x{400}bcd","d","X",[global,{return,list},unicode]), 339: ?line <<"a",208,128,"bcX">> = re:replace("a\x{400}bcd","d","X",[global,{return,binary},unicode]), 340: ?line "a\x{400}bcd" = re:replace("a\x{400}bcd","Z","X",[global,{return,list},unicode]), 341: ?line <<"a",208,128,"bcd">> = re:replace("a\x{400}bcd","Z","X",[global,{return,binary},unicode]), 342: ?t:timetrap_cancel(Dog), 343: ok. 344: 345: rtest(Subj, RE, Copt, Ropt, true) -> 346: {ok,MP} = re:compile(RE,Copt), 347: {match,_} = re:run(Subj,MP,Ropt), 348: ok; 349: rtest(Subj, RE, Copt, Ropt, false) -> 350: {ok,MP} = re:compile(RE,Copt), 351: nomatch = re:run(Subj,MP,Ropt), 352: ok. 353: 354: ctest(_,RE,Options,false,_) -> 355: case re:compile(RE,Options) of 356: {ok,_} -> 357: error; 358: {error,_} -> 359: ok 360: end; 361: ctest(Subject,RE,Options,true,Result) -> 362: try 363: {ok, Prog} = re:compile(RE,Options), 364: Result = re:run(Subject,Prog,[]), 365: ok 366: catch 367: _:_ -> 368: error 369: end. 370: crtest(_,RE,Options,false,_) -> 371: case (catch re:run("",RE,Options)) of 372: {'EXIT',{badarg,_}} -> 373: ok; 374: _ -> 375: error 376: end; 377: crtest(Subject,RE,Options,true,Result) -> 378: try 379: Result = re:run(Subject,RE,Options), 380: ok 381: catch 382: _:_ -> 383: error 384: end. 385: 386: split_autogen(doc) -> 387: ["Test split with autogenerated erlang module"]; 388: split_autogen(Config) when is_list(Config) -> 389: Dog = ?t:timetrap(?t:minutes(3)), 390: re_testoutput1_split_test:run(), 391: ?t:timetrap_cancel(Dog), 392: ok. 393: 394: split_options(doc) -> 395: ["Test special options to split."]; 396: split_options(Config) when is_list(Config) -> 397: Dog = ?t:timetrap(?t:minutes(1)), 398: ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,trim]), 399: ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,{parts,0}]), 400: ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] = 401: re:split("a b c ","( )",[{parts,infinity},group]), 402: ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] = 403: re:split("a b c ","( )",[group]), 404: ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], 405: [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] = 406: re:split(" a b c d ","( +)",[group,trim]), 407: ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], 408: [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] = 409: re:split(" a b c d ","( +)",[{parts,0},group]), 410: ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>], 411: [<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]] = 412: re:split(" a b c d ","( +)",[{parts,infinity},group]), 413: ?line [[<<"a">>,<<" ">>],[<<"b c d">>]] = 414: re:split("a b c d","( +)",[{parts,2},group]), 415: ?line [[[967]," "],["b c d"]] = 416: re:split([967]++" b c d","( +)", 417: [{parts,2},group,{return,list},unicode]), 418: ?line [[<<207,135>>,<<" ">>],[<<"b c d">>]] = 419: re:split([967]++" b c d","( +)", 420: [{parts,2},group,{return,binary},unicode]), 421: ?line {'EXIT',{badarg,_}} = 422: (catch re:split([967]++" b c d","( +)", 423: [{parts,2},group,{return,binary}])), 424: ?line {'EXIT',{badarg,_}} = 425: (catch re:split("a b c d","( +)",[{parts,-2}])), 426: ?line {'EXIT',{badarg,_}} = 427: (catch re:split("a b c d","( +)",[{parts,banan}])), 428: ?line {'EXIT',{badarg,_}} = 429: (catch re:split("a b c d","( +)",[{capture,all}])), 430: ?line {'EXIT',{badarg,_}} = 431: (catch re:split("a b c d","( +)",[{capture,[],binary}])), 432: % Parts 0 is equal to no parts specification (implicit strip) 433: ?line ["a"," ","b"," ","c"," ","d"] = 434: re:split("a b c d","( *)",[{parts,0},{return,list}]), 435: ?t:timetrap_cancel(Dog), 436: ok. 437: 438: join([]) -> []; 439: join([A]) -> [A]; 440: join([H|T]) -> [H,<<":">>|join(T)]. 441: 442: split_specials(doc) -> 443: ["Some special cases of split that are easy to get wrong."]; 444: split_specials(Config) when is_list(Config) -> 445: %% More or less just to remember these icky cases 446: Dog = ?t:timetrap(?t:minutes(1)), 447: ?line <<"::abd:f">> = 448: iolist_to_binary(join(re:split("abdf","^(?!(ab)de|x)(abd)(f)",[trim]))), 449: ?line <<":abc2xyzabc3">> = 450: iolist_to_binary(join(re:split("abc1abc2xyzabc3","\\Aabc.",[trim]))), 451: ?t:timetrap_cancel(Dog), 452: ok. 453: 454: 455: %% Test that errors are handled correctly by the erlang code. 456: error_handling(_Config) -> 457: case test_server:is_native(re) of 458: true -> 459: %% Exceptions from native code look too different. 460: {skip,"re is native"}; 461: false -> 462: error_handling() 463: end. 464: 465: error_handling() -> 466: % This test checks the exception tuples manufactured in the erlang 467: % code to hide the trapping from the user at least when it comes to errors 468: Dog = ?t:timetrap(?t:minutes(1)), 469: % The malformed precomiled RE is detected after 470: % the trap to re:grun from grun, in the grun function clause 471: % that handles precompiled expressions 472: ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_}, 473: {?MODULE,error_handling,0,_} | _]}} = 474: (catch re:run("apa",{1,2,3,4},[global])), 475: % An invalid capture list will also cause a badarg late, 476: % but with a non pre compiled RE, the exception should be thrown by the 477: % grun function clause that handles RE's compiled implicitly by 478: % the run/3 BIF before trapping. 479: ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_}, 480: {?MODULE,error_handling,0,_} | _]}} = 481: (catch re:run("apa","p",[{capture,[1,{a}]},global])), 482: % And so the case of a precompiled expression together with 483: % a compile-option (binary and list subject): 484: ?line {ok,RE} = re:compile("(p)"), 485: ?line {match,[[{1,1},{1,1}]]} = re:run(<<"apa">>,RE,[global]), 486: ?line {match,[[{1,1},{1,1}]]} = re:run("apa",RE,[global]), 487: ?line {'EXIT',{badarg,[{re,run, 488: [<<"apa">>, 489: {re_pattern,1,0,_}, 490: [global,unicode]],_}, 491: {?MODULE,error_handling,0,_} | _]}} = 492: (catch re:run(<<"apa">>,RE,[global,unicode])), 493: ?line {'EXIT',{badarg,[{re,run, 494: ["apa", 495: {re_pattern,1,0,_}, 496: [global,unicode]],_}, 497: {?MODULE,error_handling,0,_} | _]}} = 498: (catch re:run("apa",RE,[global,unicode])), 499: ?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[])), 500: ?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])), 501: % The replace errors: 502: ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_}, 503: {?MODULE,error_handling,0,_} | _]}} = 504: (catch re:replace("apa",{1,2,3,4},"X",[])), 505: ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]],_}, 506: {?MODULE,error_handling,0,_} | _]}} = 507: (catch re:replace("apa",{1,2,3,4},"X",[global])), 508: ?line {'EXIT',{badarg,[{re,replace, 509: ["apa", 510: {re_pattern,1,0,_}, 511: "X", 512: [unicode]],_}, 513: {?MODULE,error_handling,0,_} | _]}} = 514: (catch re:replace("apa",RE,"X",[unicode])), 515: ?line <<"aXa">> = iolist_to_binary(re:replace("apa","p","X",[])), 516: ?line {'EXIT',{badarg,[{re,replace, 517: ["apa","p","X",[{capture,all,binary}]],_}, 518: {?MODULE,error_handling,0,_} | _]}} = 519: (catch iolist_to_binary(re:replace("apa","p","X", 520: [{capture,all,binary}]))), 521: ?line {'EXIT',{badarg,[{re,replace, 522: ["apa","p","X",[{capture,all}]],_}, 523: {?MODULE,error_handling,0,_} | _]}} = 524: (catch iolist_to_binary(re:replace("apa","p","X", 525: [{capture,all}]))), 526: ?line {'EXIT',{badarg,[{re,replace, 527: ["apa","p","X",[{return,banana}]],_}, 528: {?MODULE,error_handling,0,_} | _]}} = 529: (catch iolist_to_binary(re:replace("apa","p","X", 530: [{return,banana}]))), 531: ?line {'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])), 532: % Badarg, not compile error. 533: ?line {'EXIT',{badarg,[{re,replace, 534: ["apa","(p","X",[{return,banana}]],_}, 535: {?MODULE,error_handling,0,_} | _]}} = 536: (catch iolist_to_binary(re:replace("apa","(p","X", 537: [{return,banana}]))), 538: % And the split errors: 539: ?line [<<"a">>,<<"a">>] = (catch re:split("apa","p",[])), 540: ?line [<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])), 541: ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]],_}, 542: {?MODULE,error_handling,0,_} | _]}} = 543: (catch re:split("apa","p",[global])), 544: ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_}, 545: {?MODULE,error_handling,0,_} | _]}} = 546: (catch re:split("apa","p",[{capture,all}])), 547: ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_}, 548: {?MODULE, error_handling,0,_} | _]}} = 549: (catch re:split("apa","p",[{capture,all,binary}])), 550: ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_}, 551: {?MODULE,error_handling,0,_} | _]}} = 552: (catch re:split("apa",{1,2,3,4})), 553: ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_}, 554: {?MODULE,error_handling,0,_} | _]}} = 555: (catch re:split("apa",{1,2,3,4},[])), 556: ?line {'EXIT',{badarg,[{re,split, 557: ["apa", 558: RE, 559: [unicode]],_}, 560: {?MODULE,error_handling,0,_} | _]}} = 561: (catch re:split("apa",RE,[unicode])), 562: ?line {'EXIT',{badarg,[{re,split, 563: ["apa", 564: RE, 565: [{return,banana}]],_}, 566: {?MODULE,error_handling,0,_} | _]}} = 567: (catch re:split("apa",RE,[{return,banana}])), 568: ?line {'EXIT',{badarg,[{re,split, 569: ["apa", 570: RE, 571: [banana]],_}, 572: {?MODULE,error_handling,0,_} | _]}} = 573: (catch re:split("apa",RE,[banana])), 574: ?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")), 575: %Exception on bad argument, not compilation error 576: ?line {'EXIT',{badarg,[{re,split, 577: ["apa", 578: "(p", 579: [banana]],_}, 580: {?MODULE,error_handling,0,_} | _]}} = 581: (catch re:split("apa","(p",[banana])), 582: ?t:timetrap_cancel(Dog), 583: ok. 584: 585: pcre_cve_2008_2371(doc) -> 586: "Fix as in http://vcs.pcre.org/viewvc?revision=360&view=revision"; 587: pcre_cve_2008_2371(Config) when is_list(Config) -> 588: %% Make sure it doesn't crash the emulator. 589: re:compile(<<"(?i)[\xc3\xa9\xc3\xbd]|[\xc3\xa9\xc3\xbdA]">>, [unicode]), 590: ok. 591: 592: pcre_compile_workspace_overflow(doc) -> 593: "Patch from http://vcs.pcre.org/viewvc/code/trunk/pcre_compile.c?r1=504&r2=505&view=patch"; 594: pcre_compile_workspace_overflow(Config) when is_list(Config) -> 595: N = 819, 596: ?line {error,{"internal error: overran compiling workspace",799}} = 597: re:compile([lists:duplicate(N, $(), lists:duplicate(N, $))]), 598: ok. 599: re_infinite_loop(doc) -> 600: "Make sure matches that really loop infinitely actually fail"; 601: re_infinite_loop(Config) when is_list(Config) -> 602: Dog = ?t:timetrap(?t:minutes(1)), 603: ?line Str = 604: "http:/www.flickr.com/slideShow/index.gne?group_id=&user_id=69845378@N0", 605: ?line EMail_regex = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+" 606: ++ "(\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*" 607: ++ "@.*([a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+" 608: ++ "([a-zA-Z]{2}|com|org|net|gov|mil" 609: ++ "|biz|info|mobi|name|aero|jobs|museum)", 610: ?line nomatch = re:run(Str, EMail_regex), 611: ?t:timetrap_cancel(Dog), 612: ok.