1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(bs_match_SUITE). 22-compile(nowarn_shadow_vars). 23 24-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 25 init_per_group/2,end_per_group/2, 26 init_per_testcase/2,end_per_testcase/2, 27 size_shadow/1,int_float/1,otp_5269/1,null_fields/1,wiger/1, 28 bin_tail/1,save_restore/1, 29 partitioned_bs_match/1,function_clause/1, 30 unit/1,shared_sub_bins/1,bin_and_float/1, 31 dec_subidentifiers/1,skip_optional_tag/1,decode_integer/1, 32 wfbm/1,degenerated_match/1,bs_sum/1,coverage/1, 33 multiple_uses/1,zero_label/1,followed_by_catch/1, 34 matching_meets_construction/1,simon/1,matching_and_andalso/1, 35 otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1, 36 match_string/1,zero_width/1,bad_size/1,haystack/1, 37 cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1, 38 no_partition/1,calling_a_binary/1,binary_in_map/1, 39 match_string_opt/1,select_on_integer/1, 40 map_and_binary/1,unsafe_branch_caching/1, 41 bad_literals/1,good_literals/1,constant_propagation/1, 42 parse_xml/1,get_payload/1,escape/1,num_slots_different/1, 43 beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,erl_689/1, 44 bs_start_match2_defs/1]). 45 46-export([coverage_id/1,coverage_external_ignore/2]). 47 48-include_lib("common_test/include/ct.hrl"). 49-include_lib("syntax_tools/include/merl.hrl"). 50 51 52suite() -> 53 [{ct_hooks,[ts_install_cth]}, 54 {timetrap,{minutes,1}}]. 55 56all() -> 57 [{group,p}]. 58 59groups() -> 60 [{p,[parallel], 61 [size_shadow,int_float,otp_5269,null_fields,wiger, 62 bin_tail,save_restore, 63 partitioned_bs_match,function_clause,unit, 64 shared_sub_bins,bin_and_float,dec_subidentifiers, 65 skip_optional_tag,decode_integer,wfbm,degenerated_match,bs_sum, 66 coverage,multiple_uses,zero_label,followed_by_catch, 67 matching_meets_construction,simon, 68 matching_and_andalso,otp_7188,otp_7233,otp_7240, 69 otp_7498,match_string,zero_width,bad_size,haystack, 70 cover_beam_bool,matched_out_size,follow_fail_branch, 71 no_partition,calling_a_binary,binary_in_map, 72 match_string_opt,select_on_integer, 73 map_and_binary,unsafe_branch_caching, 74 bad_literals,good_literals,constant_propagation,parse_xml, 75 get_payload,escape,num_slots_different, 76 beam_bsm,guard,is_ascii,non_opt_eq,erl_689, 77 bs_start_match2_defs]}]. 78 79 80init_per_suite(Config) -> 81 test_lib:recompile(?MODULE), 82 Config. 83 84end_per_suite(_Config) -> 85 ok. 86 87init_per_group(_GroupName, Config) -> 88 Config. 89 90end_per_group(_GroupName, Config) -> 91 Config. 92 93 94init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 95 Config. 96 97end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 98 ok. 99 100size_shadow(Config) when is_list(Config) -> 101 %% Originally OTP-5270. 102 7 = size_shadow_1(), 103 7 = size_shadow_2(8), 104 7 = size_shadow_3(), 105 no = size_shadow_4(8), 106 Any = {any,term,goes}, 107 {2577,Any,-175,whatever} = 108 (size_shadow_5(Any, 12))(<<2577:12>>, -175, whatever), 109 {7777,Any,42,whatever} = 110 (size_shadow_6(Any, 13))(42, <<7777:13>>, whatever), 111 {<<45>>,<<>>} = size_shadow_7({int,1}, <<1:16,45>>), 112 {'EXIT',{function_clause,_}} = 113 (catch size_shadow_7({int,42}, <<1:16,45>>)), 114 ok. 115 116size_shadow_1() -> 117 L = 8, 118 F = fun(<<L:L,B:L>>) -> B end, 119 F(<<16:8, 7:16>>). 120 121size_shadow_2(L) -> 122 F = fun(<<L:L,B:L>>) -> B end, 123 F(<<16:8, 7:16>>). 124 125size_shadow_3() -> 126 L = 8, 127 F = fun(<<L:L,B:L,L:L>>) -> B end, 128 F(<<16:8, 7:16,16:16>>). 129 130size_shadow_4(L) -> 131 F = fun(<<L:L,B:L,L:L>>) -> B; 132 (_) -> no end, 133 F(<<16:8, 7:16,15:16>>). 134 135size_shadow_5(X, Y) -> 136 fun (<< A:Y >>, Y, B) -> fum(A, X, Y, B) end. 137 138size_shadow_6(X, Y) -> 139 fun (Y, << A:Y >>, B) -> fum(A, X, Y, B) end. 140 141fum(A, B, C, D) -> 142 {A,B,C,D}. 143 144size_shadow_7({int,N}, <<N:16,B:N/binary,T/binary>>) -> 145 {B,T}. 146 147 148int_float(Config) when is_list(Config) -> 149 %% OTP-5323 150 <<103133.0:64/float>> = <<103133:64/float>>, 151 <<103133:64/float>> = <<103133:64/float>>, 152 153 %% Coverage of error cases in sys_pre_expand:coerce_to_float/2. 154 case id(default) of 155 <<(1 bsl 1024):64/float>> -> 156 ct:fail(should_not_match); 157 default -> 158 ok 159 end. 160 161%% Stolen from erl_eval_SUITE and modified. 162%% OTP-5269. Bugs in the bit syntax. 163otp_5269(Config) when is_list(Config) -> 164 check(fun() -> L = 8, 165 F = fun(<<A:L,B:A>>) -> B end, 166 F(<<16:8, 7:16>>) 167 end, 168 7), 169 check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, 170 7), 171 check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, 172 32), 173 check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, 174 [32]), 175 check(fun() -> [X || <<A:8, 176 B:A>> <- [<<16:8,19:16>>], 177 <<X:8>> <- [<<B:8>>]] end, 178 [19]), 179 check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end, 180 28), 181 check(fun() -> 182 <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, 183 {Size,B,Rest} 184 end, 185 {2,<<"AB">>,<<"CD">>}), 186 check(fun() -> X = 32, 187 [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, 188 %% "binsize variable" ^ 189 [1,2]), 190 check(fun() -> 191 (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) -> 192 case A of 193 B -> wrong; 194 _ -> ok 195 end 196 end)(<<1,2,3,4>>) end, 197 ok), 198 ok. 199 200null_fields(Config) when is_list(Config) -> 201 check(fun() -> 202 W = id(0), 203 F = fun(<<_:W>>) -> tail; 204 (<<>>) -> empty 205 end, 206 F(<<>>) 207 end, tail), 208 check(fun() -> 209 F = fun(<<_/binary>>) -> tail; 210 (<<>>) -> empty 211 end, 212 F(<<>>) 213 end, tail), 214 ok. 215 216wiger(Config) when is_list(Config) -> 217 ok1 = wcheck(<<3>>), 218 ok2 = wcheck(<<1,2,3>>), 219 ok3 = wcheck(<<4>>), 220 {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), 221 {error,<<>>} = wcheck(<<>>), 222 ok. 223 224wcheck(<<A>>) when A==3-> 225 ok1; 226wcheck(<<_,_:2/binary>>) -> 227 ok2; 228wcheck(<<_>>) -> 229 ok3; 230wcheck(Other) -> 231 {error,Other}. 232 233bin_tail(Config) when is_list(Config) -> 234 S = <<"abcde">>, 235 $a = bin_tail_c(S, 0), 236 $c = bin_tail_c(S, 2), 237 $e = bin_tail_c(S, 4), 238 {'EXIT',_} = (catch bin_tail_c(S, 5)), 239 {'EXIT',_} = (catch bin_tail_c_var(S, 5)), 240 241 $a = bin_tail_d(S, 0), 242 $b = bin_tail_d(S, 8), 243 $d = bin_tail_d(S, 3*8), 244 {'EXIT',_} = (catch bin_tail_d_dead(S, 1)), 245 {'EXIT',_} = (catch bin_tail_d_dead(S, 9)), 246 {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)), 247 {'EXIT',_} = (catch bin_tail_d_var(S, 1)), 248 249 ok = bin_tail_e(<<2:2,0:1,1:5>>), 250 ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>), 251 error = bin_tail_e(<<3:2,1:1,1:5,42:64>>), 252 error = bin_tail_e(<<>>), 253 ok. 254 255bin_tail_c(Bin, Offset) -> 256 Res = bin_tail_c_dead(Bin, Offset), 257 <<_:Offset/binary,_,Tail/binary>> = Bin, 258 {Res,Tail} = bin_tail_c_var(Bin, Offset), 259 Res. 260 261bin_tail_c_dead(Bin, Offset) -> 262 <<_:Offset/binary,C,_/binary>> = Bin, 263 C. 264 265bin_tail_c_var(Bin, Offset) -> 266 <<_:Offset/binary,C,Tail/binary>> = Bin, 267 {C,Tail}. 268 269 270bin_tail_d(Bin, BitOffset) -> 271 Res = bin_tail_d_dead(Bin, BitOffset), 272 <<_:BitOffset,_:8,Tail/binary>> = Bin, 273 {Res,Tail} = bin_tail_d_var(Bin, BitOffset), 274 Res. 275 276bin_tail_d_dead(Bin, BitOffset) -> 277 <<_:BitOffset,C,_/binary>> = Bin, 278 C. 279 280bin_tail_d_var(Bin, BitOffset) -> 281 <<_:BitOffset,C,Tail/binary>> = Bin, 282 {C,Tail}. 283 284bin_tail_e(Bin) -> 285 case bin_tail_e_dead(Bin) of 286 ok -> 287 <<_,Tail/binary>> = Bin, 288 Tail = bin_tail_e_var(Bin), 289 ok; 290 error -> 291 bin_tail_e_var(Bin) 292 end. 293 294bin_tail_e_dead(Bin) -> 295 case Bin of 296 %% The binary is aligned at the end; neither the bs_skip_bits2 nor 297 %% bs_test_tail2 instructions are needed. 298 <<2:2,_:1,1:5,_/binary>> -> ok; 299 _ -> error 300 end. 301 302bin_tail_e_var(Bin) -> 303 case Bin of 304 %% The binary is aligned at the end; neither the bs_skip_bits2 nor 305 %% bs_test_tail2 instructions are needed. 306 <<2:2,_:1,1:5,Tail/binary>> -> Tail; 307 _ -> error 308 end. 309 310save_restore(Config) when is_list(Config) -> 311 0 = save_restore_1(<<0:2,42:6>>), 312 {1,3456} = save_restore_1(<<1:2,3456:14>>), 313 {2,7981234} = save_restore_1(<<2:2,7981234:30>>), 314 {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>), 315 316 A = <<" x">>, 317 B = <<".x">>, 318 C = <<"-x">>, 319 320 {" ",<<"x">>} = lll(A), 321 {" ",<<"x">>} = mmm(A), 322 {" ",<<"x">>} = nnn(A), 323 {" ",<<"x">>} = ooo(A), 324 325 {".",<<"x">>} = lll(B), 326 {".",<<"x">>} = mmm(B), 327 {".",<<"x">>} = nnn(B), 328 {".",<<"x">>} = ooo(B), 329 330 {"-",<<"x">>} = lll(C), 331 {"-",<<"x">>} = mmm(C), 332 {"-",<<"x">>} = nnn(C), 333 {"-",<<"x">>} = ooo(C), 334 335 a = multiple_matches(<<777:16>>, <<777:16>>), 336 b = multiple_matches(<<777:16>>, <<999:16>>), 337 c = multiple_matches(<<777:16>>, <<57:8>>), 338 d = multiple_matches(<<17:8>>, <<1111:16>>), 339 340 Bin = <<-1:64>>, 341 case bad_float_unpack_match(Bin) of 342 -1 -> ok; 343 _Other -> ct:fail(bad_return_value_probably_NaN) 344 end. 345 346save_restore_1(Bin) -> 347 case Bin of 348 <<0:2,_:6>> -> 0; 349 <<1:2,A:14>> -> {1,A}; 350 <<2:2,A:30>> -> {2,A}; 351 <<A:64>> -> {3,A} 352 end. 353 354lll(<<Char, Tail/binary>>) -> {[Char],Tail}. 355 356mmm(<<$.,$.,$., Tail/binary>>) -> Tail; 357mmm(<<$\s,$-,$\s, Tail/binary>>) -> Tail; 358mmm(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail! 359 360nnn(<<"...", Tail/binary>>) -> Tail; 361nnn(<<" - ", Tail/binary>>) -> Tail; 362nnn(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail! 363 364ooo(<<" - ", Tail/binary>>) -> Tail; 365ooo(<<Char, Tail/binary>>) -> {[Char],Tail}. 366 367multiple_matches(<<Y:16>>, <<Y:16>>) -> a; 368multiple_matches(<<_:16>>, <<_:16>>) -> b; 369multiple_matches(<<_:16>>, <<_:8>>) -> c; 370multiple_matches(<<_:8>>, <<_:16>>) -> d. 371 372bad_float_unpack_match(<<F:64/float>>) -> F; 373bad_float_unpack_match(<<I:64/integer-signed>>) -> I. 374 375 376partitioned_bs_match(Config) when is_list(Config) -> 377 <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>), 378 error = partitioned_bs_match(10, <<7,8,15,13>>), 379 error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}), 380 ok = partitioned_bs_match(0, <<>>), 381 fc(partitioned_bs_match, [-1,blurf], 382 catch partitioned_bs_match(-1, blurf)), 383 fc(partitioned_bs_match, [-1,<<1,2,3>>], 384 catch partitioned_bs_match(-1, <<1,2,3>>)), 385 {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>), 386 {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>), 387 388 fc(partitioned_bs_match_2, [4,<<0:17>>], 389 catch partitioned_bs_match_2(4, <<0:17>>)), 390 391 anything = partitioned_bs_match_3(anything, <<42>>), 392 ok = partitioned_bs_match_3(1, 2), 393 394 ok. 395 396partitioned_bs_match(_, <<42:8,T/binary>>) -> 397 T; 398partitioned_bs_match(N, _) when N > 0 -> 399 error; 400partitioned_bs_match(_, <<>>) -> 401 ok. 402 403partitioned_bs_match_2(1, <<B:8,T/binary>>) -> 404 {B,T}; 405partitioned_bs_match_2(Len, <<_:8,T/binary>>) -> 406 {Len,T}. 407 408partitioned_bs_match_3(Var, <<_>>) -> Var; 409partitioned_bs_match_3(1, 2) -> ok. 410 411function_clause(Config) when is_list(Config) -> 412 ok = function_clause_1(<<0,7,0,7,42>>), 413 fc(function_clause_1, [<<0,1,2,3>>], 414 catch function_clause_1(<<0,1,2,3>>)), 415 fc(function_clause_1, [<<0,1,2,3>>], 416 catch function_clause_1(<<0,7,0,1,2,3>>)), 417 418 ok = function_clause_2(<<0,7,0,7,42>>), 419 ok = function_clause_2(<<255>>), 420 ok = function_clause_2(<<13:4>>), 421 fc(function_clause_2, [<<0,1,2,3>>], 422 catch function_clause_2(<<0,1,2,3>>)), 423 fc(function_clause_2, [<<0,1,2,3>>], 424 catch function_clause_2(<<0,7,0,1,2,3>>)), 425 426 ok. 427 428function_clause_1(<<0:8,7:8,T/binary>>) -> 429 function_clause_1(T); 430function_clause_1(<<_:8>>) -> 431 ok. 432 433function_clause_2(<<0:8,7:8,T/binary>>) -> 434 function_clause_2(T); 435function_clause_2(<<_:8>>) -> 436 ok; 437function_clause_2(<<_:4>>) -> 438 ok. 439 440unit(Config) when is_list(Config) -> 441 42 = peek1(<<42>>), 442 43 = peek1(<<43,1,2>>), 443 43 = peek1(<<43,1,2,(-1):1>>), 444 43 = peek1(<<43,1,2,(-1):2>>), 445 43 = peek1(<<43,1,2,(-1):7>>), 446 447 99 = peek8(<<99>>), 448 100 = peek8(<<100,101>>), 449 fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)), 450 451 37484 = peek16(<<37484:16>>), 452 37489 = peek16(<<37489:16,5566:16>>), 453 fc(peek16, [<<8>>], catch peek16(<<8>>)), 454 fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)), 455 fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)), 456 457 127 = peek7(<<127:7>>), 458 100 = peek7(<<100:7,19:7>>), 459 fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)), 460 ok. 461 462peek1(<<B:8,_/bitstring>>) -> B. 463 464peek7(<<B:7,_/binary-unit:7>>) -> B. 465 466peek8(<<B:8,_/binary>>) -> B. 467 468peek16(<<B:16,_/binary-unit:16>>) -> B. 469 470shared_sub_bins(Config) when is_list(Config) -> 471 {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0), 472 ok. 473 474sum(<<B,T/binary>>, Acc, Sum) -> 475 sum(T, [T|Acc], Sum+B); 476sum(<<>>, Last, Sum) -> {Sum,Last}. 477 478 479bin_and_float(Config) when is_list(Config) -> 480 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0), 481 ok. 482 483bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X), 484 is_float(Y), 485 is_float(Z) -> 486 bin_and_float(T, Sum+X*X+Y*Y+Z*Z); 487bin_and_float(<<>>, Sum) -> Sum. 488 489dec_subidentifiers(Config) when is_list(Config) -> 490 {[],<<1,2,3>>} = 491 do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2), 492 {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2), 493 {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0), 494 ok. 495 496do_dec_subidentifiers(Buffer, Av, Al, Len) -> 497 Res = dec_subidentifiers(Buffer, Av, Al, Len), 498 Res = dec_subidentifiers2(Buffer, Av, Al, Len), 499 Res = dec_subidentifiers4(Buffer, Av, Al, Len), 500 Res = dec_subidentifiers3(Buffer, Av, Al, Len). 501 502dec_subidentifiers(Buffer, _Av, Al, 0) -> 503 {lists:reverse(Al),Buffer}; 504dec_subidentifiers(<<1:1,H:7,T/binary>>, Av, Al, Len) -> 505 dec_subidentifiers(T, (Av bsl 7) bor H, Al, Len-1); 506dec_subidentifiers(<<H,T/binary>>, Av, Al, Len) -> 507 dec_subidentifiers(T, 0, [((Av bsl 7) bor H)|Al], Len-1). 508 509dec_subidentifiers2(<<Buffer/binary>>, _Av, Al, 0) -> 510 {lists:reverse(Al),Buffer}; 511dec_subidentifiers2(<<1:1,H:7,T/binary>>, Av, Al, Len) -> 512 dec_subidentifiers2(T, (Av bsl 7) bor H, Al, Len-1); 513dec_subidentifiers2(<<H,T/binary>>, Av, Al, Len) -> 514 dec_subidentifiers2(T, 0, [((Av bsl 7) bor H)|Al], Len-1). 515 516dec_subidentifiers3(Buffer, _Av, Al, 0) when is_binary(Buffer) -> 517 {lists:reverse(Al),Buffer}; 518dec_subidentifiers3(<<1:1,H:7,T/binary>>, Av, Al, Len) -> 519 dec_subidentifiers3(T, (Av bsl 7) bor H, Al, Len-1); 520dec_subidentifiers3(<<H,T/binary>>, Av, Al, Len) -> 521 dec_subidentifiers3(T, 0, [((Av bsl 7) bor H)|Al], Len-1). 522 523dec_subidentifiers4(<<1:1,H:7,T/binary>>, Av, Al, Len) when Len =/= 0 -> 524 dec_subidentifiers4(T, (Av bsl 7) bor H, Al, Len-1); 525dec_subidentifiers4(<<H,T/binary>>, Av, Al, Len) when Len =/= 0 -> 526 dec_subidentifiers4(T, 0, [((Av bsl 7) bor H)|Al], Len-1); 527dec_subidentifiers4(Buffer, _Av, Al, 0) -> 528 {lists:reverse(Al),Buffer}. 529 530 531skip_optional_tag(Config) when is_list(Config) -> 532 {ok,<<>>} = skip_optional_tag(<<42>>, <<42>>), 533 {ok,<<>>} = skip_optional_tag(<<42,1>>, <<42,1>>), 534 {ok,<<1,2,3>>} = skip_optional_tag(<<42>>, <<42,1,2,3>>), 535 missing = skip_optional_tag(<<2:3>>, blurf), 536 ok. 537 538skip_optional_tag(<<>>, Binary) -> 539 {ok,Binary}; 540skip_optional_tag(<<Tag,RestTag/binary>>, <<Tag,Rest/binary>>) -> 541 skip_optional_tag(RestTag, Rest); 542skip_optional_tag(_, _) -> missing. 543 544decode_integer(_Config) -> 545 {10795,<<43>>,whatever} = decode_integer(1, <<42,43>>, whatever), 546 {-28909,<<19>>,whatever} = decode_integer(1, <<143,19>>, whatever), 547 ok. 548 549decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) when B1 == 0 -> 550 Bin = <<_Skip:Len/unit:8, Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>, 551 Size = byte_size(Bin), 552 <<Int:Size/unit:8>> = Bin, 553 {Int,Buffer2,RemovedBytes}; 554decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) -> 555 Bin = <<_Skip:Len/unit:8,Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>, 556 Size = byte_size(Bin), 557 <<N:Size/unit:8>> = <<B2,Bs/binary>>, 558 Int = N - (1 bsl (8 * size(Bin) -1)), 559 {Int,Buffer2,RemovedBytes}. 560 561-define(DATELEN, 16). 562 563wfbm(Config) when is_list(Config) -> 564 %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski, 565 %% with modifications. 566 {nomatch,0} = check_for_dot_or_space(<<" ">>), 567 {nomatch,0} = check_for_dot_or_space(<<" abc">>), 568 {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>), 569 {nomatch,0} = check_for_dot_or_space(<<".gurka">>), 570 {nomatch,1} = check_for_dot_or_space(<<"g.urka">>), 571 572 nomatch = get_tail(<<>>), 573 {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>), 574 {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>), 575 nomatch = get_tail(<<"200y.2007.10.23.blurf ">>), 576 {'EXIT',_} = (catch get_tail({no,binary,at,all})), 577 {'EXIT',_} = (catch get_tail(no_binary)), 578 ok. 579 580check_for_dot_or_space(Bin) -> 581 check_for_dot_or_space(Bin, 0). 582 583check_for_dot_or_space(<<$\s, _/binary>>, 0) -> 584 {nomatch,0}; 585check_for_dot_or_space(Bin, Len) -> 586 case Bin of 587 <<Front:Len/binary, $\s, _/binary>> -> 588 {ok,Front}; 589 <<_:Len/binary, $., _/binary>> -> 590 {nomatch,Len}; 591 _ -> 592 check_for_dot_or_space(Bin, Len+1) 593 end. 594 595get_tail(<<>>) -> 596 nomatch; 597get_tail(Bin) -> 598 <<Front:?DATELEN/binary, Tail/binary>> = Bin, 599 case Front of 600 <<_:3/binary,"x/",Y:4/binary,$/,M:2/binary,$/,D:2/binary,$/>> -> 601 case check_for_dot_or_space(Tail) of 602 {ok,Match} -> 603 {ok,<<Y/binary,$/,M/binary,$/,D/binary,$/, Match/binary>>}; 604 {nomatch,Skip} -> {skip,?DATELEN + Skip} 605 end; 606 _ -> nomatch 607 end. 608 609degenerated_match(Config) when is_list(Config) -> 610 error = degenerated_match_1(<<>>), 611 1 = degenerated_match_1(<<1:1>>), 612 2 = degenerated_match_1(<<42,43>>), 613 614 error = degenerated_match_2(<<>>), 615 no_split = degenerated_match_2(<<1,2>>), 616 {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>), 617 618 ok. 619 620degenerated_match_1(<<>>) -> error; 621degenerated_match_1(Bin) -> byte_size(Bin). 622 623degenerated_match_2(<<>>) -> error; 624degenerated_match_2(Bin) -> 625 case byte_size(Bin) > 4 of 626 true -> 627 split_binary(Bin, 4); 628 false -> 629 no_split 630 end. 631 632bs_sum(Config) when is_list(Config) -> 633 0 = bs_sum_1([]), 634 0 = bs_sum_1(<<>>), 635 42 = bs_sum_1([42]), 636 1 = bs_sum_1(<<1>>), 637 10 = bs_sum_1([1,2,3,4]), 638 15 = bs_sum_1(<<1,2,3,4,5>>), 639 21 = bs_sum_1([1,2,3|<<4,5,6>>]), 640 15 = bs_sum_1([1,2,3|{4,5}]), 641 6 = bs_sum_1([1,2,3|zero]), 642 6 = bs_sum_1([1,2,3|0]), 643 7 = bs_sum_1([1,2,3|one]), 644 645 fc(catch bs_sum_1({too,big,tuple})), 646 fc(catch bs_sum_1([1,2,3|{too,big,tuple}])), 647 648 [] = sneaky_alias(<<>>), 649 [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)), 650 fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))), 651 fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))), 652 ok. 653 654bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T); 655bs_sum_1([H|T]) -> H+bs_sum_1(T); 656bs_sum_1({A,B}=_Tuple=_AliasForNoGoodReason) -> A+B; 657bs_sum_1(0) -> 0; 658bs_sum_1(zero=_Zero) -> 0; 659bs_sum_1(one) -> 1; 660bs_sum_1([]) -> 0; 661bs_sum_1(<<>>) -> 0. 662 663sneaky_alias(<<>>=L) -> binary_to_list(L); 664sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)]. 665 666coverage(Config) when is_list(Config) -> 667 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>), 668 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>), 669 fc(catch coverage_fold(fun(B, A) -> 670 A+B 671 end, 0, [a,b,c])), 672 673 {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float), 674 {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple), 675 {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} = 676 coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}), 677 678 [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []), 679 680 {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}), 681 682 [42] = coverage_apply(<<42>>, [coverage_id]), 683 42 = coverage_external(<<42>>), 684 685 do_coverage_bin_to_term_list([]), 686 do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]), 687 fc(coverage_bin_to_term_list, [<<0,0,0,7>>], 688 catch do_coverage_bin_to_term_list_1(<<7:32>>)), 689 690 <<>> = coverage_per_key(<<4:32>>), 691 <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>), 692 693 binary = coverage_bitstring(<<>>), 694 binary = coverage_bitstring(<<7>>), 695 bitstring = coverage_bitstring(<<7:4>>), 696 other = coverage_bitstring([a]), 697 ok. 698 699coverage_fold(Fun, Acc, <<H,T/binary>>) -> 700 IdFun = fun id/1, 701 coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T); 702coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc. 703 704coverage_build(Acc0, <<H,T/binary>>, float) -> 705 Float = id(<<H:64/float>>), 706 Acc = <<Acc0/binary,Float/binary>>, 707 coverage_build(Acc, T, float); 708coverage_build(Acc0, <<H,T/binary>>, Tuple0) -> 709 Str = id(<<H:(id(4)),(H-1):4,"abc">>), 710 Acc = id(<<Acc0/bitstring,Str/bitstring>>), 711 Tuple = setelement(2, setelement(3, Tuple0, 43), 42), 712 if 713 byte_size(Acc) > 0 -> 714 coverage_build(Acc, T, Tuple) 715 end; 716coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}. 717 718coverage_bc(<<H,T/binary>>, Acc) -> 719 B = << <<C:8>> || C <- [H] >>, 720 coverage_bc(T, [B|Acc]); 721coverage_bc(<<>>, Acc) -> Acc. 722 723coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x -> 724 setelement(H, Tuple, T1). 725 726coverage_apply(<<H,T/binary>>, [F|Fs]) -> 727 [?MODULE:F(H)|coverage_apply(T, Fs)]; 728coverage_apply(<<>>, []) -> []. 729 730coverage_external(<<H,T/binary>>) -> 731 ?MODULE:coverage_external_ignore(T, T), 732 H. 733 734coverage_external_ignore(_, _) -> 735 ok. 736 737coverage_id(I) -> id(I). 738 739do_coverage_bin_to_term_list(L) -> 740 Bin = << <<(begin BinTerm = term_to_binary(Term), 741 <<(byte_size(BinTerm)):32,BinTerm/binary>> end)/binary>> || 742 Term <- L >>, 743 L = do_coverage_bin_to_term_list_1(Bin), 744 L = do_coverage_bin_to_term_list_1(<<Bin/binary,7:32,"garbage">>), 745 L = do_coverage_bin_to_term_list_1(<<7:32,"garbage",Bin/binary>>). 746 747do_coverage_bin_to_term_list_1(Bin) -> 748 Res = coverage_bin_to_term_list(Bin), 749 Res = coverage_bin_to_term_list(Bin, []), 750 Res = coverage_bin_to_term_list_catch(Bin), 751 Res = coverage_bin_to_term_list_catch(Bin, []). 752 753coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>) -> 754 try binary_to_term(BinTerm) of 755 Term -> [Term|coverage_bin_to_term_list(T)] 756 catch 757 error:badarg -> coverage_bin_to_term_list(T) 758 end; 759coverage_bin_to_term_list(<<>>) -> []. 760 761coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) -> 762 try binary_to_term(BinTerm) of 763 Term -> coverage_bin_to_term_list(T, [Term|Acc]) 764 catch 765 error:badarg -> coverage_bin_to_term_list(T, Acc) 766 end; 767coverage_bin_to_term_list(<<>>, Acc) -> lists:reverse(Acc). 768 769coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>) -> 770 case catch binary_to_term(BinTerm) of 771 {'EXIT',_} -> coverage_bin_to_term_list_catch(T); 772 Term -> [Term|coverage_bin_to_term_list_catch(T)] 773 end; 774coverage_bin_to_term_list_catch(<<>>) -> []. 775 776coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) -> 777 case catch binary_to_term(BinTerm) of 778 {'EXIT',_} -> coverage_bin_to_term_list_catch(T, Acc); 779 Term -> coverage_bin_to_term_list_catch(T, [Term|Acc]) 780 end; 781coverage_bin_to_term_list_catch(<<>>, Acc) -> lists:reverse(Acc). 782 783coverage_per_key(<<BinSize:32,Bin/binary>> = B) -> 784 true = (byte_size(B) =:= BinSize), 785 Bin. 786 787coverage_bitstring(Bin) when is_binary(Bin) -> binary; 788coverage_bitstring(<<_/bitstring>>) -> bitstring; 789coverage_bitstring(_) -> other. 790 791multiple_uses(Config) when is_list(Config) -> 792 {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>), 793 true = multiple_uses_2(<<0,0,197,18>>), 794 <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1), 795 796 ok = first_after(<<>>, 42), 797 <<1>> = first_after(<<1,2,3>>, 0), 798 <<2>> = first_after(<<1,2,3>>, 1), 799 800 ok. 801 802multiple_uses_1(<<X:16,Tail/binary>>) -> 803 %% NOT OPTIMIZED: sub binary is matched or used in more than one place 804 {Y,Z} = multiple_uses_match(Tail), 805 {X,Y,Z,Tail}. 806 807multiple_uses_2(<<_:16,Tail/binary>>) -> 808 %% NOT OPTIMIZED: sub binary is matched or used in more than one place 809 multiple_uses_cmp(Tail, Tail). 810 811multiple_uses_3(<<_:16,Tail/binary>>, Fun) -> 812 %% NOT OPTIMIZED: sub binary is used or returned 813 Fun(Tail). 814 815multiple_uses_match(<<Y:16,Z:16>>) -> 816 {Y,Z}. 817 818multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true; 819multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false. 820 821first_after(Data, Offset) -> 822 case byte_size(Data) > Offset of 823 false -> 824 {_First, _Rest} = {ok, ok}, 825 ok; 826 true -> 827 <<_:Offset/binary, Rest/binary>> = Data, 828 %% 'Rest' saved in y(0) before the call. 829 {First, _} = match_first(Data, Rest), 830 %% When beam_bsm sees the code, the following line 831 %% which uses y(0) has been optimized away. 832 {First, Rest} = {First, Rest}, 833 First 834 end. 835 836match_first(_, <<First:1/binary, Rest/binary>>) -> 837 {First, Rest}. 838 839zero_label(Config) when is_list(Config) -> 840 <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>), 841 <<"CE">> = read_pols(<<"noFACE">>), 842 ok. 843 844read_pols(Data) -> 845 <<PolygonType:4/binary,Rest/binary>> = Data, 846 %% Intentional warning. 847 (PolygonType == <<"FACE">>) or (PolygonType == <<"PTCH">>), 848 Rest. 849 850followed_by_catch(Config) when is_list(Config) -> 851 ok = handle(<<0,1,2,3,4,5>>). 852 853-record(rec,{field}). 854handle(<<>>) -> ok; 855handle(Msg) -> 856 <<_DataLen:16, Rest/binary>> = Msg, 857 case catch fooX:func() of 858 [X] -> 859 X#rec.field; 860 _ -> 861 ok 862 end, 863 handle(Rest). 864 865matching_meets_construction(Config) when is_list(Config) -> 866 Bin = id(<<"abc">>), 867 Len = id(2), 868 Tail0 = id(<<1,2,3,4,5>>), 869 <<_:Len/binary,Tail/binary>> = Tail0, 870 Res = <<Tail/binary,Bin/binary>>, 871 <<3,4,5,"abc">> = Res, 872 {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)), 873 {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)), 874 <<"Bbc">> = matching_meets_construction_3(<<"Abc">>), 875 876 <<1,2>> = encode_octet_string(<<1,2,3>>, 2), 877 ok. 878 879matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>. 880 881matching_meets_construction_2(<<"A",H/binary>>) -> <<"B",H/float>>. 882 883matching_meets_construction_3(<<"A",H/binary>>) -> <<"B",H/binary>>. 884 885encode_octet_string(<<OctetString/binary>>, Len) -> 886 <<OctetString:Len/binary-unit:8>>. 887 888simon(Config) when is_list(Config) -> 889 one = simon(blurf, <<>>), 890 two = simon(0, <<42>>), 891 fc(simon, [17,<<1>>], catch simon(17, <<1>>)), 892 fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)), 893 894 one = simon2(blurf, <<9>>), 895 two = simon2(0, <<9,1>>), 896 fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)), 897 ok. 898 899simon(_, <<>>) -> one; 900simon(0, <<_>>) -> two. 901 902simon2(_, <<9>>) -> one; 903simon2(0, <<_:16>>) -> two. 904 905 906%% OTP-7113: Crash in v3_codegen. 907matching_and_andalso(Config) when is_list(Config) -> 908 ok = matching_and_andalso_1(<<1,2,3>>, 3), 909 {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)), 910 {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)), 911 {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)), 912 913 {"abc",<<"xyz">>} = matching_and_andalso_23("abc", <<"-xyz">>), 914 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($a-1)>>), 915 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($z+1)>>), 916 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($A-1)>>), 917 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($Z+1)>>), 918 error = matching_and_andalso_23([], <<>>), 919 error = matching_and_andalso_23([], <<$A>>), 920 error = matching_and_andalso_23([], <<$Z>>), 921 error = matching_and_andalso_23([], <<$a>>), 922 error = matching_and_andalso_23([], <<$z>>), 923 ok. 924 925matching_and_andalso_1(<<Bitmap/binary>>, K) 926 when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K -> 927 ok. 928 929matching_and_andalso_23(Datetime, Bin) -> 930 Res = matching_and_andalso_2(Datetime, Bin), 931 Res = matching_and_andalso_3(Datetime, Bin), 932 Res. 933 934matching_and_andalso_2(Datetime, <<H,T/binary>>) 935 when not ((H >= $a) andalso (H =< $z)) andalso 936 not ((H >= $A) andalso (H =< $Z)) -> 937 {Datetime,T}; 938matching_and_andalso_2(_, _) -> error. 939 940%% Contrived example to ensure we cover the handling of 'call' instructions 941%% in v3_codegen:bsm_rename_ctx/4. 942matching_and_andalso_3(Datetime, <<H,T/binary>>) 943 when not ((abs(H) >= $a) andalso (abs(H) =< $z)) andalso 944 not ((abs(H) >= $A) andalso (abs(H) =< $Z)) -> 945 {Datetime,T}; 946matching_and_andalso_3(_, _) -> error. 947 948%% Thanks to Tomas Stejskal. 949otp_7188(Config) when is_list(Config) -> 950 MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0, 951 0,0,0,0,0,0,0,0,0,0,0,0,0,68,97,110,105,101,108,32,76, 952 97,110,100,97,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66, 953 101,115,116,32,79,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 954 0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115, 955 116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 956 32,32,12>>, 957 {ok,{"ID3v1", 958 [{title,<<68,117,154,105,232,107,121>>}, 959 {artist,<<"Daniel Landa">>}, 960 {album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3). 961 962parse_v1_or_v11_tag(<<"TAG", Title:30/binary, 963 Artist:30/binary, Album:30/binary, 964 _Year:4/binary, _Comment:28/binary, 965 0:8, Track:8, _Genre:8>>) -> 966 {ok, 967 {"ID3v1.1", 968 [{track, Track}, {title, trim(Title)}, 969 {artist, trim(Artist)}, {album, trim(Album)}]}}; 970parse_v1_or_v11_tag(<<"TAG", Title:30/binary, 971 Artist:30/binary, Album:30/binary, 972 _Year:4/binary, _Comment:30/binary, 973 _Genre:8>>) -> 974 {ok, 975 {"ID3v1", 976 [{title, trim(Title)}, 977 {artist, trim(Artist)}, 978 {album, trim(Album)}]}}; 979parse_v1_or_v11_tag(_) -> 980 error. 981 982trim(Bin) -> 983 list_to_binary(trim_blanks(binary_to_list(Bin))). 984 985trim_blanks(L) -> 986 lists:reverse(skip_blanks_and_zero(lists:reverse(L))). 987 988skip_blanks_and_zero([$\s|T]) -> 989 skip_blanks_and_zero(T); 990skip_blanks_and_zero([0|T]) -> 991 skip_blanks_and_zero(T); 992skip_blanks_and_zero(L) -> 993 L. 994 995%% OTP-7233. Record and binary matching optimizations clashed. 996%% Thanks to Vladimir Klebansky. 997 998-record(rec_otp_7233, {key, val}). 999 1000otp_7233(Config) when is_list(Config) -> 1001 otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}), 1002 [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format), 1003 erase(io_format), 1004 otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}), 1005 undefined = get(io_format), 1006 ok. 1007 1008otp_7233_1(Rec) -> 1009 <<K:2/binary,_Rest:5/binary>> = Rec#rec_otp_7233.key, 1010 case K of 1011 <<"XX">> -> 1012 Value = Rec#rec_otp_7233.val, 1013 case lists:keyfind("xxxxxxxx", 1, Value) of 1014 false -> 1015 ok; 1016 T -> 1017 put(io_format, [Rec#rec_otp_7233.key,T]) 1018 end; 1019 _ -> ok 1020 end. 1021 1022 1023otp_7240(Config) when is_list(Config) -> 1024 a = otp_7240_a(0, <<>>), 1025 b = otp_7240_a(1, 2), 1026 1027 a = otp_7240_b(anything, <<>>), 1028 b = otp_7240_b(1, {x,y}), 1029 1030 a = otp_7240_c(anything, <<>>), 1031 b = otp_7240_c(1, <<2>>), 1032 1033 a = otp_7240_d(anything, <<>>), 1034 b = otp_7240_d(again, <<2>>), 1035 1036 a = otp_7240_e(anything, <<>>), 1037 b = otp_7240_e(1, 41), 1038 1039 a = otp_7240_f(anything, <<>>), 1040 b = otp_7240_f(1, {}), 1041 1042 ok. 1043 1044otp_7240_a(_, <<>>) -> a; 1045otp_7240_a(1, 2) -> b. 1046 1047otp_7240_b(_, <<>>) -> a; 1048otp_7240_b(1, {_,_}) -> b. 1049 1050otp_7240_c(_, <<>>) -> a; 1051otp_7240_c(1, <<2>>) -> b. 1052 1053otp_7240_d(_, <<>>) -> a; 1054otp_7240_d(_, <<2>>) -> b. 1055 1056otp_7240_e(_, <<>>) -> a; 1057otp_7240_e(1, B) when B < 42 -> b. 1058 1059otp_7240_f(_, <<>>) -> a; 1060otp_7240_f(1, B) when is_tuple(B) -> b. 1061 1062otp_7498(Config) when is_list(Config) -> 1063 <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0), 1064 <<2,3>> = otp_7498_foo(<<1,2,3>>, 1), 1065 <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2), 1066 1067 <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0), 1068 <<2,3>> = otp_7498_bar(<<1,2,3>>, 1), 1069 <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2), 1070 <<>> = otp_7498_bar(<<>>, 2), 1071 <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3), 1072 1073 ok. 1074 1075otp_7498_foo(Bin, 0) -> 1076 otp_7498_foo(Bin, 42); 1077otp_7498_foo(<<_A, Rest/bitstring>>, 1) -> 1078 otp_7498_foo(Rest, 43); 1079otp_7498_foo(Bin, _I) -> 1080 Bin. 1081 1082otp_7498_bar(Bin, 0) -> 1083 otp_7498_bar(Bin, 42); 1084otp_7498_bar(<<_A, Rest/bitstring>>, 1) -> 1085 otp_7498_bar(Rest, 43); 1086otp_7498_bar(<<>>, 2) -> 1087 otp_7498_bar(<<>>, 44); 1088otp_7498_bar(Bin, _I) -> 1089 Bin. 1090 1091 1092match_string(Config) when is_list(Config) -> 1093 %% To make sure that native endian really is handled correctly 1094 %% (i.e. that the compiler does not attempt to use bs_match_string/4 1095 %% instructions for native segments), running this test is not enough. 1096 %% Either examine the generated for do_match_string_native/1 or 1097 %% check the coverage for the v3_kernel module. 1098 case erlang:system_info(endian) of 1099 little -> 1100 do_match_string_native(<<$a,0,$b,0>>); 1101 big -> 1102 do_match_string_native(<<0,$a,0,$b>>) 1103 end, 1104 1105 do_match_string_big(<<0,$a,0,$b>>), 1106 do_match_string_little(<<$a,0,$b,0>>), 1107 1108 do_match_string_big_signed(<<255,255>>), 1109 do_match_string_little_signed(<<255,255>>), 1110 1111 plain = no_match_string_opt(<<"abc">>), 1112 strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>), 1113 1114 ok. 1115 1116do_match_string_native(<<$a:16/native,$b:16/native>>) -> ok. 1117 1118do_match_string_big(<<$a:16/big,$b:16/big>>) -> ok. 1119 1120do_match_string_little(<<$a:16/little,$b:16/little>>) -> ok. 1121 1122do_match_string_big_signed(<<(-1):16/signed>>) -> ok. 1123 1124do_match_string_little_signed(<<(-1):16/little-signed>>) -> ok. 1125 1126no_match_string_opt(<<"abc">>) -> plain; 1127no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange. 1128 1129 1130%% OTP-7591: A zero-width segment in matching would crash the compiler. 1131 1132zero_width(Config) when is_list(Config) -> 1133 <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>, 1134 2 = Len, 1135 Str = <<"hi">>, 1136 1137 %% Match sure that values that cannot fit in a segment will not match. 1138 case id(<<0:8>>) of 1139 <<256:8>> -> ct:fail(should_not_match); 1140 _ -> ok 1141 end, 1142 ok. 1143 1144 1145%% OTP_7650: A invalid size for binary segments could crash the compiler. 1146bad_size(Config) when is_list(Config) -> 1147 Tuple = {a,b,c}, 1148 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)), 1149 Binary = <<1,2,3>>, 1150 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)), 1151 ok. 1152 1153haystack(Config) when is_list(Config) -> 1154 <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>), 1155 [<<0:10/unit:8>>, 1156 <<0:20/unit:8>>] = haystack_2(<<1:8192>>), 1157 ok. 1158 1159%% Used to crash the compiler. 1160haystack_1(Haystack) -> 1161 Subs = [10], 1162 [begin 1163 <<B:Y/binary>> = Haystack, 1164 B 1165 end || Y <- Subs], 1166 Haystack. 1167 1168%% There would be an incorrect badmatch exception. 1169haystack_2(Haystack) -> 1170 Subs = [{687,10},{369,20}], 1171 [begin 1172 <<_:X/binary,B:Y/binary,_/binary>> = Haystack, 1173 B 1174 end || {X,Y} <- Subs ]. 1175 1176fc({'EXIT',{function_clause,_}}) -> ok; 1177fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= bs_match_inline_SUITE -> ok. 1178 1179fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok; 1180fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity,_}|_]}}) 1181 when length(Args) =:= Arity -> 1182 true = test_server:is_native(?MODULE); 1183fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}}) 1184 when ?MODULE =:= bs_match_inline_SUITE -> 1185 Args = tuple_to_list(ActualArgs). 1186 1187%% Cover the clause handling bs_context to binary in 1188%% beam_block:initialized_regs/2. 1189cover_beam_bool(Config) when is_list(Config) -> 1190 ok = do_cover_beam_bool(<<>>, 3), 1191 <<19>> = do_cover_beam_bool(<<19>>, 2), 1192 <<42>> = do_cover_beam_bool(<<42>>, 1), 1193 <<17>> = do_cover_beam_bool(<<13,17>>, 0), 1194 ok. 1195 1196do_cover_beam_bool(Bin, X) when X > 0 -> 1197 if 1198 X =:= 1; X =:= 2 -> 1199 Bin; 1200 true -> 1201 ok 1202 end; 1203do_cover_beam_bool(<<_,Bin/binary>>, X) -> 1204 do_cover_beam_bool(Bin, X+1). 1205 1206matched_out_size(Config) when is_list(Config) -> 1207 {253,16#DEADBEEF} = mos_int(<<8,253,16#DEADBEEF:32>>), 1208 {6,16#BEEFDEAD} = mos_int(<<3,6:3,16#BEEFDEAD:32>>), 1209 {53,16#CAFEDEADBEEFCAFE} = mos_int(<<16,53:16,16#CAFEDEADBEEFCAFE:64>>), 1210 {23,16#CAFEDEADBEEFCAFE} = mos_int(<<5,23:5,16#CAFEDEADBEEFCAFE:64>>), 1211 1212 {<<1,2,3>>,4} = mos_bin(<<3,1,2,3,4,3>>), 1213 {<<1,2,3,7>>,19,42} = mos_bin(<<4,1,2,3,7,19,4,42>>), 1214 <<1,2,3,7>> = mos_bin(<<4,1,2,3,7,"abcdefghij">>), 1215 1216 ok. 1217 1218mos_int(<<L,I:L,X:32>>) -> 1219 {I,X}; 1220mos_int(<<L,I:L,X:64>>) -> 1221 {I,X}. 1222 1223mos_bin(<<L,Bin:L/binary,X:8,L>>) -> 1224 L = byte_size(Bin), 1225 {Bin,X}; 1226mos_bin(<<L,Bin:L/binary,X:8,L,Y:8>>) -> 1227 L = byte_size(Bin), 1228 {Bin,X,Y}; 1229mos_bin(<<L,Bin:L/binary,"abcdefghij">>) -> 1230 L = byte_size(Bin), 1231 Bin. 1232 1233follow_fail_branch(_) -> 1234 42 = ffb_1(<<0,1>>, <<0>>), 1235 8 = ffb_1(<<0,1>>, [a]), 1236 42 = ffb_2(<<0,1>>, <<0>>, 17), 1237 8 = ffb_2(<<0,1>>, [a], 0), 1238 ok. 1239 1240ffb_1(<<_,T/bitstring>>, List) -> 1241 case List of 1242 <<_>> -> 1243 42; 1244 [_|_] -> 1245 %% The fail branch of the bs_start_match2 instruction 1246 %% pointing to here would be ignored, making the compiler 1247 %% incorrectly assume that the delayed sub-binary 1248 %% optimization was safe. 1249 bit_size(T) 1250 end. 1251 1252ffb_2(<<_,T/bitstring>>, List, A) -> 1253 case List of 1254 <<_>> when A =:= 17 -> 42; 1255 [_|_] -> bit_size(T) 1256 end. 1257 1258no_partition(_) -> 1259 one = no_partition_1(<<"string">>, a1), 1260 {two,<<"string">>} = no_partition_1(<<"string">>, a2), 1261 {two,<<>>} = no_partition_1(<<>>, a2), 1262 {two,a} = no_partition_1(a, a2), 1263 three = no_partition_1(undefined, a3), 1264 {four,a,[]} = no_partition_1([a], a4), 1265 {five,a,b} = no_partition_1({a,b}, a5), 1266 1267 one = no_partition_2(<<"string">>, a1), 1268 two = no_partition_2(<<"string">>, a2), 1269 two = no_partition_2(<<>>, a2), 1270 two = no_partition_2(a, a2), 1271 three = no_partition_2(undefined, a3), 1272 four = no_partition_2(42, a4), 1273 five = no_partition_2([], a5), 1274 six = no_partition_2(42.0, a6), 1275 ok. 1276 1277no_partition_1(<<"string">>, a1) -> 1278 one; 1279no_partition_1(V, a2) -> 1280 {two,V}; 1281no_partition_1(undefined, a3) -> 1282 three; 1283no_partition_1([H|T], a4) -> 1284 {four,H,T}; 1285no_partition_1({A,B}, a5) -> 1286 {five,A,B}. 1287 1288no_partition_2(<<"string">>, a1) -> 1289 one; 1290no_partition_2(_, a2) -> 1291 two; 1292no_partition_2(undefined, a3) -> 1293 three; 1294no_partition_2(42, a4) -> 1295 four; 1296no_partition_2([], a5) -> 1297 five; 1298no_partition_2(42.0, a6) -> 1299 six. 1300 1301calling_a_binary(Config) when is_list(Config) -> 1302 [] = call_binary(<<>>, []), 1303 {'EXIT',{badarg,_}} = (catch call_binary(<<1>>, [])), 1304 {'EXIT',{badarg,_}} = (catch call_binary(<<1,2,3>>, [])), 1305 ok. 1306 1307call_binary(<<>>, Acc) -> 1308 Acc; 1309call_binary(<<H,T/bits>>, Acc) -> 1310 T(<<Acc/binary,H>>). 1311 1312binary_in_map(Config) when is_list(Config) -> 1313 ok = match_binary_in_map(#{key => <<42:8>>}), 1314 {'EXIT',{{badmatch,#{key := 1}},_}} = 1315 (catch match_binary_in_map(#{key => 1})), 1316 {'EXIT',{{badmatch,#{key := <<1023:16>>}},_}} = 1317 (catch match_binary_in_map(#{key => <<1023:16>>})), 1318 {'EXIT',{{badmatch,#{key := <<1:8>>}},_}} = 1319 (catch match_binary_in_map(#{key => <<1:8>>})), 1320 {'EXIT',{{badmatch,not_a_map},_}} = 1321 (catch match_binary_in_map(not_a_map)), 1322 ok. 1323 1324match_binary_in_map(Map) -> 1325 case 8 of 1326 N -> 1327 #{key := <<42:N>>} = Map, 1328 ok 1329 end. 1330 1331match_string_opt(Config) when is_list(Config) -> 1332 {x,<<1,2,3>>,{<<1>>,{v,<<1,2,3>>}}} = 1333 do_match_string_opt({<<1>>,{v,<<1,2,3>>}}), 1334 ok. 1335 1336do_match_string_opt({<<1>>,{v,V}}=T) -> 1337 {x,V,T}. 1338 1339select_on_integer(Config) when is_list(Config) -> 1340 42 = do_select_on_integer(<<42>>), 1341 <<"abc">> = do_select_on_integer(<<128,"abc">>), 1342 1343 {'EXIT',_} = (catch do_select_on_integer(<<0:1>>)), 1344 {'EXIT',_} = (catch do_select_on_integer(<<1:1>>)), 1345 {'EXIT',_} = (catch do_select_on_integer(<<0:1,0:15>>)), 1346 ok. 1347 1348%% The ASN.1 compiler frequently generates code like this. 1349do_select_on_integer(<<0:1,I:7>>) -> 1350 I; 1351do_select_on_integer(<<1:1,_:7,Bin/binary>>) -> 1352 Bin. 1353 1354%% If 'bin_opt_info' was given the warning would lack filename 1355%% and line number. 1356 1357map_and_binary(_Config) -> 1358 {<<"10">>,<<"37">>,<<"am">>} = do_map_and_binary(<<"10:37am">>), 1359 Map1 = #{time => "noon"}, 1360 {ok,Map1} = do_map_and_binary(Map1), 1361 Map2 = #{hour => 8, min => 42}, 1362 {8,42,Map2} = do_map_and_binary(Map2), 1363 ok. 1364 1365do_map_and_binary(<<Hour:2/bytes, $:, Min:2/bytes, Rest/binary>>) -> 1366 {Hour, Min, Rest}; 1367do_map_and_binary(#{time := _} = T) -> 1368 {ok, T}; 1369do_map_and_binary(#{hour := Hour, min := Min} = T) -> 1370 {Hour, Min, T}. 1371 1372%% Unsafe caching of branch outcomes in beam_bsm would cause the 1373%% delayed creation of sub-binaries optimization to be applied even 1374%% when it was unsafe. 1375 1376unsafe_branch_caching(_Config) -> 1377 <<>> = do_unsafe_branch_caching(<<42,1>>), 1378 <<>> = do_unsafe_branch_caching(<<42,2>>), 1379 <<>> = do_unsafe_branch_caching(<<42,3>>), 1380 <<17,18>> = do_unsafe_branch_caching(<<42,3,17,18>>), 1381 <<>> = do_unsafe_branch_caching(<<1,3,42,2>>), 1382 1383 ok. 1384 1385do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) -> 1386 <<C1/integer, B1/binary>> = Bin, 1387 case C1 of 1388 X when X =:= 1 orelse X =:= 2 -> 1389 Bin2 = <<>>; 1390 _ -> 1391 Bin2 = B1 1392 end, 1393 case Code of 1394 1 -> do_unsafe_branch_caching(Bin2); 1395 _ -> Bin2 1396 end. 1397 1398bad_literals(_Config) -> 1399 Mod = list_to_atom(?MODULE_STRING ++ "_" ++ 1400 atom_to_list(?FUNCTION_NAME)), 1401 S = [signed_lit_match(V, Sz) || V <- lists:seq(-8, 8), 1402 Sz <- [0,1,2,3]] ++ 1403 [unsigned_lit_match(V, Sz) || V <- lists:seq(-2, 8), 1404 Sz <- [0,1,2]] ++ 1405 [unicode_match(V) || 1406 V <- [-100,-1,0,1,2|lists:seq(16#10FFFC, 16#110004)]], 1407 Code = ?Q(["-module('@Mod@').\n" 1408 "-export([f/0]).\n" 1409 "f() ->\n" 1410 "_@S,\n" 1411 "ok.\n"]), 1412 merl:print(Code), 1413 Opts = test_lib:opt_opts(?MODULE), 1414 {ok,_} = merl:compile_and_load(Code, Opts), 1415 Mod:f(), 1416 1417 {'EXIT',<<42>>} = (catch bad_literals_1()), 1418 1419 Sz = id(8), 1420 {'EXIT',{{badmatch,_},_}} = (catch <<-1:Sz>> = <<-1>>), 1421 ok. 1422 1423bad_literals_1() -> 1424 BadSz = bad, 1425 case case <<42>> of 1426 <<42:BadSz>> -> ok; 1427 Val -> exit(Val) 1428 end of 1429 ok -> ok; 1430 error -> error 1431 end. 1432 1433signed_lit_match(V, Sz) -> 1434 case <<V:Sz>> of 1435 <<V:Sz/signed>> -> 1436 ?Q("<<_@V@:_@Sz@/signed>> = <<_@V@:_@Sz@>>"); 1437 _ -> 1438 ?Q(["case <<_@V@:_@Sz@>> of\n", 1439 " <<_@V@:_@Sz@/signed>> ->\n", 1440 " ct:fail(should_not_match);\n", 1441 " _ ->\n", 1442 " ok\n", 1443 "end\n"]) 1444 end. 1445 1446unsigned_lit_match(V, Sz) -> 1447 case <<V:Sz>> of 1448 <<V:Sz/unsigned>> -> 1449 ?Q("<<_@V@:_@Sz@>> = <<_@V@:_@Sz@>>"); 1450 _ -> 1451 ?Q(["case <<_@V@:_@Sz@>> of\n", 1452 " <<_@V@:_@Sz@/unsigned>> ->\n", 1453 " ct:fail(should_not_match);\n", 1454 " _ ->\n", 1455 " ok\n", 1456 "end\n"]) 1457 end. 1458 1459unicode_match(V) -> 1460 try <<V/utf8>> of 1461 <<V/utf8>> -> 1462 ?Q(["<<_@V@/utf8>> = <<_@V@/utf8>>,\n", 1463 "<<_@V@/utf16>> = <<_@V@/utf16>>,\n", 1464 "<<_@V@/utf32>> = <<_@V@/utf32>>\n"]) 1465 catch 1466 error:badarg -> 1467 ?Q(["case <<_@V@:32>> of\n", 1468 " <<_@V@/utf32>> ->\n", 1469 " ct:fail(should_not_match);\n", 1470 " _ ->\n", 1471 " ok\n", 1472 "end\n"]) 1473 end. 1474 1475%% Test a few legal but rare cases. 1476 1477good_literals(_Config) -> 1478 Sz = id(64), 1479 1480 %% Variable size. 1481 <<42:Sz>> = id(<<42:Sz>>), 1482 <<42.0:Sz/float>> = id(<<42:Sz/float>>), 1483 1484 %% unit > 1 1485 <<16#cafebeef:4/unit:8>> = id(<<16#cafebeef:32>>), 1486 ok. 1487 1488constant_propagation(_Config) -> 1489 <<5>> = constant_propagation_a(a, <<5>>), 1490 {'EXIT',{{case_clause,b},_}} = (catch constant_propagation_a(b, <<5>>)), 1491 258 = constant_propagation_b(<<1,2>>), 1492 F = constant_propagation_c(), 1493 259 = F(<<1,3>>), 1494 ok. 1495 1496constant_propagation_a(X, Y) -> 1497 case X of 1498 a -> Y2 = 8 1499 end, 1500 <<5:Y2>> = Y. 1501 1502constant_propagation_b(B) -> 1503 Sz = 16, 1504 <<X:Sz/integer>> = B, 1505 X. 1506 1507constant_propagation_c() -> 1508 Size = 16, 1509 fun(Bin) -> 1510 <<X:Size/integer>> = Bin, 1511 X 1512 end. 1513 1514parse_xml(_Config) -> 1515 <<"<?xmlX">> = do_parse_xml(<<"<?xmlX">>), 1516 <<" ">> = do_parse_xml(<<"<?xml ">>), 1517 ok. 1518 1519do_parse_xml(<<"<?xml"/utf8,Rest/binary>> = Bytes) -> 1520 %% Delayed sub-binary creation is not safe. A buggy (development) 1521 %% version of check_liveness_everywhere() in beam_utils would turn 1522 %% on the optimization. 1523 Rest1 = case is_next_char_whitespace(Rest) of 1524 false -> 1525 Bytes; 1526 true -> 1527 id(Rest) 1528 end, 1529 id(Rest1). 1530 1531is_next_char_whitespace(<<C/utf8,_/binary>>) -> 1532 C =:= $\s. 1533 1534-record(ext_header, 1535 {this_hdr = 17, 1536 ext_hdr_opts}). 1537 1538get_payload(_Config) -> 1539 <<3445:48>> = do_get_payload(#ext_header{ext_hdr_opts = <<3445:48>>}), 1540 {'EXIT',_} = (catch do_get_payload(#ext_header{})), 1541 ok. 1542 1543do_get_payload(ExtHdr) -> 1544 _ = ExtHdr#ext_header.this_hdr, 1545 ExtHdrOptions = ExtHdr#ext_header.ext_hdr_opts, 1546 <<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts, 1547 ExtHdrOptions. 1548 1549escape(_Config) -> 1550 0 = escape(<<>>, 0), 1551 1 = escape(<<128>>, 0), 1552 2 = escape(<<128,255>>, 0), 1553 42 = escape(<<42>>, 0), 1554 50 = escape(<<42,8>>, 0), 1555 ok. 1556 1557escape(<<Byte, Rest/bits>>, Pos) when Byte >= 127 -> 1558 escape(Rest, Pos + 1); 1559escape(<<Byte, Rest/bits>>, Pos) -> 1560 escape(Rest, Pos + Byte); 1561escape(<<_Rest/bits>>, Pos) -> 1562 Pos. 1563 1564%% ERL-490 1565num_slots_different(_Config) -> 1566 Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>}, 1567 {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>}, 1568 {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>}, 1569 {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>}, 1570 {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>}, 1571 {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>}, 1572 {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}], 1573 _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts], 1574 1575 {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)), 1576 {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)), 1577 {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)), 1578 {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)), 1579 ok. 1580 1581 1582lgettext(<<"de">>, <<"default">>, <<"Remove">>) -> 1583 {ok, <<"a">>}; 1584lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) -> 1585 {ok, <<"a">>}; 1586lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) -> 1587 {ok, <<"a">>}; 1588lgettext(<<"de">>, <<"default">>, <<"Results">>) -> 1589 {ok, <<"Ergebnisse">>}; 1590lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) -> 1591 {ok, <<"a">>}; 1592lgettext(<<"de">>, <<"navigation">>, <<"Results">>) -> 1593 {ok, <<"Ergebnisse">>}; 1594lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) -> 1595 {ok, <<"Ressourcen">>}. 1596 1597%% Test more code in beam_bsm. 1598beam_bsm(_Config) -> 1599 true = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [1,0,1,1]), 1600 false = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [0]), 1601 1602 true = bsm_validate_scheme(<<>>), 1603 true = bsm_validate_scheme(<<5,10>>), 1604 false = bsm_validate_scheme(<<5,10,11,12>>), 1605 true = bsm_validate_scheme([]), 1606 true = bsm_validate_scheme([5,10]), 1607 false = bsm_validate_scheme([5,6,7]), 1608 1609 <<1,2,3>> = bsm_must_save_and_not_save(<<1,2,3>>, []), 1610 D = fun(N) -> 2*N end, 1611 [2,4|<<3>>] = bsm_must_save_and_not_save(<<1,2,3>>, [D,D]), 1612 1613 ok. 1614 1615check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) -> 1616 check_bitstring_list(T1, T2); 1617check_bitstring_list(<<>>, []) -> 1618 true; 1619check_bitstring_list(_, _) -> 1620 false. 1621 1622bsm_validate_scheme([]) -> true; 1623bsm_validate_scheme([H|T]) -> 1624 case bsm_is_scheme(H) of 1625 true -> bsm_validate_scheme(T); 1626 false -> false 1627 end; 1628bsm_validate_scheme(<<>>) -> true; 1629bsm_validate_scheme(<<H, Rest/binary>>) -> 1630 case bsm_is_scheme(H) of 1631 true -> bsm_validate_scheme(Rest); 1632 false -> false 1633 end. 1634 1635bsm_is_scheme(Int) -> 1636 Int rem 5 =:= 0. 1637 1638%% NOT OPTIMIZED: different control paths use different positions in the binary 1639bsm_must_save_and_not_save(Bin, []) -> 1640 Bin; 1641bsm_must_save_and_not_save(<<H,T/binary>>, [F|Fs]) -> 1642 [F(H)|bsm_must_save_and_not_save(T, Fs)]; 1643bsm_must_save_and_not_save(<<>>, []) -> 1644 []. 1645 1646guard(_Config) -> 1647 _Tuple = id({a,b}), 1648 ok = guard_1(<<1,2,3>>, {1,2,3}), 1649 ok = guard_2(<<42>>, #{}), 1650 ok. 1651 1652%% Cover handling of #k_put{} in v3_codegen:bsm_rename_ctx/4. 1653guard_1(<<A,B,C>>, Tuple) when Tuple =:= {A,B,C} -> 1654 ok. 1655 1656%% Cover handling of #k_call{} in v3_codegen:bsm_rename_ctx/4. 1657guard_2(<<_>>, Healing) when Healing#{[] => Healing} =:= #{[] => #{}} -> 1658 ok. 1659 1660is_ascii(_Config) -> 1661 true = do_is_ascii(<<>>), 1662 true = do_is_ascii(<<"string">>), 1663 false = do_is_ascii(<<1024/utf8>>), 1664 {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<$A,0:3>>)), 1665 {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<16#80,0:3>>)), 1666 ok. 1667 1668do_is_ascii(<<>>) -> 1669 true; 1670do_is_ascii(<<C,_/binary>>) when C >= 16#80 -> 1671 %% This clause must fail to match if the size of the argument in 1672 %% bits is not divisible by 8. Beware of unsafe optimizations. 1673 false; 1674do_is_ascii(<<_, T/binary>>) -> 1675 do_is_ascii(T). 1676 1677non_opt_eq(_Config) -> 1678 true = non_opt_eq([], <<>>), 1679 true = non_opt_eq([$a], <<$a>>), 1680 false = non_opt_eq([$a], <<$b>>), 1681 ok. 1682 1683%% An example from the Efficiency Guide. It used to be not optimized, 1684%% but now it can be optimized. 1685 1686non_opt_eq([H|T1], <<H,T2/binary>>) -> 1687 non_opt_eq(T1, T2); 1688non_opt_eq([_|_], <<_,_/binary>>) -> 1689 false; 1690non_opt_eq([], <<>>) -> 1691 true. 1692 1693%% ERL-689 1694 1695erl_689(_Config) -> 1696 {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE), 1697 {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE), 1698 {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>), 1699 {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>), 1700 ok. 1701 1702do_erl_689_1(Arg1, Arg2) -> 1703 Res = do_erl_689_1a(Arg1, Arg2), 1704 Res = do_erl_689_1b(Arg1, Arg2). 1705 1706do_erl_689_2(Arg1, Arg2) -> 1707 Res = do_erl_689_2a(Arg1, Arg2), 1708 Res = do_erl_689_2b(Arg1, Arg2). 1709 1710do_erl_689_1a(<<Length, Data/binary>>, _) -> 1711 case {Data, Length} of 1712 {_, 0} -> 1713 %% bs_context_to_binary would incorrectly set Data to the original 1714 %% binary (before matching in the function head). 1715 {{0, 0, 0}, Data}; 1716 {<<Y:16/little, M, D, Rest/binary>>, 4} -> 1717 {{Y, M, D}, Rest} 1718 end. 1719 1720do_erl_689_1b(<<Length, Data/binary>>, _) -> 1721 case {Data, Length} of 1722 {_, 0} -> 1723 %% bs_context_to_binary would incorrectly set Data to the original 1724 %% binary (before matching in the function head). 1725 id(0), 1726 {{0, 0, 0}, Data}; 1727 {<<Y:16/little, M, D, Rest/binary>>, 4} -> 1728 id(1), 1729 {{Y, M, D}, Rest} 1730 end. 1731 1732do_erl_689_2a(_, <<Length, Data/binary>>) -> 1733 case {Length, Data} of 1734 {0, _} -> 1735 %% bs_context_to_binary would incorrectly set Data to the original 1736 %% binary (before matching in the function head). 1737 {{0, 0, 0}, Data}; 1738 {4, <<Y:16/little, M, D, Rest/binary>>} -> 1739 {{Y, M, D}, Rest} 1740 end. 1741 1742do_erl_689_2b(_, <<Length, Data/binary>>) -> 1743 case {Length, Data} of 1744 {0, _} -> 1745 %% bs_context_to_binary would incorrectly set Data to the original 1746 %% binary (before matching in the function head). 1747 id(0), 1748 {{0, 0, 0}, Data}; 1749 {4, <<Y:16/little, M, D, Rest/binary>>} -> 1750 id(1), 1751 {{Y, M, D}, Rest} 1752 end. 1753 1754%% ERL-753 1755 1756bs_start_match2_defs(_Config) -> 1757 {<<"http://127.0.0.1:1234/vsaas/hello">>} = api_url(<<"hello">>, dummy), 1758 {"https://127.0.0.1:4321/vsaas/hello"} = api_url({https, "hello"}, dummy). 1759 1760api_url(URL, Auth) -> 1761 Header = [], 1762 case URL of 1763 <<_/binary>> -> {<<"http://127.0.0.1:1234/vsaas/",URL/binary>>}; 1764 {https, [_|_] = URL1} -> {"https://127.0.0.1:4321/vsaas/"++URL1} 1765 end. 1766 1767check(F, R) -> 1768 R = F(). 1769 1770id(I) -> I. 1771