001: /*
002: * Conditions Of Use
003: *
004: * This software was developed by employees of the National Institute of
005: * Standards and Technology (NIST), and others.
006: * This software is has been contributed to the public domain.
007: * As a result, a formal license is not needed to use the software.
008: *
009: * This software is provided "AS IS."
010: * NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
011: * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
012: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
013: * AND DATA ACCURACY. NIST does not warrant or make any representations
014: * regarding the use of the software or the results thereof, including but
015: * not limited to the correctness, accuracy, reliability or usefulness of
016: * the software.
017: *
018: *
019: */
020: package test.tck.msgflow;
021:
022: import junit.framework.*;
023:
024: import javax.sip.*;
025: import javax.sip.message.*;
026: import javax.sip.header.*;
027: import java.util.*;
028: import java.text.*;
029: import test.tck.*;
030:
031: /**
032: *
033: * The test tries to verify that Invite Server Transactions correctly change
034: * states as specified by the rfc3261. The Reference Implementation is used
035: * to send requests and a Tested Implementation ServerTransaction's states are
036: * queried and compared to those in the state machine described in
037: * section 17.2.1 of rfc3261
038: *<pre>
039: *
040: * |Request received
041: * |pass to TU
042: * V
043: * +-----------+
044: * | |
045: * | Trying |-------------+
046: * | | |
047: * +-----------+ |200-699 from TU
048: * | |send response
049: * |1xx from TU |
050: * |send response |
051: * | |
052: * Request V 1xx from TU |
053: * send response+-----------+send response|
054: * +--------| |--------+ |
055: * | | Proceeding| | |
056: * +------->| |<-------+ |
057: * +<--------------| | |
058: * |Trnsprt Err +-----------+ |
059: * |Inform TU | |
060: * | | |
061: * | |200-699 from TU |
062: * | |send response |
063: * | Request V |
064: * | send response+-----------+ |
065: * | +--------| | |
066: * | | | Completed |<------------+
067: * | +------->| |
068: * +<--------------| |
069: * |Trnsprt Err +-----------+
070: * |Inform TU |
071: * | |Timer J fires
072: * | |-
073: * | |
074: * | V
075: * | +-----------+
076: * | | |
077: * +-------------->| Terminated|
078: * | |
079: * +-----------+
080: *
081: * Figure 8: non-INVITE server transaction
082: *
083: *</pre>
084: *
085: * @author Emil Ivov
086: * Network Research Team, Louis Pasteur University, Strasbourg, France.
087: * This code is in the public domain.
088: * @version 1.0
089: */
090:
091: public class NonInviteServerTransactionsStateMachineTest extends
092: MessageFlowHarness {
093:
094: public NonInviteServerTransactionsStateMachineTest(String name) {
095: super (name);
096: }
097:
098: //==================== tests ==============================
099:
100: /**
101: * Tries to steer a TI server transaction through the following scenario
102: * Trying-->Proceeding-->Completed-->Terminated. Apart from state
103: * transitions, we also test, retransmissions and proper hiding/passing
104: * of messages to the TU.
105: */
106: public void testTryingProceedingCompletedScenario() {
107: try {
108: Request register = createRiRegisterRequest();
109: SipEventCollector responseCollector = new SipEventCollector();
110: //Before Sending the request we should first register a listener with the
111: //RI that would catch the TRYING response
112: try {
113: responseCollector.collectResponseEvent(riSipProvider);
114: } catch (TooManyListenersException ex) {
115: throw new TckInternalError(
116: "Failed to register a SipListener with an RI SipProvider",
117: ex);
118: }
119: //Send the initial request
120: try {
121: eventCollector.collectRequestEvent(tiSipProvider);
122: riSipProvider.sendRequest(register);
123: } catch (SipException ex) {
124: throw new TckInternalError(
125: "A SipExceptionOccurred while trying to send request!",
126: ex);
127: } catch (TooManyListenersException ex) {
128: throw new TiUnexpectedError(
129: "Failed to register a SipListener with a TI SipProvider",
130: ex);
131: }
132: waitForMessage();
133: RequestEvent registerReceivedEvent = eventCollector
134: .extractCollectedRequestEvent();
135: if (registerReceivedEvent == null
136: || registerReceivedEvent.getRequest() == null)
137: throw new TiUnexpectedError(
138: "The initial register request was not received by the TI!");
139: //Let's create the transaction
140: ServerTransaction tran = null;
141: try {
142: tran = tiSipProvider
143: .getNewServerTransaction(registerReceivedEvent
144: .getRequest());
145: } catch (Exception ex) {
146: ex.printStackTrace();
147: fail(ex.getClass().getName()
148: + "was thrown while trying to "
149: + "create the server transaction");
150: }
151: assertNotNull(
152: "tiSipProvider.getNewServerTransaction() returned null",
153: tran);
154: //At this point the ServerTransaction should be TRYING!
155: assertEquals(TransactionState.TRYING, tran.getState());
156: //Send a TRYING response
157: Response trying = null;
158: try {
159: trying = tiMessageFactory.createResponse(
160: Response.TRYING, registerReceivedEvent
161: .getRequest());
162: tran.sendResponse(trying);
163: } catch (Exception ex) {
164: throw new TiUnexpectedError(
165: "Failed to send a TRYING response", ex);
166: }
167: waitForMessage();
168: //The transaction should now be PROCEEDING
169: assertEquals(
170: "The transaction did not pass into the PROCEEDING state "
171: + "upon transmission of a 1xx response.",
172: TransactionState.PROCEEDING, tran.getState());
173: ResponseEvent responseEvent = responseCollector
174: .extractCollectedResponseEvent();
175: assertNotNull(
176: "The TRYING response has not been sent by the TI.",
177: responseEvent);
178: assertTrue(
179: "A response different from 100 was sent by the TI",
180: Response.TRYING == responseEvent.getResponse()
181: .getStatusCode());
182: //Resend the REGISTER and see that the TRYING response is resent
183: try {
184: //listen for the Trying response
185: responseCollector.collectResponseEvent(riSipProvider);
186: } catch (TooManyListenersException ex) {
187: throw new TckInternalError(
188: "Failed to register a SipListener with an RI SipProvider",
189: ex);
190: }
191: try {
192: eventCollector.collectRequestEvent(tiSipProvider);
193: riSipProvider.sendRequest(register);
194: } catch (SipException ex) {
195: throw new TckInternalError(
196: "A SipExceptionOccurred while trying to send request!",
197: ex);
198: } catch (TooManyListenersException ex) {
199: throw new TiUnexpectedError(
200: "Failed to register a SipListener with a TI SipProvider",
201: ex);
202: }
203: //Wait for the REGISTER
204: waitForMessage();
205: registerReceivedEvent = eventCollector
206: .extractCollectedRequestEvent();
207: assertNull(
208: "Retransmitted REGISTERs should not be passed to the TU",
209: registerReceivedEvent);
210: //Wait for a retransmitted TRYING response
211: waitForMessage();
212: //Verify whether there was a TRYING response
213: responseEvent = responseCollector
214: .extractCollectedResponseEvent();
215: assertNotNull(
216: "No TRYING response has been resent by the TI upon reception "
217: + "of a retransmitted REGISTER request",
218: responseEvent);
219: assertTrue(
220: "A response different from 100 was sent by the TI upon "
221: + "reception of a retransmitted REGISTER",
222: Response.TRYING == responseEvent.getResponse()
223: .getStatusCode());
224: //Create & send RINGING. See that it is properly sent
225: //and that tran state doesn't change
226: Response ringing = null;
227: try {
228: ringing = tiMessageFactory.createResponse(
229: Response.RINGING, tran.getRequest());
230: ((ToHeader) ringing.getHeader(ToHeader.NAME))
231: .setTag(Integer.toString(hashCode()));
232: } catch (ParseException ex) {
233: throw new TiUnexpectedError(
234: "A ParseException was thrown while trying to create a ringing "
235: + "response using TI", ex);
236: }
237: try {
238: //listen for the RINGING response
239: responseCollector.collectResponseEvent(riSipProvider);
240: } catch (TooManyListenersException ex) {
241: throw new TckInternalError(
242: "Failed to register a SipListener with an RI SipProvider",
243: ex);
244: }
245: try {
246: tran.sendResponse(ringing);
247: } catch (SipException ex) {
248: ex.printStackTrace();
249: fail("The TI failed to send a RINGING response");
250: }
251: //The Transaction should still be PROCEEDING
252: assertEquals(
253: "The Transaction did not remain PROCEEDING after transmitting a RINGING response",
254: TransactionState.PROCEEDING, tran.getState());
255: //Check whether the RINGING is received by the RI.
256: waitForMessage();
257: responseEvent = responseCollector
258: .extractCollectedResponseEvent();
259: assertNotNull(
260: "The RINGING response was not received by the RI",
261: responseEvent);
262: assertTrue(
263: "A response different from RINGING was sent by the TI",
264: Response.RINGING == responseEvent.getResponse()
265: .getStatusCode());
266: //Resend the REGISTER, see that it is hidden from the TU and see that
267: //the _RINGING_ response is resent (and not the TRYING)
268: try {
269: //listen for the Trying response
270: responseCollector.collectResponseEvent(riSipProvider);
271: } catch (TooManyListenersException ex) {
272: throw new TckInternalError(
273: "Failed to register a SipListener with an RI SipProvider",
274: ex);
275: }
276: try {
277: eventCollector.collectRequestEvent(tiSipProvider);
278: riSipProvider.sendRequest(register);
279: } catch (SipException ex) {
280: throw new TckInternalError(
281: "A SipExceptionOccurred while trying to send request!",
282: ex);
283: } catch (TooManyListenersException ex) {
284: throw new TiUnexpectedError(
285: "Failed to register a SipListener with a TI SipProvider",
286: ex);
287: }
288: //Wait for the REGISTER
289: waitForMessage();
290: registerReceivedEvent = eventCollector
291: .extractCollectedRequestEvent();
292: assertNull(
293: "Retransmitted REGISTERs should not be passed to the TU",
294: registerReceivedEvent);
295: //Wait for a retransmitted RINGING response
296: waitForMessage();
297: //Verify whether there was a RINGING response
298: responseEvent = responseCollector
299: .extractCollectedResponseEvent();
300: assertNotNull(
301: "No RINGING response has been sent by the TI upon reception "
302: + "of an REGISTER request", responseEvent);
303: assertTrue(
304: "A response different from RINGING was sent by the TI upon "
305: + "reception of a retransmitted REGISTER",
306: Response.RINGING == responseEvent.getResponse()
307: .getStatusCode());
308: //We should still be proceeding
309: assertEquals(
310: "The server transaction left the PROCEEDING state.",
311: TransactionState.PROCEEDING, tran.getState());
312: //Send 200 - 699 from TU and see the tran goes COMPLETED
313: Response ok = null;
314: try {
315: ok = tiMessageFactory.createResponse(Response.OK, tran
316: .getRequest());
317: ((ToHeader) ok.getHeader(ToHeader.NAME)).setTag(Integer
318: .toString(hashCode()));
319: } catch (ParseException ex) {
320: throw new TiUnexpectedError(
321: "A ParseException was thrown while trying to create a busy_here "
322: + "response using TI", ex);
323: }
324: try {
325: //listen for the BUSY_HERE response
326: responseCollector.collectResponseEvent(riSipProvider);
327: } catch (TooManyListenersException ex) {
328: throw new TckInternalError(
329: "Failed to register a SipListener with an RI SipProvider",
330: ex);
331: }
332: try {
333: tran.sendResponse(ok);
334: } catch (SipException ex) {
335: ex.printStackTrace();
336: fail("The TI failed to send a OK response");
337: }
338: //The Transaction should now be COMPLETED
339: assertEquals(
340: "The Transaction did not remain COMPLETED after transmitting a BUSY_HERE response",
341: TransactionState.COMPLETED, tran.getState());
342: //Check whether the OK is received by the RI.
343: waitForMessage();
344: responseEvent = responseCollector
345: .extractCollectedResponseEvent();
346: assertNotNull("The OK response was not received by the RI",
347: responseEvent);
348: assertTrue(
349: "A response different from OK was sent by the TI",
350: Response.OK == responseEvent.getResponse()
351: .getStatusCode());
352: //Resend the initial from REGISTER from the RI and see that TI
353: //resends the 200 - 699 (see that tran state remains COMPLETED)
354: try {
355: //listen for the OK response
356: responseCollector.collectResponseEvent(riSipProvider);
357: } catch (TooManyListenersException ex) {
358: throw new TckInternalError(
359: "Failed to register a SipListener with an RI SipProvider",
360: ex);
361: }
362: try {
363: eventCollector.collectRequestEvent(tiSipProvider);
364: riSipProvider.sendRequest(register);
365: } catch (SipException ex) {
366: throw new TckInternalError(
367: "A SipExceptionOccurred while trying to send request!",
368: ex);
369: } catch (TooManyListenersException ex) {
370: throw new TiUnexpectedError(
371: "Failed to register a SipListener with a TI SipProvider",
372: ex);
373: }
374: //Wait for the REGISTER
375: waitForMessage();
376: registerReceivedEvent = eventCollector
377: .extractCollectedRequestEvent();
378: assertNull(
379: "Retransmitted REGISTERs should not be passed to the TU",
380: registerReceivedEvent);
381: //Wait for a retransmitted OK response
382: waitForMessage();
383: //Verify whether there was an OK response
384: responseEvent = responseCollector
385: .extractCollectedResponseEvent();
386: assertNotNull(
387: "No OK response has been sent by the TI upon reception "
388: + "of a retransmitted REGISTER request",
389: responseEvent);
390: assertTrue(
391: "A response different from OK was sent by the TI upon "
392: + "reception of a retransmitted invite REGISTER",
393: Response.OK == responseEvent.getResponse()
394: .getStatusCode());
395: //We should still be COMPLETED
396: assertEquals(
397: "The server transaction left the COMPLETED state.",
398: TransactionState.COMPLETED, tran.getState());
399: } catch (Throwable exc) {
400: exc.printStackTrace();
401: fail(exc.getClass().getName() + ": " + exc.getMessage());
402: }
403: assertTrue(new Exception().getStackTrace()[0].toString(), true);
404:
405: }
406:
407: /**
408: * Tries to steer a TI server transaction through the following scenario
409: * Trying-->Completed. Apart from state
410: * transitions, we also test, retransmissions and proper hiding/passing
411: * of messages to the TU.
412: */
413: public void testTryingCompletedScenario() {
414: try {
415:
416: Request register = createRiRegisterRequest();
417: SipEventCollector responseCollector = new SipEventCollector();
418: //Before Sending the request we should first register a listener with the
419: //RI that would catch the TRYING response
420: try {
421: responseCollector.collectResponseEvent(riSipProvider);
422: } catch (TooManyListenersException ex) {
423: throw new TckInternalError(
424: "Failed to register a SipListener with an RI SipProvider",
425: ex);
426: }
427: //Send the initial request
428: try {
429: eventCollector.collectRequestEvent(tiSipProvider);
430: riSipProvider.sendRequest(register);
431: } catch (SipException ex) {
432: throw new TckInternalError(
433: "A SipExceptionOccurred while trying to send request!",
434: ex);
435: } catch (TooManyListenersException ex) {
436: throw new TiUnexpectedError(
437: "Failed to register a SipListener with a TI SipProvider",
438: ex);
439: }
440: waitForMessage();
441: RequestEvent registerReceivedEvent = eventCollector
442: .extractCollectedRequestEvent();
443: if (registerReceivedEvent == null
444: || registerReceivedEvent.getRequest() == null)
445: throw new TiUnexpectedError(
446: "The initial REGISTER request was not received by the TI!");
447: //Let's create the transaction
448: ServerTransaction tran = null;
449: try {
450: tran = tiSipProvider
451: .getNewServerTransaction(registerReceivedEvent
452: .getRequest());
453: } catch (Exception ex) {
454: ex.printStackTrace();
455: fail(ex.getClass().getName()
456: + "was thrown while trying to "
457: + "create the server transaction");
458: }
459: assertNotNull(
460: "tiSipProvider.getNewServerTransaction() returned null",
461: tran);
462: //At this point the ServerTransaction should be TRYING!
463: assertEquals(TransactionState.TRYING, tran.getState());
464: //Send a TRYING response
465: Response trying = null;
466: try {
467: trying = tiMessageFactory.createResponse(
468: Response.TRYING, registerReceivedEvent
469: .getRequest());
470: tran.sendResponse(trying);
471: } catch (Exception ex) {
472: throw new TiUnexpectedError(
473: "Failed to send a TRYING response", ex);
474: }
475: //The transaction should now be PROCEEDING
476: assertEquals(
477: "The transaction did not pass into the PROCEEDING state "
478: + "upon transmission of a 1xx response.",
479: TransactionState.PROCEEDING, tran.getState());
480: waitForMessage();
481: ResponseEvent responseEvent = responseCollector
482: .extractCollectedResponseEvent();
483: assertNotNull(
484: "The TRYING response has not been sent by the TI.",
485: responseEvent);
486: assertTrue(
487: "A response different from 100 was sent by the TI",
488: Response.TRYING == responseEvent.getResponse()
489: .getStatusCode());
490: //Resend the REGISTER and see that the TRYING response is resent
491: try {
492: //listen for the Trying response
493: responseCollector.collectResponseEvent(riSipProvider);
494: } catch (TooManyListenersException ex) {
495: throw new TckInternalError(
496: "Failed to register a SipListener with an RI SipProvider",
497: ex);
498: }
499: try {
500: eventCollector.collectRequestEvent(tiSipProvider);
501: riSipProvider.sendRequest(register);
502: } catch (SipException ex) {
503: throw new TckInternalError(
504: "A SipExceptionOccurred while trying to send request!",
505: ex);
506: } catch (TooManyListenersException ex) {
507: throw new TiUnexpectedError(
508: "Failed to register a SipListener with a TI SipProvider",
509: ex);
510: }
511: //Wait for the REGISTER
512: waitForMessage();
513: registerReceivedEvent = eventCollector
514: .extractCollectedRequestEvent();
515: assertNull(
516: "Retransmitted REGISTERs should not be passed to the TU",
517: registerReceivedEvent);
518: //Wait for a retransmitted TRYING response
519: waitForMessage();
520: //Verify whether there was a TRYING response
521: responseEvent = responseCollector
522: .extractCollectedResponseEvent();
523: assertNotNull(
524: "No TRYING response has been resent by the TI upon reception "
525: + "of a retransmitted REGISTER request",
526: responseEvent);
527: assertTrue(
528: "A response different from 100 was sent by the TI upon "
529: + "reception of a retransmitted REGISTER",
530: Response.TRYING == responseEvent.getResponse()
531: .getStatusCode());
532: //Send 200 - 699 from TU and see the tran goes COMPLETED
533: Response ok = null;
534: try {
535: ok = tiMessageFactory.createResponse(Response.OK, tran
536: .getRequest());
537: ((ToHeader) ok.getHeader(ToHeader.NAME)).setTag(Integer
538: .toString(hashCode()));
539: } catch (ParseException ex) {
540: throw new TiUnexpectedError(
541: "A ParseException was thrown while trying to create a busy_here "
542: + "response using TI", ex);
543: }
544: try {
545: //listen for the BUSY_HERE response
546: responseCollector.collectResponseEvent(riSipProvider);
547: } catch (TooManyListenersException ex) {
548: throw new TckInternalError(
549: "Failed to register a SipListener with an RI SipProvider",
550: ex);
551: }
552: try {
553: tran.sendResponse(ok);
554: } catch (SipException ex) {
555: ex.printStackTrace();
556: fail("The TI failed to send a OK response");
557: }
558: //The Transaction should now be COMPLETED
559: assertEquals(
560: "The Transaction did not remain COMPLETED after transmitting a BUSY_HERE response",
561: TransactionState.COMPLETED, tran.getState());
562: //Check whether the OK is received by the RI.
563: waitForMessage();
564: responseEvent = responseCollector
565: .extractCollectedResponseEvent();
566: assertNotNull("The OK response was not received by the RI",
567: responseEvent);
568: assertTrue(
569: "A response different from OK was sent by the TI",
570: Response.OK == responseEvent.getResponse()
571: .getStatusCode());
572: //Resend the initial from REGISTER from the RI and see that TI
573: //resends the 200 - 699 (see that tran state remains COMPLETED)
574: try {
575: //listen for the OK response
576: responseCollector.collectResponseEvent(riSipProvider);
577: } catch (TooManyListenersException ex) {
578: throw new TckInternalError(
579: "Failed to register a SipListener with an RI SipProvider",
580: ex);
581: }
582: try {
583: eventCollector.collectRequestEvent(tiSipProvider);
584: riSipProvider.sendRequest(register);
585: } catch (SipException ex) {
586: throw new TckInternalError(
587: "A SipExceptionOccurred while trying to send request!",
588: ex);
589: } catch (TooManyListenersException ex) {
590: throw new TiUnexpectedError(
591: "Failed to register a SipListener with a TI SipProvider",
592: ex);
593: }
594: //Wait for the REGISTER
595: waitForMessage();
596: registerReceivedEvent = eventCollector
597: .extractCollectedRequestEvent();
598: assertNull(
599: "Retransmitted REGISTERs should not be passed to the TU",
600: registerReceivedEvent);
601: //Wait for a retransmitted OK response
602: waitForMessage();
603: //Verify whether there was an OK response
604: responseEvent = responseCollector
605: .extractCollectedResponseEvent();
606: assertNotNull(
607: "No OK response has been sent by the TI upon reception "
608: + "of a retransmitted REGISTER request",
609: responseEvent);
610: assertTrue(
611: "A response different from OK was sent by the TI upon "
612: + "reception of a retransmitted invite REGISTER",
613: Response.OK == responseEvent.getResponse()
614: .getStatusCode());
615: //We should still be COMPLETED
616: assertEquals(
617: "The server transaction left the COMPLETED state.",
618: TransactionState.COMPLETED, tran.getState());
619: } catch (Throwable exc) {
620: exc.printStackTrace();
621: fail(exc.getClass().getName() + ": " + exc.getMessage());
622: }
623: assertTrue(new Exception().getStackTrace()[0].toString(), true);
624:
625: }
626:
627: //==================== end of tests
628:
629: //====== STATIC JUNIT ==========
630: public static Test suite() {
631: return new TestSuite(
632: NonInviteServerTransactionsStateMachineTest.class);
633: }
634:
635: }
|