blob: 51424b1e55c92f0214771640317b3d193b0a4957 [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 junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
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 java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncListener;
import javax.servlet.http.HttpServletRequest;
import org.apache.vysper.xml.fragment.XMLElement;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.authentication.SASLMechanism;
import org.apache.vysper.xmpp.modules.extension.xep0077_inbandreg.InBandRegistrationModule;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
import org.apache.vysper.xmpp.protocol.StanzaProcessor;
import org.apache.vysper.xmpp.server.ServerFeatures;
import org.apache.vysper.xmpp.server.ServerRuntimeContext;
import org.apache.vysper.xmpp.stanza.Stanza;
import org.apache.vysper.xmpp.stanza.StanzaBuilder;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
public class BoshHandlerTest {
private IMocksControl mocksControl;
private ServerRuntimeContext serverRuntimeContext;
private StanzaProcessor stanzaProcessor;
private BoshHandler boshHandler;
@Before
public void setUp() throws Exception {
mocksControl = createControl();
serverRuntimeContext = mocksControl.createMock(ServerRuntimeContext.class);
stanzaProcessor = mocksControl.createMock(StanzaProcessor.class);
boshHandler = new BoshHandler();
boshHandler.setServerRuntimeContext(serverRuntimeContext);
boshHandler.setStanzaProcessor(stanzaProcessor);
}
@After
public void tearDown() throws Exception {
}
@Test
public void testProcess() throws IOException, SAXException {
// test session creation
HttpServletRequest httpServletRequest = mocksControl.createMock(HttpServletRequest.class);
expect(serverRuntimeContext.getNextSessionId()).andReturn("200");
expect(serverRuntimeContext.getServerEntity()).andReturn(new EntityImpl(null, "vysper.org", null));
expect(serverRuntimeContext.getDefaultXMLLang()).andReturn("en");
AsyncContext asyncContext = mocksControl.createMock(AsyncContext.class);
expect(httpServletRequest.startAsync()).andReturn(asyncContext).atLeastOnce();
expect(httpServletRequest.getAsyncContext()).andReturn(asyncContext).atLeastOnce();
asyncContext.setTimeout(anyLong());
Capture<BoshRequest> br = new Capture<BoshRequest>();
httpServletRequest.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.<BoshRequest>capture(br));
asyncContext.addListener(EasyMock.<AsyncListener> anyObject());
asyncContext.dispatch();
ServerFeatures serverFeatures = mocksControl.createMock(ServerFeatures.class);
expect(serverRuntimeContext.getServerFeatures()).andReturn(serverFeatures);
expect(serverFeatures.getAuthenticationMethods()).andReturn(Collections.<SASLMechanism> emptyList());
expect(serverRuntimeContext.getModule(InBandRegistrationModule.class)).andReturn(null);
Capture<BoshResponse> captured = new Capture<BoshResponse>();
httpServletRequest.setAttribute(eq(BOSH_RESPONSE_ATTRIBUTE), EasyMock.<BoshResponse> capture(captured));
mocksControl.replay();
Stanza boshRequest = createSessionRequest();
boshHandler.process(httpServletRequest, boshRequest);
mocksControl.verify();
assertEquals(httpServletRequest, br.getValue().getHttpServletRequest());
assertEquals(boshRequest, br.getValue().getBody());
Stanza response = new XMLUtil(new String(captured.getValue().getContent())).parse();
assertNotNull(response);
assertEquals("body", response.getName());
assertEquals(NamespaceURIs.XEP0124_BOSH, response.getNamespaceURI());
assertEquals("200", response.getAttributeValue("sid"));
assertEquals("vysper.org", response.getAttributeValue("from"));
assertEquals("60", response.getAttributeValue("wait"));
assertEquals("1", response.getAttributeValue("hold"));
assertEquals("1.9", response.getAttributeValue("ver"));
assertEquals(1, response.getInnerElements().size());
XMLElement streamFeatures = response.getInnerElements().get(0);
assertEquals("features", streamFeatures.getName());
assertEquals(NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS, streamFeatures.getNamespaceURI());
assertEquals(1, streamFeatures.getInnerElements().size());
XMLElement saslMechanisms = streamFeatures.getInnerElements().get(0);
assertEquals("mechanisms", saslMechanisms.getName());
assertEquals(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL, saslMechanisms.getNamespaceURI());
// test session retrieval, retrieves the session above identified by sid=200
mocksControl.reset();
expect(httpServletRequest.startAsync()).andReturn(asyncContext).atLeastOnce();
expect(httpServletRequest.getAsyncContext()).andReturn(asyncContext).anyTimes();
asyncContext.setTimeout(anyLong());
httpServletRequest.setAttribute(eq(BOSH_REQUEST_ATTRIBUTE), EasyMock.capture(br));
asyncContext.addListener(EasyMock.anyObject());
Capture<Stanza> stanzaCaptured = new Capture<>();
stanzaProcessor.processStanza(eq(serverRuntimeContext), EasyMock.anyObject(),
EasyMock.capture(stanzaCaptured), EasyMock.anyObject());
mocksControl.replay();
boshRequest = createSaslRequest();
boshHandler.process(httpServletRequest, boshRequest);
mocksControl.verify();
assertEquals(httpServletRequest, br.getValue().getHttpServletRequest());
assertEquals(boshRequest, br.getValue().getBody());
Stanza stanza = stanzaCaptured.getValue();
assertNotNull(stanza);
assertEquals("auth", stanza.getName());
assertEquals(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL, stanza.getNamespaceURI());
assertEquals("DIGEST-MD5", stanza.getAttributeValue("mechanism"));
}
@Test
public void testGetEmptyResponse() {
Stanza response = BoshStanzaUtils.EMPTY_BOSH_RESPONSE;
assertNotNull(response);
assertEquals("body", response.getName());
assertEquals(NamespaceURIs.XEP0124_BOSH, response.getNamespaceURI());
assertEquals(0, response.getAttributes().size());
assertEquals(0, response.getInnerElements().size());
}
@Test
public void testWrapStanza() {
StanzaBuilder stanzaBuilder = new StanzaBuilder("iq", NamespaceURIs.JABBER_CLIENT);
Stanza stanza = stanzaBuilder.build();
Stanza body = BoshStanzaUtils.wrapStanza(stanza);
assertNotNull(body);
assertEquals("body", body.getName());
assertEquals(NamespaceURIs.XEP0124_BOSH, body.getNamespaceURI());
assertEquals(1, body.getInnerElements().size());
assertEquals("iq", body.getInnerElements().get(0).getName());
assertEquals(NamespaceURIs.JABBER_CLIENT, body.getInnerElements().get(0).getNamespaceURI());
}
@Test
public void testMergeResponses() {
Stanza response1 = createPingStanzaResponse("vysper.org", "user1@vysper.org/resource", "100");
Stanza response2 = createPingStanzaResponse("vysper.org", "user1@vysper.org/resource", "101");
assertEquals(response1, BoshStanzaUtils.mergeResponses(Arrays.asList(response1, null)));
assertEquals(response1, BoshStanzaUtils.mergeResponses(Arrays.asList(null, response1)));
Stanza merged = BoshStanzaUtils.mergeResponses(Arrays.asList(response1, response2));
assertNotNull(merged);
assertEquals("body", merged.getName());
assertEquals(NamespaceURIs.XEP0124_BOSH, merged.getNamespaceURI());
assertEquals(2, merged.getInnerElements().size());
assertEquals(response1.getInnerElements().get(0), merged.getInnerElements().get(0));
assertEquals(response2.getInnerElements().get(0), merged.getInnerElements().get(1));
}
private Stanza createSessionRequest() {
StanzaBuilder body = BoshStanzaUtils.createBoshStanzaBuilder();
body.addAttribute("rid", "100");
body.addAttribute("to", "vysper.org");
body.addAttribute(NamespaceURIs.XML, "lang", "en");
body.addAttribute("wait", "60");
body.addAttribute("hold", "1");
body.addAttribute("ver", "1.9");
body.addAttribute(NamespaceURIs.URN_XMPP_XBOSH, "version", "1.0");
return body.build();
}
private Stanza createSaslRequest() {
StanzaBuilder body = BoshStanzaUtils.createBoshStanzaBuilder();
body.addAttribute("rid", "101");
body.addAttribute("sid", "200");
body.startInnerElement("auth", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL)
.addAttribute("mechanism", "DIGEST-MD5").endInnerElement();
return body.build();
}
private static Stanza createPingStanzaResponse(String from, String to, String id) {
StanzaBuilder body = BoshStanzaUtils.createBoshStanzaBuilder();
body.startInnerElement("iq", NamespaceURIs.JABBER_CLIENT).addAttribute("from", from)
.addAttribute("type", "result").addAttribute("to", to).addAttribute("id", id);
body.endInnerElement();
return body.build();
}
}