blob: ba37ca52a305bd57061917f44b982868a586b75c [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.modules.extension.xep0045_muc.handler;
import java.util.ArrayList;
import java.util.List;
import org.apache.vysper.xml.fragment.XMLElement;
import org.apache.vysper.xml.fragment.XMLElementBuilder;
import org.apache.vysper.xml.fragment.XMLElementVerifier;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.RecordingStanzaBroker;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.TestSessionContext;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Affiliation;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.ConferenceTestUtils;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Occupant;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Role;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Room;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.RoomType;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.History;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.Password;
import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.X;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
import org.apache.vysper.xmpp.protocol.ProtocolException;
import org.apache.vysper.xmpp.protocol.SimpleStanzaBroker;
import org.apache.vysper.xmpp.protocol.StanzaHandler;
import org.apache.vysper.xmpp.server.SessionContext;
import org.apache.vysper.xmpp.stanza.MessageStanza;
import org.apache.vysper.xmpp.stanza.Stanza;
import org.apache.vysper.xmpp.stanza.StanzaBuilder;
import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
import org.apache.vysper.xmpp.stanza.StanzaErrorType;
/**
*/
public class EnterRoomTestCase extends AbstractMUCHandlerTestCase {
private Stanza enterRoom(Entity occupantJid, Entity roomJid) throws ProtocolException {
return enterRoom(occupantJid, roomJid, null, null, false);
}
private Stanza enterRoom(Entity occupantJid, Entity roomJid, String password, History history, boolean oldProtocol)
throws ProtocolException {
SessionContext userSessionContext;
if (occupantJid.equals(OCCUPANT1_JID)) {
userSessionContext = sessionContext;
} else {
userSessionContext = sessionContext2;
}
StanzaBuilder stanzaBuilder = StanzaBuilder.createPresenceStanza(occupantJid, roomJid, null, null, null, null);
if (!oldProtocol) {
List<XMLElement> xInnerElms = new ArrayList<XMLElement>();
if (password != null) {
xInnerElms.add(new Password(password));
}
if (history != null) {
xInnerElms.add(history);
}
stanzaBuilder.addPreparedElement(new X(xInnerElms));
}
Stanza presenceStanza = stanzaBuilder.build();
RecordingStanzaBroker stanzaBroker = new RecordingStanzaBroker(
new SimpleStanzaBroker(sessionContext.getStanzaRelay(), sessionContext));
handler.execute(presenceStanza, userSessionContext.getServerRuntimeContext(), true, userSessionContext, null,
stanzaBroker);
return stanzaBroker.getUniqueStanzaWrittenToSession();
}
protected TestSessionContext sessionContext2;
@Override
protected void setUp() throws Exception {
super.setUp();
sessionContext2 = TestSessionContext.createWithStanzaReceiverRelayAuthenticated();
sessionContext2.setInitiatingEntity(OCCUPANT2_JID);
}
@Override
protected StanzaHandler createHandler() {
return new MUCPresenceHandler(conference);
}
public void testEnterExistingRoom() throws Exception {
Room room = conference.findRoom(ROOM1_JID);
assertEquals(0, room.getOccupantCount());
enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK);
assertEquals(1, room.getOccupantCount());
Occupant occupant = room.getOccupants().iterator().next();
assertEquals(OCCUPANT1_JID, occupant.getJid());
assertEquals("nick", occupant.getNick());
}
public void testEnterWithGroupchatProtocol() throws Exception {
Room room = conference.findRoom(ROOM1_JID);
assertEquals(0, room.getOccupantCount());
// enter using the old groupchat protocol
enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK, null, null, true);
assertEquals(1, room.getOccupantCount());
Occupant occupant = room.getOccupants().iterator().next();
assertEquals(OCCUPANT1_JID, occupant.getJid());
assertEquals("nick", occupant.getNick());
}
public void testEnterAsAdmin() throws Exception {
Room room = conference.findRoom(ROOM1_JID);
room.getAffiliations().add(OCCUPANT1_JID, Affiliation.Admin);
enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK);
Occupant occupant = room.getOccupants().iterator().next();
assertEquals(Affiliation.Admin, occupant.getAffiliation());
}
public void testEnterAsOutcast() throws Exception {
Room room = conference.findRoom(ROOM1_JID);
room.getAffiliations().add(OCCUPANT1_JID, Affiliation.Outcast);
Stanza error = enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK);
assertPresenceErrorStanza(error, ROOM1_JID, OCCUPANT1_JID, StanzaErrorType.AUTH,
StanzaErrorCondition.FORBIDDEN);
assertEquals(0, room.getOccupantCount());
}
public void testEnterAsNonMember() throws Exception {
Room room = conference.createRoom(ROOM2_JID, "Room", RoomType.MembersOnly);
Stanza error = enterRoom(OCCUPANT1_JID, ROOM2_JID_WITH_NICK);
assertPresenceErrorStanza(error, ROOM2_JID, OCCUPANT1_JID, StanzaErrorType.AUTH,
StanzaErrorCondition.REGISTRATION_REQUIRED);
assertEquals(0, room.getOccupantCount());
}
public void testEnterRoomWithDuplicateNick() throws Exception {
Room room1 = conference.findRoom(ROOM1_JID);
room1.setRewriteDuplicateNick(false); // do not rewrite existing nick, second join will fail
assertNull(enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK)); // 1st join
Stanza error = enterRoom(OCCUPANT2_JID, ROOM1_JID_WITH_NICK); // 2nd join
assertNotNull(error);
}
public void testEnterRoomWithDuplicateNick_Rewrite() throws Exception {
Room room1 = conference.findRoom(ROOM1_JID);
room1.setRewriteDuplicateNick(true); // do rewrite nick, second join will succeed
assertNull(enterRoom(OCCUPANT2_JID, ROOM1_JID_WITH_NICK)); // 1st join
Stanza error = enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK); // 2nd join
assertNull(error);
final Stanza stanza1 = occupant1Queue.getNext();
final Stanza stanza2 = occupant1Queue.getNext();
final XMLElementVerifier verifier = stanza2.getVerifier();
final X x = X.fromStanza(stanza2);
final List<XMLElement> statuses = x.getInnerElementsNamed("status");
boolean rewriteCode = false;
for (XMLElement status : statuses) {
final String code = status.getAttributeValue("code");
if ("210".equals(code))
rewriteCode = true;
}
assertTrue(rewriteCode);
}
public void testEnterNonExistingRoom() throws Exception {
Room room = conference.findRoom(ROOM2_JID);
assertNull(room);
enterRoom(OCCUPANT1_JID, ROOM2_JID_WITH_NICK);
room = conference.findRoom(ROOM2_JID);
assertNotNull(room);
assertEquals(1, room.getOccupantCount());
Occupant occupant = room.getOccupants().iterator().next();
assertEquals(OCCUPANT1_JID, occupant.getJid());
assertEquals("nick", occupant.getNick());
assertEquals(Role.Moderator, occupant.getRole());
}
public void testEnterWithoutNick() throws Exception {
// try entering without a nick
Stanza response = enterRoom(OCCUPANT1_JID, ROOM1_JID);
assertPresenceErrorStanza(response, ROOM1_JID, OCCUPANT1_JID, StanzaErrorType.MODIFY,
StanzaErrorCondition.JID_MALFORMED);
}
public void testEnterWithPassword() throws Exception {
Room room = conference.createRoom(ROOM2_JID, "Room 1", RoomType.PasswordProtected);
room.setPassword("secret");
// no error should be returned
assertNull(enterRoom(OCCUPANT1_JID, ROOM2_JID_WITH_NICK, "secret", null, false));
assertEquals(1, room.getOccupantCount());
}
public void testEnterWithoutPassword() throws Exception {
Room room = conference.createRoom(ROOM2_JID, "Room 1", RoomType.PasswordProtected);
room.setPassword("secret");
// try entering without a password
Stanza response = enterRoom(OCCUPANT1_JID, ROOM2_JID_WITH_NICK);
assertPresenceErrorStanza(response, ROOM2_JID, OCCUPANT1_JID, StanzaErrorType.AUTH,
StanzaErrorCondition.NOT_AUTHORIZED);
}
private void assertPresenceErrorStanza(Stanza response, Entity from, Entity to, StanzaErrorType type,
StanzaErrorCondition errorName) {
XMLElement xElement = new XMLElementBuilder("x", NamespaceURIs.XEP0045_MUC).build();
assertErrorStanza(response, "presence", from, to, type, errorName, xElement);
}
public void testEnterRoomWithRelays() throws Exception {
// add one occupant to the room
Room room = ConferenceTestUtils.findOrCreateRoom(conference, ROOM1_JID, "Room 1");
room.addOccupant(OCCUPANT2_JID, "Some nick");
// now, let user 1 enter room
enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK);
// verify stanzas to existing occupants on the new user
Stanza user1JoinedStanza = occupant2Queue.getNext();
// should be from room + nick name
assertEquals(ROOM1_JID.getFullQualifiedName() + "/nick", user1JoinedStanza.getFrom().getFullQualifiedName());
// should be to the existing user
assertEquals(OCCUPANT2_JID, user1JoinedStanza.getTo());
XMLElement xElement = user1JoinedStanza.getSingleInnerElementsNamed("x");
assertEquals(NamespaceURIs.XEP0045_MUC_USER, xElement.getNamespaceURI());
// since this room is non-anonymous, x must contain an item element with the
// users full JID
XMLElement itemElement = xElement.getSingleInnerElementsNamed("item");
assertEquals(OCCUPANT1_JID.getFullQualifiedName(), itemElement.getAttributeValue("jid"));
assertEquals("none", itemElement.getAttributeValue("affiliation"));
assertEquals("participant", itemElement.getAttributeValue("role"));
// verify stanzas to the new user on all existing users, including himself with
// status=110 element
// own presence must be sent last
// assert the stanza from the already existing user
Stanza stanza = occupant1Queue.getNext();
assertNotNull(stanza);
assertEquals(ROOM1_JID.getFullQualifiedName() + "/Some nick", stanza.getFrom().getFullQualifiedName());
assertEquals(OCCUPANT1_JID, stanza.getTo());
// assert stanza from the joining user, must have extra status=110 element
stanza = occupant1Queue.getNext();
assertNotNull(stanza);
assertEquals(ROOM1_JID_WITH_NICK, stanza.getFrom());
assertEquals(OCCUPANT1_JID, stanza.getTo());
List<XMLElement> statusElements = stanza.getFirstInnerElement().getInnerElementsNamed("status");
assertEquals(2, statusElements.size());
assertEquals("100", statusElements.get(0).getAttributeValue("code"));
assertEquals("110", statusElements.get(1).getAttributeValue("code"));
}
public void testDiscussionHistory() throws Exception {
// add some messages
Room room = ConferenceTestUtils.findOrCreateRoom(conference, ROOM1_JID, "Room 1");
room.getHistory().append(createMessageStanza("Body"),
new Occupant(OCCUPANT2_JID, "nick2", room, Role.Participant));
room.getHistory().append(createMessageStanza("Body2"),
new Occupant(OCCUPANT2_JID, "nick2", room, Role.Participant));
room.getHistory().append(createMessageStanza("Body3"),
new Occupant(OCCUPANT2_JID, "nick2", room, Role.Participant));
// now, let user 1 enter room
enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK, null, new History(2, null, null, null), false);
Stanza stanza = occupant1Queue.getNext();
// first stanza should be room presence
assertNotNull(stanza);
assertEquals("presence", stanza.getName());
stanza = occupant1Queue.getNext();
// here we get the message history
assertNotNull(stanza);
assertEquals("message", stanza.getName());
MessageStanza msgStanza = (MessageStanza) MessageStanza.getWrapper(stanza);
assertEquals("Body2", msgStanza.getBody(null));
stanza = occupant1Queue.getNext();
// first stanza should be room presence
assertNotNull(stanza);
assertEquals("message", stanza.getName());
msgStanza = (MessageStanza) MessageStanza.getWrapper(stanza);
assertEquals("Body3", msgStanza.getBody(null));
// we only requested two messages
assertNull(occupant1Queue.getNext());
}
protected MessageStanza createMessageStanza(final String body) {
return ConferenceTestUtils.createMessageStanza(OCCUPANT2_JID, ROOM1_JID, body);
}
}