1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1998-2016. 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-module(bif_SUITE). 21-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 22 init_per_group/2,end_per_group/2]). 23 24-export([ 25 spawn1/1, spawn2/1, spawn3/1, spawn4/1, 26 27 28 spawn_link1/1, spawn_link2/1, spawn_link3/1, spawn_link4/1, 29 30 31 spawn_opt2/1, spawn_opt3/1, spawn_opt4/1, spawn_opt5/1, 32 33 spawn_failures/1, 34 35 run_fun/1, 36 decode_packet_delim/1, 37 wilderness/1]). 38 39-export([init_per_testcase/2, end_per_testcase/2]). 40 41-include_lib("common_test/include/ct.hrl"). 42 43init_per_testcase(_Case, Config) -> 44 Config. 45 46end_per_testcase(_Case, _Config) -> 47 ok. 48 49suite() -> 50 [{ct_hooks,[ts_install_cth]}, 51 {timetrap,{minutes,1}}]. 52 53all() -> 54 [{group, spawn_tests}, {group, spawn_link_tests}, 55 {group, spawn_opt_tests}, spawn_failures, wilderness]. 56 57groups() -> 58 [{spawn_tests, [], [spawn1, spawn2, spawn3, spawn4]}, 59 {spawn_link_tests, [], 60 [spawn_link1, spawn_link2, spawn_link3, spawn_link4]}, 61 {spawn_opt_tests, [], 62 [spawn_opt2, spawn_opt3, spawn_opt4, spawn_opt5]}]. 63 64init_per_suite(Config) -> 65 Config. 66 67end_per_suite(_Config) -> 68 ok. 69 70init_per_group(_GroupName, Config) -> 71 Config. 72 73end_per_group(_GroupName, Config) -> 74 Config. 75 76 77%% Test spawn/1. 78spawn1(Config) when is_list(Config) -> 79 Node = node(), 80 Parent = self(), 81 {_, _, FA, _} = fetch_proc_vals(self()), 82 83 %% spawn 84 P = spawn(fun() -> Parent ! {self(), fetch_proc_vals(self())} end), 85 receive 86 {P, PV} -> 87 Node = node(P), 88 check_proc_vals(false, normal, FA, 0, PV) 89 end, 90 ok. 91 92%% Test spawn/2. 93spawn2(Config) when is_list(Config) -> 94 {ok, Node} = start_node(spawn2), 95 96 Parent = self(), 97 {_, _, FA, _} = fetch_proc_vals(self()), 98 99 %% spawn_link 100 P = spawn(Node, 101 fun() -> Parent ! {self(), fetch_proc_vals(self())} end), 102 receive 103 {P, PV} -> 104 Node = node(P), 105 check_proc_vals(false, normal, FA, 0, PV) 106 end, 107 108 true = stop_node(Node), 109 ok. 110 111 112%% Test spawn/3. 113spawn3(Config) when is_list(Config) -> 114 Node = node(), 115 116 Parent = self(), 117 {_, _, FA, _} = fetch_proc_vals(self()), 118 119 %% spawn_link 120 P = spawn(?MODULE, 121 run_fun, 122 [fun() -> 123 Parent ! {self(), fetch_proc_vals(self())} 124 end]), 125 receive 126 {P, PV} -> 127 Node = node(P), 128 check_proc_vals(false, normal, FA, 0, PV) 129 end, 130 ok. 131 132%% Test spawn/4. 133spawn4(Config) when is_list(Config) -> 134 {ok, Node} = start_node(spawn4), 135 136 Parent = self(), 137 {_, _, FA, _} = fetch_proc_vals(self()), 138 139 %% spawn_link 140 P = spawn(Node, 141 ?MODULE, 142 run_fun, 143 [fun() -> 144 Parent ! {self(), fetch_proc_vals(self())} 145 end]), 146 receive 147 {P, PV} -> 148 Node = node(P), 149 check_proc_vals(false, normal, FA, 0, PV) 150 end, 151 152 true = stop_node(Node), 153 ok. 154 155 156 157%% Test spawn_link/1. 158spawn_link1(Config) when is_list(Config) -> 159 Node = node(), 160 Parent = self(), 161 {_, _, FA, _} = fetch_proc_vals(self()), 162 163 %% spawn_link 164 P = spawn_link(fun() -> Parent ! {self(), fetch_proc_vals(self())} end), 165 receive 166 {P, PV} -> 167 Node = node(P), 168 check_proc_vals(true, normal, FA, 0, PV) 169 end, 170 ok. 171 172%% Test spawn_link/2. 173spawn_link2(Config) when is_list(Config) -> 174 {ok, Node} = start_node(spawn_link2), 175 176 Parent = self(), 177 {_, _, FA, _} = fetch_proc_vals(self()), 178 179 %% spawn_link 180 P = spawn_link(Node, 181 fun() -> Parent ! {self(), fetch_proc_vals(self())} end), 182 receive 183 {P, PV} -> 184 Node = node(P), 185 check_proc_vals(true, normal, FA, 0, PV) 186 end, 187 188 true = stop_node(Node), 189 ok. 190 191%% Test spawn_link/3. 192spawn_link3(Config) when is_list(Config) -> 193 Node = node(), 194 195 Parent = self(), 196 {_, _, FA, _} = fetch_proc_vals(self()), 197 198 %% spawn_link 199 P = spawn_link(?MODULE, 200 run_fun, 201 [fun() -> 202 Parent ! {self(), fetch_proc_vals(self())} 203 end]), 204 receive 205 {P, PV} -> 206 Node = node(P), 207 check_proc_vals(true, normal, FA, 0, PV) 208 end, 209 ok. 210 211%% Test spawn_link/4. 212spawn_link4(Config) when is_list(Config) -> 213 {ok, Node} = start_node(spawn_link4), 214 215 Parent = self(), 216 {_, _, FA, _} = fetch_proc_vals(self()), 217 218 %% spawn_link 219 P = spawn_link(Node, 220 ?MODULE, 221 run_fun, 222 [fun() -> 223 Parent ! {self(), fetch_proc_vals(self())} 224 end]), 225 receive 226 {P, PV} -> 227 Node = node(P), 228 check_proc_vals(true, normal, FA, 0, PV) 229 end, 230 231 true = stop_node(Node), 232 ok. 233 234 235%% Test spawn_opt/2. 236spawn_opt2(Config) when is_list(Config) -> 237 Node = node(), 238 Parent = self(), 239 {_, _, FA, _} = fetch_proc_vals(self()), 240 241 P1 = spawn_opt(fun() -> 242 Parent ! {self(), fetch_proc_vals(self())} 243 end, 244 [{fullsweep_after, 0},{min_heap_size, 1000}, 245 link, {priority, max}]), 246 receive 247 {P1, PV1} -> 248 Node = node(P1), 249 check_proc_vals(true, max, 0, 1000, PV1) 250 end, 251 P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end, 252 [{min_heap_size, 10}]), 253 receive 254 {P2, PV2} -> 255 Node = node(P2), 256 check_proc_vals(false, normal, FA, 10, PV2) 257 end, 258 ok. 259 260%% Test spawn_opt/3. 261spawn_opt3(Config) when is_list(Config) -> 262 {ok, Node} = start_node(spawn_opt3), 263 Parent = self(), 264 {_, _, FA, _} = fetch_proc_vals(self()), 265 P1 = spawn_opt(Node, 266 fun() -> 267 Parent ! {self(), fetch_proc_vals(self())} 268 end, 269 [{fullsweep_after,0}, {min_heap_size,1000}, 270 link, {priority, max}]), 271 receive 272 {P1, PV1} -> 273 Node = node(P1), 274 check_proc_vals(true, max, 0, 1000, PV1) 275 end, 276 P2 = spawn_opt(Node, 277 fun() -> Parent ! {self(), fetch_proc_vals(self())} end, 278 [{min_heap_size, 10}]), 279 receive 280 {P2, PV2} -> 281 Node = node(P2), 282 check_proc_vals(false, normal, FA, 10, PV2) 283 end, 284 true = stop_node(Node), 285 ok. 286 287%% Test spawn_opt/4. 288spawn_opt4(Config) when is_list(Config) -> 289 Node = node(), 290 Parent = self(), 291 {_, _, FA, _} = fetch_proc_vals(self()), 292 P1 = spawn_opt(?MODULE, 293 run_fun, 294 [fun() -> 295 Parent ! {self(), fetch_proc_vals(self())} 296 end], 297 [{fullsweep_after,0}, {min_heap_size,1000}, 298 link, {priority, max}]), 299 receive 300 {P1, PV1} -> 301 Node = node(P1), 302 check_proc_vals(true, max, 0, 1000, PV1) 303 end, 304 P2 = spawn_opt(?MODULE, 305 run_fun, 306 [fun() -> 307 Parent ! {self(), fetch_proc_vals(self())} 308 end], 309 [{min_heap_size, 10}]), 310 receive 311 {P2, PV2} -> 312 Node = node(P2), 313 check_proc_vals(false, normal, FA, 10, PV2) 314 end, 315 ok. 316 317%% Test spawn_opt/5. 318spawn_opt5(Config) when is_list(Config) -> 319 {ok, Node} = start_node(spawn_opt5), 320 Parent = self(), 321 {_, _, FA, _} = fetch_proc_vals(self()), 322 P1 = spawn_opt(Node, 323 ?MODULE, 324 run_fun, 325 [fun() -> 326 Parent ! {self(), fetch_proc_vals(self())} 327 end], 328 [{fullsweep_after,0}, {min_heap_size,1000}, 329 link, {priority, max}]), 330 receive 331 {P1, PV1} -> 332 Node = node(P1), 333 check_proc_vals(true, max, 0, 1000, PV1) 334 end, 335 P2 = spawn_opt(Node, 336 ?MODULE, 337 run_fun, 338 [fun() -> 339 Parent ! {self(), fetch_proc_vals(self())} 340 end], 341 [{min_heap_size, 10}]), 342 receive 343 {P2, PV2} -> 344 Node = node(P2), 345 check_proc_vals(false, normal, FA, 10, PV2) 346 end, 347 true = stop_node(Node), 348 ok. 349 350%% Test failure behavior of spawn bifs. 351spawn_failures(Config) when is_list(Config) -> 352 ThisNode = node(), 353 {ok, Node} = start_node(spawn_remote_failure), 354 355 %% unknown nodes 356 io:format("Testing unknown nodes~n", []), 357 CrashPid1 = (catch spawn_opt('unknown@node', 358 erlang, 359 nodes, 360 [], 361 [])), 362 true = is_pid(CrashPid1), 363 ThisNode = node(CrashPid1), 364 CrashPid2 = (catch spawn_opt('unknown@node', 365 fun () -> erlang:nodes() end, 366 [])), 367 true = is_pid(CrashPid2), 368 ThisNode = node(CrashPid2), 369 370 CrashPid3 = (catch spawn('unknown@node', 371 erlang, 372 nodes, 373 [])), 374 true = is_pid(CrashPid3), 375 ThisNode = node(CrashPid3), 376 CrashPid4 = (catch spawn('unknown@node', 377 fun () -> erlang:nodes() end)), 378 true = is_pid(CrashPid4), 379 ThisNode = node(CrashPid4), 380 381 OTE = process_flag(trap_exit,true), 382 CrashPid5 = (catch spawn_link('unknown@node', 383 erlang, 384 nodes, 385 [])), 386 receive 387 {'EXIT', CrashPid5, noconnection} -> 388 true = is_pid(CrashPid5), 389 ThisNode = node(CrashPid5) 390 end, 391 CrashPid6 = (catch spawn_link('unknown@node', 392 fun () -> erlang:nodes() end)), 393 receive 394 {'EXIT', CrashPid6, noconnection} -> 395 true = is_pid(CrashPid6), 396 ThisNode = node(CrashPid6) 397 end, 398 process_flag(trap_exit,OTE), 399 case OTE of 400 false -> 401 receive 402 {'EXIT', P, R} -> 403 ct:fail({'EXIT', P, R}) 404 after 0 -> 405 ok 406 end; 407 _ -> 408 ok 409 end, 410 411 %% bad node 412 io:format("Testing bad nodes~n", []), 413 {'EXIT', {badarg, _}} = (catch spawn_opt("Node",erlang,nodes,[],[])), 414 {'EXIT', {badarg, _}} = (catch spawn_opt("Node", 415 fun () -> 416 erlang:nodes() 417 end, 418 [])), 419 {'EXIT', {badarg, _}} = (catch spawn_link("Node", 420 fun () -> 421 erlang:nodes() 422 end)), 423 {'EXIT', {badarg, _}} = (catch spawn("Node",erlang,nodes,[])), 424 {'EXIT', {badarg, _}} = (catch spawn("Node", 425 fun () -> 426 erlang:nodes() 427 end)), 428 429 %% bad module 430 io:format("Testing bad modules~n", []), 431 {'EXIT', {badarg, _}} = (catch spawn_opt(Node,"erlang",nodes,[],[])), 432 {'EXIT', {badarg, _}} = (catch spawn_opt("erlang",nodes,[],[])), 433 {'EXIT', {badarg, _}} = (catch spawn_link(Node,"erlang",nodes,[])), 434 {'EXIT', {badarg, _}} = (catch spawn_link("erlang",nodes,[])), 435 {'EXIT', {badarg, _}} = (catch spawn(Node,"erlang",nodes,[])), 436 {'EXIT', {badarg, _}} = (catch spawn("erlang",nodes,[])), 437 438 %% bad function 439 io:format("Testing bad functions~n", []), 440 {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,"nodes",[],[])), 441 {'EXIT', {badarg, _}} = (catch spawn_opt(Node,not_a_fun,[])), 442 {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,"nodes",[],[])), 443 {'EXIT', {badarg, _}} = (catch spawn_opt(not_a_fun,[])), 444 {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,"nodes",[])), 445 {'EXIT', {badarg, _}} = (catch spawn_link(Node,not_a_fun)), 446 {'EXIT', {badarg, _}} = (catch spawn_link(erlang,"nodes",[])), 447 {'EXIT', {badarg, _}} = (catch spawn_link(not_a_fun)), 448 {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,"nodes",[])), 449 {'EXIT', {badarg, _}} = (catch spawn(Node,not_a_fun)), 450 {'EXIT', {badarg, _}} = (catch spawn(erlang,"nodes",[])), 451 {'EXIT', {badarg, _}} = (catch spawn(not_a_fun)), 452 453 454 %% bad argument 455 io:format("Testing bad arguments~n", []), 456 {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[a|b],[])), 457 {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[a|b],[])), 458 {'EXIT', {badarg, _}} = (catch spawn_link(Node,erlang,nodes,[a|b])), 459 {'EXIT', {badarg, _}} = (catch spawn_link(erlang,nodes,[a|b])), 460 {'EXIT', {badarg, _}} = (catch spawn(Node,erlang,nodes,[a|b])), 461 {'EXIT', {badarg, _}} = (catch spawn(erlang,nodes,[a|b])), 462 463 %% bad option 464 io:format("Testing bad options~n", []), 465 {'EXIT', {badarg, _}} = (catch spawn_opt(Node,erlang,nodes,[],[a|b])), 466 {'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[],[a|b])), 467 468 469 true = stop_node(Node), 470 ok. 471 472check_proc_vals(Link, Priority, FullsweepAfter, MinHeapSize, {Ls, P, FA, HS}) -> 473 Link = lists:member(self(), Ls), 474 Priority = P, 475 FullsweepAfter = FA, 476 true = (HS >= MinHeapSize), 477 ok. 478 479fetch_proc_vals(Pid) -> 480 PI = process_info(Pid), 481 {value,{links, Ls}} = lists:keysearch(links, 1, PI), 482 {value,{priority,P}} = lists:keysearch(priority, 1, PI), 483 {value,{garbage_collection,Gs}} = 484 lists:keysearch(garbage_collection, 1, PI), 485 {value,{fullsweep_after,FA}} = 486 lists:keysearch(fullsweep_after, 1, Gs), 487 {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), 488 {Ls, P, FA, HS}. 489 490%% Test erlang:packet_delim/3 with {line_delimiter,0} option. 491decode_packet_delim(Config) when is_list(Config) -> 492 {ok,<<"abc",0>>,<<"efg",0>>} = 493 erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]), 494 {more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []). 495 496%% This testcase should probably be moved somewhere else 497 498%% Test that memory allocation command line options affecting the 499%% wilderness of the heap are interpreted correct by the emulator. 500wilderness(Config) when is_list(Config) -> 501 OKParams = {512, 8}, 502 Alloc = erlang:system_info(allocator), 503 io:format("Test server allocator info:~n~p", [Alloc]), 504 Result = case Alloc of 505 {Allocator, _, _, _} when Allocator == glibc; 506 Allocator == dlmalloc -> 507 run_wilderness_test(OKParams, OKParams), 508 {comment, 509 "Allocator used: " ++ atom_to_list(Allocator)}; 510 {OtherAllocator, _, _, _} -> 511 {skipped, 512 "Only run when glibc is used. " 513 "Allocator used: " 514 ++ atom_to_list(OtherAllocator)} 515 end, 516 Result. 517 518run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) -> 519 Self = self(), 520 Ref = make_ref(), 521 SuiteDir = filename:dirname(code:which(?MODULE)), 522 {ok, Node} = test_server:start_node(allocator_test, 523 slave, 524 [{args, 525 " -pa " 526 ++ SuiteDir 527 ++" +MYtt "++to_string(Set_tt) 528 ++" +MYtp "++to_string(Set_tp)}, 529 {linked, false}]), 530 spawn(Node, fun () -> 531 Self ! {Ref, erlang:system_info(allocator)} 532 end), 533 receive 534 {Ref, {A, V, F, S}} -> 535 Ett = Exp_tt*1024, 536 Etp = Exp_tp*1024, 537 io:format("Test allocator info:~n~p", 538 [{A, V, F, S}]), 539 {value, {sys_alloc, SA_Opts}} 540 = lists:keysearch(sys_alloc, 1, S), 541 {value, {tt, Ett}} = lists:keysearch(tt, 1, SA_Opts), 542 {value, {tp, Etp}} = lists:keysearch(tp, 1, SA_Opts) 543 end, 544 stop_node(Node). 545 546to_string(X) when is_integer(X) -> 547 integer_to_list(X); 548to_string(X) when is_atom(X) -> 549 atom_to_list(X); 550to_string(X) when is_list(X) -> 551 X. 552 553get_nodenames(N, T) -> 554 get_nodenames(N, T, []). 555 556get_nodenames(0, _, Acc) -> 557 Acc; 558get_nodenames(N, T, Acc) -> 559 {A, B, C} = now(), 560 get_nodenames(N-1, T, [list_to_atom(atom_to_list(?MODULE) 561 ++ "-" 562 ++ atom_to_list(T) 563 ++ "-" 564 ++ integer_to_list(A) 565 ++ "-" 566 ++ integer_to_list(B) 567 ++ "-" 568 ++ integer_to_list(C)) | Acc]). 569 570start_node(TestCase) -> 571 [Name] = get_nodenames(1, TestCase), 572 Pa = filename:dirname(code:which(?MODULE)), 573 test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]). 574 575stop_node(Node) -> 576 true = test_server:stop_node(Node). 577 578run_fun(Fun) -> 579 Fun(). 580