jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r155927 [1/2] - in incubator/jackrabbit/trunk: applications/test/ applications/test/repository/nodetypes/ src/java/org/apache/jackrabbit/core/util/ src/test/org/apache/jackrabbit/test/ src/test/org/apache/jackrabbit/test/api/
Date Wed, 02 Mar 2005 16:32:29 GMT
Author: mreutegg
Date: Wed Mar  2 08:32:25 2005
New Revision: 155927

URL: http://svn.apache.org/viewcvs?view=rev&rev=155927
Log:
Adding level 2 test cases for Node and Session interface.

Added:
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeOrderableChildNodesTest.java   (with props)
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeTest.java   (with props)
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeUUIDTest.java   (with props)
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SessionTest.java   (with props)
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/SessionUUIDTest.java   (with props)
Modified:
    incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml
    incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ISO9075.java
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java
    incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/TestAll.java

Modified: incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml?view=diff&r1=155926&r2=155927
==============================================================================
--- incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml (original)
+++ incubator/jackrabbit/trunk/applications/test/repository/nodetypes/custom_nodetypes.xml Wed Mar  2 08:32:25 2005
@@ -66,5 +66,14 @@
       </requiredPrimaryTypes>
     </childNodeDef>
   </nodeType>
+  
+  <!-- Defines a referenceable nodetype for testing purposes -->
+  <nodeType name="test:refTargetNode" mixin="false" orderableChildNodes="false" primaryItemName="">
+    <supertypes>
+      <supertype>mix:versionable</supertype>
+      <supertype>nt:base</supertype>
+    </supertypes>
+    <propertyDef name="*" requiredType="undefined" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" multiple="false"/>
+  </nodeType>
 </nodeTypes>
 

Modified: incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties?view=diff&r1=155926&r2=155927
==============================================================================
--- incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties (original)
+++ incubator/jackrabbit/trunk/applications/test/repositoryStubImpl.properties Wed Mar  2 08:32:25 2005
@@ -106,6 +106,78 @@
 # Test class: NamespaceRemappingTest
 javax.jcr.tck.NamespaceRemappingTest.testroot=/
 
+# Test class: SessionTest
+# Test method: testMoveItemExistsException
+# nodetype that does not allow same name siblings
+javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype2=nt:folder
+# valid node type that can be added as child of nodetype2
+javax.jcr.tck.SessionTest.testMoveItemExistsException.nodetype3=nt:hierarchyNode
+
+# Test class: SessionTest
+# Test method: testSaveContstraintViolationException
+# nodetype that has a property that is mandatory but not autocreated
+javax.jcr.tck.SessionTest.testSaveContstraintViolationException.nodetype2=nt:file
+
+# Test class: SessionUUIDTest
+# node type that has a property of type PropertyType.REFERENCE
+javax.jcr.tck.SessionUUIDTest.nodetype=nt:unstructured
+# name of the property that is of type PropertyType.REFERENCE
+javax.jcr.tck.SessionUUIDTest.propertyname1=foobar
+# nodetype that has nodetype mix:referenceable assigned
+javax.jcr.tck.SessionUUIDTest.nodetype2=test:refTargetNode
+
+# Test class: SessionUUIDTest
+# Test method: testSaveMovedRefNode
+# name of the property that can be modified
+javax.jcr.tck.SessionUUIDTest.testSaveMovedRefNode.propertyname1=foobar
+
+# Test class: NodeTest
+# Test method: testAddNodeItemExistsException
+# nodetype that does not allow same name siblings and allows child nodes of
+# the same type
+javax.jcr.tck.NodeTest.testAddNodeItemExistsException.nodetype=nt:folder
+
+# Test class: NodeTest
+# Test method: testRemoveMandatoryNode
+# nodetype that has a mandatory child node definition
+javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype2=nt:file
+# nodetype of the  mandatory child
+javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype3=nt:base
+# name of the mandatory node
+javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodename3=jcr:content
+
+# Test class: NodeTest
+# Test method: testSaveContstraintViolationException
+# nodetype that has a property that is mandatory but not autocreated
+javax.jcr.tck.NodeTest.testSaveContstraintViolationException.nodetype2=nt:file
+
+# Test class: NodeUUIDTest
+# node type that has a property of type PropertyType.REFERENCE
+javax.jcr.tck.NodeUUIDTest.nodetype=nt:unstructured
+# name of the property that is of type PropertyType.REFERENCE
+javax.jcr.tck.NodeUUIDTest.propertyname1=ref
+# nodetype that has nodetype mix:referenceable assigned
+javax.jcr.tck.NodeUUIDTest.nodetype2=test:refTargetNode
+
+# Test class: NodeUUIDTest
+# Test method: testSaveMovedRefNode
+# name of the property that can be modified
+javax.jcr.tck.NodeUUIDTest.testSaveMovedRefNode.propertyname1=foobar
+# nodetype that has nodetype mix:referenceable assigned
+
+# Test class: NodeOrderableChildNodesTest
+# nodetype that supports orderable child nodes
+javax.jcr.tck.NodeOrderableChildNodesTest.nodetype2=nt:unstructured
+# valid node type that can be added as child of nodetype 2
+javax.jcr.tck.NodeOrderableChildNodesTest.nodetype3=nt:unstructured
+
+# Test class: NodeOrderableChildNodesTest
+# Test method: testOrderBeforeUnsupportedRepositoryOperationException
+# nodetype that does not allow ordering of child nodes
+javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype2=nt:folder
+# valid node type that can be added as child of nodetype 2
+javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3=nt:hierarchyNode
+
 # ==============================================================================
 # JAVAX.JCR.QUERY CONFIGURATION
 # ==============================================================================

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ISO9075.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ISO9075.java?view=diff&r1=155926&r2=155927
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ISO9075.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ISO9075.java Wed Mar  2 08:32:25 2005
@@ -26,12 +26,12 @@
  * Implements the encode and decode routines as specified for XML name to SQL
  * identifier conversion in ISO 9075-14:2003.<br/>
  * If a character <code>c</code> is not valid at a certain position in an XML 1.0
- * Name it is encoded in the form: '_x' + hexValueOf(c) + '_'
- * todo or is it NCName
+ * NCName it is encoded in the form: '_x' + hexValueOf(c) + '_'
  * <p/>
  * Note that only the local part of a {@link org.apache.jackrabbit.core.QName}
  * is encoded / decoded. A URI namespace will always be valid and does not
  * need encoding.
