package org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.get.items;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import org.buddycloud.channelserver.Configuration;
import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.db.ClosableIteratorImpl;
import org.buddycloud.channelserver.db.CloseableIterator;
import org.buddycloud.channelserver.db.exception.NodeStoreException;
import org.buddycloud.channelserver.packetHandler.iq.IQTestHandler;
import org.buddycloud.channelserver.pubsub.accessmodel.AccessModels;
import org.buddycloud.channelserver.pubsub.affiliation.Affiliations;
import org.buddycloud.channelserver.pubsub.model.NodeItem;
import org.buddycloud.channelserver.pubsub.model.NodeMembership;
import org.buddycloud.channelserver.pubsub.model.impl.NodeItemImpl;
import org.buddycloud.channelserver.pubsub.model.impl.NodeMembershipImpl;
import org.buddycloud.channelserver.pubsub.subscription.Subscriptions;
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.NodeAclRefuseReason;
import org.buddycloud.channelserver.utils.node.NodeViewAcl;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.tree.BaseElement;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
import org.xmpp.resultsetmanagement.ResultSetImpl;
public class NodeItemsGetTest extends IQTestHandler {
private IQ request;
private NodeItemsGet itemsGet;
private Element element;
private BlockingQueue<Packet> queue = new LinkedBlockingQueue<Packet>();
private String node = "/user/francisco@denmark.lit/posts";
private JID jid = new JID("juliet@shakespeare.lit");
private ChannelManager channelManager;
private NodeViewAcl nodeViewAcl;
@Before
public void setUp() throws Exception {
queue = new LinkedBlockingQueue<Packet>();
itemsGet = new NodeItemsGet(queue, channelManager);
request = readStanzaAsIq("/iq/pubsub/items/request.stanza");
element = new BaseElement("items");
channelManager = Mockito.mock(ChannelManager.class);
Configuration.getInstance().putProperty(
Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, Boolean.TRUE.toString());
itemsGet.setChannelManager(channelManager);
ArrayList<NodeMembership> nodeMemberships = new ArrayList<NodeMembership>();
Mockito.when(channelManager.getNodeMemberships(Mockito.anyString())).thenReturn(
new ResultSetImpl<NodeMembership>(nodeMemberships)
);
ArrayList<NodeMembership> userMemberships = new ArrayList<NodeMembership>();
Mockito.when(channelManager.getUserMemberships(Mockito.any(JID.class))).thenReturn(
new ResultSetImpl<NodeMembership>(userMemberships)
);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.member, null));
nodeViewAcl = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAcl)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAcl);
}
@Test
public void testPassingItemsAsElementNameReturnsTrue() {
Assert.assertTrue(itemsGet.accept(element));
}
@Test
public void testPassingNotItemsAsElementNameReturnsFalse() {
Element element = new BaseElement("not-items");
Assert.assertFalse(itemsGet.accept(element));
}
@Test
public void testExternalNodeReturnsExpectedStanzaEarly() throws Exception {
Configuration.getInstance().putProperty(
Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, Boolean.FALSE.toString());
IQ request = this.request.createCopy();
request.getChildElement().element(XMLConstants.ITEMS_ELEM).attribute(XMLConstants.NODE_ATTR).detach();
request.getChildElement().element(XMLConstants.ITEMS_ELEM).addAttribute(XMLConstants.NODE_ATTR, "/user/user@remote-server.com/posts");
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
Element element = response.getElement();
Assert.assertEquals(IQ.Type.get.toString(),
element.attributeValue("type"));
Assert.assertEquals("remote-server.com", response.getTo().getDomain());
Assert.assertEquals(element.element("pubsub").element("actor")
.getText(), response.getFrom().toBareJID());
}
@Test
public void nodeWhichDoesntExistReturnsNotFoundStanza()
throws Exception {
Mockito.when(channelManager.nodeExists(node)).thenReturn(false);
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
Assert.assertEquals(PacketError.Type.cancel, error.getType());
Assert.assertEquals(PacketError.Condition.item_not_found,
error.getCondition());
}
@Test
public void nodeStoreExceptionReturnsInternalServerErrorStanza()
throws Exception {
Mockito.when(channelManager.nodeExists(node)).thenThrow(
NodeStoreException.class);
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
Assert.assertEquals(PacketError.Type.wait, error.getType());
Assert.assertEquals(PacketError.Condition.internal_server_error,
error.getCondition());
}
@Test
public void testSubscriptionIncompatibleWithItemRetrievalReturnsExpectedStanza()
throws Exception {
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
new NodeMembershipImpl(node, jid, Subscriptions.none,
Affiliations.none, null));
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(false)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
NodeAclRefuseReason refusalReason = new NodeAclRefuseReason(
PacketError.Type.auth, PacketError.Condition.forbidden,
"pending-subscription");
Mockito.when(nodeViewAclMock.getReason()).thenReturn(refusalReason);
itemsGet.setNodeViewAcl(nodeViewAclMock);
itemsGet.process(element, jid, request, null);
Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
PacketError error = response.getError();
Assert.assertNotNull(error);
Assert.assertEquals(PacketError.Type.auth, error.getType());
Assert.assertEquals(PacketError.Condition.forbidden,
error.getCondition());
Assert.assertEquals("pending-subscription",
error.getApplicationConditionName());
}
@Test
public void testStandardNodeWithNoItemsReturnsNoItems() throws Exception {
AccessModels accessModel = AccessModels.authorize;
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
Mockito.when(
channelManager.getNodeItems(Mockito.anyString(),
Mockito.anyString(), Mockito.anyInt(), Mockito.eq(false)))
.thenReturn(null);
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAclMock);
itemsGet.process(element, jid, request, null);
Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
Element element = response.getElement();
Assert.assertEquals(IQ.Type.result.toString(),
element.attributeValue("type"));
Assert.assertEquals(node, element.element("pubsub").element("items")
.attributeValue("node"));
Assert.assertNull(element.element("pubsub").element("items")
.element("item"));
}
@Test
public void testUnparsableNodeEntryIsIgnoredInItemsResponse()
throws Exception {
AccessModels accessModel = AccessModels.authorize;
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
NodeItem item = Mockito.mock(NodeItem.class);
Mockito.when(item.getId()).thenReturn("id");
Mockito.when(item.getNodeId()).thenReturn(node);
Mockito.when(item.getPayload())
.thenReturn("<entry>entry <text><entry>");
NodeItem[] items = new NodeItem[2];
items[0] = item;
items[1] = item;
CloseableIterator<NodeItem> itemList = new ClosableIteratorImpl<NodeItem>(
Arrays.asList(items).iterator());
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
Mockito.anyInt(), Mockito.eq(false));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAclMock);
itemsGet.process(element, jid, request, null);
Packet response = queue.poll(100, TimeUnit.MILLISECONDS);
Element element = response.getElement();
Assert.assertEquals(IQ.Type.result.toString(),
element.attributeValue("type"));
Assert.assertEquals(node, element.element("pubsub").element("items")
.attributeValue("node"));
Assert.assertEquals(0, element.element("pubsub").element("items")
.nodeCount());
}
@Test
public void testPostsNodeReturnsItemsAsExpected() throws Exception {
AccessModels accessModel = AccessModels.authorize;
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
NodeItem item = Mockito.mock(NodeItem.class);
Mockito.when(item.getId()).thenReturn("id");
Mockito.when(item.getNodeId()).thenReturn(node);
Mockito.when(item.getPayload()).thenReturn("<entry>entry text</entry>");
NodeItem[] items = new NodeItem[2];
items[0] = item;
items[1] = item;
CloseableIterator<NodeItem> itemList = new ClosableIteratorImpl<NodeItem>(
Arrays.asList(items).iterator());
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
Mockito.anyInt(), Mockito.eq(false));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAclMock);
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
Element element = response.getElement();
Assert.assertEquals(IQ.Type.result.toString(),
element.attributeValue("type"));
Assert.assertEquals(node, element.element("pubsub").element("items")
.attributeValue("node"));
Assert.assertEquals(2, element.element("pubsub").element("items")
.nodeCount());
Assert.assertEquals("id", element.element("pubsub").element("items")
.element("item").attributeValue("id"));
Assert.assertEquals("entry text",
element.element("pubsub").element("items").element("item")
.elementText("entry"));
}
@Test
public void testPagingAfterItem() throws Exception {
Element rsm = new BaseElement(new QName("set", new Namespace("",
"http://jabber.org/protocol/rsm")));
rsm.addElement("after").setText(
"tag:denmark.lit,/user/" + node + "/posts,item-id");
Mockito.when(channelManager.nodeExists(anyString())).thenReturn(true);
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
itemsGet.process(element, jid, request, rsm);
verify(channelManager).getNodeItems(anyString(), eq("item-id"),
anyInt(), Mockito.eq(false));
}
@Test
public void pagingAfterItemWithPlainNodeID() throws Exception {
Element rsm = new BaseElement(new QName("set", new Namespace("",
"http://jabber.org/protocol/rsm")));
rsm.addElement("after").setText("item-id");
Mockito.when(channelManager.nodeExists(anyString())).thenReturn(true);
itemsGet.process(element, jid, request, rsm);
verify(channelManager).getNodeItems(anyString(), eq("item-id"),
anyInt(), Mockito.eq(false));
}
@Test
public void pagingAfterItemWithInvalidNode() throws Exception {
Element rsm = new BaseElement(new QName("set", new Namespace("",
"http://jabber.org/protocol/rsm")));
rsm.addElement("after").setText(
"tag:denmark.lit,/user/juliet@capulet.lit/posts,item-id");
element.addAttribute("node", "/user/francisco@denmark.lit/posts");
Mockito.when(channelManager.nodeExists(anyString())).thenReturn(true);
itemsGet.process(element, jid, request, rsm);
Packet p = queue.poll();
assertEquals("Error expected", "error",
p.getElement().attributeValue("type"));
}
@Test
public void getItemNotFoundIfSingleItemNotFound() throws Exception {
element.addAttribute("node", "/user/francisco@denmark.lit/posts");
element.addElement("item").addAttribute("id", "12345");
itemsGet.process(element, jid, request, null);
Packet p = queue.poll();
assertEquals("Error expected", "error",
p.getElement().attributeValue("type"));
assertEquals("Expected 'cancel'", "cancel",
p.getElement().element("error").attributeValue("type"));
assertNotNull(p.getElement().element("error").element("item-not-found"));
}
@Test
public void canRetrieveSingleItem() throws Exception {
String id = "12345";
String payload = "<entry>entry text</entry>";
Mockito.when(channelManager.nodeExists(Mockito.anyString()))
.thenReturn(true);
NodeItem dbItem = new NodeItemImpl(node, id, new Date(), payload);
Mockito.when(
channelManager.getNodeItem(Mockito.eq(node),
Mockito.eq(id))).thenReturn(dbItem);
IQ request = this.request.createCopy();
Element item = request.getChildElement().element("items").addElement("item");
item.addAttribute("id", id);
System.out.println(request.toXML());
itemsGet.process(element, jid, request, null);
IQ response = (IQ) queue.poll();
Element element = response.getChildElement();
Element items = element.element("items");
Assert.assertEquals(IQ.Type.result,
response.getType());
Assert.assertEquals(node, items
.attributeValue("node"));
Assert.assertEquals(1, items
.nodeCount());
Assert.assertEquals(node, items
.attributeValue("node"));
Assert.assertEquals(id, items
.element("item").attributeValue("id"));
Assert.assertEquals("entry text",
items.element("item")
.elementText("entry"));
}
@Test
public void settingParentOnlyToTrueRequestsParentOnlyItems() throws Exception {
AccessModels accessModel = AccessModels.authorize;
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
NodeItem item = Mockito.mock(NodeItem.class);
Mockito.when(item.getId()).thenReturn("id");
Mockito.when(item.getNodeId()).thenReturn(node);
Mockito.when(item.getPayload()).thenReturn("<entry>entry text</entry>");
NodeItem[] items = new NodeItem[2];
items[0] = item;
items[1] = item;
CloseableIterator<NodeItem> itemList = new ClosableIteratorImpl<NodeItem>(
Arrays.asList(items).iterator());
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
Mockito.anyInt(), Mockito.eq(true));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAclMock);
IQ request = this.request.createCopy();
request.getChildElement().element("items").addAttribute("parent-only", "true");
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
Assert.assertEquals(2, response.getElement().element("pubsub").element("items")
.nodeCount());
}
@Test
public void settingParentOnlyToOneRequestsParentOnlyItems() throws Exception {
AccessModels accessModel = AccessModels.authorize;
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
NodeItem item = Mockito.mock(NodeItem.class);
Mockito.when(item.getId()).thenReturn("id");
Mockito.when(item.getNodeId()).thenReturn(node);
Mockito.when(item.getPayload()).thenReturn("<entry>entry text</entry>");
NodeItem[] items = new NodeItem[2];
items[0] = item;
items[1] = item;
CloseableIterator<NodeItem> itemList = new ClosableIteratorImpl<NodeItem>(
Arrays.asList(items).iterator());
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
Mockito.anyInt(), Mockito.eq(true));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAclMock);
IQ request = this.request.createCopy();
request.getChildElement().element("items").addAttribute("parent-only", "1");
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
Assert.assertEquals(2, response.getElement().element("pubsub").element("items")
.nodeCount());
}
@Test
public void settingIllegalParentOnlyAttributeDoesNotRequestParentOnlyItems() throws Exception {
AccessModels accessModel = AccessModels.authorize;
NodeMembershipImpl membership = Mockito.mock(NodeMembershipImpl.class);
Mockito.when(membership.getAffiliation()).thenReturn(
Affiliations.member);
Mockito.when(membership.getSubscription()).thenReturn(
Subscriptions.subscribed);
Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn(
membership);
NodeItem item = Mockito.mock(NodeItem.class);
Mockito.when(item.getId()).thenReturn("id");
Mockito.when(item.getNodeId()).thenReturn(node);
Mockito.when(item.getPayload()).thenReturn("<entry>entry text</entry>");
NodeItem[] items = new NodeItem[2];
items[0] = item;
items[1] = item;
CloseableIterator<NodeItem> itemList = new ClosableIteratorImpl<NodeItem>(
Arrays.asList(items).iterator());
Mockito.doReturn(itemList)
.when(channelManager)
.getNodeItems(Mockito.anyString(), Mockito.anyString(),
Mockito.anyInt(), Mockito.eq(false));
Mockito.when(channelManager.nodeExists(node)).thenReturn(true);
NodeViewAcl nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
Mockito.doReturn(true)
.when(nodeViewAclMock)
.canViewNode(Mockito.anyString(),
Mockito.any(NodeMembership.class),
Mockito.any(AccessModels.class), Mockito.anyBoolean());
itemsGet.setNodeViewAcl(nodeViewAclMock);
IQ request = this.request.createCopy();
request.getChildElement().element("items").addAttribute("parent-only", "invalidvalue");
itemsGet.process(element, jid, request, null);
Packet response = queue.poll();
Assert.assertEquals(2, response.getElement().element("pubsub").element("items")
.nodeCount());
}
}