Index: /Users/marett/Documents/Workspace/jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/MoveSynchroWebDavTest.java =================================================================== --- /Users/marett/Documents/Workspace/jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/MoveSynchroWebDavTest.java (revision 0) +++ /Users/marett/Documents/Workspace/jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/MoveSynchroWebDavTest.java (revision 0) @@ -0,0 +1,247 @@ +package org.apache.jackrabbit.jcr2dav; + +import org.apache.jackrabbit.core.PropertyImpl; +import org.apache.jackrabbit.test.AbstractJCRTest; +import org.apache.jackrabbit.test.RepositoryStub; +import org.apache.jackrabbit.test.RepositoryStubException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.ValueFactory; +import javax.jcr.nodetype.NodeType; +import java.util.Calendar; +import java.util.Collections; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + + +public class MoveSynchroWebDavTest extends AbstractJCRTest { + + private static Logger log = LoggerFactory.getLogger(MoveSynchroWebDavTest.class); + + static final long MAX_WAIT_TIME_IN_MS = 60000; // 60s + + static final long MAX_SYNCH_TIME_IN_MS = 10000; // 10s + + /** + * TODO + */ + public void testMovePropagation() throws Exception { + + final ExecutorService executor = Executors.newFixedThreadPool(4); + final String nodeTest = "a" + Math.random() + "z"; + final Context c = new Context(); + try{ + executor.submit(new P1(c, nodeTest)); + final Future fp2 = executor.submit(new P2(c, nodeTest)); + fp2.get(MAX_WAIT_TIME_IN_MS, TimeUnit.MILLISECONDS); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw e; + } finally { + executor.shutdown(); + } + } + + // + + private class P1 extends Process implements Callable { + + P1(Context context, String nodeTest) throws RepositoryStubException { + super(context, nodeTest); + } + + public Integer call() throws Exception { + Session session = null; + try { + // 0. Get a session + session = getReadWriteSession(); + // 1. Create initial content + buildInitialTree(session); + // 2. Check initial content + assertTrue(checkInitialTree(session)); + // 3. Notify initial content is ready + context.release(context.contentReady); + // 4. Wait that other checks are done + assertTrue(context.block(context.checkDone)); + // 3. move node + moveNode(session); + // 4. Check after move + assertTrue(checkMovedTree(session)); + // 5. notify node moved + context.release(context.modeDone); + // done + } catch (Exception e){ + throw e; + } finally { + releaseSession(session); + } + return 0; + } + } + + // + + private class P2 extends Process implements Callable { + + P2(final Context context, String nodeTest) throws RepositoryStubException { + super(context, nodeTest); + } + + + public Integer call() throws Exception { + Session session1 = null; + Session session2 = null; + try { + // 0. Get a session + session1 = getReadWriteSession(); + // 1. Wait that initial content is ready + assertTrue(context.block(context.contentReady)); + // 2. Check for initial content + checkInitialTree(session1); + // 3. Notify Check is done + context.release(context.checkDone); + // 4. Wait that the move operation is completed + context.block(context.modeDone); + // 5. Get a session + session2 = getReadWriteSession(); + // 5. Check moved content on new session + assertTrue(checkMovedTree(session2)); + // done + } catch (Exception e){ + throw e; + } finally { + releaseSession(session1); + releaseSession(session2); + } + return 0; + } + } + + // + + private class Context { + + CountDownLatch contentReady = new CountDownLatch(1); + CountDownLatch checkDone = new CountDownLatch(1); + CountDownLatch modeDone = new CountDownLatch(1); + + void release (CountDownLatch l) { + l.countDown(); + } + + boolean block (CountDownLatch l) throws InterruptedException { + return l.await(MAX_SYNCH_TIME_IN_MS, TimeUnit.MILLISECONDS); + } + + } + + // + + private class Process { + + //static final String NODE_TEST = "nodetest"; + + final String NODE_SUB = "sub"; + + final String NODE_FILE = "myfile"; + + final String NODE_CONTENT = "jcr:content"; + + final String PROPERTY_NAME = PropertyImpl.JCR_LAST_MODIFIED; + + final Calendar PROPERTY_VALUE = Calendar.getInstance(); + + final RepositoryStub stub ; + + final String nodeTest; + + Repository repository; + + final Context context; + + Process(Context context, String nodeTest) throws RepositoryStubException { + this.stub = RepositoryStub.getInstance(Collections.EMPTY_MAP); + this.nodeTest = nodeTest; + this.context = context; + getRepository(); + } + + Repository getRepository() throws RepositoryStubException { + if (repository == null) { + repository = stub.getRepository(); + } + return repository; + } + + Session getReadWriteSession() throws RepositoryStubException, RepositoryException { + return getRepository().login(stub.getReadWriteCredentials(), null); + } + + void releaseSession(Session session){ + if (session != null) { + session.logout(); + } + } + + // + + void buildInitialTree(Session session) throws RepositoryException { + final Node root = session.getRootNode(); + if (root.hasNode(nodeTest)) { + root.getNode(nodeTest).remove(); + session.save(); + } + final Node test = root.addNode(nodeTest, NodeType.NT_FOLDER); + final Node file = test.addNode(NODE_FILE, NodeType.NT_FILE); + final Node content = file.addNode(NODE_CONTENT, NodeType.NT_UNSTRUCTURED); + final ValueFactory valueFactory = session.getValueFactory(); + content.setProperty(PROPERTY_NAME, valueFactory.createValue(PROPERTY_VALUE)); + test.addNode(NODE_SUB, NodeType.NT_FOLDER); + session.save(); + } + + boolean checkInitialTree(Session session) throws RepositoryException { + final Node root = session.getRootNode(); + root.getNode(nodeTest); + root.getNode(nodeTest + "/" + NODE_FILE); + root.getNode(nodeTest + "/" + NODE_FILE + "/" + NODE_CONTENT); + root.getNode(nodeTest + "/" + NODE_SUB); + root.getProperty(nodeTest + "/" + NODE_FILE + "/" + NODE_CONTENT + "/" + PROPERTY_NAME); + return true; + } + + boolean checkMovedTree(Session session) throws RepositoryException { + final Node root = session.getRootNode(); + root.getNode(nodeTest); + root.getNode(nodeTest + "/" + NODE_SUB); + root.getNode(nodeTest + "/" + NODE_SUB + "/" + NODE_FILE); + root.getNode(nodeTest + "/" + NODE_SUB + "/" + NODE_FILE + "/" + NODE_CONTENT); + root.getProperty(nodeTest + "/" + NODE_SUB + "/" + NODE_FILE + "/" + NODE_CONTENT + "/" + PROPERTY_NAME); + try { + root.getNode(nodeTest + "/" + NODE_FILE); + return false; + } catch(Exception e){ + // OK + } + return true; + } + + void moveNode(Session session) throws RepositoryException { + final String srcPath = "/" + nodeTest + "/" + NODE_FILE ; + final String dstPath = "/" + nodeTest + "/" + NODE_SUB + "/" + NODE_FILE ; + session.move(srcPath, dstPath); + session.save(); + } + + } + +} Property changes on: /Users/marett/Documents/Workspace/jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/MoveSynchroWebDavTest.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native