blob: b8a8c69544ebf01e00ed25e4844f4dda817107e4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.vysper.xmpp.extension.xep0124;
import static org.apache.vysper.xmpp.extension.xep0124.BoshBackedSessionContext.BOSH_REQUEST_ATTRIBUTE;
import static org.apache.vysper.xmpp.extension.xep0124.BoshBackedSessionContext.BOSH_RESPONSE_ATTRIBUTE;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.vysper.xml.fragment.Renderer;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.protocol.StanzaProcessor;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
import org.apache.vysper.xmpp.stanza.Stanza;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class BoshBackedSessionContextTest {
private IMocksControl mocksControl;
private BoshHandler boshHandler;
private ServerRuntimeContext serverRuntimeContext;
private StanzaProcessor stanzaProcessor;
private InactivityChecker inactivityChecker;
@Before
public void setUp() throws Exception {
mocksControl = createControl();
boshHandler = mocksControl.createMock(BoshHandler.class);
serverRuntimeContext = mocksControl.createMock(ServerRuntimeContext.class);
stanzaProcessor = mocksControl.createMock(StanzaProcessor.class);
expect(serverRuntimeContext.getNextSessionId()).andReturn("123");
expect(serverRuntimeContext.getServerEntity()).andReturn(new EntityImpl(null, "vysper.org", null));
expect(serverRuntimeContext.getDefaultXMLLang()).andReturn("en");
inactivityChecker = new InactivityChecker(boshHandler);
// inactivityChecker.start();
}
@After
public void tearDown() throws Exception {
// inactivityChecker.interrupt();
}
@Test
public void testWrite0() {
HttpServletRequest httpServletRequest = mocksControl.createMock(HttpServletRequest.class);
AsyncContext asyncContext = mocksControl.createMock(AsyncContext.class);
expect(httpServletRequest.startAsync()).andReturn(asyncContext);
expectLastCall().atLeastOnce();
expect(httpServletRequest.getAsyncContext()).andReturn(asyncContext);
expectLastCall().atLeastOnce();
asyncContext.setTimeout(anyLong());
asyncContext.dispatch();
expectLastCall().atLeastOnce();
httpServletRequest.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.<BoshRequest>notNull());
asyncContext.addListener(EasyMock.<AsyncListener>anyObject());
Capture<BoshResponse> captured = new Capture<BoshResponse>();
httpServletRequest.setAttribute(eq(BOSH_RESPONSE_ATTRIBUTE), EasyMock.<BoshResponse> capture(captured));
mocksControl.replay();
BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, stanzaProcessor, null, inactivityChecker);
Stanza body = BoshStanzaUtils.EMPTY_BOSH_RESPONSE;
boshBackedSessionContext.insertRequest(new BoshRequest(httpServletRequest, body, 1L));
boshBackedSessionContext.writeBoshResponse(body);
mocksControl.verify();
BoshResponse boshResponse = captured.getValue();
assertEquals(BoshServlet.XML_CONTENT_TYPE, boshResponse.getContentType());
assertEquals(new Renderer(body).getComplete(), new String(boshResponse.getContent()));
}
@Test
public void testSetBoshVersion1() {
mocksControl.replay();
BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, stanzaProcessor, null, inactivityChecker);
boshBackedSessionContext.setBoshVersion("1.8");
assertEquals("1.8", boshBackedSessionContext.getBoshVersion());
mocksControl.verify();
}
@Test
public void testSetBoshVersion2() {
mocksControl.replay();
BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, stanzaProcessor, null, inactivityChecker);
boshBackedSessionContext.setBoshVersion("2.0");
assertEquals("1.9", boshBackedSessionContext.getBoshVersion());
mocksControl.verify();
}
@Test
public void testRequestExpired() throws IOException {
Stanza emtpyStanza = BoshStanzaUtils.EMPTY_BOSH_RESPONSE;
// addRequest
HttpServletRequest httpServletRequest = mocksControl.createMock(HttpServletRequest.class);
AsyncContext asyncContext = mocksControl.createMock(AsyncContext.class);
expect(httpServletRequest.startAsync()).andReturn(asyncContext).atLeastOnce();
expect(httpServletRequest.getAsyncContext()).andReturn(asyncContext).atLeastOnce();
asyncContext.setTimeout(anyLong());
httpServletRequest.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.<BoshRequest>notNull());
expect(asyncContext.getRequest()).andReturn(httpServletRequest).atLeastOnce();
asyncContext.dispatch();
expectLastCall().atLeastOnce();
Capture<AsyncListener> listenerCaptured = new Capture<AsyncListener>();
asyncContext.addListener(EasyMock.<AsyncListener> capture(listenerCaptured));
AsyncEvent asyncEvent = mocksControl.createMock(AsyncEvent.class);
BoshRequest br = new BoshRequest(httpServletRequest, emtpyStanza, 1L);
// requestExpired
expect(httpServletRequest.getAttribute(BOSH_REQUEST_ATTRIBUTE)).andReturn(br);
Capture<BoshResponse> responseCaptured = new Capture<BoshResponse>();
httpServletRequest.setAttribute(eq(BOSH_RESPONSE_ATTRIBUTE), EasyMock.<BoshResponse> capture(responseCaptured));
// write0
mocksControl.replay();
BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, stanzaProcessor, null, inactivityChecker);
boshBackedSessionContext.insertRequest(br);
listenerCaptured.getValue().onTimeout(asyncEvent);
mocksControl.verify();
assertEquals(new Renderer(emtpyStanza).getComplete(), new String(responseCaptured.getValue().getContent()));
assertEquals(BoshServlet.XML_CONTENT_TYPE, responseCaptured.getValue().getContentType());
}
@Test
public void testAddRequest() {
// addRequest
HttpServletRequest httpServletRequest1 = mocksControl.createMock(HttpServletRequest.class);
HttpServletRequest httpServletRequest2 = mocksControl.createMock(HttpServletRequest.class);
AsyncContext asyncContext1 = mocksControl.createMock(AsyncContext.class);
AsyncContext asyncContext2 = mocksControl.createMock(AsyncContext.class);
BoshStanzaUtils boshStanzaUtils = mocksControl.createMock(BoshStanzaUtils.class);
expect(httpServletRequest1.startAsync()).andReturn(asyncContext1).atLeastOnce();
expect(httpServletRequest1.getAsyncContext()).andReturn(asyncContext1).atLeastOnce();
expect(httpServletRequest2.startAsync()).andReturn(asyncContext2).atLeastOnce();
expect(httpServletRequest2.getAsyncContext()).andReturn(asyncContext2).anyTimes();
asyncContext1.setTimeout(anyLong());
Capture<BoshRequest> br1 = new Capture<BoshRequest>();
httpServletRequest1.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.<BoshRequest> capture(br1));
asyncContext2.setTimeout(anyLong());
Capture<BoshRequest> br2 = new Capture<BoshRequest>();
httpServletRequest2.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.<BoshRequest>capture(br2));
asyncContext1.addListener(EasyMock.<AsyncListener> anyObject());
asyncContext2.addListener(EasyMock.<AsyncListener>anyObject());
asyncContext1.dispatch();
expectLastCall().atLeastOnce();
Stanza body = BoshStanzaUtils.EMPTY_BOSH_RESPONSE;
// write0
Capture<BoshResponse> captured = new Capture<BoshResponse>();
httpServletRequest1.setAttribute(eq(BOSH_RESPONSE_ATTRIBUTE), EasyMock.<BoshResponse> capture(captured));
mocksControl.replay();
BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(serverRuntimeContext, stanzaProcessor, null, inactivityChecker);
boshBackedSessionContext.setHold(2);
// consecutive writes with RID 1 and 2
long maxRID = 2L;
boshBackedSessionContext.insertRequest(new BoshRequest(httpServletRequest1, body, 1L));
boshBackedSessionContext.insertRequest(new BoshRequest(httpServletRequest2, body, maxRID));
boshBackedSessionContext.writeBoshResponse(body);
mocksControl.verify();
assertEquals(httpServletRequest1, br1.getValue().getHttpServletRequest());
assertEquals(httpServletRequest2, br2.getValue().getHttpServletRequest());
// expect ack for newest/largest RID
final Stanza ackedResponse = BoshStanzaUtils.addAttribute(body, "ack", Long.toString(maxRID));
assertEquals(new Renderer(ackedResponse).getComplete(), new String(captured.getValue().getContent()));
assertEquals(BoshServlet.XML_CONTENT_TYPE, captured.getValue().getContentType());
}
@Test
public void testAddRequestWithDelayedResponses() {
HttpServletRequest httpServletRequest = mocksControl.createMock(HttpServletRequest.class);
AsyncContext asyncContext = mocksControl.createMock(AsyncContext.class);
expect(httpServletRequest.startAsync()).andReturn(asyncContext).atLeastOnce();
expect(httpServletRequest.getAsyncContext()).andReturn(asyncContext).atLeastOnce();
asyncContext.setTimeout(anyLong());
httpServletRequest.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.<BoshRequest>notNull());
asyncContext.addListener(EasyMock.<AsyncListener>anyObject());
asyncContext.dispatch();
expectLastCall().atLeastOnce();
Stanza body = BoshStanzaUtils.createBoshStanzaBuilder().startInnerElement("presence").endInnerElement().build();
Capture<BoshResponse> captured = new Capture<BoshResponse>();
httpServletRequest.setAttribute(eq(BOSH_RESPONSE_ATTRIBUTE), EasyMock.<BoshResponse> capture(captured));
mocksControl.replay();
BoshBackedSessionContext boshBackedSessionContext = new BoshBackedSessionContext(
serverRuntimeContext, stanzaProcessor, null, inactivityChecker);
boshBackedSessionContext.writeBoshResponse(body); // queued for merging
boshBackedSessionContext.writeBoshResponse(body); // queued for merging
boshBackedSessionContext.writeBoshResponse(body); // queued for merging
boshBackedSessionContext.insertRequest(new BoshRequest(httpServletRequest, body, 1L));
mocksControl.verify();
final String mergedAllBodiesStanza = new String(captured.getValue().getContent());
assertEquals(3, StringUtils.countMatches(mergedAllBodiesStanza, "<presence"));
}
}