1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1997-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(list_bif_SUITE). 22-include_lib("common_test/include/ct.hrl"). 23 24-export([all/0, suite/0]). 25-export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1, 26 t_list_to_ref/1, t_list_to_ext_pidportref/1, 27 t_list_to_port/1,t_list_to_float/1,t_list_to_integer/1]). 28 29 30suite() -> 31 [{ct_hooks,[ts_install_cth]}, 32 {timetrap, {minutes, 1}}]. 33 34 35all() -> 36 [hd_test, tl_test, t_length, t_list_to_pid, t_list_to_port, 37 t_list_to_ref, t_list_to_ext_pidportref, 38 t_list_to_float, t_list_to_integer]. 39 40%% Tests list_to_integer and string:to_integer 41t_list_to_integer(Config) when is_list(Config) -> 42 {'EXIT',{badarg,_}} = (catch list_to_integer("12373281903728109372810937209817320981321ABC")), 43 12373281903728109372810937209817320981321 = (catch list_to_integer("12373281903728109372810937209817320981321")), 44 12373 = (catch list_to_integer("12373")), 45 -12373 = (catch list_to_integer("-12373")), 46 12373 = (catch list_to_integer("+12373")), 47 {'EXIT',{badarg,_}} = ( catch list_to_integer(abc)), 48 {'EXIT',{badarg,_}} = (catch list_to_integer("")), 49 {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"), 50 {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"), 51 {12,[345]} = string:to_integer([$1,$2,345]), 52 {error, badarg} = string:to_integer([$1,$2,a]), 53 {error,no_integer} = string:to_integer([$A]), 54 {error,badarg} = string:to_integer($A), 55 ok. 56 57%% Test hd/1 with correct and incorrect arguments. 58hd_test(Config) when is_list(Config) -> 59 $h = hd(id("hejsan")), 60 case catch hd(id($h)) of 61 {'EXIT', {badarg, _}} -> ok; 62 Res -> 63 ct:fail("hd/1 with incorrect args succeeded.~nResult: ~p", [Res]) 64 end, 65 ok. 66 67 68%% Test tl/1 with correct and incorrect arguments. 69tl_test(Config) when is_list(Config) -> 70 "ejsan" = tl(id("hejsan")), 71 case catch tl(id(104)) of 72 {'EXIT', {badarg, _}} -> 73 ok; 74 Res -> 75 ct:fail("tl/1 with incorrect args succeeded.~nResult: ~p", [Res]) 76 end, 77 ok. 78 79 80%% Test length/1 with correct and incorrect arguments. 81 82t_length(Config) when is_list(Config) -> 83 0 = length(""), 84 0 = length([]), 85 1 = length([1]), 86 2 = length([1,a]), 87 2 = length("ab"), 88 3 = length("abc"), 89 4 = length(id([x|"abc"])), 90 6 = length("hejsan"), 91 {'EXIT',{badarg,_}} = (catch length(id([a,b|c]))), 92 case catch length({tuple}) of 93 {'EXIT', {badarg, _}} -> 94 ok; 95 Res -> 96 ct:fail("length/1 with incorrect args succeeded.~nResult: ~p", [Res]) 97 end, 98 ok. 99 100 101%% Test list_to_pid/1 with correct and incorrect arguments. 102 103t_list_to_pid(Config) when is_list(Config) -> 104 Me = self(), 105 MyListedPid = pid_to_list(Me), 106 Me = list_to_pid(MyListedPid), 107 case catch list_to_pid(id("Incorrect list")) of 108 {'EXIT', {badarg, _}} -> 109 ok; 110 Res -> 111 ct:fail("list_to_pid/1 with incorrect arg succeeded.~n" 112 "Result: ~p", [Res]) 113 end, 114 ok. 115 116%% Test list_to_port/1 with correct and incorrect arguments. 117 118t_list_to_port(Config) when is_list(Config) -> 119 Me = hd(erlang:ports()), 120 MyListedPid = port_to_list(Me), 121 Me = list_to_port(MyListedPid), 122 case catch list_to_port(id("Incorrect list")) of 123 {'EXIT', {badarg, _}} -> 124 ok; 125 Res -> 126 ct:fail("list_to_port/1 with incorrect arg succeeded.~n" 127 "Result: ~p", [Res]) 128 end, 129 ok. 130 131t_list_to_ref(Config) when is_list(Config) -> 132 Ref = make_ref(), 133 RefStr = ref_to_list(Ref), 134 Ref = list_to_ref(RefStr), 135 case catch list_to_ref(id("Incorrect list")) of 136 {'EXIT', {badarg, _}} -> 137 ok; 138 Res -> 139 ct:fail("list_to_ref/1 with incorrect arg succeeded.~n" 140 "Result: ~p", [Res]) 141 end, 142 ok. 143 144%% Test list_to_pid/port/ref for external pids/ports/refs. 145t_list_to_ext_pidportref(Config) when is_list(Config) -> 146 {ok, Node} = slave:start(net_adm:localhost(), t_list_to_ext_pidportref), 147 Pid = rpc:call(Node, erlang, self, []), 148 Port = hd(rpc:call(Node, erlang, ports, [])), 149 Ref = rpc:call(Node, erlang, make_ref, []), 150 151 PidStr = pid_to_list(Pid), 152 PortStr = port_to_list(Port), 153 RefStr = ref_to_list(Ref), 154 155 Pid2 = list_to_pid(PidStr), 156 Port2 = list_to_port(PortStr), 157 Ref2 = list_to_ref(RefStr), 158 159 %% Local roundtrips of externals work from OTP-23 160 %% as even though 'creation' is missing in the string formats 161 %% we know the 'creation' of the connected node and list_to_* use that. 162 true = (Pid =:= Pid2), 163 true = (Port =:= Port2), 164 true = (Ref =:= Ref2), 165 true = (Pid == Pid2), 166 true = (Port == Port2), 167 true = (Ref == Ref2), 168 169 %% And it works when sent back to the same node instance, 170 %% which was connected when list_to_* were called. 171 true = rpc:call(Node, erlang, '=:=', [Pid, Pid2]), 172 true = rpc:call(Node, erlang, '==', [Pid, Pid2]), 173 true = rpc:call(Node, erlang, '=:=', [Port, Port2]), 174 true = rpc:call(Node, erlang, '==', [Port, Port2]), 175 true = rpc:call(Node, erlang, '=:=', [Ref, Ref2]), 176 true = rpc:call(Node, erlang, '==', [Ref, Ref2]), 177 178 %% Make sure no ugly comparison with 0-creation as wildcard is done. 179 Pid0 = make_0_creation(Pid), 180 Port0 = make_0_creation(Port), 181 Ref0 = make_0_creation(Ref), 182 false = (Pid =:= Pid0), 183 false = (Port =:= Port0), 184 false = (Ref =:= Ref0), 185 false = (Pid == Pid0), 186 false = (Port == Port0), 187 false = (Ref == Ref0), 188 189 %% Check 0-creations are converted to local node creations 190 %% when sent to matching node name. 191 true = rpc:call(Node, erlang, '=:=', [Pid, Pid0]), 192 true = rpc:call(Node, erlang, '==', [Pid, Pid0]), 193 true = rpc:call(Node, erlang, '=:=', [Port, Port0]), 194 true = rpc:call(Node, erlang, '==', [Port, Port0]), 195 true = rpc:call(Node, erlang, '=:=', [Ref, Ref0]), 196 true = rpc:call(Node, erlang, '==', [Ref, Ref0]), 197 198 slave:stop(Node), 199 ok. 200 201-define(NEW_PID_EXT, 88). 202-define(NEW_PORT_EXT, 89). 203-define(NEWER_REFERENCE_EXT, 90). 204 205%% Copy pid/port/ref but set creation=0 206make_0_creation(X) when is_pid(X); is_port(X); is_reference(X) -> 207 B = term_to_binary(X), 208 Sz = byte_size(B), 209 B2 = case B of 210 <<131, ?NEW_PID_EXT, _/binary>> -> 211 PreSz = Sz - 4, 212 <<_:PreSz/binary, Cr:32>> = B, 213 true = (Cr =/= 0), 214 <<B:PreSz/binary, 0:32>>; 215 <<131, ?NEW_PORT_EXT, _/binary>> -> 216 PreSz = Sz - 4, 217 <<_:PreSz/binary, Cr:32>> = B, 218 true = (Cr =/= 0), 219 <<B:PreSz/binary, 0:32>>; 220 <<131, ?NEWER_REFERENCE_EXT, Len:16, _/binary>> -> 221 PostSz = Len*4, 222 PreSz = Sz - (4 + PostSz), 223 <<_:PreSz/binary, Cr:32, PostFix:PostSz/binary>> = B, 224 true = (Cr =/= 0), 225 <<B:PreSz/binary, 0:32, PostFix/binary>> 226 end, 227 binary_to_term(B2). 228 229 230%% Test list_to_float/1 with correct and incorrect arguments. 231 232t_list_to_float(Config) when is_list(Config) -> 233 5.89000 = list_to_float(id("5.89")), 234 5.89898 = list_to_float(id("5.89898")), 235 case catch list_to_float(id("58")) of 236 {'EXIT', {badarg, _}} -> ok; 237 Res -> 238 ct:fail("list_to_float with incorrect arg succeeded.~nResult: ~p", [Res]) 239 end, 240 ok. 241 242id(I) -> I. 243