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 2008/03/14 17:50:01 UTC

svn commit: r637157 [1/2] - in /jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core: ./ integration/ integration/random/ integration/random/operation/ integration/random/task/

Author: mreutegg
Date: Fri Mar 14 09:49:56 2008
New Revision: 637157

URL: http://svn.apache.org/viewvc?rev=637157&view=rev
Log:
JCR-1478: Perform random operation tests

Added:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/RandomOperationTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddNode.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddVersionLabel.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkin.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkout.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/CreateNodes.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetNode.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetRandomNodes.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Operation.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationFactory.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationSequence.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomContentOperations.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomOperations.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomVersionOperations.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Remove.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersion.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersionLabel.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Restore.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Save.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/SetProperty.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/TraverseNodes.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/VersionOperation.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/XATransaction.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/task/
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/task/ContentOperationsTask.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/task/RandomOperationsTask.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/task/VersionOperationsTask.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentCheckinMixedTransactionTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java?rev=637157&r1=637156&r2=637157&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java Fri Mar 14 09:49:56 2008
@@ -21,6 +21,8 @@
 import javax.jcr.Session;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
 
 /**
  * <code>AbstractConcurrencyTest</code> provides utility methods to run tests
@@ -37,22 +39,35 @@
      * @throws RepositoryException if an error occurs.
      */
     protected void runTask(Task task, int concurrency) throws RepositoryException {
-        Thread[] threads = new Thread[concurrency];
-        for (int i = 0; i < concurrency; i++) {
-            Session s = helper.getSuperuserSession();
-            Node test = s.getRootNode().addNode(testPath + "/node" + i);
-            s.save();
-            threads[i] = new Thread(new Executor(s, test, task));
-        }
-        for (int i = 0; i < threads.length; i++) {
-            threads[i].start();
-        }
-        for (int i = 0; i < threads.length; i++) {
-            try {
-                threads[i].join();
-            } catch (InterruptedException e) {
+        runTasks(new Task[]{task}, concurrency,
+                // run for at most one year ;)
+                getOneYearAhead());
+    }
+
+    /**
+     * Runs each of the tasks with the given concurrency and creates an
+     * individual test node for each thread.
+     *
+     * @param tasks       the tasks to run.
+     * @param concurrency the concurrency.
+     * @param timeout     when System.currentTimeMillis() reaches timeout the
+     *                    threads executing the tasks should be interrupted.
+     *                    This indicates that a deadlock occured.
+     * @throws RepositoryException if an error occurs.
+     */
+    protected void runTasks(Task[] tasks, int concurrency, long timeout)
+            throws RepositoryException {
+        Executor[] executors = new Executor[concurrency * tasks.length];
+        for (int t = 0; t < tasks.length; t++) {
+            for (int i = 0; i < concurrency; i++) {
+                int id = t * concurrency + i;
+                Session s = helper.getSuperuserSession();
+                Node test = s.getRootNode().addNode(testPath + "/node" + id);
+                s.save();
+                executors[id] = new Executor(s, test, tasks[t]);
             }
         }
+        executeAll(executors, timeout);
     }
 
     /**
@@ -65,25 +80,92 @@
      */
     protected void runTask(Task task, int concurrency, String path)
             throws RepositoryException {
-        Thread[] threads = new Thread[concurrency];
+        Executor[] executors = new Executor[concurrency];
         for (int i = 0; i < concurrency; i++) {
             Session s = helper.getSuperuserSession();
             Node test = (Node) s.getItem(path);
             s.save();
-            threads[i] = new Thread(new Executor(s, test, task));
+            executors[i] = new Executor(s, test, task);
+        }
+        executeAll(executors, getOneYearAhead());
+    }
+
+    /**
+     * Executes all executors using individual threads.
+     *
+     * @param executors the executors.
+     * @param timeout time when running threads should be interrupted.
+     * @throws RepositoryException if one of the executors throws an exception.
+     */
+    private void executeAll(Executor[] executors, long timeout) throws RepositoryException {
+        Thread[] threads = new Thread[executors.length];
+        for (int i = 0; i < executors.length; i++) {
+            threads[i] = new Thread(executors[i]);
         }
         for (int i = 0; i < threads.length; i++) {
             threads[i].start();
         }
+        boolean stacksDumped = false;
         for (int i = 0; i < threads.length; i++) {
             try {
-                threads[i].join();
+                long wait = Math.max(timeout - System.currentTimeMillis(), 1);
+                threads[i].join(wait);
+                if (threads[i].isAlive()) {
+                    if (!stacksDumped) {
+                        dumpStacks(threads);
+                        stacksDumped = true;
+                    }
+                    threads[i].interrupt();
+                    // give the thread a couple of seconds, then call stop
+                    Thread.sleep(5 * 1000);
+                    if (threads[i].isAlive()) {
+                        threads[i].stop();
+                    }
+                }
             } catch (InterruptedException e) {
-                e.printStackTrace();
+                // ignore
+            }
+        }
+        for (int i = 0; i < executors.length; i++) {
+            if (executors[i].getException() != null) {
+                throw executors[i].getException();
             }
         }
     }
 
+    protected long getOneYearAhead() {
+        return System.currentTimeMillis() + 1000L * 60L * 60L * 24L * 30L * 12L;
+    }
+
+    /**
+     * If tests are run in a 1.5 JVM or higher the stack of the given threads
+     * are dumped to system out.
+     */
+    protected static void dumpStacks(Thread[] threads) {
+        try {
+            Method m = Thread.class.getMethod("getStackTrace", null);
+            for (int t = 0; t < threads.length; t++) {
+                StackTraceElement[] elements = (StackTraceElement[]) m.invoke(
+                        threads[t], null);
+                System.out.println(threads[t]);
+                for (int i = 0; i < elements.length; i++) {
+                    System.out.println("\tat " + elements[i]);
+                }
+                System.out.println();
+            }
+        } catch (NoSuchMethodException e) {
+            // not a 1.5 JVM
+        } catch (IllegalAccessException e) {
+            // ignore
+        } catch (InvocationTargetException e) {
+            // ignore
+        }
+    }
+
+    /**
+     * Task implementations must be thread safe! Multiple threads will call
+     * {@link #execute(Session, Node)} concurrently.
+     */
     public interface Task {
 
         public abstract void execute(Session session, Node test)
@@ -98,17 +180,23 @@
 
         protected final Task task;
 
+        protected RepositoryException exception;
+
         public Executor(Session session, Node test, Task task) {
             this.session = session;
             this.test = test;
             this.task = task;
         }
 
+        public RepositoryException getException() {
+            return exception;
+        }
+
         public void run() {
             try {
                 task.execute(session, test);
             } catch (RepositoryException e) {
-                e.printStackTrace();
+                exception = e;
             } finally {
                 session.logout();
             }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentCheckinMixedTransactionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentCheckinMixedTransactionTest.java?rev=637157&r1=637156&r2=637157&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentCheckinMixedTransactionTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentCheckinMixedTransactionTest.java Fri Mar 14 09:49:56 2008
@@ -47,68 +47,54 @@
         final long end = System.currentTimeMillis() + RUN_NUM_SECONDS * 1000;
         // tasks with even ids run within transactions
         final int[] taskId = new int[1];
-        Thread t = new Thread(new Runnable() {
-            public void run() {
-                try {
-                    runTask(new Task() {
-                        public void execute(Session session, Node test)
-                                throws RepositoryException {
-                            int id;
-                            synchronized (ConcurrentCheckinMixedTransactionTest.this) {
-                                id = taskId[0]++;
-                            }
-                            int i = 0;
-                            while (end > System.currentTimeMillis()) {
-                                UserTransactionImpl uTx = null;
-                                try {
-                                    if (id % 2 == 0) {
-                                        uTx = new UserTransactionImpl(session);
-                                        uTx.begin();
-                                    }
-                                    Node n = test.addNode("node" + i++);
-                                    n.addMixin(mixVersionable);
-                                    session.save();
-                                    n.checkout();
-                                    n.checkin();
-                                    if (uTx != null) {
-                                        uTx.commit();
-                                    }
-                                } catch (NotSupportedException e) {
-                                    throw new RepositoryException(e);
-                                } catch (SystemException e) {
-                                    throw new RepositoryException(e);
-                                } catch (HeuristicMixedException e) {
-                                    throw new RepositoryException(e);
-                                } catch (HeuristicRollbackException e) {
-                                    throw new RepositoryException(e);
-                                } catch (RollbackException e) {
-                                    Throwable t = e;
-                                    do {
-                                        t = t.getCause();
-                                        if (t instanceof StaleItemStateException) {
-                                            break;
-                                        }
-                                    } while (t != null);
-                                    if (t == null) {
-                                        throw new RepositoryException(e);
-                                    }
-                                } catch (InvalidItemStateException e) {
-                                    // try again
-                                }
+        runTask(new Task() {
+            public void execute(Session session, Node test)
+                    throws RepositoryException {
+                int id;
+                synchronized (ConcurrentCheckinMixedTransactionTest.this) {
+                    id = taskId[0]++;
+                }
+                int i = 0;
+                while (end > System.currentTimeMillis()) {
+                    UserTransactionImpl uTx = null;
+                    try {
+                        if (id % 2 == 0) {
+                            uTx = new UserTransactionImpl(session);
+                            uTx.begin();
+                        }
+                        Node n = test.addNode("node" + i++);
+                        n.addMixin(mixVersionable);
+                        session.save();
+                        n.checkout();
+                        n.checkin();
+                        if (uTx != null) {
+                            uTx.commit();
+                        }
+                    } catch (NotSupportedException e) {
+                        throw new RepositoryException(e);
+                    } catch (SystemException e) {
+                        throw new RepositoryException(e);
+                    } catch (HeuristicMixedException e) {
+                        throw new RepositoryException(e);
+                    } catch (HeuristicRollbackException e) {
+                        throw new RepositoryException(e);
+                    } catch (RollbackException e) {
+                        Throwable t = e;
+                        do {
+                            t = t.getCause();
+                            if (t instanceof StaleItemStateException) {
+                                break;
                             }
+                        } while (t != null);
+                        if (t == null) {
+                            throw new RepositoryException(e);
                         }
-                    }, NUM_THREADS);
-                } catch (RepositoryException e) {
-                    exceptions.add(e);
+                    } catch (InvalidItemStateException e) {
+                        // try again
+                    }
                 }
             }
-        });
-        t.start();
-        try {
-            t.join();
-        } catch (InterruptedException e) {
-            // ignore
-        }
+        }, NUM_THREADS);
         if (!exceptions.isEmpty()) {
             fail(((RepositoryException) exceptions.get(0)).getMessage());
         }

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/RandomOperationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/RandomOperationTest.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/RandomOperationTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/RandomOperationTest.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration;
+
+import org.apache.jackrabbit.core.AbstractConcurrencyTest;
+import org.apache.jackrabbit.core.integration.random.task.VersionOperationsTask;
+import org.apache.jackrabbit.core.integration.random.task.ContentOperationsTask;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>RandomOperationTest</code> executes randomly chosen operations using
+ * multiple threads.
+ * Please note that this test is disabled by default!
+ * You can enable them by setting {@link #NUM_THREADS} to 1 or higher.
+ */
+public class RandomOperationTest extends AbstractConcurrencyTest {
+
+    /**
+     * Each task is executed with this number of threads.
+     */
+    private static final int NUM_THREADS = 0;
+
+    /**
+     * Tasks are advised to run for this amount of time.
+     */
+    private static final int RUN_NUM_SECONDS = 60;
+
+    /**
+     * Number of seconds to wait at most for the tasks to finish their work.
+     */
+    private static final int MAX_WAIT_SECONDS = 60;
+
+    /**
+     * Number of levels of test data to create per thread
+     */
+    private static final int NUM_LEVELS = 4;
+
+    /**
+     * Number of nodes per level
+     */
+    private static final int NODES_PER_LEVEL = 3;
+
+    private long end;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        end = System.currentTimeMillis() + RUN_NUM_SECONDS * 1000;
+    }
+
+    public void testRandomContentOperations() throws RepositoryException {
+        runTask(new ContentOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end), NUM_THREADS);
+    }
+
+    public void testRandomContentOperationsXA() throws RepositoryException {
+        ContentOperationsTask task = new ContentOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        task.setUseXA(true);
+        runTask(task, NUM_THREADS);
+    }
+
+    public void testRandomVersionOperations() throws RepositoryException {
+        runTask(new VersionOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end), NUM_THREADS);
+    }
+
+    public void testRandomVersionOperationsXA() throws RepositoryException {
+        VersionOperationsTask task = new VersionOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        task.setUseXA(true);
+        runTask(task, NUM_THREADS);
+    }
+
+    public void testContentAndVersionOperations() throws RepositoryException {
+        runTasks(new Task[]{
+            new ContentOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end),
+            new VersionOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end)
+        }, NUM_THREADS, end + MAX_WAIT_SECONDS * 1000);
+    }
+
+    public void testContentAndVersionOperationsXA() throws RepositoryException {
+        ContentOperationsTask task1 = new ContentOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        task1.setUseXA(true);
+        VersionOperationsTask task2 = new VersionOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        task2.setUseXA(true);
+        runTasks(new Task[]{task1, task2}, NUM_THREADS, end + MAX_WAIT_SECONDS * 1000);
+    }
+
+    public void testContentAndVersionOperationsXAMixed() throws RepositoryException {
+        ContentOperationsTask task1 = new ContentOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        ContentOperationsTask task2 = new ContentOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        task2.setUseXA(true);
+        VersionOperationsTask task3 = new VersionOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        VersionOperationsTask task4 = new VersionOperationsTask(NUM_LEVELS, NODES_PER_LEVEL, end);
+        task4.setUseXA(true);
+        runTasks(new Task[]{task1, task2, task3, task4}, NUM_THREADS, end + MAX_WAIT_SECONDS * 1000);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/RandomOperationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddNode.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddNode.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddNode.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import javax.jcr.Node;
+
+/**
+ * <code>AddNode</code> adds a node with a given name.
+ */
+public class AddNode extends Operation {
+
+    private static final Logger log = LoggerFactory.getLogger(AddNode.class);
+
+    private final String name;
+
+    public AddNode(Session s, String path, String name) {
+        super(s, path);
+        this.name = name;
+    }
+
+    /**
+     * Returns the node that was added.
+     */
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        log.info(n.getPath() + "/" + name);
+        return wrapWithIterator(getNode().addNode(name));
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddVersionLabel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddVersionLabel.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddVersionLabel.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddVersionLabel.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>AddVersionLabel</code> adds a random 3 character label to the base
+ * base version of the current node.
+ */
+public class AddVersionLabel extends VersionOperation {
+
+    private static final Logger log = LoggerFactory.getLogger(AddVersionLabel.class);
+
+    public AddVersionLabel(Session s, String path) {
+        super(s, path);
+    }
+
+    /**
+     * Returns the versionable node.
+     */ 
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        String name = n.getBaseVersion().getName();
+        String label = getRandomText(3);
+        log.info(n.getPath() + ":" + name + " -> " + label);
+        n.getVersionHistory().addVersionLabel(name, label, true);
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/AddVersionLabel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkin.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkin.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkin.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkin.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import javax.jcr.version.Version;
+
+/**
+ * <code>Checkin</code> calls checkin on the current node if it is not yet
+ * checked in.
+ */
+public class Checkin extends VersionOperation {
+
+    private static final Logger log = LoggerFactory.getLogger(Checkin.class);
+
+    public Checkin(Session s, String path) {
+        super(s, path);
+    }
+
+    /**
+     * Returns the versionable node.
+     */ 
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        if (n.isCheckedOut()) {
+            Version v = n.checkin();
+            log.info(n.getPath() + ":" + v.getName());
+        }
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkin.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkout.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkout.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkout.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkout.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>Checkout</code> performs a checkout on the current node if it is not
+ * yet checked out.
+ */
+public class Checkout extends VersionOperation {
+
+    private static final Logger log = LoggerFactory.getLogger(Checkout.class);
+
+    public Checkout(Session s, String path) {
+        super(s, path);
+    }
+
+    /**
+     * Returns the versionable node.
+     */ 
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        if (!n.isCheckedOut()) {
+            log.info(n.getPath() + ":" + n.getBaseVersion().getName());
+            n.checkout();
+        }
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Checkout.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/CreateNodes.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/CreateNodes.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/CreateNodes.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/CreateNodes.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * <code>CreateNodes</code> creates a node hierarchy with a given number of
+ * levels and nodes per level.
+ */
+public class CreateNodes extends Operation {
+
+    private static final Logger log = LoggerFactory.getLogger(CreateNodes.class);
+
+    private final int numLevels;
+
+    private final int nodesPerLevel;
+
+    private final String[] mixins;
+
+    public CreateNodes(Session s,
+                       String path,
+                       int numLevels,
+                       int nodesPerLevel,
+                       String[] mixins) {
+        super(s, path);
+        this.numLevels = numLevels;
+        this.nodesPerLevel = nodesPerLevel;
+        this.mixins = mixins;
+    }
+
+    /**
+     * Returns the top of the created node hierarchy.
+     */
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        addMixins(n);
+        createNodes(n, nodesPerLevel, numLevels, 0);
+        return wrapWithIterator(n);
+    }
+
+    private int createNodes(Node n, int nodesPerLevel, int levels, int count)
+            throws RepositoryException {
+        levels--;
+        for (int i = 0; i < nodesPerLevel; i++) {
+            Node child = n.addNode("node" + i);
+            addMixins(child);
+            log.info("Create node {}", child.getPath());
+            if (count % 1000 == 0) {
+                getSession().save();
+                log.debug("Created " + (count / 1000) + "k nodes");
+            }
+            if (levels > 0) {
+                count = createNodes(child, nodesPerLevel, levels, count);
+            }
+        }
+        if (levels == 0) {
+            // final save
+            getSession().save();
+        }
+        return count;
+    }
+
+    private void addMixins(Node node) throws RepositoryException {
+        for (int i = 0; i < mixins.length; i++) {
+            if (!node.isNodeType(mixins[i])) {
+                node.addMixin(mixins[i]);
+            }
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/CreateNodes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetNode.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetNode.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetNode.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import javax.jcr.Node;
+
+/**
+ * <code>GetNode</code> returns the node at the given path.
+ */
+public class GetNode extends Operation {
+
+    public GetNode(Session s, String path) {
+        super(s, path);
+    }
+
+    /**
+     * Returns the node at the given path.
+     */ 
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetRandomNodes.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetRandomNodes.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetRandomNodes.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetRandomNodes.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * <code>GetRandomNodes</code> randomly returns nodes that were returned by
+ * the parent operation.
+ */
+public class GetRandomNodes extends Operation {
+
+    private final Operation op;
+
+    public GetRandomNodes(Session s, Operation op) {
+        super(s, "/");
+        this.op = op;
+    }
+
+    /**
+     * Randomly returns node from the parent operation. Please note that the
+     * returned iterator runs forever!!!
+     * {@link NodeIterator#hasNext()} will always return true.
+     */
+    public NodeIterator execute() throws Exception {
+        final List paths = new ArrayList();
+        for (NodeIterator it = op.execute(); it.hasNext(); ) {
+            paths.add(it.nextNode().getPath());
+        }
+        return new NodeIteratorAdapter(new Iterator() {
+
+            public boolean hasNext() {
+                // runs forever!!!
+                return true;
+            }
+
+            public Object next() {
+                String path = (String) paths.get(getRandom().nextInt(paths.size()));
+                try {
+                    return getSession().getItem(path);
+                } catch (RepositoryException e) {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        });
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/GetRandomNodes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Operation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Operation.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Operation.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Operation.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.util.Collections;
+import java.util.Random;
+
+/**
+ * <code>Operation</code> is the common base class for all operations.
+ */
+public abstract class Operation {
+
+    private final Random rand = new Random();
+
+    private boolean useTransaction = false;
+
+    private int maxRandomWait = 0;
+
+    private final Session session;
+
+    private final String path;
+
+    public Operation(Session s, String path) {
+        this.session = s;
+        this.path = path;
+    }
+
+    public abstract NodeIterator execute() throws Exception;
+
+    public boolean isUseTransaction() {
+        return useTransaction;
+    }
+
+    public void setUseTransaction(boolean useTransaction) {
+        this.useTransaction = useTransaction;
+    }
+
+    protected Session getSession() {
+        return session;
+    }
+
+    protected String getPath() {
+        return path;
+    }
+
+    protected Item getItem() throws RepositoryException {
+        return session.getItem(path);
+    }
+
+    protected Node getNode() throws RepositoryException {
+        return (Node) getItem();
+    }
+
+    /**
+     * Do a random wait. See also {@link #setMaxRandomWait(int)}.
+     */
+    protected void randomWait() throws Exception {
+        if (maxRandomWait > 0) {
+            Thread.sleep(rand.nextInt(maxRandomWait));
+        }
+    }
+
+    /**
+     * @return the maximum number of milliseconds to wait when doing a
+     *         randomized wait.
+     */
+    public int getMaxRandomWait() {
+        return maxRandomWait;
+    }
+
+    /**
+     * @param maxRandomWait the maximum number of milliseconds to wait when
+     *                      doing a randomized wait.
+     */
+    public void setMaxRandomWait(int maxRandomWait) {
+        this.maxRandomWait = maxRandomWait;
+    }
+
+    /**
+     * Wraps a single node with a node iterator.
+     *
+     * @param node the node to wrap.
+     * @return a node iterator over the single <code>node</code>.
+     */
+    protected static NodeIterator wrapWithIterator(Node node) {
+        return new NodeIteratorAdapter(Collections.singletonList(node));
+    }
+
+    protected String getRandomText(int numChars) {
+        StringBuffer tmp = new StringBuffer(numChars);
+        for (int i = 0; i < numChars; i++) {
+            char c = (char) (rand.nextInt(('z' + 1) - 'a') + 'a');
+            tmp.append(c);
+        }
+        return tmp.toString();
+    }
+
+    protected Random getRandom() {
+        return rand;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Operation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationFactory.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationFactory.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationFactory.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Arrays;
+
+/**
+ * <code>OperationFactory</code> hides operation instantiation.
+ */
+public class OperationFactory {
+
+    private final Random rand = new Random();
+
+    private final Session session;
+
+    private int nodeCount = 0;
+
+    public OperationFactory(Session s) {
+        this.session = s;
+    }
+
+    /**
+     * Creates a series of random content operations using <code>nodes</code> as
+     * a source of nodes to operate on.
+     */
+    public Operation randomContentOperations(NodeIterator nodes,
+                                             int minOperations,
+                                             int maxOperations)
+            throws Exception {
+        return new RandomContentOperations(this, session, nodes,
+                minOperations + rand.nextInt(maxOperations - minOperations));
+    }
+
+    /**
+     * Creates random operations for all the nodes <code>op</code> returns on
+     * {@link Operation#execute()}.
+     */
+    public Operation randomContentOperation(Operation op) throws Exception {
+        NodeIterator it = op.execute();
+        List ops = new ArrayList();
+        while (it.hasNext()) {
+            Node n = it.nextNode();
+            String path = n.getPath();
+            switch (rand.nextInt(3)) { // TODO keep in sync with case list
+                case 0:
+                    ops.add(new AddNode(session, path, "payload" + nodeCount++));
+                    break;
+                case 1:
+                    // limit to 10 distinct properties
+                    ops.add(new SetProperty(session, path, "prop" + rand.nextInt(10)));
+                    break;
+                case 2:
+                    ops.add(new Remove(session, path, "payload"));
+                    break;
+            }
+        }
+        if (ops.size() == 1) {
+            return (Operation) ops.get(0);
+        } else {
+            OperationSequence sequence = new OperationSequence(session, ops);
+            return sequence;
+        }
+    }
+
+    /**
+     * Creates a series of random version operations using <code>nodes</code> as
+     * a source of nodes to operate on.
+     */
+    public Operation randomVersionOperations(NodeIterator nodes,
+                                             int minOperations,
+                                             int maxOperations)
+            throws Exception {
+        return new RandomVersionOperations(this, session, nodes,
+                minOperations + rand.nextInt(maxOperations - minOperations));
+    }
+
+    /**
+     * Creates random operations for all the nodes <code>op</code> returns on
+     * {@link Operation#execute()}.
+     */
+    public Operation randomVersionOperation(Operation op) throws Exception {
+        NodeIterator it = op.execute();
+        List ops = new ArrayList();
+        while (it.hasNext()) {
+            Node n = it.nextNode();
+            String path = n.getPath();
+            switch (rand.nextInt(6)) { // TODO keep in sync with case list
+                case 0:
+                    ops.add(new Checkin(session, path));
+                    break;
+                case 1:
+                    ops.add(new Checkout(session, path));
+                    break;
+                case 2:
+                    //ops.add(new Restore(session, path));
+                    break;
+                case 3:
+                    ops.add(new AddVersionLabel(session, path));
+                    break;
+                case 4:
+                    ops.add(new RemoveVersionLabel(session, path));
+                    break;
+                case 5:
+                    ops.add(new RemoveVersion(session, path));
+                    break;
+            }
+        }
+        if (ops.size() == 1) {
+            return (Operation) ops.get(0);
+        } else {
+            OperationSequence sequence = new OperationSequence(session, ops);
+            return sequence;
+        }
+    }
+
+    /**
+     * Wraps an XA transaction operation around <code>op</code>.
+     */
+    public Operation runInTransaction(Operation op) {
+        return new XATransaction(session, op);
+    }
+
+    /**
+     * Creates a new operation that contains the passed <code>ops</code>.
+     */
+    public Operation runInSequence(Operation[] ops) {
+        return new OperationSequence(session, Arrays.asList(ops));
+    }
+
+    /**
+     * Creates a save operation on the node with the given path.
+     */
+    public Operation save(String path) {
+        return new Save(session, path);
+    }
+
+    /**
+     * Creates an operation the return the node with the given <code>path</code>.
+     */
+    public Operation getNode(String path) {
+         return new GetNode(session, path);
+    }
+
+    /**
+     * Creates an operation that returns all nodes that are visited by traversing
+     * the node hierarchy starting at the node with the given <code>path</code>.
+     */
+    public Operation traverseNodes(String path) {
+         return new TraverseNodes(session, path);
+    }
+
+    /**
+     * Creates a node hierarchy.
+     */
+    public Operation createNodes(String path,
+                                 int numLevels,
+                                 int nodesPerLevel,
+                                 String[] mixins) {
+        return new CreateNodes(session, path, numLevels, nodesPerLevel, mixins);
+    }
+
+    /**
+     * Creates an iterator that randomly returns nodes produced by <code>op</code>.
+     * Please note that the returned iterator always returns <code>true</code>
+     * for {@link NodeIterator#hasNext()}!!!
+     */
+    public NodeIterator getRandomNodes(Operation op) throws Exception {
+        return new GetRandomNodes(session, op).execute();
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationSequence.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationSequence.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationSequence.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationSequence.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import java.util.List;
+
+/**
+ * <code>OperationSequence</code> wraps other operations and executes the in
+ * sequence.
+ */
+public class OperationSequence extends Operation {
+
+    private final Operation[] ops;
+
+    public OperationSequence(Session s, List operations) {
+        super(s, "/");
+        this.ops = (Operation[]) operations.toArray(new Operation[operations.size()]);
+    }
+
+    public NodeIterator execute() throws Exception {
+        IteratorChain chain = new IteratorChain();
+        for (int i = 0; i < ops.length; i++) {
+            chain.addIterator(ops[i].execute());
+        }
+        return new NodeIteratorAdapter(chain);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/OperationSequence.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomContentOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomContentOperations.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomContentOperations.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomContentOperations.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import javax.jcr.Session;
+import javax.jcr.NodeIterator;
+
+/**
+ * <code>RandomContentOperations</code> executes a number of content operations.
+ */
+public class RandomContentOperations extends RandomOperations {
+
+    public RandomContentOperations(OperationFactory factory,
+                 Session s,
+                 NodeIterator op,
+                 int numOperations) {
+        super(factory, s, op, numOperations);
+    }
+
+    public NodeIterator execute() throws Exception {
+        return super.execute();
+    }
+
+    protected Operation getRandomOperation(String path) throws Exception {
+        OperationFactory f = getFactory();
+        return f.randomContentOperation(f.getNode(path));
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomContentOperations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomOperations.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomOperations.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomOperations.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <code>RandomOperations</code> is an abstract base class for a set of random
+ * operation.
+ */
+public abstract class RandomOperations extends Operation {
+
+    private final OperationFactory factory;
+
+    private final NodeIterator nodes;
+
+    private final int numOperations;
+
+    public RandomOperations(OperationFactory factory,
+                            Session s,
+                            NodeIterator nodes,
+                            int numOperations) {
+        super(s, "/");
+        this.factory = factory;
+        this.nodes = nodes;
+        this.numOperations = numOperations;
+    }
+
+    public NodeIterator execute() throws Exception {
+        List operations = new ArrayList();
+        for (int i = 0; i < numOperations && nodes.hasNext(); i++) {
+            Node n = nodes.nextNode();
+            operations.add(getRandomOperation(n.getPath()));
+        }
+        return new OperationSequence(getSession(), operations).execute();
+    }
+
+    protected int getNumOperations() {
+        return numOperations;
+    }
+
+    protected OperationFactory getFactory() {
+        return factory;
+    }
+
+    protected abstract Operation getRandomOperation(String path) throws Exception;
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomOperations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomVersionOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomVersionOperations.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomVersionOperations.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomVersionOperations.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import javax.jcr.Session;
+import javax.jcr.NodeIterator;
+
+/**
+ * <code>RandomVersionOperations</code> executes a number of version operations.
+ */
+public class RandomVersionOperations extends RandomOperations {
+
+    public RandomVersionOperations(OperationFactory factory,
+                 Session s,
+                 NodeIterator nodes,
+                 int numOperations) {
+        super(factory, s, nodes, numOperations);
+    }
+
+    public NodeIterator execute() throws Exception {
+        return super.execute();
+    }
+
+    protected Operation getRandomOperation(String path) throws Exception {
+        OperationFactory f = getFactory();
+        return f.randomVersionOperation(f.getNode(path));
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RandomVersionOperations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Remove.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Remove.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Remove.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Remove.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>Remove</code> performs a remove of a node if its name starts with a
+ * given prefix.
+ */
+public class Remove extends Operation {
+
+    private static final Logger log = LoggerFactory.getLogger(Remove.class);
+
+    private final String namePrefix;
+
+    public Remove(Session s, String path, String namePrefix) {
+        super(s, path);
+        this.namePrefix = namePrefix;
+    }
+
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        for (NodeIterator it = n.getNodes(); it.hasNext(); ) {
+            Node r = it.nextNode();
+            if (r.getName().startsWith(namePrefix)) {
+                log.info(r.getPath());
+                r.remove();
+                break;
+            }
+        }
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Remove.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersion.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersion.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersion.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersion.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Session;
+import javax.jcr.NodeIterator;
+import javax.jcr.Node;
+import javax.jcr.version.Version;
+
+/**
+ * <code>RemoveVersion</code> removes a version.
+ */
+public class RemoveVersion extends VersionOperation {
+
+    private static final Logger log = LoggerFactory.getLogger(RemoveVersion.class);
+
+    public RemoveVersion(Session s, String path) {
+        super(s, path);
+    }
+
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        Version v = getRandomVersion(true);
+        // TODO: for now only remove version without labels, see: JCR-1475
+        if (v != null && v.getContainingHistory().getVersionLabels(v).length == 0) {
+            log.info(n.getPath() + ":" + v.getName());
+            n.getVersionHistory().removeVersion(v.getName());
+        }
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersion.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersionLabel.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersionLabel.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersionLabel.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersionLabel.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Session;
+import javax.jcr.NodeIterator;
+import javax.jcr.Node;
+import javax.jcr.version.VersionHistory;
+
+/**
+ * <code>RemoveVersionLabel</code> removes a randomly chosen version label on
+ * the version history of the current node.
+ */
+public class RemoveVersionLabel extends VersionOperation {
+
+    private static final Logger log = LoggerFactory.getLogger(RemoveVersionLabel.class);
+
+    public RemoveVersionLabel(Session s, String path) {
+        super(s, path);
+    }
+
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        VersionHistory vh = n.getVersionHistory();
+        String[] labels = vh.getVersionLabels();
+        if (labels.length > 0) {
+            String label = labels[getRandom().nextInt(labels.length)];
+            log.info(n.getPath() + " -> " + label);
+            vh.removeVersionLabel(label);
+        }
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/RemoveVersionLabel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Restore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Restore.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Restore.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Restore.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import javax.jcr.version.Version;
+
+/**
+ * <code>Restore</code>...
+ */
+public class Restore extends VersionOperation {
+
+    private static final Logger log = LoggerFactory.getLogger(Restore.class);
+
+    public Restore(Session s, String path) {
+        super(s, path);
+    }
+
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        Version v = getRandomVersion(false);
+        // TODO: for now only call restore on non-base versions. See: JCR-1476
+        if (v != null && !n.getBaseVersion().isSame(v)) {
+            log.info(n.getPath() + ":" + v.getName());
+            n.restore(v, true);
+        }
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Restore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Save.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Save.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Save.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Save.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>Save</code> performs a {@link Node#save()} on the current node.
+ */
+public class Save extends Operation {
+
+    private static final Logger log = LoggerFactory.getLogger(Save.class);
+
+    public Save(Session s, String path) {
+        super(s, path);
+    }
+
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        log.info(n.getPath());
+        n.save();
+        return wrapWithIterator(n);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/Save.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/SetProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/SetProperty.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/SetProperty.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/SetProperty.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>SetProperty</code> sets a string property with a random text of length
+ * 5.
+ */
+public class SetProperty extends Operation {
+
+    private static final Logger log = LoggerFactory.getLogger(SetProperty.class);
+
+    private final String name;
+
+    public SetProperty(Session s, String path, String name) {
+        super(s, path);
+        this.name = name;
+    }
+
+    public NodeIterator execute() throws Exception {
+        Node n = getNode();
+        String value = getRandomText(5);
+        String path = n.setProperty(name, value).getPath();
+        log.info(path + ": " + value);
+        return wrapWithIterator(getNode());
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/SetProperty.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/TraverseNodes.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/TraverseNodes.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/TraverseNodes.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/TraverseNodes.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
+import org.apache.jackrabbit.commons.packaging.FilterContentPackage;
+import org.apache.jackrabbit.commons.predicate.IsNodePredicate;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+
+/**
+ * <code>TraverseNodes</code> traverses a node hierarchy.
+ */
+public class TraverseNodes extends Operation {
+
+    public TraverseNodes(Session s, String path) {
+        super(s, path);
+    }
+
+    public NodeIterator execute() throws Exception {
+        FilterContentPackage pack = new FilterContentPackage();
+        pack.addContent(getPath(), new IsNodePredicate());
+        return new NodeIteratorAdapter(pack.getItems(getSession()));
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/TraverseNodes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/VersionOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/VersionOperation.java?rev=637157&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/VersionOperation.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/VersionOperation.java Fri Mar 14 09:49:56 2008
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.core.integration.random.operation;
+
+import javax.jcr.Session;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.VersionIterator;
+import javax.jcr.version.Version;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * <code>VersionOperation</code> is a base class for all version operations.
+ */
+public abstract class VersionOperation extends Operation {
+
+    public VersionOperation(Session s, String path) {
+        super(s, path);
+    }
+
+    /**
+     * Returns a randomly chosen version for the current node or
+     * <code>null</code> if the current node only has a root version.
+     *
+     * @param excludeReferenced exclude versions that are still referenced.
+     * @return randomly chosen version or <code>null</code>.
+     * @throws RepositoryException if an error occurs while reading from the
+     *                             repository.
+     */
+    protected Version getRandomVersion(boolean excludeReferenced) throws RepositoryException {
+        List allVersions = new ArrayList();
+        for (VersionIterator it = getNode().getVersionHistory().getAllVersions(); it.hasNext(); ) {
+            Version v = it.nextVersion();
+            if (v.getPredecessors().length > 0) {
+                if (!excludeReferenced || !v.getReferences().hasNext()) {
+                    allVersions.add(v);
+                }
+            }
+        }
+        if (allVersions.size() > 0) {
+            return (Version) allVersions.get(getRandom().nextInt(allVersions.size()));
+        } else {
+            return null;
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/random/operation/VersionOperation.java
------------------------------------------------------------------------------
    svn:eol-style = native