/** Sends a single invite request and checks whether it arrives normally at the other end. */
 public void testSendRequest() {
   try {
     // create an empty invite request.
     Request invite = createTiInviteRequest(null, null, null);
     Request receivedRequest = null;
     try {
       // Send using TI and collect using RI
       eventCollector.collectRequestEvent(riSipProvider);
       waitForMessage();
       tiSipProvider.sendRequest(invite);
       waitForMessage();
       RequestEvent receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
       assertNotNull("The sent request was not received at the other end!", receivedRequestEvent);
       assertNotNull(
           "The sent request was not received at the other end!",
           receivedRequestEvent.getRequest());
     } catch (TooManyListenersException ex) {
       throw new TckInternalError(
           "The following exception was thrown while trying to add "
               + "a SipListener to an RI SipProvider",
           ex);
     } catch (SipException ex) {
       ex.printStackTrace();
       fail("A SipException exception was thrown while " + "trying to send a request.");
     }
   } catch (Throwable exc) {
     exc.printStackTrace();
     fail(exc.getClass().getName() + ": " + exc.getMessage());
   }
   assertTrue(new Exception().getStackTrace()[0].toString(), true);
 }
  /** Tests sending a request from a ClientTransaction. */
  public void testSendRequest() {
    try {
      Request invite = createTiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      ClientTransaction tran = null;
      try {
        tran = tiSipProvider.getNewClientTransaction(invite);
        eventCollector.collectRequestEvent(riSipProvider);
        tran.sendRequest();
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        assertNotNull("The sent request was not received by the RI!", receivedRequestEvent);
        assertNotNull(
            "The sent request was not received by the RI!", receivedRequestEvent.getRequest());
      } catch (TransactionUnavailableException exc) {
        throw new TiUnexpectedError(
            "A TransactionUnavailableException was thrown while trying to "
                + "create a new client transaction",
            exc);
      } catch (SipException exc) {
        exc.printStackTrace();
        fail("The SipException was thrown while trying to send the request.");
      } catch (TooManyListenersException exc) {
        throw new TckInternalError(
            "A  TooManyListenersException was thrown while trying "
                + "to add a SipListener to an RI SipProvider",
            exc);
      }
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }

    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
  /**
   * Creates an invite request using the Tested Implementation and then tests creating a cancel for
   * the same invite request.
   */
  public void testCreateCancel() {
    try {
      Request invite = createTiInviteRequest(null, null, null);
      ClientTransaction tran = null;
      try {
        tran = tiSipProvider.getNewClientTransaction(invite);
      } catch (TransactionUnavailableException exc) {
        throw new TiUnexpectedError(
            "A TransactionUnavailableException was thrown while trying to "
                + "create a new client transaction",
            exc);
      }
      Request cancel = null;
      try {
        cancel = tran.createCancel();
      } catch (SipException ex) {
        ex.printStackTrace();
        fail("Failed to create cancel request!");
      }
      assertEquals(
          "The created request did not have a CANCEL method.", cancel.getMethod(), Request.CANCEL);
      assertEquals(
          "Request-URIs of the original and the cancel request do not match",
          cancel.getRequestURI(),
          invite.getRequestURI());
      assertEquals(
          "Call-IDs of the original and the cancel request do not match",
          cancel.getHeader(CallIdHeader.NAME),
          invite.getHeader(CallIdHeader.NAME));
      assertEquals(
          "ToHeaders of the original and the cancel request do not match",
          cancel.getHeader(ToHeader.NAME),
          invite.getHeader(ToHeader.NAME));
      assertTrue(
          "The CSeqHeader's sequence number of the original and "
              + "the cancel request do not match",
          ((CSeqHeader) cancel.getHeader(CSeqHeader.NAME)).getSequenceNumber()
              == ((CSeqHeader) invite.getHeader(CSeqHeader.NAME)).getSequenceNumber());
      assertEquals(
          "The CSeqHeader's method of the cancel request was not CANCEL",
          ((CSeqHeader) cancel.getHeader(CSeqHeader.NAME)).getMethod(),
          Request.CANCEL);
      assertTrue(
          "There was no ViaHeader in the cancel request",
          cancel.getHeaders(ViaHeader.NAME).hasNext());
      Iterator cancelVias = cancel.getHeaders(ViaHeader.NAME);
      ViaHeader cancelVia = ((ViaHeader) cancelVias.next());
      ViaHeader inviteVia = ((ViaHeader) invite.getHeaders(ViaHeader.NAME).next());
      assertEquals(
          "ViaHeaders of the original and the cancel request do not match!", cancelVia, inviteVia);
      assertFalse("Cancel request had more than one ViaHeader.", cancelVias.hasNext());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }

    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
  /**
   * Sends a request from the TI, generates a response at the RI side, sends it back and checks
   * whether it arrives at the TI.
   */
  public void testReceiveResponse() {
    try {
      // 1. Create and send the original request

      Request invite = createTiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      try {
        // Send using TI and collect using RI
        eventCollector.collectRequestEvent(riSipProvider);
        tiSipProvider.sendRequest(invite);
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
          throw new TckInternalError("The sent request was not received by the RI!");
      } catch (TooManyListenersException ex) {
        throw new TckInternalError(
            "A TooManyListenersException was thrown while trying to add "
                + "a SipListener to an RI SipProvider.",
            ex);
      } catch (SipException ex) {
        throw new TiUnexpectedError("The TI failed to send the request!", ex);
      }
      Request receivedRequest = receivedRequestEvent.getRequest();
      // 2. Create and send the response
      Response ok = null;
      try {
        ok = riMessageFactory.createResponse(Response.OK, receivedRequest);
        addStatus(receivedRequest, ok);
      } catch (ParseException ex) {
        throw new TckInternalError("Failed to create an OK response!", ex);
      }
      // Send the response using the RI and collect using TI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Error while trying to add riSipProvider");
      }
      try {
        riSipProvider.sendResponse(ok);
      } catch (SipException ex) {
        throw new TckInternalError("Could not send back the response", ex);
      }
      waitForMessage();
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      // 3. Now ... do we like what we got?
      assertNotNull("The TI failed to receive the response!", responseEvent);
      assertNotNull("The TI failed to receive the response!", responseEvent.getResponse());
      assertNull(
          "The TI had implicitly created a client transaction! "
              + "Transactions should only be created explicitly using "
              + "the SipProvider.getNewXxxTransaction() method.",
          responseEvent.getClientTransaction());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
 /**
  * Send a simple invite request from the RI and check whether it is properly delivered by the TI
  * SipProvider
  */
 public void testReceiveRequest() {
   try {
     // create an empty invite request.
     Request invite = createRiInviteRequest(null, null, null);
     RequestEvent receivedRequestEvent = null;
     try {
       // Send using RI and collect using TI
       eventCollector.collectRequestEvent(tiSipProvider);
       riSipProvider.sendRequest(invite);
       waitForMessage();
       receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
       assertNotNull("The sent request was not received at the other end!", receivedRequestEvent);
       assertNotNull(
           "The sent request was not received at the other end!",
           receivedRequestEvent.getRequest());
     } catch (TooManyListenersException ex) {
       // This time adding the listener is (sort of) part of the test
       // so we fail instead of just "throwing on" the exc
       ex.printStackTrace();
       fail(
           "A TooManyListenersException was thrown while trying to add "
               + "a SipListener to a TI SipProvider.");
     } catch (SipException ex) {
       throw new TckInternalError("The RI failed to send the request!", ex);
     }
     // question: should we compare sent and received request?
     // my opinion: finding a discrepancy while comparing requests
     // would most probably mean a parse error and parsing is not what
     // we are currently testing
     // Transaction initiating requests should not have a server transaction
     // associated with them as the application might decide to handle the
     // request statelessly
     assertNull(
         "The Tested Implementation has implicitly created a ServerTransaction "
             + "for the received request. Transactions should only be created "
             + "explicitly using the SipProvider.getNewXxxTransaction() method.",
         receivedRequestEvent.getServerTransaction());
   } catch (Throwable exc) {
     exc.printStackTrace();
     fail(exc.getClass().getName() + ": " + exc.getMessage());
   }
   assertTrue(new Exception().getStackTrace()[0].toString(), true);
 }
 /** Test whether new ClientTransactions are properly created. */
 public void testGetNewClientTransaction() {
   try {
     Request invite = createTiInviteRequest(null, null, null);
     ClientTransaction tran = null;
     try {
       tran = tiSipProvider.getNewClientTransaction(invite);
     } catch (TransactionUnavailableException exc) {
       exc.printStackTrace();
       fail(
           "A TransactionUnavailableException was thrown while trying to "
               + "create a new client transaction");
     }
     assertNotNull(
         "A null ClientTransaction was returned by SipProvider." + "getNewClientTransaction().",
         tran);
     String tranBranch = tran.getBranchId();
     String reqBranch = ((ViaHeader) invite.getHeader(ViaHeader.NAME)).getBranch();
     assertEquals(
         "The newly created transaction did not have the same "
             + "branch id as the request that created it",
         tranBranch,
         reqBranch);
     assertNotNull(
         "The newly created transaction returned a null Dialog. "
             + "Please check the docs on Transaction.getDialog()",
         tran.getDialog());
     assertNotNull(
         "The transaction's getRequest() method returned a null Request ", tran.getRequest());
     assertEquals(
         "The transaction's getRequest() method returned a Request "
             + "that did not match the one that we used to create it!",
         tran.getRequest(),
         invite);
   } catch (Throwable exc) {
     exc.printStackTrace();
     fail(exc.getClass().getName() + ": " + exc.getMessage());
   }
   assertTrue(new Exception().getStackTrace()[0].toString(), true);
 }
  /** Tests creating of ACK requests. */
  public void testCreateAck() {
    try {
      // 1. Create and send the original request

      Request invite = createTiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      ClientTransaction tran = null;
      try {
        tran = tiSipProvider.getNewClientTransaction(invite);
        eventCollector.collectRequestEvent(riSipProvider);
        tran.sendRequest();
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
          throw new TiUnexpectedError("The sent request was not received by the RI!");
      } catch (TooManyListenersException ex) {
        throw new TckInternalError(
            "A TooManyListenersException was thrown while trying to add "
                + "a SipListener to an RI SipProvider.",
            ex);
      } catch (SipException ex) {
        throw new TiUnexpectedError("The TI failed to send the request!", ex);
      }
      Request receivedRequest = receivedRequestEvent.getRequest();
      // 2. Create and send the response
      Response ok = null;
      try {
        ok = riMessageFactory.createResponse(Response.OK, receivedRequest);
      } catch (ParseException ex) {
        throw new TckInternalError("Failed to create an OK response!", ex);
      }
      // Send the response using the RI and collect using TI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Error while trying to add riSipProvider");
      }
      try {
        riSipProvider.sendResponse(ok);
      } catch (SipException ex) {
        throw new TckInternalError("Could not send back the response", ex);
      }
      waitForMessage();
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      // 3. Now let's create the ack
      if (responseEvent == null || responseEvent.getResponse() == null)
        throw new TiUnexpectedError("The TI failed to receive the response!");
      if (responseEvent.getClientTransaction() != tran)
        throw new TiUnexpectedError(
            "The TI has associated a new ClientTransaction to a response "
                + "instead of using existing one!");
      Request ack = null;
      try {
        ack = tran.createAck();
      } catch (SipException ex) {
        ex.printStackTrace();
        fail("A SipException was thrown while creating an ack request");
      }
      assertNotNull("ClientTransaction.createAck returned null!", ack);
      assertEquals(
          "The created request did not have a CANCEL method.", ack.getMethod(), Request.ACK);
      assertEquals(
          "Request-URIs of the original and the ack request do not match",
          ack.getRequestURI(),
          invite.getRequestURI());
      assertEquals(
          "Call-IDs of the original and the ack request do not match",
          ack.getHeader(CallIdHeader.NAME),
          invite.getHeader(CallIdHeader.NAME));
      assertEquals(
          "ToHeaders of the original and the ack request do not match",
          ack.getHeader(ToHeader.NAME),
          invite.getHeader(ToHeader.NAME));
      assertTrue(
          "The CSeqHeader's sequence number of the original and " + "the ack request do not match",
          ((CSeqHeader) ack.getHeader(CSeqHeader.NAME)).getSequenceNumber()
              == ((CSeqHeader) invite.getHeader(CSeqHeader.NAME)).getSequenceNumber());
      assertEquals(
          "The CSeqHeader's method of the ack request was not ACK",
          ((CSeqHeader) ack.getHeader(CSeqHeader.NAME)).getMethod(),
          Request.ACK);
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }

    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
 /**
  * Sends a request from the RI and tests whether the tested implementation properly creates a
  * ServerTransaction.
  */
 public void testGetNewServerTransaction() {
   try {
     Request invite = createRiInviteRequest(null, null, null);
     ServerTransaction tran = null;
     RequestEvent receivedRequestEvent = null;
     try {
       // Send using RI and collect using TI
       eventCollector.collectRequestEvent(tiSipProvider);
       riSipProvider.sendRequest(invite);
       waitForMessage();
       receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
       if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
         throw new TiUnexpectedError("The sent request was not received by the RI!");
     } catch (TooManyListenersException ex) {
       throw new TiUnexpectedError(
           "A TooManyListenersException was thrown while trying to add "
               + "a SipListener to a TI SipProvider.",
           ex);
     } catch (SipException ex) {
       throw new TckInternalError("The RI failed to send the request!", ex);
     }
     try {
       tran = tiSipProvider.getNewServerTransaction(invite);
     } catch (TransactionUnavailableException exc) {
       exc.printStackTrace();
       fail(
           "A TransactionUnavailableException was thrown while trying to "
               + "create a new client transaction");
     } catch (TransactionAlreadyExistsException exc) {
       exc.printStackTrace();
       fail(
           "A TransactionAlreadyExistsException was thrown while trying to "
               + "create a new server transaction");
     }
     assertNotNull(
         "A null ServerTransaction was returned by SipProvider." + "getNewServerTransaction().",
         tran);
     String tranBranch = tran.getBranchId();
     String reqBranch = ((ViaHeader) invite.getHeader(ViaHeader.NAME)).getBranch();
     assertEquals(
         "The newly created transaction did not have the same "
             + "branch id as the request that created it!",
         tranBranch,
         reqBranch);
     assertNotNull(
         "The newly created transaction returned a null Dialog. "
             + "Please check the docs on Transaction.getDialog()",
         tran.getDialog());
     assertNotNull(
         "The transaction's getRequest() method returned a null Request ", tran.getRequest());
     assertEquals(
         "The transaction's getRequest() method returned a Request "
             + "that did not match the one that we used to create it!",
         tran.getRequest(),
         invite);
   } catch (Throwable exc) {
     exc.printStackTrace();
     fail(exc.getClass().getName() + ": " + exc.getMessage());
   }
   assertTrue(new Exception().getStackTrace()[0].toString(), true);
 }
  /**
   * Sends a request from the RI, generates a response at the TI side, sends it back and checks
   * whether it arrives at the RI.
   */
  public void testSendResponse() {
    try {
      // 1. Create and send the original request

      Request invite = createRiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      try {
        // Send using RI and collect using TI
        eventCollector.collectRequestEvent(tiSipProvider);
        riSipProvider.sendRequest(invite);
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
          throw new TiUnexpectedError("The sent request was not received by the RI!");
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError(
            "A TooManyListenersException was thrown while trying to add "
                + "a SipListener to a TI SipProvider.",
            ex);
      } catch (SipException ex) {
        throw new TckInternalError("The RI failed to send the request!", ex);
      }
      Request receivedRequest = receivedRequestEvent.getRequest();
      // 2. Create and send the response
      // Create an ok response. We are not testing the message factory so let's
      // not leave it a chance to mess something up and specify the response
      // as completely as possible.
      List via = new LinkedList();
      via.add(receivedRequest.getHeader(ViaHeader.NAME));
      Response ok = null;
      try {
        ok =
            tiMessageFactory.createResponse(
                Response.OK,
                (CallIdHeader) receivedRequest.getHeader(CallIdHeader.NAME),
                (CSeqHeader) receivedRequest.getHeader(CSeqHeader.NAME),
                (FromHeader) receivedRequest.getHeader(FromHeader.NAME),
                (ToHeader) receivedRequest.getHeader(ToHeader.NAME),
                via,
                (MaxForwardsHeader) receivedRequest.getHeader(MaxForwardsHeader.NAME));
        addStatus(receivedRequest, ok);
      } catch (ParseException ex) {
        throw new TiUnexpectedError("Failed to create an OK response!", ex);
      }
      // Send the response using the TI and collect using RI
      try {
        eventCollector.collectResponseEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Error while trying to add riSipProvider");
      }
      try {
        tiSipProvider.sendResponse(ok);
      } catch (SipException ex) {
        ex.printStackTrace();
        fail("A SipException occurred while trying to send an ok response.");
      }
      waitForMessage();
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull("The sent response was not received by the RI!", responseEvent);
      assertNotNull("The sent response was not received by the RI!", responseEvent.getResponse());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
  /**
   * Tries to steer a TI client transaction through the following scenario Calling-->Terminated.
   * Apart from state transitions, we also test, retransmissions and proper hiding/passing of
   * messages to the TU.
   */
  public void testCallingTerminatedScenario() {
    try {
      Request invite = createTiInviteRequest(null, null, null);
      ClientTransaction tran = null;
      try {
        eventCollector.collectRequestEvent(riSipProvider);
        tran = tiSipProvider.getNewClientTransaction(invite);
        tran.sendRequest();
      } catch (SipException ex) {
        throw new TiUnexpectedError("A SipExceptionOccurred while trying to send request!", ex);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      waitForMessage();
      RequestEvent inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      if (inviteReceivedEvent == null || inviteReceivedEvent.getRequest() == null)
        throw new TiUnexpectedError("The invite request was not received by the RI!");
      // At this point the ClientTransaction should be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Check Request retransmission
      try {
        eventCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      // Wait for the retransmission timer to fire if it had not already
      // done so.
      if (tran.getRetransmitTimer() > MESSAGES_ARRIVE_FOR)
        sleep((long) tran.getRetransmitTimer() - MESSAGES_ARRIVE_FOR); // subtract
      // the
      // time
      // we
      // waited
      // for
      // the
      // invite
      // Wait for the retransmitted request to arrive
      waitForMessage();
      inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent);
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent.getRequest());
      assertEquals(Request.INVITE, inviteReceivedEvent.getRequest().getMethod());
      // At this point the ClientTransaction should STILL be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Send a 200 OK (final) response from the RI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // The OK response shouldn't trigger any ACKs so let's register
      // a listener with the RI to verify whether that is the case
      SipEventCollector ackCollector = new SipEventCollector();
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      Response ok = null;
      try {
        ok = riMessageFactory.createResponse(Response.OK, inviteReceivedEvent.getRequest());
        addStatus(inviteReceivedEvent.getRequest(), ok);

        // JvB: MUST add Contact too!
        ContactHeader contact =
            riHeaderFactory.createContactHeader(((ToHeader) ok.getHeader("To")).getAddress());
        ok.addHeader(contact);
        // end JvB

        riSipProvider.sendResponse(ok);
      } catch (Throwable ex) {
        throw new TckInternalError("The TCK could not send an OK response back to the TI", ex);
      }
      waitForMessage();
      // Analyze the OK response and Tran state back at the TI
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull(
          "The Tested Implementation did not pass a 200 OK response to the TU!", responseEvent);
      assertNotNull(
          "The Tested Implementation did not pass a 200 OK response to the TU!",
          responseEvent.getResponse());
      assertSame(
          "The OK response was not associated with the right transaction",
          tran,
          responseEvent.getClientTransaction());
      assertSame(
          "A response different from OK was passed to the TU",
          tran,
          responseEvent.getClientTransaction());
      assertEquals(
          "The ClientTransaction did not pass in the TERMINATED state after "
              + "receiving 200 final response",
          tran.getState(),
          TransactionState.TERMINATED);
      // check whether the ackCollector has caught any fish
      RequestEvent ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNull("The TI sent an ACK to an OK (this is TU's job)!", ackReceivedEvent);
      // Now let's retransmit the final response and see that it is
      // passed to the TU (again no ACKs should be sent by the TI)
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // go fish the ack
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      try {
        riSipProvider.sendResponse((Response) ok.clone());
      } catch (Throwable ex) {
        throw new TckInternalError("The TCK could not send an OK response back to the TI", ex);
      }
      waitForMessage();
      // Did we get the 2nd OK?
      responseEvent = eventCollector.extractCollectedResponseEvent();
      /*
       * JvB: see previous comment
       *
       * assertNotNull( "The TI did not pass to the TU a retransmitted OK
       * response!", responseEvent); assertNotNull( "The TI did not pass
       * to the TU a retransmitted OK response!",
       * responseEvent.getResponse()); assertTrue( "The TI passed to the
       * TU a bad response!",
       * responseEvent.getResponse().getStatusCode()==Response.OK);
       */
      // JvB: TBD
      // assertNull( "The TI should filter the retransmitted OK response",
      // responseEvent );

      // We must still be in the terminated state.
      assertEquals(
          "The ClientTransaction mysteriously left the TERMINATED state!",
          tran.getState(),
          TransactionState.TERMINATED);
      // check whether the ackCollector has caught any fish
      ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNull(
          "The TI sent an ACK request to the second OK response "
              + "(OK acks are TU's responsibility)!",
          ackReceivedEvent);
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
  /**
   * Tries to steer a TI client transaction through the following scenario
   * Calling-->Completed-->Terminated. Apart from state transitions, we also test, retransmissions
   * and proper hiding/passing of messages to the TU.
   */
  public void testCallingCompletedTerminatedScenario() {
    try {
      Request invite = createTiInviteRequest(null, null, null);

      // JvB: test
      // ((MessageExt) invite).getFirstViaHeader().setParameter( "rport",
      // null );

      ClientTransaction tran = null;
      try {
        eventCollector.collectRequestEvent(riSipProvider);
        tran = tiSipProvider.getNewClientTransaction(invite);
        tran.sendRequest();
      } catch (SipException ex) {
        throw new TiUnexpectedError("A SipExceptionOccurred while trying to send request!", ex);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      waitForMessage();
      RequestEvent inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      if (inviteReceivedEvent == null || inviteReceivedEvent.getRequest() == null)
        throw new TiUnexpectedError("The invite request was not received by the RI!");
      // At this point the ClientTransaction should be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Check Request retransmission
      try {
        eventCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      // Wait for the retransmission timer to fire if it had not already
      // done so.
      if (tran.getRetransmitTimer() > MESSAGES_ARRIVE_FOR)
        sleep((long) tran.getRetransmitTimer() - MESSAGES_ARRIVE_FOR); // subtract
      // the
      // time
      // we
      // waited
      // for
      // the
      // invite
      // Wait for the retransmitted request to arrive
      waitForMessage();
      inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent);
      assertNotNull("The invite request was not retransmitted!", inviteReceivedEvent.getRequest());
      assertEquals(Request.INVITE, inviteReceivedEvent.getRequest().getMethod());
      // At this point the ClientTransaction should STILL be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());
      // Send a 486 BUSY HERE (final) response from the RI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // The BUSY_HERE response should trigger some ACKs so let's register
      // a listener with the RI
      SipEventCollector ackCollector = new SipEventCollector();
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      Response busyHere = null;
      try {
        busyHere =
            riMessageFactory.createResponse(Response.BUSY_HERE, inviteReceivedEvent.getRequest());
        addStatus(inviteReceivedEvent.getRequest(), busyHere);

        // JvB: set to-tag, check it against the ACK generated
        ((ToHeader) busyHere.getHeader("to")).setTag("ack-to-test");

        riSipProvider.sendResponse((Response) busyHere.clone());
      } catch (Throwable ex) {
        throw new TckInternalError(
            "The TCK could not send a BUSY HERE response back to the TI", ex);
      }
      waitForMessage();
      // Analyze the BUSY_HERE response and Tran state back at the TI
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull(
          "The Tested Implementation did not pass a 300-699 response to the TU!", responseEvent);
      assertNotNull(
          "The Tested Implementation did not pass a 300-699 response to the TU!",
          responseEvent.getResponse());
      assertSame(
          "The BUSY_HERE response was not associated with the right transaction",
          tran,
          responseEvent.getClientTransaction());
      assertSame(
          "A response different from BUSY_HERE was passed to the TU",
          tran,
          responseEvent.getClientTransaction());
      assertEquals(
          "The ClientTransaction did not pass in the COMPLETED state after "
              + "receiving 300-699 final response",
          tran.getState(),
          TransactionState.COMPLETED);
      // check whether the ackCollector has caught any fish
      RequestEvent ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNotNull("The TI did not send an ACK request", ackReceivedEvent);
      assertNotNull("The TI did not send an ACK request", ackReceivedEvent.getRequest());
      assertEquals(Request.ACK, ackReceivedEvent.getRequest().getMethod());
      // Try to kill remaining ACK retransmissions
      // TODO this may not always work .. should give it a specific
      // timeout value
      waitForMessage();
      // Now let's retransmit the final response. This time it shouldn't
      // be
      // passed to the TU but an ACK should still be sent
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      // go fish the ack
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      try {
        riSipProvider.sendResponse((Response) busyHere.clone());
      } catch (Throwable ex) {
        throw new TckInternalError(
            "The TCK could not send a BUSY HERE response back to the TI", ex);
      }
      waitForMessage();
      // The TU shouldn't see the retransmitted BUSY_HERE response
      responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNull(
          "The Tested Implementation passed a retransmitted 300-699 response "
              + "to the TU instead of just silently acknowledging it!",
          responseEvent);
      // We must still be in the completed state.
      assertEquals(
          "The ClientTransaction did not stay long enough in the COMPLETED " + "state.",
          tran.getState(),
          TransactionState.COMPLETED);
      // check whether the ackCollector has caught any fish
      ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNotNull("The TI did not send an ACK request to the second response", ackReceivedEvent);
      assertNotNull(
          "The TI did not send an ACK request to the second response",
          ackReceivedEvent.getRequest());

      assertEquals(Request.ACK, ackReceivedEvent.getRequest().getMethod());

      // JvB: verify to tag
      assertEquals(
          "The To header field in the ACK MUST equal the To header field "
              + " in the response being acknowledged",
          "ack-to-test",
          ((ToHeader) ackReceivedEvent.getRequest().getHeader("to")).getTag());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);

    // Unfortunately we can't assert the TERMINATED state as timerD
    // is not exported by JAIN SIP

  }
  /**
   * JvB: Tests transmission of an INVITE followed by CANCELlation of that request -> INVITE <- 100
   * -> CANCEL <- OK <- 487 -> ACK
   *
   * <p>Note: for 1.2 it is impossible to manually set the top via branch to something not
   * RFC3261-compliant
   */
  private void doCancelTest(boolean rfc3261Compliant) {
    try {
      Request invite = createTiInviteRequest(null, null, null);
      ClientTransaction tran = null;
      try {
        eventCollector.collectRequestEvent(riSipProvider);

        // This call overwrites any branch we set
        tran = tiSipProvider.getNewClientTransaction(invite);

        // And this call too
        tran.sendRequest();
      } catch (SipException ex) {
        throw new TiUnexpectedError("A SipExceptionOccurred while trying to send request!", ex);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }
      waitForMessage();
      RequestEvent inviteReceivedEvent = eventCollector.extractCollectedRequestEvent();

      if (inviteReceivedEvent == null || inviteReceivedEvent.getRequest() == null)
        throw new TiUnexpectedError("The invite request was not received by the RI!");

      // At this point the ClientTransaction should be CALLING!
      assertEquals(TransactionState.CALLING, tran.getState());

      // Send a TRYING response
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      try {
        Response resp =
            riMessageFactory.createResponse(Response.TRYING, inviteReceivedEvent.getRequest());
        addStatus(inviteReceivedEvent.getRequest(), resp);
        riSipProvider.sendResponse(resp);
      } catch (Throwable ex) {
        throw new TckInternalError("The TCK could not send a trying response back to the TI", ex);
      }

      waitForMessage();
      // Analyze the TRYING response and Tran state back at the TI
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull(
          "The Tested Implementation did not pass a 1xx response to the TU!", responseEvent);
      assertNotNull(
          "The Tested Implementation did not pass a 1xx response to the TU!",
          responseEvent.getResponse());
      assertTrue(
          "A response different from TYING was passed to the TU!",
          responseEvent.getResponse().getStatusCode() == Response.TRYING);
      assertSame(
          "The TRYING response was not associated with the right transaction.",
          tran,
          responseEvent.getClientTransaction());
      // verify the the tran state is now PROCEEDING
      assertEquals(
          "The ClientTransaction did not pass in the PROCEEDING state after "
              + "receiving 1xx provisional response",
          tran.getState(),
          TransactionState.PROCEEDING);

      // Send a CANCEL from the TI
      Request tiCancel = tran.createCancel();

      /*
       * this works, but since we cannot patch the INVITE the test fails
       * if (!rfc3261Compliant) { ((ViaHeader)
       * tiCancel.getHeader("Via")).setBranch( "xxx" ); // Not allowed by
       * RI // ((FromHeader) tiCancel.getHeader("From")).setTag( "" ); }
       */

      ClientTransaction tiCancelTrans;
      try {
        eventCollector.collectRequestEvent(riSipProvider);
        tiCancelTrans = tiSipProvider.getNewClientTransaction(tiCancel);
        tiCancelTrans.sendRequest();
      } catch (SipException ex) {
        throw new TiUnexpectedError("A SipExceptionOccurred while trying to send CANCEL!", ex);
      }
      waitForMessage();
      RequestEvent cancelReceivedEvent = eventCollector.extractCollectedRequestEvent();
      if (cancelReceivedEvent == null || cancelReceivedEvent.getRequest() == null)
        throw new TiUnexpectedError("The CANCEL request was not received by the RI!");

      // Send 200 OK to the CANCEL
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      Response riCancelOk = null;
      try {
        riCancelOk = riMessageFactory.createResponse(Response.OK, cancelReceivedEvent.getRequest());
        addStatus(cancelReceivedEvent.getRequest(), riCancelOk);
        riSipProvider.sendResponse(riCancelOk);
      } catch (Throwable ex) {
        throw new TckInternalError(
            "The TCK could not send a CANCEL OK response back to the TI", ex);
      }
      waitForMessage();

      // Analyze the OK response and Tran state back at the TI
      responseEvent = eventCollector.extractCollectedResponseEvent();
      if (responseEvent == null || responseEvent.getResponse() == null) {
        throw new TiUnexpectedError("The CANCEL OK response was not received by the TI!");
      }

      // Send 487 to the INVITE, expect ACK
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Failed to register a SipListener with TI", ex);
      }
      SipEventCollector ackCollector = new SipEventCollector();
      try {
        ackCollector.collectRequestEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Failed to regiest a SipListener with an RI SipProvider", ex);
      }

      Response riInviteTerminated = null;
      try {
        riInviteTerminated =
            riMessageFactory.createResponse(
                Response.REQUEST_TERMINATED, inviteReceivedEvent.getRequest());
        addStatus(inviteReceivedEvent.getRequest(), riInviteTerminated);
        riSipProvider.sendResponse(riInviteTerminated);
      } catch (Throwable ex) {
        throw new TckInternalError(
            "The TCK could not send a INVITE 487 response back to the TI", ex);
      }
      waitForMessage();

      // Analyze the REQUEST_TERMINATED response and Tran state back at
      // the TI
      responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull(
          "The Tested Implementation did not pass a 300-699 response to the TU!", responseEvent);
      assertNotNull(
          "The Tested Implementation did not pass a 300-699 response to the TU!",
          responseEvent.getResponse());
      assertSame(
          "The 487 response was not associated with the right transaction",
          tran,
          responseEvent.getClientTransaction());
      assertEquals(
          "A response different from 487 was passed to the TU",
          Response.REQUEST_TERMINATED,
          responseEvent.getResponse().getStatusCode());
      assertEquals(
          "The ClientTransaction did not pass in the COMPLETED state after "
              + "receiving 300-699 final response",
          tran.getState(),
          TransactionState.COMPLETED);
      // check whether the ackCollector has caught any fish
      RequestEvent ackReceivedEvent = ackCollector.extractCollectedRequestEvent();
      assertNotNull("The TI did not send an ACK request event", ackReceivedEvent);
      assertNotNull("The TI did not send an ACK request", ackReceivedEvent.getRequest());
      assertEquals(Request.ACK, ackReceivedEvent.getRequest().getMethod());

      // Try to kill remaining ACK retransmissions?
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);

    // Unfortunately we can't assert the TERMINATED state as timerK timerD
    // is not exported by JAIN SIP
  }
Beispiel #13
0
 /**
  * Log an exception.
  *
  * @param ex the exception that we are to log.
  */
 public void logException(Throwable ex) {
   logger.warn("Exception in the JAIN-SIP stack: " + ex.getMessage());
   if (logger.isInfoEnabled()) logger.info("JAIN-SIP exception stack trace is", ex);
 }