You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2005/02/26 21:51:52 UTC

svn commit: r155583 [2/2] - in incubator/jackrabbit/trunk: applications/test/ src/java/org/apache/jackrabbit/core/ src/java/org/apache/jackrabbit/core/observation/ src/java/org/apache/jackrabbit/core/state/ src/java/org/apache/jackrabbit/core/version/persistence/ src/test/org/apache/jackrabbit/test/ src/test/org/apache/jackrabbit/test/api/observation/ src/test/org/apache/jackrabbit/test/api/version/

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AbstractObservationTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AbstractObservationTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AbstractObservationTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AbstractObservationTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,216 @@
+/*
+ * 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.observation;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.observation.EventListenerIterator;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * This class implements the basic {@link #setUp} and {@link #tearDown()}
+ * methods for the observation test cases.
+ */
+abstract class AbstractObservationTest extends AbstractJCRTest {
+
+    /**
+     * Default wait timeout for events: 5000 ms
+     */
+    protected static final long DEFAULT_WAIT_TIMEOUT = 5000;
+
+    /**
+     * The <code>ObservationManager</code>
+     */
+    protected ObservationManager obsMgr;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        obsMgr = superuser.getWorkspace().getObservationManager();
+    }
+
+    /**
+     * Registers an <code>EventListener</code> for all events.
+     *
+     * @param listener the <code>EventListener</code>.
+     * @throws RepositoryException if registration fails.
+     */
+    protected void addEventListener(EventListener listener) throws RepositoryException {
+        addEventListener(listener,
+                Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED);
+    }
+
+    /**
+     * Registers an <code>EventListener</code> for events of the specified
+     * type(s).
+     *
+     * @param listener  the <code>EventListener</code>.
+     * @param eventType the event types
+     * @throws RepositoryException if registration fails.
+     */
+    protected void addEventListener(EventListener listener, int eventType)
+            throws RepositoryException {
+        if (obsMgr != null) {
+            obsMgr.addEventListener(listener,
+                    eventType,
+                    superuser.getRootNode().getPath(),
+                    true,
+                    null,
+                    null,
+                    false);
+        } else {
+            throw new IllegalStateException("ObservationManager not available.");
+        }
+    }
+
+    /**
+     * Removes the <code>EventListener</code> from the ObservationManager.
+     *
+     * @param listener the <code>EventListener</code> to unregister.
+     * @throws RepositoryException if unregister fails.
+     */
+    protected void removeEventListener(EventListener listener) throws RepositoryException {
+        if (obsMgr != null) {
+            obsMgr.removeEventListener(listener);
+        } else {
+            throw new IllegalStateException("ObservationManager not available.");
+        }
+    }
+
+    /**
+     * Consumes the <code>EventListenerIterator</code> and returns the
+     * <code>EventListener</code> as an array.
+     * @param it the iterator.
+     * @return array of <code>EventListeners</code>.
+     */
+    protected EventListener[] toArray(EventListenerIterator it) {
+        List listeners = new ArrayList();
+        while (it.hasNext()) {
+            listeners.add(it.nextEventListener());
+        }
+        return (EventListener[]) listeners.toArray(new EventListener[listeners.size()]);
+    }
+
+    //--------------------< check methods >-------------------------------------
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #testRoot}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to child nodes added relative to {@link
+     *                 #testRoot}.
+     * @throws RepositoryException if an error occurs while retrieving the nodes
+     *                             from event instances.
+     */
+    protected void checkNodeAdded(Event[] events, String[] relPaths)
+            throws RepositoryException {
+        checkNodes(events, relPaths, Event.NODE_ADDED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #testRoot}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to child nodes added relative to {@link
+     *                 #testRoot}.
+     * @throws RepositoryException if an error occurs while retrieving the nodes
+     *                             from event instances.
+     */
+    protected void checkNodeRemoved(Event[] events, String[] relPaths)
+            throws RepositoryException {
+        checkNodes(events, relPaths, Event.NODE_REMOVED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #testRoot}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to added properties relative to {@link
+     *                 #testRoot}.
+     * @throws RepositoryException if an error occurs while retrieving the nodes
+     *                             from event instances.
+     */
+    protected void checkPropertyAdded(Event[] events, String[] relPaths)
+            throws RepositoryException {
+        checkNodes(events, relPaths, Event.PROPERTY_ADDED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #testRoot}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to changed properties relative to {@link
+     *                 #testRoot}.
+     * @throws RepositoryException if an error occurs while retrieving the nodes
+     *                             from event instances.
+     */
+    protected void checkPropertyChanged(Event[] events, String[] relPaths)
+            throws RepositoryException {
+        checkNodes(events, relPaths, Event.PROPERTY_CHANGED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #testRoot}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to removed properties relative to {@link
+     *                 #testRoot}.
+     * @throws RepositoryException if an error occurs while retrieving the nodes
+     *                             from event instances.
+     */
+    protected void checkPropertyRemoved(Event[] events, String[] relPaths)
+            throws RepositoryException {
+        checkNodes(events, relPaths, Event.PROPERTY_REMOVED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #testRoot}.
+     *
+     * @param events    the <code>Event</code>s.
+     * @param relPaths  paths to item events relative to {@link #testRoot}.
+     * @param eventType the type of event to check.
+     * @throws RepositoryException if an error occurs while retrieving the nodes
+     *                             from event instances.
+     */
+    private void checkNodes(Event[] events, String[] relPaths, long eventType)
+            throws RepositoryException {
+        assertEquals("Number of events wrong", relPaths.length, events.length);
+        Set paths = new HashSet();
+        for (int i = 0; i < events.length; i++) {
+            assertEquals("Wrong event type", eventType, events[i].getType());
+            String path = events[i].getPath();
+            paths.add(path);
+        }
+        for (int i = 0; i < relPaths.length; i++) {
+            String expected = testRoot + "/" + relPaths[i];
+            assertTrue("Path " + expected + " not found in events.",
+                    paths.contains(expected));
+        }
+    }
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AddEventListenerTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AddEventListenerTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AddEventListenerTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/AddEventListenerTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,184 @@
+/*
+ * 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.observation;
+
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.observation.Event;
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+
+/**
+ * Tests the options for addEventListener().
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1} and
+ * {@link #nodeName2}. Furthermore {@link #testNodeType} must allow to add
+ * child nodes of the same type ({@link #testNodeType}).
+ * <p/>
+ * Certain test require that {@link #testNodeType} is mix:referenceable or
+ * allows to add that mixin. If the repository does not support mix:referenceable
+ * a {@link org.apache.jackrabbit.test.NotExecutableException} is thrown
+ * in those test cases.
+ *
+ * @test
+ * @sources AddEventListenerTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.AddEventListenerTest
+ * @keywords observation
+ */
+public class AddEventListenerTest extends AbstractObservationTest {
+
+    /**
+     * Tests if events are only created for a sub tree of the workspace.
+     */
+    public void testPath() throws RepositoryException {
+        EventResult listener = new EventResult(log);
+        obsMgr.addEventListener(listener, Event.NODE_ADDED, testRoot + "/" + nodeName1, true, null, null, false);
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        n.addNode(nodeName2);
+        testRootNode.save();
+        obsMgr.removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1, nodeName1 + "/" + nodeName2});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#NODE_ADDED} is created only
+     * for the specified path if <code>isDeep</code> is <code>false</code>.
+     */
+    public void testIsDeepFalseNodeAdded() throws RepositoryException {
+        EventResult listener = new EventResult(log);
+        obsMgr.addEventListener(listener, Event.NODE_ADDED, testRoot + "/" + nodeName1, false, null, null, false);
+        Node n = testRootNode.addNode(nodeName1, testNodeType);
+        n.addNode(nodeName2);
+        testRootNode.save();
+        obsMgr.removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#PROPERTY_ADDED} is created only
+     * for the specified path if <code>isDeep</code> is <code>false</code>.
+     */
+    public void testIsDeepFalsePropertyAdded() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        EventResult listener = new EventResult(log);
+        obsMgr.addEventListener(listener, Event.PROPERTY_ADDED, testRoot + "/" + nodeName1, false, null, null, false);
+        n1.setProperty(propertyName1, "foo");
+        n2.setProperty(propertyName1, "foo");
+        testRootNode.save();
+        obsMgr.removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyAdded(events, new String[]{nodeName1 + "/" + propertyName1});
+    }
+
+    /**
+     * Tests if no events are generated for own modifications if
+     * <code>noLocal</code> is set to <code>true</code>.
+     */
+    public void testNoLocalTrue() throws RepositoryException {
+        EventResult listener = new EventResult(log);
+        obsMgr.addEventListener(listener,
+                Event.NODE_ADDED,
+                testRoot,
+                true,
+                null,
+                null,
+                true); // noLocal
+
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        obsMgr.removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        assertEquals("EventListener must not receive own modification when noLocal=true", 0, events.length);
+    }
+
+    /**
+     * Tests if events are only generated for specified UUIDs.
+     */
+    public void testUUID() throws RepositoryException, NotExecutableException {
+        Node n1 = null;
+        Node n2 = null;
+        try {
+            n1 = createReferenceable(nodeName1, testNodeType);
+            n2 = createReferenceable(nodeName2, testNodeType);
+        } catch (RepositoryException e) {
+            throw new NotExecutableException("Repository does not support mix:referenceable");
+        }
+        testRootNode.save();
+        EventResult listener = new EventResult(log);
+        obsMgr.addEventListener(listener,
+                Event.PROPERTY_ADDED,
+                testRoot,
+                true,
+                new String[]{n1.getUUID()},
+                null,
+                false);
+        n1.setProperty(propertyName1, "foo");
+        n2.setProperty(propertyName1, "foo");
+        testRootNode.save();
+        obsMgr.removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyAdded(events, new String[]{nodeName1 + "/" + propertyName1});
+    }
+
+    /**
+     * Tests if events are only generated for specified node types.
+     */
+    public void testNodeType() throws RepositoryException {
+        EventResult listener = new EventResult(log);
+        obsMgr.addEventListener(listener,
+                Event.NODE_ADDED,
+                testRoot,
+                true,
+                null,
+                new String[]{testNodeType},
+                false);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.addNode(nodeName2, ntBase);
+        testRootNode.save();
+        obsMgr.removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1});
+    }
+
+    //-------------------------< internal >-------------------------------------
+
+    /**
+     * Creates a node with name <code>nodeName</code> with type
+     * <code>nodeType</code> as a child node of {@link #testRootNode}.
+     * If the created node is not of type mix:referenceable a mixin is added
+     * of that type.
+     *
+     * @param nodeName the node name.
+     * @param nodeType the node type of the node to create.
+     * @return the created node
+     * @throws RepositoryException if node creation fails.
+     */
+    private Node createReferenceable(String nodeName, String nodeType)
+            throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName, nodeType);
+        if (!n.isNodeType(mixReferenceable)) {
+            n.addMixin(mixReferenceable);
+        }
+        return n;
+    }
+}
\ No newline at end of file

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventIteratorTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventIteratorTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventIteratorTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventIteratorTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,115 @@
+/*
+ * 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.observation;
+
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.RepositoryException;
+import java.util.NoSuchElementException;
+
+/**
+ * Tests the methods the following methods:
+ * <ul>
+ * <li>{@link javax.jcr.observation.EventIterator#getSize()}</li>
+ * <li>{@link javax.jcr.observation.EventIterator#getPos()}</li>
+ * <li>{@link javax.jcr.observation.EventIterator#skip(long)}</li>
+ * </ul>
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1},
+ * {@link #nodeName2} and {@link #nodeName3}.
+ *
+ * @test
+ * @sources EventIteratorTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.EventIteratorTest
+ * @keywords observation
+ */
+public class EventIteratorTest extends AbstractObservationTest{
+
+    /**
+     * Tests if getSize() returns the correct number of events. If getSize()
+     * returns -1 a {@link org.apache.jackrabbit.test.NotExecutableException}
+     * is thrown.
+     */
+    public void testGetSize() throws RepositoryException, NotExecutableException {
+        EventResult listener = new EventResult(log);
+        addEventListener(listener, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        removeEventListener(listener);
+        EventIterator events = listener.getEventIterator(DEFAULT_WAIT_TIMEOUT);
+        assertNotNull("No events delivered within " + DEFAULT_WAIT_TIMEOUT + "ms.", events);
+        long size = events.getSize();
+        if (size == -1) {
+            throw new NotExecutableException("EventIterator.getSize() returns unavailable size.");
+        }
+        assertEquals("Wrong number of events", 1, size);
+    }
+
+    /**
+     * Tests if getPos() returns the correct values.
+     */
+    public void testGetPos() throws RepositoryException {
+        EventResult listener = new EventResult(log);
+        addEventListener(listener, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.addNode(nodeName2, testNodeType);
+        testRootNode.addNode(nodeName3, testNodeType);
+        testRootNode.save();
+        removeEventListener(listener);
+        EventIterator events = listener.getEventIterator(DEFAULT_WAIT_TIMEOUT);
+        assertNotNull("No events delivered within " + DEFAULT_WAIT_TIMEOUT + "ms.", events);
+        assertEquals("Initial call to getPos() must return 0.", 0, events.getPos());
+        events.nextEvent();
+        assertEquals("Wrong value for getPos()", 1, events.getPos());
+        events.nextEvent();
+        assertEquals("Wrong value for getPos()", 2, events.getPos());
+        events.nextEvent();
+        assertEquals("Wrong value for getPos()", 3, events.getPos());
+    }
+
+    /**
+     * Tests the method skip()
+     */
+    public void testSkip() throws RepositoryException {
+        EventResult listener = new EventResult(log);
+        addEventListener(listener, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.addNode(nodeName2, testNodeType);
+        testRootNode.addNode(nodeName3, testNodeType);
+        testRootNode.save();
+        removeEventListener(listener);
+        EventIterator events = listener.getEventIterator(DEFAULT_WAIT_TIMEOUT);
+        assertNotNull("No events delivered within " + DEFAULT_WAIT_TIMEOUT + "ms.", events);
+        // skip zero elements
+        events.skip(0);
+        assertEquals("getPos() for first element must return 0.", 0, events.getPos());
+        // skip one element
+        events.skip(2);
+        assertEquals("Wrong value for getPos()", 2, events.getPos());
+        // skip past end
+        try {
+            events.skip(2);
+            fail("EventIterator must throw NoSuchElementException when skipping past the end");
+        } catch (NoSuchElementException e) {
+            // success
+        }
+    }
+}
\ No newline at end of file

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventResult.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventResult.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventResult.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventResult.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,136 @@
+/*
+ * 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.observation;
+
+import EDU.oswego.cs.dl.util.concurrent.Mutex;
+import EDU.oswego.cs.dl.util.concurrent.Sync;
+
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.PrintWriter;
+
+/**
+ * Utility class for <code>Event</code> retrieval with an
+ * <code>EventListener</code>.
+ * <p/>
+ * The {@link #getEventIterator(long)} and {@link #getEvents(long)} methods
+ * will block until an event is delivered and then return the events. Note, that
+ * only one of the methods can be called for an expected event delivery. Calling
+ * the 'other' method will block until the next events are delivered.
+ */
+class EventResult implements EventListener {
+
+    /**
+     * The <code>EventIterator</code> delivered to this <code>EventListener</code>
+     */
+    private EventIterator events;
+
+    /**
+     * Sync object for result synchronization
+     */
+    private Sync sync = new Mutex();
+
+    /**
+     * <code>PrintWriter</code> where log messages are written.
+     */
+    private final PrintWriter log;
+
+    /**
+     * Creates a new <code>EventResult</code>.
+     *
+     * @param log log messages are written to this <code>Logger</code>.
+     */
+    EventResult(PrintWriter log) {
+        this.log = log;
+        try {
+            sync.acquire();
+        } catch (InterruptedException e) {
+            log.println("Could not aquire sync.");
+            throw new RuntimeException("EventResult: Interrupted while aquiring sync.");
+        }
+    }
+
+    /**
+     * Gets the events from the EventListener. Waits at most <code>wait</code>
+     * milliseconds for the events.
+     * <p/>
+     * If the events are not delivered within <code>wait</code> time an empty
+     * array is returned and a log message is written.
+     *
+     * @param wait time in milliseconds to wait at most for <code>Event</code>s.
+     * @return <code>Event</code>s.
+     */
+    public Event[] getEvents(long wait) {
+        EventIterator events = getEventIterator(wait);
+        if (events != null) {
+            return getEvents(events);
+        } else {
+            return new Event[0];
+        }
+    }
+
+    /**
+     * Gets the events from the EventListener. Waits at most <code>wait</code>
+     * milliseconds for the events.
+     * <p/>
+     * If the events are not delivered within <code>wait</code> time
+     * <code>null</code> is returned and a log message is written.
+     * @param wait time in milliseconds to wait at most for
+     * <code>EventIterator</code>.
+     * @return <code>EventIterator</code>.
+     */
+    public EventIterator getEventIterator(long wait) {
+        try {
+            if (sync.attempt(wait)) {
+                // result ready
+                return events;
+            }
+        } catch (InterruptedException e) {
+            log.println("Interrupted while waiting for EventIterator");
+        }
+        return null;
+    }
+
+    //--------------------< EventListener >-------------------------------------
+
+    /**
+     * Called when events are delivered.
+     *
+     * @param events the events.
+     */
+    public void onEvent(EventIterator events) {
+        this.events = events;
+        sync.release();
+    }
+
+    /**
+     * Returns the <code>events</code> as an array of <code>Event</code>
+     * instances.
+     * @param events the event iterator.
+     * @return the events from the iterator.
+     */
+    private Event[] getEvents(EventIterator events) {
+        List eventList = new ArrayList();
+        while (events.hasNext()) {
+            eventList.add(events.nextEvent());
+        }
+        return (Event[]) eventList.toArray(new Event[eventList.size()]);
+    }
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/EventTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,84 @@
+/*
+ * 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.observation;
+
+import javax.jcr.observation.Event;
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+
+/**
+ * Tests methods on the {@link javax.jcr.observation.Event} interface.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child node that is created will be named {@link #nodeName1}.
+ *
+ * @test
+ * @sources EventTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.EventTest
+ * @keywords observation
+ */
+public class EventTest extends AbstractObservationTest {
+
+    /**
+     * Tests if getPath() returns the correct path.
+     */
+    public void testGetNodePath() throws RepositoryException{
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        Node addedNode = testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        assertEquals("Wrong number of events returned", 1, events.length);
+        String path = events[0].getPath();
+        String absPath = addedNode.getPath();
+        assertEquals("Path returned by getPath() is wrong", absPath, path);
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#getUserId()} returns the same
+     * value as {@link javax.jcr.Session#getUserId()}.
+     */
+    public void testGetUserId() throws RepositoryException{
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        removeEventListener(result);
+        assertEquals("Wrong number of events returned", 1, events.length);
+        String userId = events[0].getUserId();
+        String sessionUId = superuser.getUserId();
+        assertEquals("UserId of event is not equal to userId of session", userId, sessionUId);
+    }
+
+    /**
+     * Tests if getType() returns the correct value.
+     */
+    public void testGetType() throws RepositoryException{
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        assertEquals("Wrong number of events returned", 1, events.length);
+        int type = events[0].getType();
+        assertEquals("Event did not return correct event type", Event.NODE_ADDED, type);
+    }
+}
\ No newline at end of file

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/GetRegisteredEventListenersTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/GetRegisteredEventListenersTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/GetRegisteredEventListenersTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/GetRegisteredEventListenersTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,65 @@
+/*
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.EventListener;
+
+
+/**
+ * Tests the method {@link javax.jcr.observation.ObservationManager#getRegisteredEventListeners()}.
+ *
+ * @test
+ * @sources GetRegisteredEventListenersTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.GetRegisteredEventListenersTest
+ * @keywords observation
+ */
+public class GetRegisteredEventListenersTest extends AbstractObservationTest {
+
+    public void testGetSize() throws RepositoryException {
+        EventListener[] listeners = toArray(obsMgr.getRegisteredEventListeners());
+        assertEquals("A new session must not have any event listeners registered.", 0, listeners.length);
+
+        EventListener listener1 = new EventResult(log);
+        EventListener listener2 = new EventResult(log);
+        addEventListener(listener1);
+        addEventListener(listener2);
+
+        listeners = toArray(obsMgr.getRegisteredEventListeners());
+        assertEquals("Wrong number of event listeners.", 2, listeners.length);
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.ObservationManager#getRegisteredEventListeners()}
+     * returns the correct listeners after an remove event listener.
+     */
+    public void testRemoveEventListener() throws RepositoryException {
+        EventListener listener1 = new EventResult(log);
+        EventListener listener2 = new EventResult(log);
+        addEventListener(listener1);
+        addEventListener(listener2);
+
+        EventListener[] listeners = toArray(obsMgr.getRegisteredEventListeners());
+        assertEquals("Wrong number of event listeners.", 2, listeners.length);
+
+        removeEventListener(listener1);
+        listeners = toArray(obsMgr.getRegisteredEventListeners());
+        assertEquals("Wrong number of event listeners.", 1, listeners.length);
+        assertEquals("Returned listener is not equal to regsitered one.", listener2, listeners[0]);
+    }
+
+}
\ No newline at end of file

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/LockingTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/LockingTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/LockingTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/LockingTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,120 @@
+/*
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.Event;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Tests if locking a node triggers property added events for jcr:lockOwner
+ * and jcr:lockIsDeep.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child node that is created will be named {@link #nodeName1}. The node
+ * type {@link #testNodeType} must either have mix:lockable as one of its
+ * supertypes or must allow to add mix:lockable as mixin.
+ *
+ * @test
+ * @sources LockingTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.LockingTest
+ * @keywords observation locking
+ */
+public class LockingTest extends AbstractObservationTest {
+
+    /**
+     * Tests if locking a node triggers property added events for the properties
+     * jcr:lockOwner and jcr:lockIsDeep.
+     */
+    public void testAddLockToNode() throws RepositoryException {
+        Node lockable = createLockable(nodeName1, testNodeType);
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_ADDED);
+
+        // now lock node. no save needed
+        lockable.lock(false,true);
+
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+
+        assertEquals("Wrong number of events.", 2, events.length);
+        for (int i = 0; i < events.length; i++) {
+            assertEquals("Wrong type of event.", Event.PROPERTY_ADDED, events[i].getType());
+        }
+        List paths = new ArrayList();
+        for (int i = 0; i < events.length; i++) {
+            paths.add(events[i].getPath());
+        }
+        String lockOwnerPath = testRoot + "/" + nodeName1 + "/" + jcrLockOwner;
+        assertTrue("No event created for jcr:lockOwner", paths.contains(lockOwnerPath));
+        String lockIsDeepPath = testRoot + "/" + nodeName1 + "/" + jcrlockIsDeep;
+        assertTrue("No event created for jcr:lockIsDeep", paths.contains(lockIsDeepPath));
+
+        lockable.unlock();
+    }
+
+    /**
+     * Tests if unlocking a node triggers property removed events for the
+     * properties jcr:lockOwner and jcr:lockIsDeep.
+     */
+    public void testRemoveLockFromNode() throws RepositoryException {
+        Node lockable = createLockable(nodeName1, testNodeType);
+        testRootNode.save();
+        // lock the node
+        lockable.lock(false, true);
+
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_REMOVED);
+        lockable.unlock();
+        removeEventListener(result);
+
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        assertEquals("Wrong number of events.", 2, events.length);
+        for (int i = 0; i < events.length; i++) {
+            assertEquals("Wrong type of event.", Event.PROPERTY_REMOVED, events[i].getType());
+        }
+        List paths = new ArrayList();
+        for (int i = 0; i < events.length; i++) {
+            paths.add(events[i].getPath());
+        }
+        String lockOwnerPath = testRoot + "/" + nodeName1 + "/" + jcrLockOwner;
+        assertTrue("No event created for jcr:lockOwner", paths.contains(lockOwnerPath));
+        String lockIsDeepPath = testRoot + "/" + nodeName1 + "/" + jcrlockIsDeep;
+        assertTrue("No event created for jcr:lockIsDeep", paths.contains(lockIsDeepPath));
+    }
+
+    /**
+     * Creates a child node under {@link #testRoot} with name <code>nodeName</code>
+     * and node type <code>nodeType</code>.
+     * If <code>nodeType</code> is not of type mix:lockable the mixin is added.
+     * @param nodeName the name of the new node.
+     * @param nodeType the node type of the new node.
+     * @return the lockable node
+     */
+    private Node createLockable(String nodeName, String nodeType)
+            throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName, nodeType);
+        if (!n.isNodeType(mixLockable)) {
+            n.addMixin(mixLockable);
+        }
+        return n;
+    }
+}
\ No newline at end of file

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeAddedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeAddedTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeAddedTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeAddedTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,97 @@
+/*
+ * 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.observation;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.Event.NODE_ADDED} events.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1} and
+ * {@link #nodeName2}. Furthermore {@link #testNodeType} must allow to add
+ * child nodes of the same type ({@link #testNodeType}).
+ *
+ * @test
+ * @sources NodeAddedTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.NodeAddedTest
+ * @keywords observation
+ */
+public class NodeAddedTest extends AbstractObservationTest {
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#NODE_ADDED} is triggerd
+     * when a single node is added.
+     */
+    public void testSingleNodeAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#NODE_ADDED} is triggered
+     * for multiple nodes on the same level.
+     */
+    public void testMultipleNodeAdded1() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        testRootNode.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1, nodeName2});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#NODE_ADDED} is triggered
+     * when nodes are created on multiple levels.
+     */
+    public void testMultipleNodeAdded2() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        n1.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1, nodeName1 + "/" + nodeName2});
+    }
+
+    /**
+     * Tests if events are only created for changes that are persisted.
+     */
+    public void testTransientNodeAddedRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_ADDED);
+        testRootNode.addNode(nodeName1, testNodeType);
+        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
+        n2.remove();
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName1});
+    }
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeMovedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeMovedTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeMovedTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeMovedTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,62 @@
+/*
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.Event;
+
+/**
+ * Tests if {@link javax.jcr.Session#move} operations trigger the appropriate
+ * observation events.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1},
+ * {@link #nodeName2}, {@link #nodeName3} and {@link #nodeName4}. Furthermore
+ * {@link #testNodeType} must allow to add child nodes of the same type
+ * ({@link #testNodeType}).
+ *
+ * @test
+ * @sources NodeMovedTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.NodeMovedTest
+ * @keywords observation
+ */
+public class NodeMovedTest extends AbstractObservationTest {
+
+    /**
+     * Tests if node removed and node added event is triggered when a node
+     * is moved.
+     */
+    public void testMoveNode() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        n1.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        EventResult addNodeListener = new EventResult(log);
+        EventResult removeNodeListener = new EventResult(log);
+        addEventListener(addNodeListener, Event.NODE_ADDED);
+        addEventListener(removeNodeListener, Event.NODE_REMOVED);
+        superuser.move(n1.getPath(), testRoot + "/" + nodeName3);
+        testRootNode.save();
+        removeEventListener(addNodeListener);
+        removeEventListener(removeNodeListener);
+        Event[] added = addNodeListener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        Event[] removed = removeNodeListener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(added, new String[]{nodeName3});
+        checkNodeRemoved(removed, new String[]{nodeName1});
+    }
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/NodeRemovedTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,72 @@
+/*
+ * 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.observation;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.Event.NODE_REMOVED} events.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1} and
+ * {@link #nodeName2}. Furthermore {@link #testNodeType} must allow to add
+ * child nodes of the same type ({@link #testNodeType}).
+ *
+ * @test
+ * @sources NodeRemovedTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.NodeRemovedTest
+ * @keywords observation
+ */
+public class NodeRemovedTest extends AbstractObservationTest {
+
+    /**
+     * Tests if a {@link javax.jcr.observation.Event#NODE_REMOVED} is triggered
+     * when a single node is removed.
+     */
+    public void testSingleNodeRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_REMOVED);
+        Node foo = testRootNode.addNode(nodeName1);
+        testRootNode.save();
+        foo.remove();
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeRemoved(events, new String[]{nodeName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#NODE_REMOVED} events are
+     * triggered when multiple nodes are removed.
+     */
+    public void testMultiNodesRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.NODE_REMOVED);
+        Node n1 = testRootNode.addNode(nodeName1);
+        n1.addNode(nodeName2);
+        testRootNode.save();
+        n1.remove();
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeRemoved(events, new String[]{nodeName1, nodeName1 + "/" + nodeName2});
+    }
+
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyAddedTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,97 @@
+/*
+ * 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.observation;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test cases for {@link javax.jcr.observation.Event.PROPERTY_ADDED} events.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1} and
+ * {@link #nodeName2}.
+ * {@link #testNodeType} must also support String properties with names
+ * {@link #propertyName1} and {@link #propertyName2}.
+ *
+ * @test
+ * @sources PropertyAddedTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.PropertyAddedTest
+ * @keywords observation
+ */
+public class PropertyAddedTest extends AbstractObservationTest {
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#PROPERTY_ADDED} is triggered
+     * for system generated property jcr:primaryType.
+     */
+    public void testSystemGenerated() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_ADDED);
+        testRootNode.addNode(nodeName1);
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        List paths = new ArrayList();
+        for (int i = 0; i < events.length; i++) {
+            paths.add(events[i].getPath());
+        }
+        String jcrPrimaryTypePath = testRoot + "/" + nodeName1 + "/" + jcrPrimaryType;
+        assertTrue("No event generated for jcr:primaryType.", paths.contains(jcrPrimaryTypePath));
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#PROPERTY_ADDED} is triggered
+     * when a single property is added.
+     * @throws RepositoryException
+     */
+    public void testSinglePropertyAdded() throws RepositoryException {
+        Node foo = testRootNode.addNode(nodeName1);
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_ADDED);
+        foo.setProperty(propertyName1, "test content");
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyAdded(events, new String[]{nodeName1 + "/" + propertyName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#PROPERTY_ADDED} is triggered
+     * when multiple properties are added.
+     */
+    public void testMultiPropertyAdded() throws RepositoryException {
+        Node foo = testRootNode.addNode(nodeName1);
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_ADDED);
+        foo.setProperty(propertyName1, "foo");
+        foo.setProperty(propertyName2, "bar");
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyAdded(events, new String[]{nodeName1 + "/" + propertyName1,
+                                                nodeName1 + "/" + propertyName2});
+    }
+
+
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyChangedTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,96 @@
+/*
+ * 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.observation;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.Event.PROPERTY_CHANGED} events.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1} and
+ * {@link #nodeName2}.
+ * {@link #testNodeType} must also support String properties with names
+ * {@link #propertyName1} and {@link #propertyName2}.
+ *
+ * @test
+ * @sources PropertyChangedTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.PropertyChangedTest
+ * @keywords observation
+ */
+public class PropertyChangedTest extends AbstractObservationTest {
+
+    /**
+     * Tests if a {@link javax.jcr.observation.Event#PROPERTY_CHANGED} is
+     * triggered when a single property is changed.
+     */
+    public void testSinglePropertyChanged() throws RepositoryException {
+        Node node = testRootNode.addNode(nodeName1);
+        node.setProperty(propertyName1, "foo");
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_CHANGED);
+        node.getProperty(propertyName1).setValue("foobar");
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyChanged(events, new String[]{nodeName1 + "/" + propertyName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#PROPERTY_CHANGED} are
+     * triggered when multiple properties are changed.
+     * @throws RepositoryException
+     */
+    public void testMultiPropertyChanged() throws RepositoryException {
+        Node node = testRootNode.addNode(nodeName1);
+        node.setProperty(propertyName1, "foo");
+        node.setProperty(propertyName2, "bar");
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_CHANGED);
+        node.getProperty(propertyName1).setValue("foobar");
+        node.getProperty(propertyName2).setValue("foobar");
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyChanged(events, new String[]{nodeName1 + "/" + propertyName1,
+                                                  nodeName1 + "/" + propertyName2});
+    }
+
+    /**
+     * Tests if a {@link javax.jcr.observation.Event#PROPERTY_CHANGED} is
+     * triggered only for changed properties and not for new properties.
+     */
+    public void testSinglePropertyChangedWithAdded() throws RepositoryException {
+        Node node = testRootNode.addNode(nodeName1);
+        node.setProperty(propertyName1, "foo");
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_CHANGED);
+        node.getProperty(propertyName1).setValue("foobar");
+        node.setProperty(propertyName2, "bar");    // will not fire prop changed event
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyChanged(events, new String[]{nodeName1 + "/" + propertyName1});
+    }
+
+}

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

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyRemovedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyRemovedTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyRemovedTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/PropertyRemovedTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,78 @@
+/*
+ * 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.observation;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Property;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.Event.PROPERTY_REMOVED} events.
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1} and
+ * {@link #nodeName2}.
+ * {@link #testNodeType} must also support String properties with names
+ * {@link #propertyName1} and {@link #propertyName2}.
+ *
+ * @test
+ * @sources PropertyRemovedTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.PropertyRemovedTest
+ * @keywords observation
+ */
+public class PropertyRemovedTest extends AbstractObservationTest {
+
+    /**
+     * Tests if a {@link javax.jcr.observation.Event#PROPERTY_REMOVED} is
+     * triggered when a property is removed.
+     */
+    public void testSinglePropertyRemoved() throws RepositoryException {
+        Node node = testRootNode.addNode(nodeName1);
+        Property prop1 = node.setProperty(propertyName1, "foo");
+        node.setProperty(propertyName2, "bar");
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_REMOVED);
+        prop1.remove();
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyRemoved(events, new String[]{nodeName1 + "/" + propertyName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.observation.Event#PROPERTY_REMOVED} are
+     * triggered when multiple properties are removed.
+     */
+    public void testMultiPropertyRemoved() throws RepositoryException {
+        Node node = testRootNode.addNode(nodeName1);
+        Property prop1 = node.setProperty(propertyName1, "foo");
+        Property prop2 = node.setProperty(propertyName2, "bar");
+        testRootNode.save();
+        EventResult result = new EventResult(log);
+        addEventListener(result, Event.PROPERTY_REMOVED);
+        prop1.remove();
+        prop2.remove();
+        testRootNode.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkPropertyRemoved(events, new String[]{nodeName1 + "/" + propertyName1,
+                                                  nodeName1 + "/" + propertyName2});
+    }
+}

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

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/TestAll.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/TestAll.java?view=diff&r1=155582&r2=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/TestAll.java (original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/TestAll.java Sat Feb 26 12:51:46 2005
@@ -16,13 +16,12 @@
  */
 package org.apache.jackrabbit.test.api.observation;
 
-import junit.framework.TestCase;
 import junit.framework.Test;
+import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
 /**
- * Test suite that includes all testcases for the package
- * <code>javax.jcr.observation</code>.
+ * Test suite that includes all testcases for the Observation module.
  */
 public class TestAll extends TestCase {
 
@@ -34,10 +33,21 @@
      *         package.
      */
     public static Test suite() {
-        TestSuite suite = new TestSuite("javax.jcr.observation tests");
+        TestSuite suite = new TestSuite("Observation tests");
 
-        // ADD TEST CLASSES HERE:
+        suite.addTestSuite(EventIteratorTest.class);
+        suite.addTestSuite(EventTest.class);
+        suite.addTestSuite(GetRegisteredEventListenersTest.class);
+        suite.addTestSuite(LockingTest.class);
+        suite.addTestSuite(NodeAddedTest.class);
+        suite.addTestSuite(NodeRemovedTest.class);
+        suite.addTestSuite(NodeMovedTest.class);
+        suite.addTestSuite(PropertyAddedTest.class);
+        suite.addTestSuite(PropertyChangedTest.class);
+        suite.addTestSuite(PropertyRemovedTest.class);
+        suite.addTestSuite(AddEventListenerTest.class);
+        suite.addTestSuite(WorkspaceOperationTest.class);
 
         return suite;
     }
-}
\ No newline at end of file
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/WorkspaceOperationTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/WorkspaceOperationTest.java?view=auto&rev=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/WorkspaceOperationTest.java (added)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/observation/WorkspaceOperationTest.java Sat Feb 26 12:51:46 2005
@@ -0,0 +1,102 @@
+/*
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.Event;
+
+/**
+ * Tests if workspace operations trigger the appropriate observation events.
+ *
+ * <p/>
+ * Configuration requirements are:<br/>
+ * The {@link #testRoot} must allow child nodes of type {@link #testNodeType}.
+ * The child nodes that are created will be named {@link #nodeName1},
+ * {@link #nodeName2}, {@link #nodeName3} and {@link #nodeName4}. Furthermore
+ * {@link #testNodeType} must allow to add child nodes of the same type
+ * ({@link #testNodeType}).
+ *
+ * @test
+ * @sources WorkspaceOperationTest.java
+ * @executeClass org.apache.jackrabbit.test.api.observation.WorkspaceOperationTest
+ * @keywords observation
+ */
+public class WorkspaceOperationTest extends AbstractObservationTest {
+
+    /**
+     * Tests if {@link javax.jcr.Workspace#copy(String, String)} triggers
+     * the correct events.
+     */
+    public void testCopy() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        n1.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        EventResult listener = new EventResult(log);
+        addEventListener(listener, Event.NODE_ADDED);
+        superuser.getWorkspace().copy(testRoot + "/" + nodeName1, testRoot + "/" + nodeName3);
+        removeEventListener(listener);
+        Event[] events = listener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[]{nodeName3, nodeName3 + "/" + nodeName2});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.Workspace#move(String, String)} triggers the
+     * correct events.
+     */
+    public void testRename() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        n1.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        EventResult addNodeListener = new EventResult(log);
+        EventResult removeNodeListener = new EventResult(log);
+        addEventListener(addNodeListener, Event.NODE_ADDED);
+        addEventListener(removeNodeListener, Event.NODE_REMOVED);
+        superuser.getWorkspace().move(n1.getPath(), testRoot + "/" + nodeName3);
+        testRootNode.save();
+        removeEventListener(addNodeListener);
+        removeEventListener(removeNodeListener);
+        Event[] added = addNodeListener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        Event[] removed = removeNodeListener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(added, new String[]{nodeName3});
+        checkNodeRemoved(removed, new String[]{nodeName1});
+    }
+
+    /**
+     * Tests if {@link javax.jcr.Workspace#move(String, String)} triggers the
+     * correct events.
+     */
+    public void testMove() throws RepositoryException {
+        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
+        Node n3 = testRootNode.addNode(nodeName3, testNodeType);
+        n1.addNode(nodeName2, testNodeType);
+        testRootNode.save();
+        EventResult addNodeListener = new EventResult(log);
+        EventResult removeNodeListener = new EventResult(log);
+        addEventListener(addNodeListener, Event.NODE_ADDED);
+        addEventListener(removeNodeListener, Event.NODE_REMOVED);
+        superuser.getWorkspace().move(n1.getPath(), n3.getPath() + "/" + nodeName4);
+        testRootNode.save();
+        removeEventListener(addNodeListener);
+        removeEventListener(removeNodeListener);
+        Event[] added = addNodeListener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        Event[] removed = removeNodeListener.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(added, new String[]{nodeName3 + "/" + nodeName4});
+        checkNodeRemoved(removed, new String[]{nodeName1});
+    }
+
+}

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

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/version/AbstractVersionTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/version/AbstractVersionTest.java?view=diff&r1=155582&r2=155583
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/version/AbstractVersionTest.java (original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/version/AbstractVersionTest.java Sat Feb 26 12:51:46 2005
@@ -100,6 +100,8 @@
         try {
             versionableNode.remove();
             testRootNode.save();
+        } catch (Exception e) {
+            log.println("Exception in tearDown: " + e.toString());
         } finally {
             super.tearDown();
         }