Java tutorial
/* ************************************************************************ ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* ************** CENTRE CANADIEN DE DONNES ASTRONOMIQUES ************** * * (c) 2009. (c) 2009. * Government of Canada Gouvernement du Canada * National Research Council Conseil national de recherches * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 * All rights reserved Tous droits rservs * * NRC disclaims any warranties, Le CNRC dnie toute garantie * expressed, implied, or nonce, implicite ou lgale, * statutory, of any kind with de quelque nature que ce * respect to the software, soit, concernant le logiciel, * including without limitation y compris sans restriction * any warranty of merchantability toute garantie de valeur * or fitness for a particular marchande ou de pertinence * purpose. NRC shall not be pour un usage particulier. * liable in any event for any Le CNRC ne pourra en aucun cas * damages, whether direct or tre tenu responsable de tout * indirect, special or general, dommage, direct ou indirect, * consequential or incidental, particulier ou gnral, * arising from the use of the accessoire ou fortuit, rsultant * software. Neither the name de l'utilisation du logiciel. Ni * of the National Research le nom du Conseil National de * Council of Canada nor the Recherches du Canada ni les noms * names of its contributors may de ses participants ne peuvent * be used to endorse or promote tre utiliss pour approuver ou * products derived from this promouvoir les produits drivs * software without specific prior de ce logiciel sans autorisation * written permission. pralable et particulire * par crit. * * This file is part of the Ce fichier fait partie du projet * OpenCADC project. OpenCADC. * * OpenCADC is free software: OpenCADC est un logiciel libre ; * you can redistribute it and/or vous pouvez le redistribuer ou le * modify it under the terms of modifier suivant les termes de * the GNU Affero General Public la GNU Affero General Public * License as published by the License? telle que publie * Free Software Foundation, par la Free Software Foundation * either version 3 of the : soit la version 3 de cette * License, or (at your option) licence, soit ( votre gr) * any later version. toute version ultrieure. * * OpenCADC is distributed in the OpenCADC est distribu * hope that it will be useful, dans lespoir quil vous * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE * without even the implied GARANTIE : sans mme la garantie * warranty of MERCHANTABILITY implicite de COMMERCIALISABILIT * or FITNESS FOR A PARTICULAR ni dADQUATION UN OBJECTIF * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence * General Public License for Gnrale Publique GNU Affero * more details. pour plus de dtails. * * You should have received Vous devriez avoir reu une * a copy of the GNU Affero copie de la Licence Gnrale * General Public License along Publique GNU Affero avec * with OpenCADC. If not, see OpenCADC ; si ce nest * <http://www.gnu.org/licenses/>. pas le cas, consultez : * <http://www.gnu.org/licenses/>. * * $Revision: 4 $ * ************************************************************************ */ package ca.nrc.cadc.vos.server; import static org.junit.Assert.assertEquals; import java.io.FileNotFoundException; import java.net.URI; import java.security.Principal; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.List; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.x500.X500Principal; import javax.sql.DataSource; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate; import ca.nrc.cadc.auth.AuthenticationUtil; import ca.nrc.cadc.auth.X500IdentityManager; import ca.nrc.cadc.db.ConnectionConfig; import ca.nrc.cadc.db.DBConfig; import ca.nrc.cadc.db.DBUtil; import ca.nrc.cadc.util.FileMetadata; import ca.nrc.cadc.util.HexUtil; import ca.nrc.cadc.util.Log4jInit; import ca.nrc.cadc.vos.ContainerNode; import ca.nrc.cadc.vos.DataNode; import ca.nrc.cadc.vos.LinkNode; import ca.nrc.cadc.vos.Node; import ca.nrc.cadc.vos.NodeProperty; import ca.nrc.cadc.vos.VOS; import ca.nrc.cadc.vos.VOS.NodeBusyState; import ca.nrc.cadc.vos.VOSURI; import ca.nrc.cadc.vos.server.NodeDAO.NodeSchema; /** * Test class for the NodeDAO class in cadcVOS. * * @author pdowler * */ public class NodeDAOTest { private static Logger log = Logger.getLogger(NodeDAOTest.class); static final String SERVER = "VOSPACE_WS_TEST"; static final String DATABASE = "cadctest"; static final String VOS_AUTHORITY = "cadc.nrc.ca!vospace"; static final String HOME_CONTAINER = "CADCRegtest1"; static final String NODE_OWNER = "CN=CADC Regtest1 10577,OU=CADC,O=HIA"; static final String NODE_OWNER2 = "CN=CADC Authtest1 10627,OU=CADC,O=HIA"; static final String DELETED_OWNER = "CN=CADC admin,OU=CADC,O=HIA"; static final String DELETED_NODES = "DeletedNodes"; protected Subject owner; protected Subject owner2; protected Principal principal; protected Principal principal2; static { Log4jInit.setLevel("ca.nrc.cadc.vos", Level.INFO); } DataSource dataSource; NodeDAO nodeDAO; NodeSchema nodeSchema; String runID; public NodeDAOTest() throws Exception { this.runID = "test" + new Date().getTime(); log.debug("runID = " + runID); this.principal = new X500Principal(NODE_OWNER); this.principal2 = new X500Principal(NODE_OWNER2); Set<Principal> pset = new HashSet<Principal>(); Set<Principal> pset2 = new HashSet<Principal>(); pset.add(principal); pset2.add(principal2); this.owner = new Subject(true, pset, new HashSet(), new HashSet()); this.owner2 = new Subject(true, pset2, new HashSet(), new HashSet()); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = null; try { connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); } catch (NoSuchElementException e) { log.warn("Skipping itegration tests because there is no database entry in ~/.dbrc"); org.junit.Assume.assumeTrue(false); } this.dataSource = DBUtil.getDataSource(connConfig); this.nodeSchema = new NodeSchema("Node", "NodeProperty", true); // TOP // cleanup from old runs //JdbcTemplate jdbc = new JdbcTemplate(dataSource); //jdbc.update("DELETE FROM " + nodeSchema.propertyTable); //jdbc.update("DELETE FROM " + nodeSchema.nodeTable); this.nodeDAO = new NodeDAO(dataSource, nodeSchema, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); } catch (FileNotFoundException e) { log.warn("Skipping itegration tests because there is no ~/.dbrc file."); org.junit.Assume.assumeTrue(false); } catch (NoSuchElementException e) { log.warn("Skipping itegration tests because there is no database entry in ~/.dbrc"); org.junit.Assume.assumeTrue(false); } catch (Exception ex) { // make sure it gets fully dumped log.error("SETUP FAILED", ex); throw ex; } } @Before public void setup() throws Exception { JdbcTemplate jdbc = new JdbcTemplate(dataSource); jdbc.update("delete from " + nodeSchema.propertyTable); jdbc.update("delete from " + nodeSchema.nodeTable); ContainerNode root = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); if (root == null) { VOSURI vos = new VOSURI(new URI("vos", VOS_AUTHORITY, "/" + HOME_CONTAINER, null, null)); root = new ContainerNode(vos); root.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_CREATOR, NODE_OWNER)); root = (ContainerNode) nodeDAO.put(root, owner); log.debug("created base node: " + root.getUri()); } else log.debug("found base node: " + root.getUri()); ContainerNode deleted = (ContainerNode) nodeDAO.getPath(DELETED_NODES); if (deleted == null) { VOSURI vos = new VOSURI(new URI("vos", VOS_AUTHORITY, "/" + DELETED_NODES, null, null)); deleted = new ContainerNode(vos); deleted.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_CREATOR, DELETED_OWNER)); deleted = (ContainerNode) nodeDAO.put(deleted, owner); log.debug("created base node: " + deleted); } else log.debug("found deleted node: " + deleted.getUri()); } private String getNodeName(String s) { return runID + s; } private void assertRecursiveDelete() throws Exception { ContainerNode top = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); Assert.assertNotNull(top); JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "select count(*) from " + nodeSchema.nodeTable + " where parentID IS NULL"; int topLevel = jdbc.queryForInt(sql); Assert.assertEquals("number of top-level nodes", 2, topLevel); sql = "select count(*) from " + nodeSchema.nodeTable + " where parentID = " + ((NodeID) top.appData).id; int accessible = jdbc.queryForInt(sql); Assert.assertEquals("number of directly accessible children ", 0, accessible); sql = "select count(*) from " + nodeSchema.nodeTable + " where parentID is not null and parentID not in (select nodeID from " + nodeSchema.nodeTable + ")"; int orphans = jdbc.queryForInt(sql); Assert.assertEquals("number of orphans", 0, orphans); } @Test public void testGetPath() { log.debug("testGetPath - START"); try { ContainerNode cNode1 = null; ContainerNode cNode2 = null; ContainerNode cNode3 = null; LinkNode linkNode = null; DataNode dataNode = null; Node putNodeL = null; Node putNode1 = null; Node putNode2 = null; Node putNode3 = null; Node putNode4 = null; // create root container: / ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // create 1st container under root container: /adir1 String nodePath1 = basePath + getNodeName("adir1"); cNode1 = getCommonContainerNode(nodePath1, getCommonProperties()); cNode1.setParent(rootContainer); // back link to persistent parent required putNode1 = nodeDAO.put(cNode1, owner); ContainerNode adir1 = (ContainerNode) nodeDAO.getPath(nodePath1); Assert.assertNotNull(adir1); nodeDAO.getProperties(adir1); log.debug("PutNode: " + putNode1); log.debug("GetNode: " + adir1); compareNodes("assertNode1", putNode1, adir1); compareProperties("assertProp1", putNode1.getProperties(), adir1.getProperties()); // create 2nd container under 1st container: /adir1/adir2 String nodePath2 = nodePath1 + "/" + getNodeName("adir2"); cNode2 = getCommonContainerNode(nodePath2, getCommonProperties()); cNode2.setParent(cNode1); // back link to persistent parent required putNode2 = nodeDAO.put(cNode2, owner); ContainerNode adir2 = (ContainerNode) nodeDAO.getPath(nodePath2); Assert.assertNotNull(adir2); nodeDAO.getProperties(adir2); log.debug("PutNode: " + putNode2); log.debug("GetNode: " + adir2); compareNodes("assertNode2", putNode2, adir2); compareProperties("assertProp2", putNode2.getProperties(), adir2.getProperties()); // create 3rd container under 1st container: /adir1/adir3 String nodePath3 = nodePath1 + "/" + getNodeName("adir3"); cNode3 = getCommonContainerNode(nodePath3, getCommonProperties()); cNode3.setParent(cNode1); // back link to persistent parent required putNode3 = nodeDAO.put(cNode3, owner); ContainerNode adir3 = (ContainerNode) nodeDAO.getPath(nodePath3); Assert.assertNotNull(adir3); nodeDAO.getProperties(adir3); log.debug("PutNode: " + putNode3); log.debug("GetNode: " + adir3); compareNodes("assertNode3", putNode3, adir3); compareProperties("assertProp4", putNode3.getProperties(), adir3.getProperties()); // create a file: /adir1/adir3/afile String nodePath4 = nodePath3 + "/" + getNodeName("afile"); dataNode = getCommonDataNode(nodePath4, getDataNodeProperties()); dataNode.setParent(adir3); // back link to persistent parent required putNode4 = nodeDAO.put(dataNode, owner); Node afile = nodeDAO.getPath(nodePath4); Assert.assertNotNull(afile); nodeDAO.getProperties(afile); Assert.assertNotNull(afile.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertEquals("0", afile.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertNull(afile.findProperty(VOS.PROPERTY_URI_CONTENTMD5)); compareNodes("assert4", putNode4, afile); compareProperties("assert4", putNode4.getProperties(), afile.getProperties()); // create a link node: /adir1/adir2/alink String nodePathL = nodePath2 + "/" + getNodeName("alink"); String linkStr = nodePath3; URI link = new URI(linkStr); linkNode = getCommonLinkNode(nodePathL, getLinkNodeProperties()); linkNode.setParent(adir2); // back link to persistent parent required linkNode.setTarget(link); putNodeL = nodeDAO.put(linkNode, owner); Node alink = nodeDAO.getPath(nodePathL); Assert.assertNotNull(alink); nodeDAO.getProperties(alink); Assert.assertNotNull(alink.findProperty(VOS.PROPERTY_URI_DESCRIPTION)); Assert.assertEquals("Linked resource", alink.getPropertyValue(VOS.PROPERTY_URI_DESCRIPTION)); Assert.assertNull(alink.findProperty(VOS.PROPERTY_URI_CONTENTMD5)); compareNodes("assertNodeL", putNodeL, alink); compareProperties("assertPropL", putNodeL.getProperties(), alink.getProperties()); // test path to LinkNode String linkNodePath = nodePath2 + "/" + linkNode.getName(); Node actualLinkNode = nodeDAO.getPath(linkNodePath, true); String nodePathStr = actualLinkNode.getUri().getPath(); Assert.assertEquals("failed to get the complete path", linkNodePath, nodePathStr); // test path to linked resource String dataNodePath = nodePath2 + "/" + linkNode.getName() + "/" + cNode3.getName() + "/" + dataNode.getName(); String expectedNodePath = nodePath2 + "/" + linkNode.getName(); Node actualDataNode = nodeDAO.getPath(dataNodePath, true); Assert.assertNotNull(actualDataNode); nodePathStr = actualDataNode.getUri().getPath(); Assert.assertEquals("failed to get the complete path", expectedNodePath, nodePathStr); // test path to invalid DataNode dataNodePath = nodePath4 + "/noSuchNode"; actualDataNode = nodeDAO.getPath(dataNodePath, false); Assert.assertNull("expected a null node", actualDataNode); expectedNodePath = nodePath4; actualDataNode = nodeDAO.getPath(dataNodePath, true); Assert.assertNotNull("expected a node", actualDataNode); // test path not found dataNodePath = "/" + HOME_CONTAINER + "/nonsense"; Node ret = nodeDAO.getPath(dataNodePath, true); Assert.assertNotNull(ret); ret = nodeDAO.getPath(dataNodePath, false); Assert.assertNull(ret); log.debug("testPutGetDeleteNodes - CLEANUP"); // delete the three roots nodeDAO.delete(adir1, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetPath - DONE"); } } @Test public void testGetHome() { log.debug("testGetHome - START"); try { Node root = nodeDAO.getPath(HOME_CONTAINER); Assert.assertNotNull(root); Assert.assertEquals(ContainerNode.class, root.getClass()); Assert.assertEquals(HOME_CONTAINER, root.getName()); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetHome - DONE"); } } @Test public void testPutGetDeleteNodes() { log.debug("testPutGetDeleteNodes - START"); try { DataNode dataNode = null; ContainerNode containerNode = null; LinkNode linkNode = null; Node putNode = null; ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; String nodePath2 = basePath + getNodeName("adir"); containerNode = getCommonContainerNode(nodePath2, getCommonProperties()); containerNode.setParent(rootContainer); // back link to persistent parent required putNode = nodeDAO.put(containerNode, owner); ContainerNode adir = (ContainerNode) nodeDAO.getPath(nodePath2); Assert.assertNotNull(adir); nodeDAO.getProperties(adir); log.debug("PutNode: " + putNode); log.debug("GetNode: " + adir); compareNodes("assert3", putNode, adir); compareProperties("assert4", putNode.getProperties(), adir.getProperties()); // /adir/afile String nodePath4 = basePath + getNodeName("adir") + "/" + getNodeName("afile"); dataNode = getCommonDataNode(nodePath4, getDataNodeProperties()); dataNode.setParent(adir); // back link to persistent parent required putNode = nodeDAO.put(dataNode, owner); Node afile = nodeDAO.getPath(nodePath4); Assert.assertNotNull(afile); nodeDAO.getProperties(afile); Assert.assertNotNull(afile.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertEquals("0", afile.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertNull(afile.findProperty(VOS.PROPERTY_URI_CONTENTMD5)); compareNodes("assert7", putNode, afile); compareProperties("assert8", putNode.getProperties(), afile.getProperties()); // /adir/alink String nodePath5 = basePath + getNodeName("adir") + "/" + getNodeName("alink"); linkNode = getCommonLinkNode(nodePath5, getLinkNodeProperties()); linkNode.setParent(adir); // back link to persistent parent required putNode = nodeDAO.put(linkNode, owner); Node alink = nodeDAO.getPath(nodePath5); Assert.assertNotNull(alink); nodeDAO.getProperties(alink); Assert.assertNotNull(alink.findProperty(VOS.PROPERTY_URI_DESCRIPTION)); Assert.assertEquals("Linked resource", alink.getPropertyValue(VOS.PROPERTY_URI_DESCRIPTION)); Assert.assertNull(alink.findProperty(VOS.PROPERTY_URI_CONTENTMD5)); compareNodes("assert9", putNode, alink); compareProperties("assert10", putNode.getProperties(), alink.getProperties()); log.debug("testPutGetDeleteNodes - CLEANUP"); // delete the three roots nodeDAO.delete(adir, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testPutGetDeleteNodes - DONE"); } } @Test public void testGetChildren() { log.debug("testGetChildren - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // create a container String path = basePath + getNodeName("dir"); ContainerNode testNode = getCommonContainerNode(path); testNode.setParent(rootContainer); ContainerNode cn = (ContainerNode) nodeDAO.put(testNode, owner); ContainerNode cur = (ContainerNode) nodeDAO.getPath(path); Assert.assertNotNull(cur); DataNode n1 = getCommonDataNode(path + "/one"); ContainerNode n2 = getCommonContainerNode(path + "/two"); DataNode n3 = getCommonDataNode(path + "/three"); ContainerNode n4 = getCommonContainerNode(path + "/four"); n1.setParent(cn); n2.setParent(cn); n3.setParent(cn); n4.setParent(cn); nodeDAO.put(n1, owner); nodeDAO.put(n2, owner); nodeDAO.put(n3, owner); nodeDAO.put(n4, owner); // get a vanilla container with no children cur = (ContainerNode) nodeDAO.getPath(path); Assert.assertNotNull(cur); Assert.assertEquals("empty child list", 0, cur.getNodes().size()); // load the child nodes nodeDAO.getChildren(cur); Assert.assertEquals("full child list", 4, cur.getNodes().size()); // rely on implementation of Node.equals Assert.assertTrue(cur.getNodes().contains(n1)); Assert.assertTrue(cur.getNodes().contains(n2)); Assert.assertTrue(cur.getNodes().contains(n3)); Assert.assertTrue(cur.getNodes().contains(n4)); nodeDAO.delete(cur, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetChildren - DONE"); } } @Test public void testGetChildrenLimit() { log.debug("testGetChildrenLimit - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // create a container String path = basePath + getNodeName("dir"); ContainerNode testNode = getCommonContainerNode(path); testNode.setParent(rootContainer); ContainerNode cn = (ContainerNode) nodeDAO.put(testNode, owner); ContainerNode cur = (ContainerNode) nodeDAO.getPath(path); Assert.assertNotNull(cur); // make 4 nodes in predictable alpha-order == NodeDAO ordering DataNode n1 = getCommonDataNode(path + "/abc"); ContainerNode n2 = getCommonContainerNode(path + "/bcd"); DataNode n3 = getCommonDataNode(path + "/cde"); ContainerNode n4 = getCommonContainerNode(path + "/def"); n1.setParent(cn); n2.setParent(cn); n3.setParent(cn); n4.setParent(cn); nodeDAO.put(n1, owner); nodeDAO.put(n2, owner); nodeDAO.put(n3, owner); nodeDAO.put(n4, owner); // get a vanilla container with no children cur = (ContainerNode) nodeDAO.getPath(path); Assert.assertNotNull(cur); Assert.assertEquals("empty child list", 0, cur.getNodes().size()); // load 2 child nodes nodeDAO.getChildren(cur, null, new Integer(2)); Assert.assertEquals("leading partial child list", 2, cur.getNodes().size()); // rely on implementation of Node.equals Assert.assertTrue(cur.getNodes().contains(n1)); Assert.assertTrue(cur.getNodes().contains(n2)); // get a trailing batch cur.getNodes().clear(); nodeDAO.getChildren(cur, n3.getUri(), new Integer(100)); Assert.assertEquals("trailing partial child list", 2, cur.getNodes().size()); Assert.assertTrue(cur.getNodes().contains(n3)); Assert.assertTrue(cur.getNodes().contains(n4)); nodeDAO.delete(cur, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetChildrenLimit - DONE"); } } @Test public void testGetChild() { log.debug("testGetChild - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // create a container String path = basePath + getNodeName("dir"); ContainerNode testNode = getCommonContainerNode(path); testNode.setParent(rootContainer); ContainerNode cn = (ContainerNode) nodeDAO.put(testNode, owner); ContainerNode cur = (ContainerNode) nodeDAO.getPath(path); Assert.assertNotNull(cur); DataNode n1 = getCommonDataNode(path + "/one"); ContainerNode n2 = getCommonContainerNode(path + "/two"); DataNode n3 = getCommonDataNode(path + "/three"); ContainerNode n4 = getCommonContainerNode(path + "/four"); n1.setParent(cn); n2.setParent(cn); n3.setParent(cn); n4.setParent(cn); nodeDAO.put(n1, owner); nodeDAO.put(n2, owner); nodeDAO.put(n3, owner); nodeDAO.put(n4, owner); // get a vanilla container with no children cur = (ContainerNode) nodeDAO.getPath(path); Assert.assertNotNull(cur); Assert.assertEquals("empty child list", 0, cur.getNodes().size()); // load the child nodes one at a time nodeDAO.getChild(cur, n1.getName()); Assert.assertEquals("contains 1", 1, cur.getNodes().size()); Assert.assertTrue("contains n1", cur.getNodes().contains(n1)); nodeDAO.getChild(cur, n4.getName()); Assert.assertEquals("contains 2", 2, cur.getNodes().size()); Assert.assertTrue("contains n4", cur.getNodes().contains(n4)); nodeDAO.getChild(cur, n2.getName()); Assert.assertEquals("contains 3", 3, cur.getNodes().size()); Assert.assertTrue("contains n2", cur.getNodes().contains(n2)); nodeDAO.getChild(cur, n3.getName()); Assert.assertEquals("contains 4", 4, cur.getNodes().size()); Assert.assertTrue("contains n3", cur.getNodes().contains(n3)); nodeDAO.delete(cur, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetChild - DONE"); } } @Test public void testUpdateProperties() { log.debug("testUpdateProperties - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a node with properties String path = basePath + getNodeName("g"); DataNode testNode = getCommonDataNode(path); testNode.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "stuff")); // NP table testNode.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_TYPE, "text/plain")); // N table testNode.setParent(rootContainer); // put + get + compare nodeDAO.put(testNode, owner); Node pNode = nodeDAO.getPath(path); Assert.assertNotNull(pNode); nodeDAO.getProperties(pNode); compareProperties("assert1", testNode.getProperties(), pNode.getProperties()); // add a property List<NodeProperty> props = new ArrayList<NodeProperty>(); props.add(new NodeProperty("some:thing", "value1")); // NP table props.add(new NodeProperty(VOS.PROPERTY_URI_CONTENTENCODING, "gzip")); // N table testNode.getProperties().addAll(props); // for comparison below // check that return value is right pNode = nodeDAO.updateProperties(pNode, props); Assert.assertNotNull(pNode); compareProperties("assert2", testNode.getProperties(), pNode.getProperties()); // check that persisted value is right pNode = nodeDAO.getPath(path); nodeDAO.getProperties(pNode); Assert.assertNotNull(pNode); compareProperties("assert3", testNode.getProperties(), pNode.getProperties()); // replace values testNode.getProperties().remove(new NodeProperty("some:thing", "")); testNode.getProperties().remove(new NodeProperty(VOS.PROPERTY_URI_TYPE, "")); props.clear(); props.add(new NodeProperty("some:thing", "value2")); props.add(new NodeProperty(VOS.PROPERTY_URI_TYPE, "application/pdf")); testNode.getProperties().addAll(props); // for comparison // check that return value is right pNode = nodeDAO.updateProperties(pNode, testNode.getProperties()); Assert.assertNotNull(pNode); compareProperties("assert4", testNode.getProperties(), pNode.getProperties()); // check that persisted value is right pNode = nodeDAO.getPath(path); nodeDAO.getProperties(pNode); Assert.assertNotNull(pNode); compareProperties("assert5", testNode.getProperties(), pNode.getProperties()); // test that we cannot update some read-only props props.clear(); props.add(new NodeProperty(VOS.PROPERTY_URI_CONTENTLENGTH, new Long(1024).toString())); props.add(new NodeProperty(VOS.PROPERTY_URI_CONTENTMD5, HexUtil.toHex(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }))); // do not add to testNode since these props cannot be updated by user // check that return value is right pNode = nodeDAO.updateProperties(pNode, props); Assert.assertNotNull(pNode); compareProperties("assert6", testNode.getProperties(), pNode.getProperties()); // check persisted value pNode = nodeDAO.getPath(path); Assert.assertNotNull(pNode); nodeDAO.getProperties(pNode); compareProperties("assert7", testNode.getProperties(), pNode.getProperties()); // remove properties props.clear(); NodeProperty newURI2 = new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, ""); // NP table newURI2.setMarkedForDeletion(true); props.add(newURI2); NodeProperty newEncoding = new NodeProperty(VOS.PROPERTY_URI_CONTENTENCODING, ""); // N table newEncoding.setMarkedForDeletion(true); props.add(newEncoding); testNode.getProperties().removeAll(props); // for future tests // check that return value is right pNode = nodeDAO.updateProperties(pNode, props); Assert.assertNotNull(pNode); Assert.assertNull("assert8", pNode.findProperty(VOS.PROPERTY_URI_DESCRIPTION)); Assert.assertNull("assert8", pNode.findProperty(VOS.PROPERTY_URI_CONTENTENCODING)); // check persisted value pNode = nodeDAO.getPath(path); Assert.assertNotNull(pNode); nodeDAO.getProperties(pNode); Assert.assertNull("assert9", pNode.findProperty(VOS.PROPERTY_URI_DESCRIPTION)); Assert.assertNull("assert9", pNode.findProperty(VOS.PROPERTY_URI_CONTENTENCODING)); log.debug("** test client adding props with duplicate in list **"); props.clear(); props.add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc1")); props.add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc1")); props.add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc2")); props.add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc2")); props.add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc1")); props.add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc2")); // expect the last one to win since we use List testNode.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "desc2")); // check that return value is right pNode = nodeDAO.updateProperties(pNode, props); Assert.assertNotNull(pNode); compareProperties("assert10", testNode.getProperties(), pNode.getProperties()); // check persisted value pNode = nodeDAO.getPath(path); Assert.assertNotNull(pNode); nodeDAO.getProperties(pNode); compareProperties("assert11", testNode.getProperties(), pNode.getProperties()); log.debug("** test client updating existing properties with duplicates in list **"); // check that return value is right pNode = nodeDAO.updateProperties(pNode, props); Assert.assertNotNull(pNode); compareProperties("assert12", testNode.getProperties(), pNode.getProperties()); pNode = nodeDAO.getPath(path); Assert.assertNotNull(pNode); nodeDAO.getProperties(pNode); compareProperties("assert13", testNode.getProperties(), pNode.getProperties()); log.debug("** test race condition on two clients adding the same new property **"); props.clear(); props.add(new NodeProperty(VOS.PROPERTY_URI_TITLE, "My Stuff")); testNode.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_TITLE, "My Stuff")); // now interleave the gets and upates Node pNode1 = nodeDAO.getPath(path); Assert.assertNotNull(pNode1); nodeDAO.getProperties(pNode1); Node pNode2 = nodeDAO.getPath(path); Assert.assertNotNull(pNode2); nodeDAO.getProperties(pNode2); // update and check return values pNode1 = nodeDAO.updateProperties(pNode1, props); Assert.assertNotNull(pNode1); compareProperties("assert14", testNode.getProperties(), pNode1.getProperties()); pNode2 = nodeDAO.updateProperties(pNode2, props); Assert.assertNotNull(pNode2); compareProperties("assert15", testNode.getProperties(), pNode2.getProperties()); // check persisted value pNode = nodeDAO.getPath(path); Assert.assertNotNull(pNode); nodeDAO.getProperties(pNode); compareProperties("assert16", testNode.getProperties(), pNode.getProperties()); nodeDAO.delete(pNode, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testUpdateProperties - DONE"); } } @Test public void testSetBusyState() { log.debug("testSetBusyState - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a node with properties String path = basePath + getNodeName("cl-test"); DataNode testNode = getCommonDataNode(path); testNode.setParent(rootContainer); // put and check default nodeDAO.put(testNode, owner); DataNode persistNode = (DataNode) nodeDAO.getPath(path); Assert.assertNotNull(persistNode); Assert.assertEquals("assert not busy", NodeBusyState.notBusy, persistNode.getBusy()); // -> write nodeDAO.setBusyState(persistNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); persistNode = (DataNode) nodeDAO.getPath(path); Assert.assertNotNull(persistNode); Assert.assertEquals("assert not busy", NodeBusyState.busyWithWrite, persistNode.getBusy()); // -> not busy nodeDAO.setBusyState(persistNode, NodeBusyState.busyWithWrite, NodeBusyState.notBusy); persistNode = (DataNode) nodeDAO.getPath(path); Assert.assertNotNull(persistNode); Assert.assertEquals("assert not busy", NodeBusyState.notBusy, persistNode.getBusy()); nodeDAO.delete(persistNode, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testSetBusyState - DONE"); } } @Test public void testUpdateFileMetadata() { log.debug("testUpdateFileMetadata - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; NodeProperty np; // Create a node with properties String cPath = basePath + getNodeName("ufm-dir"); ContainerNode cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); np = cNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull(np); // containers always have length //Assert.assertEquals("new container length", 0, Long.parseLong(np.getPropertyValue())); String dPath = cPath + "/" + getNodeName("ufm-file"); DataNode dNode = getCommonDataNode(dPath); dNode.setParent(cNode); nodeDAO.put(dNode, owner); dNode = (DataNode) nodeDAO.getPath(dPath); Assert.assertNotNull(dNode); Assert.assertNotNull(dNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertEquals("0", dNode.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); // update the quick way FileMetadata meta = new FileMetadata(); meta.setContentLength(new Long(2048L)); meta.setContentEncoding("gzip"); meta.setContentType("text/plain"); meta.setMd5Sum(HexUtil.toHex(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); log.debug("** update without setting busy state **"); try { nodeDAO.updateNodeMetadata(dNode, meta, false); Assert.fail("expected IllegalStateException calling updateNodeMetadata with busy=N"); } catch (IllegalStateException expected) { log.debug("caught expected exception: " + expected); } // get and store size of root container //np = rootContainer.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //long rootContentLength = Long.parseLong(np.getPropertyValue()); log.debug("** set busy state correctly and redo **"); nodeDAO.setBusyState(dNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); nodeDAO.updateNodeMetadata(dNode, meta, true); // check size on root container Node n = nodeDAO.getPath(HOME_CONTAINER); np = n.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull("contentLength NP", np); //long modRootLen = Long.parseLong(np.getPropertyValue()); //Assert.assertEquals("root length", rootContentLength+2048, modRootLen); // check size on container node n = nodeDAO.getPath(cPath); Assert.assertNotNull(n); np = n.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull("contentLength NP", np); //Assert.assertEquals(2048, Long.parseLong(np.getPropertyValue())); // check all metadata on data node n = nodeDAO.getPath(dPath); Assert.assertNotNull(n); np = n.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); Assert.assertNotNull("contentLength NP", np); Assert.assertEquals(2048, Long.parseLong(np.getPropertyValue())); np = n.findProperty(VOS.PROPERTY_URI_TYPE); Assert.assertNotNull("contentType NP", np); Assert.assertEquals(meta.getContentType(), np.getPropertyValue()); np = n.findProperty(VOS.PROPERTY_URI_CONTENTENCODING); Assert.assertNotNull("contentEncoding NP", np); Assert.assertEquals(meta.getContentEncoding(), np.getPropertyValue()); np = n.findProperty(VOS.PROPERTY_URI_CONTENTMD5); Assert.assertNotNull("contentMD5 NP", np); Assert.assertEquals(meta.getMd5Sum(), np.getPropertyValue()); nodeDAO.delete(cNode, 10, false); // cleanup assertRecursiveDelete(); log.debug("** now test that it fails when the c is moved mid-call **"); String oPath = cPath + "-other"; ContainerNode oNode = getCommonContainerNode(oPath); oNode.setParent(rootContainer); nodeDAO.put(oNode, owner); oNode = (ContainerNode) nodeDAO.getPath(oPath); Assert.assertNotNull(oNode); cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); np = cNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull(np); // containers always have length //Assert.assertEquals("new container length", 0, Long.parseLong(np.getPropertyValue())); dPath = cPath + "/" + getNodeName("ufm-test"); dNode = getCommonDataNode(dPath); dNode.setParent(cNode); nodeDAO.put(dNode, owner); dNode = (DataNode) nodeDAO.getPath(dPath); Assert.assertNotNull(dNode); Assert.assertNotNull(dNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertEquals("0", dNode.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); // alter path but leave dNode object alone Node srcNode = nodeDAO.getPath(dPath); nodeDAO.move(srcNode, oNode); Node movedNode = nodeDAO.getPath(oNode.getUri().getPath() + "/" + dNode.getName()); Assert.assertNotNull(movedNode); log.debug("movedNode: " + movedNode.getUri()); // set busy state nodeDAO.setBusyState(dNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); //try //{ // nodeDAO.updateNodeMetadata(dNode, meta); // Assert.fail("expected IllegalStateException calling updateNodeMetadata with altered path"); //} //catch(IllegalStateException expected) //{ // log.debug("caught expected exception: " + expected); //} // reset to enable cleanup nodeDAO.setBusyState(dNode, NodeBusyState.busyWithWrite, NodeBusyState.notBusy); nodeDAO.delete(cNode, 10, false); // cleanup nodeDAO.delete(oNode, 10, false); // cleanup assertRecursiveDelete(); log.debug("** now test that it fails when the data node is busy during put **"); oNode = getCommonContainerNode(oPath); oNode.setParent(rootContainer); nodeDAO.put(oNode, owner); oNode = (ContainerNode) nodeDAO.getPath(oPath); Assert.assertNotNull(oNode); cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); np = cNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull(np); // containers always have length //Assert.assertEquals("new container length", 0, Long.parseLong(np.getPropertyValue())); dPath = cPath + "/" + getNodeName("ufm-test"); dNode = getCommonDataNode(dPath); dNode.setParent(cNode); nodeDAO.put(dNode, owner); dNode = (DataNode) nodeDAO.getPath(dPath); Assert.assertNotNull(dNode); //Assert.assertNotNull(dNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH)); //Assert.assertEquals("0", dNode.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); // set busy state nodeDAO.setBusyState(dNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); // alter path but leave dNode object alone srcNode = nodeDAO.getPath(dPath); try { nodeDAO.move(srcNode, oNode); Assert.fail("expected IllegalStateException calling move of busy DataNode"); } catch (IllegalStateException expected) { log.debug("caught expected exception: " + expected); } // reset to enable cleanup nodeDAO.setBusyState(dNode, NodeBusyState.busyWithWrite, NodeBusyState.notBusy); nodeDAO.delete(cNode, 10, false); // cleanup nodeDAO.delete(oNode, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testUpdateFileMetadata - DONE"); } } @Test public void testGetRoot() { log.debug("testGetRoot - START"); try { VOSURI vos = new VOSURI(new URI("vos", VOS_AUTHORITY, null, null, null)); log.debug("path with null: [" + vos.getPath() + "]"); ContainerNode root = new ContainerNode(vos); vos = new VOSURI(new URI("vos", VOS_AUTHORITY, "", null, null)); log.debug("path with 0-length string: [" + vos.getPath() + "]"); root = new ContainerNode(vos); root.appData = new NodeID(); // null internal ID means root root.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_ISPUBLIC, "true")); nodeDAO.getChildren(root); for (Node n : root.getNodes()) log.debug("found: " + n); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetRoot - DONE"); } } @Test public void testMove() { log.debug("testMove - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a new node tree String moveRootPath = basePath + getNodeName("movetest"); String moveCont1Path = moveRootPath + "/" + getNodeName("movecont1"); String moveCont2Path = moveRootPath + "/" + getNodeName("movecont2"); String moveData1Path = moveRootPath + "/" + getNodeName("movedata1"); String moveCont3Path = moveCont1Path + "/" + getNodeName("movecont3"); String moveData2Path = moveCont1Path + "/" + getNodeName("movedata2"); String moveData3Path = moveCont2Path + "/" + getNodeName("movedata3"); String moveLink1Path = moveCont2Path + "/" + getNodeName("movelink1"); String moveData4Path = moveCont3Path + "/" + getNodeName("movedata4"); ContainerNode moveRoot = getCommonContainerNode(moveRootPath); ContainerNode moveCont1 = getCommonContainerNode(moveCont1Path); ContainerNode moveCont2 = getCommonContainerNode(moveCont2Path); DataNode moveData1 = getCommonDataNode(moveData1Path); ContainerNode moveCont3 = getCommonContainerNode(moveCont3Path); DataNode moveData2 = getCommonDataNode(moveData2Path); DataNode moveData3 = getCommonDataNode(moveData3Path); LinkNode moveLink1 = getCommonLinkNode(moveLink1Path); DataNode moveData4 = getCommonDataNode(moveData4Path); moveRoot.setParent(rootContainer); moveRoot = (ContainerNode) nodeDAO.put(moveRoot, owner); moveCont1.setParent(moveRoot); moveCont1 = (ContainerNode) nodeDAO.put(moveCont1, owner); moveCont2.setParent(moveRoot); moveCont2 = (ContainerNode) nodeDAO.put(moveCont2, owner); moveData1.setParent(moveRoot); moveData1 = (DataNode) nodeDAO.put(moveData1, owner); moveCont3.setParent(moveCont1); moveCont3 = (ContainerNode) nodeDAO.put(moveCont3, owner); moveData2.setParent(moveCont1); moveData2 = (DataNode) nodeDAO.put(moveData2, owner); moveData3.setParent(moveCont2); moveData3 = (DataNode) nodeDAO.put(moveData3, owner); moveLink1.setParent(moveCont2); moveLink1 = (LinkNode) nodeDAO.put(moveLink1, owner); moveData4.setParent(moveCont3); moveData4 = (DataNode) nodeDAO.put(moveData4, owner); // move cont2 to cont3 nodeDAO.move(moveCont2, moveCont3); // check that cont2 no longer under moveRoot moveRoot = (ContainerNode) nodeDAO.getPath(moveRootPath); Assert.assertNotNull(moveRoot); nodeDAO.getChildren(moveRoot); for (Node child : moveRoot.getNodes()) { if (child.getName().equals(moveCont2.getName()) || ((NodeID) child.appData).equals(((NodeID) moveCont2.appData).getID())) { Assert.fail("Failed to move container 2: still in old location."); } } // check that cont2 under cont3 moveCont3 = (ContainerNode) nodeDAO.getPath(moveCont3Path); Assert.assertNotNull(moveCont3); nodeDAO.getChildren(moveCont3); boolean found = false; for (Node child : moveCont3.getNodes()) { if (child.getName().equals(moveCont2.getName()) && ((NodeID) child.appData).getID().equals(((NodeID) moveCont2.appData).getID())) { found = true; } } if (!found) Assert.fail("Failed to move container 2: not in new location."); // check that cont2 has parent cont3 and child data3 moveCont2 = (ContainerNode) nodeDAO.getPath(moveCont3Path + "/" + moveCont2.getName()); Assert.assertNotNull(moveCont2); nodeDAO.getChildren(moveCont2); assertEquals("Cont2 has wrong parent.", moveCont3.getName(), moveCont2.getParent().getName()); assertEquals("Cont2 has wrong parent.", ((NodeID) moveCont3.appData).getID(), ((NodeID) moveCont2.getParent().appData).getID()); found = false; boolean foundLink = false; for (Node child : moveCont2.getNodes()) { if (child.getName().equals(moveData3.getName()) && ((NodeID) child.appData).getID().equals(((NodeID) moveData3.appData).getID())) { found = true; } else if (child.getName().equals(moveLink1.getName()) && ((NodeID) child.appData).getID().equals(((NodeID) moveLink1.appData).getID())) { foundLink = true; } } if (!found) Assert.fail("Lost child movedata3 on move."); if (!foundLink) Assert.fail("Lost child moveLink1 on move."); // move to a container underneath own tree (not allowed) moveCont1 = (ContainerNode) nodeDAO.getPath(moveCont1Path); Assert.assertNotNull(moveCont1); moveCont2 = (ContainerNode) nodeDAO.getPath(moveCont3Path + "/" + moveCont2.getName()); Assert.assertNotNull(moveCont2); try { nodeDAO.move(moveCont1, moveCont2); Assert.fail("Move should not have been allowed due to circular tree."); } catch (IllegalArgumentException e) { // expected } // try to move root (not allowed) try { Node root = new ContainerNode(new VOSURI("vos://cadc.nrc.ca~vospace/")); nodeDAO.move(root, moveCont1); Assert.fail("Should not have been allowed move root."); } catch (IllegalArgumentException e) { // expected } // try to move root container (not allowed) try { nodeDAO.move(rootContainer, moveCont1); Assert.fail("Should not have been allowed move root container."); } catch (IllegalArgumentException e) { // expected } // move with new owner, new name moveCont1 = (ContainerNode) nodeDAO.getPath(moveCont1Path); moveData3 = (DataNode) nodeDAO .getPath(moveCont3Path + "/" + moveCont2.getName() + "/" + moveData3.getName()); String newName = getNodeName("newName"); moveData3.setName(newName); nodeDAO.move(moveData3, moveCont1); // check that moveRoot now has moveData3 moveCont1 = (ContainerNode) nodeDAO.getPath(moveCont1Path); nodeDAO.getChildren(moveCont1); found = false; for (Node child : moveCont1.getNodes()) { if (child.getName().equals(newName) && ((NodeID) child.appData).getID().equals(((NodeID) moveData3.appData).getID())) { found = true; } } if (!found) Assert.fail("moveData4 not under root after move (name, id check)"); nodeDAO.delete(moveRoot, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testMove - DONE"); } } @Test public void testDelete() { log.debug("testDelete - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; NodeProperty np; // Create a node with properties String cPath = basePath + getNodeName("del-test-dir"); ContainerNode cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); np = cNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull(np); // containers always have length //Assert.assertEquals("new container length", 0, Long.parseLong(np.getPropertyValue())); String dPath = cPath + "/" + getNodeName("del-test-file"); DataNode dNode = getCommonDataNode(dPath); dNode.setParent(cNode); nodeDAO.put(dNode, owner); dNode = (DataNode) nodeDAO.getPath(dPath); Assert.assertNotNull(dNode); Assert.assertNotNull(dNode.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH)); Assert.assertEquals("0", dNode.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); // update the quick way FileMetadata meta = new FileMetadata(); meta.setContentLength(new Long(2048L)); meta.setContentEncoding("gzip"); meta.setContentType("text/plain"); meta.setMd5Sum(HexUtil.toHex(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); // get and store size of root container //np = rootContainer.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //long rootContentLength = Long.parseLong(np.getPropertyValue()); // set busy state and set data node size nodeDAO.setBusyState(dNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); // test that busy node cannot be deleted directly try { // thread 1: do the delete log.debug("** trying to delete busy " + dNode.getUri().getPath()); nodeDAO.delete(dNode); Assert.fail("expected IllegalStateException but delete returned"); } catch (IllegalStateException expected) { log.debug("caught expected exception: " + expected); } nodeDAO.updateNodeMetadata(dNode, meta, true); // check size on root container Node n = nodeDAO.getPath(HOME_CONTAINER); np = n.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull("contentLength NP", np); //long modRootLen = Long.parseLong(np.getPropertyValue()); //Assert.assertEquals("root length", rootContentLength+2048, modRootLen); // check size on container node n = nodeDAO.getPath(cPath); Assert.assertNotNull(n); np = n.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull("contentLength NP", np); //Assert.assertEquals(2048, Long.parseLong(np.getPropertyValue())); Node target = n; nodeDAO.delete(n); // check size on root container n = nodeDAO.getPath(HOME_CONTAINER); np = n.findProperty(VOS.PROPERTY_URI_CONTENTLENGTH); //Assert.assertNotNull("contentLength NP", np); //modRootLen = Long.parseLong(np.getPropertyValue()); //Assert.assertEquals("root length", rootContentLength, modRootLen); // check that cNode is now under /DeletedNodes ContainerNode deleted = (ContainerNode) nodeDAO.getPath(DELETED_NODES); nodeDAO.getChildren(deleted); boolean found = false; for (Node child : deleted.getNodes()) { if (((NodeID) child.appData).getID().equals(((NodeID) target.appData).getID())) { found = true; } } if (!found) Assert.fail("delete: node not found under /DeletedNodes after delete"); log.debug("** test failed delete if path changed **"); cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); dNode = getCommonDataNode(dPath); dNode.setParent(cNode); nodeDAO.put(dNode, owner); dNode = (DataNode) nodeDAO.getPath(dPath); Assert.assertNotNull(dNode); //Assert.assertNotNull(dNode.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); //Assert.assertEquals("0", dNode.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH)); String oPath = cPath + "-other"; ContainerNode oNode = getCommonContainerNode(oPath); oNode.setParent(rootContainer); nodeDAO.put(oNode, owner); oNode = (ContainerNode) nodeDAO.getPath(oPath); Assert.assertNotNull(oNode); // thread 1: select independent object to delete later Node deletedNode = nodeDAO.getPath(dPath); Assert.assertNotNull(deletedNode); // thread 2: move nodeDAO.move(dNode, oNode); Node actual = nodeDAO.getPath(oPath + "/" + dNode.getName()); Assert.assertNotNull(actual); try { // thread 1: do the delete log.debug("** trying to delete " + deletedNode.getUri().getPath()); nodeDAO.delete(deletedNode); Assert.fail("expected IllegalStateException but delete returned"); } catch (IllegalStateException expected) { log.debug("caught expected exception: " + expected); } nodeDAO.delete(oNode, 10, false); // cleanup nodeDAO.delete(cNode, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testDelete - DONE"); } } @Test public void testBatchChown() { log.debug("testBatchChown - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a new node tree with owner/creator NODE_OWNER String chownRootPath = basePath + getNodeName("chowntest"); String chownSub1Path = chownRootPath + "/" + getNodeName("chownsub1"); String chownSub2Path = chownRootPath + "/" + getNodeName("chownsub2"); String chownSub3Path = chownRootPath + "/" + getNodeName("chownsub3"); String chownSub1Sub1Path = chownSub1Path + "/" + getNodeName("chownsub1sub1"); String chownSub1Sub2Path = chownSub1Path + "/" + getNodeName("chownsub1sub2"); String chownSub2Sub1Path = chownSub2Path + "/" + getNodeName("chownsub2sub1"); String chownSub1Sub1Sub1Path = chownSub1Sub1Path + "/" + getNodeName("chownsub1sub1sub1"); ContainerNode chownRoot = getCommonContainerNode(chownRootPath); ContainerNode chownSub1 = getCommonContainerNode(chownSub1Path); ContainerNode chownSub2 = getCommonContainerNode(chownSub2Path); DataNode chownSub3 = getCommonDataNode(chownSub3Path); ContainerNode chownSub1Sub1 = getCommonContainerNode(chownSub1Sub1Path); DataNode chownSub1Sub2 = getCommonDataNode(chownSub1Sub2Path); DataNode chownSub2Sub1 = getCommonDataNode(chownSub2Sub1Path); DataNode chownSub1Sub1Sub1 = getCommonDataNode(chownSub1Sub1Sub1Path); chownRoot.setParent(rootContainer); chownRoot = (ContainerNode) nodeDAO.put(chownRoot, owner); chownSub1.setParent(chownRoot); chownSub1 = (ContainerNode) nodeDAO.put(chownSub1, owner); chownSub2.setParent(chownRoot); chownSub2 = (ContainerNode) nodeDAO.put(chownSub2, owner); chownSub3.setParent(chownRoot); chownSub3 = (DataNode) nodeDAO.put(chownSub3, owner); chownSub1Sub1.setParent(chownSub1); chownSub1Sub1 = (ContainerNode) nodeDAO.put(chownSub1Sub1, owner); chownSub1Sub2.setParent(chownSub1); chownSub1Sub2 = (DataNode) nodeDAO.put(chownSub1Sub2, owner); chownSub2Sub1.setParent(chownSub2); chownSub2Sub1 = (DataNode) nodeDAO.put(chownSub2Sub1, owner); chownSub1Sub1Sub1.setParent(chownSub1Sub1); chownSub1Sub1Sub1 = (DataNode) nodeDAO.put(chownSub1Sub1Sub1, owner); // get the root node chownRoot = (ContainerNode) nodeDAO.getPath(chownRootPath); Assert.assertNotNull(chownRoot); int numS = nodeDAO.numTxnStarted; int numC = nodeDAO.numTxnCommitted; // change the ownership non recursively nodeDAO.chown(chownRoot, owner2, false, 1000, false); Assert.assertEquals("batch start", numS + 1, nodeDAO.numTxnStarted); Assert.assertEquals("batch commit", numC + 1, nodeDAO.numTxnCommitted); // check the ownership change chownRoot = (ContainerNode) nodeDAO.getPath(chownRootPath); assertEquals("Non-recursive chown failed.", chownRoot.getPropertyValue(VOS.PROPERTY_URI_CREATOR).toLowerCase(), NODE_OWNER2.toLowerCase()); // get a sub node chownSub1 = (ContainerNode) nodeDAO.getPath(chownSub1Path); // check for no ownership change assertEquals("Non-recursive chown failed.", chownSub1.getPropertyValue(VOS.PROPERTY_URI_CREATOR).toLowerCase(), NODE_OWNER.toLowerCase()); // change the ownership recursively in one large batch numS = nodeDAO.numTxnStarted; numC = nodeDAO.numTxnCommitted; nodeDAO.chown(chownRoot, owner2, true, 2, false); // 8 nodes = 4 batches in total, plus one extra empty txn at the end Assert.assertEquals("batch start", numS + 5, nodeDAO.numTxnStarted); Assert.assertEquals("batch commit", numC + 5, nodeDAO.numTxnCommitted); // check for deep ownership change chownSub1Sub1Sub1 = (DataNode) nodeDAO.getPath(chownSub1Sub1Sub1Path); assertEquals("Recursive chown failed.", chownSub1Sub1Sub1.getPropertyValue(VOS.PROPERTY_URI_CREATOR).toLowerCase(), NODE_OWNER2.toLowerCase()); nodeDAO.delete(chownRoot, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testBatchChown - DONE"); } } @Test public void testBatchChownDryrun() { log.debug("testBatchChownDryrun - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a new node tree with owner/creator NODE_OWNER String chownRootPath = basePath + getNodeName("chowntest"); String chownSub1Path = chownRootPath + "/" + getNodeName("chownsub1"); String chownSub2Path = chownRootPath + "/" + getNodeName("chownsub2"); String chownSub3Path = chownRootPath + "/" + getNodeName("chownsub3"); String chownSub1Sub1Path = chownSub1Path + "/" + getNodeName("chownsub1sub1"); String chownSub1Sub2Path = chownSub1Path + "/" + getNodeName("chownsub1sub2"); String chownSub2Sub1Path = chownSub2Path + "/" + getNodeName("chownsub2sub1"); String chownSub1Sub1Sub1Path = chownSub1Sub1Path + "/" + getNodeName("chownsub1sub1sub1"); ContainerNode chownRoot = getCommonContainerNode(chownRootPath); ContainerNode chownSub1 = getCommonContainerNode(chownSub1Path); ContainerNode chownSub2 = getCommonContainerNode(chownSub2Path); DataNode chownSub3 = getCommonDataNode(chownSub3Path); ContainerNode chownSub1Sub1 = getCommonContainerNode(chownSub1Sub1Path); DataNode chownSub1Sub2 = getCommonDataNode(chownSub1Sub2Path); DataNode chownSub2Sub1 = getCommonDataNode(chownSub2Sub1Path); DataNode chownSub1Sub1Sub1 = getCommonDataNode(chownSub1Sub1Sub1Path); chownRoot.setParent(rootContainer); chownRoot = (ContainerNode) nodeDAO.put(chownRoot, owner); chownSub1.setParent(chownRoot); chownSub1 = (ContainerNode) nodeDAO.put(chownSub1, owner); chownSub2.setParent(chownRoot); chownSub2 = (ContainerNode) nodeDAO.put(chownSub2, owner); chownSub3.setParent(chownRoot); chownSub3 = (DataNode) nodeDAO.put(chownSub3, owner); chownSub1Sub1.setParent(chownSub1); chownSub1Sub1 = (ContainerNode) nodeDAO.put(chownSub1Sub1, owner); chownSub1Sub2.setParent(chownSub1); chownSub1Sub2 = (DataNode) nodeDAO.put(chownSub1Sub2, owner); chownSub2Sub1.setParent(chownSub2); chownSub2Sub1 = (DataNode) nodeDAO.put(chownSub2Sub1, owner); chownSub1Sub1Sub1.setParent(chownSub1Sub1); chownSub1Sub1Sub1 = (DataNode) nodeDAO.put(chownSub1Sub1Sub1, owner); // get the root node chownRoot = (ContainerNode) nodeDAO.getPath(chownRootPath); Assert.assertNotNull(chownRoot); int numS = nodeDAO.numTxnStarted; int numC = nodeDAO.numTxnCommitted; // change the ownership non recursively, dryrun == no actual change nodeDAO.chown(chownRoot, owner2, false, 1000, true); // no new txns Assert.assertEquals("batch start", numS, nodeDAO.numTxnStarted); Assert.assertEquals("batch commit", numC, nodeDAO.numTxnCommitted); // check the ownership change chownRoot = (ContainerNode) nodeDAO.getPath(chownRootPath); assertEquals("Non-recursive chown failed.", chownRoot.getPropertyValue(VOS.PROPERTY_URI_CREATOR).toLowerCase(), NODE_OWNER.toLowerCase()); // get a sub node chownSub1 = (ContainerNode) nodeDAO.getPath(chownSub1Path); // check for no ownership change assertEquals("Non-recursive chown failed.", chownSub1.getPropertyValue(VOS.PROPERTY_URI_CREATOR).toLowerCase(), NODE_OWNER.toLowerCase()); // change the ownership recursively in one large batch numS = nodeDAO.numTxnStarted; numC = nodeDAO.numTxnCommitted; nodeDAO.chown(chownRoot, owner2, true, 2, true); // dryrun: no txns Assert.assertEquals("batch start", numS, nodeDAO.numTxnStarted); Assert.assertEquals("batch commit", numC, nodeDAO.numTxnCommitted); // check for deep ownership change chownSub1Sub1Sub1 = (DataNode) nodeDAO.getPath(chownSub1Sub1Sub1Path); assertEquals("Recursive chown failed.", chownSub1Sub1Sub1.getPropertyValue(VOS.PROPERTY_URI_CREATOR).toLowerCase(), NODE_OWNER.toLowerCase()); nodeDAO.delete(chownRoot, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testBatchChownDryrun - DONE"); } } @Test public void testBatchDelete() { log.debug("testBatchDelete - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; NodeProperty np; // test setup: // del-test-dir/del-test-file1 // /del-test-file2 // /del-test-dir1 // /del-test-dir1/del-test-file3 // /del-test-dir2 // Create a node with properties String cPath = basePath + getNodeName("del-test-dir"); ContainerNode cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); String dPath1 = cPath + "/" + getNodeName("del-test-file1"); Node dNode1 = getCommonDataNode(dPath1); dNode1.setParent(cNode); nodeDAO.put(dNode1, owner); dNode1 = nodeDAO.getPath(dPath1); Assert.assertNotNull(dNode1); String dPath2 = cPath + "/" + getNodeName("del-test-file2"); Node dNode2 = getCommonDataNode(dPath2); dNode2.setParent(cNode); nodeDAO.put(dNode2, owner); dNode2 = nodeDAO.getPath(dPath2); Assert.assertNotNull(dNode2); // since this is an admin API delete, it should ignore busy state nodeDAO.setBusyState((DataNode) dNode2, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); String cPath1 = cPath + "/" + getNodeName("del-test-dir1"); ContainerNode cNode1 = getCommonContainerNode(cPath1); cNode1.setParent(cNode); nodeDAO.put(cNode1, owner); cNode1 = (ContainerNode) nodeDAO.getPath(cPath1); Assert.assertNotNull(cNode1); String dPath3 = cPath1 + "/" + getNodeName("del-test-file3"); Node dNode3 = getCommonDataNode(dPath3); dNode3.setParent(cNode1); nodeDAO.put(dNode3, owner); dNode3 = nodeDAO.getPath(dPath3); Assert.assertNotNull(dNode3); String cPath2 = cPath + "/" + getNodeName("del-test-dir2"); Node cNode2 = getCommonContainerNode(cPath2); cNode2.setParent(cNode); nodeDAO.put(cNode2, owner); cNode2 = nodeDAO.getPath(cPath2); Assert.assertNotNull(cNode2); int numS = nodeDAO.numTxnStarted; int numC = nodeDAO.numTxnCommitted; nodeDAO.delete(cNode, 2, false); // 4 nodes = 4 batches + 1 empty txn Assert.assertEquals("batch start", numS + 5, nodeDAO.numTxnStarted); Assert.assertEquals("batch commit", numC + 5, nodeDAO.numTxnCommitted); Node notFound = nodeDAO.getPath(cPath); Assert.assertNull(notFound); assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testBatchDelete - DONE"); } } @Test public void testBatchDeleteDryrun() { log.debug("testBatchDeleteDryrun - START"); try { ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; NodeProperty np; // Create a node with properties String cPath = basePath + getNodeName("del-test-dir"); ContainerNode cNode = getCommonContainerNode(cPath); cNode.setParent(rootContainer); nodeDAO.put(cNode, owner); cNode = (ContainerNode) nodeDAO.getPath(cPath); Assert.assertNotNull(cNode); String dPath1 = cPath + "/" + getNodeName("del-test-file1"); Node dNode1 = getCommonDataNode(dPath1); dNode1.setParent(cNode); nodeDAO.put(dNode1, owner); dNode1 = nodeDAO.getPath(dPath1); Assert.assertNotNull(dNode1); String dPath2 = cPath + "/" + getNodeName("del-test-file2"); Node dNode2 = getCommonDataNode(dPath2); dNode2.setParent(cNode); nodeDAO.put(dNode2, owner); dNode2 = nodeDAO.getPath(dPath2); Assert.assertNotNull(dNode2); String cPath2 = cPath + "/" + getNodeName("del-test-dir2"); Node cNode2 = getCommonContainerNode(cPath2); cNode2.setParent(cNode); nodeDAO.put(cNode2, owner); cNode2 = nodeDAO.getPath(cPath2); Assert.assertNotNull(cNode2); int numS = nodeDAO.numTxnStarted; int numC = nodeDAO.numTxnCommitted; nodeDAO.delete(cNode, 2, true); // dryrun - no extra txns Assert.assertEquals("batch start", numS, nodeDAO.numTxnStarted); Assert.assertEquals("batch commit", numC, nodeDAO.numTxnCommitted); Node notDeleted = nodeDAO.getPath(cPath); Assert.assertNotNull(notDeleted); // actual delete nodeDAO.delete(cNode, 10, false); // cleanup assertRecursiveDelete(); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testBatchDeleteDryrun - DONE"); } } @Test public void testUpdateMetadataDelta() { log.debug("testUpdateMetadataDelta - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerPath = basePath + getNodeName("delta-test"); ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); // manually set the content length & nodeSize JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "update Node set contentLength=4, busyState='W' where name='" + dataNode.getName() + "'"; jdbc.update(sql); FileMetadata meta = new FileMetadata(); meta.setContentLength(10L); // perform the metadata update nodeDAO.updateNodeMetadata(dataNode, meta, true); int delta = jdbc.queryForInt("select delta from Node where name='" + dataNode.getName() + "'"); Assert.assertEquals("Wrong delta", 6, delta); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testUpdateMetadataDelta - DONE"); } } @Test public void testDeleteDelta() { log.debug("testDeleteDelta - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerPath = basePath + getNodeName("delta-test2"); ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); // manually set the nodeSize JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "update Node set contentLength=2 where name='" + dataNode.getName() + "'"; jdbc.update(sql); // manually set the delta sql = "update Node set delta=7 where name='" + containerNode.getName() + "'"; jdbc.update(sql); nodeDAO.delete(dataNode); int delta = jdbc.queryForInt("select delta from Node where name='" + containerNode.getName() + "'"); // delta should now be 7-2 Assert.assertEquals("Wrong delta", 5, delta); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testDeleteDelta - DONE"); } } @Test public void testMoveDelta() { log.debug("testMoveDelta - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerPath = basePath + getNodeName("delta-test3"); ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create another container node String containerPath2 = basePath + getNodeName("delta-test4"); ContainerNode containerNode2 = this.getCommonContainerNode(containerPath2); containerNode2.setParent(rootContainer); containerNode2 = (ContainerNode) nodeDAO.put(containerNode2, owner); // Create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); // manually set the nodeSize JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "update Node set contentLength=9 where name='" + dataNode.getName() + "'"; jdbc.update(sql); // manually set the deltas sql = "update Node set delta=11 where name='" + containerNode.getName() + "'"; jdbc.update(sql); sql = "update Node set delta=13 where name='" + containerNode2.getName() + "'"; jdbc.update(sql); nodeDAO.move(dataNode, containerNode2); int delta = jdbc.queryForInt("select delta from Node where name='" + containerNode.getName() + "'"); Assert.assertEquals("Wrong delta", 2, delta); delta = jdbc.queryForInt("select delta from Node where name='" + containerNode2.getName() + "'"); Assert.assertEquals("Wrong delta", 22, delta); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testMoveDelta - DONE"); } } @Test public void testGetOutstandingSizePropagations() { log.debug("testGetOutstandingSizePropagations - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerPath = basePath + getNodeName("trickle-test1"); ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); // manually set the deltas JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "update Node set delta=11 where name='" + dataNode.getName() + "'"; jdbc.update(sql); sql = "update Node set delta=3 where name='" + containerNode.getName() + "'"; jdbc.update(sql); // grab the nodeIDs for assertion sql = "select nodeID from Node where name='" + dataNode.getName() + "'"; Long dataNodeID = jdbc.queryForLong(sql); sql = "select nodeID from Node where name='" + containerNode.getName() + "'"; Long containerNodeID = jdbc.queryForLong(sql); sql = "select nodeID from Node where name='" + rootContainer.getName() + "'"; Long rootNodeID = jdbc.queryForLong(sql); List<NodeSizePropagation> propagations = nodeDAO.getOutstandingPropagations(100, false); Assert.assertTrue("Wrong number of oustanding propagations", propagations.size() == 2); // sort them for assertion Collections.sort(propagations, new Comparator<NodeSizePropagation>() { @Override public int compare(NodeSizePropagation n1, NodeSizePropagation n2) { return -1 * n1.getChildType().compareTo(n2.getChildType()); } }); Assert.assertEquals("Wrong data node ID", dataNodeID, (Long) propagations.get(0).getChildID()); Assert.assertEquals("Wrong data node ID", containerNodeID, propagations.get(0).getParentID()); Assert.assertEquals("Wrong data node ID", containerNodeID, (Long) propagations.get(1).getChildID()); Assert.assertEquals("Wrong data node ID", rootNodeID, propagations.get(1).getParentID()); } catch (Exception unexpected) { log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testGetOutstandingSizePropagations - DONE"); } } @Test public void testApplyNodeSizePropagation() { log.debug("testApplyNodeSizePropagation - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerPath = basePath + getNodeName("trickle-test2"); ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); // manually set the deltas JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "update Node set delta=11 where name='" + dataNode.getName() + "'"; jdbc.update(sql); sql = "update Node set delta=3 where name='" + containerNode.getName() + "'"; jdbc.update(sql); List<NodeSizePropagation> propagations = nodeDAO.getOutstandingPropagations(100, true); // sort them Collections.sort(propagations, new Comparator<NodeSizePropagation>() { @Override public int compare(NodeSizePropagation n1, NodeSizePropagation n2) { return -1 * n1.getChildType().compareTo(n2.getChildType()); } }); Assert.assertTrue("Wrong number of outstanding propagations", propagations.size() == 1); // get them again propagations = nodeDAO.getOutstandingPropagations(100, false); // sort them Collections.sort(propagations, new Comparator<NodeSizePropagation>() { @Override public int compare(NodeSizePropagation n1, NodeSizePropagation n2) { return -1 * n1.getChildType().compareTo(n2.getChildType()); } }); Assert.assertTrue("Wrong number of outstanding propagations", propagations.size() == 2); nodeDAO.applyPropagation(propagations.get(0)); propagations = nodeDAO.getOutstandingPropagations(100, false); Assert.assertTrue("Wrong number of outstanding propagations", propagations.size() == 1); nodeDAO.applyPropagation(propagations.get(0)); propagations = nodeDAO.getOutstandingPropagations(100, false); Assert.assertTrue("Wrong number of outstanding propagations", propagations.size() == 1); nodeDAO.applyPropagation(propagations.get(0)); propagations = nodeDAO.getOutstandingPropagations(100, false); Assert.assertTrue("Wrong number of outstanding propagations", propagations.size() == 0); } catch (Exception unexpected) { unexpected.printStackTrace(); log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testApplyNodeSizePropagation - DONE"); } } @Test public void testPropagationNewThenApply() { log.debug("testPropagationNewThenApply - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerName = getNodeName("trickle-test3"); String containerPath = basePath + containerName; ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); JdbcTemplate jdbc = new JdbcTemplate(dataSource); // ensure the contentLength is zero to start String sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; Long contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(0L), contentLength); // ensure the data node delta is zero to start sql = "select delta from Node where name='" + dataNode.getName() + "'"; Long delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(0L), delta); // manually set the busy state sql = "update Node set busyState='W' where name='" + dataNode.getName() + "'"; jdbc.update(sql); // update the metadata, using the strict option FileMetadata metadata = new FileMetadata(); metadata.setContentLength(10L); metadata.setMd5Sum("a94fc20c049422af7c591e2984f1f82d"); nodeDAO.updateNodeMetadata(dataNode, metadata, true); // ensure the state is back to normal sql = "select busyState from Node where name='" + dataNode.getName() + "'"; String curState = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong busy state", "N", curState); // ensure the contentLength is correct sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(10L), contentLength); // ensure the data node delta is correct sql = "select delta from Node where name='" + dataNode.getName() + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(10L), delta); // ensure the md5sum is correct sql = "select contentMD5 from Node where name='" + dataNode.getName() + "'"; String md5sum = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong md5 sum", "a94fc20c049422af7c591e2984f1f82d".toUpperCase(), md5sum.toUpperCase()); // get the nodeID sql = "select nodeID from Node where name='" + dataNode.getName() + "'"; long nodeID = jdbc.queryForLong(sql); log.debug("nodeID is " + nodeID); // get the propagation List<NodeSizePropagation> propagations = nodeDAO.getOutstandingPropagations(100, false); NodeSizePropagation propagation = null; for (NodeSizePropagation next : propagations) { log.debug("Looking at propgation with nodeID: " + next.getChildID()); if (next.getChildID() == nodeID) propagation = next; } Assert.assertNotNull("Null propagation", propagation); // apply the propagation nodeDAO.applyPropagation(propagation); // ensure the data node content length is correct sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(10L), contentLength); // ensure the data node delta is correct sql = "select delta from Node where name='" + dataNode.getName() + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(0L), delta); // ensure the container node content length is correct sql = "select contentLength from Node where name='" + containerName + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container content length", Long.valueOf(0L), contentLength); // ensure the container node delta is correct sql = "select delta from Node where name='" + containerName + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container delta", Long.valueOf(10L), delta); } catch (Exception unexpected) { unexpected.printStackTrace(); log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testPropagationNewThenApply - DONE"); } } @Test public void testPropagationNewReplaceThenApply() { log.debug("testPropagationNewReplaceThenApply - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerName = getNodeName("trickle-test4"); String containerPath = basePath + containerName; ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); JdbcTemplate jdbc = new JdbcTemplate(dataSource); // ensure the contentLength is zero to start String sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; Long contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(0L), contentLength); // ensure the data node delta is zero to start sql = "select delta from Node where name='" + dataNode.getName() + "'"; Long delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(0L), delta); // manually set the busy state sql = "update Node set busyState='W' where name='" + dataNode.getName() + "'"; jdbc.update(sql); // update the metadata, using the strict option FileMetadata metadata = new FileMetadata(); metadata.setContentLength(10L); metadata.setMd5Sum("a94fc20c049422af7c591e2984f1f82d"); nodeDAO.updateNodeMetadata(dataNode, metadata, true); // ensure the state is back to normal sql = "select busyState from Node where name='" + dataNode.getName() + "'"; String curState = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong busy state", "N", curState); // ensure the contentLength is correct sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(10L), contentLength); // ensure the md5sum is correct sql = "select contentMD5 from Node where name='" + dataNode.getName() + "'"; String md5sum = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong md5 sum", "a94fc20c049422af7c591e2984f1f82d".toUpperCase(), md5sum.toUpperCase()); // ensure the data node delta is correct sql = "select delta from Node where name='" + dataNode.getName() + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(10L), delta); // start the replace--manually set the busy state sql = "update Node set busyState='W' where name='" + dataNode.getName() + "'"; jdbc.update(sql); // update the metadata, using the strict option metadata = new FileMetadata(); metadata.setContentLength(15L); metadata.setMd5Sum("c2831384aae9c2e175c255797c2cfca5"); nodeDAO.updateNodeMetadata(dataNode, metadata, true); // ensure the state is back to normal sql = "select busyState from Node where name='" + dataNode.getName() + "'"; curState = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong busy state", "N", curState); // ensure the contentLength is correct sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(15L), contentLength); // ensure the md5sum is correct sql = "select contentMD5 from Node where name='" + dataNode.getName() + "'"; md5sum = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong md5 sum", "c2831384aae9c2e175c255797c2cfca5".toUpperCase(), md5sum.toUpperCase()); // ensure the data node delta is correct sql = "select delta from Node where name='" + dataNode.getName() + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(15L), delta); // get the nodeID sql = "select nodeID from Node where name='" + dataNode.getName() + "'"; long nodeID = jdbc.queryForLong(sql); // get the propagation List<NodeSizePropagation> propagations = nodeDAO.getOutstandingPropagations(100, false); NodeSizePropagation propagation = null; for (NodeSizePropagation next : propagations) { if (next.getChildID() == nodeID) propagation = next; } Assert.assertNotNull("Null propagation", propagation); // apply the propagation nodeDAO.applyPropagation(propagation); // ensure the data node content length is correct sql = "select contentLength from Node where name='" + dataNode.getName() + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong content length", Long.valueOf(15L), contentLength); // ensure the data node delta is correct sql = "select delta from Node where name='" + dataNode.getName() + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong delta", Long.valueOf(0L), delta); // ensure the container node content length is correct sql = "select contentLength from Node where name='" + containerName + "'"; contentLength = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container content length", Long.valueOf(0L), contentLength); // ensure the container node delta is correct sql = "select delta from Node where name='" + containerName + "'"; delta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container delta", Long.valueOf(15L), delta); } catch (Exception unexpected) { unexpected.printStackTrace(); log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testPropagationNewReplaceThenApply - DONE"); } } @Test public void testPropagateThenDelete() { log.debug("testPropagateThenDelete - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container String containerName = getNodeName("trickle-test4"); String containerPath = basePath + containerName; ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a child data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); JdbcTemplate jdbc = new JdbcTemplate(dataSource); // update data node metadata (simulate a put) nodeDAO.setBusyState(dataNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); FileMetadata metadata = new FileMetadata(); metadata.setContentLength(5L); metadata.setMd5Sum("a94fc20c049422af7c591e2984f1f82d"); nodeDAO.updateNodeMetadata(dataNode, metadata, false); // propagate data node String sql = "select nodeID from Node where name='" + containerNode.getName() + "'"; long parentNodeID = jdbc.queryForLong(sql); sql = "select nodeID from Node where name='" + dataNode.getName() + "'"; long dataNodeID = jdbc.queryForLong(sql); NodeSizePropagation np = new NodeSizePropagation(dataNodeID, NodeDAO.NODE_TYPE_DATA, parentNodeID); nodeDAO.applyPropagation(np); sql = "select delta from Node where name='" + containerNode.getName() + "'"; long actualDelta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container delta", 5L, actualDelta); // delete data node nodeDAO.delete(dataNode); // assert right container size actualDelta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container delta", 0L, actualDelta); } catch (Exception unexpected) { unexpected.printStackTrace(); log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testPropagateThenDelete - DONE"); } } @Test public void testDeltaOnDelete() { log.debug("testDeltaOnDelete - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container String containerName = getNodeName("trickle-test4"); String containerPath = basePath + containerName; ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a child data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); JdbcTemplate jdbc = new JdbcTemplate(dataSource); // update data node metadata (simulate a put) nodeDAO.setBusyState(dataNode, NodeBusyState.notBusy, NodeBusyState.busyWithWrite); FileMetadata metadata = new FileMetadata(); metadata.setContentLength(5L); metadata.setMd5Sum("a94fc20c049422af7c591e2984f1f82d"); nodeDAO.updateNodeMetadata(dataNode, metadata, false); String sql = "select delta from Node where name='" + containerNode.getName() + "'"; long actualDelta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container delta", 0L, actualDelta); // delete data node nodeDAO.delete(dataNode); // assert right delta size actualDelta = jdbc.queryForLong(sql); Assert.assertEquals("Wrong container delta", 0L, actualDelta); } catch (Exception unexpected) { unexpected.printStackTrace(); log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testDeltaOnDelete - DONE"); } } @Test public void testDatabaseDateRoundTrip() { log.debug("testDatabaseDateRoundTrip - START"); try { DBConfig dbConfig = new DBConfig(); ConnectionConfig connConfig = dbConfig.getConnectionConfig(SERVER, DATABASE); this.dataSource = DBUtil.getDataSource(connConfig); NodeSchema ns = new NodeSchema("Node", "NodeProperty", true); // TOP this.nodeDAO = new NodeDAO(dataSource, ns, VOS_AUTHORITY, new X500IdentityManager(), DELETED_NODES); ContainerNode rootContainer = (ContainerNode) nodeDAO.getPath(HOME_CONTAINER); log.debug("ROOT: " + rootContainer); Assert.assertNotNull(rootContainer); String basePath = "/" + HOME_CONTAINER + "/"; // Create a container node String containerPath = basePath + getNodeName("trickle-test2"); ContainerNode containerNode = this.getCommonContainerNode(containerPath); containerNode.setParent(rootContainer); containerNode = (ContainerNode) nodeDAO.put(containerNode, owner); // Create a data node String dataPath = containerNode.getUri().getPath() + "/" + "dataNode" + System.currentTimeMillis(); DataNode dataNode = getCommonDataNode(dataPath); dataNode.setParent(containerNode); nodeDAO.put(dataNode, owner); // manually set the busy state JdbcTemplate jdbc = new JdbcTemplate(dataSource); String sql = "update Node set busyState='W' where name='" + dataNode.getName() + "'"; jdbc.update(sql); // update the metadata, using the strict option nodeDAO.updateNodeMetadata(dataNode, new FileMetadata(), true); // ensure the state is back to normal sql = "select busyState from Node where name='" + dataNode.getName() + "'"; String curState = (String) jdbc.queryForObject(sql, String.class); Assert.assertEquals("Wrong busy state", "N", curState); // manually reset the busy state sql = "update Node set busyState='W' where name='" + dataNode.getName() + "'"; jdbc.update(sql); // modify some metadata (this will tweak the date) List<NodeProperty> properties = new ArrayList<NodeProperty>(); properties.add(new NodeProperty(VOS.PROPERTY_URI_ISLOCKED, "true")); nodeDAO.updateProperties(dataNode, properties); // update the metadata again (should get illegal argument exception) try { nodeDAO.updateNodeMetadata(dataNode, new FileMetadata(), true); Assert.fail("Strict option failed."); } catch (IllegalStateException e) { // expected } } catch (Exception unexpected) { unexpected.printStackTrace(); log.error("unexpected exception", unexpected); Assert.fail("unexpected exception: " + unexpected); } finally { log.debug("testDatabaseDateRoundTrip - DONE"); } } private long getContentLength(Node node) { String str = node.getPropertyValue(VOS.PROPERTY_URI_CONTENTLENGTH); if (str != null) return Long.parseLong(str); return 0; } private LinkNode getCommonLinkNode(String path, List<NodeProperty> properties) throws Exception { LinkNode linkNode = getCommonLinkNode(path); linkNode.getProperties().addAll(properties); return linkNode; } private LinkNode getCommonLinkNode(String path) throws Exception { VOSURI vosuri = new VOSURI(new URI("vos", VOS_AUTHORITY, path, null, null)); URI link = new URI("/" + HOME_CONTAINER + "/linkResource"); LinkNode linkNode = new LinkNode(vosuri, link); return linkNode; } private DataNode getCommonDataNode(String path, List<NodeProperty> properties) throws Exception { DataNode dataNode = getCommonDataNode(path); dataNode.getProperties().addAll(properties); return dataNode; } private DataNode getCommonDataNode(String path) throws Exception { VOSURI vosuri = new VOSURI(new URI("vos", VOS_AUTHORITY, path, null, null)); DataNode dataNode = new DataNode(vosuri); //dataNode.getProperties().add(new NodeProperty(VOS.PROPERTY_URI_CREATOR, NODE_OWNER)); return dataNode; } private ContainerNode getCommonContainerNode(String path, List<NodeProperty> properties) throws Exception { ContainerNode containerNode = getCommonContainerNode(path); containerNode.getProperties().addAll(properties); return containerNode; } private ContainerNode getCommonContainerNode(String path) throws Exception { VOSURI vosuri = new VOSURI(new URI("vos", VOS_AUTHORITY, path, null, null)); ContainerNode containerNode = new ContainerNode(vosuri); return containerNode; } private List<NodeProperty> getCommonProperties() { List<NodeProperty> properties = new ArrayList<NodeProperty>(); NodeProperty prop1 = new NodeProperty("uri1", "value1"); NodeProperty prop2 = new NodeProperty("uri2", "value2"); properties.add(prop1); properties.add(prop2); return properties; } private List<NodeProperty> getDataNodeProperties() { List<NodeProperty> properties = getCommonProperties(); NodeProperty prop1 = new NodeProperty(VOS.PROPERTY_URI_TYPE, "text/plain"); NodeProperty prop2 = new NodeProperty(VOS.PROPERTY_URI_CONTENTENCODING, "gzip"); properties.add(prop1); properties.add(prop2); return properties; } private List<NodeProperty> getLinkNodeProperties() { List<NodeProperty> properties = getCommonProperties(); NodeProperty prop1 = new NodeProperty(VOS.PROPERTY_URI_DESCRIPTION, "Linked resource"); NodeProperty prop2 = new NodeProperty(VOS.PROPERTY_URI_CONTENTENCODING, "gzip"); properties.add(prop1); properties.add(prop2); return properties; } private void compareNodes(String assertName, Node a, Node b) { Assert.assertNotNull(b); Assert.assertEquals(assertName + "URI", a.getUri(), b.getUri()); Assert.assertEquals(assertName + "type", a.getClass().getName(), b.getClass().getName()); Assert.assertEquals(assertName + "name", a.getName(), b.getName()); Subject subject = ((NodeID) b.appData).getOwner(); Assert.assertNotNull(assertName + " owner", owner); Principal xp = null; for (Principal p : subject.getPrincipals()) { if (p instanceof X500Principal) { xp = p; break; } } Assert.assertNotNull(xp); Assert.assertTrue("caller==owner", AuthenticationUtil.equals(principal, xp)); } private void compareProperties(String assertName, List<NodeProperty> expected, List<NodeProperty> actual) { for (NodeProperty np : expected) log.debug(assertName + ".expected: " + np); for (NodeProperty np : actual) log.debug(assertName + ".actual: " + np); for (NodeProperty e : expected) { int found = 0; for (NodeProperty a : actual) { if (e.getPropertyURI().equals(a.getPropertyURI())) { if (isDN(e.getPropertyURI())) Assert.assertTrue(AuthenticationUtil.equals(new X500Principal(e.getPropertyValue()), new X500Principal(a.getPropertyValue()))); else if (isDate(e.getPropertyURI())) // TODO: some sort of sensible comparison? Assert.assertNotNull("date prop", a.getPropertyValue()); else Assert.assertEquals(e.getPropertyURI(), e.getPropertyValue(), a.getPropertyValue()); found++; } } Assert.assertEquals(assertName + ": " + e.getPropertyURI() + "=" + e.getPropertyValue(), 1, found); } // look for duplicates in actual for (NodeProperty a1 : actual) { int found = 0; for (NodeProperty a2 : actual) if (a1.getPropertyURI().equals(a2.getPropertyURI())) found++; Assert.assertEquals(assertName + " duplciates: " + a1.getPropertyURI(), 1, found); } } private boolean isDate(String uri) { if (VOS.PROPERTY_URI_DATE.equals(uri)) return true; return false; } private boolean isDN(String uri) { if (VOS.PROPERTY_URI_CREATOR.equals(uri)) return true; return false; } }