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();
+ }
+
+ }
+ }
+}