package org.buddycloud.channelserver.db.jdbc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Properties; import junit.framework.Assert; import org.buddycloud.channelserver.Configuration; import org.buddycloud.channelserver.channel.node.configuration.field.AccessModel; import org.buddycloud.channelserver.db.ClosableIteratorImpl; import org.buddycloud.channelserver.db.CloseableIterator; import org.buddycloud.channelserver.db.NodeStore; import org.buddycloud.channelserver.db.exception.ItemNotFoundException; import org.buddycloud.channelserver.db.exception.NodeStoreException; import org.buddycloud.channelserver.db.jdbc.JDBCNodeStore.NodeStoreSQLDialect; 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.impl.GlobalItemIDImpl; import org.buddycloud.channelserver.pubsub.model.impl.NodeItemImpl; import org.buddycloud.channelserver.pubsub.model.impl.NodeSubscriptionImpl; import org.buddycloud.channelserver.pubsub.subscription.Subscriptions; import org.junit.Ignore; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mockito; import org.xmpp.packet.JID; @SuppressWarnings("serial") public class JDBCNodeStoreTest extends JDBCNodeStoreAbstract { public JDBCNodeStoreTest() throws SQLException, IOException, ClassNotFoundException { dbTester = new DatabaseTester(); IQTestHandler.readConf(); } @Test public void testIsCachedJidForCachedJid() throws Exception { dbTester.loadData("node_1"); boolean result = store.isCachedJID(TEST_SERVER1_USER1_JID); assertEquals("Expected JID to be shown as cached", true, result); } @Test public void testIsCachedJidForNonCachedJid() throws Exception { dbTester.loadData("node_1"); boolean result = store.isCachedJID(new JID("anotheruser@sample.com")); assertEquals("Expected JID to be shown as not cached", false, result); } @Test public void testGetNodeItems() throws Exception { dbTester.loadData("node_1"); Iterator<NodeItem> result = store.getNodeItems(TEST_SERVER1_NODE1_ID); String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM5_ID, TEST_SERVER1_NODE1_ITEM4_ID, TEST_SERVER1_NODE1_ITEM3_ID, TEST_SERVER1_NODE1_ITEM2_ID, TEST_SERVER1_NODE1_ITEM1_ID, }; String[] expectedEntryContent = { TEST_SERVER1_NODE1_ITEM5_CONTENT, TEST_SERVER1_NODE1_ITEM4_CONTENT, TEST_SERVER1_NODE1_ITEM3_CONTENT, TEST_SERVER1_NODE1_ITEM2_CONTENT, TEST_SERVER1_NODE1_ITEM1_CONTENT, }; int i = 0; while (result.hasNext()) { NodeItem item = result.next(); assertEquals("The " + i + " node returned does not have the expected id", expectedNodeIds[i], item.getId()); assertTrue("The " + i + " node returned does not have the expected content", item .getPayload().contains(expectedEntryContent[i])); ++i; } assertEquals("Too few items returned", expectedNodeIds.length, i); assertFalse("Too many items were returned", result.hasNext()); } @Test public void testGetNodeItemsForUnknownNodeReturnsEmptyIterator() throws Exception { dbTester.loadData("node_1"); Iterator<NodeItem> result = store.getNodeItems(TEST_SERVER1_NODE2_ID); assertFalse("Items were returned but none were expected", result.hasNext()); } @Test public void testGetNodeItemsWithLimits() throws Exception { dbTester.loadData("node_1"); Iterator<NodeItem> result = store.getNodeItems(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM4_ID, 4, false); String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM3_ID, TEST_SERVER1_NODE1_ITEM2_ID, TEST_SERVER1_NODE1_ITEM1_ID }; String[] expectedEntryContent = { TEST_SERVER1_NODE1_ITEM3_CONTENT, TEST_SERVER1_NODE1_ITEM2_CONTENT, TEST_SERVER1_NODE1_ITEM1_CONTENT }; int i = 0; while (result.hasNext()) { NodeItem item = result.next(); assertEquals("The " + i + " node returned does not have the expected id", expectedNodeIds[i], item.getId()); assertTrue("The " + i + " node returned does not have the expected content", item .getPayload().contains(expectedEntryContent[i])); ++i; } assertEquals("Too few items returned", expectedNodeIds.length, i); assertFalse("Too many items were returned", result.hasNext()); } @Test public void testGetNodeItemsWithPaging() throws Exception { dbTester.loadData("node_1"); long start = System.currentTimeMillis(); NodeItem[] items = new NodeItem[20]; for (int i = 0; i < 20; i++) { items[i] = new NodeItemImpl(TEST_SERVER1_NODE1_ID, String.valueOf(i), new Date(start + i * 10), "payload" + String.valueOf(i)); store.addNodeItem(items[i]); } CloseableIterator<NodeItem> result = store.getNodeItems( TEST_SERVER1_NODE1_ID, "15", 3, false); assertEquals("Incorrect node item returned", items[14], result.next()); assertEquals("Incorrect node item returned", items[13], result.next()); assertEquals("Incorrect node item returned", items[12], result.next()); } @Test public void testGetNodeItemsWithNegativeOneCountReturnsAllItems() throws Exception { dbTester.loadData("node_1"); Iterator<NodeItem> result = store.getNodeItems(TEST_SERVER1_NODE1_ID, null, -1, false); String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM5_ID, TEST_SERVER1_NODE1_ITEM4_ID, TEST_SERVER1_NODE1_ITEM3_ID, TEST_SERVER1_NODE1_ITEM2_ID, TEST_SERVER1_NODE1_ITEM1_ID, }; String[] expectedEntryContent = { TEST_SERVER1_NODE1_ITEM5_CONTENT, TEST_SERVER1_NODE1_ITEM4_CONTENT, TEST_SERVER1_NODE1_ITEM3_CONTENT, TEST_SERVER1_NODE1_ITEM2_CONTENT, TEST_SERVER1_NODE1_ITEM1_CONTENT, }; int i = 0; while (result.hasNext()) { NodeItem item = result.next(); assertEquals("The " + i + " node returned does not have the expected id", expectedNodeIds[i], item.getId()); assertTrue("The " + i + " node returned does not have the expected content", item .getPayload().contains(expectedEntryContent[i])); ++i; } assertEquals("Too few items returned", expectedNodeIds.length, i); assertFalse("Too many items were returned", result.hasNext()); } @Test(expected = IllegalArgumentException.class) public void testGetNodeItemsWithInvalidCountThrowsException() throws Exception { store.getNodeItems(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID, -2, false); } @Test public void testGetNodeItemsWithUnknownItemReturnsAllItems() throws Exception { dbTester.loadData("node_1"); Iterator<NodeItem> result = store.getNodeItems(TEST_SERVER1_NODE1_ID, "randomunknownitemid", 10, false); String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM5_ID, TEST_SERVER1_NODE1_ITEM4_ID, TEST_SERVER1_NODE1_ITEM3_ID, TEST_SERVER1_NODE1_ITEM2_ID, TEST_SERVER1_NODE1_ITEM1_ID, }; String[] expectedEntryContent = { TEST_SERVER1_NODE1_ITEM5_CONTENT, TEST_SERVER1_NODE1_ITEM4_CONTENT, TEST_SERVER1_NODE1_ITEM3_CONTENT, TEST_SERVER1_NODE1_ITEM2_CONTENT, TEST_SERVER1_NODE1_ITEM1_CONTENT, }; int i = 0; while (result.hasNext()) { NodeItem item = result.next(); assertEquals("The " + i + " node returned does not have the expected id", expectedNodeIds[i], item.getId()); assertTrue("The " + i + " node returned does not have the expected content", item .getPayload().contains(expectedEntryContent[i])); ++i; } assertEquals("Too few items returned", expectedNodeIds.length, i); assertFalse("Too many items were returned", result.hasNext()); } @Test public void testCountNodeItems() throws Exception { dbTester.loadData("node_1"); int result = store.countNodeItems(TEST_SERVER1_NODE1_ID, false); assertEquals("Incorrect item count", 5, result); } @Test public void countNodeItemsWithNoReplies() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_4"); int result = store.countNodeItems(TEST_SERVER1_NODE1_ID, true); assertEquals("Incorrect item count", 6, result); } @Test public void testGetNewNodeItemsForUserBetweenDates() throws Exception { dbTester.loadData("node_1"); // We shouldn't see this item come out! store.addRemoteNode(TEST_SERVER2_NODE1_ID); store.addNodeItem(new NodeItemImpl(TEST_SERVER2_NODE1_ID, "1", new Date(), "item-payload")); Iterator<NodeItem> result = store.getNewNodeItemsForUser( TEST_SERVER1_USER1_JID, new Date(0), new Date()); String[] expectedNodeIds = { TEST_SERVER1_NODE1_ITEM5_ID, TEST_SERVER1_NODE1_ITEM4_ID, TEST_SERVER1_NODE1_ITEM3_ID, TEST_SERVER1_NODE1_ITEM2_ID, TEST_SERVER1_NODE1_ITEM1_ID, }; String[] expectedEntryContent = { TEST_SERVER1_NODE1_ITEM5_CONTENT, TEST_SERVER1_NODE1_ITEM4_CONTENT, TEST_SERVER1_NODE1_ITEM3_CONTENT, TEST_SERVER1_NODE1_ITEM2_CONTENT, TEST_SERVER1_NODE1_ITEM1_CONTENT, }; int i = 0; while (result.hasNext()) { NodeItem item = result.next(); assertEquals("The " + i + " node returned does not have the expected id", expectedNodeIds[i], item.getId()); assertTrue("The " + i + " node returned does not have the expected content", item .getPayload().contains(expectedEntryContent[i])); ++i; } assertEquals("Too few items returned", expectedNodeIds.length, i); assertFalse("Too many items were returned", result.hasNext()); } @Test public void testGetNewNodeItemsForUserBetweenDatesWhenOutcast() throws Exception { dbTester.loadData("node_1"); store.setUserAffiliation(TEST_SERVER1_NODE1_ID, TEST_SERVER1_USER1_JID, Affiliations.outcast); Iterator<NodeItem> result = store.getNewNodeItemsForUser( TEST_SERVER1_USER1_JID, new Date(0), new Date()); int i = 0; while (result.hasNext()) { ++i; } assertEquals(0, i); } @Test public void testCountNodeItemsNonExistantNode() throws Exception { dbTester.loadData("node_1"); int result = store.countNodeItems("iamanodewhichdoesntexist", false); assertEquals("Incorrect item count", 0, result); } @Test public void testIsCachedNode() throws Exception { dbTester.loadData("node_1"); boolean result = store.isCachedNode(TEST_SERVER1_NODE1_ID); assertEquals("Incorrect caching reported", true, result); } @Test public void testIsCachedNodeForNonCachedNode() throws Exception { dbTester.loadData("node_1"); boolean result = store.isCachedNode("iamanodewhichdoesntexist"); assertEquals("Incorrect cached response", false, result); } @Test public void testGetNodeItem() throws Exception { dbTester.loadData("node_1"); NodeItem result = store.getNodeItem(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID); assertEquals("Unexpected Node ID returned", TEST_SERVER1_NODE1_ITEM1_ID, result.getId()); assertTrue("Unexpected Node content returned", result.getPayload() .contains(TEST_SERVER1_NODE1_ITEM1_CONTENT)); } @Test public void canUpdateUpdatedDateOfItem() throws Exception { dbTester.loadData("node_1"); NodeItem result = store.getNodeItem(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID); Date originalDate = result.getUpdated(); store.updateThreadParent(result.getNodeId(), result.getId()); result = store.getNodeItem(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID); assertTrue(result.getUpdated().after(originalDate)); } @Test public void canGetItemReplies() throws Exception { dbTester.loadData("node_1"); NodeItem testItem = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(), "<entry>payload</entry>", "a5", new Date()); store.addNodeItem(testItem); ClosableIteratorImpl<NodeItem> items = store.getNodeItemReplies( TEST_SERVER1_NODE1_ID, "a5", null, true, -1); int count = 0; NodeItem item = null; while (items.hasNext()) { ++count; item = items.next(); } assertEquals(1, count); assertSameNodeItem(item, testItem); } @Test public void canGetItemRepliesWithResultSetManagement() throws Exception { dbTester.loadData("node_1"); NodeItem testItem1 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(), "<entry>payload</entry>", "a5", new Date()); NodeItem testItem2 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a7", new Date(0), "<entry>payload</entry>", "a5", new Date()); NodeItem testItem3 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a8", new Date(100), "<entry>payload</entry>", "a5", new Date()); NodeItem testItem4 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a9", new Date(200), "<entry>payload</entry>", "/full-node-item-id-ref/a5", new Date()); store.addNodeItem(testItem1); store.addNodeItem(testItem2); store.addNodeItem(testItem3); store.addNodeItem(testItem4); ClosableIteratorImpl<NodeItem> items = store.getNodeItemReplies( TEST_SERVER1_NODE1_ID, "a5", "a7", true, 2); int count = 0; ArrayList<NodeItem> itemsResult = new ArrayList<NodeItem>(); while (items.hasNext()) { ++count; itemsResult.add(items.next()); } assertEquals(2, count); assertSameNodeItem(itemsResult.get(0), testItem4); assertSameNodeItem(itemsResult.get(1), testItem1); } @Test public void canGetItemRepliesWithResultSetManagementPagingBackwards() throws Exception { dbTester.loadData("node_1"); NodeItem testItem1 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(), "<entry>payload</entry>", "a5", new Date()); Thread.sleep(100); NodeItem testItem2 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a7", new Date(), "<entry>payload</entry>", "a5", new Date()); Thread.sleep(100); NodeItem testItem3 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a8", new Date(), "<entry>payload</entry>", "a5", new Date()); Thread.sleep(100); NodeItem testItem4 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a9", new Date(), "<entry>payload</entry>", "/full-node-item-id-ref/a5", new Date()); store.addNodeItem(testItem1); store.addNodeItem(testItem2); store.addNodeItem(testItem3); store.addNodeItem(testItem4); ClosableIteratorImpl<NodeItem> items = store.getNodeItemReplies( TEST_SERVER1_NODE1_ID, "a5", "a8", false, 4); int count = 0; ArrayList<NodeItem> itemsResult = new ArrayList<NodeItem>(); while (items.hasNext()) { ++count; itemsResult.add(items.next()); } assertEquals(2, count); assertSameNodeItem(itemsResult.get(0), testItem1); assertSameNodeItem(itemsResult.get(1), testItem2); } @Test public void canGetCountOfItemReplies() throws Exception { dbTester.loadData("node_1"); NodeItem testItem = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(), "<entry>payload</entry>", "/full-node-item-id-ref/a5", new Date()); store.addNodeItem(testItem); int items = store.getCountNodeItemReplies(TEST_SERVER1_NODE1_ID, "a5"); assertEquals(1, items); } @Test public void canGetItemThread() throws Exception { dbTester.loadData("node_1"); NodeItem testItem = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(), "<entry>payload</entry>", "/full-node-item-id-ref/a5", new Date()); store.addNodeItem(testItem); ClosableIteratorImpl<NodeItem> items = store.getNodeItemThread( TEST_SERVER1_NODE1_ID, "a5", null, -1); int count = 0; NodeItem item = null; while (items.hasNext()) { ++count; item = items.next(); } assertEquals(2, count); assertSameNodeItem(item, testItem); } @Test public void canGetItemThreadWithResultSetManagement() throws Exception { dbTester.loadData("node_1"); NodeItem testItemParent = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a100", new Date(100), "<entry>payload parent</entry>", null, new Date()); NodeItem testItem1 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(20), "<entry>payload</entry>", "a100", new Date()); NodeItem testItem2 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a7", new Date(40), "<entry>payload</entry>", "a100", new Date()); NodeItem testItem3 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "/full-node-item-id-ref/a8", new Date(80), "<entry>payload</entry>", "a100", new Date()); NodeItem testItem4 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a9", new Date(160), "<entry>payload</entry>", "a100", new Date()); store.addNodeItem(testItemParent); store.addNodeItem(testItem1); store.addNodeItem(testItem2); store.addNodeItem(testItem3); store.addNodeItem(testItem4); ClosableIteratorImpl<NodeItem> items = store.getNodeItemThread( TEST_SERVER1_NODE1_ID, "a100", "a7", 2); int count = 0; ArrayList<NodeItem> itemsResult = new ArrayList<NodeItem>(); while (items.hasNext()) { ++count; itemsResult.add(items.next()); } assertEquals(2, count); assertSameNodeItem(itemsResult.get(0), testItemParent); assertSameNodeItem(itemsResult.get(1), testItem4); } @Test public void canGetCountOfItemThread() throws Exception { dbTester.loadData("node_1"); NodeItem testItem = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6", new Date(), "<entry>payload</entry>", "/full-node-item-id-ref/a5", new Date()); store.addNodeItem(testItem); int items = store.getCountNodeThread(TEST_SERVER1_NODE1_ID, "a5"); assertEquals(2, items); } @Test public void testAddNodeItem() throws Exception { dbTester.loadData("node_1"); final String itemId = "test-item-id"; final Timestamp updated = new Timestamp(System.currentTimeMillis()); final String testContent = "<content>Hello World</content>"; NodeItem item = new NodeItemImpl(TEST_SERVER1_NODE1_ID, itemId, updated, testContent); store.addNodeItem(item); dbTester.assertions().assertTableContains("items", new HashMap<String, Object>() { { put("node", TEST_SERVER1_NODE1_ID); put("id", itemId); put("updated", updated); put("xml", testContent); } }); } @Test public void addNoteItemWithInReplyTo() throws Exception { dbTester.loadData("node_1"); final String itemId = "test-item-id"; final Timestamp updated = new Timestamp(System.currentTimeMillis()); final String testContent = "<content>Hello World</content>"; final String inReplyTo = "a5"; NodeItem item = new NodeItemImpl(TEST_SERVER1_NODE1_ID, itemId, updated, testContent, "a5", new Date()); store.addNodeItem(item); dbTester.assertions().assertTableContains("items", new HashMap<String, Object>() { { put("node", TEST_SERVER1_NODE1_ID); put("id", itemId); put("updated", updated); put("xml", testContent); put("in_reply_to", inReplyTo); } }); } @Test(expected = NodeStoreException.class) public void testAddNodeItemWithExistingIdThrowsException() throws Exception { dbTester.loadData("node_1"); final Date updated = new Date(System.currentTimeMillis()); final String testContent = "<content>Hello World</content>"; NodeItem item = new NodeItemImpl(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID, updated, testContent); store.addNodeItem(item); } @Test public void testUpdateNodeItem() throws Exception { dbTester.loadData("node_1"); final Timestamp updated = new Timestamp(System.currentTimeMillis()); final String testContent = "<content>Hello World</content>"; NodeItem item = new NodeItemImpl(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID, updated, testContent); store.updateNodeItem(item); dbTester.assertions().assertTableContains("items", new HashMap<String, Object>() { { put("node", TEST_SERVER1_NODE1_ID); put("id", TEST_SERVER1_NODE1_ITEM1_ID); put("updated", updated); put("xml", testContent); } }); } @Test(expected = ItemNotFoundException.class) public void testUpdateNodeItemForNonExistantItemThrowsException() throws Exception { dbTester.loadData("node_1"); final String itemId = "test-item-id"; final Timestamp updated = new Timestamp(System.currentTimeMillis()); final String testContent = "<content>Hello World</content>"; NodeItem item = new NodeItemImpl(TEST_SERVER1_NODE1_ID, itemId, updated, testContent); store.updateNodeItem(item); } @Test public void testDeleteNodeItem() throws Exception { dbTester.loadData("node_1"); store.deleteNodeItemById(TEST_SERVER1_NODE1_ID, TEST_SERVER1_NODE1_ITEM1_ID); dbTester.assertions().assertTableContains("items", new HashMap<String, Object>() { { put("node", TEST_SERVER1_NODE1_ID); put("id", TEST_SERVER1_NODE1_ITEM1_ID); } }, 0); } @Test(expected = ItemNotFoundException.class) public void testDeleteNodeItemForNonExistantItemThrowsException() throws Exception { dbTester.loadData("node_1"); store.deleteNodeItemById(TEST_SERVER1_NODE1_ID, "test-item-id"); } @Test public void testGetNodeListReturnsExpectedNodes() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_2"); dbTester.loadData("advertise_nodes"); ArrayList<String> nodeList = store.getNodeList(); assertEquals(6, nodeList.size()); Assert.assertEquals("/user/advertised@server1/posts", nodeList.get(0)); Assert.assertEquals("/user/advertised@server2/posts", nodeList.get(1)); } @Test public void testPurgeNodeItemsDeletesNodeItems() throws Exception { dbTester.loadData("node_1"); assertTrue(store.countNodeItems(TEST_SERVER1_NODE1_ID, false) > 0); store.purgeNodeItems(TEST_SERVER1_NODE1_ID); assertEquals(0, store.countNodeItems(TEST_SERVER1_NODE1_ID, false)); } @Test public void testPurgeNodeItemsDoesntDeleteItemsUnexpectedly() throws Exception { dbTester.loadData("node_1"); int itemCount = store.countNodeItems(TEST_SERVER1_NODE1_ID, false); assertTrue(itemCount > 0); store.purgeNodeItems(TEST_SERVER1_NODE2_ID); // <--- NODE **2** assertEquals(itemCount, store.countNodeItems(TEST_SERVER1_NODE1_ID, false)); } @Test public void testGetIsCachedSubscriptionNodeReturnsFalseWhereThereAreNoSubscriptions() throws Exception { boolean cached = store.nodeHasSubscriptions(TEST_SERVER1_NODE1_ID); assertEquals(false, cached); } @Test(expected = IllegalArgumentException.class) public void testFirehoseItemsThrowsExceptionIfNegativeLimitRequested() throws Exception { store.getFirehose(-1, null, false, TEST_SERVER1_HOSTNAME); } @Test public void testCanGetFirehoseItems() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_2"); store.setNodeConfValue(TEST_SERVER1_NODE1_ID, "pubsub#access_model", "open"); store.setNodeConfValue(TEST_SERVER1_NODE2_ID, "pubsub#access_model", "open"); // Add a remote node - don't expect to see HashMap<String, String> remoteNodeConf = new HashMap<String, String>(); remoteNodeConf.put("pubsub#access_model", "open"); store.addRemoteNode(TEST_SERVER2_NODE1_ID); store.setNodeConf(TEST_SERVER2_NODE1_ID, remoteNodeConf); // Add a private node - don't expect to see HashMap<String, String> privateNodeConf = new HashMap<String, String>(); privateNodeConf.put("pubsub#access_model", "subscribe"); store.createNode(TEST_SERVER1_USER1_JID, TEST_SERVER1_NODE3_ID, privateNodeConf); store.addNodeItem(new NodeItemImpl(TEST_SERVER1_NODE3_ID, "1111", new Date(), "<entry/>")); Thread.sleep(4); CloseableIterator<NodeItem> items = store.getFirehose(50, null, false, TEST_SERVER1_HOSTNAME); NodeItem item = null; int count = 0; while (items.hasNext()) { item = items.next(); ++count; } assertEquals(6, count); } @Test public void testCanGetFirehoseItemsIncludingPrivateAsAdminUser() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_2"); store.setNodeConfValue(TEST_SERVER1_NODE1_ID, AccessModel.FIELD_NAME, AccessModels.open.toString()); store.setNodeConfValue(TEST_SERVER1_NODE2_ID, AccessModel.FIELD_NAME, AccessModels.open.toString()); // Add a private node - *do* expect to see HashMap<String, String> privateNodeConf = new HashMap<String, String>(); privateNodeConf.put(AccessModel.FIELD_NAME, AccessModels.authorize.toString()); store.createNode(TEST_SERVER1_USER1_JID, TEST_SERVER1_NODE3_ID, privateNodeConf); store.addNodeItem(new NodeItemImpl(TEST_SERVER1_NODE3_ID, "1111", new Date(), "<entry/>")); // Add a remote node - don't expect to see HashMap<String, String> remoteNodeConf = new HashMap<String, String>(); remoteNodeConf.put(AccessModel.FIELD_NAME, AccessModels.open.toString()); store.addRemoteNode(TEST_SERVER2_NODE1_ID); store.setNodeConf(TEST_SERVER2_NODE1_ID, remoteNodeConf); CloseableIterator<NodeItem> items = store.getFirehose(50, null, true, TEST_SERVER1_HOSTNAME); NodeItem item = null; int count = 0; while (items.hasNext()) { item = items.next(); ++count; } assertEquals(7, count); } @Test @Ignore("Ordering by timestamp isn't happening here. Return to later") public void testCanGetFirehoseItemsWithRsm() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_2"); store.setNodeConfValue(TEST_SERVER1_NODE1_ID, "pubsub#access_model", "open"); store.setNodeConfValue(TEST_SERVER1_NODE2_ID, "pubsub#access_model", "open"); // Add a private node - don't expect to see HashMap<String, String> privateNodeConf = new HashMap<String, String>(); privateNodeConf.put("pubsub#access_model", "subscribe"); store.createNode(TEST_SERVER1_USER1_JID, TEST_SERVER1_NODE3_ID, privateNodeConf); store.addNodeItem(new NodeItemImpl(TEST_SERVER1_NODE3_ID, "1111", new Date(), "<entry/>")); // Add a remote node - don't expect to see HashMap<String, String> remoteNodeConf = new HashMap<String, String>(); remoteNodeConf.put("pubsub#access_model", "open"); store.addRemoteNode(TEST_SERVER2_NODE1_ID); store.setNodeConf(TEST_SERVER2_NODE1_ID, remoteNodeConf); CloseableIterator<NodeItem> items = store.getFirehose(2, "a3", false, TEST_SERVER1_HOSTNAME); NodeItem item1 = items.next(); NodeItem item2 = items.next(); assertFalse(items.hasNext()); assertEquals("a4", item1.getId()); assertEquals("node2:1", item2.getId()); assertEquals(TEST_SERVER1_NODE1_ID, item1.getNodeId()); assertEquals(TEST_SERVER1_NODE2_ID, item2.getNodeId()); } @Test public void testCanGetFirehoseItemCount() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_2"); store.setNodeConfValue(TEST_SERVER1_NODE1_ID, "pubsub#access_model", "open"); store.setNodeConfValue(TEST_SERVER1_NODE2_ID, "pubsub#access_model", "open"); // Add a private node - *do* expect to see HashMap<String, String> privateNodeConf = new HashMap<String, String>(); privateNodeConf.put("pubsub#access_model", "subscribe"); store.createNode(TEST_SERVER1_USER1_JID, TEST_SERVER1_NODE3_ID, privateNodeConf); store.addNodeItem(new NodeItemImpl(TEST_SERVER1_NODE3_ID, "1111", new Date(), "<entry/>")); // Add a remote node - don't expect to see HashMap<String, String> remoteNodeConf = new HashMap<String, String>(); remoteNodeConf.put("pubsub#access_model", "open"); store.addRemoteNode(TEST_SERVER2_NODE1_ID); store.setNodeConf(TEST_SERVER2_NODE1_ID, remoteNodeConf); assertEquals(6, store.getFirehoseItemCount(false, TEST_SERVER1_HOSTNAME)); } @Test public void testCanGetFirehostItemCountWithPrivateItemsAsAdmin() throws Exception { dbTester.loadData("node_1"); dbTester.loadData("node_2"); store.setNodeConfValue(TEST_SERVER1_NODE1_ID, "pubsub#access_model", "open"); store.setNodeConfValue(TEST_SERVER1_NODE2_ID, "pubsub#access_model", "open"); // Add a private node - *do* expect to see HashMap<String, String> privateNodeConf = new HashMap<String, String>(); privateNodeConf.put("pubsub#access_model", "subscribe"); store.createNode(TEST_SERVER1_USER1_JID, TEST_SERVER1_NODE3_ID, privateNodeConf); store.addNodeItem(new NodeItemImpl(TEST_SERVER1_NODE3_ID, "1111", new Date(), "<entry/>")); // Add a remote node - don't expect to see HashMap<String, String> remoteNodeConf = new HashMap<String, String>(); remoteNodeConf.put("pubsub#access_model", "open"); store.addRemoteNode(TEST_SERVER2_NODE1_ID); store.setNodeConf(TEST_SERVER2_NODE1_ID, remoteNodeConf); assertEquals(7, store.getFirehoseItemCount(true, TEST_SERVER1_HOSTNAME)); } @Test public void testOnlySeeSearchResultsFromSubscribedPostsNodes() throws Exception { dbTester.loadData("search-test-1"); CloseableIterator<NodeItem> items = store.performSearch( new JID("user1@server1"), new ArrayList<String>(), new JID("author@server1"), 1, 25 ); int counter = 0; while (items.hasNext()) { ++counter; NodeItem item = items.next(); assertEquals("a1", item.getId()); assertEquals("/users/subscribed@server1/posts", item.getNodeId()); } assertEquals(1, counter); } @Test public void testOnlySeeSearchResultsFromRequestedAuthor() throws Exception { dbTester.loadData("search-test-2"); CloseableIterator<NodeItem> items = store.performSearch( new JID("user1@server1"), new ArrayList<String>(), new JID("author@server1"), 1, 25 ); int counter = 0; NodeItem item; while (items.hasNext()) { ++counter; item = items.next(); if (1 == counter) { assertEquals("b1", item.getId()); assertEquals("/users/another-subscribed@server1/posts", item.getNodeId()); } else if (2 == counter) { assertEquals("a1", item.getId()); assertEquals("/users/subscribed@server1/posts", item.getNodeId()); } } assertEquals(2, counter); } @Test public void testOnlySeeSearchResultsWithSpecificContent() throws Exception { dbTester.loadData("search-test-3"); ArrayList<String> searchTerms = new ArrayList<String>(); searchTerms.add("keyword"); searchTerms.add("post"); CloseableIterator<NodeItem> items = store.performSearch( new JID("user1@server1"), searchTerms, new JID("author@server1"), 1, 25 ); int counter = 0; NodeItem item; while (items.hasNext()) { ++counter; item = items.next(); if (1 == counter) { assertEquals("a3", item.getId()); assertEquals("/users/subscribed@server1/posts", item.getNodeId()); } else if (2 == counter) { assertEquals("a1", item.getId()); assertEquals("/users/subscribed@server1/posts", item.getNodeId()); } } assertEquals(2, counter); } @Test public void testOnlySeeSearchResultsWithSpecificContentAndAuthor() throws Exception { dbTester.loadData("search-test-4"); ArrayList<String> searchTerms = new ArrayList<String>(); searchTerms.add("keyword"); searchTerms.add("post"); CloseableIterator<NodeItem> items = store.performSearch( new JID("user1@server1"), searchTerms, new JID("author@server1"), 1, 25 ); int counter = 0; NodeItem item; while (items.hasNext()) { ++counter; item = items.next(); if (1 == counter) { assertEquals("a3", item.getId()); assertEquals("/users/subscribed@server1/posts", item.getNodeId()); } else if (2 == counter) { assertEquals("a1", item.getId()); assertEquals("/users/subscribed@server1/posts", item.getNodeId()); } } assertEquals(2, counter); } @Test public void testBeginTransaction() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); NodeStore.Transaction t = store.beginTransaction(); assertNotNull("Null transaction returned", t); verify(conn).setAutoCommit(false); } @Test public void testCommitTransaction() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); NodeStore.Transaction t = store.beginTransaction(); t.commit(); verify(conn).commit(); verify(conn).setAutoCommit(true); } @Test public void testCloseTransaction() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); NodeStore.Transaction t = store.beginTransaction(); t.close(); verify(conn, never()).commit(); verify(conn).rollback(); verify(conn).setAutoCommit(true); } @Test public void testCloseOnAlreadyCommittedTransactionDoesntRollback() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); NodeStore.Transaction t = store.beginTransaction(); t.commit(); t.close(); verify(conn, never()).rollback(); } @Test public void testNestedTransactionsOnlySetAutoCommitOnce() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); store.beginTransaction(); // Make sure setAutoCommit was called verify(conn).setAutoCommit(false); store.beginTransaction(); store.beginTransaction(); // Make sure setAutoCommit was still only called once verify(conn).setAutoCommit(false); } @Test public void testNestedTransactionsOnlyCallCommitOnOuterTransaction() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); InOrder inOrder = inOrder(conn); NodeStore.Transaction t1 = store.beginTransaction(); NodeStore.Transaction t2 = store.beginTransaction(); NodeStore.Transaction t3 = store.beginTransaction(); t3.commit(); verify(conn, never()).commit(); // Make sure that commit isn't called // until the outer transaction is // committed t2.commit(); verify(conn, never()).commit(); // Make sure that commit isn't called // until the outer transaction is // committed t1.commit(); inOrder.verify(conn).commit(); // Make sure that commit was called inOrder.verify(conn).setAutoCommit(true); } @Test(expected = IllegalStateException.class) public void testNestedTransactionsWithRollbackInMiddle() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); NodeStore.Transaction t1 = store.beginTransaction(); NodeStore.Transaction t2 = store.beginTransaction(); NodeStore.Transaction t3 = store.beginTransaction(); t3.commit(); t2.close(); t1.commit(); } @Test(expected = IllegalStateException.class) public void testNestedTransactionsWithOutOfOrderCommitsThrowsException() throws Exception { Connection conn = Mockito.mock(Connection.class); JDBCNodeStore store = new JDBCNodeStore(conn, mock(NodeStoreSQLDialect.class), configuration); NodeStore.Transaction t1 = store.beginTransaction(); NodeStore.Transaction t2 = store.beginTransaction(); NodeStore.Transaction t3 = store.beginTransaction(); t3.commit(); t1.commit(); // t1 must not be committed before t2 t2.commit(); } @Test public void testSelectNodeThreads() throws Exception { dbTester.loadData("node_1"); assertEquals(5, store.getNodeThreads(TEST_SERVER1_NODE1_ID, null, 10) .size()); } @Test public void testCountNodeThreads() throws Exception { dbTester.loadData("node_1"); assertEquals(5, store.countNodeThreads(TEST_SERVER1_NODE1_ID)); } @Test public void testNoNodeOwnersReturnsEmptyList() throws Exception { dbTester.loadData("node_1"); assertEquals(0, store.getNodeOwners(UNKNOWN_NODE).size()); } @Test public void testNodeOwnersReturnsExpectedList() throws Exception { dbTester.loadData("node_1"); store.addUserSubscription(new NodeSubscriptionImpl(TEST_SERVER1_NODE1_ID, TEST_SERVER1_USER2_JID, Subscriptions.subscribed, null)); store.setUserAffiliation(TEST_SERVER1_NODE1_ID, TEST_SERVER1_USER2_JID, Affiliations.owner); assertEquals(2, store.getNodeOwners(TEST_SERVER1_NODE1_ID).size()); assertEquals(TEST_SERVER1_USER1_JID, store.getNodeOwners(TEST_SERVER1_NODE1_ID).get(0)); assertEquals(TEST_SERVER1_USER2_JID, store.getNodeOwners(TEST_SERVER1_NODE1_ID).get(1)); } @Test public void notPreviousRatingByUserReturnsFalse() throws Exception { String node = "/users/romeo@capulet.lit/posts"; store.addRemoteNode(node); String content = "" + "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:thr='http://purl.org/syndication/thread/1.0' " + "xmlns:activity='http://activitystrea.ms/spec/1.0/'>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,6</id>" + "<title>Post title</title>" + "<published>2014-01-01T00:00:00.000Z</published>" + "<updated>2014-01-01T00:00:00.000Z</updated>" + "<author>" + "<name>romeo@capulet.lit</name>" + "<uri>acct:romeo@capulet.lit</uri>" + "<jid xmlns='http://buddycloud.com/atom-elements-0'>romeo@capulet.lit</jid>" + "</author>" + "<content type='text'>rating:5.0</content>" + "<activity:verb>rated</activity:verb>" + "<activity:object>" + "<activity:object-type>comment</activity:object-type>" + "</activity:object>" + "<thr:in-reply-to ref='tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5' />" + "<activity:target>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5</id>" + "</activity:target>" + "<review:rating>5.0</review:rating>" + "</entry>"; String alternativeContent = "" + "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:thr='http://purl.org/syndication/thread/1.0' " + "xmlns:activity='http://activitystrea.ms/spec/1.0/'>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,7</id>" + "<title>Post title</title>" + "<published>2014-01-01T00:00:00.000Z</published>" + "<content type='text'>rating:5.0</content>" + "<activity:verb>rated</activity:verb>" + "<activity:object>" + "<activity:object-type>comment</activity:object-type>" + "</activity:object>" + "<thr:in-reply-to ref='tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5' />" + "<activity:target>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5</id>" + "</activity:target>" + "<review:rating>5.0</review:rating>" + "</entry>"; NodeItem item1 = new NodeItemImpl(node, "6", new Date(), content); store.addNodeItem(item1); NodeItem item2 = new NodeItemImpl(node, "7", new Date(), alternativeContent); store.addNodeItem(item2); Assert.assertFalse( store.userHasRatedPost(node, new JID("romeo@capulet.lit"), new GlobalItemIDImpl(new JID("channels.capulet.lit"), node, "6")) ); } @Test public void previousRatingByUserReturnsTrue() throws Exception { String node = "/users/romeo@capulet.lit/posts"; store.addRemoteNode(node); String content = "" + "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:thr='http://purl.org/syndication/thread/1.0' " + "xmlns:activity='http://activitystrea.ms/spec/1.0/'>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,6</id>" + "<title>Post title</title>" + "<published>2014-01-01T00:00:00.000Z</published>" + "<updated>2014-01-01T00:00:00.000Z</updated>" + "<author>" + "<name>romeo@capulet.lit</name>" + "<uri>acct:romeo@capulet.lit</uri>" + "<jid xmlns='http://buddycloud.com/atom-elements-0'>romeo@capulet.lit</jid>" + "</author>" + "<content type='text'>rating:5.0</content>" + "<activity:verb>rated</activity:verb>" + "<activity:object>" + "<activity:object-type>comment</activity:object-type>" + "</activity:object>" + "<thr:in-reply-to ref='tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5' />" + "<activity:target>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5</id>" + "</activity:target>" + "<review:rating>5.0</review:rating>" + "</entry>"; String alternativeContent = "" + "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:thr='http://purl.org/syndication/thread/1.0' " + "xmlns:activity='http://activitystrea.ms/spec/1.0/'>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,7</id>" + "<title>Post title</title>" + "<published>2014-01-01T00:00:00.000Z</published>" + "<content type='text'>rating:5.0</content>" + "<activity:verb>rated</activity:verb>" + "<activity:object>" + "<activity:object-type>comment</activity:object-type>" + "</activity:object>" + "<thr:in-reply-to ref='tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5' />" + "<activity:target>" + "<id>tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,5</id>" + "</activity:target>" + "<review:rating>5.0</review:rating>" + "</entry>"; NodeItem item1 = new NodeItemImpl(node, "6", new Date(), content); store.addNodeItem(item1); NodeItem item2 = new NodeItemImpl(node, "7", new Date(), alternativeContent); store.addNodeItem(item2); Assert.assertTrue( store.userHasRatedPost(node, new JID("romeo@capulet.lit"), new GlobalItemIDImpl(new JID("channels.capulet.lit"), node, "5")) ); } }