blob: 5abac0e30e7959fb28c197c6f76087975e7eaa51 [file] [log] [blame]
/***********************************************************************
* Copyright (c) 2006-2007 The Apache Software Foundation. *
* All rights reserved. *
* ------------------------------------------------------------------- *
* Licensed 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.protocol;
import junit.framework.TestCase;
import org.apache.vysper.xml.fragment.XMLElement;
import org.apache.vysper.xml.fragment.XMLElementVerifier;
import org.apache.vysper.xml.fragment.XMLSemanticError;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.delivery.StanzaReceiverRelay;
import org.apache.vysper.xmpp.server.DefaultServerRuntimeContext;
import org.apache.vysper.xmpp.server.SessionState;
import org.apache.vysper.xmpp.server.TestSessionContext;
import org.apache.vysper.xmpp.stanza.IQStanza;
import org.apache.vysper.xmpp.stanza.IQStanzaType;
import org.apache.vysper.xmpp.stanza.Stanza;
import org.apache.vysper.xmpp.stanza.StanzaBuilder;
import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
import org.apache.vysper.xmpp.state.resourcebinding.BindException;
/**
* test basic behavior of ProtocolWorker.processStanza()
*/
public class ProtocolWorkerProcessTestCase extends TestCase {
private ProtocolWorker protocolWorker;
private NamespaceHandlerDictionary namespaceHandlerDictionary;
private DefaultServerRuntimeContext serverRuntimeContext;
private TestSessionContext sessionContext;
private static Entity serverEnitity = new EntityImpl(null, "test", null);
private SessionStateHolder sessionStateHolder;
@Override
protected void setUp() throws Exception {
super.setUp();
protocolWorker = new ProtocolWorker();
namespaceHandlerDictionary = new NamespaceHandlerDictionary("testNSURI");
StanzaReceiverRelay receiverRelay = new StanzaReceiverRelay();
serverRuntimeContext = new DefaultServerRuntimeContext(serverEnitity, receiverRelay);
receiverRelay.setServerRuntimeContext(serverRuntimeContext);
serverRuntimeContext.addDictionary(namespaceHandlerDictionary);
sessionStateHolder = new SessionStateHolder();
sessionContext = new TestSessionContext(serverRuntimeContext, sessionStateHolder);
}
public void testProcessUnknownStanza() {
sessionContext.setSessionState(SessionState.AUTHENTICATED);
Stanza stanza = new StanzaBuilder("ProtocolWorkerProcessTestCase", "testNSURI").build();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanza,
sessionStateHolder);
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
XMLElementVerifier verifier = recordedResponse.getVerifier();
assertTrue("error", verifier.nameEquals("error"));
assertTrue("unsupported stanza type", verifier.subElementPresent(StreamErrorCondition.UNSUPPORTED_STANZA_TYPE
.value()));
}
public void testProcessStanzaNoResponse() {
sessionContext.setSessionState(SessionState.AUTHENTICATED);
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("ProtocolWorkerProcessTestCase");
namespaceHandlerDictionary.register(stanzaHandler);
Stanza stanza = new StanzaBuilder("ProtocolWorkerProcessTestCase", "testNSURI").build();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanza,
sessionStateHolder);
stanzaHandler.assertHandlerCalled();
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertNull("no emmitter, no response", recordedResponse);
}
public void testProcessStanzaWithResponse() {
sessionContext.setSessionState(SessionState.AUTHENTICATED);
CallTestStanzaHandlerResponse stanzaHandler = new CallTestStanzaHandlerResponse("ProtocolWorkerProcessTestCase");
namespaceHandlerDictionary.register(stanzaHandler);
Stanza stanza = new StanzaBuilder("ProtocolWorkerProcessTestCase", "testNSURI").build();
Stanza responseStanza = new StanzaBuilder("response").build();
stanzaHandler.setResponseStanza(responseStanza);
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanza,
sessionStateHolder);
stanzaHandler.assertHandlerCalled();
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertEquals("response handled", responseStanza, recordedResponse);
stanzaHandler.setResponseStanza(null);
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanza,
sessionStateHolder);
assertNull("handler emmitted null as response", stanzaHandler.getUniqueResponseStanza());
}
public void testHandlerThrowProtocolException() {
sessionContext.setSessionState(SessionState.AUTHENTICATED);
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("ProtocolWorkerProcessTestCase");
namespaceHandlerDictionary.register(stanzaHandler);
stanzaHandler.setProtocolException(new ProtocolException("forced error"));
Stanza stanza = new StanzaBuilder("ProtocolWorkerProcessTestCase", "testNSURI").build();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanza,
sessionStateHolder);
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertEquals("bad format", "error", recordedResponse.getName());
assertTrue("closed", sessionContext.isClosed());
}
public void testProcessWrongStartStanza() {
sessionContext.setSessionState(SessionState.INITIATED);
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("ProtocolWorkerProcessTestCase");
namespaceHandlerDictionary.register(stanzaHandler);
Stanza stanza = new StanzaBuilder("ProtocolWorkerProcessTestCase", "testNSURI").build();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanza,
sessionStateHolder);
try {
stanzaHandler.assertHandlerCalled();
fail("handler called");
} catch (Exception e) {
// not called, OK
}
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertEquals("open stream", "stream", recordedResponse.getName());
XMLElementVerifier xmlElementVerifier = recordedResponse.getVerifier();
assertTrue("error embedded", xmlElementVerifier.subElementPresent("error"));
XMLElement error = (XMLElement) recordedResponse.getInnerFragments().get(0);
assertEquals("bad format", "error", error.getName());
assertTrue("closed", sessionContext.isClosed());
}
public void testDetectWrongFromAddress() throws XMLSemanticError {
Entity server = sessionContext.getServerRuntimeContext().getServerEntity();
sessionContext.setSessionState(SessionState.AUTHENTICATED);
// the session is running for 'mark'
sessionContext.setInitiatingEntity(new EntityImpl("mark", server.getDomain(), null));
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("iq");
namespaceHandlerDictionary.register(stanzaHandler);
StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(null, null, IQStanzaType.GET, "test");
// we set a different from user name 'ernest'!
stanzaBuilder.addAttribute("from", new EntityImpl("ernest", server.getDomain(), null).getFullQualifiedName());
stanzaBuilder.startInnerElement("query", "jabber:iq:roster").endInnerElement();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanzaBuilder.build(),
sessionStateHolder);
try {
stanzaHandler.assertHandlerCalled();
fail("handler called");
} catch (Exception e) {
// not called, OK
}
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertUnknownSenderError(recordedResponse);
}
public void testAllowProperFromResourceId() throws XMLSemanticError, BindException {
Entity server = sessionContext.getServerRuntimeContext().getServerEntity();
sessionContext.setSessionState(SessionState.AUTHENTICATED);
// the session is running for 'charlotte'
sessionContext.setInitiatingEntity(new EntityImpl("charlotte", server.getDomain(), null));
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("iq", "testNSURI");
namespaceHandlerDictionary.register(stanzaHandler);
String onlyBoundResource = sessionContext.bindResource();
StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(null, null, IQStanzaType.GET, "test");
stanzaBuilder.addAttribute("from", new EntityImpl("charlotte", server.getDomain(), onlyBoundResource)
.getFullQualifiedName());
stanzaBuilder.startInnerElement("query", "testNSURI").endInnerElement();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanzaBuilder.build(),
sessionStateHolder);
stanzaHandler.assertHandlerCalled();
}
public void testDetectWrongFromResourceId() throws XMLSemanticError, BindException {
Entity server = sessionContext.getServerRuntimeContext().getServerEntity();
sessionContext.setSessionState(SessionState.AUTHENTICATED);
// the session is running for 'charlotte'
sessionContext.setInitiatingEntity(new EntityImpl("charlotte", server.getDomain(), null));
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("iq", "testNSURI");
namespaceHandlerDictionary.register(stanzaHandler);
String onlyBoundResource = sessionContext.bindResource();
String arbitraryUnboundResource = "unboundResourceID";
StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(null, null, IQStanzaType.GET, "test");
stanzaBuilder.addAttribute("from", new EntityImpl("charlotte", server.getDomain(), arbitraryUnboundResource)
.getFullQualifiedName());
stanzaBuilder.startInnerElement("query", "testNSURI").endInnerElement();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanzaBuilder.build(),
sessionStateHolder);
try {
stanzaHandler.assertHandlerCalled();
fail("handler called");
} catch (Exception e) {
// not called, OK
}
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertUnknownSenderError(recordedResponse);
}
public void testAllowBareFromEntityOnlyOnSingleBoundResource() throws XMLSemanticError, BindException {
// from="client@vysper.org" is only allowed when a single resource is bound
// if there is more than one resource bound in the same session, from must come
// fully qualified, e.g. from="client@vysper.org/resourceId"
Entity server = sessionContext.getServerRuntimeContext().getServerEntity();
sessionContext.setSessionState(SessionState.AUTHENTICATED);
// the session is running for 'lea'
sessionContext.setInitiatingEntity(new EntityImpl("lea", server.getDomain(), null));
CallTestStanzaHandler stanzaHandler = new CallTestStanzaHandler("iq", "testNSURI");
namespaceHandlerDictionary.register(stanzaHandler);
String firstBoundResource = sessionContext.bindResource();
String secondBoundResource = sessionContext.bindResource();
StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(null, null, IQStanzaType.GET, "test");
stanzaBuilder.addAttribute("from", new EntityImpl("lea", server.getDomain(), null).getFullQualifiedName());
stanzaBuilder.startInnerElement("query", "testNSURI").endInnerElement();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanzaBuilder.build(),
sessionStateHolder);
Stanza recordedResponse = sessionContext.getNextRecordedResponse();
assertUnknownSenderError(recordedResponse); // not allowed, bare id without resource and two resources bound
sessionContext.reset();
// unbind second resource, leaving only one
boolean noResourceRemains = sessionContext.getServerRuntimeContext().getResourceRegistry().unbindResource(
secondBoundResource);
assertFalse(noResourceRemains);
// bare id allowed, only one resource is bound
stanzaBuilder = StanzaBuilder.createIQStanza(null, null, IQStanzaType.GET, "test");
stanzaBuilder.addAttribute("from", new EntityImpl("lea", server.getDomain(), null).getFullQualifiedName());
stanzaBuilder.startInnerElement("query", "testNSURI").endInnerElement();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanzaBuilder.build(),
sessionStateHolder);
stanzaHandler.assertHandlerCalled();
sessionContext.reset();
// second resource is now invalid and cannot be used anymore in a full qualified entity
stanzaBuilder = StanzaBuilder.createIQStanza(null, null, IQStanzaType.GET, "test");
stanzaBuilder.addAttribute("from", new EntityImpl("lea", server.getDomain(), secondBoundResource)
.getFullQualifiedName());
stanzaBuilder.startInnerElement("query", "testNSURI").endInnerElement();
protocolWorker.processStanza(sessionContext.getServerRuntimeContext(), sessionContext, stanzaBuilder.build(),
sessionStateHolder);
recordedResponse = sessionContext.getNextRecordedResponse();
assertUnknownSenderError(recordedResponse);
}
private void assertUnknownSenderError(Stanza recordedResponse) throws XMLSemanticError {
XMLElementVerifier verifier = recordedResponse.getVerifier();
assertEquals("iq stanza error", "iq", recordedResponse.getName());
IQStanza iqStanza = (IQStanza) XMPPCoreStanza.getWrapper(recordedResponse);
assertEquals("error", iqStanza.getType());
assertTrue("error embedded", verifier.subElementPresent("error"));
XMLElement errorInner = recordedResponse.getSingleInnerElementsNamed("error");
assertEquals("modify", errorInner.getAttributeValue("type"));
XMLElementVerifier errorVerifier = errorInner.getVerifier();
errorVerifier.subElementPresent("unknown-sender");
}
}