You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2013/12/05 17:53:00 UTC

svn commit: r1548204 - in /jackrabbit/oak/trunk/oak-jcr: pom.xml src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationRefreshTest.java

Author: tripod
Date: Thu Dec  5 16:53:00 2013
New Revision: 1548204

URL: http://svn.apache.org/r1548204
Log:
OAK-1262 observation event is triggered but session sees old content

- adding test case

Added:
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationRefreshTest.java
Modified:
    jackrabbit/oak/trunk/oak-jcr/pom.xml

Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1548204&r1=1548203&r2=1548204&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Thu Dec  5 16:53:00 2013
@@ -77,6 +77,8 @@
       org.apache.jackrabbit.test.api.observation.NodeReorderTest#testNodeReorderSameName           <!-- Uses SNS -->
       org.apache.jackrabbit.test.api.observation.NodeReorderTest#testNodeReorderSameNameWithRemove <!-- Uses SNS -->
       org.apache.jackrabbit.core.observation.ReorderTest                                           <!-- Uses SNS -->
+        
+      org.apache.jackrabbit.oak.jcr.observation.ObservationRefreshTest <!-- [tripod] currently too slow...will fix soon -->
 
       <!-- Versioning -->
       org.apache.jackrabbit.test.api.version.VersionTest#testUpdate

Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationRefreshTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationRefreshTest.java?rev=1548204&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationRefreshTest.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationRefreshTest.java Thu Dec  5 16:53:00 2013
@@ -0,0 +1,302 @@
+/*
+ * 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.oak.jcr.observation;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeTemplate;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
+import org.apache.jackrabbit.oak.jcr.NodeStoreFixture;
+import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
+import org.apache.jackrabbit.test.api.util.Text;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static javax.jcr.observation.Event.NODE_ADDED;
+import static javax.jcr.observation.Event.NODE_MOVED;
+import static javax.jcr.observation.Event.NODE_REMOVED;
+import static javax.jcr.observation.Event.PERSIST;
+import static javax.jcr.observation.Event.PROPERTY_ADDED;
+import static javax.jcr.observation.Event.PROPERTY_CHANGED;
+import static javax.jcr.observation.Event.PROPERTY_REMOVED;
+import static org.junit.Assert.assertEquals;
+
+public class ObservationRefreshTest extends AbstractRepositoryTest {
+    public static final int ALL_EVENTS = NODE_ADDED | NODE_REMOVED | NODE_MOVED | PROPERTY_ADDED |
+            PROPERTY_REMOVED | PROPERTY_CHANGED | PERSIST;
+    private static final String TEST_NODE = "test_node";
+    private static final String REFERENCEABLE_NODE = "\"referenceable\"";
+    private static final String TEST_PATH = '/' + TEST_NODE;
+    private static final String TEST_TYPE = "mix:test";
+
+    private static final long CONDITION_TIMEOUT = 30000;
+
+    private Session observingSession;
+    private ObservationManager observationManager;
+
+    public ObservationRefreshTest(NodeStoreFixture fixture) {
+        super(fixture);
+    }
+
+    @Before
+    public void setup() throws RepositoryException {
+        Session session = getAdminSession();
+
+        NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager();
+        NodeTypeTemplate mixTest = ntMgr.createNodeTypeTemplate();
+        mixTest.setName(TEST_TYPE);
+        mixTest.setMixin(true);
+        ntMgr.registerNodeType(mixTest, false);
+
+        Node n = session.getRootNode().addNode(TEST_NODE);
+        n.addMixin(TEST_TYPE);
+        Node refNode = n.addNode(REFERENCEABLE_NODE);
+        refNode.addMixin(JcrConstants.MIX_REFERENCEABLE);
+
+        session.save();
+
+        Map<String,Object> attrs = new HashMap<String, Object>();
+        attrs.put(RepositoryImpl.REFRESH_INTERVAL, 0);
+        observingSession = ((JackrabbitRepository) getRepository()).login(new SimpleCredentials("admin", "admin".toCharArray()), null, attrs);
+        observationManager = observingSession.getWorkspace().getObservationManager();
+    }
+
+    @After
+    public void tearDown() {
+        observingSession.logout();
+    }
+
+    @Test
+    public void observation() throws RepositoryException, InterruptedException, ExecutionException {
+        final MyListener listener = new MyListener();
+        observationManager.addEventListener(listener, ALL_EVENTS, "/", true, null, null, false);
+        try {
+            Node n = getAdminSession().getNode(TEST_PATH);
+            for (int i=0; i<1000; i++) {
+                n.addNode("n" + i);
+                n.getSession().save();
+            }
+            Timer.waitFor(CONDITION_TIMEOUT, new Condition() {
+                @Override
+                public boolean evaluate() {
+                    return listener.numAdded == 1000;
+                }
+            });
+            assertEquals("", listener.error);
+            assertEquals("added nodes", 1000, listener.numAdded);
+
+            for (int i=0; i<1000; i++) {
+                n.getNode("n" + i).remove();
+                n.getSession().save();
+            }
+            Timer.waitFor(CONDITION_TIMEOUT , new Condition() {
+                @Override
+                public boolean evaluate() {
+                    return listener.numRemoved == 1000;
+                }
+            });
+            assertEquals("", listener.error);
+            assertEquals("removed nodes", 1000, listener.numRemoved);
+
+            for (int i=0; i<100; i++) {
+                n.setProperty("test" + i, "foo");
+                n.getSession().save();
+            }
+            Timer.waitFor(CONDITION_TIMEOUT , new Condition() {
+                @Override
+                public boolean evaluate() {
+                    return listener.numPropsAdded == 1100;
+                }
+            });
+            assertEquals("", listener.error);
+            assertEquals("properties added", 1100, listener.numPropsAdded);
+
+            for (int i=0; i<100; i++) {
+                n.setProperty("test" + i, i);
+                n.getSession().save();
+            }
+            Timer.waitFor(CONDITION_TIMEOUT , new Condition() {
+                @Override
+                public boolean evaluate() {
+                    return listener.numPropsModified == 100;
+                }
+            });
+            assertEquals("", listener.error);
+            assertEquals("properties modified", 100, listener.numPropsModified);
+
+            for (int i=0; i<10; i++) {
+                n.setProperty("test100", "foo");
+                n.getSession().save();
+                Timer.waitFor(CONDITION_TIMEOUT, new Condition() {
+                    @Override
+                    public boolean evaluate() {
+                        return listener.test100Exists;
+                    }
+                });
+                n.getProperty("test100").remove();
+                n.getSession().save();
+                Timer.waitFor(CONDITION_TIMEOUT, new Condition() {
+                    @Override
+                    public boolean evaluate() {
+                        return !listener.test100Exists;
+                    }
+                });
+            }
+            assertEquals("", listener.error);
+
+            for (int i=0; i<100; i++) {
+                n.getProperty("test" + i).remove();
+                n.getSession().save();
+            }
+            Timer.waitFor(CONDITION_TIMEOUT , new Condition() {
+                @Override
+                public boolean evaluate() {
+                    return listener.numPropsRemoved == 1100;
+                }
+            });
+            assertEquals("", listener.error);
+            assertEquals("properties removed", 1100, listener.numPropsRemoved);
+        }
+        finally {
+            observationManager.removeEventListener(listener);
+        }
+    }
+
+    private interface Condition {
+        boolean evaluate();
+    }
+    private static class Timer {
+
+        public static boolean waitFor(long timeout, Condition c) throws InterruptedException {
+            long end = System.currentTimeMillis() + timeout;
+            while (System.currentTimeMillis() < end) {
+                if (c.evaluate()) {
+                    return true;
+                }
+                Thread.sleep(100);
+            }
+            return false;
+        }
+    }
+
+    private class MyListener implements EventListener {
+
+        private String error = "";
+
+        private volatile int numAdded = 0;
+
+        private volatile int numRemoved = 0;
+
+        private volatile int numPropsAdded = 0;
+
+        private volatile int numPropsRemoved = 0;
+
+        private volatile int numPropsModified = 0;
+
+        private volatile boolean test100Exists = false;
+
+        @Override
+        public void onEvent(EventIterator events) {
+            try {
+                while (events.hasNext()) {
+                    Event event = events.nextEvent();
+                    if (event.getType() == Event.NODE_ADDED) {
+                        numAdded++;
+                        if (!observingSession.nodeExists(event.getPath())) {
+                            error = "node missing: " + event.getPath();
+                        }
+                    }
+                    if (event.getType() == Event.NODE_REMOVED) {
+                        numRemoved++;
+                        if (observingSession.nodeExists(event.getPath())) {
+                            error = "node not missing: " + event.getPath();
+                        }
+                    }
+                    if (event.getType() == Event.PROPERTY_ADDED) {
+                        Node node = observingSession.getNode(Text.getRelativeParent(event.getPath(), 1));
+                        PropertyIterator iter = node.getProperties();
+                        boolean ok = false;
+                        while (iter.hasNext()) {
+                            Property p = iter.nextProperty();
+                            if (p.getPath().equals(event.getPath())) {
+                                ok = true;
+                            }
+                        }
+                        if (!ok) {
+                            error = "property missing: " + event.getPath();
+                        }
+                        String name = Text.getName(event.getPath());
+                        if ("test100".equals(name)) {
+                            test100Exists = true;
+                        } else {
+                            numPropsAdded++;
+                            if (!observingSession.propertyExists(event.getPath())) {
+                                error = "property missing: " + event.getPath();
+                            }
+                        }
+                    }
+                    if (event.getType() == Event.PROPERTY_REMOVED) {
+                        String name = Text.getName(event.getPath());
+                        if ("test100".equals(name)) {
+                            test100Exists = false;
+                        } else {
+                            numPropsRemoved++;
+                            if (observingSession.propertyExists(event.getPath())) {
+                                error = "property not missing: " + event.getPath();
+                            }
+                        }
+                    }
+                    if (event.getType() == Event.PROPERTY_CHANGED) {
+                        String name = Text.getName(event.getPath());
+                        if ("test100".equals(name)) {
+
+                        } else {
+                            numPropsModified++;
+                            long v = observingSession.getProperty(event.getPath()).getLong();
+                            if (v != Long.valueOf(Text.getName(name).substring(4))) {
+                                error = "property has wrong content: " + event.getPath();
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                error = e.toString();
+                e.printStackTrace();
+            }
+
+        }
+    }
+}