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 2004/09/28 16:42:39 UTC

svn commit: rev 47400 - in incubator/jackrabbit/trunk/src/test/org: . apache apache/jackrabbit apache/jackrabbit/test apache/jackrabbit/test/observation apache/jackrabbit/test/search

Author: mreutegg
Date: Tue Sep 28 07:42:38 2004
New Revision: 47400

Added:
   incubator/jackrabbit/trunk/src/test/org/
   incubator/jackrabbit/trunk/src/test/org/apache/
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/JUnitTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/JackrabbitRepositoryStub.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryHelper.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryStub.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryStubException.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/AbstractObservationTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/EventResult.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/NodeAddedTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/NodeRemovedTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyAddedTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyChangedTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyRemovedTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/TestAll.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java
Log:
Checked in a couple of testcases covering search and observation functionality.

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/AbstractTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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;
+
+import javax.jcr.Session;
+import javax.jcr.Node;
+
+/**
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public abstract class AbstractTest extends JUnitTest {
+
+    protected static final String TEST_ROOT = "testroot";
+
+    protected static final String JCR_PRIMARY_TYPE = "jcr:primaryType";
+
+    protected static final String NT_UNSTRUCTURED = "nt:unstructured";
+
+    protected static final String MIX_REFERENCABLE = "mix:referencable";
+
+    protected static final String NT_BASE = "nt:base";
+
+    /** The superuser session */
+    protected Session superuser;
+
+    /** The root <code>Node</code> for testing */
+    protected Node testRoot;
+
+    protected void setUp() throws Exception {
+        superuser = helper.getSuperuserSession();
+        Node root = superuser.getRootNode();
+        if (root.hasNode(TEST_ROOT)) {
+            // remove test root
+            root.remove(TEST_ROOT);
+            root.save();
+        }
+        testRoot = root.addNode(TEST_ROOT, NT_UNSTRUCTURED);
+        root.save();
+    }
+
+    protected void tearDown() throws Exception {
+        if (superuser != null) {
+            // do a 'rollback'
+            superuser.refresh(false);
+            Node root = superuser.getRootNode();
+            if (root.hasNode(TEST_ROOT)) {
+                root.remove(TEST_ROOT);
+                root.save();
+            }
+            superuser.logout();
+        }
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/JUnitTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/JUnitTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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;
+
+import junit.framework.TestCase;
+import org.apache.log4j.Logger;
+
+/**
+ *
+ * @version $Revision: 1.4 $, $Date: 2004/05/04 12:06:31 $
+ * @author Marcel Reutegger
+ */
+public class JUnitTest extends TestCase {
+
+    /** Helper object to access repository transparently */
+    public static final RepositoryHelper helper = new RepositoryHelper();
+
+    /** Logger instance for test cases */
+    protected static final Logger log = Logger.getLogger(JUnitTest.class);
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/JackrabbitRepositoryStub.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/JackrabbitRepositoryStub.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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;
+
+import org.apache.jackrabbit.core.RepositoryFactory;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import java.util.Properties;
+
+/**
+ * Implements the <code>RepositoryStub</code> for the JCR Reference Implementation.
+ *
+ * @version $Revision: 1.2 $, $Date: 2004/06/28 14:52:37 $
+ * @author Marcel Reutegger
+ */
+public class JackrabbitRepositoryStub extends RepositoryStub {
+
+    /** Property for the repositry name */
+    public static final String PROP_REPOSITORY_NAME = "org.apache.jackrabbit.repository.name";
+
+    public static final String PROP_REPOSITRY_HOME = "org.apache.jackrabbit.repository.home";
+
+    /** The repository instance */
+    private Repository repository;
+
+    private RepositoryFactory factory;
+
+    /**
+     * Constructor as required by the JCR TCK.
+     *
+     * @param env environment properties.
+     */
+    public JackrabbitRepositoryStub(Properties env) {
+	super(env);
+    }
+
+    /**
+     * Returns the configured <code>Repository</code> instance.
+     * <br>
+     * The default repository name is 'localfs'.
+     *
+     * @return the configured <code>Repository</code> instance.
+     *
+     * @throws RepositoryStubException if an error occurs while
+     *   obtaining the Repository instance.
+     */
+    public synchronized Repository getRepository() throws RepositoryStubException {
+	if (repository == null) {
+	    try {
+		String repName = environment.getProperty(PROP_REPOSITORY_NAME, "localfs");
+		String repHome = environment.getProperty(PROP_REPOSITRY_HOME);
+		factory = RepositoryFactory.create(repHome + "/config.xml", repHome);
+		repository = factory.getRepository(repName);
+		Runtime.getRuntime().addShutdownHook(new Thread() {
+		    public void run() {
+			factory.shutdown();
+		    }
+		});
+	    } catch (RepositoryException e) {
+		throw new RepositoryStubException(e.toString());
+	    }
+	}
+	return repository;
+    }
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryHelper.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryHelper.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ *
+ * @version $Revision: 1.5 $, $Date: 2004/06/28 14:29:16 $
+ * @author Marcel Reutegger
+ */
+public class RepositoryHelper {
+
+    public Repository getRepository() throws RepositoryException {
+        try {
+            RepositoryStub repStub = RepositoryStub.getInstance();
+            return repStub.getRepository();
+        } catch (RepositoryStubException e) {
+            throw new RepositoryException("Failed to get Repository instance.", e);
+        }
+    }
+
+    public Session getSuperuserSession() throws RepositoryException {
+        try {
+            RepositoryStub repStub = RepositoryStub.getInstance();
+            return repStub.getRepository().login(repStub.getSuperuserCredentials(), null);
+        } catch (RepositoryStubException e) {
+            throw new RepositoryException("Failed to login to Repository.", e);
+        }
+    }
+
+    public Session getReadWriteSession() throws RepositoryException {
+        try {
+            RepositoryStub repStub = RepositoryStub.getInstance();
+            return repStub.getRepository().login(repStub.getReadWriteCredentials(), null);
+        } catch (RepositoryStubException e) {
+            throw new RepositoryException("Failed to login to Repository.", e);
+        }
+    }
+
+    public Session getReadOnlySession() throws RepositoryException {
+        try {
+            RepositoryStub repStub = RepositoryStub.getInstance();
+            return repStub.getRepository().login(repStub.getReadOnlyCredentials(), null);
+        } catch (RepositoryStubException e) {
+            throw new RepositoryException("Failed to login to Repository.", e);
+        }
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryStub.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryStub.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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;
+
+import javax.jcr.Repository;
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+import java.util.Properties;
+import java.io.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * The <code>RepositoryStub</code> is the entry point to the JCR Repository
+ * for the TCK Test harness.
+ * <p>
+ * Implementors of the JCR specification need to provide an implementation
+ * for the abstract methods defined in this class.
+ *
+ * @version $Revision: 1.3 $, $Date: 2004/05/04 12:06:31 $
+ * @author Marcel Reutegger
+ */
+public abstract class RepositoryStub {
+
+    public static final String STUB_IMPL_PROPS = "repositoryStubImpl.properties";
+
+    public static final String STUB_IMPL_SYS_PROPS = "javax.jcr.tck.properties";
+
+    public static final String PROP_STUB_IMPL_CLASS = "javax.jcr.tck.repository_stub_impl";
+
+    public static final String PROP_SUPERUSER_PWD = "javax.jcr.tck.superuser.pwd";
+
+    public static final String PROP_SUPERUSER_NAME = "javax.jcr.tck.superuser.name";
+
+    public static final String PROP_READONLY_PWD = "javax.jcr.tck.readonly.pwd";
+
+    public static final String PROP_READONLY_NAME = "javax.jcr.tck.readonly.name";
+
+    public static final String PROP_READWRITE_PWD = "javax.jcr.tck.readwrite.pwd";
+
+    public static final String PROP_READWRITE_NAME = "javax.jcr.tck.readwrite.name";
+
+    protected static RepositoryStub instance;
+
+    protected final Properties environment;
+
+    protected SimpleCredentials superuser;
+
+    protected SimpleCredentials readonly;
+
+    protected SimpleCredentials readwrite;
+
+    /**
+     * Implementations of this class must overwrite this constructor.
+     *
+     * @param env the environment variables. This parameter must not be null.
+     */
+    protected RepositoryStub(Properties env) {
+        if (env == null) throw new IllegalArgumentException("Parameter 'env' must not be null!");
+        environment = env;
+	superuser = new SimpleCredentials(env.getProperty(PROP_SUPERUSER_NAME, ""),
+		env.getProperty(PROP_SUPERUSER_PWD, "").toCharArray());
+	readonly = new SimpleCredentials(env.getProperty(PROP_READONLY_NAME, ""),
+		env.getProperty(PROP_READONLY_PWD, "").toCharArray());
+	readwrite = new SimpleCredentials(env.getProperty(PROP_READWRITE_NAME, ""),
+		env.getProperty(PROP_READWRITE_PWD, "").toCharArray());
+    }
+
+    /**
+     * Creates and/or returns the configured <code>RepositryStub</code>
+     * implementation.
+     * <p>
+     * The property file is located in the following sequence:
+     * <ol>
+     * <li>If the system property <code>-Djavax.jcr.tck.properties</code> is
+     * set, then the accroding file is used as configuration.</li>
+     * <li>If the system property <code>-Djavax.jcr.tck.properties</code> is
+     * not set, then the TCK tries to load the file <code>repositoryStubImpl.properties</code>
+     * as a resource from the ClassLoader of this <code>RepositryStub</code> class.</li>
+     * <li>If none of the above is found, a {@link RepositoryStubException} is thrown.
+     * </ol>
+     * @return a <code>RepositoryStub</code> implementation.
+     * @throws RepositoryStubException
+     */
+    public static synchronized RepositoryStub getInstance() throws RepositoryStubException {
+        if (instance == null) {
+            Properties props = null;
+            String implProp = System.getProperty(STUB_IMPL_SYS_PROPS);
+	    if (implProp != null) {
+		File implPropFile = new File(implProp);
+		if (implPropFile.exists()) {
+		    props = new Properties();
+		    try {
+			props.load(new FileInputStream(implPropFile));
+		    } catch (IOException e) {
+			throw new RepositoryStubException("Unable to load config file: "
+				+ implProp + " " + e.toString());
+		    }
+		} else {
+		    throw new RepositoryStubException("File does not exist: " + implProp);
+		}
+	    }
+
+	    if (props == null) {
+		InputStream is = RepositoryStub.class.getClassLoader().getResourceAsStream(STUB_IMPL_PROPS);
+		if (is == null) {
+		    throw new RepositoryStubException(STUB_IMPL_PROPS + " not found in classpath!");
+		}
+		try {
+		    props = new Properties();
+		    props.load(is);
+		} catch (IOException e) {
+		    throw new RepositoryStubException("Exception reading "
+			    + STUB_IMPL_PROPS + ": " + e.toString());
+		}
+	    }
+
+            try {
+                String className = props.getProperty(PROP_STUB_IMPL_CLASS);
+                if (className == null || className.length() == 0) {
+                    throw new RepositoryStubException("Property " + PROP_STUB_IMPL_CLASS + " not defined!");
+                }
+                Class stubClass = Class.forName(className);
+                Constructor constr = stubClass.getConstructor(new Class[] {Properties.class});
+                instance = (RepositoryStub)constr.newInstance(new Object[] {props});
+            } catch (ClassCastException e) {
+                throw new RepositoryStubException(e.toString());
+            } catch (NoSuchMethodException e) {
+                throw new RepositoryStubException(e.toString());
+            } catch (ClassNotFoundException e) {
+                throw new RepositoryStubException(e.toString());
+            } catch (InstantiationException e) {
+                throw new RepositoryStubException(e.toString());
+            } catch (IllegalAccessException e) {
+                throw new RepositoryStubException(e.toString());
+            } catch (InvocationTargetException e) {
+                throw new RepositoryStubException(e.toString());
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * Returns a reference to the <code>Repository</code> provided by this
+     * <code>RepositoryStub</code>.
+     * @return
+     */
+    public abstract Repository getRepository() throws RepositoryStubException;
+
+    /**
+     * Returns a <code>Credentials</code> object, that can be used to login
+     * to the <code>Repository</code> returned by {@link #getRepository}.
+     * <p>
+     * The <code>Credentials</code> returned has 'superuser' rights. That
+     * is, the <code>Ticket</code> object returned by {@link Repository#login}
+     * has read write access to the whole Content Repository.
+     *
+     * @return a <code>Credentials</code> object, that allows to login to the
+     *      <code>Repository</code> as 'superuser'.
+     */
+    public Credentials getSuperuserCredentials() {
+	return superuser;
+    }
+
+    /**
+     * Returns a <code>Credentials</code> object, that can be used to login
+     * to the <code>Repository</code> returned by {@link #getRepository}.
+     * <p>
+     * The <code>Credentials</code> returned has read/write rights. That
+     * is, the <code>Ticket</code> object returned by {@link Repository#login}
+     * has read write access to the <code>Node</code> configured in the
+     * JCR TCK Interview.
+     * <p>
+     * For details, see: JCR TCK User Guide.
+     *
+     * @return a <code>Credentials</code> object, that allows to login to the
+     *      <code>Repository</code> with read/write right.
+     */
+    public Credentials getReadWriteCredentials() {
+	return readwrite;
+    }
+
+    /**
+     * Returns a <code>Credentials</code> object, that can be used to login
+     * to the <code>Repository</code> returned by {@link #getRepository}.
+     * <p>
+     * The <code>Credentials</code> returned must have read-only rights. That
+     * is, the <code>Ticket</code> object returned by {@link Repository#login}
+     * has read-only access to the <code>Node</code> configured in the
+     * JCR TCK Interview.
+     * <p>
+     * For details, see: JCR TCK User Guide.
+     *
+     * @return a <code>Credentials</code> object, that allows to login to the
+     *      <code>Repository</code> with read-only right.
+     */
+    public Credentials getReadOnlyCredentials() {
+	return readonly;
+    }
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryStubException.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/RepositoryStubException.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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;
+
+/**
+ *
+ * @version $Revision: 1.3 $, $Date: 2004/05/04 12:06:31 $
+ * @author Marcel Reutegger
+ */
+public class RepositoryStubException extends Exception {
+
+    public RepositoryStubException(String msg) {
+        super(msg);
+    }
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/AbstractObservationTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/AbstractObservationTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import org.apache.jackrabbit.test.AbstractTest;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventType;
+import javax.jcr.observation.Event;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * This class implements the basic {@link #setUp} and {@link #tearDown()}
+ * methods for the observation test cases.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public abstract class AbstractObservationTest extends AbstractTest {
+
+    /** 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,
+                EventType.CHILD_NODE_ADDED | EventType.CHILD_NODE_REMOVED | EventType.PROPERTY_ADDED | EventType.PROPERTY_CHANGED | EventType.PROPERTY_REMOVED);
+    }
+
+    /**
+     * Registers an <code>EventListener</code> for events of the specified
+     * type(s).
+     *
+     * @param listener the <code>EventListener</code>.
+     * @param eventType the {@link javax.jcr.observation.EventType}s
+     * @throws RepositoryException if registration fails.
+     */
+    protected void addEventListener(EventListener listener, long 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.");
+        }
+    }
+
+    //--------------------< check methods >-------------------------------------
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #TEST_ROOT}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to child nodes added relative to {@link
+     *                 #TEST_ROOT}.
+     * @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, EventType.CHILD_NODE_ADDED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #TEST_ROOT}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to child nodes added relative to {@link
+     *                 #TEST_ROOT}.
+     * @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, EventType.CHILD_NODE_REMOVED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #TEST_ROOT}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to added properties relative to {@link
+     *                 #TEST_ROOT}.
+     * @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, EventType.PROPERTY_ADDED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #TEST_ROOT}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to changed properties relative to {@link
+     *                 #TEST_ROOT}.
+     * @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, EventType.PROPERTY_CHANGED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #TEST_ROOT}.
+     *
+     * @param events   the <code>Event</code>s.
+     * @param relPaths paths to removed properties relative to {@link
+     *                 #TEST_ROOT}.
+     * @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, EventType.PROPERTY_REMOVED);
+    }
+
+    /**
+     * Checks <code>Events</code> for paths. All <code>relPaths</code> are
+     * relative to {@link #TEST_ROOT}.
+     *
+     * @param events    the <code>Event</code>s.
+     * @param relPaths  paths to item events relative to {@link #TEST_ROOT}.
+     * @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].getNodePath()
+		    + "/" + events[i].getChildName();
+	    paths.add(path);
+	}
+	for (int i = 0; i < relPaths.length; i++) {
+	    String expected = "/" + TEST_ROOT + "/" + relPaths[i];
+	    assertTrue("Path " + expected + " not found in events.",
+		    paths.contains(expected));
+	}
+    }
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/EventResult.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/EventResult.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import EDU.oswego.cs.dl.util.concurrent.Sync;
+import EDU.oswego.cs.dl.util.concurrent.Mutex;
+
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.Event;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Utility class for <code>Event</code> retrieval with an
+ * <code>EventListener</code>.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class EventResult implements EventListener {
+
+    /** The actual <code>Event</code>s delivered to this <code>EventListener</code> */
+    private Event[] events;
+
+    /** Sync object for result synchronization */
+    private Sync sync = new Mutex();
+
+    /** <code>Logger</code> where log message are written. */
+    private final Logger log;
+
+    /**
+     * Creates a new <code>EventResult</code>.
+     *
+     * @param log log messages are written to this <code>Logger</code>.
+     */
+    EventResult(Logger log) {
+        this.log = log;
+        try {
+            sync.acquire();
+        } catch (InterruptedException e) {
+            log.error("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) {
+        try {
+            if (sync.attempt(wait)) {
+                // result ready
+
+                // release sync again for following getEvents() calls
+                sync.release();
+                return events;
+            } else {
+                log.error("Events not delivered within " + wait + " ms.");
+            }
+        } catch (InterruptedException e) {
+            log.warn("Interrupted while waiting for EventIterator.");
+        }
+        return new Event[0];
+    }
+
+    //--------------------< EventListener >-------------------------------------
+
+    /**
+     * Called when events are delivered.
+     * @param events the events.
+     */
+    public void onEvent(EventIterator events) {
+        List eventList = new ArrayList();
+        while (events.hasNext()) {
+            eventList.add(events.nextEvent());
+        }
+        this.events = (Event[])eventList.toArray(new Event[eventList.size()]);
+        sync.release();
+    }
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/NodeAddedTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/NodeAddedTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventType;
+
+/**
+ * Test cases for {@link javax.jcr.observation.EventType#CHILD_NODE_ADDED
+ * CHILD_NODE_ADDED} events.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class NodeAddedTest extends AbstractObservationTest {
+
+    public void testSingleNodeAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, EventType.CHILD_NODE_ADDED);
+        testRoot.addNode("foo", NT_UNSTRUCTURED);
+        testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[] { "foo" });
+    }
+
+    public void testMultipleNodeAdded1() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, EventType.CHILD_NODE_ADDED);
+        testRoot.addNode("foo", NT_UNSTRUCTURED);
+        testRoot.addNode("bar", NT_UNSTRUCTURED);
+        testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[] { "foo", "bar" });
+    }
+
+    public void testMultipleNodeAdded2() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, EventType.CHILD_NODE_ADDED);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+        foo.addNode("bar", NT_UNSTRUCTURED);
+        testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[] { "foo", "foo/bar" });
+    }
+
+    public void testTransientNodeAddedRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, EventType.CHILD_NODE_ADDED);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+        foo.addNode("bar", NT_UNSTRUCTURED);
+        foo.remove("bar");
+        testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[] { "foo" });
+    }
+
+    /*
+    NOT POSSIBLE YET. WAIT FOR MIXIN IMPLEMENTATION.
+
+    public void testMultiPathSameNameAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        addEventListener(result, EventType.CHILD_NODE_ADDED);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+        Node bar = testRoot.addNode("bar", NT_UNSTRUCTURED);
+        Node bla = foo.addNode("bla", NT_UNSTRUCTURED);
+        bla.addMixin(MIX_REFERENCABLE);
+        bar.addNode(bla, "bla");
+        testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeAdded(events, new String[] { "foo", "bar", "foo/bla", "bar/bla"});
+    }
+    */
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/NodeRemovedTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/NodeRemovedTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.EventType;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.EventType#CHILD_NODE_REMOVED
+ * CHILD_NODE_REMOVED} events.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class NodeRemovedTest extends AbstractObservationTest {
+
+    public void testSingleNodeRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+	addEventListener(result, EventType.CHILD_NODE_REMOVED);
+        testRoot.addNode("foo", NT_UNSTRUCTURED);
+        testRoot.save();
+	testRoot.remove("foo");
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeRemoved(events, new String[] { "foo" });
+    }
+
+    public void testMultiNodesRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+	addEventListener(result, EventType.CHILD_NODE_REMOVED);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.addNode("bar", NT_UNSTRUCTURED);
+        testRoot.save();
+	testRoot.remove("foo");
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+        checkNodeRemoved(events, new String[] { "foo", "foo/bar" });
+    }
+
+    public void testMultiNodesRemovedWithRemaining() throws RepositoryException {
+	EventResult result = new EventResult(log);
+	addEventListener(result, EventType.CHILD_NODE_REMOVED);
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	testRoot.addNode("foobar", NT_UNSTRUCTURED);
+	foo.addNode("bar", NT_UNSTRUCTURED);
+	testRoot.save();
+	testRoot.remove("foo");
+	testRoot.save();
+	removeEventListener(result);
+	Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkNodeRemoved(events, new String[] { "foo", "foo/bar" });
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyAddedTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyAddedTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.EventType;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.EventType#PROPERTY_ADDED
+ * PROPERTY_ADDED} events.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class PropertyAddedTest extends AbstractObservationTest {
+
+    public void testSinglePropertyAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+	addEventListener(result, EventType.PROPERTY_ADDED);
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("prop1", new String[] { "foo" });
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyAdded(events, new String[] { "foo/prop1",
+						  "foo/" + JCR_PRIMARY_TYPE });
+    }
+
+    public void testMultiPropertyAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+	addEventListener(result, EventType.PROPERTY_ADDED);
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("prop1", new String[] { "foo" });
+	foo.setProperty("prop2", new String[] { "bar" });
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyAdded(events, new String[] { "foo/prop1",
+						  "foo/prop2",
+						  "foo/" + JCR_PRIMARY_TYPE });
+    }
+
+
+
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyChangedTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyChangedTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.EventType;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.EventType#PROPERTY_CHANGED
+ * PROPERTY_CHANGED} events.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class PropertyChangedTest extends AbstractObservationTest {
+
+    public void testSinglePropertyChanged() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("bar", new String[] { "foo" });
+        testRoot.save();
+	addEventListener(result, EventType.PROPERTY_CHANGED);
+	foo.getProperty("bar").setValue(new String[] { "foobar" });
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyChanged(events, new String[] { "foo/bar" });
+    }
+
+    public void testMultiPropertyChanged() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("prop1", new String[] { "foo" });
+	foo.setProperty("prop2", new String[] { "bar" });
+        testRoot.save();
+	addEventListener(result, EventType.PROPERTY_CHANGED);
+	foo.getProperty("prop1").setValue(new String[] { "foobar" });
+	foo.getProperty("prop2").setValue(new String[] { "foobar" });
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyChanged(events, new String[] { "foo/prop1", "foo/prop2" });
+    }
+
+    public void testSinglePropertyChangedWithAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("bar", new String[] { "foo" });
+        testRoot.save();
+	addEventListener(result, EventType.PROPERTY_CHANGED);
+	foo.getProperty("bar").setValue(new String[] { "foobar" });
+	foo.setProperty("foo", new String[] { "bar" });    // will not fire prop changed event
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyChanged(events, new String[] { "foo/bar" });
+    }
+
+    public void testMultiPropertyChangedWithAdded() throws RepositoryException {
+        EventResult result = new EventResult(log);
+        Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("prop1", new String[] { "foo" });
+	foo.setProperty("prop2", new String[] { "bar" });
+        testRoot.save();
+	addEventListener(result, EventType.PROPERTY_CHANGED);
+	foo.getProperty("prop1").setValue(new String[] { "foobar" });
+	foo.getProperty("prop2").setValue(new String[] { "foobar" });
+	foo.setProperty("prop3", new String[] { "foo" }); // will not fire prop changed event
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyChanged(events, new String[] { "foo/prop1", "foo/prop2" });
+    }
+
+
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyRemovedTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/PropertyRemovedTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.observation.EventType;
+import javax.jcr.observation.Event;
+
+/**
+ * Test cases for {@link javax.jcr.observation.EventType#PROPERTY_REMOVED
+ * PROPERTY_REMOVED} events.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class PropertyRemovedTest extends AbstractObservationTest {
+
+    public void testSinglePropertyRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+	addEventListener(result, EventType.PROPERTY_REMOVED);
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("prop1", new String[] { "foo" });
+	foo.setProperty("prop2", new String[] { "bar" });
+	testRoot.save();
+	foo.remove("prop1");
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyRemoved(events, new String[] { "foo/prop1" });
+    }
+
+    public void testMultiPropertyRemoved() throws RepositoryException {
+        EventResult result = new EventResult(log);
+	addEventListener(result, EventType.PROPERTY_REMOVED);
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("prop1", new String[] { "foo" });
+	foo.setProperty("prop2", new String[] { "bar" });
+	testRoot.save();
+	foo.remove("prop1");
+	foo.remove("prop2");
+	testRoot.save();
+        removeEventListener(result);
+        Event[] events = result.getEvents(DEFAULT_WAIT_TIMEOUT);
+	checkPropertyRemoved(events, new String[] { "foo/prop1", "foo/prop2" });
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/TestAll.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/observation/TestAll.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.observation;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for the Observation module.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class TestAll extends TestCase {
+
+    /**
+     * Returns a <code>Test</code> suite that executes all tests inside this
+     * package.
+     *
+     * @return a <code>Test</code> suite that executes all tests inside this
+     * package.
+     */
+    public static Test suite() {
+	TestSuite suite = new TestSuite("Observation tests");
+
+	suite.addTestSuite(NodeAddedTest.class);
+	suite.addTestSuite(NodeRemovedTest.class);
+	suite.addTestSuite(PropertyAddedTest.class);
+	suite.addTestSuite(PropertyChangedTest.class);
+	suite.addTestSuite(PropertyRemovedTest.class);
+
+	return suite;
+    }
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.search;
+
+import org.apache.jackrabbit.test.AbstractTest;
+
+import javax.jcr.query.QueryResult;
+import javax.jcr.*;
+
+/**
+ * Abstract base class for query test cases.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class AbstractQueryTest extends AbstractTest {
+
+    /**
+     * Checks if the <code>result</code> contains a number of <code>hits</code>.
+     * @param result the <code>QueryResult</code>.
+     * @param hits the number of expected hits.
+     * @throws RepositoryException if an error occurs while iterating over
+     *  the result nodes.
+     */
+    protected void checkResult(QueryResult result, int hits)
+	    throws RepositoryException {
+	int count = 0;
+	log.info("Nodes:");
+	for (NodeIterator nodes = result.getNodes(); nodes.hasNext(); count++ ) {
+	    Node n = nodes.nextNode();
+	    log.info(" " + n.getPath());
+	}
+	if (count == 0) {
+	    log.info(" NONE");
+	}
+	assertEquals("Wrong hit count.", hits, count);
+    }
+
+    /**
+     * Checks if the <code>result</code> contains a number of <code>hits</code>
+     * and <code>properties</code>.
+     * @param result the <code>QueryResult</code>.
+     * @param hits the number of expected hits.
+     * @param properties the number of expected properties.
+     * @throws RepositoryException if an error occurs while iterating over
+     *  the result nodes.
+     */
+    protected void checkResult(QueryResult result, int hits, int properties)
+	    throws RepositoryException {
+	checkResult(result, hits);
+	// now check property count
+	int count = 0;
+	log.info("Properties:");
+	for (PropertyIterator it = result.getProperties(); it.hasNext(); count++ ) {
+	    StringBuffer msg = new StringBuffer();
+	    Property p = it.nextProperty();
+	    msg.append("  ").append(p.getName()).append(": ");
+	    Value[] values = null;
+	    if (p.getDefinition().isMultiple()) {
+		values = p.getValues();
+	    } else {
+		values = new Value[] { p.getValue() };
+	    }
+	    String sep = "";
+	    for (int i = 0; i < values.length; i++) {
+		msg.append(sep);
+		msg.append(values[i].getString());
+		sep = " | ";
+	    }
+	    log.info(msg);
+	}
+	if (count == 0) {
+	    log.info("  NONE");
+	}
+	assertEquals("Wrong property count.", properties, count);
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.search;
+
+import javax.jcr.Node;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+
+/**
+ * Performs tests with the <code>TEXTSEARCH</code> clause.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class FulltextQueryTest extends AbstractQueryTest {
+
+    public void testFulltextSimple() throws Exception {
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT +"// TEXTSEARCH \"fox\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+    }
+
+    public void testFulltextMultiWord() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "test text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "other text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// TEXTSEARCH \"fox test\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+    }
+
+    public void testFulltextPhrase() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "test text" });
+	n.setProperty("mytext", new String[] { "the quick brown jumps fox over the lazy dog." });
+
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "other text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// TEXTSEARCH \"text 'fox jumps'\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+    }
+
+    public void testFulltextExclude() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "test text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "other text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	superuser.getRootNode().save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// TEXTSEARCH \"text 'fox jumps' -other\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+    }
+
+    public void testFulltextOr() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "test text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "other text" });
+	n.setProperty("mytext", new String[] { "the quick brown fox jumps over the lazy dog." });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// TEXTSEARCH \"'fox jumps' test OR other\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2);
+    }
+
+    public void testFulltextIntercap() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "tEst text" });
+	n.setProperty("mytext", new String[] { "The quick brown Fox jumps over the lazy dog." });
+
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("title", new String[] { "Other text" });
+	n.setProperty("mytext", new String[] { "the quick brown FOX jumPs over the lazy dog." });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// TEXTSEARCH \"'fox juMps' Test OR otheR\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2);
+    }
+
+
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.search;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+
+/**
+ * Performs tests with on the <code>SELECT</code> clause.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class SelectClauseTest extends AbstractQueryTest {
+
+    public void testSelect() throws RepositoryException {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("myvalue", new String[] { "foo" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("myvalue", new String[] { "bar" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("yourvalue", new String[] { "foo" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT myvalue FROM * LOCATION /" + TEST_ROOT + "//";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT myvalue FROM * LOCATION /" + TEST_ROOT + "// WHERE yourvalue = \"foo\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 0);
+
+	jcrql = "SELECT myvalue FROM *";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+    }
+
+    public void testPropertyCount() throws RepositoryException {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("myvalue", new String[] { "foo" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("myvalue", new String[] { "bar" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("yourvalue", new String[] { "foo" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT myvalue FROM * LOCATION /" + TEST_ROOT + "//";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2, 2);
+
+	jcrql = "SELECT myvalue FROM * LOCATION /" + TEST_ROOT + "// WHERE yourvalue = \"foo\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 0, 0);
+
+	jcrql = "SELECT myvalue FROM *";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE myvalue LIKE \"*\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2, 4);
+    }
+
+    public void testSameNameSibling() throws RepositoryException {
+	Node n = testRoot.addNode("node", NT_UNSTRUCTURED);
+	n.setProperty("myvalue", new String[] { "foo" });
+	n = testRoot.addNode("node", NT_UNSTRUCTURED);
+	n.setProperty("myvalue", new String[] { "bar" });
+	n = testRoot.addNode("node", NT_UNSTRUCTURED);
+	n.setProperty("yourvalue", new String[] { "foo" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT myvalue FROM * LOCATION /" + TEST_ROOT + "/node";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2, 2);
+
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.search;
+
+import javax.jcr.*;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import java.util.Calendar;
+
+/**
+ * Performs various query test cases.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision: 1.4 $, $Date: 2004/06/28 14:28:15 $
+ */
+public class SimpleQueryTest extends AbstractQueryTest {
+
+
+    public void testSimpleQuery1() throws Exception {
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("bla", new String[] { "bla" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "/foo WHERE bla=\"bla\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+    }
+
+    public void testSimpleQuery2() throws Exception {
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("bla", new String[] { "bla" });
+	Node bla = superuser.getRootNode().addNode("bla", NT_UNSTRUCTURED);
+	bla.setProperty("bla", new String[] { "bla" });
+
+	superuser.getRootNode().save();
+
+	String jcrql = "SELECT * FROM nt:bla LOCATION /" + TEST_ROOT + "// WHERE bla=\"bla\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 0);
+    }
+
+    public void testSimpleQuery3() throws Exception {
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("bla", new String[] { "bla" });
+	Node bla = testRoot.addNode("bla", NT_UNSTRUCTURED);
+	bla.setProperty("bla", new String[] { "bla" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM nt:unstructured LOCATION /" + TEST_ROOT + "// WHERE bla=\"bla\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2);
+    }
+
+    public void testSimpleQuery4() throws Exception {
+	Node foo = testRoot.addNode("foo", NT_UNSTRUCTURED);
+	foo.setProperty("bla", new String[] { "bla" });
+	Node bla = testRoot.addNode("bla", NT_UNSTRUCTURED);
+	bla.setProperty("bla", new String[] { "bla" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM nt:unstructured LOCATION /" + TEST_ROOT + "//";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2);
+    }
+
+    public void testDateField1() throws Exception {
+	Node n = testRoot.addNode("marcel", NT_UNSTRUCTURED);
+	Calendar marcel = Calendar.getInstance();
+	marcel.set(1976, 4, 20, 15, 40);
+	n.setProperty("birth", new Value[] { new DateValue(marcel) });
+
+	n = testRoot.addNode("vanessa", NT_UNSTRUCTURED);
+	Calendar vanessa = Calendar.getInstance();
+	vanessa.set(1975, 4, 10, 13, 30);
+	n.setProperty("birth", new Value[] { new DateValue(vanessa) });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE birth > 1976-01-01T00:00:00.000+01:00";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE birth > 1975-01-01T00:00:00.000+01:00";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+    }
+
+    public void testDoubleField() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new Value[] { new DoubleValue(1.9928375d) });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new Value[] { new DoubleValue(0.0d) });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new Value[] { new DoubleValue(-1.42982475d) });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value > 0.1e-0";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value > -0.1";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value > -1.5";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+    }
+
+    public void testLongField() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new Value[] { new LongValue(1) });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new Value[] { new LongValue(0) });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new Value[] { new LongValue(-1) });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value > 0";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value > -1";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value > -2";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+    }
+
+    public void testLikePattern() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "king" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "ping" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "ching" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"ping\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"?ing\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"*ing\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"_ing\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"%ing\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+    }
+
+    public void testLikePatternBetween() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "ping" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "pong" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "puung" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"ping\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"p?ng\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"p*ng\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"p_ng\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"p%ng\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+    }
+
+    public void testLikePatternEnd() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "bli" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "bla" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "blub" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"bli\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"bl?\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"bl*\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"bl_\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"bl%\"";
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 3);
+    }
+
+    public void testLikePatternEscaped() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "foo\\?bar" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "foobar" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "foo?bar" });
+	n = testRoot.addNode("node4", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "foolbar" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"foo\\?bar\""; // matches node3
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 1);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"foo?bar\"";    // matches node3 and node4
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 2);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"foo*bar\"";  // matches all nodes
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 4);
+
+	jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value LIKE \"foo\\\\\\?bar\"";  // matches node1
+	q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	result = q.execute();
+	checkResult(result, 1);
+
+    }
+
+    public void testNotEqual() throws Exception {
+	Node n = testRoot.addNode("node1", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "foo" });
+	n = testRoot.addNode("node2", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "bar" });
+	n = testRoot.addNode("node3", NT_UNSTRUCTURED);
+	n.setProperty("value", new String[] { "foobar" });
+
+	testRoot.save();
+
+	String jcrql = "SELECT * FROM * LOCATION /" + TEST_ROOT + "// WHERE value <> \"bar\"";
+	Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+	QueryResult result = q.execute();
+	checkResult(result, 2);
+
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java	Tue Sep 28 07:42:38 2004
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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.search;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for the Search module.
+ *
+ * @author Marcel Reutegger
+ * @version $Revision:  $, $Date:  $
+ */
+public class TestAll extends TestCase {
+
+    /**
+     * Returns a <code>Test</code> suite that executes all tests inside this
+     * package.
+     *
+     * @return a <code>Test</code> suite that executes all tests inside this
+     * package.
+     */
+    public static Test suite() {
+	TestSuite suite = new TestSuite("Search tests");
+
+	suite.addTestSuite(SimpleQueryTest.class);
+	suite.addTestSuite(FulltextQueryTest.class);
+	suite.addTestSuite(SelectClauseTest.class);
+
+	return suite;
+    }
+}