1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2019-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%% 22%% This test suite is basically a "placeholder" for a proper test suite... 23%% Also we should really call prim_net directly, and not net (since that does 24%% not even reside here). 25%% 26 27%% Run the entire test suite: 28%% ts:run(emulator, net_SUITE, [batch]). 29%% 30%% Run a specific group: 31%% ts:run(emulator, net_SUITE, {group, foo}, [batch]). 32%% 33%% Run a specific test case: 34%% ts:run(emulator, net_SUITE, foo, [batch]). 35 36-module(net_SUITE). 37 38-include_lib("common_test/include/ct.hrl"). 39-include_lib("common_test/include/ct_event.hrl"). 40 41%% Suite exports 42-export([suite/0, all/0, groups/0]). 43-export([init_per_suite/1, end_per_suite/1, 44 init_per_group/2, end_per_group/2, 45 init_per_testcase/2, end_per_testcase/2]). 46 47%% Test cases 48-export([ 49 %% *** API Basic *** 50 api_b_gethostname/1, 51 api_b_getifaddrs/1, 52 api_b_name_and_addr_info/1, 53 54 api_b_name_and_index/1 55 56 %% Tickets 57 ]). 58 59 60%% -include("socket_test_evaluator.hrl"). 61 62%% Internal exports 63%% -export([]). 64 65 66%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 67 68-define(SLEEP(T), receive after T -> ok end). 69 70-define(FAIL(R), exit(R)). 71-define(SKIP(R), throw({skip, R})). 72 73-define(MINS(M), timer:minutes(M)). 74-define(SECS(S), timer:seconds(S)). 75 76-define(TT(T), ct:timetrap(T)). 77 78 79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80 81suite() -> 82 [{ct_hooks,[ts_install_cth]}, 83 {timetrap,{minutes,1}}]. 84 85all() -> 86 Groups = [{api, "ENET_TEST_API", include}], 87 [use_group(Group, Env, Default) || {Group, Env, Default} <- Groups]. 88 89use_group(Group, Env, Default) -> 90 case os:getenv(Env) of 91 false when (Default =:= include) -> 92 [{group, Group}]; 93 false -> 94 []; 95 Val -> 96 case list_to_atom(string:to_lower(Val)) of 97 Use when (Use =:= include) orelse 98 (Use =:= enable) orelse 99 (Use =:= true) -> 100 [{group, Group}]; 101 _ -> 102 [] 103 end 104 end. 105 106 107groups() -> 108 [{api, [], api_cases()}, 109 {api_basic, [], api_basic_cases()} 110 111 %% {tickets, [], ticket_cases()} 112 ]. 113 114api_cases() -> 115 [ 116 {group, api_basic} 117 ]. 118 119api_basic_cases() -> 120 [ 121 api_b_gethostname, 122 api_b_getifaddrs, 123 api_b_name_and_addr_info, 124 api_b_name_and_index 125 ]. 126 127%% ticket_cases() -> 128%% []. 129 130 131 132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 133 134init_per_suite(Config) -> 135 try net:info() of 136 #{} -> 137 %% ?LOGGER:start(), 138 Config 139 catch 140 error : notsup -> 141 {skip, "esock not supported"} 142 end. 143 144end_per_suite(_) -> 145 %% ?LOGGER:stop(), 146 ok. 147 148init_per_group(_Group, Config) -> 149 Config. 150 151end_per_group(_Group, Config) -> 152 Config. 153 154 155init_per_testcase(_TC, Config) -> 156 Config. 157 158end_per_testcase(_TC, Config) -> 159 Config. 160 161 162 163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 165%% %% 166%% API BASIC %% 167%% %% 168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 169%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 170 171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 172 173%% Get the hostname of the host. 174api_b_gethostname(suite) -> 175 []; 176api_b_gethostname(doc) -> 177 []; 178api_b_gethostname(_Config) when is_list(_Config) -> 179 ?TT(?SECS(5)), 180 tc_try(api_b_gethostname, 181 fun() -> 182 ok = api_b_gethostname() 183 end). 184 185 186api_b_gethostname() -> 187 case net:gethostname() of 188 {ok, Hostname} -> 189 i("hostname: ~s", [Hostname]), 190 ok; 191 {error, Reason} -> 192 ?FAIL(Reason) 193 end. 194 195 196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 197 198%% This is a *very* basic test. It simply calls the function and expect 199%% it to succeed... 200api_b_getifaddrs(suite) -> 201 []; 202api_b_getifaddrs(doc) -> 203 []; 204api_b_getifaddrs(_Config) when is_list(_Config) -> 205 ?TT(?SECS(5)), 206 tc_try(api_b_getifaddrs, 207 fun() -> 208 ok = api_b_getifaddrs() 209 end). 210 211 212api_b_getifaddrs() -> 213 case net:getifaddrs() of 214 {ok, IfAddrs} -> 215 i("IfAddrs: " 216 "~n ~p", [IfAddrs]), 217 ok; 218 {error, enotsup = Reason} -> 219 i("getifaddrs not supported - skipping"), 220 skip(Reason); 221 {error, Reason} -> 222 ?FAIL(Reason) 223 end. 224 225 226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 227 228%% Get name and address info. 229api_b_name_and_addr_info(suite) -> 230 []; 231api_b_name_and_addr_info(doc) -> 232 []; 233api_b_name_and_addr_info(_Config) when is_list(_Config) -> 234 ?TT(?SECS(5)), 235 tc_try(api_b_name_and_addr_info, 236 fun() -> 237 ok = api_b_name_and_addr_info() 238 end). 239 240 241api_b_name_and_addr_info() -> 242 Domain = inet, 243 Addr = which_local_addr(Domain), 244 SA = #{family => Domain, addr => Addr}, 245 Hostname = 246 case net:getnameinfo(SA) of 247 {ok, #{host := Name, service := Service} = NameInfo} 248 when is_list(Name) andalso is_list(Service) -> 249 i("getnameinfo: " 250 "~n ~p", [NameInfo]), 251 Name; 252 {ok, BadNameInfo} -> 253 ?FAIL({getnameinfo, SA, BadNameInfo}); 254 {error, enotsup = ReasonNI} -> 255 i("getnameinfo not supported - skipping"), 256 ?SKIP({getnameinfo, ReasonNI}); 257 {error, Reason1} -> 258 ?FAIL({getnameinfo, SA, Reason1}) 259 end, 260 case net:getaddrinfo(Hostname) of 261 {ok, AddrInfos} when is_list(AddrInfos) -> 262 i("getaddrinfo: " 263 "~n ~p", [AddrInfos]), 264 verify_addr_info(AddrInfos, Domain); 265 {ok, BadAddrInfo} -> 266 ?FAIL({getaddrinfo, Hostname, BadAddrInfo}); 267 {error, enotsup = ReasonAI} -> 268 i("getaddrinfo not supported - skipping"), 269 ?SKIP({getaddrinfo, ReasonAI}); 270 {error, Reason2} -> 271 ?FAIL({getaddrinfo, Hostname, Reason2}) 272 end. 273 274 275verify_addr_info(AddrInfos, Domain) when (AddrInfos =/= []) -> 276 verify_addr_info2(AddrInfos, Domain). 277 278verify_addr_info2([], _Domain) -> 279 ok; 280verify_addr_info2([#{addr := #{addr := Addr, 281 family := Domain, 282 port := Port}, 283 family := Domain, 284 type := _Type, 285 protocol := _Proto}|T], Domain) 286 when is_integer(Port) andalso 287 (((Domain =:= inet) andalso is_tuple(Addr) andalso (size(Addr) =:= 4)) orelse 288 ((Domain =:= inet6) andalso is_tuple(Addr) andalso (size(Addr) =:= 8))) -> 289 verify_addr_info2(T, Domain); 290verify_addr_info2([#{family := DomainA}|T], DomainB) 291 when (DomainA =/= DomainB) -> 292 %% Ignore entries for other domains 293 verify_addr_info2(T, DomainB); 294verify_addr_info2([BadAddrInfo|_], Domain) -> 295 ?FAIL({bad_address_info, BadAddrInfo, Domain}). 296 297 298 299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 300 301%% Verify (interface) name and index functions. 302%% if_names/0, 303%% if_name2index/1 304%% if_index2name/1 305api_b_name_and_index(suite) -> 306 []; 307api_b_name_and_index(doc) -> 308 []; 309api_b_name_and_index(_Config) when is_list(_Config) -> 310 ?TT(?SECS(5)), 311 tc_try(api_b_name_and_index, 312 fun() -> 313 ok = api_b_name_and_index() 314 end). 315 316 317api_b_name_and_index() -> 318 Names = 319 case net:if_names() of 320 {ok, N} when is_list(N) andalso (N =/= []) -> 321 N; 322 {error, enotsup = Reason} -> 323 i("if_names not supported - skipping"), 324 ?SKIP({if_names, Reason}); 325 {error, Reason} -> 326 ?FAIL({if_names, Reason}) 327 end, 328 verify_if_names(Names). 329 330verify_if_names([]) -> 331 ok; 332verify_if_names([{Index, Name}|T]) -> 333 case net:if_name2index(Name) of 334 {ok, Index} -> 335 ok; 336 {ok, BadIndex} -> 337 ?FAIL({if_name2index, Name, Index, BadIndex}); 338 {error, enotsup = Reason_N2I1} -> 339 i("if_name2index not supported - skipping"), 340 ?SKIP({if_name2index, Reason_N2I1}); 341 {error, Reason_N2I2} -> 342 ?FAIL({if_name2index, Name, Reason_N2I2}) 343 end, 344 case net:if_index2name(Index) of 345 {ok, Name} -> 346 ok; 347 {ok, BadName} -> 348 ?FAIL({if_index2name, Index, Name, BadName}); 349 {error, enotsup = Reason_I2N1} -> 350 i("if_index2name not supported - skipping"), 351 ?SKIP({if_index2name, Reason_I2N1}); 352 {error, Reason_I2N2} -> 353 ?FAIL({if_index2name, Index, Reason_I2N2}) 354 end, 355 verify_if_names(T). 356 357 358 359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 360 361%% This gets the local address (not 127.0...) 362%% We should really implement this using the (new) net module, 363%% but until that gets the necessary functionality... 364which_local_addr(Domain) -> 365 case inet:getifaddrs() of 366 {ok, IFL} -> 367 which_addr(Domain, IFL); 368 {error, Reason} -> 369 ?FAIL({inet, getifaddrs, Reason}) 370 end. 371 372which_addr(_Domain, []) -> 373 skip(no_address); 374which_addr(Domain, [{"lo" ++ _, _}|IFL]) -> 375 which_addr(Domain, IFL); 376which_addr(Domain, [{_Name, IFO}|IFL]) -> 377 case which_addr2(Domain, IFO) of 378 {ok, Addr} -> 379 Addr; 380 {error, no_address} -> 381 which_addr(Domain, IFL) 382 end; 383which_addr(Domain, [_|IFL]) -> 384 which_addr(Domain, IFL). 385 386which_addr2(_Domain, []) -> 387 {error, no_address}; 388which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 4) -> 389 {ok, Addr}; 390which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 8) -> 391 {ok, Addr}; 392which_addr2(Domain, [_|IFO]) -> 393 which_addr2(Domain, IFO). 394 395 396 397 398 399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 400 401not_yet_implemented() -> 402 skip("not yet implemented"). 403 404skip(Reason) -> 405 throw({skip, Reason}). 406 407 408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 409 410%% t() -> 411%% os:timestamp(). 412 413 414%% tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) -> 415%% T1 = A1*1000000000+B1*1000+(C1 div 1000), 416%% T2 = A2*1000000000+B2*1000+(C2 div 1000), 417%% T2 - T1. 418 419 420formated_timestamp() -> 421 format_timestamp(os:timestamp()). 422 423format_timestamp({_N1, _N2, _N3} = TS) -> 424 {_Date, Time} = calendar:now_to_local_time(TS), 425 %% {YYYY,MM,DD} = Date, 426 {Hour,Min,Sec} = Time, 427 %% FormatTS = 428 %% io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~w", 429 %% [YYYY, MM, DD, Hour, Min, Sec, N3]), 430 FormatTS = io_lib:format("~.2.0w:~.2.0w:~.2.0w", [Hour, Min, Sec]), 431 lists:flatten(FormatTS). 432 433 434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 435 436set_tc_name(N) when is_atom(N) -> 437 set_tc_name(atom_to_list(N)); 438set_tc_name(N) when is_list(N) -> 439 put(tc_name, N). 440 441%% get_tc_name() -> 442%% get(tc_name). 443 444tc_begin(TC) -> 445 set_tc_name(TC), 446 tc_print("begin ***", 447 "~n----------------------------------------------------~n", ""). 448 449tc_end(Result) when is_list(Result) -> 450 tc_print("done: ~s", [Result], 451 "", "----------------------------------------------------~n~n"), 452 ok. 453 454 455tc_try(Case, Fun) when is_atom(Case) andalso is_function(Fun, 0) -> 456 tc_begin(Case), 457 try 458 begin 459 Fun(), 460 ?SLEEP(?SECS(1)), 461 tc_end("ok") 462 end 463 catch 464 throw:{skip, _} = SKIP -> 465 tc_end("skipping"), 466 SKIP; 467 Class:Error:Stack -> 468 tc_end("failed"), 469 erlang:raise(Class, Error, Stack) 470 end. 471 472 473tc_print(F, Before, After) -> 474 tc_print(F, [], Before, After). 475 476tc_print(F, A, Before, After) -> 477 Name = tc_which_name(), 478 FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", 479 [formated_timestamp(),Name,self()|A]), 480 io:format(user, Before ++ FStr ++ After, []). 481 482tc_which_name() -> 483 case get(tc_name) of 484 undefined -> 485 case get(sname) of 486 undefined -> 487 ""; 488 SName when is_list(SName) -> 489 SName 490 end; 491 Name when is_list(Name) -> 492 Name 493 end. 494 495 496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 497 498%% l2a(S) when is_list(S) -> 499%% list_to_atom(S). 500 501%% l2b(L) when is_list(L) -> 502%% list_to_binary(L). 503 504%% b2l(B) when is_binary(B) -> 505%% binary_to_list(B). 506 507f(F, A) -> 508 lists:flatten(io_lib:format(F, A)). 509 510 511i(F) -> 512 i(F, []). 513 514i(F, A) -> 515 FStr = f("[~s] " ++ F, [formated_timestamp()|A]), 516 io:format(user, FStr ++ "~n", []), 517 io:format(FStr, []). 518 519