diff options
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 64 | ||||
-rw-r--r-- | lib/compiler/test/beam_utils_SUITE.erl | 17 | ||||
-rw-r--r-- | lib/compiler/test/bs_match_SUITE.erl | 38 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 34 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE_data/deterministic_module.erl | 21 | ||||
-rw-r--r-- | lib/compiler/test/core_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/compiler/test/core_SUITE_data/non_variable_apply.core | 80 |
7 files changed, 253 insertions, 9 deletions
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 86146c614f..d44fa60997 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -22,7 +22,8 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, integers/1,coverage/1,booleans/1,setelement/1,cons/1, - tuple/1,record_float/1,binary_float/1,float_compare/1]). + tuple/1,record_float/1,binary_float/1,float_compare/1, + arity_checks/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -40,7 +41,8 @@ groups() -> tuple, record_float, binary_float, - float_compare + float_compare, + arity_checks ]}]. init_per_suite(Config) -> @@ -64,6 +66,15 @@ integers(_Config) -> college = do_integers_3(), + zero = do_integers_4(<<0:1>>, 0), + one = do_integers_4(<<1:1>>, 0), + other = do_integers_4(<<1:1>>, 2), + + zero = do_integers_5(0, 0), + one = do_integers_5(0, 1), + two = do_integers_5(0, 2), + three = do_integers_5(0, 3), + ok. do_integers_1(B0) -> @@ -86,6 +97,30 @@ do_integers_3() -> 1 -> 0 end. +do_integers_4(<<X:1,T/bits>>, C) -> + %% Binary matching gives the range 0-1 for X. + %% The range for `X bor C` is unknown. It must not be inherited + %% from X. (`X bor C` will reuse the register used for X.) + case X bor C of + 0 -> do_integers_4(T, C, zero); + 1 -> do_integers_4(T, C, one); + _ -> do_integers_4(T, C, other) + end. + +do_integers_4(_, _, Res) -> + Res. + +do_integers_5(X0, Y0) -> + %% X and Y will use the same register. + X = X0 band 1, + Y = Y0 band 3, + case Y of + 0 -> zero; + 1 -> one; + 2 -> two; + 3 -> three + end. + coverage(_Config) -> {'EXIT',{badarith,_}} = (catch id(1) bsl 0.5), {'EXIT',{badarith,_}} = (catch id(2.0) bsl 2), @@ -171,6 +206,31 @@ do_float_compare(X) -> _T -> Y > 0 end. +arity_checks(_Config) -> + %% ERL-549: an unsafe optimization removed a test_arity instruction, + %% causing the following to return 'broken' instead of 'ok'. + ok = do_record_arity_check({rgb, 255, 255, 255, 1}), + ok = do_tuple_arity_check({255, 255, 255, 1}). + +-record(rgb, {r = 255, g = 255, b = 255}). + +do_record_arity_check(RGB) when + (element(2, RGB) >= 0), (element(2, RGB) =< 255), + (element(3, RGB) >= 0), (element(3, RGB) =< 255), + (element(4, RGB) >= 0), (element(4, RGB) =< 255) -> + if + element(1, RGB) =:= rgb, is_record(RGB, rgb) -> broken; + true -> ok + end. + +do_tuple_arity_check(RGB) when is_tuple(RGB), + (element(1, RGB) >= 0), (element(1, RGB) =< 255), + (element(2, RGB) >= 0), (element(2, RGB) =< 255), + (element(3, RGB) >= 0), (element(3, RGB) =< 255) -> + case RGB of + {255, _, _} -> broken; + _ -> ok + end. id(I) -> I. diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl index a3f1bb93fe..710cb050d4 100644 --- a/lib/compiler/test/beam_utils_SUITE.erl +++ b/lib/compiler/test/beam_utils_SUITE.erl @@ -260,6 +260,14 @@ otp_8949_b(A, B) -> liveopt(_Config) -> F = liveopt_fun(42, pebkac, user), void = F(42, #alarmInfo{type=sctp,cause=pebkac,origin=user}), + + + A = {#alarmInfo{cause = {abc, def}}, ghi}, + A = liveopt_guard_bif(A), + + B = {#alarmInfo{cause = {abc}}, def}, + {#alarmInfo{cause = {{abc}}}, def} = liveopt_guard_bif(B), + ok. liveopt_fun(Peer, Cause, Origin) -> @@ -271,6 +279,15 @@ liveopt_fun(Peer, Cause, Origin) -> void end. +liveopt_guard_bif({#alarmInfo{cause=F}=R, X}=A) -> + %% ERIERL-48 + if + is_tuple(F), tuple_size(F) == 2 -> A; + true -> + R2 = R#alarmInfo{cause={F}}, + {R2,X} + end. + %% Thanks to QuickCheck. coverage(_Config) -> 42+7 = merchant([[],7,false]), diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 0ec05456ec..2fe8cd0cff 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -39,7 +39,7 @@ match_string_opt/1,select_on_integer/1, map_and_binary/1,unsafe_branch_caching/1, bad_literals/1,good_literals/1,constant_propagation/1, - parse_xml/1,get_payload/1]). + parse_xml/1,get_payload/1,num_slots_different/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -71,7 +71,7 @@ groups() -> match_string_opt,select_on_integer, map_and_binary,unsafe_branch_caching, bad_literals,good_literals,constant_propagation,parse_xml, - get_payload]}]. + get_payload,num_slots_different]}]. init_per_suite(Config) -> @@ -1524,6 +1524,40 @@ do_get_payload(ExtHdr) -> <<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts, ExtHdrOptions. +%% ERL-490 +num_slots_different(_Config) -> + Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>}, + {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>}, + {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>}, + {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}], + _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts], + + {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)), + ok. + + +lgettext(<<"de">>, <<"default">>, <<"Remove">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Results">>) -> + {ok, <<"Ergebnisse">>}; +lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"navigation">>, <<"Results">>) -> + {ok, <<"Ergebnisse">>}; +lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) -> + {ok, <<"Ressourcen">>}. + + check(F, R) -> R = F(). diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index f647a4030d..c455afcb48 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -36,7 +36,7 @@ core_roundtrip/1, asm/1, optimized_guards/1, sys_pre_attributes/1, dialyzer/1, warnings/1, pre_load_check/1, env_compiler_options/1, - bc_options/1 + bc_options/1, deterministic_include/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -53,7 +53,8 @@ all() -> strict_record, utf8_atoms, utf8_functions, extra_chunks, cover, env, core_pp, core_roundtrip, asm, optimized_guards, sys_pre_attributes, dialyzer, warnings, pre_load_check, - env_compiler_options, custom_debug_info, bc_options]. + env_compiler_options, custom_debug_info, bc_options, + deterministic_include]. groups() -> []. @@ -119,9 +120,19 @@ file_1(Config) when is_list(Config) -> true = exists(Target), passed = run(Target, test, []), + %% Test option 'deterministic' as a compiler attribute. + Det = deterministic_module, + {DetPath, DetTarget} = get_files(Config, Det, "det_target"), + {ok,Det,DetCode} = compile:file(DetPath, [binary]), + {module,Det} = code:load_binary(Det, "", DetCode), + [{version,_}] = Det:module_info(compile), + true = code:delete(Det), + false = code:purge(Det), + %% Cleanup. ok = file:delete(Target), ok = file:del_dir(filename:dirname(Target)), + ok = file:del_dir(filename:dirname(DetTarget)), %% There should not be any messages in the messages. receive @@ -398,6 +409,7 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> ok = file:delete(filename:join(Listings, File ++ ".core")), do_listing(Simple, TargetDir, to_core, ".core"), do_listing(Simple, TargetDir, to_kernel, ".kernel"), + do_listing(Simple, TargetDir, to_dis, ".dis"), %% Final clean up. lists:foreach(fun(F) -> ok = file:delete(F) end, @@ -413,6 +425,7 @@ listings_big(Config) when is_list(Config) -> do_listing(Big, TargetDir, 'E'), do_listing(Big, TargetDir, 'P'), do_listing(Big, TargetDir, dkern, ".kernel"), + do_listing(Big, TargetDir, to_dis, ".dis"), TargetNoext = filename:rootname(Target, code:objfile_extension()), {ok,big} = compile:file(TargetNoext, [from_asm,{outdir,TargetDir}]), @@ -1433,6 +1446,23 @@ highest_opcode(DataDir, Mod, Opt) -> <<16:32,0:32,HighestOpcode:32,_/binary>> = Code, HighestOpcode. +deterministic_include(Config) when is_list(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Simple = filename:join(DataDir, "simple"), + + %% Files without +deterministic should differ if their include paths do, + %% as their debug info will be different. + {ok,_,NonDetA} = compile:file(Simple, [binary, {i,"gurka"}]), + {ok,_,NonDetB} = compile:file(Simple, [binary, {i,"gaffel"}]), + true = NonDetA =/= NonDetB, + + %% ... but files with +deterministic shouldn't. + {ok,_,DetC} = compile:file(Simple, [binary, deterministic, {i,"gurka"}]), + {ok,_,DetD} = compile:file(Simple, [binary, deterministic, {i,"gaffel"}]), + true = DetC =:= DetD, + + ok. + %%% %%% Utilities. %%% diff --git a/lib/compiler/test/compile_SUITE_data/deterministic_module.erl b/lib/compiler/test/compile_SUITE_data/deterministic_module.erl new file mode 100644 index 0000000000..5e0e29c25e --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/deterministic_module.erl @@ -0,0 +1,21 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(deterministic_module). +-compile([deterministic]). diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index f8839da42f..0e07e8dd2e 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -28,7 +28,8 @@ map_core_test/1,eval_case/1,bad_boolean_guard/1, bs_shadowed_size_var/1, cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1, - cover_v3_kernel_4/1,cover_v3_kernel_5/1]). + cover_v3_kernel_4/1,cover_v3_kernel_5/1, + non_variable_apply/1]). -include_lib("common_test/include/ct.hrl"). @@ -56,7 +57,8 @@ groups() -> map_core_test,eval_case,bad_boolean_guard, bs_shadowed_size_var, cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3, - cover_v3_kernel_4,cover_v3_kernel_5 + cover_v3_kernel_4,cover_v3_kernel_5, + non_variable_apply ]}]. @@ -90,7 +92,7 @@ end_per_group(_GroupName, Config) -> ?comp(cover_v3_kernel_3). ?comp(cover_v3_kernel_4). ?comp(cover_v3_kernel_5). - +?comp(non_variable_apply). try_it(Mod, Conf) -> Src = filename:join(proplists:get_value(data_dir, Conf), diff --git a/lib/compiler/test/core_SUITE_data/non_variable_apply.core b/lib/compiler/test/core_SUITE_data/non_variable_apply.core new file mode 100644 index 0000000000..d9322cc455 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/non_variable_apply.core @@ -0,0 +1,80 @@ +module 'non_variable_apply' ['module_info'/0, + 'module_info'/1, + 'non_variable_apply'/0] + attributes [] + +'non_variable_apply'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + let <OkFun> = + fun (_@c0) -> + %% Line 5 + case _@c0 of + <'ok'> when 'true' -> + 'ok' + ( <_@c1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c1}) + -| [{'function_name',{'-non_variable_apply/0-fun-0-',1}}] ) + -| ['compiler_generated'] ) + end + in let <F> = + fun (_@c5,_@c4) -> + %% Line 6 + case <_@c5,_@c4> of + <F,X> when 'true' -> + apply apply 'id'/1 (F) (X) + ( <_@c7,_@c6> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c7,_@c6}) + -| [{'function_name',{'-non_variable_apply/0-fun-1-',2}}] ) + -| ['compiler_generated'] ) + end + in %% Line 9 + apply F + (OkFun, 'ok') + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'non_variable_apply',0}}] ) + -| ['compiler_generated'] ) + end +'id'/1 = + %% Line 11 + fun (_@c0) -> + case _@c0 of + <I> when 'true' -> + I + ( <_@c1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c1}) + -| [{'function_name',{'id',1}}] ) + -| ['compiler_generated'] ) + end +'module_info'/0 = + fun () -> + case <> of + <> when 'true' -> + call 'erlang':'get_module_info' + ('non_variable_apply') + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'module_info',0}}] ) + -| ['compiler_generated'] ) + end +'module_info'/1 = + fun (_@c0) -> + case _@c0 of + <X> when 'true' -> + call 'erlang':'get_module_info' + ('non_variable_apply', X) + ( <_@c1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_@c1}) + -| [{'function_name',{'module_info',1}}] ) + -| ['compiler_generated'] ) + end +end |