anchor.diff:  
   -spec transaction_test_() -> term().
   transaction_test_() ->
  +    Tests = [client_invite_ok, 
  +             client_invite_err, 
  +             client_invite_timeout],
  +    specs(Tests).
  +
  +%% @doc
  +%% Generates EUnit specification for given tests. Each test is given
  +%% as function name (atom).
  +%% Could be used like:
  +%% eunit:test(sip_transaction_test:test_([client_invite_ok]))
  +%% @end
  +-spec specs([atom()]) -> term().
  +specs(Tests) ->
  +    Transports = [tcp, udp],
  +    TestFuns = lists:map(fun (Test) -> fun(T) -> sip_transaction_test:Test(T) end end, Tests),
  +    {foreach, fun setup/0, fun cleanup/1, sip_test:with_timeout(for_transports(TestFuns, Transports), 60)}.
  +
  +setup() ->
       % Listen on 15060
       Cfg = sip_config:from_options([{udp, [15060]}, {tcp, [15060]}, {router, undefined}]),
  -    Setup =
  -        fun () -> {ok, Pid} = sip_transaction_sup:start_link(Cfg),
  -                  % Mock transport layer calls
  -                  meck:new(sip_transport, [passthrough]),
  -                  SendRequest = fun (Conn, To, Msg) ->
  -                                         ?MODULE ! {tp, Conn, {request, To, Msg}},
  -                                         {ok, Conn}
  -                                end,
  -                  SendResponse = fun (Conn, Msg) ->
  -                                          ?MODULE ! {tp, Conn, {response, Msg}},
  -                                          {ok, Conn}
  -                                 end,
  -                  meck:expect(sip_transport, send_request, SendRequest),
  -                  meck:expect(sip_transport, send_response, SendResponse),
  -                  {Pid}
  +    
  +    {ok, Pid} = sip_transaction_sup:start_link(Cfg),
  +    % Mock transport layer calls
  +    meck:new(sip_transport, [passthrough]),
  +    SendRequest = fun (Conn, To, Msg) ->
  +                           ?MODULE ! {tp, Conn, {request, To, Msg}},
  +                           {ok, Conn}
  +                  end,
  +    SendResponse = fun (Conn, Msg) ->
  +                            ?MODULE ! {tp, Conn, {response, Msg}},
  +                            {ok, Conn}
  +                   end,
  +    meck:expect(sip_transport, send_request, SendRequest),
  +    meck:expect(sip_transport, send_response, SendResponse),
  +    {Pid}.
  +
  +cleanup({Pid}) ->
  +    meck:unload(sip_transport),
  +    sip_test:shutdown_sup(Pid),
  +    ok.
  +
  +%% Generate list of test functions with single parameter (resource created by setup)
  +%% for every possible combination of test function and transport. Each test function
  +%% from the list accepts single transport parameter.
  +for_transports(Tests, Transports) ->
  +    Fun =
  +        fun (Transport) ->
  +                 ApplyTest = fun(Test) ->
  +                                     fun(_Res) -> Test(Transport) end
  +                             end,
  +                 lists:map(ApplyTest, Tests)
           end,
  -    Cleanup =
  -        fun ({Pid}) ->
  -                 meck:unload(sip_transport),
  -                 sip_test:shutdown_sup(Pid),
  -                 ok
  -        end,
  -    {foreach, Setup, Cleanup,
  -     sip_test:with_timeout([fun(_Res) -> client_invite_ok(udp) end,
  -                            fun(_Res) -> client_invite_ok(tcp) end,
  -                            fun(_Res) -> client_invite_err(udp) end,
  -                            fun(_Res) -> client_invite_err(tcp) end], 60)
  -    }.
  +    lists:flatmap(Fun, Transports).
   
   %% Scenario tested:
   %% - client INVITE transaction is created
  
positive.code: %%% @copyright 2011 Ivan Dubrov
  %%%----------------------------------------------------------------
  -module(sip_transaction_test).
  
  %% Include files
  -include_lib("sip_message.hrl").
  
negative.code:     unregister(?MODULE),
      ok.
  
  %% Scenario tested:
  %% - client INVITE transaction is created
  %% - nothing happens in 32 seconds
  %% - transaction terminates due to the timeout
  client_invite_timeout(Transport)->
      register(?MODULE, self()),
  
      Remote = sip_test:endpoint(Transport),
      Request = sip_test:invite(Transport),
  
      {ok, TxRef} = sip_transaction:start_tx(client, self(), Remote, Request),
      ?assertReceive("Expect first request to be sent by tx layer",
                     {tp, _Conn, {request, Remote, Request}}),
  
      timer:sleep(32000),
  
      ?assertReceive("Expect tx to terminate after timeout",
                     {tx, TxRef, {terminated, timeout}}),
  
      unregister(?MODULE),
      ok.
  
  -endif.