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 re...@apache.org on 2018/04/26 13:09:14 UTC

svn commit: r1830213 - in /jackrabbit/oak/branches/1.6/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/document/util/ test/java/org/apache/jackrabbit/oak/plugins/index/property/ test/java/org/apache/jackrabbit/oak/util/

Author: reschke
Date: Thu Apr 26 13:09:14 2018
New Revision: 1830213

URL: http://svn.apache.org/viewvc?rev=1830213&view=rev
Log:
OAK-7453: oak-store-document: fix broken line ends in repo (in 1.6 - oak-core)

Modified:
    jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/ReadOnlyDocumentStoreWrapperFactory.java
    jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookupTest.java
    jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/util/PerfLoggerIT.java

Modified: jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/ReadOnlyDocumentStoreWrapperFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/ReadOnlyDocumentStoreWrapperFactory.java?rev=1830213&r1=1830212&r2=1830213&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/ReadOnlyDocumentStoreWrapperFactory.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/ReadOnlyDocumentStoreWrapperFactory.java Thu Apr 26 13:09:14 2018
@@ -1,46 +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.oak.plugins.document.util;
-
-import com.google.common.collect.Sets;
-import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
-
-import javax.annotation.Nonnull;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Arrays;
-import java.util.Set;
-
-public class ReadOnlyDocumentStoreWrapperFactory {
-    private static final Set<String> unsupportedMethods = Sets.newHashSet(
-            "remove", "create", "update", "createOrUpdate", "findAndUpdate");
-    public static DocumentStore getInstance(@Nonnull final DocumentStore delegate) {
-        return (DocumentStore)Proxy.newProxyInstance(DocumentStore.class.getClassLoader(),
-                new Class[]{DocumentStore.class},
-                new InvocationHandler() {
-                    @Override
-                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                        if (unsupportedMethods.contains(method.getName())) {
-                            throw new UnsupportedOperationException(String.format("Method - %s. Params: %s",
-                                    method.getName(), Arrays.toString(args)));
-                        }
-                        return method.invoke(delegate, args);
-                    }
-                });
-    }
-}
+/*
+ * 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.plugins.document.util;
+
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
+
+import javax.annotation.Nonnull;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Set;
+
+public class ReadOnlyDocumentStoreWrapperFactory {
+    private static final Set<String> unsupportedMethods = Sets.newHashSet(
+            "remove", "create", "update", "createOrUpdate", "findAndUpdate");
+    public static DocumentStore getInstance(@Nonnull final DocumentStore delegate) {
+        return (DocumentStore)Proxy.newProxyInstance(DocumentStore.class.getClassLoader(),
+                new Class[]{DocumentStore.class},
+                new InvocationHandler() {
+                    @Override
+                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                        if (unsupportedMethods.contains(method.getName())) {
+                            throw new UnsupportedOperationException(String.format("Method - %s. Params: %s",
+                                    method.getName(), Arrays.toString(args)));
+                        }
+                        return method.invoke(delegate, args);
+                    }
+                });
+    }
+}

Modified: jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookupTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookupTest.java?rev=1830213&r1=1830212&r2=1830213&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookupTest.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookupTest.java Thu Apr 26 13:09:14 2018
@@ -1,111 +1,111 @@
-/*
- * 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.plugins.index.property;
-
-import com.google.common.collect.Lists;
-import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
-import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
-import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
-import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
-import org.apache.jackrabbit.oak.query.NodeStateNodeTypeInfoProvider;
-import org.apache.jackrabbit.oak.query.QueryEngineSettings;
-import org.apache.jackrabbit.oak.query.ast.NodeTypeInfo;
-import org.apache.jackrabbit.oak.query.ast.NodeTypeInfoProvider;
-import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
-import org.apache.jackrabbit.oak.query.index.FilterImpl;
-import org.apache.jackrabbit.oak.spi.commit.EditorHook;
-import org.apache.jackrabbit.oak.spi.query.Filter;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
-import static org.apache.jackrabbit.oak.api.Type.NAMES;
-import static org.apache.jackrabbit.oak.api.Type.STRINGS;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.PROPERTY_NAMES;
-import static org.apache.jackrabbit.oak.spi.commit.CommitInfo.EMPTY;
-import static org.junit.Assert.assertNotNull;
-
-public class PropertyIndexLookupTest {
-
-    private static final List<String> PROP_NAMES = Lists.newArrayList("jcr:primaryType", "jcr:mixinTypes");
-    private static final List<String> DECL_NODE_TYPES = Lists.newArrayList("nt:unstructured", "mix:versionable");
-
-    private NodeState root;
-    private NodeBuilder rootBuilder;
-    private static final EditorHook HOOK = new EditorHook(
-            new IndexUpdateProvider(new PropertyIndexEditorProvider()));
-
-    @Before
-    public void setup() throws Exception {
-        root = EmptyNodeState.EMPTY_NODE;
-        rootBuilder = InitialContent.INITIAL_CONTENT.builder();
-        commit();
-    }
-
-    @Test
-    public void getIndexNodeForNamedDeclaringNodeTypes() throws Exception {
-        rootBuilder.child(INDEX_DEFINITIONS_NAME).child("nodetype")
-                .setProperty(PropertyStates.createProperty(DECLARING_NODE_TYPES, DECL_NODE_TYPES, NAMES));
-        commit();
-
-        Filter f = createFilter(root, "nt:unstructured");
-        assertNotNull("declaringNodeTypes with Name[] must find index node",
-                new PropertyIndexLookup(root).getIndexNode(root, JCR_PRIMARYTYPE, f));
-    }
-
-    @Test
-    public void getIndexNodeForStringDeclaringNodeTypes() throws Exception {
-        rootBuilder.child(INDEX_DEFINITIONS_NAME).child("nodetype")
-                .setProperty(PropertyStates.createProperty(DECLARING_NODE_TYPES, DECL_NODE_TYPES, STRINGS));
-        commit();
-
-        Filter f = createFilter(root, "nt:unstructured");
-        assertNotNull("declaringNodeTypes with String[] should also find index node",
-                new PropertyIndexLookup(root).getIndexNode(root, JCR_PRIMARYTYPE, f));
-    }
-
-    @Test
-    public void getIndexNodeForStringPropertyNames() throws Exception {
-        rootBuilder.child(INDEX_DEFINITIONS_NAME).child("nodetype")
-                .removeProperty(PROPERTY_NAMES)
-                .setProperty(PropertyStates.createProperty(PROPERTY_NAMES, PROP_NAMES, STRINGS));
-        commit();
-
-        Filter f = createFilter(root, "nt:unstructured");
-        assertNotNull("propertyNames with String[] should also find index node",
-                new PropertyIndexLookup(root).getIndexNode(root, JCR_PRIMARYTYPE, f));
-    }
-
-    private void commit() throws Exception {
-        root = HOOK.processCommit(rootBuilder.getBaseState(), rootBuilder.getNodeState(), EMPTY);
-        rootBuilder = root.builder();
-    }
-
-    private static FilterImpl createFilter(NodeState root, String nodeTypeName) {
-        NodeTypeInfoProvider nodeTypes = new NodeStateNodeTypeInfoProvider(root);
-        NodeTypeInfo type = nodeTypes.getNodeTypeInfo(nodeTypeName);
-        SelectorImpl selector = new SelectorImpl(type, nodeTypeName);
-        return new FilterImpl(selector, "SELECT * FROM [" + nodeTypeName + "]",
-                new QueryEngineSettings());
-    }
-}
+/*
+ * 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.plugins.index.property;
+
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.query.NodeStateNodeTypeInfoProvider;
+import org.apache.jackrabbit.oak.query.QueryEngineSettings;
+import org.apache.jackrabbit.oak.query.ast.NodeTypeInfo;
+import org.apache.jackrabbit.oak.query.ast.NodeTypeInfoProvider;
+import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.PROPERTY_NAMES;
+import static org.apache.jackrabbit.oak.spi.commit.CommitInfo.EMPTY;
+import static org.junit.Assert.assertNotNull;
+
+public class PropertyIndexLookupTest {
+
+    private static final List<String> PROP_NAMES = Lists.newArrayList("jcr:primaryType", "jcr:mixinTypes");
+    private static final List<String> DECL_NODE_TYPES = Lists.newArrayList("nt:unstructured", "mix:versionable");
+
+    private NodeState root;
+    private NodeBuilder rootBuilder;
+    private static final EditorHook HOOK = new EditorHook(
+            new IndexUpdateProvider(new PropertyIndexEditorProvider()));
+
+    @Before
+    public void setup() throws Exception {
+        root = EmptyNodeState.EMPTY_NODE;
+        rootBuilder = InitialContent.INITIAL_CONTENT.builder();
+        commit();
+    }
+
+    @Test
+    public void getIndexNodeForNamedDeclaringNodeTypes() throws Exception {
+        rootBuilder.child(INDEX_DEFINITIONS_NAME).child("nodetype")
+                .setProperty(PropertyStates.createProperty(DECLARING_NODE_TYPES, DECL_NODE_TYPES, NAMES));
+        commit();
+
+        Filter f = createFilter(root, "nt:unstructured");
+        assertNotNull("declaringNodeTypes with Name[] must find index node",
+                new PropertyIndexLookup(root).getIndexNode(root, JCR_PRIMARYTYPE, f));
+    }
+
+    @Test
+    public void getIndexNodeForStringDeclaringNodeTypes() throws Exception {
+        rootBuilder.child(INDEX_DEFINITIONS_NAME).child("nodetype")
+                .setProperty(PropertyStates.createProperty(DECLARING_NODE_TYPES, DECL_NODE_TYPES, STRINGS));
+        commit();
+
+        Filter f = createFilter(root, "nt:unstructured");
+        assertNotNull("declaringNodeTypes with String[] should also find index node",
+                new PropertyIndexLookup(root).getIndexNode(root, JCR_PRIMARYTYPE, f));
+    }
+
+    @Test
+    public void getIndexNodeForStringPropertyNames() throws Exception {
+        rootBuilder.child(INDEX_DEFINITIONS_NAME).child("nodetype")
+                .removeProperty(PROPERTY_NAMES)
+                .setProperty(PropertyStates.createProperty(PROPERTY_NAMES, PROP_NAMES, STRINGS));
+        commit();
+
+        Filter f = createFilter(root, "nt:unstructured");
+        assertNotNull("propertyNames with String[] should also find index node",
+                new PropertyIndexLookup(root).getIndexNode(root, JCR_PRIMARYTYPE, f));
+    }
+
+    private void commit() throws Exception {
+        root = HOOK.processCommit(rootBuilder.getBaseState(), rootBuilder.getNodeState(), EMPTY);
+        rootBuilder = root.builder();
+    }
+
+    private static FilterImpl createFilter(NodeState root, String nodeTypeName) {
+        NodeTypeInfoProvider nodeTypes = new NodeStateNodeTypeInfoProvider(root);
+        NodeTypeInfo type = nodeTypes.getNodeTypeInfo(nodeTypeName);
+        SelectorImpl selector = new SelectorImpl(type, nodeTypeName);
+        return new FilterImpl(selector, "SELECT * FROM [" + nodeTypeName + "]",
+                new QueryEngineSettings());
+    }
+}

Modified: jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/util/PerfLoggerIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/util/PerfLoggerIT.java?rev=1830213&r1=1830212&r2=1830213&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/util/PerfLoggerIT.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/util/PerfLoggerIT.java Thu Apr 26 13:09:14 2018
@@ -1,156 +1,156 @@
-/*
- * 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.util;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.slf4j.Logger;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-/**
- * Timing tests for {@link PerfLogger} using {@code Thread.sleep} because
- * virtual clock requires currentTimeMillis (OAK-3877)
- */
-public class PerfLoggerIT {
-    @Mock
-    Logger logger;
-
-    private PerfLogger perfLogger;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        when(logger.isTraceEnabled()).thenReturn(false);
-        when(logger.isDebugEnabled()).thenReturn(false);
-        when(logger.isInfoEnabled()).thenReturn(false);
-
-        perfLogger = new PerfLogger(logger);
-    }
-
-    //test for logger set at DEBUG
-    @Test
-    public void logAtDebugTimeoutNotHit() {
-        setupDebugLogger();
-
-        long start = perfLogger.start();
-        perfLogger.end(start, 100, "message", "argument");
-
-        verifyTraceInteractions(1, false, false);
-        verifyDebugInteractions(2, false);
-        verifyNoMoreInteractions(logger);
-    }
-
-    @Test
-    public void logAtDebugTimeoutHit() throws InterruptedException {
-        setupDebugLogger();
-
-        long start = perfLogger.start();
-        Thread.sleep(100);
-        perfLogger.end(start, 20, "message", "argument");
-
-        verifyTraceInteractions(1, false, false);
-        verifyDebugInteractions(3, true);
-        verifyNoMoreInteractions(logger);
-    }
-    //end DEBUG tests
-
-
-    //test for logger set at INFO
-    @Test
-    public void logAtInfoDebugTimeoutHit() throws InterruptedException {
-        setupInfoLogger();
-
-        long start = perfLogger.start();
-        Thread.sleep(100);
-        perfLogger.end(start, 20, "message", "argument");
-
-        verifyDebugInteractions(1, false);
-        verifyNoMoreInteractions(logger);
-    }
-
-    @Test
-    public void logAtInfoInfoTimeoutNotHit() throws InterruptedException {
-        setupInfoLogger();
-
-        long start = perfLogger.startForInfoLog();
-        Thread.sleep(100);
-        perfLogger.end(start, 20, 500, "message", "argument");
-
-        verifyTraceInteractions(1, false, false);
-        verifyDebugInteractions(1, false);
-        verifyInfoInteractions(2, false);
-        verifyNoMoreInteractions(logger);
-    }
-
-    @Test
-    public void logAtInfoInfoTimeoutHit() throws InterruptedException {
-        setupInfoLogger();
-
-        long start = perfLogger.startForInfoLog();
-        Thread.sleep(100);
-        perfLogger.end(start, 20, 50, "message", "argument");
-
-        verifyTraceInteractions(1, false, false);
-        verifyDebugInteractions(1, false);
-        verifyInfoInteractions(2, true);
-        verifyNoMoreInteractions(logger);
-    }
-    //end INFO tests
-
-    private void setupDebugLogger() {
-        when(logger.isDebugEnabled()).thenReturn(true);
-        setupInfoLogger();
-    }
-    private void setupInfoLogger() {
-        when(logger.isInfoEnabled()).thenReturn(true);
-    }
-
-    private void verifyTraceInteractions(int enabled, boolean shouldLogStart, boolean shouldLogEnd) {
-        verify(logger, times(enabled)).isTraceEnabled();
-
-        if (shouldLogStart) {
-            verify(logger, times(1)).trace(anyString());
-        }
-        if (shouldLogEnd) {
-            verify(logger, times(1)).trace(anyString(), any(Object[].class));
-        }
-    }
-
-    private void verifyDebugInteractions(int enabled, boolean shouldLog) {
-        verify(logger, times(enabled)).isDebugEnabled();
-
-        if (shouldLog) {
-            verify(logger, times(1)).debug(anyString(), any(Object[].class));
-        }
-    }
-
-    private void verifyInfoInteractions(int enabled, boolean shouldLog) {
-        verify(logger, times(enabled)).isInfoEnabled();
-
-        if (shouldLog) {
-            verify(logger, times(1)).info(anyString(), any(Object[].class));
-        }
-    }
-}
+/*
+ * 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.util;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.slf4j.Logger;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * Timing tests for {@link PerfLogger} using {@code Thread.sleep} because
+ * virtual clock requires currentTimeMillis (OAK-3877)
+ */
+public class PerfLoggerIT {
+    @Mock
+    Logger logger;
+
+    private PerfLogger perfLogger;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        when(logger.isTraceEnabled()).thenReturn(false);
+        when(logger.isDebugEnabled()).thenReturn(false);
+        when(logger.isInfoEnabled()).thenReturn(false);
+
+        perfLogger = new PerfLogger(logger);
+    }
+
+    //test for logger set at DEBUG
+    @Test
+    public void logAtDebugTimeoutNotHit() {
+        setupDebugLogger();
+
+        long start = perfLogger.start();
+        perfLogger.end(start, 100, "message", "argument");
+
+        verifyTraceInteractions(1, false, false);
+        verifyDebugInteractions(2, false);
+        verifyNoMoreInteractions(logger);
+    }
+
+    @Test
+    public void logAtDebugTimeoutHit() throws InterruptedException {
+        setupDebugLogger();
+
+        long start = perfLogger.start();
+        Thread.sleep(100);
+        perfLogger.end(start, 20, "message", "argument");
+
+        verifyTraceInteractions(1, false, false);
+        verifyDebugInteractions(3, true);
+        verifyNoMoreInteractions(logger);
+    }
+    //end DEBUG tests
+
+
+    //test for logger set at INFO
+    @Test
+    public void logAtInfoDebugTimeoutHit() throws InterruptedException {
+        setupInfoLogger();
+
+        long start = perfLogger.start();
+        Thread.sleep(100);
+        perfLogger.end(start, 20, "message", "argument");
+
+        verifyDebugInteractions(1, false);
+        verifyNoMoreInteractions(logger);
+    }
+
+    @Test
+    public void logAtInfoInfoTimeoutNotHit() throws InterruptedException {
+        setupInfoLogger();
+
+        long start = perfLogger.startForInfoLog();
+        Thread.sleep(100);
+        perfLogger.end(start, 20, 500, "message", "argument");
+
+        verifyTraceInteractions(1, false, false);
+        verifyDebugInteractions(1, false);
+        verifyInfoInteractions(2, false);
+        verifyNoMoreInteractions(logger);
+    }
+
+    @Test
+    public void logAtInfoInfoTimeoutHit() throws InterruptedException {
+        setupInfoLogger();
+
+        long start = perfLogger.startForInfoLog();
+        Thread.sleep(100);
+        perfLogger.end(start, 20, 50, "message", "argument");
+
+        verifyTraceInteractions(1, false, false);
+        verifyDebugInteractions(1, false);
+        verifyInfoInteractions(2, true);
+        verifyNoMoreInteractions(logger);
+    }
+    //end INFO tests
+
+    private void setupDebugLogger() {
+        when(logger.isDebugEnabled()).thenReturn(true);
+        setupInfoLogger();
+    }
+    private void setupInfoLogger() {
+        when(logger.isInfoEnabled()).thenReturn(true);
+    }
+
+    private void verifyTraceInteractions(int enabled, boolean shouldLogStart, boolean shouldLogEnd) {
+        verify(logger, times(enabled)).isTraceEnabled();
+
+        if (shouldLogStart) {
+            verify(logger, times(1)).trace(anyString());
+        }
+        if (shouldLogEnd) {
+            verify(logger, times(1)).trace(anyString(), any(Object[].class));
+        }
+    }
+
+    private void verifyDebugInteractions(int enabled, boolean shouldLog) {
+        verify(logger, times(enabled)).isDebugEnabled();
+
+        if (shouldLog) {
+            verify(logger, times(1)).debug(anyString(), any(Object[].class));
+        }
+    }
+
+    private void verifyInfoInteractions(int enabled, boolean shouldLog) {
+        verify(logger, times(enabled)).isInfoEnabled();
+
+        if (shouldLog) {
+            verify(logger, times(1)).info(anyString(), any(Object[].class));
+        }
+    }
+}