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.