test.tck.msgflow.NonInviteServerTransactionsStateMachineTest Maven / Gradle / Ivy
/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), and others.
* This software is has been contributed to the public domain.
* As a result, a formal license is not needed to use the software.
*
* This software is provided "AS IS."
* NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
*
*/
package test.tck.msgflow;
import junit.framework.*;
import javax.sip.*;
import javax.sip.message.*;
import javax.sip.header.*;
import java.util.*;
import java.text.*;
import test.tck.*;
/**
*
* The test tries to verify that Invite Server Transactions correctly change
* states as specified by the rfc3261. The Reference Implementation is used
* to send requests and a Tested Implementation ServerTransaction's states are
* queried and compared to those in the state machine described in
* section 17.2.1 of rfc3261
*
*
* |Request received
* |pass to TU
* V
* +-----------+
* | |
* | Trying |-------------+
* | | |
* +-----------+ |200-699 from TU
* | |send response
* |1xx from TU |
* |send response |
* | |
* Request V 1xx from TU |
* send response+-----------+send response|
* +--------| |--------+ |
* | | Proceeding| | |
* +------->| |<-------+ |
* +<--------------| | |
* |Trnsprt Err +-----------+ |
* |Inform TU | |
* | | |
* | |200-699 from TU |
* | |send response |
* | Request V |
* | send response+-----------+ |
* | +--------| | |
* | | | Completed |<------------+
* | +------->| |
* +<--------------| |
* |Trnsprt Err +-----------+
* |Inform TU |
* | |Timer J fires
* | |-
* | |
* | V
* | +-----------+
* | | |
* +-------------->| Terminated|
* | |
* +-----------+
*
* Figure 8: non-INVITE server transaction
*
*
*
* @author Emil Ivov
* Network Research Team, Louis Pasteur University, Strasbourg, France.
* This code is in the public domain.
* @version 1.0
*/
public class NonInviteServerTransactionsStateMachineTest
extends MessageFlowHarness {
public NonInviteServerTransactionsStateMachineTest(String name) {
super(name);
}
//==================== tests ==============================
/**
* Tries to steer a TI server transaction through the following scenario
* Trying-->Proceeding-->Completed-->Terminated. Apart from state
* transitions, we also test, retransmissions and proper hiding/passing
* of messages to the TU.
*/
public void testTryingProceedingCompletedScenario() {
try {
Request register = createRiRegisterRequest();
SipEventCollector responseCollector = new SipEventCollector();
//Before Sending the request we should first register a listener with the
//RI that would catch the TRYING response
try {
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
//Send the initial request
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
waitForMessage();
RequestEvent registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
if (registerReceivedEvent == null
|| registerReceivedEvent.getRequest() == null)
throw new TiUnexpectedError("The initial register request was not received by the TI!");
//Let's create the transaction
ServerTransaction tran = null;
try {
tran =
tiSipProvider.getNewServerTransaction(
registerReceivedEvent.getRequest());
} catch (Exception ex) {
ex.printStackTrace();
fail(
ex.getClass().getName()
+ "was thrown while trying to "
+ "create the server transaction");
}
assertNotNull(
"tiSipProvider.getNewServerTransaction() returned null",
tran);
//At this point the ServerTransaction should be TRYING!
assertEquals(TransactionState.TRYING, tran.getState());
//Send a TRYING response
Response trying = null;
try {
trying =
tiMessageFactory.createResponse(
Response.TRYING,
registerReceivedEvent.getRequest());
tran.sendResponse(trying);
} catch (Exception ex) {
throw new TiUnexpectedError(
"Failed to send a TRYING response",
ex);
}
waitForMessage();
//The transaction should now be PROCEEDING
assertEquals(
"The transaction did not pass into the PROCEEDING state "
+ "upon transmission of a 1xx response.",
TransactionState.PROCEEDING,
tran.getState());
ResponseEvent responseEvent =
responseCollector.extractCollectedResponseEvent();
assertNotNull(
"The TRYING response has not been sent by the TI.",
responseEvent);
assertTrue(
"A response different from 100 was sent by the TI",
Response.TRYING == responseEvent.getResponse().getStatusCode());
//Resend the REGISTER and see that the TRYING response is resent
try {
//listen for the Trying response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
//Wait for the REGISTER
waitForMessage();
registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
assertNull(
"Retransmitted REGISTERs should not be passed to the TU",
registerReceivedEvent);
//Wait for a retransmitted TRYING response
waitForMessage();
//Verify whether there was a TRYING response
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"No TRYING response has been resent by the TI upon reception "
+ "of a retransmitted REGISTER request",
responseEvent);
assertTrue(
"A response different from 100 was sent by the TI upon "
+ "reception of a retransmitted REGISTER",
Response.TRYING == responseEvent.getResponse().getStatusCode());
//Create & send RINGING. See that it is properly sent
//and that tran state doesn't change
Response ringing = null;
try {
ringing =
tiMessageFactory.createResponse(
Response.RINGING,
tran.getRequest());
((ToHeader) ringing.getHeader(ToHeader.NAME)).setTag(
Integer.toString(hashCode()));
} catch (ParseException ex) {
throw new TiUnexpectedError(
"A ParseException was thrown while trying to create a ringing "
+ "response using TI",
ex);
}
try {
//listen for the RINGING response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
tran.sendResponse(ringing);
} catch (SipException ex) {
ex.printStackTrace();
fail("The TI failed to send a RINGING response");
}
//The Transaction should still be PROCEEDING
assertEquals(
"The Transaction did not remain PROCEEDING after transmitting a RINGING response",
TransactionState.PROCEEDING,
tran.getState());
//Check whether the RINGING is received by the RI.
waitForMessage();
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"The RINGING response was not received by the RI",
responseEvent);
assertTrue(
"A response different from RINGING was sent by the TI",
Response.RINGING
== responseEvent.getResponse().getStatusCode());
//Resend the REGISTER, see that it is hidden from the TU and see that
//the _RINGING_ response is resent (and not the TRYING)
try {
//listen for the Trying response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
//Wait for the REGISTER
waitForMessage();
registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
assertNull(
"Retransmitted REGISTERs should not be passed to the TU",
registerReceivedEvent);
//Wait for a retransmitted RINGING response
waitForMessage();
//Verify whether there was a RINGING response
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"No RINGING response has been sent by the TI upon reception "
+ "of an REGISTER request",
responseEvent);
assertTrue(
"A response different from RINGING was sent by the TI upon "
+ "reception of a retransmitted REGISTER",
Response.RINGING
== responseEvent.getResponse().getStatusCode());
//We should still be proceeding
assertEquals(
"The server transaction left the PROCEEDING state.",
TransactionState.PROCEEDING,
tran.getState());
//Send 200 - 699 from TU and see the tran goes COMPLETED
Response ok = null;
try {
ok =
tiMessageFactory.createResponse(
Response.OK,
tran.getRequest());
((ToHeader) ok.getHeader(ToHeader.NAME)).setTag(
Integer.toString(hashCode()));
} catch (ParseException ex) {
throw new TiUnexpectedError(
"A ParseException was thrown while trying to create a busy_here "
+ "response using TI",
ex);
}
try {
//listen for the BUSY_HERE response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
tran.sendResponse(ok);
} catch (SipException ex) {
ex.printStackTrace();
fail("The TI failed to send a OK response");
}
//The Transaction should now be COMPLETED
assertEquals(
"The Transaction did not remain COMPLETED after transmitting a BUSY_HERE response",
TransactionState.COMPLETED,
tran.getState());
//Check whether the OK is received by the RI.
waitForMessage();
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"The OK response was not received by the RI",
responseEvent);
assertTrue(
"A response different from OK was sent by the TI",
Response.OK == responseEvent.getResponse().getStatusCode());
//Resend the initial from REGISTER from the RI and see that TI
//resends the 200 - 699 (see that tran state remains COMPLETED)
try {
//listen for the OK response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
//Wait for the REGISTER
waitForMessage();
registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
assertNull(
"Retransmitted REGISTERs should not be passed to the TU",
registerReceivedEvent);
//Wait for a retransmitted OK response
waitForMessage();
//Verify whether there was an OK response
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"No OK response has been sent by the TI upon reception "
+ "of a retransmitted REGISTER request",
responseEvent);
assertTrue(
"A response different from OK was sent by the TI upon "
+ "reception of a retransmitted invite REGISTER",
Response.OK == responseEvent.getResponse().getStatusCode());
//We should still be COMPLETED
assertEquals(
"The server transaction left the COMPLETED state.",
TransactionState.COMPLETED,
tran.getState());
} catch (Throwable exc) {
exc.printStackTrace();
fail(exc.getClass().getName() + ": " + exc.getMessage());
}
assertTrue(new Exception().getStackTrace()[0].toString(), true);
}
/**
* Tries to steer a TI server transaction through the following scenario
* Trying-->Completed. Apart from state
* transitions, we also test, retransmissions and proper hiding/passing
* of messages to the TU.
*/
public void testTryingCompletedScenario() {
try {
Request register = createRiRegisterRequest();
SipEventCollector responseCollector = new SipEventCollector();
//Before Sending the request we should first register a listener with the
//RI that would catch the TRYING response
try {
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
//Send the initial request
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
waitForMessage();
RequestEvent registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
if (registerReceivedEvent == null
|| registerReceivedEvent.getRequest() == null)
throw new TiUnexpectedError("The initial REGISTER request was not received by the TI!");
//Let's create the transaction
ServerTransaction tran = null;
try {
tran =
tiSipProvider.getNewServerTransaction(
registerReceivedEvent.getRequest());
} catch (Exception ex) {
ex.printStackTrace();
fail(
ex.getClass().getName()
+ "was thrown while trying to "
+ "create the server transaction");
}
assertNotNull(
"tiSipProvider.getNewServerTransaction() returned null",
tran);
//At this point the ServerTransaction should be TRYING!
assertEquals(TransactionState.TRYING, tran.getState());
//Send a TRYING response
Response trying = null;
try {
trying =
tiMessageFactory.createResponse(
Response.TRYING,
registerReceivedEvent.getRequest());
tran.sendResponse(trying);
} catch (Exception ex) {
throw new TiUnexpectedError(
"Failed to send a TRYING response",
ex);
}
//The transaction should now be PROCEEDING
assertEquals(
"The transaction did not pass into the PROCEEDING state "
+ "upon transmission of a 1xx response.",
TransactionState.PROCEEDING,
tran.getState());
waitForMessage();
ResponseEvent responseEvent =
responseCollector.extractCollectedResponseEvent();
assertNotNull(
"The TRYING response has not been sent by the TI.",
responseEvent);
assertTrue(
"A response different from 100 was sent by the TI",
Response.TRYING == responseEvent.getResponse().getStatusCode());
//Resend the REGISTER and see that the TRYING response is resent
try {
//listen for the Trying response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
//Wait for the REGISTER
waitForMessage();
registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
assertNull(
"Retransmitted REGISTERs should not be passed to the TU",
registerReceivedEvent);
//Wait for a retransmitted TRYING response
waitForMessage();
//Verify whether there was a TRYING response
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"No TRYING response has been resent by the TI upon reception "
+ "of a retransmitted REGISTER request",
responseEvent);
assertTrue(
"A response different from 100 was sent by the TI upon "
+ "reception of a retransmitted REGISTER",
Response.TRYING == responseEvent.getResponse().getStatusCode());
//Send 200 - 699 from TU and see the tran goes COMPLETED
Response ok = null;
try {
ok =
tiMessageFactory.createResponse(
Response.OK,
tran.getRequest());
((ToHeader) ok.getHeader(ToHeader.NAME)).setTag(
Integer.toString(hashCode()));
} catch (ParseException ex) {
throw new TiUnexpectedError(
"A ParseException was thrown while trying to create a busy_here "
+ "response using TI",
ex);
}
try {
//listen for the BUSY_HERE response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
tran.sendResponse(ok);
} catch (SipException ex) {
ex.printStackTrace();
fail("The TI failed to send a OK response");
}
//The Transaction should now be COMPLETED
assertEquals(
"The Transaction did not remain COMPLETED after transmitting a BUSY_HERE response",
TransactionState.COMPLETED,
tran.getState());
//Check whether the OK is received by the RI.
waitForMessage();
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"The OK response was not received by the RI",
responseEvent);
assertTrue(
"A response different from OK was sent by the TI",
Response.OK == responseEvent.getResponse().getStatusCode());
//Resend the initial from REGISTER from the RI and see that TI
//resends the 200 - 699 (see that tran state remains COMPLETED)
try {
//listen for the OK response
responseCollector.collectResponseEvent(riSipProvider);
} catch (TooManyListenersException ex) {
throw new TckInternalError(
"Failed to register a SipListener with an RI SipProvider",
ex);
}
try {
eventCollector.collectRequestEvent(tiSipProvider);
riSipProvider.sendRequest(register);
} catch (SipException ex) {
throw new TckInternalError(
"A SipExceptionOccurred while trying to send request!",
ex);
} catch (TooManyListenersException ex) {
throw new TiUnexpectedError(
"Failed to register a SipListener with a TI SipProvider",
ex);
}
//Wait for the REGISTER
waitForMessage();
registerReceivedEvent =
eventCollector.extractCollectedRequestEvent();
assertNull(
"Retransmitted REGISTERs should not be passed to the TU",
registerReceivedEvent);
//Wait for a retransmitted OK response
waitForMessage();
//Verify whether there was an OK response
responseEvent = responseCollector.extractCollectedResponseEvent();
assertNotNull(
"No OK response has been sent by the TI upon reception "
+ "of a retransmitted REGISTER request",
responseEvent);
assertTrue(
"A response different from OK was sent by the TI upon "
+ "reception of a retransmitted invite REGISTER",
Response.OK == responseEvent.getResponse().getStatusCode());
//We should still be COMPLETED
assertEquals(
"The server transaction left the COMPLETED state.",
TransactionState.COMPLETED,
tran.getState());
} catch (Throwable exc) {
exc.printStackTrace();
fail(exc.getClass().getName() + ": " + exc.getMessage());
}
assertTrue(new Exception().getStackTrace()[0].toString(), true);
}
//==================== end of tests
//====== STATIC JUNIT ==========
public static Test suite() {
return new TestSuite(NonInviteServerTransactionsStateMachineTest.class);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy