package org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.get;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import junit.framework.Assert;
import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.db.ClosableIteratorImpl;
import org.buddycloud.channelserver.db.exception.NodeStoreException;
import org.buddycloud.channelserver.packetHandler.iq.IQTestHandler;
import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.PubSubElementProcessorAbstract;
import org.buddycloud.channelserver.pubsub.accessmodel.AccessModels;
import org.buddycloud.channelserver.pubsub.model.NodeItem;
import org.buddycloud.channelserver.pubsub.model.impl.NodeItemImpl;
import org.buddycloud.channelserver.pubsub.model.impl.NodeMembershipImpl;
import org.buddycloud.channelserver.utils.node.NodeAclRefuseReason;
import org.buddycloud.channelserver.utils.node.NodeViewAcl;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
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;
public class ThreadGetTest extends IQTestHandler {
private static final Integer TOTAL_RESULTS = 4;
private IQ request;
private PubSubElementProcessorAbstract threadGet;
private Element element;
private BlockingQueue<Packet> queue = new LinkedBlockingQueue<Packet>();
private String node = "/user/pamela@denmark.lit/posts";
private JID jid = new JID("juliet@shakespeare.lit");
private ChannelManager channelManager;
private static final String TEST_NODE = "node1";
private NodeViewAcl nodeViewAclMock;
@Before
public void setUp() throws Exception {
queue = new LinkedBlockingQueue<Packet>();
channelManager = Mockito.mock(ChannelManager.class);
threadGet = new ThreadGet(queue, channelManager);
request = readStanzaAsIq("/iq/pubsub/thread/request.stanza");
element = new BaseElement("thread");
Mockito.when(channelManager.nodeExists(Mockito.anyString())).thenReturn(true);
Mockito.doReturn(new HashMap<String, String>()).when(channelManager).getNodeConf(Mockito.anyString());
Mockito.when(channelManager.getCountNodeThread(Mockito.anyString(), Mockito.anyString())).thenReturn(TOTAL_RESULTS);
Mockito.when(channelManager.getNodeItem(Mockito.anyString(), Mockito.anyString())).thenReturn(
new NodeItemImpl(TEST_NODE, "1", new Date(), "payload"));
nodeViewAclMock = Mockito.mock(NodeViewAcl.class);
threadGet.setNodeViewAcl(nodeViewAclMock);
Mockito.doReturn(true).when(nodeViewAclMock)
.canViewNode(Mockito.anyString(), Mockito.any(NodeMembershipImpl.class), Mockito.any(AccessModels.class), Mockito.anyBoolean());
}
@Test
public void testPassingRecentItemsAsElementNameReturnsTrue() {
Assert.assertTrue(threadGet.accept(element));
}
@Test
public void testPassingNotThreadAsElementNameReturnsFalse() {
Element element = new BaseElement("not-thread");
Assert.assertFalse(threadGet.accept(element));
}
@Test
public void testMissingNodeAttributeReturnsErrorStanza() throws Exception {
request.getChildElement().element("thread").addAttribute("node", null);
threadGet.process(element, jid, request, null);
Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
Assert.assertEquals(PacketError.Type.modify, error.getType());
Assert.assertEquals("nodeid-required", error.getApplicationConditionName());
}
@Test
public void testMissingItemIdAttributeReturnsErrorStanza() throws Exception {
request.getChildElement().element("thread").addAttribute("item_id", null);
threadGet.process(element, jid, request, null);
Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
Assert.assertEquals(PacketError.Type.modify, error.getType());
Assert.assertEquals("itemid-required", error.getApplicationConditionName());
}
@Test
public void testNodeStoreExceptionGeneratesAnErrorStanza() throws Exception {
Mockito.when(channelManager.nodeExists(Mockito.anyString())).thenThrow(new NodeStoreException());
threadGet.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 userWhoCantAccessChannelGetsPermissionErrorStanzaReply() throws Exception {
Mockito.doReturn(false).when(nodeViewAclMock)
.canViewNode(Mockito.anyString(), Mockito.any(NodeMembershipImpl.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);
threadGet.process(element, jid, request, null);
Packet response = queue.poll();
PacketError error = response.getError();
Assert.assertNotNull(error);
Assert.assertEquals(PacketError.Type.auth, error.getType());
Assert.assertEquals(PacketError.Condition.forbidden, error.getCondition());
}
@Test
public void ifItemDoesNotExistErrorStanzaIsReturned() throws Exception {
Mockito.when(channelManager.getNodeItem(Mockito.anyString(), Mockito.anyString())).thenReturn(null);
threadGet.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());
Assert.assertEquals("parent-item-not-found", error.getApplicationConditionName());
Assert.assertEquals(Buddycloud.NS_ERROR, error.getApplicationConditionNamespaceURI());
}
@Test
public void testOutgoingStanzaFormattedAsExpected() throws Exception {
ArrayList<NodeItem> expectedResults = new ArrayList<NodeItem>();
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "<entry>value1</entry>"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "<entry>value2</entry>"));
Mockito.when(channelManager.getNodeItemThread(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
threadGet.process(element, jid, request, null);
Packet response = queue.poll();
Element items = response.getElement().element("pubsub").element("items");
Assert.assertEquals("/user/channeluser@example.com/posts", items.attributeValue("node"));
Assert.assertEquals(2, items.elements("item").size());
Assert.assertEquals("1", items.element("item").attributeValue("id"));
Assert.assertEquals("value1", items.element("item").elementText("entry"));
}
@Test
public void testUnparsableItemEntriesAreSimplyIgnored() throws Exception {
ArrayList<NodeItem> expectedResults = new ArrayList<NodeItem>();
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "<entry>value1</entry>"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "<entry>value2"));
Mockito.when(channelManager.getNodeItemThread(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
threadGet.process(element, jid, request, null);
Packet response = queue.poll();
Element items = response.getElement().element("pubsub").element("items");
Assert.assertEquals("/user/channeluser@example.com/posts", items.attributeValue("node"));
Assert.assertEquals(1, items.elements("item").size());
Assert.assertEquals("1", items.element("item").attributeValue("id"));
Assert.assertEquals("value1", items.element("item").elementText("entry"));
}
@Test
public void testRsmElementIsAddedCorrectly() throws Exception {
Element rsm = request.getChildElement().addElement("set");
rsm.addNamespace("", PubSubElementProcessorAbstract.NS_RSM);
rsm.addElement("max").setText("4");
rsm.addElement("after").setText("1");
ArrayList<NodeItem> expectedResults = new ArrayList<NodeItem>();
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "<entry>value1</entry>"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "<entry>value2</entry>"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "3", new Date(), "<entry>value3</entry>"));
expectedResults.add(new NodeItemImpl(TEST_NODE, "4", new Date(), "<entry>value4</entry>"));
Mockito.when(channelManager.getNodeItemThread(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(4))).thenReturn(
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
threadGet.process(element, jid, request, null);
Packet response = queue.poll();
Element items = response.getElement().element("pubsub").element("items");
Assert.assertEquals("/user/channeluser@example.com/posts", items.attributeValue("node"));
Assert.assertEquals(4, items.elements("item").size());
Element rsmResult = response.getElement().element("pubsub").element("set");
Assert.assertEquals("1", rsmResult.elementText("first"));
Assert.assertEquals("4", rsmResult.elementText("last"));
Assert.assertEquals(String.valueOf(TOTAL_RESULTS), rsmResult.elementText("count"));
}
}