/* * JBoss, Home of Professional Open Source * Copyright 2009 Red Hat Inc. and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.api.tree; import org.infinispan.config.Configuration; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.test.SingleCacheManagerTest; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.infinispan.tree.Fqn; import org.infinispan.tree.Node; import org.infinispan.tree.TreeCache; import org.infinispan.tree.TreeCacheImpl; import org.testng.annotations.Test; import javax.transaction.TransactionManager; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static org.testng.AssertJUnit.*; /** * Tests {@link Node}-centric operations * * @author <a href="mailto:manik AT jboss DOT org">Manik Surtani</a> */ @Test(groups = "functional", testName = "api.tree.NodeAPITest") public class NodeAPITest extends SingleCacheManagerTest { static final Fqn A = Fqn.fromString("/a"), B = Fqn.fromString("/b"), C = Fqn.fromString("/c"), D = Fqn.fromString("/d"); Fqn A_B = Fqn.fromRelativeFqn(A, B); Fqn A_C = Fqn.fromRelativeFqn(A, C); TransactionManager tm; TreeCache cache; @Override protected EmbeddedCacheManager createCacheManager() throws Exception { // start a single cache instance Configuration c = getDefaultStandaloneConfig(true); c.setInvocationBatchingEnabled(true); EmbeddedCacheManager cm = TestCacheManagerFactory.createCacheManager(c); cache = new TreeCacheImpl(cm.getCache()); tm = cache.getCache().getAdvancedCache().getTransactionManager(); return cm; } public void testAddingData() { Node<Object, Object> rootNode = cache.getRoot(); Node<Object, Object> nodeA = rootNode.addChild(A); nodeA.put("key", "value"); assertEquals("value", nodeA.get("key")); } public void testAddingDataPutMap() { cache.put(A_B, Collections.singletonMap("key", "value")); assertEquals("value", cache.get(A_B, "key")); } public void testAddingDataPutKey() { cache.put(A_B, "key", "value"); assertEquals("value", cache.get(A_B, "key")); } public void testAddingDataTx() throws Exception { Node<Object, Object> rootNode = cache.getRoot(); tm.begin(); Node<Object, Object> nodeA = rootNode.addChild(A); nodeA.put("key", "value"); assertEquals("value", nodeA.get("key")); tm.commit(); } public void testOverwritingDataTx() throws Exception { Node<Object, Object> rootNode = cache.getRoot(); Node<Object, Object> nodeA = rootNode.addChild(A); nodeA.put("key", "value"); assertEquals("value", nodeA.get("key")); tm.begin(); rootNode.removeChild(A); cache.put(A, "k2", "v2"); tm.commit(); assertNull(nodeA.get("key")); assertEquals("v2", nodeA.get("k2")); } /** * Remember, Fqns are relative!! */ public void testParentsAndChildren() { Node<Object, Object> rootNode = cache.getRoot(); Node<Object, Object> nodeA = rootNode.addChild(A); Node<Object, Object> nodeB = nodeA.addChild(B); Node<Object, Object> nodeC = nodeA.addChild(C); Node<Object, Object> nodeD = rootNode.addChild(D); assertEquals(rootNode, nodeA.getParent()); assertEquals(nodeA, nodeB.getParent()); assertEquals(nodeA, nodeC.getParent()); assertEquals(rootNode, nodeD.getParent()); assertTrue(rootNode.hasChild(A)); assertFalse(rootNode.hasChild(B)); assertFalse(rootNode.hasChild(C)); assertTrue(rootNode.hasChild(D)); assertTrue(nodeA.hasChild(B)); assertTrue(nodeA.hasChild(C)); assertEquals(nodeA, rootNode.getChild(A)); assertEquals(nodeD, rootNode.getChild(D)); assertEquals(nodeB, nodeA.getChild(B)); assertEquals(nodeC, nodeA.getChild(C)); assertTrue(nodeA.getChildren().contains(nodeB)); assertTrue(nodeA.getChildren().contains(nodeC)); assertEquals(2, nodeA.getChildren().size()); assertTrue(rootNode.getChildren().contains(nodeA)); assertTrue(rootNode.getChildren().contains(nodeD)); assertEquals(2, rootNode.getChildren().size()); assertEquals(true, rootNode.removeChild(A)); assertFalse(rootNode.getChildren().contains(nodeA)); assertTrue(rootNode.getChildren().contains(nodeD)); assertEquals(1, rootNode.getChildren().size()); assertEquals("double remove", false, rootNode.removeChild(A)); assertEquals("double remove", false, rootNode.removeChild(A.getLastElement())); } public void testImmutabilityOfData() { Node<Object, Object> rootNode = cache.getRoot(); rootNode.put("key", "value"); Map<Object, Object> m = rootNode.getData(); try { m.put("x", "y"); fail("Map should be immutable!!"); } catch (Exception e) { // expected } try { rootNode.getKeys().add(new Object()); fail("Key set should be immutable"); } catch (Exception e) { // expected } } public void testDefensiveCopyOfData() { Node<Object, Object> rootNode = cache.getRoot(); rootNode.put("key", "value"); Map<Object, Object> data = rootNode.getData(); Set<Object> keys = rootNode.getKeys(); assert keys.size() == 1; assert keys.contains("key"); assert data.size() == 1; assert data.containsKey("key"); // now change stuff. rootNode.put("key2", "value2"); // assert that the collections we initially got have not changed. assert keys.size() == 1; assert keys.contains("key"); assert data.size() == 1; assert data.containsKey("key"); } public void testDefensiveCopyOfChildren() { Node<Object, Object> rootNode = cache.getRoot(); Fqn childFqn = Fqn.fromString("/child"); rootNode.addChild(childFqn).put("k", "v"); Set<Node<Object, Object>> children = rootNode.getChildren(); Set<Object> childrenNames = rootNode.getChildrenNames(); assert childrenNames.size() == 1; assert childrenNames.contains(childFqn.getLastElement()); assert children.size() == 1; assert children.iterator().next().getFqn().equals(childFqn); // now change stuff. rootNode.addChild(Fqn.fromString("/child2")); // assert that the collections we initially got have not changed. assert childrenNames.size() == 1; assert childrenNames.contains(childFqn.getLastElement()); assert children.size() == 1; assert children.iterator().next().getFqn().equals(childFqn); } public void testImmutabilityOfChildren() { Node<Object, Object> rootNode = cache.getRoot(); rootNode.addChild(A); try { rootNode.getChildren().clear(); fail("Collection of child nodes returned in getChildren() should be immutable"); } catch (Exception e) { // expected } } public void testGetChildAPI() { Node<Object, Object> rootNode = cache.getRoot(); // creates a Node<Object, Object> with fqn /a/b/c Node childA = rootNode.addChild(A); childA.addChild(B).addChild(C); rootNode.getChild(A).put("key", "value"); rootNode.getChild(A).getChild(B).put("key", "value"); rootNode.getChild(A).getChild(B).getChild(C).put("key", "value"); assertEquals("value", rootNode.getChild(A).get("key")); assertEquals("value", rootNode.getChild(A).getChild(B).get("key")); assertEquals("value", rootNode.getChild(A).getChild(B).getChild(C).get("key")); assertNull(rootNode.getChild(Fqn.fromElements("nonexistent"))); } public void testClearingData() { Node<Object, Object> rootNode = cache.getRoot(); rootNode.put("k", "v"); rootNode.put("k2", "v2"); assertEquals(2, rootNode.getKeys().size()); rootNode.clearData(); assertEquals(0, rootNode.getKeys().size()); assertTrue(rootNode.getData().isEmpty()); } public void testClearingDataTx() throws Exception { Node<Object, Object> rootNode = cache.getRoot(); tm.begin(); rootNode.put("k", "v"); rootNode.put("k2", "v2"); assertEquals(2, rootNode.getKeys().size()); rootNode.clearData(); assertEquals(0, rootNode.getKeys().size()); assertTrue(rootNode.getData().isEmpty()); tm.commit(); assertTrue(rootNode.getData().isEmpty()); } public void testPutData() { Node<Object, Object> rootNode = cache.getRoot(); assertTrue(rootNode.getData().isEmpty()); Map<Object, Object> map = new HashMap<Object, Object>(); map.put("k1", "v1"); map.put("k2", "v2"); rootNode.putAll(map); assertEquals(2, rootNode.getData().size()); assertEquals("v1", rootNode.get("k1")); assertEquals("v2", rootNode.get("k2")); map.clear(); map.put("k3", "v3"); rootNode.putAll(map); assertEquals(3, rootNode.getData().size()); assertEquals("v1", rootNode.get("k1")); assertEquals("v2", rootNode.get("k2")); assertEquals("v3", rootNode.get("k3")); map.clear(); map.put("k4", "v4"); map.put("k5", "v5"); rootNode.replaceAll(map); assertEquals(2, rootNode.getData().size()); assertEquals("v4", rootNode.get("k4")); assertEquals("v5", rootNode.get("k5")); } public void testGetChildrenNames() throws Exception { Node<Object, Object> rootNode = cache.getRoot(); rootNode.addChild(A).put("k", "v"); rootNode.addChild(B).put("k", "v"); Set<Object> childrenNames = new HashSet<Object>(); childrenNames.add(A.getLastElement()); childrenNames.add(B.getLastElement()); assertEquals(childrenNames, rootNode.getChildrenNames()); // now delete a child, within a tx tm.begin(); rootNode.removeChild(B); assertFalse(rootNode.hasChild(B)); childrenNames.remove(B.getLastElement()); assertEquals(childrenNames, rootNode.getChildrenNames()); tm.commit(); assertEquals(childrenNames, rootNode.getChildrenNames()); } public void testDoubleRemovalOfData() throws Exception { assert tm.getTransaction() == null; cache.put("/foo/1/2/3", "item", 1); assert tm.getTransaction() == null; assert 1 == (Integer) cache.get("/foo/1/2/3", "item"); tm.begin(); assert 1 == (Integer) cache.get("/foo/1/2/3", "item"); cache.removeNode("/foo/1"); assertNull(cache.getNode("/foo/1")); assertNull(cache.get("/foo/1", "item")); cache.removeNode("/foo/1/2/3"); System.out.println("Cache: " + cache); assertNull(cache.get("/foo/1/2/3", "item")); assertNull(cache.get("/foo/1", "item")); tm.commit(); assertFalse(cache.exists("/foo/1")); assertNull(cache.get("/foo/1/2/3", "item")); assertNull(cache.get("/foo/1", "item")); } public void testDoubleRemovalOfData2() throws Exception { cache.put("/foo/1/2", "item", 1); tm.begin(); assertEquals(cache.get("/foo/1", "item"), null); cache.removeNode("/foo/1"); assertNull(cache.get("/foo/1", "item")); cache.removeNode("/foo/1/2"); assertNull(cache.get("/foo/1", "item")); tm.commit(); assertFalse(cache.exists("/foo/1")); assertNull(cache.get("/foo/1/2", "item")); assertNull(cache.get("/foo/1", "item")); } }