anchor.diff:  
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   %% Flush the message queue and return its messages
  +
   flush() ->
       receive
   	Msg ->
  
positive.code:     end.
  		      
      
  t([Case]) when is_atom(Case) ->
      %% p("t -> entry with"
      %% 	 "~n   [Case]: [~p]", [Case]),
      t(Case);
  t(Case) ->
      %% p("t -> entry with"
      %% 	 "~n   Case: ~p", [Case]),
      process_flag(trap_exit, true),
      MEM = fun() -> case (catch erlang:memory()) of
  			{'EXIT', _} ->
  			    [];
  			Res ->
  			    Res
  		    end
  	  end,
      Alloc1 = alloc_info(),
      Mem1 = MEM(),
      Res  = lists:flatten(t(Case, default_config())),
      Alloc2 = alloc_info(),
      Mem2 = MEM(),
      display_result(Res, Alloc1, Mem1, Alloc2, Mem2),
      Res.
  
  
  groups(Mod) when is_atom(Mod) ->
      try Mod:groups() of
  	Groups when is_list(Groups) ->
  	    Groups;
  	BadGroups ->
  	    exit({bad_groups, Mod, BadGroups})
      catch 
  	_:_ ->
  	    []
      end.
  
  init_suite(Mod, Config) ->
      Mod:init_per_suite(Config).
  
  end_suite(Mod, Config) ->
      Mod:end_per_suite(Config).
  
  init_group(Mod, Group, Config) ->
      Mod:init_per_group(Group, Config).
  
  end_group(Mod, Group, Config) ->
      Mod:init_per_group(Group, Config).
  
  %% This is for sub-SUITEs
  t({_Mod, {NewMod, all}, _Groups}, _Config) when is_atom(NewMod) ->
      %% p("t(all) -> entry with"
      %%   "~n   NewMod: ~p", [NewMod]),
      t(NewMod);
  t({Mod, {group, Name} = Group, Groups}, Config) 
    when is_atom(Mod) andalso is_atom(Name) andalso is_list(Groups) ->
      %% p("t(group) -> entry with"
      %%   "~n   Mod:    ~p"
      %%   "~n   Name:   ~p"
      %%   "~n   Groups: ~p"
      %%   "~n   Config: ~p", [Mod, Name, Groups, Config]),
      case lists:keysearch(Name, 1, Groups) of
  	{value, {Name, _Props, GroupsAndCases}} ->
  	    try init_group(Mod, Name, Config) of
  		Config2 when is_list(Config2) ->
  		    Res = [t({Mod, Case, Groups}, Config2) || 
  			      Case <- GroupsAndCases],
  		    (catch end_group(Mod, Name, Config2)), 
  		    Res;
  		Error ->
  		    io:format(" => group (~w) init failed: ~p~n", 
  			      [Name, Error]),
  		    [{failed, {Mod, Group}, Error}]
  	    catch
  		exit:{skip, SkipReason} ->
  		    io:format(" => skipping group: ~p~n", [SkipReason]),
  		    [{skip, {Mod, Group}, SkipReason, 0}];
  		error:undef ->
  		    [t({Mod, Case, Groups}, Config) || 
  			      Case <- GroupsAndCases];
  		T:E ->
  		    [{failed, {Mod, Group}, {T,E}, 0}]
  	    end;
  	false ->
  	    exit({unknown_group, Mod, Name, Groups})
      end;
  t({Mod, Fun, _}, Config) 
    when is_atom(Mod) andalso is_atom(Fun) ->
      %% p("t -> entry with"
      %%   "~n   Mod:    ~p"
      %%   "~n   Fun:    ~p"
      %%   "~n   Config: ~p", [Mod, Fun, Config]),
      try apply(Mod, Fun, [suite]) of
  	[] ->
  	    io:format("Eval:   ~p:", [{Mod, Fun}]),
  	    Res = eval(Mod, Fun, Config),
  	    {R, _, _, _} = Res,
  	    io:format(" ~p~n", [R]),
  	    Res;
  
  	Cases when is_list(Cases) ->
  	    io:format("Expand: ~p ...~n", [{Mod, Fun}]),
  	    Map = fun(Case) when is_atom(Case) -> {Mod, Case};
  		     (Case) -> Case
  		  end,
  	    t(lists:map(Map, Cases), Config);
  
          Error ->
  	    io:format("Ignoring:   ~p: ~p~n", [{Mod, Fun}, Error]),
  	    [{failed, {Mod, Fun}, Error, 0}]
  
      catch
          error:undef ->
  	    io:format("Undefined:   ~p~n", [{Mod, Fun}]),
  	    [{nyi, {Mod, Fun}, ok, 0}]
  
  	
      end;
  t(Mod, Config) when is_atom(Mod) ->
      %% p("t -> entry with"
      %%   "~n   Mod:    ~p"
      %%   "~n   Config: ~p", [Mod, Config]),    
      %% This is assumed to be a test suite, so we start by calling 
      %% the top test suite function(s) (all/0 and groups/0).
      try Mod:all() of
  	Cases when is_list(Cases) -> 
  	    %% The list may contain atoms (actual test cases) and
  	    %% group-tuples (a tuple naming a group of test cases).
  	    %% A group is defined by the (optional) groups/0 function.
  	    Groups = groups(Mod),
  	    try init_suite(Mod, Config) of
  		Config2 when is_list(Config2) ->
  		    Res = [t({Mod, Case, Groups}, Config2) || Case <- Cases],
  		    (catch end_suite(Mod, Config2)),
  		    Res;
  		Error ->
  		    io:format(" => suite init failed: ~p~n", [Error]),
  		    [{failed, {Mod, init_per_suite}, Error}]
  	    catch 
  		exit:{skip, SkipReason} ->
  		    io:format(" => skipping suite: ~p~n", [SkipReason]),
  		    [{skip, {Mod, init_per_suite}, SkipReason, 0}];
  		error:undef ->
  		    [t({Mod, Case, Groups}, Config) || Case <- Cases];
  		T:E ->
  		    io:format(" => failed suite: ~p~n", [{T,E}]),
  		    [{failed, {Mod, init_per_suite}, {T,E}, 0}]
  	    end;
  
  	Crap ->
  	    Crap
  
      catch
          error:undef ->
  	    io:format("Undefined:   ~p~n", [{Mod, all}]),
  	    [{nyi, {Mod, all}, ok, 0}]
  		    
      end;
  t(Bad, _Config) ->
      [{badarg, Bad, ok, 0}].
  
  eval(Mod, Fun, Config) ->
      TestCase = {?MODULE, Mod, Fun},
      Label = lists:concat(["TEST CASE: ", Fun]),
      megaco:report_event(40, ?MODULE, Mod, Label ++ " started",
  			[TestCase, Config]),
      global:register_name(megaco_test_case_sup, self()),
      Flag = process_flag(trap_exit, true),
      put(megaco_test_server, true),
      Config2 = Mod:init_per_testcase(Fun, Config),
      Pid = spawn_link(fun() -> do_eval(self(), Mod, Fun, Config2) end),
      R = wait_for_evaluator(Pid, Mod, Fun, Config2, []),
      Mod:end_per_testcase(Fun, Config2),
      erase(megaco_test_server),    
      global:unregister_name(megaco_test_case_sup),
      process_flag(trap_exit, Flag),
      R.
  
  -record('REASON', {mod, line, desc}).
  
  wait_for_evaluator(Pid, Mod, Fun, Config, Errors) ->
      wait_for_evaluator(Pid, Mod, Fun, Config, Errors, 0).
  wait_for_evaluator(Pid, Mod, Fun, Config, Errors, AccTime) ->
      %% p("wait_for_evaluator -> "
      %%   "~n   Pid:     ~p"
      %%   "~n   Mod:     ~p"
      %%   "~n   Fun:     ~p"
      %%   "~n   Config:  ~p"
      %%   "~n   Errors:  ~p"
      %%   "~n   AccTime: ~p", 
      %%   [Pid, Mod, Fun, Config, Errors, AccTime]),
      TestCase = {?MODULE, Mod, Fun},
      Label = lists:concat(["TEST CASE: ", Fun]),
      receive
  	{done, Pid, ok, Time} when Errors =:= [] ->
  	    megaco:report_event(40, Mod, ?MODULE, Label ++ " ok",
  				[TestCase, Config]),
  	    {ok, {Mod, Fun}, Errors, Time};
  	{done, Pid, ok, Time} ->
  	    megaco:report_event(40, Mod, ?MODULE, Label ++ " failed",
  				[TestCase, Config]),
  	    {failed, {Mod, Fun}, Errors, Time};
  	{done, Pid, {ok, _}, Time} when Errors =:= [] ->
  	    megaco:report_event(40, Mod, ?MODULE, Label ++ " ok",
  				[TestCase, Config]),
  	    {ok, {Mod, Fun}, Errors, Time};
  	{done, Pid, {ok, _}, Time} ->
  	    megaco:report_event(40, Mod, ?MODULE, Label ++ " failed",
  				[TestCase, Config]),
  	    {failed, {Mod, Fun}, Errors, Time};
  	{done, Pid, Fail, Time} ->
  	    megaco:report_event(20, Mod, ?MODULE, Label ++ " failed",
  				[TestCase, Config, {return, Fail}, Errors]),
  	    {failed, {Mod,Fun}, Fail, Time};
  	{'EXIT', Pid, {skip, Reason}, Time} -> 
  	    megaco:report_event(20, Mod, ?MODULE, Label ++ " skipped",
  				[TestCase, Config, {skip, Reason}]),
  	    {skip, {Mod, Fun}, Errors, Time};
  	{'EXIT', Pid, Reason, Time} -> 
  	    megaco:report_event(20, Mod, ?MODULE, Label ++ " crashed",
  				[TestCase, Config, {'EXIT', Reason}]),
  	    {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors], Time};
  	{fail, Pid, Reason, Time} ->
  	    wait_for_evaluator(Pid, Mod, Fun, Config, 
  			       Errors ++ [Reason], AccTime + Time)
      end.
  
  do_eval(ReplyTo, Mod, Fun, Config) ->
      %% p("do_eval -> "
      %%   "~n   ReplyTo: ~p"
      %%   "~n   Mod:     ~p"
      %%   "~n   Fun:     ~p"
      %%   "~n   Config:  ~p", [ReplyTo, Mod, Fun, Config]),
      display_system_info("before", Mod, Fun),
      T1 = os:timestamp(), 
      try Mod:Fun(Config) of
  	Res ->
  	    %% p("do_eval -> done"
  	    %%   "~n   Res: ~p", [Res]),
  	    T2   = os:timestamp(), 
  	    Time = timer:now_diff(T2, T1), 
  	    display_tc_time(Time),
  	    display_system_info("after", Mod, Fun),
  	    ReplyTo ! {done, self(), Res, Time}
      catch
  	error:undef ->
  	    %% p("do_eval -> error - undef", []),
  	    ReplyTo ! {'EXIT', self(), undef, 0};
  	exit:{skip, Reason} ->
  	    %% p("do_eval -> exit - skipped"
  	    %%   "~n   Reason: ~p", [Reason]),
  	    T2   = os:timestamp(), 
  	    Time = timer:now_diff(T2, T1), 
  	    display_tc_time(Time),
  	    display_system_info("after (skipped)", Mod, Fun),
  	    ReplyTo ! {'EXIT', self(), {skip, Reason}, Time};
  	exit:{suite_failed, Reason} ->
  	    %% p("do_eval -> exit - suite-failed"
  	    %%   "~n   Reason: ~p", [Reason]),
  	    T2   = os:timestamp(), 
  	    Time = timer:now_diff(T2, T1), 
  	    display_tc_time(Time),
  	    display_system_info("after (failed)", Mod, Fun),
  	    ReplyTo ! {done, self(), Reason, Time}
  
      end,
      unlink(ReplyTo),
      exit(shutdown).
  
  
  display_tc_time(Time) ->
      io:format("~n"
  	      "~n*********************************************"
  	      "~n"
  	      "~nTest case completion time: ~.3f sec (~w)"
  	      "~n", [(Time / 1000000), Time]),
      ok.
  
  display_system_info(WhenStr) ->
      display_system_info(WhenStr, undefined, undefined).
  
  
negative.code: 	_ ->
  	    []
      end.
  
  mk_nodes(N) when (N > 0) ->
      mk_nodes(N, []).
  