1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2001-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: -module(lc_SUITE). 21: 22: %% Copied from lc_SUITE in the compiler application. 23: 24: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 25: init_per_testcase/2,end_per_testcase/2, 26: init_per_suite/1,end_per_suite/1, 27: basic/1,deeply_nested/1,no_generator/1, 28: empty_generator/1]). 29: 30: -include_lib("test_server/include/test_server.hrl"). 31: 32: suite() -> [{ct_hooks,[ts_install_cth]}]. 33: 34: all() -> 35: [basic, deeply_nested, no_generator, empty_generator]. 36: 37: groups() -> 38: []. 39: 40: init_per_group(_GroupName, Config) -> 41: Config. 42: 43: end_per_group(_GroupName, Config) -> 44: Config. 45: 46: init_per_testcase(_Case, Config) -> 47: test_lib:interpret(?MODULE), 48: 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: basic(Config) when is_list(Config) -> 65: ?line L0 = lists:seq(1, 10), 66: ?line L1 = my_map(fun(X) -> {x,X} end, L0), 67: ?line L1 = [{x,X} || X <- L0], 68: ?line L0 = my_map(fun({x,X}) -> X end, L1), 69: ?line [1,2,3,4,5] = [X || X <- L0, X < 6], 70: ?line [4,5,6] = [X || X <- L0, X > 3, X < 7], 71: ?line [] = [X || X <- L0, X > 32, X < 7], 72: ?line [1,3,5,7,9] = [X || X <- L0, odd(X)], 73: ?line [2,4,6,8,10] = [X || X <- L0, not odd(X)], 74: ?line [1,3,5,9] = [X || X <- L0, odd(X), X =/= 7], 75: ?line [2,4,8,10] = [X || X <- L0, not odd(X), X =/= 6], 76: 77: %% Append is specially handled. 78: ?line [1,3,5,9,2,4,8,10] = [X || X <- L0, odd(X), X =/= 7] ++ 79: [X || X <- L0, not odd(X), X =/= 6], 80: 81: %% Guards BIFs are evaluated in guard context. Weird, but true. 82: ?line [{a,b,true},{x,y,true,true}] = [X || X <- tuple_list(), element(3, X)], 83: 84: %% Filter expressions with andalso/orelse. 85: ?line "abc123" = alphanum("?abc123.;"), 86: 87: %% Error cases. 88: ?line [] = [{xx,X} || X <- L0, element(2, X) == no_no_no], 89: ?line {'EXIT',_} = (catch [X || X <- L1, list_to_atom(X) == dum]), 90: ?line [] = [X || X <- L1, X+1 < 2], 91: ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]), 92: 93: %% A bad generator has a different exception compared to BEAM. 94: ?line {'EXIT',{{bad_generator,x},_}} = (catch [E || E <- id(x)]), 95: ok. 96: 97: tuple_list() -> 98: [{a,b,true},[a,b,c],glurf,{a,b,false,xx},{a,b},{x,y,true,true},{a,b,d,ddd}]. 99: 100: my_map(F, L) -> 101: [F(X) || X <- L]. 102: 103: odd(X) -> 104: X rem 2 == 1. 105: 106: alphanum(Str) -> 107: [C || C <- Str, ((C >= $0) andalso (C =< $9)) 108: orelse ((C >= $a) andalso (C =< $z)) 109: orelse ((C >= $A) andalso (C =< $Z))]. 110: 111: deeply_nested(Config) when is_list(Config) -> 112: [[99,98,97,96,42,17,1764,12,11,10,9,8,7,6,5,4,3,7,2,1]] = deeply_nested_1(), 113: ok. 114: 115: deeply_nested_1() -> 116: %% This used to compile really, really SLOW before R11B-1... 117: [[X1,X2,X3,X4,X5,X6,X7(),X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18(),X19,X20] || 118: X1 <- [99],X2 <- [98],X3 <- [97],X4 <- [96],X5 <- [42],X6 <- [17], 119: X7 <- [fun() -> X5*X5 end],X8 <- [12],X9 <- [11],X10 <- [10], 120: X11 <- [9],X12 <- [8],X13 <- [7],X14 <- [6],X15 <- [5], 121: X16 <- [4],X17 <- [3],X18 <- [fun() -> X16+X17 end],X19 <- [2],X20 <- [1]]. 122: 123: no_generator(Config) when is_list(Config) -> 124: ?line Seq = lists:seq(-10, 17), 125: ?line [no_gen_verify(no_gen(A, B), A, B) || A <- Seq, B <- Seq], 126: 127: %% Literal expression, for coverage. 128: ?line [a] = [a || true], 129: ?line [a,b,c] = [a || true] ++ [b,c], 130: ok. 131: 132: no_gen(A, B) -> 133: [{A,B} || A+B =:= 0] ++ 134: [{A,B} || A*B =:= 0] ++ 135: [{A,B} || A rem B =:= 3] ++ 136: [{A,B} || A =:= B] ++ 137: [{one_more,A,B} || no_gen_one_more(A, B)] ++ 138: [A || A =:= 1] ++ 139: [A || A =:= 2] ++ 140: [A || A =:= 3] ++ 141: [A || A =:= 4] ++ 142: [A || A =:= 5] ++ 143: [A || A =:= 6] ++ 144: [A || A =:= 7] ++ 145: [A || A =:= 8] ++ 146: [A || A =:= 9] ++ 147: [B || B =:= 1] ++ 148: [B || B =:= 2] ++ 149: [B || B =:= 3] ++ 150: [B || B =:= 4] ++ 151: [B || B =:= 5] ++ 152: [B || B =:= 6] ++ 153: [B || B =:= 7] ++ 154: [B || B =:= 8] ++ 155: [B || B =:= 9]. 156: 157: no_gen_verify(Res, A, B) -> 158: Pair = {A,B}, 159: ShouldBe = no_gen_eval(fun() -> A+B =:= 0 end, Pair) ++ 160: no_gen_eval(fun() -> A*B =:= 0 end, Pair) ++ 161: no_gen_eval(fun() -> B =/= 0 andalso A rem B =:= 3 end, Pair) ++ 162: no_gen_eval(fun() -> A =:= B end, Pair) ++ 163: no_gen_eval(fun() -> A + 1 =:= B end, {one_more,A,B}) ++ 164: no_gen_eval(fun() -> 1 =< A andalso A =< 9 end, A) ++ 165: no_gen_eval(fun() -> 1 =< B andalso B =< 9 end, B), 166: case Res of 167: ShouldBe -> ok; 168: _ -> 169: io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]), 170: ?t:fail() 171: end. 172: 173: no_gen_eval(Fun, Res) -> 174: case Fun() of 175: true -> [Res]; 176: false -> [] 177: end. 178: 179: no_gen_one_more(A, B) -> A + 1 =:= B. 180: 181: empty_generator(Config) when is_list(Config) -> 182: ?line [] = [X || {X} <- [], (false or (X/0 > 3))], 183: ok. 184: 185: id(I) -> I.