1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2010-2011. 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(receive_SUITE).
   21: 
   22: %% Tests receive after.
   23: 
   24: -include_lib("test_server/include/test_server.hrl").
   25: 
   26: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   27: 	 init_per_group/2,end_per_group/2,
   28: 	 call_with_huge_message_queue/1,receive_in_between/1]).
   29: 
   30: -export([init_per_testcase/2,end_per_testcase/2]).
   31: 
   32: suite() -> [{ct_hooks,[ts_install_cth]}].
   33: 
   34: all() -> 
   35:     [call_with_huge_message_queue, receive_in_between].
   36: 
   37: groups() -> 
   38:     [].
   39: 
   40: init_per_suite(Config) ->
   41:     Config.
   42: 
   43: end_per_suite(_Config) ->
   44:     ok.
   45: 
   46: init_per_group(_GroupName, Config) ->
   47:     Config.
   48: 
   49: end_per_group(_GroupName, Config) ->
   50:     Config.
   51: 
   52: 
   53: init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
   54:     Dog=?t:timetrap(?t:minutes(3)),
   55:     [{watchdog, Dog}|Config].
   56: 
   57: end_per_testcase(_Func, Config) ->
   58:     Dog=?config(watchdog, Config),
   59:     ?t:timetrap_cancel(Dog).
   60: 
   61: call_with_huge_message_queue(Config) when is_list(Config) ->
   62:     Pid = spawn_link(fun echo_loop/0),
   63: 
   64:     {Time,ok} = tc(fun() -> calls(10, Pid) end),
   65: 
   66:     [self() ! {msg,N} || N <- lists:seq(1, 500000)],
   67:     erlang:garbage_collect(),
   68:     {NewTime1,ok} = tc(fun() -> calls(10, Pid) end),
   69:     {NewTime2,ok} = tc(fun() -> calls(10, Pid) end),
   70: 
   71:     io:format("Time for empty message queue: ~p", [Time]),
   72:     io:format("Time1 for huge message queue: ~p", [NewTime1]),
   73:     io:format("Time2 for huge message queue: ~p", [NewTime2]),
   74: 
   75:     case hd(lists:sort([(NewTime1+1) / (Time+1), (NewTime2+1) / (Time+1)])) of
   76: 	Q when Q < 10 ->
   77: 	    ok;
   78: 	Q ->
   79: 	    io:format("Best Q = ~p", [Q]),
   80: 	    ?t:fail()
   81:     end,
   82:     ok.
   83: 
   84: calls(0, _) -> ok;
   85: calls(N, Pid) ->
   86:     {ok,{ultimate_answer,42}} = call(Pid, {ultimate_answer,42}),
   87:     calls(N-1, Pid).
   88: 
   89: call(Pid, Msg) ->
   90:     Mref = erlang:monitor(process, Pid),
   91:     Pid ! {Mref,{self(),Msg}},
   92:     receive
   93: 	{Mref, Reply} ->
   94: 	    erlang:demonitor(Mref, [flush]),
   95: 	    {ok, Reply};
   96: 	{'DOWN', Mref, _, _, Reason} ->
   97: 	    exit(Reason)
   98:     end.
   99: 
  100: receive_in_between(Config) when is_list(Config) ->
  101:     Pid = spawn_link(fun echo_loop/0),
  102:     [{ok,{a,b}} = call2(Pid, {a,b}) || _ <- lists:seq(1, 100000)],
  103:     ok.
  104: 
  105: call2(Pid, Msg) ->
  106:     self() ! dummy,
  107:     Mref = erlang:monitor(process, Pid),
  108:     Pid ! {Mref,{self(),Msg}},
  109:     receive_one(),
  110:     receive
  111: 	{Mref,Reply} ->
  112: 	    erlang:demonitor(Mref, [flush]),
  113: 	    {ok,Reply};
  114: 	{'DOWN',Mref,_,_,Reason} ->
  115: 	    exit(Reason)
  116:     end.
  117: 
  118: receive_one() ->
  119:     receive
  120: 	dummy -> ok
  121:     end.
  122: 
  123: %%%
  124: %%% Common helpers.
  125: %%%
  126: 
  127: echo_loop() ->
  128:     receive
  129: 	{Ref,{Pid,Msg}} ->
  130: 	    Pid ! {Ref,Msg},
  131: 	    echo_loop()
  132:     end.
  133: 
  134: tc(Fun) ->
  135:     timer:tc(erlang, apply, [Fun,[]]).