diff options
Diffstat (limited to 'erts/emulator/test/bif_SUITE.erl')
-rw-r--r-- | erts/emulator/test/bif_SUITE.erl | 223 |
1 files changed, 205 insertions, 18 deletions
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index 69e911e796..5f66122ee7 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2022. All Rights Reserved. +%% Copyright Ericsson AB 2005-2023. 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. @@ -43,7 +43,8 @@ verify_middle_queue_save/1, test_length/1, fixed_apply_badarg/1, - external_fun_apply3/1]). + external_fun_apply3/1, + node_1/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -61,7 +62,7 @@ all() -> is_process_alive, is_process_alive_signal_from, process_info_blast, os_env_case_sensitivity, verify_middle_queue_save, test_length,fixed_apply_badarg, - external_fun_apply3]. + external_fun_apply3, node_1]. init_per_testcase(guard_bifs_in_erl_bif_types, Config) when is_list(Config) -> skip_missing_erl_bif_types(Config); @@ -356,6 +357,11 @@ auto_imports([], Errors) -> extract_functions(M, Abstr) -> [{{M,F,A},Body} || {function,_,F,A,Body} <- Abstr]. +check_stub({_,F,2}, _B) when F =:= min; F =:= max -> + %% In Erlang/OTP 26, min/2 and max/2 are guard BIFs. For backward + %% compatibility with code compiled with an earlier version, the + %% Erlang implementation of them is kept. + ok; check_stub({_,F,A}, B) -> try [{clause,_,Args,[],Body}] = B, @@ -724,33 +730,147 @@ fail_atom_to_binary(Term) -> end. -min_max(Config) when is_list(Config) -> - a = erlang:min(id(a), a), - a = erlang:min(id(a), b), - a = erlang:min(id(b), a), - b = erlang:min(id(b), b), - a = erlang:max(id(a), a), - b = erlang:max(id(a), b), - b = erlang:max(id(b), a), - b = erlang:max(id(b), b), - - 42.0 = erlang:min(42.0, 42), - 42.0 = erlang:max(42.0, 42), - %% And now (R14) they are also autoimported! +min_max(Config) when is_list(Config) -> + Self = self(), + Port = hd(erlang:ports()), + Ref = make_ref(), a = min(id(a), a), a = min(id(a), b), a = min(id(b), a), b = min(id(b), b), + Ref = min(id(Self), id(Ref)), + + -3 = min(id(5), -3), + -3 = min(-3, id(5)), + -3 = min(0, id(-3)), + -3 = min(id(-3), 0), + 0 = min(0, id(17)), + a = max(id(a), a), b = max(id(a), b), b = max(id(b), a), b = max(id(b), b), + Self = max(id(Self), id(Ref)), + + 5 = max(id(5), -3), + 5 = max(-3, id(5)), + 0 = max(0, id(-3)), + 0 = max(id(-3), 0), + 17 = max(0, id(17)), + + %% Return the first argument when arguments are equal. + 42.0 = min(id(42.0), 42), + 42.0 = max(id(42.0), 42), + + Min = id(min), + Max = id(max), + + "abc" = erlang:Min("abc", "def"), + <<"def">> = erlang:Max(<<"abc">>, <<"def">>), + + %% Make sure that the JIT doesn't do any unsafe optimizations. + {0, 0} = min_max_zero(0), + {-7, 0} = min_max_zero(-7), + {0, 555} = min_max_zero(555), + {0, 1 bsl 64} = min_max_zero(1 bsl 64), + {-1 bsl 64, 0} = min_max_zero(-1 bsl 64), + + {-99, 23} = do_min_max(-99, 23), + {-10, 0} = do_min_max(0, -10), + {0, 77} = do_min_max(77, 0), + {1, 2} = do_min_max(1, 2), + {42, 99} = do_min_max(99, 42), + {100, 1 bsl 64} = do_min_max(100, 1 bsl 64), + {-1 bsl 64, 77} = do_min_max(77, -1 bsl 64), + {-1 bsl 64, 1 bsl 64} = do_min_max(1 bsl 64, -1 bsl 64), + {42.0, 43} = do_min_max(42.0, 43), + {42.0, 50.0} = do_min_max(42.0, 50.0), + {42.0, 42.0} = do_min_max(42.0, id(40.0 + 2.0)), + {{1,2}, {a,b}} = do_min_max({id(a), id(b)}, {id(1), id(2)}), + {{a,b}, [a,b]} = do_min_max({a,id(b)}, [a,id(b)]), + {{1.0,b}, {1.0,b}} = do_min_max({id(1.0), id(b)}, {id(1), id(b)}), + {{7,b}, {7,b}} = do_min_max({id(7), id(b)}, {id(7.0), id(b)}), + + {42,Self} = do_min_max(42, Self), + {42,Self} = do_min_max(Self, 42), + {42,Port} = do_min_max(42, Port), + {42,Port} = do_min_max(Port, 42), - 42.0 = min(42.0, 42), - 42.0 = max(42.0, 42), ok. +min_max_zero(A0) -> + Result = {min(A0, 0), max(A0, 0)}, + Result = {min(0, A0), max(0, A0)}, + A = id(A0), + Result = {min(A, 0), max(A, 0)}, + Result = {min(0, A), max(0, A)}. + +do_min_max(A0, B0) -> + Result = {min(A0, B0), max(A0, B0)}, + + A0 = min(id(A0), A0), + A0 = max(id(A0), A0), + B0 = min(id(B0), B0), + B0 = max(id(B0), B0), + + A = id(A0), + B = id(B0), + Result = {min(A, B), max(A, B)}, + + if + is_integer(A), is_atom(node(B)) orelse is_integer(B) -> + _ = id(0), + Result = {min(A, B),max(A, B)}; + is_atom(node(A)) orelse is_integer(A), is_integer(B) -> + _ = id(0), + Result = {min(A, B),max(A, B)}; + true -> + ok + end, + + if + is_integer(A), 0 =< A, A =< 1000, is_atom(node(B)) orelse is_integer(B) -> + _ = id(0), + Result = {min(A, B),max(A, B)}; + is_atom(node(A)) orelse is_integer(A), is_integer(B), 0 =< B, B =< 1000 -> + _ = id(0), + Result = {min(A, B),max(A, B)}; + true -> + ok + end, + Result = do_min_max_1(1, 2, 3, 4, 5, A, B). + +do_min_max_1(_, _, _, _, _, A, B) -> + if + is_integer(A), 0 =< A, A < 16#1_0000, + is_integer(B), 0 =< B, B < 16#1_0000 -> + Result = {min(A, B),max(A, B)}, + Result = {min(B, A),max(B, A)}, + _ = id(0), + Result = {min(A, B),max(A, B)}, + Result = {min(B, A),max(B, A)}; + is_integer(A), is_integer(B) -> + Result = {min(A, B),max(A, B)}, + Result = {min(B, A),max(B, A)}, + _ = id(0), + Result = {min(A, B),max(A, B)}, + Result = {min(B, A),max(B, A)}; + is_float(A), is_float(B) -> + Result = {min(A, B),max(A, B)}, + Result = {min(B, A),max(B, A)}, + _ = id(0), + Result = {min(A, B),max(A, B)}, + Result = {min(B, A),max(B, A)}; + is_number(A), is_number(B) -> + Result = {min(A, B),max(A, B)}, + _ = id(0), + Result = {min(A, B),max(A, B)}; + true -> + Result = {min(A, B),max(A, B)}, + _ = id(0), + Result = {min(A, B),max(A, B)} + end. erlang_halt(Config) when is_list(Config) -> try erlang:halt(undefined) of @@ -1445,6 +1565,73 @@ external_fun_apply3(_Config) -> ok. +node_1(_Config) -> + {ok, Peer, Node} = ?CT_PEER(), + + local_node(self()), + LocalPort = lists:last(erlang:ports()), + local_node(LocalPort), + local_node(make_ref()), + + external_node(erpc:call(Node, erlang, self, []), Node), + ExtPort = hd(erpc:call(Node, erlang, ports, [])), + external_node(ExtPort, Node), + external_node(erpc:call(Node, erlang, make_ref, []), Node), + + node_error(a), + node_error(42), + node_error({a,b,c}), + node_error({tag,self()}), + node_error([self()]), + node_error(1 bsl 133), + node_error(#{}), + node_error(#{id(a) => b}), + node_error(<<"binary">>), + + peer:stop(Peer), + ok. + +local_node(E) -> + test_node(E, node()). + +external_node(E, Node) -> + test_node(E, Node). + +test_node(E0, Node) -> + true = node(id(E0)) =:= Node, + E = id(E0), + if + node(E) =:= Node -> + ok + end, + test_node_2(id(E), Node). + +test_node_2(E, Node) when is_pid(E); is_port(E); is_reference(E) -> + true = node(E) =:= Node, + if + node(E) =:= Node -> + ok + end, + test_node_3(id(E), Node), + ok. + +test_node_3(E, Node) when is_pid(E) -> + true = node(E) =:= Node; +test_node_3(E, Node) when is_port(E) -> + true = node(E) =:= Node; +test_node_3(E, Node) when is_reference(E) -> + true = node(E) =:= Node. + +node_error(E0) -> + E = id(E0), + {'EXIT',{badarg,[{erlang,node,[E],_}|_]}} = catch node(E), + if + node(E) -> + ct:fail(should_fail); + true -> + ok + end. + %% helpers busy_wait_go() -> |