1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2006-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(andor_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: 	 t_andalso/1,t_orelse/1,inside/1,overlap/1,
   27: 	 combined/1,in_case/1]).
   28: 
   29: -include_lib("test_server/include/test_server.hrl").
   30: 
   31: suite() -> [{ct_hooks,[ts_install_cth]}].
   32: 
   33: all() -> 
   34:     cases().
   35: 
   36: groups() -> 
   37:     [].
   38: 
   39: init_per_group(_GroupName, Config) ->
   40:     Config.
   41: 
   42: end_per_group(_GroupName, Config) ->
   43:     Config.
   44: 
   45: 
   46: init_per_testcase(_Case, Config) ->
   47:     test_lib:interpret(?MODULE),
   48:     ?line Dog = test_server:timetrap(?t:minutes(1)),
   49:     [{watchdog,Dog}|Config].
   50: 
   51: end_per_testcase(_Case, Config) ->
   52:     Dog = ?config(watchdog, Config),
   53:     ?t:timetrap_cancel(Dog),
   54:     ok.
   55: 
   56: init_per_suite(Config) when is_list(Config) ->
   57:     ?line test_lib:interpret(?MODULE),
   58:     ?line true = lists:member(?MODULE, int:interpreted()),
   59:     Config.
   60: 
   61: end_per_suite(Config) when is_list(Config) ->
   62:     ok.
   63: 
   64: cases() -> 
   65:     [t_andalso, t_orelse, inside, overlap, combined,
   66:      in_case].
   67: 
   68: t_andalso(Config) when is_list(Config) ->
   69:     Bs = [true,false],
   70:     Ps = [{X,Y} || X <- Bs, Y <- Bs],
   71:     lists:foreach(fun (P) -> t_andalso_1(P) end, Ps),
   72: 
   73:     ?line true = true andalso true,
   74:     ?line false = true andalso false,
   75:     ?line false = false andalso true,
   76:     ?line false = false andalso false,
   77: 
   78:     ?line false = false andalso glurf,
   79:     ?line false = false andalso exit(exit_now),
   80: 
   81:     ?line true = not id(false) andalso not id(false),
   82:     ?line false = not id(false) andalso not id(true),
   83:     ?line false = not id(true) andalso not id(false),
   84:     ?line false = not id(true) andalso not id(true),
   85: 
   86:     ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)),
   87:     ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)),
   88:     ?line false = id(false) andalso not id(glurf),
   89:     ?line false = false andalso not id(glurf),
   90: 
   91:     ok.
   92: 
   93: t_orelse(Config) when is_list(Config) ->
   94:     Bs = [true,false],
   95:     Ps = [{X,Y} || X <- Bs, Y <- Bs],
   96:     lists:foreach(fun (P) -> t_orelse_1(P) end, Ps),
   97: 
   98:     ?line true = true orelse true,
   99:     ?line true = true orelse false,
  100:     ?line true = false orelse true,
  101:     ?line false = false orelse false,
  102: 
  103:     ?line true = true orelse glurf,
  104:     ?line true = true orelse exit(exit_now),
  105: 
  106:     ?line true = not id(false) orelse not id(false),
  107:     ?line true = not id(false) orelse not id(true),
  108:     ?line true = not id(true) orelse not id(false),
  109:     ?line false = not id(true) orelse not id(true),
  110: 
  111:     ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)),
  112:     ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)),
  113:     ?line true = id(true) orelse not id(glurf),
  114:     ?line true = true orelse not id(glurf),
  115: 
  116:     ok.
  117: 
  118: t_andalso_1({X,Y}) ->
  119:     io:fwrite("~w andalso ~w: ",[X,Y]),
  120:     V1 = echo(X) andalso echo(Y),
  121:     V1 = if
  122: 	     X andalso Y -> true;
  123: 	     true -> false
  124: 	 end,
  125:     check(V1, X and Y).
  126: 
  127: t_orelse_1({X,Y}) ->
  128:     io:fwrite("~w orelse ~w: ",[X,Y]),
  129:     V1 = echo(X) orelse echo(Y),
  130:     V1 = if
  131: 	     X orelse Y -> true;
  132: 	     true -> false
  133: 	 end,
  134:     check(V1, X or Y).
  135: 
  136: inside(Config) when is_list(Config) ->
  137:     ?line true = inside(-8, 1),
  138:     ?line false = inside(-53.5, -879798),
  139:     ?line false = inside(1.0, -879),
  140:     ?line false = inside(59, -879),
  141:     ?line false = inside(-11, 1.0),
  142:     ?line false = inside(100, 0.2),
  143:     ?line false = inside(100, 1.2),
  144:     ?line false = inside(-53.5, 4),
  145:     ?line false = inside(1.0, 5.3),
  146:     ?line false = inside(59, 879),
  147:     ok.
  148: 
  149: inside(Xm, Ym) ->
  150:     X = -10.0,
  151:     Y = -2.0,
  152:     W = 20.0,
  153:     H = 4.0,
  154:     Res = inside(Xm, Ym, X, Y, W, H),
  155:     Res = if
  156: 	      X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H -> true;
  157: 	      true -> false
  158: 	  end,
  159:     case not id(Res) of
  160: 	Outside ->
  161: 	    Outside = if
  162: 			  not(X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H) -> true;
  163: 			  true -> false
  164: 		      end
  165:     end,
  166:     {Res,Xm,Ym,X,Y,W,H} = inside_guard(Xm, Ym, X, Y, W, H),
  167:     io:format("~p =< ~p andalso ~p < ~p andalso ~p =< ~p andalso ~p < ~p ==> ~p",
  168: 	      [X,Xm,Xm,X+W,Y,Ym,Ym,Y+H,Res]),
  169:     Res.
  170: 
  171: inside(Xm, Ym, X, Y, W, H) ->
  172:     X =< Xm andalso Xm < X+W andalso Y =< Ym andalso Ym < Y+H.
  173: 
  174: inside_guard(Xm, Ym, X, Y, W, H) when X =< Xm andalso Xm < X+W
  175: 				      andalso Y =< Ym andalso Ym < Y+H ->
  176:     {true,Xm,Ym,X,Y,W,H};
  177: inside_guard(Xm, Ym, X, Y, W, H) ->
  178:     {false,Xm,Ym,X,Y,W,H}.
  179: 
  180: overlap(Config) when is_list(Config) ->
  181:     ?line true = overlap(7.0, 2.0, 8.0, 0.5),
  182:     ?line true = overlap(7.0, 2.0, 8.0, 2.5),
  183:     ?line true = overlap(7.0, 2.0, 5.3, 2),
  184:     ?line true = overlap(7.0, 2.0, 0.0, 100.0),
  185: 
  186:     ?line false = overlap(-1, 2, -35, 0.5),
  187:     ?line false = overlap(-1, 2, 777, 0.5),
  188:     ?line false = overlap(-1, 2, 2, 10),
  189:     ?line false = overlap(2, 10, 12, 55.3),
  190:     ok.
  191: 
  192: overlap(Pos1, Len1, Pos2, Len2) ->
  193:     Res = case Pos1 of
  194: 	      Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
  195: 			orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) ->
  196: 		  true;
  197: 	      Pos1 -> false
  198: 	  end,
  199:     Res = (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
  200: 	orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1),
  201:     Res = case Pos1 of
  202: 	      Pos1 when (Pos2 =< Pos1 andalso Pos1 < Pos2+Len2)
  203: 			orelse (Pos1 =< Pos2 andalso Pos2 < Pos1+Len1) ->
  204: 		  true;
  205: 	      Pos1 -> false
  206: 	  end,
  207:     id(Res).
  208: 
  209: 
  210: -define(COMB(A,B,C), (A andalso B orelse C)).
  211: 
  212: combined(Config) when is_list(Config) ->
  213:     ?line false = comb(false, false, false),
  214:     ?line true = comb(false, false, true),
  215:     ?line false = comb(false, true, false),
  216:     ?line true = comb(false, true, true),
  217: 
  218:     ?line false = comb(true, false, false),
  219:     ?line true = comb(true, true, false),
  220:     ?line true = comb(true, false, true),
  221:     ?line true = comb(true, true, true),
  222: 
  223:     ?line false = comb(false, blurf, false),
  224:     ?line true = comb(false, blurf, true),
  225:     ?line true = comb(true, true, blurf),
  226: 
  227:     ?line false = ?COMB(false, false, false),
  228:     ?line true = ?COMB(false, false, true),
  229:     ?line false = ?COMB(false, true, false),
  230:     ?line true = ?COMB(false, true, true),
  231: 
  232:     ?line false = ?COMB(true, false, false),
  233:     ?line true = ?COMB(true, true, false),
  234:     ?line true = ?COMB(true, false, true),
  235:     ?line true = ?COMB(true, true, true),
  236: 
  237:     ?line false = ?COMB(false, blurf, false),
  238:     ?line true = ?COMB(false, blurf, true),
  239:     ?line true = ?COMB(true, true, blurf),
  240: 
  241:     ok.
  242: -undef(COMB).
  243: 
  244: comb(A, B, C) ->
  245:     Res = A andalso B orelse C,
  246:     Res = if
  247: 	      A andalso B orelse C -> true;
  248: 	      true -> false
  249: 	  end,
  250:     NotRes = if
  251: 		 not(A andalso B orelse C) -> true;
  252: 		 true -> false
  253: 	     end,
  254:     NotRes = id(not Res),
  255:     Res = A andalso B orelse C,
  256:     Res = if
  257: 	      A andalso B orelse C -> true;
  258: 	      true -> false
  259: 	  end,
  260:     NotRes = id(not Res),
  261:     Res = if
  262: 	      A andalso B orelse C -> true;
  263: 	      true -> false
  264: 	  end,
  265:     id(Res).
  266: 
  267: %% Test that a boolean expression in a case expression is properly
  268: %% optimized (in particular, that the error behaviour is correct).
  269: in_case(Config) when is_list(Config) ->
  270:     ?line edge_rings = in_case_1(1, 1, 1, 1, 1),
  271:     ?line not_loop = in_case_1(0.5, 1, 1, 1, 1),
  272:     ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4),
  273:     ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)),
  274:     ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)),
  275:     ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)),
  276:     ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)),
  277:     ok.
  278: 
  279: in_case_1(LenUp, LenDw, LenN, Rotation, Count) ->
  280:     Res = in_case_1_body(LenUp, LenDw, LenN, Rotation, Count),
  281:     Res = in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count),
  282:     Res.
  283: 
  284: in_case_1_body(LenUp, LenDw, LenN, Rotation, Count) ->
  285:     case (LenUp/Count > 0.707) and (LenN/Count > 0.707) and
  286: 	(abs(Rotation) > 0.707) of
  287: 	true ->
  288: 	    edge_rings;
  289: 	false ->
  290: 	    case (LenUp >= 1) or (LenDw >= 1) or
  291: 		(LenN =< 1) or (Count < 4) of
  292: 		true ->
  293: 		    not_loop;
  294: 		false ->
  295: 		    loop
  296: 	    end
  297:     end.
  298: 
  299: in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) ->
  300:     case (LenUp/Count > 0.707) andalso (LenN/Count > 0.707) andalso
  301: 	(abs(Rotation) > 0.707) of
  302: 	true -> edge_rings;
  303: 	false when LenUp >= 1 orelse LenDw >= 1 orelse
  304: 	LenN =< 1 orelse Count < 4 -> not_loop;
  305: 	false -> loop
  306:     end.
  307: 
  308: check(V1, V0) ->
  309:     if V1 /= V0 ->
  310: 	    io:fwrite("error: ~w.\n", [V1]),
  311: 	    ?t:fail();
  312:        true ->
  313: 	    io:fwrite("ok: ~w.\n", [V1])
  314:     end.
  315: 
  316: echo(X) ->
  317:     io:fwrite("eval(~w); ",[X]),
  318:     X.
  319: 
  320: id(I) -> I.