diff options
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/Makefile | 2 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/compiler/test/core_SUITE.erl | 5 | ||||
-rw-r--r-- | lib/compiler/test/core_SUITE_data/eval_case.core | 34 | ||||
-rw-r--r-- | lib/compiler/test/error_SUITE.erl | 19 | ||||
-rw-r--r-- | lib/compiler/test/map_SUITE.erl | 93 |
6 files changed, 142 insertions, 19 deletions
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index 0a637a07cd..0b56a49cd6 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -48,6 +48,7 @@ NO_OPT= \ fun \ guard \ lc \ + map \ match \ misc \ num_bif \ @@ -68,6 +69,7 @@ INLINE= \ fun \ guard \ lc \ + map \ match \ misc \ num_bif \ diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 34c4b1e264..8cb7d1b55b 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -24,7 +24,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - app_test/1, + app_test/1,appup_test/1, file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1, binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, other_output/1, encrypted_abstr/1, @@ -42,7 +42,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), - [app_test, file_1, forms_2, module_mismatch, big_file, outdir, + [app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir, binary, makedep, cond_and_ifdef, listings, listings_big, other_output, encrypted_abstr, {group, bad_record_use}, strict_record, @@ -71,6 +71,10 @@ end_per_group(_GroupName, Config) -> app_test(Config) when is_list(Config) -> ?line ?t:app_test(compiler). +%% Test that the Application upgrade file has no `basic' errors."; +appup_test(Config) when is_list(Config) -> + ok = ?t:appup_test(compiler). + %% Tests that we can compile and run a simple Erlang program, %% using compile:file/1. diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index 1a521c3591..aa222c48de 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -24,7 +24,7 @@ dehydrated_itracer/1,nested_tries/1, seq_in_guard/1,make_effect_seq/1,eval_is_boolean/1, unsafe_case/1,nomatch_shadow/1,reversed_annos/1, - map_core_test/1]). + map_core_test/1,eval_case/1]). -include_lib("test_server/include/test_server.hrl"). @@ -50,7 +50,7 @@ groups() -> [{p,test_lib:parallel(), [dehydrated_itracer,nested_tries,seq_in_guard,make_effect_seq, eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos, - map_core_test + map_core_test,eval_case ]}]. @@ -76,6 +76,7 @@ end_per_group(_GroupName, Config) -> ?comp(nomatch_shadow). ?comp(reversed_annos). ?comp(map_core_test). +?comp(eval_case). try_it(Mod, Conf) -> Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)), diff --git a/lib/compiler/test/core_SUITE_data/eval_case.core b/lib/compiler/test/core_SUITE_data/eval_case.core new file mode 100644 index 0000000000..f2776e2b1f --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/eval_case.core @@ -0,0 +1,34 @@ +module 'eval_case' ['eval_case'/0] + attributes [] +'eval_case'/0 = + fun () -> + case <> of + <> when 'true' -> + case apply 'do_case'/0() of + <'ok'> when 'true' -> + 'ok' + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'eval_case',0}}] ) + -| ['compiler_generated'] ) + end +'do_case'/0 = + fun () -> + case let <_cor0> = + apply 'id'/1(42) + in let <_cor1> = + call 'erlang':'+' + (_cor0, 7) + in {'x',_cor1} of + <{'x',49}> when 'true' -> + 'ok' + end +'id'/1 = + fun (_cor0) -> _cor0 +end diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl index 859c4571ea..5cdf429a5f 100644 --- a/lib/compiler/test/error_SUITE.erl +++ b/lib/compiler/test/error_SUITE.erl @@ -23,7 +23,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, head_mismatch_line/1,warnings_as_errors/1, bif_clashes/1, - transforms/1]). + transforms/1,forbidden_maps/1]). %% Used by transforms/1 test case. -export([parse_transform/2]). @@ -36,7 +36,7 @@ all() -> groups() -> [{p,test_lib:parallel(), - [head_mismatch_line,warnings_as_errors,bif_clashes,transforms]}]. + [head_mismatch_line,warnings_as_errors,bif_clashes,transforms,forbidden_maps]}]. init_per_suite(Config) -> Config. @@ -240,6 +240,21 @@ parse_transform(_, _) -> error(too_bad). +forbidden_maps(Config) when is_list(Config) -> + Ts1 = [{map_illegal_use_of_pattern, + <<" + -export([t/0]). + t() -> + V = 32, + #{<<\"hi\",V,\"all\">> := 1} = id(#{<<\"hi all\">> => 1}). + id(I) -> I. + ">>, + [return], + {error,[{5,erl_lint,{illegal_map_key_variable,'V'}}], []}}], + [] = run2(Config, Ts1), + ok. + + run(Config, Tests) -> ?line File = test_filename(Config), run(Tests, File, dont_write_beam). diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index dc880a7a9d..b4baef461b 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -30,6 +30,7 @@ t_list_comprehension/1, t_map_sort_literals/1, t_map_size/1, + t_build_and_match_aliasing/1, %% warnings t_warn_useless_build/1, @@ -38,10 +39,10 @@ %% not covered in 17.0-rc1 t_build_and_match_over_alloc/1, t_build_and_match_empty_val/1, - t_build_and_match_val/1 + t_build_and_match_val/1, %% errors in 17.0-rc1 - + t_update_values/1 ]). suite() -> []. @@ -54,6 +55,8 @@ all() -> [ t_guard_bifs, t_guard_sequence, t_guard_update, t_guard_receive,t_guard_fun, t_list_comprehension, t_map_sort_literals, + t_map_size, + t_build_and_match_aliasing, %% warnings t_warn_useless_build, @@ -62,10 +65,10 @@ all() -> [ %% not covered in 17.0-rc1 t_build_and_match_over_alloc, t_build_and_match_empty_val, - t_build_and_match_val + t_build_and_match_val, %% errors in 17.0-rc1 - + t_update_values ]. groups() -> []. @@ -103,8 +106,6 @@ t_build_and_match_literals(Config) when is_list(Config) -> id(#{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first}), %% error case - %V = 32, - %{'EXIT',{{badmatch,_},_}} = (catch (#{<<"hi all">> => 1} = id(#{<<"hi",V,"all">> => 1}))), {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3,x:=2} = id(#{x=>3}))), {'EXIT',{{badmatch,_},_}} = (catch (#{x:=2} = id(#{x=>3}))), {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id({a,b,c}))), @@ -112,6 +113,20 @@ t_build_and_match_literals(Config) when is_list(Config) -> {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{x=>"three"}))), ok. +t_build_and_match_aliasing(Config) when is_list(Config) -> + M1 = id(#{a=>1,b=>2,c=>3,d=>4}), + #{c:=C1=_=_=C2} = M1, + true = C1 =:= C2, + #{a:=A,a:=A,a:=A,b:=B,b:=B} = M1, + #{a:=A,a:=A,a:=A,b:=B,b:=B,b:=2} = M1, + #{a:=A=1,a:=A,a:=A,b:=B=2,b:=B,b:=2} = M1, + #{c:=C1, c:=_, c:=3, c:=_, c:=C2} = M1, + #{c:=C=_=3=_=C} = M1, + + M2 = id(#{"a"=>1,"b"=>2,"c"=>3,"d"=>4}), + #{"a":=A2,"a":=A2,"a":=A2,"b":=B2,"b":=B2,"b":=2} = M2, + #{"a":=_,"a":=_,"a":=_,"b":=_,"b":=_,"b":=2} = M2, + ok. t_map_size(Config) when is_list(Config) -> 0 = map_size(id(#{})), @@ -179,6 +194,17 @@ t_update_map_expressions(Config) when is_list(Config) -> #{ a :=42, b:=42, c:=42 } = (maps:from_list([{a,1},{b,2},{c,3}]))#{ a := 42, b := 42, c := 42 }, #{ "a" :=1, "b":=42, "c":=42 } = (maps:from_list([{"a",1},{"b",2}]))#{ "b" := 42, "c" => 42 }, + %% Test need to be in a fun. + %% This tests that let expr optimisation in sys_core_fold + %% covers maps correctly. + F = fun() -> + M0 = id(#{ "a" => [1,2,3] }), + #{ "a" := _ } = M0, + M0#{ "a" := b } + end, + + #{ "a" := b } = F(), + %% Error cases, FIXME: should be 'badmap'? {'EXIT',{badarg,_}} = (catch (id(<<>>))#{ a := 42, b => 2 }), {'EXIT',{badarg,_}} = (catch (id([]))#{ a := 42, b => 2 }), @@ -212,7 +238,14 @@ t_update_exact(Config) when is_list(Config) -> M2 = M0#{3.0:=new}, #{1:=a,2:=b,3.0:=new,4:=d,5:=e} = M2, M2 = M0#{3.0=>wrong,3.0:=new}, - M2 = M0#{3=>wrong,3.0:=new}, + true = M2 =/= M0#{3=>right,3.0:=new}, + #{ 3 := right, 3.0 := new } = M0#{3=>right,3.0:=new}, + + M3 = id(#{ 1 => val}), + #{1 := update2,1.0 := new_val4} = M3#{ + 1.0 => new_val1, 1 := update, 1=> update3, + 1 := update2, 1.0 := new_val2, 1.0 => new_val3, + 1.0 => new_val4 }, %% Errors cases. {'EXIT',{badarg,_}} = (catch ((id(nil))#{ a := b })), @@ -220,9 +253,31 @@ t_update_exact(Config) when is_list(Config) -> {'EXIT',{badarg,_}} = (catch M0#{1.0:=v,1.0=>v2}), {'EXIT',{badarg,_}} = (catch M0#{42.0:=v,42:=v2}), {'EXIT',{badarg,_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}), + ok. +t_update_values(Config) when is_list(Config) -> + V0 = id(1337), + M0 = #{ a => 1, val => V0}, + V1 = get_val(M0), + M1 = M0#{ val := [V0,V1], "wazzup" => 42 }, + [1337, {some_val, 1337}] = get_val(M1), + + N = 110, + List = [{[I,1,2,3,I],{1,2,3,"wat",I}}|| I <- lists:seq(1,N)], + + {_,_,#{val2 := {1,2,3,"wat",N}, val1 := [N,1,2,3,N]}} = lists:foldl(fun + ({V2,V3},{Old2,Old3,Mi}) -> + ok = check_val(Mi,Old2,Old3), + #{ val1 := Old2, val2 := Old3 } = Mi, + {V2,V3, Mi#{ val1 := id(V2), val2 := V1, val2 => id(V3)}} + end, {none, none, #{val1=>none,val2=>none}},List), ok. +check_val(#{val1:=V1, val2:=V2},V1,V2) -> ok. + +get_val(#{ "wazzup" := _, val := V}) -> V; +get_val(#{ val := V }) -> {some_val, V}. + t_guard_bifs(Config) when is_list(Config) -> true = map_guard_head(#{a=>1}), false = map_guard_head([]), @@ -363,8 +418,12 @@ t_guard_fun(Config) when is_list(Config) -> {l,V} = F2(#{s=>l,v=>[V,V]}), %% error case - {'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} = (catch F1(#{s=>none,v=>none})), - ok. + case (catch F1(#{s=>none,v=>none})) of + {'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} -> ok; + {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; + Other -> + test_server:fail({no_match, Other}) + end. t_map_sort_literals(Config) when is_list(Config) -> @@ -445,8 +504,12 @@ t_build_and_match_empty_val(Config) when is_list(Config) -> ok = F(id(#{"hi"=>ok,{1,2}=>ok,1337=>ok})), %% error case - {'EXIT',{function_clause,_}} = (catch (F(id(#{"hi"=>ok})))), - ok. + case (catch (F(id(#{"hi"=>ok})))) of + {'EXIT',{function_clause,_}} -> ok; + {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; + Other -> + test_server:fail({no_match, Other}) + end. t_build_and_match_val(Config) when is_list(Config) -> F = fun @@ -459,8 +522,12 @@ t_build_and_match_val(Config) when is_list(Config) -> {2,"second"} = F(id(#{"hi"=>second,v=>"second"})), %% error case - {'EXIT',{function_clause,_}} = (catch (F(id(#{"hi"=>ok})))), - ok. + case (catch (F(id(#{"hi"=>ok})))) of + {'EXIT',{function_clause,_}} -> ok; + {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; + Other -> + test_server:fail({no_match, Other}) + end. %% Use this function to avoid compile-time evaluation of an expression. |