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.header.ViaHeader;
026: import javax.sip.message.*;
027:
028: import java.util.*;
029: import java.text.*;
030: import test.tck.*;
031:
032: /**
033: * <p>
034: * Title: TCK
035: * </p>
036: * <p>
037: * Description: JAIN SIP 1.1 Technology Compatibility Kit
038: * </p>
039: *
040: * @author Emil Ivov Network Research Team, Louis Pasteur University,
041: * Strasbourg, France. This code is in the public domain.
042: * @version 1.0
043: *
044: */
045:
046: public class ServerTransactionTest extends MessageFlowHarness {
047:
048: public ServerTransactionTest(String name) {
049: super (name);
050: }
051:
052: // ==================== tests ==============================
053:
054: public void testSendResponse() {
055: try {
056: Request invite = createRiInviteRequest(null, null, null);
057: SipEventCollector responseCollector = new SipEventCollector();
058: // Send the initial request
059: try {
060: eventCollector.collectRequestEvent(tiSipProvider);
061: riSipProvider.sendRequest(invite);
062: } catch (SipException ex) {
063: throw new TckInternalError(
064: "A SipExceptionOccurred while trying to send request!",
065: ex);
066: } catch (TooManyListenersException ex) {
067: throw new TiUnexpectedError(
068: "Failed to register a SipListener with a TI SipProvider",
069: ex);
070: }
071: waitForMessage();
072: RequestEvent inviteReceivedEvent = eventCollector
073: .extractCollectedRequestEvent();
074: if (inviteReceivedEvent == null
075: || inviteReceivedEvent.getRequest() == null)
076: throw new TiUnexpectedError(
077: "The initial invite request was not received by the TI!");
078: // Let's create the transaction
079: ServerTransaction tran = null;
080: try {
081: tran = tiSipProvider
082: .getNewServerTransaction(inviteReceivedEvent
083: .getRequest());
084: } catch (Exception ex) {
085: ex.printStackTrace();
086: fail(ex.getClass().getName()
087: + "was thrown while trying to "
088: + "create the server transaction");
089: }
090: assertNotNull(
091: "tiSipProvider.getNewServerTransaction() returned null",
092: tran);
093: // Create & send RINGING. See that it is properly sent
094: Response ringing = null;
095: try {
096: ringing = tiMessageFactory.createResponse(
097: Response.RINGING, tran.getRequest());
098: // BUG: set contact header on dialog-creating response
099: ringing.setHeader(createTiContact());
100: } catch (ParseException ex) {
101: throw new TiUnexpectedError(
102: "A ParseException was thrown while trying to create a ringing "
103: + "response using TI", ex);
104: }
105: try {
106: // listen for the RINGING response
107: responseCollector.collectResponseEvent(riSipProvider);
108: } catch (TooManyListenersException ex) {
109: throw new TckInternalError(
110: "Failed to register a SipListener with an RI SipProvider",
111: ex);
112: }
113: try {
114: tran.sendResponse(ringing);
115: } catch (SipException ex) {
116: ex.printStackTrace();
117: fail("The TI failed to send a RINGING response");
118: }
119:
120: // reset the collector
121: responseCollector.extractCollectedResponseEvent();
122:
123: } catch (Throwable exc) {
124: exc.printStackTrace();
125: fail(exc.getClass().getName() + ": " + exc.getMessage());
126: }
127:
128: assertTrue(new Exception().getStackTrace()[0].toString(), true);
129: }
130:
131: public void testCancel() {
132: try {
133: Request invite = createRiInviteRequest(null, null, null);
134: ClientTransaction tran = null;
135: try {
136: eventCollector.collectRequestEvent(tiSipProvider);
137:
138: // This call overwrites any branch we set
139: tran = riSipProvider.getNewClientTransaction(invite);
140:
141: // And this call too
142: tran.sendRequest();
143: } catch (SipException ex) {
144: throw new TiUnexpectedError(
145: "A SipExceptionOccurred while trying to send request!",
146: ex);
147: } catch (TooManyListenersException ex) {
148: throw new TckInternalError(
149: "Failed to regiest a SipListener with an RI SipProvider",
150: ex);
151: }
152: waitForMessage();
153: RequestEvent inviteReceivedEvent = eventCollector
154: .extractCollectedRequestEvent();
155:
156: ServerTransaction st = tiSipProvider
157: .getNewServerTransaction(inviteReceivedEvent
158: .getRequest());
159:
160: Request inviteRequest = inviteReceivedEvent.getRequest();
161:
162: Dialog dialog = st.getDialog();
163:
164: assertNotNull("Dialog ID must be valid", dialog);
165:
166: if (inviteReceivedEvent == null
167: || inviteReceivedEvent.getRequest() == null)
168: throw new TiUnexpectedError(
169: "The invite request was not received by the TI!");
170:
171: // At this point the ClientTransaction should be CALLING!
172: assertEquals(TransactionState.CALLING, tran.getState());
173:
174: // Send a TRYING response
175: try {
176: eventCollector.collectResponseEvent(riSipProvider);
177: } catch (TooManyListenersException ex) {
178: throw new TiUnexpectedError(
179: "Failed to register a SipListener with TI", ex);
180: }
181: try {
182: Response resp = tiMessageFactory.createResponse(
183: Response.TRYING, inviteReceivedEvent
184: .getRequest());
185: addStatus(inviteReceivedEvent.getRequest(), resp);
186: st.sendResponse(resp);
187: } catch (Throwable ex) {
188: throw new TckInternalError(
189: "The TCK could not send a trying response back to the TI",
190: ex);
191: }
192:
193: waitForMessage();
194:
195: ResponseEvent responseEvent = eventCollector
196: .extractCollectedResponseEvent();
197:
198: assertNotNull("Response must be seen", responseEvent);
199: assertEquals("Must see 100 trying response", responseEvent
200: .getResponse().getStatusCode(), 100);
201:
202: // Analyze the TRYING response and Tran state back at the TI
203:
204: // Send a CANCEL from the RI
205: Request riCancel = tran.createCancel();
206:
207: ClientTransaction riCancelTrans;
208: try {
209: eventCollector.collectRequestEvent(tiSipProvider);
210: riCancelTrans = riSipProvider
211: .getNewClientTransaction(riCancel);
212: riCancelTrans.sendRequest();
213: } catch (SipException ex) {
214: throw new TiUnexpectedError(
215: "A SipExceptionOccurred while trying to send CANCEL!",
216: ex);
217: }
218: waitForMessage();
219: RequestEvent cancelReceivedEvent = eventCollector
220: .extractCollectedRequestEvent();
221: if (cancelReceivedEvent == null
222: || cancelReceivedEvent.getRequest() == null)
223: throw new TiUnexpectedError(
224: "The CANCEL request was not received by the TI!");
225:
226: // Send 200 OK to the CANCEL
227:
228: assertNotNull("Cancel dialog must be non null",
229: cancelReceivedEvent.getDialog() != null);
230: assertSame("Cancel dialog must match Invite",
231: cancelReceivedEvent.getDialog(), dialog);
232: try {
233: eventCollector.collectResponseEvent(riSipProvider);
234: } catch (TooManyListenersException ex) {
235: throw new TiUnexpectedError(
236: "Failed to register a SipListener with TI", ex);
237: }
238: Response tiCancelOk = null;
239: try {
240: tiCancelOk = tiMessageFactory.createResponse(
241: Response.OK, cancelReceivedEvent.getRequest());
242: addStatus(cancelReceivedEvent.getRequest(), tiCancelOk);
243: } catch (Throwable ex) {
244: throw new TckInternalError(
245: "The TI could not send a CANCEL OK response back to the RI",
246: ex);
247: }
248:
249: ServerTransaction cancelTx = cancelReceivedEvent
250: .getServerTransaction();
251:
252: assertNotNull("Must have valid cancel tx", cancelTx);
253:
254: assertTrue(
255: "Cancel tx must not be the same as the invite Tx",
256: cancelTx != st);
257:
258: assertTrue("Method must be cancel ", cancelTx.getRequest()
259: .getMethod().equals(Request.CANCEL));
260:
261: assertTrue("Branch must match invite branch",
262: ((ViaHeader) cancelTx.getRequest().getHeader(
263: ViaHeader.NAME)).getBranch().equals(
264: ((ViaHeader) inviteRequest
265: .getHeader(ViaHeader.NAME))
266: .getBranch()));
267:
268: cancelTx.sendResponse(tiCancelOk);
269:
270: waitForMessage();
271:
272: // Analyze the OK response and Tran state back at the TI
273: responseEvent = eventCollector
274: .extractCollectedResponseEvent();
275: if (responseEvent == null
276: || responseEvent.getResponse() == null) {
277: throw new TiUnexpectedError(
278: "The CANCEL OK response was not received by the RI!");
279: }
280:
281: assertEquals("Must see a 200", eventCollector
282: .extractCollectedResponseEvent().getResponse()
283: .getStatusCode(), 200);
284:
285: try {
286: eventCollector.collectResponseEvent(riSipProvider);
287: } catch (TooManyListenersException ex) {
288: throw new TiUnexpectedError(
289: "Failed to register a SipListener with TI", ex);
290: }
291: SipEventCollector ackCollector = new SipEventCollector();
292: try {
293: ackCollector.collectRequestEvent(tiSipProvider);
294: } catch (TooManyListenersException ex) {
295: throw new TckInternalError(
296: "Failed to regiest a SipListener with an RI SipProvider",
297: ex);
298: }
299: Response tiInviteTerminated = null;
300: try {
301: tiInviteTerminated = tiMessageFactory.createResponse(
302: Response.REQUEST_TERMINATED,
303: inviteReceivedEvent.getRequest());
304: addStatus(inviteReceivedEvent.getRequest(),
305: tiInviteTerminated);
306: st.sendResponse(tiInviteTerminated);
307: } catch (Throwable ex) {
308: throw new TckInternalError(
309: "The TCK could not send a INVITE 487 response back to the TI",
310: ex);
311: }
312: waitForMessage();
313: assertEquals("Must see a 487", eventCollector
314: .extractCollectedResponseEvent().getResponse()
315: .getStatusCode(), 487);
316:
317: waitForMessage();
318:
319: // check whether the ackCollector has caught any fish
320: RequestEvent ackReceivedEvent = ackCollector
321: .extractCollectedRequestEvent();
322:
323: // NOTE -- per 3261 the ack is not passed to the TU.
324: assertNull("The TI MUST NOT see the ACK", ackReceivedEvent);
325:
326: } catch (Throwable exc) {
327: exc.printStackTrace();
328: fail(exc.getClass().getName() + ": " + exc.getMessage());
329: }
330: assertTrue(new Exception().getStackTrace()[0].toString(), true);
331:
332: // Unfortunately we can't assert the TERMINATED state as TIMER_K TIMER_D
333: // is not exported by JAIN SIP
334: }
335:
336: // ==================== end of tests
337:
338: // ====== STATIC JUNIT ==========
339: public static Test suite() {
340: return new TestSuite(ServerTransactionTest.class);
341: }
342:
343: }
|