summaryrefslogtreecommitdiff
path: root/erts/emulator/test/bif_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/bif_SUITE.erl')
-rw-r--r--erts/emulator/test/bif_SUITE.erl223
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() ->