1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1999-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: 20: %% 21: -module(guard_SUITE). 22: 23: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 24: init_per_testcase/2,end_per_testcase/2, 25: init_per_suite/1,end_per_suite/1, 26: bad_arith/1,bad_tuple/1,test_heap_guards/1,guard_bifs/1, 27: type_tests/1,const_guard/1, 28: const_cond/1,basic_not/1,complex_not/1, 29: semicolon/1,complex_semicolon/1,comma/1, 30: or_guard/1,more_or_guards/1, 31: complex_or_guards/1,and_guard/1, 32: xor_guard/1,more_xor_guards/1, 33: old_guard_tests/1, 34: build_in_guard/1,gbif/1, 35: t_is_boolean/1,is_function_2/1, 36: tricky/1,rel_ops/1, 37: basic_andalso_orelse/1,traverse_dcd/1, 38: check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, 39: bad_constants/1]). 40: 41: -include_lib("test_server/include/test_server.hrl"). 42: 43: -export([init/4]). 44: -import(lists, [member/2]). 45: 46: suite() -> [{ct_hooks,[ts_install_cth]}]. 47: 48: all() -> 49: cases(). 50: 51: groups() -> 52: []. 53: 54: init_per_group(_GroupName, Config) -> 55: Config. 56: 57: end_per_group(_GroupName, Config) -> 58: Config. 59: 60: 61: cases() -> 62: [bad_arith, bad_tuple, test_heap_guards, guard_bifs, 63: type_tests, const_guard, const_cond, basic_not, 64: complex_not, semicolon, complex_semicolon, comma, 65: or_guard, more_or_guards, complex_or_guards, and_guard, 66: xor_guard, more_xor_guards, build_in_guard, 67: old_guard_tests, gbif, t_is_boolean, is_function_2, 68: tricky, rel_ops, basic_andalso_orelse, traverse_dcd, 69: check_qlc_hrl, andalso_semi, t_tuple_size, binary_part, 70: bad_constants]. 71: 72: init_per_testcase(_Case, Config) -> 73: test_lib:interpret(?MODULE), 74: ?line Dog = test_server:timetrap(?t:minutes(1)), 75: [{watchdog,Dog}|Config]. 76: 77: end_per_testcase(_Case, Config) -> 78: Dog = ?config(watchdog, Config), 79: ?t:timetrap_cancel(Dog), 80: ok. 81: 82: init_per_suite(Config) when is_list(Config) -> 83: ?line test_lib:interpret(?MODULE), 84: ?line true = lists:member(?MODULE, int:interpreted()), 85: Config. 86: 87: end_per_suite(Config) when is_list(Config) -> 88: ok. 89: 90: bad_arith(doc) -> "Test that a bad arithmetic operation in a guard works correctly."; 91: bad_arith(suite) -> []; 92: bad_arith(Config) when list(Config) -> 93: ?line 5 = bad_arith1(2, 3), 94: ?line 10 = bad_arith1(1, infinity), 95: ?line 10 = bad_arith1(infinity, 1), 96: ?line 42 = bad_div(24, 0), 97: ok. 98: 99: bad_arith1(T1, T2) when T1+T2 < 10 -> 100: T1+T2; 101: bad_arith1(_, _) -> 102: 10. 103: 104: bad_div(A, B) when A/B > 0 -> 105: A/B; 106: bad_div(A, B) when A div B > 0 -> 107: A div B; 108: bad_div(_A, _B) -> 109: 42. 110: 111: bad_tuple(doc) -> "Test that bad arguments to element/2 are handled correctly."; 112: bad_tuple(suite) -> []; 113: bad_tuple(Config) when list(Config) -> 114: ?line error = bad_tuple1(a), 115: ?line error = bad_tuple1({a, b}), 116: ?line x = bad_tuple1({x, b}), 117: ?line y = bad_tuple1({a, b, y}), 118: ok. 119: 120: bad_tuple1(T) when element(1, T) == x -> x; 121: bad_tuple1(T) when element(3, T) == y -> y; 122: bad_tuple1(_) -> error. 123: 124: test_heap_guards(doc) -> ""; 125: test_heap_guards(suite) -> []; 126: test_heap_guards(Config) when list(Config) -> 127: ?line process_flag(trap_exit, true), 128: ?line Tuple = {a, tuple, is, built, here, xxx}, 129: ?line List = [a, list, is, built, here], 130: 131: ?line try_fun(fun a_case/1, [Tuple], [Tuple]), 132: ?line try_fun(fun a_case/1, [List], [List, List]), 133: ?line try_fun(fun a_case/1, [a], [a]), 134: 135: ?line try_fun(fun an_if/1, [Tuple], [Tuple]), 136: ?line try_fun(fun an_if/1, [List], [List, List]), 137: ?line try_fun(fun an_if/1, [a], [a]), 138: 139: ?line try_fun(fun receive_test/1, [Tuple], [Tuple]), 140: ?line try_fun(fun receive_test/1, [List], [List, List]), 141: ?line try_fun(fun receive_test/1, [a], [a]), 142: ok. 143: 144: a_case(V) -> 145: case V of 146: T when T == {a, tuple, is, built, here, xxx} -> 147: [T]; 148: L when L == [a, list, is, built, here] -> 149: [L, L]; 150: a -> 151: [a] 152: end. 153: 154: an_if(V) -> 155: if 156: V == {a, tuple, is, built, here, xxx} -> 157: [V]; 158: V == [a, list, is, built, here] -> 159: [V, V]; 160: V == a -> 161: [a] 162: end. 163: 164: receive_test(V) -> 165: self() ! V, 166: a_receive(). 167: 168: a_receive() -> 169: receive 170: T when T == {a, tuple, is, built, here, xxx} -> 171: [T]; 172: L when L == [a, list, is, built, here] -> 173: [L, L]; 174: a -> 175: [a] 176: end. 177: 178: try_fun(Fun, Args, Result) -> 179: try_fun(16, Fun, Args, Result, []). 180: 181: try_fun(0, _, _, _, _) -> 182: ok; 183: try_fun(Iter, Fun, Args, Result, Filler) -> 184: Pid = spawn_link(?MODULE, init, [self(),Fun,Args,list_to_tuple(Filler)]), 185: receive 186: {'EXIT',Pid,{result,Result}} -> 187: ?line try_fun(Iter-1, Fun, Args, Result, [0|Filler]); 188: {'EXIT',Pid,{result,Other}} -> 189: ?line io:format("Expected ~p; got ~p~n", [Result,Other]), 190: ?line test_server:fail(); 191: Other -> 192: ?line test_server:fail({unexpected_message,Other}) 193: end. 194: 195: init(_ReplyTo, Fun, Args, Filler) -> 196: Result = {result, apply(Fun, Args)}, 197: dummy(Filler), 198: io:format("~p: result = ~p\n", [?LINE,Result]), 199: exit(Result). 200: 201: dummy(_) -> 202: ok. 203: 204: guard_bifs(doc) -> "Test all guard bifs with nasty (but legal arguments)."; 205: guard_bifs(suite) -> []; 206: guard_bifs(Config) when list(Config) -> 207: ?line Big = -237849247829874297658726487367328971246284736473821617265433, 208: ?line Float = 387924.874, 209: 210: %% Succeding use of guard bifs. 211: 212: ?line try_gbif('abs/1', Big, -Big), 213: ?line try_gbif('float/1', Big, float(Big)), 214: ?line try_gbif('trunc/1', Float, 387924.0), 215: ?line try_gbif('round/1', Float, 387925.0), 216: ?line try_gbif('length/1', [], 0), 217: 218: ?line try_gbif('length/1', [a], 1), 219: ?line try_gbif('length/1', [a, b], 2), 220: ?line try_gbif('length/1', lists:seq(0, 31), 32), 221: 222: ?line try_gbif('hd/1', [a], a), 223: ?line try_gbif('hd/1', [a, b], a), 224: 225: ?line try_gbif('tl/1', [a], []), 226: ?line try_gbif('tl/1', [a, b], [b]), 227: ?line try_gbif('tl/1', [a, b, c], [b, c]), 228: 229: ?line try_gbif('size/1', {}, 0), 230: ?line try_gbif('size/1', {a}, 1), 231: ?line try_gbif('size/1', {a, b}, 2), 232: ?line try_gbif('size/1', {a, b, c}, 3), 233: ?line try_gbif('size/1', list_to_binary([]), 0), 234: ?line try_gbif('size/1', list_to_binary([1]), 1), 235: ?line try_gbif('size/1', list_to_binary([1, 2]), 2), 236: ?line try_gbif('size/1', list_to_binary([1, 2, 3]), 3), 237: 238: ?line try_gbif('element/2', {x}, {1, x}), 239: ?line try_gbif('element/2', {x, y}, {1, x}), 240: ?line try_gbif('element/2', {x, y}, {2, y}), 241: 242: ?line try_gbif('self/0', 0, self()), 243: ?line try_gbif('node/0', 0, node()), 244: ?line try_gbif('node/1', self(), node()), 245: 246: %% Failing use of guard bifs. 247: 248: ?line try_fail_gbif('abs/1', Big, 1), 249: ?line try_fail_gbif('abs/1', [], 1), 250: 251: ?line try_fail_gbif('float/1', Big, 42), 252: ?line try_fail_gbif('float/1', [], 42), 253: 254: ?line try_fail_gbif('trunc/1', Float, 0.0), 255: ?line try_fail_gbif('trunc/1', [], 0.0), 256: 257: ?line try_fail_gbif('round/1', Float, 1.0), 258: ?line try_fail_gbif('round/1', [], a), 259: 260: ?line try_fail_gbif('length/1', [], 1), 261: ?line try_fail_gbif('length/1', [a], 0), 262: ?line try_fail_gbif('length/1', a, 0), 263: ?line try_fail_gbif('length/1', {a}, 0), 264: 265: ?line try_fail_gbif('hd/1', [], 0), 266: ?line try_fail_gbif('hd/1', [a], x), 267: ?line try_fail_gbif('hd/1', x, x), 268: 269: ?line try_fail_gbif('tl/1', [], 0), 270: ?line try_fail_gbif('tl/1', [a], x), 271: ?line try_fail_gbif('tl/1', x, x), 272: 273: ?line try_fail_gbif('size/1', {}, 1), 274: ?line try_fail_gbif('size/1', [], 0), 275: ?line try_fail_gbif('size/1', [a], 1), 276: 277: ?line try_fail_gbif('element/2', {}, {1, x}), 278: ?line try_fail_gbif('element/2', {x}, {1, y}), 279: ?line try_fail_gbif('element/2', [], {1, z}), 280: 281: ?line try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")), 282: ?line try_fail_gbif('node/0', 0, xxxx), 283: ?line try_fail_gbif('node/1', self(), xxx), 284: ?line try_fail_gbif('node/1', yyy, xxx), 285: ok. 286: 287: try_gbif(Id, X, Y) -> 288: case guard_bif(Id, X, Y) of 289: {Id, X, Y} -> 290: io:format("guard_bif(~p, ~p, ~p) -- ok", [Id, X, Y]); 291: Other -> 292: ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", 293: [Id, X, Y, Other]), 294: ?line test_server:fail() 295: end. 296: 297: try_fail_gbif(Id, X, Y) -> 298: case catch guard_bif(Id, X, Y) of 299: {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y],_}|_]}} -> 300: io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]); 301: Other -> 302: ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", 303: [Id, X, Y, Other]), 304: ?line test_server:fail() 305: end. 306: 307: guard_bif('abs/1', X, Y) when abs(X) == Y -> 308: {'abs/1', X, Y}; 309: guard_bif('float/1', X, Y) when float(X) == Y -> 310: {'float/1', X, Y}; 311: guard_bif('trunc/1', X, Y) when trunc(X) == Y -> 312: {'trunc/1', X, Y}; 313: guard_bif('round/1', X, Y) when round(X) == Y -> 314: {'round/1', X, Y}; 315: guard_bif('length/1', X, Y) when length(X) == Y -> 316: {'length/1', X, Y}; 317: guard_bif('hd/1', X, Y) when hd(X) == Y -> 318: {'hd/1', X, Y}; 319: guard_bif('tl/1', X, Y) when tl(X) == Y -> 320: {'tl/1', X, Y}; 321: guard_bif('size/1', X, Y) when size(X) == Y -> 322: {'size/1', X, Y}; 323: guard_bif('element/2', X, {Pos, Expected}) when element(Pos, X) == Expected -> 324: {'element/2', X, {Pos, Expected}}; 325: guard_bif('self/0', X, Y) when self() == Y -> 326: {'self/0', X, Y}; 327: guard_bif('node/0', X, Y) when node() == Y -> 328: {'node/0', X, Y}; 329: guard_bif('node/1', X, Y) when node(X) == Y -> 330: {'node/1', X, Y}. 331: 332: type_tests(doc) -> "Test the type tests."; 333: type_tests(suite) -> []; 334: type_tests(Config) when list(Config) -> 335: ?line Types = all_types(), 336: ?line Tests = type_test_desc(), 337: ?line put(errors, 0), 338: ?line put(violations, 0), 339: ?line type_tests(Tests, Types), 340: ?line case {get(errors), get(violations)} of 341: {0, 0} -> 342: ok; 343: {0, N} -> 344: {comment, integer_to_list(N) ++ " standard violation(s)"}; 345: {Errors, Violations} -> 346: io:format("~p sub test(s) failed, ~p violation(s)", 347: [Errors, Violations]), 348: ?line test_server:fail() 349: end. 350: 351: type_tests([{Test, AllowedTypes}| T], AllTypes) -> 352: type_tests(Test, AllTypes, AllowedTypes), 353: type_tests(T, AllTypes); 354: type_tests([], _) -> 355: ok. 356: 357: type_tests(Test, [Type|T], Allowed) -> 358: {TypeTag, Value} = Type, 359: case member(TypeTag, Allowed) of 360: true -> 361: case catch type_test(Test, Value) of 362: Test -> 363: ok; 364: _Other -> 365: io:format("Test ~p(~p) failed", [Test, Value]), 366: put(errors, get(errors) + 1) 367: end; 368: false -> 369: case catch type_test(Test, Value) of 370: {'EXIT',{function_clause, 371: [{?MODULE,type_test,[Test,Value],_}|_]}} -> 372: ok; 373: {'EXIT',Other} -> 374: ?line test_server:fail({unexpected_error_reason,Other}); 375: tuple when function(Value) -> 376: io:format("Standard violation: Test ~p(~p) should fail", 377: [Test, Value]), 378: put(violations, get(violations) + 1); 379: _Other -> 380: io:format("Test ~p(~p) succeeded (should fail)", [Test, Value]), 381: put(errors, get(errors) + 1) 382: end 383: end, 384: type_tests(Test, T, Allowed); 385: type_tests(_, [], _) -> 386: ok. 387: 388: all_types() -> 389: [{small, 42}, 390: {big, 392742928742947293873938792874019287447829874290742}, 391: {float, 3.14156}, 392: {nil, []}, 393: {cons, [a]}, 394: {tuple, {a, b}}, 395: {atom, xxxx}, 396: {ref, make_ref()}, 397: {pid, self()}, 398: {port, open_port({spawn, efile}, [])}, 399: {function, fun(X) -> X+1, "" end}, 400: {binary, list_to_binary([])}]. 401: 402: type_test_desc() -> 403: [{integer, [small, big]}, 404: {float, [float]}, 405: {number, [small, big, float]}, 406: {atom, [atom]}, 407: {list, [cons, nil]}, 408: {nonempty_list, [cons]}, 409: {nil, [nil]}, 410: {tuple, [tuple]}, 411: {pid, [pid]}, 412: {port, [port]}, 413: {reference, [ref]}, 414: {function, [function]}]. 415: 416: type_test(integer, X) when integer(X) -> 417: integer; 418: type_test(float, X) when float(X) -> 419: float; 420: type_test(number, X) when number(X) -> 421: number; 422: type_test(atom, X) when atom(X) -> 423: atom; 424: type_test(list, X) when list(X) -> 425: list; 426: type_test(nonempty_list, [_]) -> 427: nonempty_list; 428: type_test(nil, []) -> 429: nil; 430: type_test(tuple, X) when tuple(X) -> 431: tuple; 432: type_test(pid, X) when pid(X) -> 433: pid; 434: type_test(reference, X) when reference(X) -> 435: reference; 436: type_test(port, X) when port(X) -> 437: port; 438: type_test(binary, X) when binary(X) -> 439: binary; 440: type_test(function, X) when function(X) -> 441: function. 442: 443: const_guard(Config) when is_list(Config) -> 444: ?line if 445: (0 == 0) and ((0 == 0) or (0 == 0)) -> 446: ok 447: end. 448: 449: 450: const_cond(Config) when is_list(Config) -> 451: ?line ok = const_cond({}, 0), 452: ?line ok = const_cond({a}, 1), 453: ?line error = const_cond({a,b}, 3), 454: ?line error = const_cond({a}, 0), 455: ?line error = const_cond({a,b}, 1), 456: ok. 457: 458: const_cond(T, Sz) -> 459: case T of 460: _X when false -> never; 461: _X when tuple(T), eq == eq, size(T) == Sz -> ok; 462: _X when tuple(T), eq == leq, size(T) =< Sz -> ok; 463: _X -> error 464: end. 465: 466: basic_not(Config) when is_list(Config) -> 467: True = id(true), 468: False = id(false), 469: Glurf = id(glurf), 470: A = id(5), 471: B = id(37.5), 472: C = id(-1), 473: D = id(5), 474: ATuple = {False,True,Glurf}, 475: 476: ?line check(fun() -> if not false -> ok; true -> error end end, ok), 477: ?line check(fun() -> if not true -> ok; true -> error end end, error), 478: ?line check(fun() -> if not False -> ok; true -> error end end, ok), 479: ?line check(fun() -> if not True -> ok; true -> error end end, error), 480: 481: ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt), 482: ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt), 483: ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq), 484: 485: ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge; 486: not (7 == 453) -> ne; true -> eq end end, le), 487: ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge; 488: not (7 == -8) -> ne; true -> eq end end, ge), 489: ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge; 490: not (7 == 7) -> ne; true -> eq end end, le), 491: 492: ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge; 493: not (A == B) -> ne; true -> eq end end, le), 494: ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge; 495: not (A == C) -> ne; true -> eq end end, ge), 496: ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge; 497: not (A == D) -> ne; true -> eq end end, le), 498: 499: ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok), 500: ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error), 501: ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error), 502: 503: ?line check(fun() -> if not glurf -> ok; true -> error end end, error), 504: ?line check(fun() -> if not Glurf -> ok; true -> error end end, error), 505: 506: ok. 507: 508: complex_not(Config) when is_list(Config) -> 509: ATuple = id({false,true,gurka}), 510: ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok), 511: ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error), 512: 513: ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok; 514: true -> error end end, error), 515: ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok; 516: true -> error end end, ok), 517: 518: ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok; 519: true -> error end end, ok), 520: ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok; 521: true -> error end end, error), 522: 523: ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok; 524: true -> error end end, error), 525: 526: %% orelse 527: ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok; 528: true -> error end end, error), 529: 530: ok. 531: 532: semicolon(Config) when is_list(Config) -> 533: 534: %% True/false combined using ';' (literal atoms). 535: 536: ?line check(fun() -> if true; false -> ok end end, ok), 537: ?line check(fun() -> if false; true -> ok end end, ok), 538: ?line check(fun() -> if true; true -> ok end end, ok), 539: ?line check(fun() -> if false; false -> ok; true -> error end end, error), 540: ?line check(fun() -> 541: {'EXIT',{if_clause,_}} = (catch if false; false -> ok end), 542: exit 543: end, exit), 544: 545: %% True/false combined used ';'. 546: 547: True = id(true), 548: False = id(false), 549: 550: ?line check(fun() -> if True; False -> ok end end, ok), 551: ?line check(fun() -> if False; True -> ok end end, ok), 552: ?line check(fun() -> if True; True -> ok end end, ok), 553: ?line check(fun() -> if False; False -> ok; true -> error end end, error), 554: ?line check(fun() -> 555: {'EXIT',{if_clause,_}} = (catch if False; False -> ok end), 556: exit 557: end, exit), 558: 559: %% Combine true/false with a non-boolean value. 560: Glurf = id(glurf), 561: 562: 563: ?line check(fun() -> if True; Glurf -> ok end end, ok), 564: ?line check(fun() -> if Glurf; True -> ok end end, ok), 565: ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error), 566: ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error), 567: ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error), 568: ?line check(fun() -> 569: {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end), 570: exit 571: end, exit), 572: 573: %% Combine true/false with errors. 574: 575: ATuple = id({false,true,gurka}), 576: 577: ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok), 578: ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok), 579: ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok; 580: true -> error end end, error), 581: ?line check(fun() -> if False; element(42, ATuple) -> ok; 582: true -> error end end, error), 583: ?line check(fun() -> if element(42, ATuple); 584: False -> ok; true -> error end end, error), 585: ?line check(fun() -> 586: {'EXIT',{if_clause,_}} = 587: (catch if element(42, ATuple); 588: element(42, ATuple) -> ok end), 589: exit 590: end, exit), 591: 592: ok. 593: 594: complex_semicolon(Config) when is_list(Config) -> 595: ?line ok = csemi1(int, {blurf}), 596: ?line ok = csemi1(string, {blurf}), 597: ?line ok = csemi1(float, [a]), 598: ?line error = csemi1(35, 42), 599: 600: %% 2 601: ?line ok = csemi2({}, {a,b,c}), 602: ?line ok = csemi2({1,3.5}, {a,b,c}), 603: ?line ok = csemi2(dum, {a,b,c}), 604: 605: ?line ok = csemi2({45,-19.3}, {}), 606: ?line ok = csemi2({45,-19.3}, {dum}), 607: ?line ok = csemi2({45,-19.3}, {dum,dum}), 608: 609: ?line error = csemi2({45}, {dum}), 610: ?line error = csemi2([], {dum}), 611: ?line error = csemi2({dum}, []), 612: ?line error = csemi2([], []), 613: 614: %% 3 615: ?line csemi3(fun csemi3a/4), 616: ?line csemi3(fun csemi3b/4), 617: ?line csemi3(fun csemi3c/4), 618: 619: %% 4 620: ?line csemi4(fun csemi4a/4), 621: ?line csemi4(fun csemi4b/4), 622: ?line csemi4(fun csemi4c/4), 623: ?line csemi4(fun csemi4d/4), 624: 625: %% 4, 'orelse' instead of 'or' 626: ?line csemi4_orelse(fun csemi4_orelse_a/4), 627: ?line csemi4_orelse(fun csemi4_orelse_b/4), 628: ?line csemi4_orelse(fun csemi4_orelse_c/4), 629: ?line csemi4_orelse(fun csemi4_orelse_d/4), 630: 631: ok. 632: 633: csemi1(Type, Val) when is_list(Val), Type == float; 634: Type == int; Type == string -> ok; 635: csemi1(_, _) -> error. 636: 637: csemi2(A, B) when size(A) > 1; size(B) > 2 -> ok; 638: csemi2(_, _) -> error. 639: 640: csemi3(Csemi3) -> 641: ok = Csemi3({}, {a,b,c}, [0], [0]), 642: ok = Csemi3({1,3.5}, {a,b,c}, -1, -1), 643: ok = Csemi3(dum, {a,b,c}, 0.0, 0.0), 644: ok = Csemi3(dum, {c}, b, a), 645: ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0), 646: ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1), 647: 648: ok = Csemi3({45,-19.3}, {}, [], []), 649: ok = Csemi3({45,-19.3}, {dum}, 42, 42), 650: ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33), 651: 652: ok = Csemi3({45}, {dum}, 1.0, 0), 653: ok = Csemi3([a], {dum}, 1.0, 0), 654: ok = Csemi3({dum}, [], 1.0, 0), 655: ok = Csemi3([], [], 1.0, 0), 656: ok = Csemi3(blurf, {dum}, 1.0, 0), 657: ok = Csemi3({a}, blurf, 1.0, 0), 658: ok = Csemi3([a], [dum], 1.0, 0), 659: ok = Csemi3({dum}, [], 1.0, 0), 660: ok = Csemi3([], [], 1.0, 0), 661: 662: error = Csemi3({45}, {dum}, 0, 0), 663: error = Csemi3([a], {dum}, 0, 0), 664: error = Csemi3({dum}, [], 0, 0), 665: error = Csemi3([], [], 0, 0), 666: ok. 667: 668: csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok; 669: csemi3a(_, _, _, _) -> error. 670: 671: csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok; 672: csemi3b(_, _, _, _) -> error. 673: 674: csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok; 675: csemi3c(_, _, _, _) -> error. 676: 677: 678: csemi4(Test) -> 679: ok = Test({a,b}, 2, {c,d}, 2), 680: ok = Test({1,2,3}, 0, [], 0), 681: ok = Test({}, 2, blurf, 0), 682: ok = Test({}, 2, {1}, 2), 683: 684: error = Test([], 4, {}, 0), 685: error = Test({}, 0, [a,b], 4), 686: error = Test({}, 0, [a,b], 0), 687: error = Test([], 0, {}, 0), 688: error = Test({}, 0, {}, 0), 689: 690: ok. 691: 692: csemi4a(A, X, B, Y) when (size(A) > 1) or (X > 1); 693: (size(B) > 1) or (Y > 1) -> ok; 694: csemi4a(_, _, _, _) -> error. 695: 696: csemi4b(A, X, B, Y) when (X > 1) or (size(A) > 1); 697: (size(B) > 1) or (Y > 1) -> ok; 698: csemi4b(_, _, _, _) -> error. 699: 700: csemi4c(A, X, B, Y) when (size(A) > 1) or (X > 1); 701: (Y > 1) or (size(B) > 1) -> ok; 702: csemi4c(_, _, _, _) -> error. 703: 704: csemi4d(A, X, B, Y) when (X > 1) or (size(A) > 1); 705: (Y > 1) or (size(B) > 1) -> ok; 706: csemi4d(_, _, _, _) -> error. 707: 708: 709: csemi4_orelse(Test) -> 710: ok = Test({a,b}, 2, {c,d}, 2), 711: ok = Test({1,2,3}, 0, [], 0), 712: ok = Test({}, 2, blurf, 0), 713: ok = Test({}, 2, {1}, 2), 714: 715: ?line error = Test([], 1, {}, 0), 716: 717: ok. 718: 719: csemi4_orelse_a(A, X, B, Y) when (size(A) > 1) orelse (X > 1); 720: (size(B) > 1) orelse (Y > 1) -> ok; 721: csemi4_orelse_a(_, _, _, _) -> error. 722: 723: csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (size(A) > 1); 724: (size(B) > 1) orelse (Y > 1) -> ok; 725: csemi4_orelse_b(_, _, _, _) -> error. 726: 727: csemi4_orelse_c(A, X, B, Y) when (size(A) > 1) orelse (X > 1); 728: (Y > 1) orelse (size(B) > 1) -> ok; 729: csemi4_orelse_c(_, _, _, _) -> error. 730: 731: csemi4_orelse_d(A, X, B, Y) when (X > 1) or (size(A) > 1); 732: (Y > 1) or (size(B) > 1) -> ok; 733: csemi4_orelse_d(_, _, _, _) -> error. 734: 735: 736: comma(Config) when is_list(Config) -> 737: 738: %% ',' combinations of literal true/false. 739: 740: ?line check(fun() -> if true, false -> ok; true -> error end end, error), 741: ?line check(fun() -> if false, true -> ok; true -> error end end, error), 742: ?line check(fun() -> if true, true -> ok end end, ok), 743: ?line check(fun() -> if false, false -> ok; true -> error end end, error), 744: ?line check(fun() -> 745: {'EXIT',{if_clause,_}} = 746: (catch if true, false -> ok; 747: false, true -> ok; 748: false, false -> ok 749: end), 750: exit 751: end, exit), 752: 753: %% ',' combinations of true/false in variables. 754: 755: True = id(true), 756: False = id(false), 757: 758: ?line check(fun() -> if True, False -> ok; true -> error end end, error), 759: ?line check(fun() -> if False, True -> ok; true -> error end end, error), 760: ?line check(fun() -> if True, True -> ok end end, ok), 761: ?line check(fun() -> if False, False -> ok; true -> error end end, error), 762: ?line check(fun() -> 763: {'EXIT',{if_clause,_}} = 764: (catch if True, False -> ok; 765: False, True -> ok; 766: False, False -> ok 767: end), 768: exit 769: end, exit), 770: 771: %% ',' combinations of true/false, and non-boolean in variables. 772: 773: Glurf = id(glurf), 774: 775: ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error), 776: ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error), 777: ?line check(fun() -> if True, True -> ok end end, ok), 778: ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error), 779: ?line check(fun() -> 780: {'EXIT',{if_clause,_}} = 781: (catch if True, Glurf -> ok; 782: Glurf, True -> ok; 783: Glurf, Glurf -> ok 784: end), 785: exit 786: end, exit), 787: 788: %% ',' combinations of true/false with errors. 789: ATuple = id({a,b,c}), 790: 791: ?line check(fun() -> if True, element(42, ATuple) -> ok; 792: true -> error end end, error), 793: ?line check(fun() -> if element(42, ATuple), True -> ok; 794: true -> error end end, error), 795: ?line check(fun() -> if True, True -> ok end end, ok), 796: ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok; 797: true -> error end end, error), 798: ?line check(fun() -> 799: {'EXIT',{if_clause,_}} = 800: (catch if True, element(42, ATuple) -> ok; 801: element(42, ATuple), True -> ok; 802: element(42, ATuple), element(42, ATuple) -> ok 803: end), 804: exit 805: end, exit), 806: 807: ok. 808: 809: or_guard(Config) when is_list(Config) -> 810: True = id(true), 811: False = id(false), 812: Glurf = id(glurf), 813: 814: %% 'or' combinations of literal true/false. 815: ?line check(fun() -> if true or false -> ok end end, ok), 816: ?line check(fun() -> if false or true -> ok end end, ok), 817: ?line check(fun() -> if true or true -> ok end end, ok), 818: ?line check(fun() -> if false or false -> ok; true -> error end end, error), 819: 820: ?line check(fun() -> if glurf or true -> ok; true -> error end end, error), 821: ?line check(fun() -> if true or glurf -> ok; true -> error end end, error), 822: ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error), 823: 824: ?line check(fun() -> 825: {'EXIT',{if_clause,_}} = (catch if false or false -> ok end), 826: exit 827: end, exit), 828: 829: 830: %% 'or' combinations using variables containing true/false. 831: ?line check(fun() -> if True or False -> ok end end, ok), 832: ?line check(fun() -> if False or True -> ok end end, ok), 833: ?line check(fun() -> if True or True -> ok end end, ok), 834: ?line check(fun() -> if False or False -> ok; true -> error end end, error), 835: 836: ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error), 837: ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error), 838: ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error), 839: 840: ?line check(fun() -> 841: {'EXIT',{if_clause,_}} = (catch if False or False -> ok end), 842: exit 843: end, exit), 844: 845: ok. 846: 847: more_or_guards(Config) when is_list(Config) -> 848: True = id(true), 849: False = id(false), 850: ATuple = id({false,true,gurka}), 851: 852: ?line check(fun() -> 853: if element(42, ATuple) or False -> ok; 854: true -> error end 855: end, error), 856: 857: ?line check(fun() -> 858: if False or element(42, ATuple) -> ok; 859: true -> error end 860: end, error), 861: 862: ?line check(fun() -> 863: if element(18, ATuple) or element(42, ATuple) -> ok; 864: true -> error end 865: end, error), 866: 867: ?line check(fun() -> 868: if True or element(42, ATuple) -> ok; 869: true -> error end 870: end, error), 871: 872: ?line check(fun() -> 873: if element(42, ATuple) or True -> ok; 874: true -> error end 875: end, error), 876: 877: ?line check(fun() -> 878: if element(1, ATuple) or element(42, ATuple) or True -> ok; 879: true -> error end 880: end, error), 881: 882: ?line check(fun() -> 883: if element(1, ATuple) or True or element(42, ATuple) -> ok; 884: true -> error end 885: end, error), 886: 887: ?line check(fun() -> 888: if 889: (<<False:8>> == <<0>>) or element(2, ATuple) -> ok; 890: true -> error end 891: end, error), 892: 893: ?line check(fun() -> 894: if 895: element(2, ATuple) or (<<True:8>> == <<1>>) -> ok; 896: true -> error end 897: end, error), 898: 899: ?line check(fun() -> 900: if element(2, ATuple) or element(42, ATuple) -> ok; 901: true -> error end 902: end, error), 903: 904: ?line check(fun() -> 905: if 906: element(1, ATuple) or 907: element(2, ATuple) or 908: element(19, ATuple) -> ok; 909: true -> error end 910: end, error), 911: ok. 912: 913: complex_or_guards(Config) when is_list(Config) -> 914: %% complex_or_1/2 915: ?line ok = complex_or_1({a,b,c,d}, {1,2,3}), 916: ?line ok = complex_or_1({a,b,c,d}, {1}), 917: ?line ok = complex_or_1({a}, {1,2,3}), 918: ?line error = complex_or_1({a}, {1}), 919: 920: ?line error = complex_or_1(1, 2), 921: ?line error = complex_or_1([], {a,b,c,d}), 922: ?line error = complex_or_1({a,b,c,d}, []), 923: 924: 925: %% complex_or_2/1 926: ?line ok = complex_or_2({true,{}}), 927: ?line ok = complex_or_2({false,{a}}), 928: ?line ok = complex_or_2({false,{a,b,c}}), 929: ?line ok = complex_or_2({true,{a,b,c,d}}), 930: 931: ?line error = complex_or_2({blurf,{a,b,c}}), 932: 933: ?line error = complex_or_2({true}), 934: ?line error = complex_or_2({true,no_tuple}), 935: ?line error = complex_or_2({true,[]}), 936: 937: %% complex_or_3/2 938: ?line ok = complex_or_3({true}, {}), 939: ?line ok = complex_or_3({false}, {a}), 940: ?line ok = complex_or_3({false}, {a,b,c}), 941: ?line ok = complex_or_3({true}, {a,b,c,d}), 942: ?line ok = complex_or_3({false}, <<1,2,3>>), 943: ?line ok = complex_or_3({true}, <<1,2,3,4>>), 944: 945: ?line error = complex_or_3(blurf, {a,b,c}), 946: 947: ?line error = complex_or_3({false}, <<1,2,3,4>>), 948: ?line error = complex_or_3([], <<1,2>>), 949: ?line error = complex_or_3({true}, 45), 950: ?line error = complex_or_3(<<>>, <<>>), 951: 952: %% complex_or_4/2 953: ?line ok = complex_or_4(<<1,2,3>>, {true}), 954: ?line ok = complex_or_4(<<1,2,3>>, {false}), 955: ?line ok = complex_or_4(<<1,2,3>>, {true}), 956: ?line ok = complex_or_4({1,2,3}, {true}), 957: ?line error = complex_or_4({1,2,3,4}, {false}), 958: 959: ?line error = complex_or_4(<<1,2,3,4>>, []), 960: ?line error = complex_or_4([], {true}), 961: 962: %% complex_or_5/2 963: ?line ok = complex_or_5(<<1>>, {false}), 964: ?line ok = complex_or_5(<<1,2,3>>, {true}), 965: ?line ok = complex_or_5(<<1,2,3,4>>, {false}), 966: ?line ok = complex_or_5({1,2,3}, {false}), 967: ?line ok = complex_or_5({1,2,3,4}, {false}), 968: 969: ?line error = complex_or_5(blurf, {false}), 970: ?line error = complex_or_5(<<1>>, klarf), 971: ?line error = complex_or_5(blurf, klarf), 972: 973: %% complex_or_6/2 974: ?line ok = complex_or_6({true,true}, {1,2,3,4}), 975: ?line ok = complex_or_6({true,true}, <<1,2,3,4>>), 976: ?line ok = complex_or_6({false,false}, <<1,2,3,4>>), 977: ?line ok = complex_or_6({false,true}, <<1>>), 978: ?line ok = complex_or_6({true,false}, {1}), 979: ?line ok = complex_or_6({true,true}, {1}), 980: 981: ?line error = complex_or_6({false,false}, {1}), 982: 983: ?line error = complex_or_6({true}, {1,2,3,4}), 984: ?line error = complex_or_6({}, {1,2,3,4}), 985: ?line error = complex_or_6([], {1,2,3,4}), 986: ?line error = complex_or_6([], {1,2,3,4}), 987: ?line error = complex_or_6({true,false}, klurf), 988: 989: ok. 990: 991: complex_or_1(A, B) -> 992: if 993: ((3 < size(A)) and (size(A) < 9)) or 994: ((2 < size(B)) and (size(B) < 7)) -> ok; 995: true -> error 996: end. 997: 998: complex_or_2(Tuple) -> 999: if 1000: element(1, Tuple) or not (size(element(2, Tuple)) > 3) -> ok; 1001: true -> error 1002: end. 1003: 1004: complex_or_3(A, B) -> 1005: if 1006: not (size(B) > 3) or element(1, A) -> ok; 1007: true -> error 1008: end. 1009: 1010: complex_or_4(A, B) -> 1011: if 1012: not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok; 1013: true -> error 1014: end. 1015: 1016: complex_or_5(A, B) -> 1017: if 1018: not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok; 1019: true -> error 1020: end. 1021: 1022: complex_or_6(A, B) -> 1023: if 1024: not (not element(1, A) and not element(2, A)) or 1025: not (not (size(B) > 3)) -> ok; 1026: true -> error 1027: end. 1028: 1029: and_guard(Config) when is_list(Config) -> 1030: 1031: %% 'and' combinations of literal true/false. 1032: 1033: ?line check(fun() -> if true and false -> ok; true -> error end end, error), 1034: ?line check(fun() -> if false and true -> ok; true -> error end end, error), 1035: ?line check(fun() -> if true and true -> ok end end, ok), 1036: ?line check(fun() -> if false and false -> ok; true -> error end end, error), 1037: 1038: ?line check(fun() -> if glurf and true -> ok; true -> error end end, error), 1039: ?line check(fun() -> if true and glurf -> ok; true -> error end end, error), 1040: ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error), 1041: 1042: ?line check(fun() -> 1043: {'EXIT',{if_clause,_}} = 1044: (catch if true and false -> ok; 1045: false and true -> ok; 1046: false and false -> ok 1047: end), 1048: exit 1049: end, exit), 1050: 1051: %% 'and' combinations of true/false in variables. 1052: 1053: True = id(true), 1054: False = id(false), 1055: 1056: ?line check(fun() -> if True and False -> ok; true -> error end end, error), 1057: ?line check(fun() -> if False and True -> ok; true -> error end end, error), 1058: ?line check(fun() -> if True and True -> ok end end, ok), 1059: ?line check(fun() -> if False and False -> ok; true -> error end end, error), 1060: ?line check(fun() -> 1061: {'EXIT',{if_clause,_}} = 1062: (catch if True and False -> ok; 1063: False and True -> ok; 1064: False and False -> ok 1065: end), 1066: exit 1067: end, exit), 1068: 1069: %% 'and' combinations of true/false and a non-boolean in variables. 1070: 1071: Glurf = id(glurf), 1072: 1073: ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error), 1074: ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error), 1075: ?line check(fun() -> if True and True -> ok end end, ok), 1076: ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error), 1077: ?line check(fun() -> 1078: {'EXIT',{if_clause,_}} = 1079: (catch if True and Glurf -> ok; 1080: Glurf and True -> ok; 1081: Glurf and Glurf -> ok 1082: end), 1083: exit 1084: end, exit), 1085: 1086: %% 'and' combinations of true/false with errors. 1087: ATuple = id({a,b,c}), 1088: 1089: ?line check(fun() -> if True and element(42, ATuple) -> ok; 1090: true -> error end end, error), 1091: ?line check(fun() -> if element(42, ATuple) and True -> ok; 1092: true -> error end end, error), 1093: ?line check(fun() -> if True and True -> ok end end, ok), 1094: ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok; 1095: true -> error end end, error), 1096: ?line check(fun() -> 1097: {'EXIT',{if_clause,_}} = 1098: (catch if True and element(42, ATuple) -> ok; 1099: element(42, ATuple) and True -> ok; 1100: element(42, ATuple) and element(42, ATuple) -> ok 1101: end), 1102: exit 1103: end, exit), 1104: 1105: ?line ok = relprod({'Set',a,b}, {'Set',a,b}), 1106: 1107: ok. 1108: 1109: relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') -> 1110: ok. 1111: 1112: 1113: xor_guard(Config) when is_list(Config) -> 1114: 1115: %% 'xor' combinations of literal true/false. 1116: ?line check(fun() -> if true xor false -> ok end end, ok), 1117: ?line check(fun() -> if false xor true -> ok end end, ok), 1118: ?line check(fun() -> if true xor true -> ok; true -> error end end, error), 1119: ?line check(fun() -> if false xor false -> ok; true -> error end end, error), 1120: ?line check(fun() -> 1121: {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end), 1122: exit 1123: end, exit), 1124: ?line check(fun() -> 1125: {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end), 1126: exit 1127: end, exit), 1128: 1129: 1130: %% 'xor' combinations using variables containing true/false. 1131: 1132: True = id(true), 1133: False = id(false), 1134: 1135: ?line check(fun() -> if True xor False -> ok end end, ok), 1136: ?line check(fun() -> if False xor True -> ok end end, ok), 1137: ?line check(fun() -> if True xor True -> ok; true -> error end end, error), 1138: ?line check(fun() -> if False xor False -> ok; true -> error end end, error), 1139: ?line check(fun() -> 1140: {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end), 1141: exit 1142: end, exit), 1143: ?line check(fun() -> 1144: {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end), 1145: exit 1146: end, exit), 1147: 1148: ok. 1149: 1150: more_xor_guards(Config) when is_list(Config) -> 1151: True = id(true), 1152: False = id(false), 1153: ATuple = id({false,true,gurka}), 1154: 1155: ?line check(fun() -> 1156: if element(42, ATuple) xor False -> ok; 1157: true -> error end 1158: end, error), 1159: 1160: ?line check(fun() -> 1161: if False xor element(42, ATuple) xor False -> ok; 1162: true -> error end 1163: end, error), 1164: 1165: ?line check(fun() -> 1166: if element(18, ATuple) xor element(42, ATuple) -> ok; 1167: true -> error end 1168: end, error), 1169: 1170: ?line check(fun() -> 1171: if True xor element(42, ATuple) -> ok; 1172: true -> error end 1173: end, error), 1174: 1175: ?line check(fun() -> 1176: if element(42, ATuple) xor True -> ok; 1177: true -> error end 1178: end, error), 1179: ok. 1180: 1181: build_in_guard(Config) when is_list(Config) -> 1182: SubBin = <<5.0/float>>, 1183: ?line B = <<1,SubBin/binary,3.5/float>>, 1184: ?line if 1185: B =:= <<1,SubBin/binary,3.5/float>> -> ok 1186: end. 1187: 1188: old_guard_tests(Config) when list(Config) -> 1189: %% Check that all the old guard tests are still recognized. 1190: ?line list = og(Config), 1191: ?line atom = og(an_atom), 1192: ?line binary = og(<<1,2>>), 1193: ?line float = og(3.14), 1194: ?line integer = og(43), 1195: ?line a_function = og(fun() -> ok end), 1196: ?line pid = og(self()), 1197: ?line reference = og(make_ref()), 1198: ?line tuple = og({}), 1199: 1200: ?line number = on(45.333), 1201: ?line number = on(-19), 1202: ok. 1203: 1204: og(V) when atom(V) -> atom; 1205: og(V) when binary(V) -> binary; 1206: og(V) when float(V) -> float; 1207: og(V) when integer(V) -> integer; 1208: og(V) when function(V) -> a_function; 1209: og(V) when list(V) -> list; 1210: og(V) when pid(V) -> pid; 1211: og(V) when port(V) -> port; 1212: og(V) when reference(V) -> reference; 1213: og(V) when tuple(V) -> tuple; 1214: og(_) -> what. 1215: 1216: on(V) when number(V) -> number; 1217: on(_) -> not_number. 1218: 1219: gbif(Config) when is_list(Config) -> 1220: ?line error = gbif_1(1, {false,true}), 1221: ?line ok = gbif_1(2, {false,true}), 1222: ok. 1223: 1224: gbif_1(P, T) when element(P, T) -> ok; 1225: gbif_1(_, _) -> error. 1226: 1227: 1228: t_is_boolean(Config) when is_list(Config) -> 1229: ?line true = is_boolean(true), 1230: ?line true = is_boolean(false), 1231: ?line true = is_boolean(id(true)), 1232: ?line true = is_boolean(id(false)), 1233: 1234: ?line false = is_boolean(glurf), 1235: ?line false = is_boolean(id(glurf)), 1236: 1237: ?line false = is_boolean([]), 1238: ?line false = is_boolean(id([])), 1239: ?line false = is_boolean(42), 1240: ?line false = is_boolean(id(-42)), 1241: 1242: ?line false = is_boolean(math:pi()), 1243: ?line false = is_boolean(384793478934378924978439789873478934897), 1244: 1245: ?line false = is_boolean(id(self())), 1246: ?line false = is_boolean(id({x,y,z})), 1247: ?line false = is_boolean(id([a,b,c])), 1248: ?line false = is_boolean(id(make_ref())), 1249: ?line false = is_boolean(id(<<1,2,3>>)), 1250: 1251: ?line ok = bool(true), 1252: ?line ok = bool(false), 1253: ?line ok = bool(id(true)), 1254: ?line ok = bool(id(false)), 1255: 1256: ?line error = bool(glurf), 1257: ?line error = bool(id(glurf)), 1258: 1259: ?line error = bool([]), 1260: ?line error = bool(id([])), 1261: ?line error = bool(42), 1262: ?line error = bool(id(-42)), 1263: 1264: ?line error = bool(math:pi()), 1265: ?line error = bool(384793478934378924978439789873478934897), 1266: 1267: ?line error = bool(id(self())), 1268: ?line error = bool(id({x,y,z})), 1269: ?line error = bool(id([a,b,c])), 1270: ?line error = bool(id(make_ref())), 1271: ?line error = bool(id(<<1,2,3>>)), 1272: 1273: ok. 1274: 1275: bool(X) when is_boolean(X) -> ok; 1276: bool(_) -> error. 1277: 1278: 1279: is_function_2(Config) when is_list(Config) -> 1280: true = is_function(id(fun ?MODULE:all/1), 1), 1281: true = is_function(id(fun() -> ok end), 0), 1282: false = is_function(id(fun ?MODULE:all/1), 0), 1283: false = is_function(id(fun() -> ok end), 1), 1284: 1285: F = fun(_) -> ok end, 1286: if 1287: is_function(F, 1) -> ok 1288: end. 1289: 1290: tricky(Config) when is_list(Config) -> 1291: ?line not_ok = tricky_1(1, 2), 1292: ?line not_ok = tricky_1(1, blurf), 1293: ?line not_ok = tricky_1(foo, 2), 1294: ?line not_ok = tricky_1(a, b), 1295: 1296: ?line false = rb(100000, [1], 42), 1297: ?line true = rb(100000, [], 42), 1298: ?line true = rb(555, [a,b,c], 19), 1299: ok. 1300: 1301: tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok; 1302: tricky_1(_, _) -> not_ok. 1303: 1304: %% From dets_v9:read_buckets/11, simplified. 1305: 1306: rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true; 1307: rb(_, _, _) -> false. 1308: 1309: 1310: -define(T(Op,A,B), 1311: ok = if A Op B -> ok; true -> error end, 1312: ok = if not (A Op B) -> error; true -> ok end, 1313: (fun(X, Y, True, False) -> 1314: ok = if X Op Y -> ok; true -> error end, 1315: ok = if False; X Op Y; False -> ok; true -> error end, 1316: ok = if X Op Y, True -> ok; true -> error end, 1317: ok = if not (X Op Y) -> error; true -> ok end, 1318: ok = if False; not (X Op Y); False -> error; true -> ok end 1319: end)(id(A), id(B), id(true), id(false))). 1320: 1321: -define(F(Op,A,B), 1322: ok = if A Op B -> error; true -> ok end, 1323: ok = if not (A Op B) -> ok; true -> error end, 1324: (fun(X, Y, True, False) -> 1325: ok = if X Op Y -> error; true -> ok end, 1326: ok = if False; X Op Y; False -> error; true -> ok end, 1327: ok = if not (X Op Y); False -> ok; true -> error end, 1328: ok = if not (X Op Y), True -> ok; true -> error end 1329: end)(id(A), id(B), id(true), id(false))). 1330: 1331: 1332: rel_ops(Config) when is_list(Config) -> 1333: ?line ?T(=/=, 1, 1.0), 1334: ?line ?F(=/=, 2, 2), 1335: ?line ?F(=/=, {a}, {a}), 1336: 1337: ?line ?F(/=, a, a), 1338: ?line ?F(/=, 0, 0.0), 1339: ?line ?T(/=, 0, 1), 1340: ?line ?F(/=, {a}, {a}), 1341: 1342: ?line ?T(==, 1, 1.0), 1343: ?line ?F(==, a, {}), 1344: 1345: ?line ?F(=:=, 1, 1.0), 1346: ?line ?T(=:=, 42.0, 42.0), 1347: 1348: ?line ?F(>, a, b), 1349: ?line ?T(>, 42, 1.0), 1350: ?line ?F(>, 42, 42.0), 1351: 1352: ?line ?T(<, a, b), 1353: ?line ?F(<, 42, 1.0), 1354: ?line ?F(<, 42, 42.0), 1355: 1356: ?line ?T(=<, 1.5, 5), 1357: ?line ?F(=<, -9, -100.344), 1358: ?line ?T(=<, 42, 42.0), 1359: 1360: ?line ?T(>=, 42, 42.0), 1361: ?line ?F(>=, a, b), 1362: ?line ?T(>=, 1.0, 0), 1363: 1364: ok. 1365: 1366: -undef(TestOp). 1367: 1368: basic_andalso_orelse(Config) when is_list(Config) -> 1369: ?line T = id({type,integers,23,42}), 1370: ?line 65 = if 1371: ((element(1, T) =:= type) andalso (size(T) =:= 4) andalso 1372: element(2, T) == integers) -> 1373: element(3, T) + element(4, T); 1374: true -> error 1375: end, 1376: ?line 65 = case [] of 1377: [] when ((element(1, T) =:= type) andalso (size(T) =:= 4) andalso 1378: element(2, T) == integers) -> 1379: element(3, T) + element(4, T) 1380: end, 1381: 1382: ?line 42 = basic_rt({type,integers,40,2}), 1383: ?line 5.0 = basic_rt({vector,{3.0,4.0}}), 1384: ?line 20 = basic_rt(['+',3,7]), 1385: ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}), 1386: ?line 12 = basic_rt({klurf,4}), 1387: 1388: ?line error = basic_rt({type,integers,40,2,3}), 1389: ?line error = basic_rt({kalle,integers,40,2}), 1390: ?line error = basic_rt({kalle,integers,40,2}), 1391: ?line error = basic_rt({1,2}), 1392: ?line error = basic_rt([]), 1393: 1394: RelProdBody = 1395: fun(R1, R2) -> 1396: if 1397: (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'), 1398: (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') -> 1399: ok 1400: end 1401: end, 1402: 1403: ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}), 1404: ok. 1405: 1406: basic_rt(T) when is_tuple(T) andalso size(T) =:= 4 andalso element(1, T) =:= type andalso 1407: element(2, T) == integers -> 1408: element(3, T) + element(4, T); 1409: basic_rt(T) when is_tuple(T) andalso size(T) =:= 2 andalso element(1, T) =:= vector -> 1410: {X,Y} = element(2, T), 1411: if 1412: is_float(X), is_float(Y) -> 1413: math:sqrt(X*X+Y*Y) 1414: end; 1415: basic_rt(['+',A,B]) -> 1416: 2*id(A+B); 1417: basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set', 1418: erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' -> 1419: R1 = id(R1), 1420: R2 = id(R2), 1421: R1; 1422: basic_rt(T) when is_tuple(T) andalso size(T) =:= 2 andalso element(1, T) =:= klurf -> 1423: 3*id(element(2, T)); 1424: basic_rt(_) -> 1425: error. 1426: 1427: traverse_dcd(Config) when is_list(Config) -> 1428: L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c}, 1429: {log_header,dcd_log,"0.0",a,b,c},blurf], 1430: {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} = 1431: traverse_dcd({cont,L0}, log, funny), 1432: L1 = [{log_header,dcd_log,"1.0"}], 1433: {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny), 1434: L2 = [{a,tuple}], 1435: {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny), 1436: ok. 1437: 1438: %% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}. 1439: %% The outer match of a two tuple will places the first element in {x,3} and 1440: %% second in {x,4}. The guard for the first clause must make ensure that all of those 1441: %% registers are restored befor entering the second clause. 1442: %% 1443: %% (From mnesia_checkpoint.erl, modified.) 1444: 1445: traverse_dcd({Cont,[LogH|Rest]},Log,Fun) 1446: when is_tuple(LogH) andalso size(LogH) =:= 6 andalso element(1, LogH) =:= log_header 1447: andalso erlang:element(2,LogH) == dcd_log, 1448: is_tuple(LogH) andalso size(LogH) =:= 6 andalso element(1, LogH) =:= log_header 1449: andalso erlang:element(3,LogH) >= "1.0" -> 1450: traverse_dcd({Cont,Rest},Log,Fun); 1451: traverse_dcd({Cont,Recs},Log,Fun) -> 1452: {Cont,Recs,Log,Fun}. 1453: 1454: 1455: check_qlc_hrl(Config) when is_list(Config) -> 1456: St = {r1,false,dum}, 1457: ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St), 1458: ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St), 1459: ?line St = cqlc(qlc, q, [], St), 1460: ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St), 1461: ?line St = cqlc(q, q, [{lc,1,2,3},b], St), 1462: ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St), 1463: ?line St = cqlc(qlc, q, [a,b], St), 1464: ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}), 1465: ok. 1466: 1467: %% From erl_lint.erl; original name was check_qlc_hrl/4. 1468: cqlc(M, F, As, St) -> 1469: Arity = length(As), 1470: case As of 1471: [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q, 1472: Arity < 3, 1473: not (((element(1, St) =:= r1) orelse fail) and (size(St) =:= 3) and element(2, St)) -> 1474: foo; 1475: _ -> 1476: St 1477: end. 1478: 1479: %% OTP-7679: Thanks to Hunter Morris. 1480: andalso_semi(Config) when is_list(Config) -> 1481: ?line ok = andalso_semi_foo(0), 1482: ?line ok = andalso_semi_foo(1), 1483: ?line fc(catch andalso_semi_foo(2)), 1484: 1485: ?line ok = andalso_semi_bar([a,b,c]), 1486: ?line ok = andalso_semi_bar(1), 1487: ?line fc(catch andalso_semi_bar([a,b])), 1488: ok. 1489: 1490: andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 -> 1491: ok. 1492: 1493: andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 -> 1494: ok. 1495: 1496: 1497: t_tuple_size(Config) when is_list(Config) -> 1498: ?line 10 = do_tuple_size({1,2,3,4}), 1499: ?line fc(catch do_tuple_size({1,2,3})), 1500: ?line fc(catch do_tuple_size(42)), 1501: 1502: ?line error = ludicrous_tuple_size({a,b,c}), 1503: ?line error = ludicrous_tuple_size([a,b,c]), 1504: 1505: ok. 1506: 1507: do_tuple_size(T) when tuple_size(T) =:= 4 -> 1508: {A,B,C,D} = T, 1509: A+B+C+D. 1510: 1511: ludicrous_tuple_size(T) 1512: when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok; 1513: ludicrous_tuple_size(T) 1514: when tuple_size(T) =:= 16#10000000000000000 -> ok; 1515: ludicrous_tuple_size(T) 1516: when tuple_size(T) =:= (1 bsl 64) - 1 -> ok; 1517: ludicrous_tuple_size(T) 1518: when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok; 1519: ludicrous_tuple_size(_) -> error. 1520: 1521: %% 1522: %% The binary_part/2,3 guard BIFs 1523: %% 1524: -define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))). 1525: mask_error({'EXIT',{Err,_}}) -> 1526: Err; 1527: mask_error(Else) -> 1528: Else. 1529: 1530: binary_part(doc) -> 1531: ["Tests the binary_part/2,3 guard (GC) bif's"]; 1532: binary_part(Config) when is_list(Config) -> 1533: %% This is more or less a copy of what the guard_SUITE in emulator 1534: %% does to cover the guard bif's 1535: ?line 1 = bptest(<<1,2,3>>), 1536: ?line 2 = bptest(<<2,1,3>>), 1537: ?line error = bptest(<<1>>), 1538: ?line error = bptest(<<>>), 1539: ?line error = bptest(apa), 1540: ?line 3 = bptest(<<2,3,3>>), 1541: % With one variable (pos) 1542: ?line 1 = bptest(<<1,2,3>>,1), 1543: ?line 2 = bptest(<<2,1,3>>,1), 1544: ?line error = bptest(<<1>>,1), 1545: ?line error = bptest(<<>>,1), 1546: ?line error = bptest(apa,1), 1547: ?line 3 = bptest(<<2,3,3>>,1), 1548: % With one variable (length) 1549: ?line 1 = bptesty(<<1,2,3>>,1), 1550: ?line 2 = bptesty(<<2,1,3>>,1), 1551: ?line error = bptesty(<<1>>,1), 1552: ?line error = bptesty(<<>>,1), 1553: ?line error = bptesty(apa,1), 1554: ?line 3 = bptesty(<<2,3,3>>,2), 1555: % With one variable (whole tuple) 1556: ?line 1 = bptestx(<<1,2,3>>,{1,1}), 1557: ?line 2 = bptestx(<<2,1,3>>,{1,1}), 1558: ?line error = bptestx(<<1>>,{1,1}), 1559: ?line error = bptestx(<<>>,{1,1}), 1560: ?line error = bptestx(apa,{1,1}), 1561: ?line 3 = bptestx(<<2,3,3>>,{1,2}), 1562: % With two variables 1563: ?line 1 = bptest(<<1,2,3>>,1,1), 1564: ?line 2 = bptest(<<2,1,3>>,1,1), 1565: ?line error = bptest(<<1>>,1,1), 1566: ?line error = bptest(<<>>,1,1), 1567: ?line error = bptest(apa,1,1), 1568: ?line 3 = bptest(<<2,3,3>>,1,2), 1569: % Direct (autoimported) call, these will be evaluated by the compiler... 1570: ?line <<2>> = binary_part(<<1,2,3>>,1,1), 1571: ?line <<1>> = binary_part(<<2,1,3>>,1,1), 1572: % Compiler warnings due to constant evaluation expected (3) 1573: ?line badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)), 1574: ?line badarg = ?MASK_ERROR(binary_part(<<>>,1,1)), 1575: ?line badarg = ?MASK_ERROR(binary_part(apa,1,1)), 1576: ?line <<3,3>> = binary_part(<<2,3,3>>,1,2), 1577: % Direct call through apply 1578: ?line <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]), 1579: ?line <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]), 1580: % Compiler warnings due to constant evaluation expected (3) 1581: ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])), 1582: ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])), 1583: ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])), 1584: ?line <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]), 1585: % Constant propagation 1586: ?line Bin = <<1,2,3>>, 1587: ?line ok = if 1588: binary_part(Bin,1,1) =:= <<2>> -> 1589: ok; 1590: %% Compiler warning, clause cannot match (expected) 1591: true -> 1592: error 1593: end, 1594: ?line ok = if 1595: binary_part(Bin,{1,1}) =:= <<2>> -> 1596: ok; 1597: %% Compiler warning, clause cannot match (expected) 1598: true -> 1599: error 1600: end, 1601: ok. 1602: 1603: 1604: bptest(B) when length(B) =:= 1337 -> 1605: 1; 1606: bptest(B) when binary_part(B,{1,1}) =:= <<2>> -> 1607: 1; 1608: bptest(B) when erlang:binary_part(B,1,1) =:= <<1>> -> 1609: 2; 1610: bptest(B) when erlang:binary_part(B,{1,2}) =:= <<3,3>> -> 1611: 3; 1612: bptest(_) -> 1613: error. 1614: 1615: bptest(B,A) when length(B) =:= A -> 1616: 1; 1617: bptest(B,A) when binary_part(B,{A,1}) =:= <<2>> -> 1618: 1; 1619: bptest(B,A) when erlang:binary_part(B,A,1) =:= <<1>> -> 1620: 2; 1621: bptest(B,A) when erlang:binary_part(B,{A,2}) =:= <<3,3>> -> 1622: 3; 1623: bptest(_,_) -> 1624: error. 1625: 1626: bptestx(B,A) when length(B) =:= A -> 1627: 1; 1628: bptestx(B,A) when binary_part(B,A) =:= <<2>> -> 1629: 1; 1630: bptestx(B,A) when erlang:binary_part(B,A) =:= <<1>> -> 1631: 2; 1632: bptestx(B,A) when erlang:binary_part(B,A) =:= <<3,3>> -> 1633: 3; 1634: bptestx(_,_) -> 1635: error. 1636: 1637: bptesty(B,A) when length(B) =:= A -> 1638: 1; 1639: bptesty(B,A) when binary_part(B,{1,A}) =:= <<2>> -> 1640: 1; 1641: bptesty(B,A) when erlang:binary_part(B,1,A) =:= <<1>> -> 1642: 2; 1643: bptesty(B,A) when erlang:binary_part(B,{1,A}) =:= <<3,3>> -> 1644: 3; 1645: bptesty(_,_) -> 1646: error. 1647: 1648: bptest(B,A,_C) when length(B) =:= A -> 1649: 1; 1650: bptest(B,A,C) when binary_part(B,{A,C}) =:= <<2>> -> 1651: 1; 1652: bptest(B,A,C) when erlang:binary_part(B,A,C) =:= <<1>> -> 1653: 2; 1654: bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> -> 1655: 3; 1656: bptest(_,_,_) -> 1657: error. 1658: 1659: -define(FAILING(C), 1660: if 1661: C -> ?t:fail(should_fail); 1662: true -> ok 1663: end, 1664: if 1665: true, C -> ?t:fail(should_fail); 1666: true -> ok 1667: end). 1668: 1669: bad_constants(Config) when is_list(Config) -> 1670: ?line ?FAILING(false), 1671: ?line ?FAILING([]), 1672: ?line ?FAILING([a]), 1673: ?line ?FAILING([Config]), 1674: ?line ?FAILING({a,b}), 1675: ?line ?FAILING({a,Config}), 1676: ?line ?FAILING(<<1>>), 1677: ?line ?FAILING(42), 1678: ?line ?FAILING(3.14), 1679: ok. 1680: 1681: %% Call this function to turn off constant propagation. 1682: id(I) -> I. 1683: 1684: check(F, Result) -> 1685: case F() of 1686: Result -> ok; 1687: Other -> 1688: io:format("Expected: ~p\n", [Result]), 1689: io:format(" Got: ~p\n", [Other]), 1690: test_server:fail() 1691: end. 1692: 1693: fc({'EXIT',{function_clause,_}}) -> ok.