+ * todo change implementation to latest spec. only encode _x when followed by XXXX_
  */
 public class ISO9075 {
 

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java?view=diff&r1=155926&r2=155927
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java (original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractJCRTest.java Wed Mar  2 08:32:25 2005
@@ -25,6 +25,9 @@
 import javax.jcr.NamespaceException;
 import javax.jcr.RangeIterator;
 import java.util.StringTokenizer;
+import java.util.Random;
+import java.util.List;
+import java.util.Arrays;
 
 /**
  * Abstract base class for all JCR test classes.
@@ -92,6 +95,11 @@
     protected String jcrlockIsDeep;
 
     /**
+     * JCR Name jcr:mergeFailed using the namespace resolver of the current session.
+     */
+    protected String jcrMergeFailed;
+
+    /**
      * JCR Name nt:base using the namespace resolver of the current session.
      */
     protected String ntBase;
@@ -231,6 +239,7 @@
         jcrUUID = superuser.getNamespacePrefix(NS_JCR_URI) + ":uuid";
         jcrLockOwner = superuser.getNamespacePrefix(NS_JCR_URI) + ":lockOwner";
         jcrlockIsDeep = superuser.getNamespacePrefix(NS_JCR_URI) + ":lockIsDeep";
+        jcrMergeFailed = superuser.getNamespacePrefix(NS_JCR_URI) + ":mergeFailed";
         ntBase = superuser.getNamespacePrefix(NS_NT_URI) + ":base";
         mixReferenceable = superuser.getNamespacePrefix(NS_MIX_URI) + ":referenceable";
         mixVersionable = superuser.getNamespacePrefix(NS_MIX_URI) + ":versionable";
@@ -364,6 +373,41 @@
             size++;
         }
         return size;
+    }
+
+    /**
+     * Returns the name of a workspace that is not accessible from
+     * <code>session</code>.
+     * @param session the session.
+     * @return name of a non existing workspace.
+     * @throws RepositoryException if an error occurs.
+     */
+    protected String getNonExistingWorkspaceName(Session session) throws RepositoryException {
+        List names = Arrays.asList(session.getWorkspace().getAccessibleWorkspaceNames());
+        String nonExisting = null;
+        while (nonExisting == null) {
+            String name = createRandomString(10);
+            if (!names.contains(name)) {
+                nonExisting = name;
+            }
+        }
+        return nonExisting;
+    }
+
+    /**
+     * Creates a <code>String</code> with a random sequence of characters
+     * using 'a' - 'z'.
+     * @param numChars number of characters.
+     * @return the generated String.
+     */
+    protected String createRandomString(int numChars) {
+        Random rand = new Random(System.currentTimeMillis());
+        StringBuffer tmp = new StringBuffer(numChars);
+        for (int i = 0; i < numChars; i++) {
+            char c = (char) (rand.nextInt(('z' + 1) - 'a') + 'a');
+            tmp.append(c);
+        }
+        return tmp.toString();
     }
 
 }

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeOrderableChildNodesTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeOrderableChildNodesTest.java?view=auto&rev=155927
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeOrderableChildNodesTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeOrderableChildNodesTest.java Wed Mar  2 08:32:25 2005
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.Node;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>NodeOrderableChildNodesTest</code> contains all node writing tests (LEVEL 2) that require a node
+ * that allows child node ordering (tests therefore are optional).
+ * <p/>
+ * If the repository does not support a node type with orderable child nodes
+ * a {@link NotExecutableException} exception is thrown.
+ * <p/>
+ * Prerequisites:
+ * <ul>
+ * <li><code>javax.jcr.tck.NodeOrderableChildNodesTest.nodetype2</code>Name of a
+ * valid node type that allows orderable child nodes</li>
+ * <li><code>javax.jcr.tck.NodeOrderableChildNodesTest.nodetype3</code>Name of a
+ * valid node type that can be added as child node</li>
+ * </ul>
+ *
+ * @test
+ * @sources NodeOrderableChildNodesTest.java
+ * @executeClass org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest
+ * @keywords level2
+ */
+public class NodeOrderableChildNodesTest extends AbstractJCRTest {
+
+    /**
+     * A child Node of {@link #parentNode}.
+     */
+    private Node initialFirstNode;
+
+    /**
+     * A child Node of {@link #parentNode}.
+     */
+    private Node initialSecondNode;
+
+    /**
+     * The node that allows orderable child nodes
+     */
+    private Node parentNode;
+
+    /**
+     * Tries to reorder child nodes using {@link Node#orderBefore(String, String)}
+     * with an invalid destination reference. <br/><br/> This should
+     * throw an {@link ItemNotFoundException}.
+     */
+    public void testOrderBeforeInvalidDest()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+
+        // ok lets try to reorder
+        try {
+            parentNode.orderBefore(initialSecondNode.getName(), "invalid");
+            fail("Trying to reorder child nodes using Node.orderBefore() where destination is invalid" +
+                    " should throw ItemNotFoundException!");
+        } catch (ItemNotFoundException e) {
+            // ok
+        }
+    }
+
+    /**
+     * Tries to reorder child nodes using {@link Node#orderBefore(String,
+            * String)}  with an invalid source reference. <br/><br/> This should throw
+     * an {@link ItemNotFoundException}.
+     */
+    public void testOrderBeforeInvalidSrc()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+
+        // ok lets try to reorder
+        try {
+            parentNode.orderBefore("invalid", initialFirstNode.getName());
+            fail("Trying to reorder child nodes using Node.orderBefore() where source is invalid " +
+                    "should throw ItemNotFoundException!");
+        } catch (ItemNotFoundException e) {
+            // ok
+        }
+    }
+
+    /**
+     * Tries to reorder child nodes using {@link Node#orderBefore(String,
+            * String)}  using same source and destination reference. <br/><br/> This
+     * should throw an {@link ConstraintViolationException}.
+     */
+    public void testOrderBeforeConstraintViolationException()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+        // ok lets try to reorder
+        try {
+            parentNode.orderBefore(initialFirstNode.getName(), initialFirstNode.getName());
+            fail("Trying to reorder child nodes using Node.orderBefore() where source and target are same " +
+                    "hould throw ConstraintViolationException!");
+        } catch (ConstraintViolationException e) {
+            // ok
+        }
+    }
+
+    /**
+     * Tries to reorder on a node using {@link Node#orderBefore(String, String)}
+     * that does not support child reordering. <br/><br/> This should throw and
+     * {@link UnsupportedRepositoryOperationException}. Prequisites: <ul>
+     * <li>javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype2</li>
+     * A valid node type that does not suport child node ordering.</li>
+     * <li>javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3</li>
+     * A valid node type that can be added as a child. </ul>
+     */
+    public void testOrderBeforeUnsupportedRepositoryOperationException()
+            throws RepositoryException, NotExecutableException {
+        prepareTest();
+
+        // ok lets try to reorder
+        try {
+            parentNode.orderBefore(initialSecondNode.getName(), initialFirstNode.getName());
+            fail("Trying to reorder child nodes using Node.orderBefore() on node that " +
+                    "does not support ordering should throw UnsupportedRepositoryException!");
+        } catch (UnsupportedRepositoryOperationException e) {
+            // ok
+        }
+    }
+
+
+    /**
+     * Creates two child nodes, reorders first node to end, uses parentNode's
+     * {@link Node#save()}.
+     */
+    public void testOrderBeforePlaceAtEndParentSave()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+
+        // ok lets reorder and save
+        parentNode.orderBefore(initialFirstNode.getName(), null);
+        parentNode.save();
+
+        // get child node refs
+        NodeIterator it = parentNode.getNodes();
+        Node firstNode = it.nextNode();
+        Node secondNode = it.nextNode();
+
+        // lets see if reordering worked
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", firstNode.isSame(initialSecondNode));
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", secondNode.isSame(initialFirstNode));
+    }
+
+    /**
+     * Test Creates two child nodes, verifies that they are added propery.
+     * reorders first node to the end , checks again. uses session.save();
+     */
+    public void testOrderBeforePlaceAtEndSessionSave()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+
+        // ok lets reorder and save
+        parentNode.orderBefore(initialFirstNode.getName(), null);
+        superuser.save();
+
+        // get child node refs
+        NodeIterator it = parentNode.getNodes();
+        Node firstNode = it.nextNode();
+        Node secondNode = it.nextNode();
+
+        // lets see if reordering worked
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", firstNode.isSame(initialSecondNode));
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", secondNode.isSame(initialFirstNode));
+    }
+
+
+    /**
+     * Creates two child nodes, reorders second node before first, uses
+     * parentNode's {@link Node#save()}.
+     */
+    public void testOrderBeforeSecondToFirstParentSave()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+
+        // ok lets reorder and save
+        parentNode.orderBefore(initialSecondNode.getName(), initialFirstNode.getName());
+        parentNode.save();
+
+        // get child node refs
+        NodeIterator it = parentNode.getNodes();
+        Node firstNode = it.nextNode();
+        Node secondNode = it.nextNode();
+
+        // lets see if reordering worked
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", firstNode.isSame(initialSecondNode));
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", secondNode.isSame(initialFirstNode));
+    }
+
+    /**
+     * Creates two child nodes than reorders second node before first, saves
+     * using {@link Session#save()}.
+     */
+    public void testOrderBeforeSecondToFirstSessionSave()
+            throws RepositoryException, NotExecutableException {
+        checkOrderableNodeType(getProperty("nodetype2"));
+        prepareTest();
+
+        // ok lets reorder and save
+        parentNode.orderBefore(initialSecondNode.getName(), initialFirstNode.getName());
+        superuser.save();
+
+        // get child node refs
+        NodeIterator it = parentNode.getNodes();
+        Node firstNode = it.nextNode();
+        Node secondNode = it.nextNode();
+
+        // lets see if reordering worked
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", firstNode.isSame(initialSecondNode));
+        assertTrue("Child nodes are not added in proper order after Node.orderBefore()!", secondNode.isSame(initialFirstNode));
+    }
+
+    /**
+     * Sets up the test content needed for the test cases.
+     */
+    private void prepareTest() throws RepositoryException {
+        // get root node
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+        // create testNode
+        parentNode = defaultRootNode.addNode(nodeName1, getProperty("nodetype2"));
+        // add child node
+        Node firstNode = parentNode.addNode(nodeName2, getProperty("nodetype3"));
+        // add a second child node
+        Node secondNode = parentNode.addNode(nodeName3, getProperty("nodetype3"));
+        // save the new nodes
+        superuser.save();
+
+        // get child node refs
+        NodeIterator it = parentNode.getNodes();
+        initialFirstNode = it.nextNode();
+        initialSecondNode = it.nextNode();
+
+        // first lets test if the nodes have been added in the right order
+        assertTrue("Child nodes are not added in proper order ", firstNode.isSame(initialFirstNode));
+        assertTrue("Child nodes are not added in proper order ", secondNode.isSame(initialSecondNode));
+    }
+
+    /**
+     * Checks if the NodeType with name <code>ntName</code> supports orderable
+     * child nodes. If not a {@link NotExecutableException} is thrown.
+     * @param ntName the name of the node type.
+     */
+    private void checkOrderableNodeType(String ntName)
+            throws RepositoryException, NotExecutableException {
+        NodeType nt = superuser.getWorkspace().getNodeTypeManager().getNodeType(ntName);
+        if (!nt.hasOrderableChildNodes()) {
+            throw new NotExecutableException("NodeType: " + ntName + " does not support orderable child nodes.");
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeOrderableChildNodesTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeTest.java?view=auto&rev=155927
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeTest.java Wed Mar  2 08:32:25 2005
@@ -0,0 +1,972 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.Session;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.PathNotFoundException;
+import java.util.StringTokenizer;
+
+/**
+ * <code>NodeTest</code> contains all test cases for the
+ * <code>javax.jcr.Node</code> that are related to writing, modifing or deleting
+ * nodes (level 2 of the specification).
+ *
+ * @test
+ * @sources NodeTest.java
+ * @executeClass org.apache.jackrabbit.test.api.NodeTest
+ * @keywords level2
+ */
+public class NodeTest extends AbstractJCRTest {
+
+    private Session superuserW2;
+
+    /**
+     * to be able to test the update(String) and getCorrespondingNodePath(String)
+     * methods we need an addtional workspace
+     */
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // login to second workspace
+        superuserW2 = helper.getSuperuserSession(workspaceName);
+        // create the test root node
+        Node root = superuserW2.getRootNode();
+        if (root.hasNode(testPath)) {
+            // clean test root
+            Node testNode = root.getNode(testPath);
+            for (NodeIterator children = testNode.getNodes(); children.hasNext();) {
+                children.nextNode().remove();
+            }
+        } else {
+            StringTokenizer names = new StringTokenizer(testPath, "/");
+            Node currentNode = superuserW2.getRootNode();
+            while (names.hasMoreTokens()) {
+                currentNode = currentNode.addNode(names.nextToken(), testNodeType);
+            }
+        }
+        superuserW2.save();
+    }
+
+    /**
+     * remove all nodes in second workspace and log out
+     */
+    public void tearDown() throws Exception {
+        try {
+            // delete all children of test root node
+            Node rootNodeW2 = (Node) superuserW2.getItem(testRootNode.getPath());
+            for (NodeIterator children = rootNodeW2.getNodes(); children.hasNext();) {
+                children.nextNode().remove();
+            }
+            // save changes
+            superuserW2.save();
+            // log out
+            superuserW2.logout();
+        } catch (RepositoryException e) {
+            log.println("Exception in tearDown: " + e.toString());
+        }
+
+        super.tearDown();
+    }
+
+
+    /**
+     * Calls {@link javax.jcr.Node#getCorrespondingNodePath(String )} with a non
+     * existing workspace. <br/><br/> This should throw an {@link
+     * javax.jcr.NoSuchWorkspaceException }.
+     */
+    public void testGetCorrespondingNodePathNoSuchWorkspaceException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create testNode in default workspace
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save changes
+        superuser.save();
+
+        try {
+            defaultTestNode.getCorrespondingNodePath(getNonExistingWorkspaceName(superuser));
+            fail("Calling Node.getCorrespondingNodePath(workspace) with invalid workspace should throw NoSuchWorkspaceException");
+        } catch (NoSuchWorkspaceException e) {
+            // ok, works as expected
+        }
+    }
+
+
+    /**
+     * Calls {@link javax.jcr.Node#getCorrespondingNodePath(String)} on  a node
+     * that has no corresponding node in second workspace
+     */
+    public void testGetCorrespondingNodePathItemNotFoundException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create testNode in default workspace
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save changes
+        superuser.save();
+
+        try {
+            // call the update method on test node in default workspace
+            defaultTestNode.getCorrespondingNodePath(workspaceName);
+            fail("Calling Node.getCorrespondingNodePath() on node that has no correspondend node should throw ItemNotFoundException");
+        } catch (ItemNotFoundException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Creates a node with same path in both workspaces to check if {@link
+     * javax.jcr.Node#getCorrespondingNodePath(String)} works properly.
+     */
+    public void testGetCorrespondingNodePath() throws RepositoryException {
+
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create test node in default workspace
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save changes
+        superuser.save();
+
+        // get the root node in the second workspace
+        Node rootNodeW2 = (Node) superuserW2.getItem(testRootNode.getPath());
+
+        // create test node in second workspace
+        rootNodeW2.addNode(nodeName1, testNodeType);
+
+        // save changes
+        superuserW2.save();
+
+        // call the update method on test node in default workspace
+        defaultTestNode.getCorrespondingNodePath(workspaceName);
+
+        // ok, works as expected
+    }
+
+    /**
+     * Tries calling {@link javax.jcr.Node#update(String)} after node has
+     * changed in first workspace but not been saved yet. <br/><br/> This should
+     * throw and {@link javax.jcr.InvalidItemStateException}. <br/><br/>
+     * Prerequisites: <ul> <li><code>javax.jcr.tck.propertyname1</code> name of
+     * a String property that can be modified in <code>javax.jcr.tck.nodetype</code>
+     * for testing</li> </ul>
+     */
+    public void testUpdateInvalidItemStateException() throws RepositoryException {
+
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a test node in default workspace
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save changes
+        superuser.save();
+
+        // get the root node in the second workspace
+        Node rootNodeW2 = (Node) superuserW2.getItem(testRootNode.getPath());
+
+        // create test node in second workspace
+        rootNodeW2.addNode(nodeName1);
+
+        // save changes
+        superuserW2.save();
+
+        // modify the node
+        testNode.setProperty(propertyName1, "test");
+
+        try {
+            // try calling update
+            testNode.update(workspaceName);
+            fail("Calling Node.update() on modified node should throw InvalidItemStateException");
+        } catch (InvalidItemStateException e) {
+            // ok , works as expected
+        }
+    }
+
+    /**
+     * Tries to use {@link javax.jcr.Node#update(String)} with an invalid
+     * workspace. <br/><br/> This should throw an {@link
+     * javax.jcr.NoSuchWorkspaceException}.
+     */
+    public void testUpdateNoSuchWorkspaceException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a test node in default workspace
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save changes
+        superuser.save();
+
+        try {
+            testNode.update(getNonExistingWorkspaceName(superuser));
+            fail("Calling Node.update() on a non existing workspace should throw NoSuchWorkspaceException");
+        } catch (NoSuchWorkspaceException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Calls {@link javax.jcr.Node#update(String)} for a node that only exists
+     * in current workspace. <br><br> In that case nothing should happen.
+     * <br/><br/>Prerequisites: <ul> <li><code>javax.jcr.tck.propertyname1</code>
+     * name of a String property that can be modified in
+     * <code>javax.jcr.tck.nodetype</code> for testing</li> </ul>
+     */
+    public void testUpdateNoClone() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a test node in default workspace
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // modify the node
+        testNode.setProperty(propertyName1, "test");
+
+        superuser.save();
+
+        // call the update method on test node in default workspace
+        testNode.update(workspaceName);
+
+        // check if property is still there
+        assertTrue("Node got property removed after Node.update() eventhough node has no clone", testNode.hasProperty(propertyName1));
+        // check if node did not get childs suddenly
+        assertFalse("Node has children assigned after Node.update() eventhough node has no clone", testNode.hasNodes());
+    }
+
+
+    /**
+     * Checks if {@link javax.jcr.Node#update(String)} works properly by
+     * creating the same node in two workspaces one with a child node the other
+     * with a property set. <br/><br/> Calling <code>update()</code> on the node
+     * with properties, should remove the properties and add the child node.
+     * <br/><br/>Prerequisites: <ul> <li><code>javax.jcr.tck.nodetype</code>
+     * must allow children of same nodetype. <li><code>javax.jcr.tck.propertyname1</code>
+     * name of a String property that can be modified in
+     * <code>javax.jcr.tck.nodetype</code> for testing</li> </ul>
+     */
+    public void testUpdate() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create test node in default workspace
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        defaultTestNode.setProperty(propertyName1, "test");
+
+        // save changes
+        superuser.save();
+
+        // get the root node in the second workspace
+        Node rootNodeW2 = (Node) superuserW2.getItem(testRootNode.getPath());
+
+        // create test node in second workspace
+        Node testNodeW2 = rootNodeW2.addNode(nodeName1, testNodeType);
+
+        // add a child node
+        testNodeW2.addNode(nodeName2, testNodeType);
+
+        // save changes
+        superuserW2.save();
+
+        // call the update method on test node in default workspace
+        defaultTestNode.update(workspaceName);
+
+        // ok first check if node has no longer propertis
+        assertFalse("Node updated with Node.update() should have property removed", defaultTestNode.hasProperty(propertyName1));
+        // ok check if the child has been added
+        assertTrue("Node updated with Node.update() should have received childrens", defaultTestNode.hasNode(nodeName1));
+    }
+
+    /**
+     * Tries to add a node using {@link javax.jcr.Node#addNode(String)} where
+     * node type can not be determined by parent (<code>nt:base</code> is used
+     * as parent nodetype). <br/><br/> This should throw a {@link
+     * javax.jcr.nodetype.ConstraintViolationException}.
+     */
+    public void testAddNodeConstraintViolationExceptionUndefinedNodeType() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, ntBase);
+
+        try {
+            defaultTestNode.addNode(nodeName2);
+            fail("Adding a node with node.addNode(node) where nodetype can not be determined from parent should" +
+                    " throw ConstraintViolationException");
+        } catch (ConstraintViolationException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Tries to add a node using {@link javax.jcr.Node#addNode(String)} as a
+     * child of a property.<br/> <br/> This should throw an {@link
+     * javax.jcr.nodetype.ConstraintViolationException}.
+     * <br/><br/>Prerequisites: <ul> <li><code>javax.jcr.tck.propertyname1</code>
+     * name of a String property that can be set in <code>javax.jcr.tck.nodetype</code>
+     * for testing</li> </ul>
+     */
+    public void testAddNodeConstraintViolationExceptionProperty() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // add a node
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // set a property
+        defaultTestNode.setProperty(propertyName1, "test");
+
+        try {
+            // try to add a node as a child of a property
+            defaultTestNode.addNode(propertyName1 + "/" + nodeName2);
+            fail("Adding a node as a child of a property should throw ConstraintViolationException");
+        } catch (ConstraintViolationException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Tries to create a node using {@link javax.jcr.Node#addNode(String,
+            * String)}  at a location where there is already a node with same name and
+     * the parent does not allow same name siblings. <br/><br/> This should
+     * throw an {@link javax.jcr.ItemExistsException }. <br/><br> Prerequisites:
+     * <ul> <li><code>javax.jcr.tck.NodeTest.testAddNodeItemExistsException.nodetype<code>
+     * node type that does not allow same name siblings and allows to add child
+     * nodes of the same type.</li> </ul>
+     */
+    public void testAddNodeItemExistsException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // add a node
+        Node defaultTestNode = defaultRootNode.addNode(nodeName2, testNodeType);
+        // add a child
+        defaultTestNode.addNode(nodeName3, testNodeType);
+
+        // save the new node
+        defaultRootNode.save();
+
+        try {
+            // try to add a node with same name again
+            defaultTestNode.addNode(nodeName3, testNodeType);
+            fail("Adding a node to a location where same name siblings are not allowed, but a node with same name" +
+                    " already exists should throw ItemExistsException ");
+        } catch (ItemExistsException e) {
+            //ok, works as expected
+        }
+    }
+
+    /**
+     * Tries to add a node using {@link javax.jcr.Node#addNode(String)} to a non
+     * existing destination node. <br/><br/> This should throw an {@link
+     * javax.jcr.PathNotFoundException}.
+     */
+    public void testAddNodePathNotFoundException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        try {
+            // use invalid parent path
+            defaultRootNode.addNode(nodeName1 + "/" + nodeName2);
+            fail("Creating a node at a non existent destination should throw PathNotFoundException");
+        } catch (PathNotFoundException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Adds a new node using {@link javax.jcr.Node#addNode(String)} with an
+     * index for the new name. <br/><br/> This should throw an {@link
+     * RepositoryException}.
+     */
+    public void testAddNodeRepositoryExceptionRelPathIndex() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        try {
+            // use invalid relPath
+            defaultRootNode.addNode(nodeName1 + "[1]", testNodeType);
+            fail("Creating a node with index as postfix for new name should throw RepositoryException");
+        } catch (RepositoryException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Creates a new node using {@link Node#addNode(String)}, then tries to call
+     * {@link javax.jcr.Node#save()} on the newly node. <br/><br/> This should
+     * throw an {@link RepositoryException}.
+     */
+    public void testAddNodeRepositoryExceptionSaveOnNewNode() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // add a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        try {
+            // try to call save on newly created node
+            testNode.save();
+            fail("Calling Node.save() on a newly created node should throw RepositoryException");
+        } catch (RepositoryException e) {
+            // ok, works as expected.
+        }
+    }
+
+    /**
+     * Creates a new node using {@link Node#addNode(String)} , saves using
+     * {@link javax.jcr.Node#save()} on parent node. Uses a second session to
+     * verify if the node has been safed.
+     */
+    public void testAddNodeParentSave() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // add a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save new nodes
+        defaultRootNode.save();
+
+        // use a different session to verify if the node is there
+        Session session = helper.getReadOnlySession();
+        try {
+            testNode = (Node) session.getItem(testNode.getPath());
+        } finally {
+            session.logout();
+        }
+    }
+
+    /**
+     * Creates a new node using {@link Node#addNode(String)} , saves using
+     * {@link javax.jcr.Session#save()}. Uses a second session to verify if the
+     * node has been safed.
+     */
+    public void testAddNodeSessionSave() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // add a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save new nodes
+        superuser.save();
+
+        // use a different session to verify if the node is there
+        Session session = helper.getReadOnlySession();
+        try {
+            testNode = (Node) session.getItem(testNode.getPath());
+        } finally {
+            session.logout();
+        }
+    }
+
+    /**
+     * Creates a node with a mandatory child node using {@link
+     * Node#addNode(String, String)}, saves on parent node then tries to delete
+     * the mandatory child node. <br/><br/> This should throw a {@link
+     * ConstraintViolationException}. <br/><br/>Prerequisites: <ul>
+     * <li><code>javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype2</code>
+     * a node type that has a mandatory child node</li> <li><code>javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodetype3</code>
+     * nodetype of the mandatory child node</li> <li><code>javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodename3</code>
+     * name of the mandatory child node</li> </ul>
+     */
+    public void testRemoveMandatoryNode() throws RepositoryException {
+
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create the node with the mandatory child node definition
+        Node defaultTestNode = defaultRootNode.addNode(nodeName2, getProperty("nodetype2"));
+
+        // add the mandatory child node
+        Node defaultTestNodeChild = defaultTestNode.addNode(nodeName3, getProperty("nodetype3"));
+
+        // save changes
+        defaultRootNode.save();
+
+        try {
+            // try to remove the mandatory node
+            defaultTestNodeChild.remove();
+
+            defaultTestNode.save();
+            fail("Removing a mandatory node should throw a ConstraintViolationException");
+        } catch (ConstraintViolationException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Removes a node using {@link javax.jcr.Node#remove()} with session 1,
+     * afterwards it tries the same with session 2. <br/><br/> This should throw
+     * an {@link InvalidItemStateException}.
+     */
+    public void testRemoveInvalidItemStateException() throws RepositoryException {
+
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create the node
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save the nodes
+        superuser.save();
+
+        // get the node with session 2
+        Session testSession = helper.getReadWriteSession();
+        Node defaultTestNodeSession2 = (Node) testSession.getItem(defaultTestNode.getPath());
+
+        // remove node with session 1
+        defaultTestNode.remove();
+        superuser.save();
+
+        // try to remove already deleted node with session 2
+        try {
+            defaultTestNodeSession2.remove();
+            fail("Removing a node already deleted by other session should throw an InvalidItemStateException!");
+        } catch (InvalidItemStateException e) {
+            //ok, works as expected
+        }
+        testSession.logout();
+    }
+
+    /**
+     * Removes a node using {@link javax.jcr.Node#remove()}, then saves with
+     * parent's nodes {@link javax.jcr.Node#save()} method.
+     */
+    public void testRemoveNodeParentSave() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create the node
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save the nodes
+        defaultRootNode.save();
+
+        // remove them
+        defaultTestNode.remove();
+
+        defaultRootNode.save();
+
+        // check if the node has been properly removed
+        try {
+            defaultRootNode.getNode(nodeName1);
+            fail("Permanently removed node should no longer be adressable using Parent Node's getNode() method");
+        } catch (PathNotFoundException e) {
+            // ok , works as expected
+        }
+    }
+
+
+    /**
+     * Removes a node using {@link javax.jcr.Node#remove()}, then saves using
+     * {@link javax.jcr.Session#save()} method.
+     */
+    public void testRemoveNodeSessionSave() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create the node
+        Node defaultTestNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save the nodes
+        superuser.save();
+
+        // remove them
+        defaultTestNode.remove();
+
+        superuser.save();
+
+        // check if the node has been properly removed
+        try {
+            superuser.getItem(defaultRootNode.getPath() + "/" + nodeName1);
+            fail("Permanently removed node should no longer be adressable using Session.getItem()");
+        } catch (PathNotFoundException e) {
+            // ok, works as expected
+        }
+    }
+
+
+    /**
+     * Tests object identity, meaning two nodes objects accuired through the
+     * same session must have the same properties and states. <br/><br/>
+     * Prerequisites: <ul> <li><code>javax.jcr.tck.nodetype</code> must allow
+     * children of same node type</li> <li><code>javax.jcr.tck.propertyname1</code>
+     * name of a String property that can be set in <code>javax.jcr.tck.nodetype</code>
+     * for testing</li> </ul>
+     */
+    public void testNodeIdentity() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode1 = defaultRootNode.addNode(nodeName1, testNodeType);
+        // add a child node
+        testNode1.addNode(nodeName1, testNodeType);
+        // add a property
+        testNode1.setProperty(propertyName1, "test");
+
+        // save the new node
+        defaultRootNode.save();
+
+        // accuire the same node with session 2
+        Node testNode2 = (Node) superuser.getItem(testNode1.getPath());
+
+        // check if they have the same property
+        assertEquals("Two references of same node have different properties", testNode1.getProperty(propertyName1), testNode2.getProperty(propertyName1));
+        // check if they have the same child
+        assertEquals("Two references of same node have different children", testNode1.getNode(nodeName1), testNode2.getNode(nodeName1));
+        // check state methods
+        assertEquals("Two references of same node have different State for Node.isCheckedOut()", testNode1.isCheckedOut(), testNode2.isCheckedOut());
+        assertEquals("Two references of same node have different State for Node.isLocked()", testNode1.isLocked(), testNode2.isLocked());
+        assertEquals("Two references of same node have different State for Node.isModified()", testNode1.isModified(), testNode2.isModified());
+        assertEquals("Two references of same node have different State for Node.isNew()", testNode1.isNew(), testNode2.isNew());
+        assertEquals("Two references of same node have different State for Node.isNode()", testNode1.isNode(), testNode2.isNode());
+        assertEquals("Two references of same node have different State for Node.isNodeType()", testNode1.isNodeType(testNodeType), testNode2.isNodeType(testNodeType));
+        assertTrue("Two references of same node should return true for Node1.isSame(Node2)", testNode1.isSame(testNode2));
+        assertEquals("Two references of same node have different Definitions", testNode1.getDefinition(), testNode2.getDefinition());
+    }
+
+    /**
+     * Checks if {@link Node#isModified()} works correcty for unmodified and
+     * modified nodes.
+     */
+    public void testIsModified() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        defaultRootNode.save();
+
+        assertFalse("Unmodified node should return false on Node.isModified()", testNode.isModified());
+
+        // check if modified properties are recognised
+        testNode.setProperty(propertyName1, "test");
+
+        assertTrue("Modified node should return true on Node.isModified()", testNode.isModified());
+
+        defaultRootNode.save();
+
+        // check if modified child nodes are recognised
+        testNode.addNode(nodeName2, testNodeType);
+
+        assertTrue("Modified node should return true on Node.isModified()", testNode.isModified());
+
+    }
+
+    /**
+     * Checks if {@link Node#isNew()} works correctly for new and existing,
+     * unmodified nodes.
+     */
+    public void testIsNew() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        assertTrue("Newly created node should return true on newNode.isNew()", testNode.isNew());
+
+        defaultRootNode.save();
+
+        assertFalse("Unmodified, exisiting node should return false on newNode.isNew()", testNode.isNew());
+
+    }
+
+    /**
+     * Tries to call {@link Node#refresh(boolean)}  on a deleted node.
+     * <br/><br/> This should throw an {@link InvalidItemStateException}.
+     */
+    public void testRefreshInvalidItemStateException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save the new node
+        defaultRootNode.save();
+
+        // remove the node
+        defaultRootNode.remove();
+
+        try {
+            testNode.refresh(true);
+            fail("Calling Node.refresh() on deleted node should throw InvalidItemStateException!");
+        } catch (InvalidItemStateException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Moves an unreferencable node with one session and saves the same node
+     * using a different session at same time.<br/> <br/> Procedure: <ul>
+     * <li>Creates node 1 and node 2 with session 1</li> <li>Gets reference to
+     * node 1 using session 2</li> <li>session 1 moves node 1 under node 2 ,
+     * saves using parent nodes {@link Node#save()}</li> <li>session 2 modifies
+     * node 1 by adding a child node, saves using </code>Node.save()</code></li>
+     * </ul> Should throw {@link javax.jcr.InvalidItemStateException} since
+     * saving an unreferencable node that has been moved by and other session is
+     * not possible. <br/><br/>Prerequisites: <ul> <li><code>javax.jcr.tck.nodetype</code>
+     * must accept children of same nodetype and it must not be
+     * referencable</li> </ul>
+     */
+    public void testSaveMovedNotRefNode() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create non referenciable node to be moved with session 1
+        Node testNodeSession1 = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // create a second node with session 1 that will serve as new parent
+        Node newParentNodeSession1 = defaultRootNode.addNode(nodeName2, testNodeType);
+
+        // save the new nodes
+        defaultRootNode.save();
+
+        // get the moving node with session 2
+        Session testSession = helper.getReadWriteSession();
+        Node testNodeSession2 = (Node) testSession.getItem(testNodeSession1.getPath());
+
+        //move the node with session 1
+        superuser.move(testNodeSession1.getPath(), newParentNodeSession1.getPath() + "/testNewName");
+
+        // make the move persistent with session 1
+        defaultRootNode.save();
+
+        // add a child to the node with session
+        testNodeSession2.addNode(nodeName3, testNodeType);
+
+        // save it
+        try {
+            defaultRootNode.save();
+            fail("Saving a unreferencedable Node that has been moved by other session should throw InvalidItemStateException");
+        } catch (InvalidItemStateException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Checks if {@link javax.jcr.Node#refresh(boolean refresh)} works properly
+     * with <code>refresh</code> set to <code>false</code>.<br/> <br/>
+     * Procedure: <ul> <li>Creates two nodes with session 1</li> <li>Modifies
+     * node 1 with session 1 by adding a child node</li> <li>Get node 2 with
+     * session 2</li> <li>Modifies node 2 with session 2 by adding a child
+     * node</li> <li>saves session 2 changes using {@link
+     * javax.jcr.Node#save()}</li> <li>calls <code>Node.refresh(false)</code>
+     * on root node in session 1</li> </ul> Session 1 changes should be cleared
+     * and session 2 changes should now be visible to session 1.
+     * <br/><br/>Prerequisites: <ul> <li><code>javax.jcr.tck.nodetype</code>
+     * must accept children of same nodetype</li> </ul>
+     */
+    public void testRefreshBooleanFalse() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode1Session1 = defaultRootNode.addNode(nodeName1, testNodeType);
+        // create a second node
+        Node testNode2Session1 = defaultRootNode.addNode(nodeName2, testNodeType);
+
+        // save the new nodes
+        defaultRootNode.save();
+
+        // add child node to test node 1 using session 1
+        testNode1Session1.addNode(nodeName2, testNodeType);
+
+        // get session 2
+        Session session2 = helper.getReadWriteSession();
+
+        // get the second node
+        Node testNode2Session2 = (Node) session2.getItem(testNode2Session1.getPath());
+
+        // adds a child node
+        testNode2Session2.addNode(nodeName3, testNodeType);
+
+        // save the changes
+        session2.save();
+
+        // call refresh on session 1
+        defaultRootNode.refresh(false);
+
+        // check if session 1 flag has been cleared
+        assertFalse("Session should have no pending changes recorded after Node.refresh(false)!", superuser.hasPendingChanges());
+
+        // check if added child node for node 1 by session 1 has been removed
+        assertFalse("Node Modifications have not been flushed after Node.refresh(false)", testNode1Session1.hasNodes());
+
+        // check if added child node for node 2 by session 2 has become visible in session 1
+        assertTrue("Node modified by a different session has not been updated after Node.refresh(false)", testNode2Session1.hasNodes());
+    }
+
+    /**
+     * Checks if {@link javax.jcr.Node#refresh(boolean refresh)} works properly
+     * with <code>refresh</code> set to <code>true</code>.<br/> <br/>
+     * Procedure: <ul> <li>Creates two nodes with session 1</li> <li>Modifies
+     * node 1 with session 1 by adding a child node</li> <li>Get node 2 with
+     * session 2</li> <li>Modifies node 2 with session 2 by adding a child
+     * node</li> <li>saves session 2 changes using {@link
+     * javax.jcr.Node#save()}</li> <li>calls <code>Node.refresh(true)</code> on
+     * root node in session 1</li> </ul> Session 1 changes and session 2
+     * changes now be visible to session 1. <br/><br/>Prerequisites: <ul>
+     * <li><code>javax.jcr.tck.nodetype</code> must accept children of same
+     * nodetype</li> </ul>
+     */
+    public void testRefreshBooleanTrue() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode1Session1 = defaultRootNode.addNode(nodeName1, testNodeType);
+        // create a second node
+        Node testNode2Session1 = defaultRootNode.addNode(nodeName2, testNodeType);
+
+        // save the new nodes
+        defaultRootNode.save();
+
+        // add child node to test node 1 using session 1
+        testNode1Session1.addNode(nodeName2, testNodeType);
+
+        // get session 2
+        Session session2 = helper.getReadWriteSession();
+
+        // get the second node
+        Node testNode2Session2 = (Node) session2.getItem(testNode2Session1.getPath());
+
+        // adds a child node
+        testNode2Session2.addNode(nodeName3, testNodeType);
+
+        // save the changes
+        session2.save();
+
+        // call refresh on session 1
+        defaultRootNode.refresh(true);
+
+        // check if session 1 flag has been cleared
+        assertTrue("Session should still have pending changes recorded after Node.refresh(true)!", superuser.hasPendingChanges());
+
+        // check if added child node for node 1 by session 1 is still there
+        assertTrue("Node Modifications are lost after Node.refresh(true)", testNode1Session1.hasNodes());
+
+        // check if added child node for node 2 by session 2 has become visible in session 1
+        assertTrue("Node modified by a different session has not been updated after Node.refresh(true)", testNode2Session1.hasNodes());
+    }
+
+    /**
+     * Tries to save a node using {@link javax.jcr.Node#save()} that was already
+     * deleted by an other session.<br/> <br/> Procedure: <ul> <li>Creates a new
+     * node with session 1, saves it, adds a child node.</li> <li>Access new
+     * node with session 2,deletes the node, saves it.</li> <li>Session 1 tries
+     * to save modifications using <code>Node.save()</code> on root node .</li>
+     * </ul> This should throw an {@link javax.jcr.InvalidItemStateException}.
+     * <br/><br/>Prerequisites: <ul> <li><code>javax.jcr.tck.nodetype</code>
+     * must accept children of same nodetype</li> </ul>
+     */
+    public void testSaveInvalidStateException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node nodeSession1 = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save new node
+        superuser.save();
+
+        // make a modification
+        nodeSession1.addNode(nodeName2, testNodeType);
+
+        // get the new node with a different session
+        Session testSession = helper.getReadWriteSession();
+        Node nodeSession2 = (Node) testSession.getItem(nodeSession1.getPath());
+
+        // delete the node with the new session
+        nodeSession2.remove();
+
+        // make node removal persistent
+        testSession.save();
+
+        // save changes made wit superuser session
+        try {
+            defaultRootNode.save();
+            fail("Saving a modified Node using Node.save() already deleted by an other session should throw InvalidItemStateException");
+        } catch (InvalidItemStateException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Tries to create and save a node using {@link javax.jcr.Node#save()} with
+     * an mandatory property that is not set on saving time.
+     * <p/>
+     * Prerequisites: <ul> <li><code>javax.jcr.tck.Node.testSaveContstraintViolationException.nodetype2</code>
+     * must reference a nodetype that has at least one property that is
+     * mandatory but not autocreated</li> </ul>
+     */
+    public void testSaveContstraintViolationException() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node with at least one mandatory, not autocreated property
+        defaultRootNode.addNode(nodeName1, this.getProperty("nodetype2"));
+
+        // save changes
+        try {
+            superuser.save();
+            fail("Trying to use parent Node.save() with a node that has a mandatory property not set, should throw ConstraintViolationException");
+        } catch (ConstraintViolationException e) {
+            // ok
+        }
+    }
+
+
+    /**
+     * Creates a new node, saves it uses second session to verify if node has
+     * been added.
+     */
+    public void testNodeSave() throws RepositoryException {
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node testNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // save new node
+        defaultRootNode.save();
+
+        // get the new node with a different session
+        Session testSession = helper.getReadOnlySession();
+        testSession.getItem(testNode.getPath());
+        testSession.logout();
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeUUIDTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeUUIDTest.java?view=auto&rev=155927
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeUUIDTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeUUIDTest.java Wed Mar  2 08:32:25 2005
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.test.api;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+/**
+ * <code>NodeUUIDTest</code> contains all tests for the
+ * <code>javax.jcr.Node</code> class that require a UUID (and therefore are
+ * optional). If the repository does not support the node type mix:referenceable
+ * a {@link NotExecutableException} is thrown.
+ *
+ * @test
+ * @sources NodeUUIDTest.java
+ * @executeClass org.apache.jackrabbit.test.api.NodeUUIDTest
+ * @keywords level2
+ */
+public class NodeUUIDTest extends AbstractJCRTest {
+
+    /**
+     * Tries to remove a node that is a reference target using {@link
+     * Node#save()}.<br> <br>Procedure: <ul> <li>Creates two nodes with same
+     * session</li> <li>One has a referencing property pointing to the other
+     * node</li> <li>Target node gets removed.</code></li> </ul> This should
+     * generate a {@link javax.jcr.ReferentialIntegrityException} upon save.
+     * <br><br>Prerequisites: <ul> <li><code>javax.jcr.tck.NodeUUIDTest.nodetype</code>
+     * must allow a property of type {@link javax.jcr.PropertyType#REFERENCE}</li>
+     * <li><code>javax.jcr.tck.NodeUUIDTest.propertyname1</code> name of the
+     * property of type {@link javax.jcr.PropertyType#REFERENCE}</li>
+     * <li><code>javax.jcr.tck.NodeUUIDTest.nodetype2</code> must have the mixin
+     * type <code>mix:referenceable</code> assigned.</li> </ul>
+     */
+    public void testSaveReferentialIntegrityException() throws RepositoryException, NotExecutableException {
+        checkMixReferenceable();
+
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node with a property of type PropertyType.REFERENCE
+        Node referencingNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // create a node with a jcr:uuid property to serve as target
+        Node refTargetNode = defaultRootNode.addNode(nodeName2, getProperty("nodetype2"));
+
+        // set the reference
+        referencingNode.setProperty(propertyName1, refTargetNode);
+
+        // save the new nodes
+        defaultRootNode.save();
+
+        // remove the referenced node
+        refTargetNode.remove();
+
+        // try to save
+        try {
+            defaultRootNode.save();
+            fail("Saving a deleted node using Node.save() that is a reference target should throw ReferentialIntegrityException");
+        } catch (ReferentialIntegrityException e) {
+            // ok, works as expected
+        }
+    }
+
+    /**
+     * Moves a referencable node using {@link javax.jcr.Session#move(String,
+            * String)} with one session and saves afterward changes made with a second
+     * session to the moved node using {@link Node#save()}.<br/> <br/>
+     * Procedure: <ul> <li>Creates node 1 and node 2 with session 1</li>
+     * <li>Gets reference to node 1 using session 2</li> <li>Session 1 moves
+     * node 1 under node 2, saves changes</li> <li>Session 2 modifes node 1,
+     * saves</li> </ul> This should work since the modified node is identified
+     * by its UUID, not by position in repository. <br><br>Prerequisites: <ul>
+     * <li><code>javax.jcr.tck.NodeUUIDTest.nodetype2</code> must have the mixin
+     * type <code>mix:referenceable</code> assigned.</li>
+     * <li><code>javax.jcr.tck.NodeUUIDTest.testSaveMovedRefNode.propertyname1</code>
+     * name of a property that can be modified in <code>nodetype2</code> for
+     * testing</li> </ul>
+     */
+    public void testSaveMovedRefNode() throws RepositoryException, NotExecutableException {
+        checkMixReferenceable();
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node newParentNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // create a referenceable node
+        Node refTargetNode = defaultRootNode.addNode(nodeName2, getProperty("nodetype2"));
+
+        // save the new nodes
+        superuser.save();
+
+        // get the moving node with session 2
+        Session testSession = helper.getReadWriteSession();
+        Node refTargetNodeSession2 = (Node) testSession.getItem(refTargetNode.getPath());
+
+        //move the node with session 1
+        superuser.move(refTargetNode.getPath(), newParentNode.getPath() + "/" + nodeName3);
+
+        // make the move persistent with session 1
+        superuser.save();
+
+        // modify some prop of the moved node with session 2
+        refTargetNodeSession2.setProperty(propertyName1, "test");
+
+        // save it
+        refTargetNodeSession2.save();
+        // ok, works as expected
+        testSession.logout();
+    }
+
+    /**
+     * Moves a node using {@link javax.jcr.Session#move(String, String)} and
+     * places a new <b>referenceable</b> node at the source position with same
+     * name. A second session tries to save changes made to the moved node using
+     * {@link Node#save()}. <br/> Procedure: <ul> <li>Create node 1 and node 2
+     * with session 1</li> <li>Session 2 gets a reference to node 1</li>
+     * <li>Session 1 moves node 1 under node 2 , saves</li> <li>session 1 adds
+     * new referencable node previous position of node 1</li> <li>session 2
+     * modifes node, saves</li> </ul> This should fail since the node that
+     * replaces the moved node is referencable. Should throw {@link
+     * javax.jcr.InvalidItemStateException}. <br><br>Prerequisites: <ul>
+     * <li><code>javax.jcr.tck.nodetype</code> must allow children of
+     * itself.</li> <li><code>javax.jcr.tck.propertyname1</code> name of a
+     * property that can be modified in <code>javax.jcr.tck.nodetype</code> for
+     * testing</li> <li><code>javax.jcr.tck.NodeUUIDTest.nodetype2</code> must
+     * have the mixin type <code>mix:referenceable</code> assigned.</li> </ul>
+     */
+    public void testSaveReplacedNotRefNodeByRefNode() throws RepositoryException, NotExecutableException {
+        checkMixReferenceable();
+        // get default workspace test root node using superuser session
+        Node defaultRootNode = (Node) superuser.getItem(testRootNode.getPath());
+
+        // create a node
+        Node parentNode = defaultRootNode.addNode(nodeName1, testNodeType);
+
+        // create a moving node
+        Node movingNode = defaultRootNode.addNode(nodeName2, testNodeType);
+
+        // save the new nodes
+        defaultRootNode.save();
+
+        // get the moving node with session 2
+        Session testSession = helper.getReadWriteSession();
+        Node movingNodeSession2 = (Node) testSession.getItem(movingNode.getPath());
+
+        //move the node with session 1
+        superuser.move(movingNode.getPath(), parentNode.getPath() + "/" + nodeName3);
+
+        // repace it it with a referenciable node
+        parentNode.addNode(nodeName2, getProperty("nodetype2"));
+
+        // make the move and adding of new node persistent with session 1
+        defaultRootNode.save();
+
+        // modify some prop of the moved node
+        movingNodeSession2.setProperty(propertyName1, "test");
+
+        // save it
+        try {
+            movingNodeSession2.save();
+            fail("Saving a unreferenceable Node using Node.save() that has been moved and replaced by a referenceable node in the meantime should" +
+                    " throw InvalidItemStateException");
+        } catch (InvalidItemStateException e) {
+            // ok, what's expected
+        }
+        testSession.logout();
+    }
+
+    /**
+     * Checks if the repository supports the mixin mix:Referenceable otherwise a
+     * {@link NotExecutableException} is thrown.
+     *
+     * @throws NotExecutableException if the repository does not support the
+     *                                mixin mix:referenceable.
+     */
+    private void checkMixReferenceable() throws RepositoryException, NotExecutableException {
+        try {
+            superuser.getWorkspace().getNodeTypeManager().getNodeType(mixReferenceable);
+        } catch (NoSuchNodeTypeException e) {
+            throw new NotExecutableException("Repository does not support mix:referenceable");
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/NodeUUIDTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message