1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2005-2012. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(run_erl_SUITE).
   21: 
   22: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   23: 	 init_per_group/2,end_per_group/2,
   24: 	 init_per_testcase/2,end_per_testcase/2,
   25: 	 basic/1,heavy/1,heavier/1,defunct/1]).
   26: -export([ping_me_back/1]).
   27: 
   28: -include_lib("test_server/include/test_server.hrl").
   29: 
   30: init_per_testcase(_Case, Config) ->
   31:     Dog = ?t:timetrap(?t:minutes(2)),
   32:     [{watchdog, Dog}|Config].
   33: 
   34: end_per_testcase(_Case, Config) ->
   35:     Dog = ?config(watchdog, Config),
   36:     ?t:timetrap_cancel(Dog),
   37:     ok.
   38: 
   39: suite() -> [{ct_hooks,[ts_install_cth]}].
   40: 
   41: all() -> 
   42:     [basic, heavy, heavier, defunct].
   43: 
   44: groups() -> 
   45:     [].
   46: 
   47: init_per_suite(Config) ->
   48:     Config.
   49: 
   50: end_per_suite(_Config) ->
   51:     ok.
   52: 
   53: init_per_group(_GroupName, Config) ->
   54:     Config.
   55: 
   56: end_per_group(_GroupName, Config) ->
   57:     Config.
   58: 
   59: 
   60: basic(Config) when is_list(Config) ->
   61:     case os:type() of
   62: 	{unix,_} -> basic_1(Config);
   63: 	_ -> {skip,"Not Unix"}
   64:     end.
   65: 
   66: basic_1(Config) ->
   67:     ?line {Node,Pipe} = do_run_erl(Config, "basic"),
   68: 
   69:     ?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
   70:     ?line erlang:port_command(ToErl, "halt().\r\n"),
   71: 
   72:     receive
   73: 	{nodedown,Node} ->
   74: 	    ?line io:format("Down: ~p\n", [Node])
   75:     after 10000 ->
   76: 	    ?line ?t:fail()
   77:     end,
   78: 
   79:     ok.
   80: 
   81: heavy(Config) when is_list(Config) ->
   82:     case os:type() of
   83: 	{unix,_} -> heavy_1(Config);
   84: 	_ -> {skip,"Not Unix"}
   85:     end.
   86: 
   87: heavy_1(Config) ->
   88:     ?line {Node,Pipe} = do_run_erl(Config, "heavy"),
   89: 
   90:     ?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
   91:     IoFormat = "io:format(\"~s\n\", [lists:duplicate(10000, 10)]).\r\n",
   92:     ?line erlang:port_command(ToErl, IoFormat),
   93:     ?line erlang:port_command(ToErl, IoFormat),
   94:     ?line erlang:port_command(ToErl, IoFormat),
   95:     ?line erlang:port_command(ToErl, "init:stop().\r\n"),
   96:     
   97:     receive
   98: 	{nodedown,Node} ->
   99: 	    ?line io:format("Down: ~p\n", [Node])
  100:     after 10000 ->
  101: 	    ?line ?t:fail()
  102:     end,
  103: 
  104:     ?line case count_new_lines(ToErl, 0) of
  105: 	      Nls when Nls > 30000 ->
  106: 		  ok;
  107: 	      Nls ->
  108: 		  ?line io:format("new_lines: ~p\n", [Nls]),
  109: 		  ?line ?t:fail()
  110: 	  end.
  111:     
  112: 
  113: ping_me_back([Node]) when is_atom(Node) ->
  114:     net_adm:ping(Node);
  115: ping_me_back([Node]) ->
  116:     net_adm:ping(list_to_atom(Node)).
  117:     
  118: count_new_lines(P, N) ->
  119:     receive
  120: 	{P,{data,S}} ->
  121: 	    count_new_lines(P, count_new_lines_1(S, N))
  122:     after 0 ->
  123: 	    N
  124:     end.
  125: 
  126: count_new_lines_1([$\n|T], N) ->
  127:     count_new_lines_1(T, N+1);
  128: count_new_lines_1([_|T], N) ->
  129:     count_new_lines_1(T, N);
  130: count_new_lines_1([], N) -> N.
  131: 	
  132: heavier(Config) when is_list(Config) ->
  133:     case os:type() of
  134: 	{unix,_} -> heavier_1(Config);
  135: 	_ -> {skip,"Not Unix"}
  136:     end.
  137: 
  138: heavier_1(Config) ->
  139:     ?line {Node,Pipe} = do_run_erl(Config, "heavier"),
  140: 
  141:     ?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
  142:     io:format("ToErl = ~p\n", [ToErl]),
  143:     X = 1,
  144:     Y = 555,
  145:     Z = 42,
  146:     ?line random:seed(X, Y, Z),
  147:     SeedCmd = lists:flatten(io_lib:format("random:seed(~p, ~p, ~p). \r\n",
  148: 					  [X,Y,Z])),
  149:     ?line io:format("~p\n", [SeedCmd]),
  150:     ?line erlang:port_command(ToErl, SeedCmd),
  151: 
  152:     Iter = 1000,
  153:     MaxLen = 2048,
  154: 
  155:     Random = "f(F), "++
  156: 	"F = fun(F,0) -> ok; "++
  157: 	       "(F,N) -> " ++
  158: 	           "io:format(\"\\\"~s\\\"~n\","++
  159: 	                     "[[35|[random:uniform(25)+65 || " ++
  160: 	                     "_ <- lists:seq(1, "++
  161: 	                                "random:uniform("++
  162:                                              integer_to_list(MaxLen)++
  163:                                         "))]]]), "++
  164: 	           "F(F,N-1) "++
  165:              "end,"++ 
  166:         "F(F,"++integer_to_list(Iter)++")."++" \r\n",
  167: 
  168: 
  169:     ?line io:format("~p\n", [Random]),
  170:     ?line erlang:port_command(ToErl, Random),
  171: 
  172:     %% Finish.
  173:     
  174:     ?line erlang:port_command(ToErl, "init:stop().\r\n"),
  175:     ?line receive_all(Iter, ToErl, MaxLen),
  176:     receive
  177: 	{nodedown,Node} ->
  178: 	    ?line io:format("Down: ~p\n", [Node])
  179:     after 10000 ->
  180: 	    ?line c:flush(),
  181: 	    ?line ?t:fail()
  182:     end,
  183: 
  184:     ok.
  185: 
  186: receive_all(Iter, ToErl, MaxLen) ->
  187:     receive_all_1(Iter, [], ToErl, MaxLen).
  188: 
  189: receive_all_1(0, _, _, _) -> ok;
  190: receive_all_1(Iter, Line, ToErl, MaxLen) ->
  191:     NumChars = random:uniform(MaxLen),
  192:     Pattern = [random:uniform(25)+65 || _ <- lists:seq(1, NumChars)],
  193:     receive_all_2(Iter, {NumChars,Pattern}, Line, ToErl, MaxLen).
  194:     
  195: 
  196: receive_all_2(Iter, {NumChars,Pattern}, Line0, ToErl, MaxLen) ->
  197:     case receive_match(Line0, {NumChars,Pattern}) of
  198: 	{match,Line} ->
  199: 	    %%io:format("Match: ~p\n", [Line]),
  200: 	    receive_all_1(Iter-1, Line, ToErl, MaxLen);
  201: 	{nomatch,Line} ->
  202: 	    %%io:format("NoMatch: ~p\n", [Line]),
  203: 	    receive
  204: 		{ToErl,{data,S}} ->
  205: 		    %%io:format("Recv: ~p\n", [S]),
  206: 		    receive_all_2(Iter, {NumChars,Pattern}, Line++S, ToErl, MaxLen)		    
  207: 	    after 10000 ->
  208: 		    io:format("Timeout waiting for\n~p\ngot\n~p\n",
  209: 			      [Pattern, Line]),
  210: 		    ?line ?t:fail()    
  211: 	    end
  212:     end.
  213: 
  214: 
  215: receive_match("\"#"++T, {NumChars,Pattern}) when length(T) >= NumChars ->
  216:     Match = lists:sublist(T, NumChars),
  217:     io:format("match candidate: ~p\n", [Match]),
  218:     Match = Pattern,
  219:     {match,lists:nthtail(NumChars, T)};
  220: receive_match("\"#"++T, _) ->
  221:     {nomatch,"\"#"++T};
  222: receive_match("\""=Line, _) ->
  223:     {nomatch,Line};
  224: receive_match([_|T], Tpl) ->
  225:     receive_match(T, Tpl);
  226: receive_match(Line, _) ->
  227:     {nomatch,Line}.
  228: 
  229: 
  230: defunct(Config) when is_list(Config) ->
  231:     case os:type() of
  232: 	{unix,_} -> defunct_1(Config);
  233: 	_ -> {skip,"Not Unix"}
  234:     end.
  235: 
  236: defunct_1(Config) ->
  237:     case os:find_executable(perl) of
  238: 	false ->
  239: 	    {skip,"No perl found"};
  240: 	Perl ->
  241: 	    defunct_2(Config, Perl)
  242:     end.
  243: 
  244: defunct_2(Config, Perl) ->
  245:     ?line Data = ?config(data_dir, Config),
  246:     ?line RunErlTest = filename:join(Data, "run_erl_test.pl"),
  247:     ?line Defuncter = filename:join(Data, "defuncter.pl"),
  248:     ?line Priv = ?config(priv_dir, Config),
  249:     ?line LogDir = filename:join(Priv, "defunct"),
  250:     ?line ok = file:make_dir(LogDir),
  251:     ?line Pipe = LogDir ++ "/",
  252:     ?line RunErl = os:find_executable(run_erl),
  253:     ?line Cmd = Perl ++ " " ++ RunErlTest ++ " \"" ++ RunErl ++ "\" " ++
  254: 	Defuncter ++ " " ++ Pipe ++ " " ++ LogDir,
  255:     ?line io:format("~p", [Cmd]),
  256:     ?line Res = os:cmd(Cmd),
  257:     ?line io:format("~p\n", [Res]),
  258:     "OK"++_ = Res,
  259:     ok.
  260: 
  261: %%% Utilities.
  262: 
  263: do_run_erl(Config, Case) ->
  264:     ?line Priv = ?config(priv_dir, Config),
  265:     ?line LogDir = filename:join(Priv, Case),
  266:     ?line ok = file:make_dir(LogDir),
  267:     ?line Pipe = LogDir ++ "/",
  268:     ?line NodeName = "run_erl_node_" ++ Case,
  269:     ?line Cmd = "run_erl "++Pipe++" "++LogDir++" \"erl -sname " ++ NodeName ++
  270: 	" -pa " ++ filename:dirname(code:which(?MODULE)) ++
  271: 	" -s " ++ ?MODULE_STRING ++ " ping_me_back " ++
  272: 	atom_to_list(node()) ++ "\"",
  273:     ?line io:format("~p\n", [Cmd]),
  274:     
  275:     ?line net_kernel:monitor_nodes(true),
  276:     ?line open_port({spawn,Cmd}, []),
  277:     ?line [_,Host] = string:tokens(atom_to_list(node()), "@"),
  278:     ?line Node = list_to_atom(NodeName++"@"++Host),
  279: 
  280:     receive
  281: 	{nodeup,Node} ->
  282: 	    ?line io:format("Up: ~p\n", [Node]);
  283: 	Other ->
  284: 	    ?line io:format("Unexpected: ~p\n", [Other]),
  285: 	    ?line ?t:fail()
  286:     after 10000 ->
  287: 	    ?line ?t:fail()
  288:     end,
  289: 
  290:     {Node,Pipe}.