You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2014/10/13 13:54:43 UTC

svn commit: r1631356 [2/9] - in /sling/trunk: ./ testing/jcr-mock/ testing/jcr-mock/src/ testing/jcr-mock/src/main/ testing/jcr-mock/src/main/java/ testing/jcr-mock/src/main/java/org/ testing/jcr-mock/src/main/java/org/apache/ testing/jcr-mock/src/main...

Added: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java (added)
+++ sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,85 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * Mock {@link Repository} implementation. The data is stored inside the mocked
+ * session, not the repository - so it is not possible to open multiple session
+ * to access the same data in this mock implementation.
+ */
+class MockRepository implements Repository {
+
+    @Override
+    public Session login() {
+        return new MockSession(this);
+    }
+
+    @Override
+    public Session login(final String workspaceName) {
+        return login();
+    }
+
+    @Override
+    public Session login(final Credentials credentials) {
+        return login();
+    }
+
+    @Override
+    public Session login(final Credentials credentials, final String workspaceName) {
+        return login();
+    }
+
+    @Override
+    public String[] getDescriptorKeys() {
+        return ArrayUtils.EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public boolean isStandardDescriptor(final String key) {
+        return false;
+    }
+
+    @Override
+    public boolean isSingleValueDescriptor(final String key) {
+        return false;
+    }
+
+    @Override
+    public Value getDescriptorValue(final String key) {
+        return null;
+    }
+
+    @Override
+    public Value[] getDescriptorValues(final String key) { // NOPMD
+        return null; // NOPMD
+    }
+
+    @Override
+    public String getDescriptor(final String key) {
+        return null;
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockRepository.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java (added)
+++ sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,354 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.jcr.Credentials;
+import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RangeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.ValueFactory;
+import javax.jcr.Workspace;
+import javax.jcr.retention.RetentionManager;
+import javax.jcr.security.AccessControlManager;
+
+import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
+import org.apache.jackrabbit.value.ValueFactoryImpl;
+import org.xml.sax.ContentHandler;
+
+/**
+ * Mock {@link Session} implementation. This instance holds the JCR data in a
+ * simple ordered map.
+ */
+class MockSession implements Session {
+
+    private final Repository repository;
+    private final Workspace workspace;
+
+    // Use linked hashmap to ensure ordering when adding items is preserved.
+    private final Map<String, Item> items = new LinkedHashMap<String, Item>();
+
+    public MockSession(final Repository repository) {
+        this.repository = repository;
+        this.workspace = new MockWorkspace(this);
+        this.items.put("/", new MockNode("/", this, MockNodeTypes.NT_UNSTRUCTURED));
+    }
+
+    @Override
+    public ValueFactory getValueFactory() {
+        return ValueFactoryImpl.getInstance();
+    }
+
+    @Override
+    public Item getItem(final String absPath) throws RepositoryException {
+        Item item = this.items.get(absPath);
+        if (item != null) {
+            return item;
+        } else {
+            throw new PathNotFoundException(String.format("No item found at: %s.", absPath));
+        }
+    }
+
+    @Override
+    public Node getNode(final String absPath) throws RepositoryException {
+        Item item = getItem(absPath);
+        if (item instanceof Node) {
+            return (Node) item;
+        } else {
+            throw new PathNotFoundException(String.format("No node found at: %s.", absPath));
+        }
+    }
+
+    @Override
+    public Node getNodeByIdentifier(final String id) throws RepositoryException {
+        for (Item item : this.items.values()) {
+            if (item instanceof Node) {
+                Node node = (Node) item;
+                if (node.getIdentifier().equals(id)) {
+                    return node;
+                }
+            }
+        }
+        throw new ItemNotFoundException(String.format("No node found with id: %s.", id));
+    }
+
+    @Override
+    public Property getProperty(final String absPath) throws RepositoryException {
+        Item item = getItem(absPath);
+        if (item instanceof Property) {
+            return (Property) item;
+        } else {
+            throw new PathNotFoundException(String.format("No property found at: %s.", absPath));
+        }
+    }
+
+    @Override
+    public boolean nodeExists(final String absPath) throws RepositoryException {
+        try {
+            getNode(absPath);
+            return true;
+        } catch (PathNotFoundException ex) {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean propertyExists(final String absPath) throws RepositoryException {
+        try {
+            getProperty(absPath);
+            return true;
+        } catch (PathNotFoundException ex) {
+            return false;
+        }
+    }
+
+    @Override
+    public void removeItem(final String absPath) {
+        removeItemWithChildren(absPath);
+    }
+
+    @Override
+    public Node getRootNode() {
+        return (Node) this.items.get("/");
+    }
+
+    @Override
+    public Node getNodeByUUID(final String uuid) throws RepositoryException {
+        return getNodeByIdentifier(uuid);
+    }
+
+    /**
+     * Add item
+     * @param item item
+     * @throws RepositoryException
+     */
+    void addItem(final Item item) throws RepositoryException {
+        this.items.put(item.getPath(), item);
+    }
+
+    /**
+     * Remove item incl. children
+     * @param path Item path
+     */
+    void removeItemWithChildren(final String path) {
+        List<String> pathsToRemove = new ArrayList<String>();
+
+        // build regex pattern for node and all its children
+        Pattern pattern = Pattern.compile("^" + Pattern.quote(path) + "(/.+)?$");
+
+        for (String itemPath : this.items.keySet()) {
+            if (pattern.matcher(itemPath).matches()) {
+                pathsToRemove.add(itemPath);
+            }
+        }
+        for (String pathToRemove : pathsToRemove) {
+            this.items.remove(pathToRemove);
+        }
+    }
+
+    RangeIterator listChildren(final String parentPath, final ItemFilter filter) throws RepositoryException {
+        List<Item> children = new ArrayList<Item>();
+
+        // build regex pattern for all child paths of parent
+        Pattern pattern = Pattern.compile("^" + Pattern.quote(parentPath) + "/[^/]+$");
+
+        // collect child resources
+        for (Item item : this.items.values()) {
+            if (pattern.matcher(item.getPath()).matches() && (filter == null || filter.accept(item))) {
+                children.add(item);
+            }
+        }
+
+        return new RangeIteratorAdapter(children.iterator(), children.size());
+    }
+
+    @Override
+    public boolean hasPendingChanges() {
+        return false;
+    }
+
+    @Override
+    public boolean itemExists(final String absPath) {
+        return this.items.get(absPath) != null;
+    }
+
+    @Override
+    public Workspace getWorkspace() {
+        return this.workspace;
+    }
+
+    @Override
+    public String getUserID() {
+        return "mockedUserId";
+    }
+
+    @Override
+    public String getNamespacePrefix(final String uri) throws RepositoryException {
+        return getWorkspace().getNamespaceRegistry().getPrefix(uri);
+    }
+
+    @Override
+    public String[] getNamespacePrefixes() throws RepositoryException {
+        return getWorkspace().getNamespaceRegistry().getPrefixes();
+    }
+
+    @Override
+    public String getNamespaceURI(final String prefix) throws RepositoryException {
+        return getWorkspace().getNamespaceRegistry().getURI(prefix);
+    }
+
+    @Override
+    public void setNamespacePrefix(final String prefix, final String uri) throws RepositoryException {
+        getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
+    }
+
+    @Override
+    public Repository getRepository() {
+        return this.repository;
+    }
+
+    @Override
+    public void save() {
+        // do nothing
+    }
+
+    @Override
+    public void refresh(final boolean keepChanges) throws RepositoryException {
+        // do nothing
+    }
+
+    @Override
+    public void checkPermission(final String absPath, final String actions) {
+        // always grant permission
+    }
+
+    // --- unsupported operations ---
+    @Override
+    public void addLockToken(final String lt) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void exportDocumentView(final String absPath, final ContentHandler contentHandler, final boolean skipBinary,
+            final boolean noRecurse) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void exportDocumentView(final String absPath, final OutputStream out, final boolean skipBinary,
+            final boolean noRecurse) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void exportSystemView(final String absPath, final ContentHandler contentHandler, final boolean skipBinary,
+            final boolean noRecurse) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void exportSystemView(final String absPath, final OutputStream out, final boolean skipBinary,
+            final boolean noRecurse) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getAttribute(final String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getAttributeNames() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ContentHandler getImportContentHandler(final String parentAbsPath, final int uuidBehavior) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getLockTokens() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Session impersonate(final Credentials credentials) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void importXML(final String parentAbsPath, final InputStream in, final int uuidBehavior) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isLive() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void logout() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void move(final String srcAbsPath, final String destAbsPath) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeLockToken(final String lt) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public AccessControlManager getAccessControlManager() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public RetentionManager getRetentionManager() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasCapability(final String methodName, final Object target, final Object[] arguments) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasPermission(final String absPath, final String actions) {
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java (added)
+++ sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,149 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import java.io.InputStream;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.lock.LockManager;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.observation.ObservationManager;
+import javax.jcr.query.QueryManager;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionManager;
+
+import org.xml.sax.ContentHandler;
+
+/**
+ * Mock {@link Workspace} implementation
+ */
+class MockWorkspace implements Workspace {
+
+    private final Session session;
+    private final NamespaceRegistry namespaceRegistry = new MockNamespaceRegistry();
+    private final ObservationManager observationManager = new MockObservationManager();
+    private final NodeTypeManager nodeTypeManager = new MockNodeTypeManager();
+
+    /**
+     * @param session JCR session
+     */
+    public MockWorkspace(final Session session) {
+        this.session = session;
+    }
+
+    @Override
+    public Session getSession() {
+        return this.session;
+    }
+
+    @Override
+    public String getName() {
+        return MockJcr.DEFAULT_WORKSPACE;
+    }
+
+    @Override
+    public NamespaceRegistry getNamespaceRegistry() {
+        return this.namespaceRegistry;
+    }
+
+    @Override
+    public ObservationManager getObservationManager() {
+        return this.observationManager;
+    }
+
+    @Override
+    public NodeTypeManager getNodeTypeManager() {
+        return this.nodeTypeManager;
+    }
+
+    // --- unsupported operations ---
+    @Override
+    public void copy(final String srcAbsPath, final String destAbsPath) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copy(final String srcWorkspace, final String srcAbsPath, final String destAbsPath) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void clone(final String srcWorkspace, final String srcAbsPath, final String destAbsPath,
+            final boolean removeExisting) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void move(final String srcAbsPath, final String destAbsPath) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void restore(final Version[] versions, final boolean removeExisting) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public LockManager getLockManager() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public QueryManager getQueryManager() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public VersionManager getVersionManager() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getAccessibleWorkspaceNames() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ContentHandler getImportContentHandler(final String parentAbsPath, final int uuidBehavior) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void importXML(final String parentAbsPath, final InputStream in, final int uuidBehavior) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void createWorkspace(final String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void createWorkspace(final String name, final String srcWorkspace) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void deleteWorkspace(final String name) {
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/MockWorkspace.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java (added)
+++ sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,219 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+/**
+ * This is a stripped-down copy of org.apache.sling.api.resource.ResourceUtil
+ * with some methods required by the jcr-mock implementation internally.
+ */
+class ResourceUtil {
+
+    /**
+     * Resolves relative path segments '.' and '..' in the absolute path.
+     * Returns null if not possible (.. points above root) or if path is not
+     * absolute.
+     */
+    public static String normalize(String path) {
+
+        // don't care for empty paths
+        if (path.length() == 0) {
+            return path;
+        }
+
+        // prepare the path buffer with trailing slash (simplifies impl)
+        int absOffset = (path.charAt(0) == '/') ? 0 : 1;
+        char[] buf = new char[path.length() + 1 + absOffset];
+        if (absOffset == 1) {
+            buf[0] = '/';
+        }
+        path.getChars(0, path.length(), buf, absOffset);
+        buf[buf.length - 1] = '/';
+
+        int lastSlash = 0; // last slash in path
+        int numDots = 0; // number of consecutive dots after last slash
+
+        int bufPos = 0;
+        for (int bufIdx = lastSlash; bufIdx < buf.length; bufIdx++) {
+            char c = buf[bufIdx];
+            if (c == '/') {
+                if (numDots == 2) {
+                    if (bufPos == 0) {
+                        return null;
+                    }
+
+                    do {
+                        bufPos--;
+                    } while (bufPos > 0 && buf[bufPos] != '/');
+                }
+
+                lastSlash = bufIdx;
+                numDots = 0;
+            } else if (c == '.' && numDots < 2) {
+                numDots++;
+            } else {
+                // find the next slash
+                int nextSlash = bufIdx + 1;
+                while (nextSlash < buf.length && buf[nextSlash] != '/') {
+                    nextSlash++;
+                }
+
+                // append up to the next slash (or end of path)
+                if (bufPos < lastSlash) {
+                    int segLen = nextSlash - bufIdx + 1;
+                    System.arraycopy(buf, lastSlash, buf, bufPos, segLen);
+                    bufPos += segLen;
+                } else {
+                    bufPos = nextSlash;
+                }
+
+                numDots = 0;
+                lastSlash = nextSlash;
+                bufIdx = nextSlash;
+            }
+        }
+
+        String resolved;
+        if (bufPos == 0 && numDots == 0) {
+            resolved = (absOffset == 0) ? "/" : "";
+        } else if ((bufPos - absOffset) == path.length()) {
+            resolved = path;
+        } else {
+            resolved = new String(buf, absOffset, bufPos - absOffset);
+        }
+
+        return resolved;
+    }
+
+    /**
+     * Utility method returns the parent path of the given <code>path</code>,
+     * which is normalized by {@link #normalize(String)} before resolving the
+     * parent.
+     *
+     * @param path The path whose parent is to be returned.
+     * @return <code>null</code> if <code>path</code> is the root path (
+     *         <code>/</code>) or if <code>path</code> is a single name
+     *         containing no slash (<code>/</code>) characters.
+     * @throws IllegalArgumentException If the path cannot be normalized by the
+     *             {@link #normalize(String)} method.
+     * @throws NullPointerException If <code>path</code> is <code>null</code>.
+     */
+    public static String getParent(String path) {
+        if ("/".equals(path)) {
+            return null;
+        }
+
+        // normalize path (remove . and ..)
+        path = normalize(path);
+
+        // if normalized to root, there is no parent
+        if (path == null || "/".equals(path)) {
+            return null;
+        }
+
+        String workspaceName = null;
+
+        final int wsSepPos = path.indexOf(":/");
+        if (wsSepPos != -1) {
+            workspaceName = path.substring(0, wsSepPos);
+            path = path.substring(wsSepPos + 1);
+        }
+
+        // find the last slash, after which to cut off
+        int lastSlash = path.lastIndexOf('/');
+        if (lastSlash < 0) {
+            // no slash in the path
+            return null;
+        } else if (lastSlash == 0) {
+            // parent is root
+            if (workspaceName != null) {
+                return workspaceName + ":/";
+            }
+            return "/";
+        }
+
+        String parentPath = path.substring(0, lastSlash);
+        if (workspaceName != null) {
+            return workspaceName + ":" + parentPath;
+        }
+        return parentPath;
+    }
+
+    /**
+     * Utility method returns the ancestor's path at the given <code>level</code>
+     * relative to <code>path</code>, which is normalized by {@link #normalize(String)}
+     * before resolving the ancestor.
+     *
+     * <ul>
+     * <li><code>level</code> = 0 returns the <code>path</code>.</li>
+     * <li><code>level</code> = 1 returns the parent of <code>path</code>, if it exists, <code>null</code> otherwise.</li>
+     * <li><code>level</code> = 2 returns the grandparent of <code>path</code>, if it exists, <code>null</code> otherwise.</li>
+     * </ul>
+     *
+     * @param path The path whose ancestor is to be returned.
+     * @param level The relative level of the ancestor, relative to <code>path</code>.
+     * @return <code>null</code> if <code>path</code> doesn't have an ancestor at the
+     *            specified <code>level</code>.
+     * @throws IllegalArgumentException If the path cannot be normalized by the
+     *             {@link #normalize(String)} method or if <code>level</code> < 0.
+     * @throws NullPointerException If <code>path</code> is <code>null</code>.
+     * @since 2.2
+     */
+    public static String getParent(final String path, final int level) {
+        if ( level < 0 ) {
+            throw new IllegalArgumentException("level must be non-negative");
+        }
+        String result = path;
+        for(int i=0; i<level; i++) {
+            result = getParent(result);
+            if ( result == null ) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Utility method returns the name of the given <code>path</code>, which is
+     * normalized by {@link #normalize(String)} before resolving the name.
+     *
+     * @param path The path whose name (the last path element) is to be
+     *            returned.
+     * @return The empty string if <code>path</code> is the root path (
+     *         <code>/</code>) or if <code>path</code> is a single name
+     *         containing no slash (<code>/</code>) characters.
+     * @throws IllegalArgumentException If the path cannot be normalized by the
+     *             {@link #normalize(String)} method.
+     * @throws NullPointerException If <code>path</code> is <code>null</code>.
+     */
+    public static String getName(String path) {
+        if ("/".equals(path)) {
+            return "";
+        }
+
+        // normalize path (remove . and ..)
+        path = normalize(path);
+        if ("/".equals(path)) {
+            return "";
+        }
+
+        // find the last slash
+        return path.substring(path.lastIndexOf('/') + 1);
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/ResourceUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java (added)
+++ sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * Mock implementation of selected JCR APIs.
+ */
+package org.apache.sling.testing.mock.jcr;
+

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/site/markdown/index.md
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/site/markdown/index.md?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/site/markdown/index.md (added)
+++ sling/trunk/testing/jcr-mock/src/site/markdown/index.md Mon Oct 13 11:54:39 2014
@@ -0,0 +1,38 @@
+## About JCR Mocks
+
+Mock implementation of selected JCR APIs.
+
+### Maven Dependency
+
+```xml
+<dependency>
+  <groupId>org.apache.sling</groupId>
+  <artifactId>org.apache.sling.testing.jcr-mock</artifactId>
+  <version>1.0.0-SNAPHOT</version>
+</dependency>
+```
+
+### Documentation
+
+* [Usage](usage.html)
+* [API Documentation](apidocs/)
+* [Changelog](changes-report.html)
+
+### Implemented mock features
+
+The mock implementation supports:
+
+* Reading and writing all data (primitive values, arrays, binary data) via the JCR API
+* Creating any number of nodes and properties (stored in-memory in a hash map)
+* Register namespaces
+
+The following features are *not supported*:
+
+* Node types are supported in the API, but their definitions and constraints are not applied
+* Versioning not supported
+* Search not supported
+* Transactions not supported
+* Observation events can be registered but are ignored
+* Access control always grants access
+* Exporting/Importing data via document and system views not supported 
+* Workspace management methods not supported

Added: sling/trunk/testing/jcr-mock/src/site/markdown/usage.md
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/site/markdown/usage.md?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/site/markdown/usage.md (added)
+++ sling/trunk/testing/jcr-mock/src/site/markdown/usage.md Mon Oct 13 11:54:39 2014
@@ -0,0 +1,17 @@
+## Usage
+
+### Getting JCR mock objects
+
+The factory class `MockJcr` allows to instantiate the different mock implementations.
+
+Example:
+
+```java
+// get session
+Session session = MockJcr.newSession();
+
+// get repository
+Repository repository = MockJcr.newRepository();
+```
+
+The repository is empty and contains only the root node. You can use the JCR API to fill it with content.

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,95 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public abstract class AbstractItemTest {
+
+    private Session session;
+    private Node rootNode;
+    private Node node1;
+    private Property prop1;
+    private Node node11;
+
+    @Before
+    public void setUp() throws RepositoryException {
+        this.session = MockJcr.newSession();
+        this.rootNode = this.session.getRootNode();
+        this.node1 = this.rootNode.addNode("node1");
+        this.prop1 = this.node1.setProperty("prop1", "value1");
+        this.node11 = this.node1.addNode("node11");
+    }
+
+    @Test
+    public void testGetName() throws RepositoryException {
+        assertEquals("node1", this.node1.getName());
+        assertEquals("prop1", this.prop1.getName());
+    }
+
+    @Test
+    public void testGetParent() throws RepositoryException {
+        assertSame(this.rootNode, this.node1.getParent());
+        assertSame(this.node1, this.prop1.getParent());
+        assertSame(this.node1, this.node11.getParent());
+    }
+
+    @Test
+    public void testGetAncestor() throws RepositoryException {
+        assertSame(this.node11, this.node11.getAncestor(0));
+        assertSame(this.node1, this.node11.getAncestor(1));
+        assertSame(this.rootNode, this.node11.getAncestor(2));
+    }
+
+    @Test(expected = ItemNotFoundException.class)
+    public void testGetAncestorNegative() throws RepositoryException {
+        assertSame(this.node11, this.node11.getAncestor(-1));
+    }
+
+    @Test(expected = ItemNotFoundException.class)
+    public void testGetAncestorTooDeep() throws RepositoryException {
+        this.node11.getAncestor(3);
+    }
+
+    @Test
+    public void testGetDepth() throws RepositoryException {
+        assertEquals(2, this.node11.getDepth());
+        assertEquals(1, this.node1.getDepth());
+        assertEquals(0, this.rootNode.getDepth());
+    }
+
+    @Test
+    public void testModifiedNew() {
+        // methods return always false
+        assertFalse(this.node1.isModified());
+        assertFalse(this.node1.isNew());
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/AbstractItemTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,129 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MockNodeTest {
+
+    private Session session;
+    private Node rootNode;
+    private Node node1;
+    private Property prop1;
+    private Node node11;
+
+    @Before
+    public void setUp() throws RepositoryException {
+        this.session = MockJcr.newSession();
+        this.rootNode = this.session.getRootNode();
+        this.node1 = this.rootNode.addNode("node1");
+        this.prop1 = this.node1.setProperty("prop1", "value1");
+        this.node11 = this.node1.addNode("node11");
+    }
+
+    @Test
+    public void testGetNodes() throws RepositoryException {
+        NodeIterator nodes = this.node1.getNodes();
+        assertEquals(1, nodes.getSize());
+        assertSame(this.node11, nodes.next());
+
+        assertTrue(this.node1.hasNodes());
+        assertFalse(this.node11.hasNodes());
+
+        nodes = this.node1.getNodes("^node.*$");
+        assertEquals(1, nodes.getSize());
+        assertSame(this.node11, nodes.next());
+
+        nodes = this.node1.getNodes("unknown?");
+        assertEquals(0, nodes.getSize());
+    }
+
+    @Test
+    public void testGetProperties() throws RepositoryException {
+        PropertyIterator properties = this.node1.getProperties();
+        assertEquals(1, properties.getSize());
+        assertSame(this.prop1, properties.next());
+
+        assertTrue(this.node1.hasProperties());
+        assertFalse(this.node11.hasProperties());
+
+        properties = this.node1.getProperties("^prop.*$");
+        assertEquals(1, properties.getSize());
+        assertSame(this.prop1, properties.next());
+
+        properties = this.node1.getProperties("unknown?");
+        assertEquals(0, properties.getSize());
+    }
+
+    @Test
+    public void testIsNode() {
+        assertTrue(this.node1.isNode());
+        assertFalse(this.prop1.isNode());
+    }
+
+    @Test
+    public void testHasNode() throws RepositoryException {
+        assertTrue(this.node1.hasNode("node11"));
+        assertFalse(this.node1.hasNode("node25"));
+    }
+
+    @Test
+    public void testHasProperty() throws RepositoryException {
+        assertTrue(this.node1.hasProperty("prop1"));
+        assertFalse(this.node1.hasProperty("prop25"));
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testGetUUID() throws RepositoryException {
+        assertEquals(this.node1.getIdentifier(), this.node1.getUUID());
+    }
+
+    @Test
+    public void testGetPrimaryItem() throws RepositoryException {
+        Node dataParent = this.node1.addNode("dataParent");
+        Property dataProperty = dataParent.setProperty(JcrConstants.JCR_DATA, "data");
+        assertSame(dataProperty, dataParent.getPrimaryItem());
+
+        Node contentParent = this.node1.addNode("contentParent");
+        Node contentNode = contentParent.addNode(JcrConstants.JCR_CONTENT);
+        assertSame(contentNode, contentParent.getPrimaryItem());
+    }
+
+    @Test(expected = ItemNotFoundException.class)
+    public void testGetPrimaryItemNotFound() throws RepositoryException {
+        this.node1.getPrimaryItem();
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockNodeTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,240 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.value.BinaryValue;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MockPropertyTest {
+
+    private Session session;
+    private Node rootNode;
+    private Node node1;
+
+    @Before
+    public void setUp() throws RepositoryException {
+        this.session = MockJcr.newSession();
+        this.rootNode = this.session.getRootNode();
+        this.node1 = this.rootNode.addNode("node1");
+    }
+
+    @Test
+    public void testRemove() throws RepositoryException {
+        this.node1.setProperty("prop1", "value1");
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals("value1", prop1.getString());
+
+        prop1.remove();
+        assertFalse(this.node1.hasProperty("prop1"));
+    }
+
+    @Test
+    public void testString() throws RepositoryException {
+        this.node1.setProperty("prop1", "value1");
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals("value1", prop1.getString());
+        assertEquals("value1", prop1.getValue().getString());
+
+        prop1.setValue("value2");
+        assertEquals("value2", prop1.getString());
+        assertEquals("value2", prop1.getValue().getString());
+
+        assertFalse(prop1.isMultiple());
+        assertFalse(prop1.getDefinition().isMultiple());
+        assertEquals(6, prop1.getLength());
+    }
+
+    @Test
+    public void testStringArray() throws RepositoryException {
+        String[] value1 = new String[] { "aaa", "bbb" };
+        this.node1.setProperty("prop1", value1);
+        Property prop1 = this.node1.getProperty("prop1");
+
+        Value[] values = prop1.getValues();
+        for (int i = 0; i < values.length; i++) {
+            assertEquals("value #" + i, value1[i], values[i].getString());
+        }
+
+        String[] value2 = new String[] { "cc" };
+        prop1.setValue(value2);
+        values = prop1.getValues();
+        for (int i = 0; i < values.length; i++) {
+            assertEquals("value #" + i, value2[i], values[i].getString());
+        }
+
+        assertTrue(prop1.isMultiple());
+        assertTrue(prop1.getDefinition().isMultiple());
+        assertArrayEquals(new long[] { 2 }, prop1.getLengths());
+    }
+
+    @Test
+    public void testBoolean() throws RepositoryException {
+        this.node1.setProperty("prop1", true);
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals(true, prop1.getBoolean());
+        assertEquals(true, prop1.getValue().getBoolean());
+
+        prop1.setValue(false);
+        assertEquals(false, prop1.getBoolean());
+        assertEquals(false, prop1.getValue().getBoolean());
+    }
+
+    @Test
+    public void testDouble() throws RepositoryException {
+        this.node1.setProperty("prop1", 1.5d);
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals(1.5d, prop1.getDouble(), 0.001d);
+        assertEquals(1.5d, prop1.getValue().getDouble(), 0.001d);
+
+        prop1.setValue(Double.MAX_VALUE);
+        assertEquals(Double.MAX_VALUE, prop1.getDouble(), 0.001d);
+        assertEquals(Double.MAX_VALUE, prop1.getValue().getDouble(), 0.001d);
+    }
+
+    @Test
+    public void testLong() throws RepositoryException {
+        this.node1.setProperty("prop1", 5L);
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals(5L, prop1.getLong());
+        assertEquals(5L, prop1.getValue().getLong());
+
+        prop1.setValue(Long.MAX_VALUE);
+        assertEquals(Long.MAX_VALUE, prop1.getLong());
+        assertEquals(Long.MAX_VALUE, prop1.getValue().getLong());
+    }
+
+    @Test
+    public void testBigDecimal() throws RepositoryException {
+        this.node1.setProperty("prop1", new BigDecimal("1.5"));
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals(new BigDecimal("1.5"), prop1.getDecimal());
+        assertEquals(new BigDecimal("1.5"), prop1.getValue().getDecimal());
+
+        prop1.setValue(new BigDecimal("99999999.99999"));
+        assertEquals(new BigDecimal("99999999.99999"), prop1.getDecimal());
+        assertEquals(new BigDecimal("99999999.99999"), prop1.getValue().getDecimal());
+    }
+
+    @Test
+    public void testCalendar() throws RepositoryException {
+        Calendar value1 = Calendar.getInstance();
+
+        this.node1.setProperty("prop1", value1);
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals(value1, prop1.getDate());
+        assertEquals(value1, prop1.getValue().getDate());
+
+        Calendar value2 = Calendar.getInstance();
+        value2.add(Calendar.MONTH, -1);
+
+        prop1.setValue(value2);
+        assertEquals(value2, prop1.getDate());
+        assertEquals(value2, prop1.getValue().getDate());
+    }
+
+    @Test
+    public void testBinary() throws RepositoryException, IOException {
+        byte[] value1 = new byte[] { 0x01, 0x01, 0x03 };
+
+        this.node1.setProperty("prop1", new BinaryValue(value1).getBinary());
+        Property prop1 = this.node1.getProperty("prop1");
+        assertArrayEquals(value1, IOUtils.toByteArray(prop1.getBinary().getStream()));
+        assertArrayEquals(value1, IOUtils.toByteArray(prop1.getValue().getBinary().getStream()));
+
+        byte[] value2 = new byte[] { 0x04, 0x05, 0x06 };
+
+        prop1.setValue(new BinaryValue(value2).getBinary());
+        assertArrayEquals(value2, IOUtils.toByteArray(prop1.getBinary().getStream()));
+        assertArrayEquals(value2, IOUtils.toByteArray(prop1.getValue().getBinary().getStream()));
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testInputStream() throws RepositoryException, IOException {
+        byte[] value1 = new byte[] { 0x01, 0x01, 0x03 };
+
+        this.node1.setProperty("prop1", new ByteArrayInputStream(value1));
+        Property prop1 = this.node1.getProperty("prop1");
+        assertArrayEquals(value1, IOUtils.toByteArray(prop1.getStream()));
+
+        byte[] value2 = new byte[] { 0x04, 0x05, 0x06 };
+
+        prop1.setValue(new ByteArrayInputStream(value2));
+        assertArrayEquals(value2, IOUtils.toByteArray(prop1.getValue().getStream()));
+    }
+
+    @Test
+    public void testValue() throws RepositoryException {
+        this.node1.setProperty("prop1", this.session.getValueFactory().createValue("value1"));
+        Property prop1 = this.node1.getProperty("prop1");
+        assertEquals("value1", prop1.getString());
+        assertEquals("value1", prop1.getValue().getString());
+
+        prop1.setValue(this.session.getValueFactory().createValue("value2"));
+        assertEquals("value2", prop1.getString());
+        assertEquals("value2", prop1.getValue().getString());
+
+        assertFalse(prop1.isMultiple());
+        assertFalse(prop1.getDefinition().isMultiple());
+        assertEquals(6, prop1.getLength());
+    }
+
+    @Test
+    public void testValueArray() throws RepositoryException {
+        Value[] value1 = new Value[] { this.session.getValueFactory().createValue("aaa"),
+                this.session.getValueFactory().createValue("bbb") };
+        this.node1.setProperty("prop1", value1);
+        Property prop1 = this.node1.getProperty("prop1");
+
+        Value[] values = prop1.getValues();
+        for (int i = 0; i < values.length; i++) {
+            assertEquals("value #" + i, value1[i].getString(), values[i].getString());
+        }
+
+        Value[] value2 = new Value[] { this.session.getValueFactory().createValue("cc") };
+        prop1.setValue(value2);
+        values = prop1.getValues();
+        for (int i = 0; i < values.length; i++) {
+            assertEquals("value #" + i, value2[i].getString(), values[i].getString());
+        }
+
+        assertTrue(prop1.isMultiple());
+        assertTrue(prop1.getDefinition().isMultiple());
+        assertArrayEquals(new long[] { 2 }, prop1.getLengths());
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockPropertyTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,63 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.SimpleCredentials;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class MockRepositoryTest {
+
+    private static final String USER_NAME = "user";
+    private static final char[] PASSWORD = "pwd".toCharArray();
+
+    private Repository repository;
+
+    @Before
+    public void setUp() {
+        this.repository = MockJcr.newRepository();
+    }
+
+    @Test
+    public void testLogin() throws RepositoryException {
+        assertNotNull(this.repository.login());
+        assertNotNull(this.repository.login(new SimpleCredentials(USER_NAME, PASSWORD)));
+        assertNotNull(this.repository.login(MockJcr.DEFAULT_WORKSPACE));
+        assertNotNull(this.repository.login(new SimpleCredentials(USER_NAME, PASSWORD), MockJcr.DEFAULT_WORKSPACE));
+    }
+
+    @Test
+    public void testDescriptor() {
+        assertEquals(0, this.repository.getDescriptorKeys().length);
+        assertNull(this.repository.getDescriptor("test"));
+        assertNull(this.repository.getDescriptorValue("test"));
+        assertNull(this.repository.getDescriptorValues("test"));
+        assertFalse(this.repository.isStandardDescriptor("test"));
+        assertFalse(this.repository.isSingleValueDescriptor("test"));
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockRepositoryTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,228 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+public class MockSessionTest {
+
+    private Session session;
+
+    @Before
+    public void setUp() {
+        this.session = MockJcr.newSession();
+    }
+
+    @Test
+    public void testEmptySession() throws RepositoryException {
+        Node rootNode = this.session.getRootNode();
+        assertNotNull(rootNode);
+        assertFalse(rootNode.getProperties().hasNext());
+        assertFalse(rootNode.getNodes().hasNext());
+    }
+
+    @Test
+    public void testNodePropertyCreateRead() throws RepositoryException {
+        Node rootNode = this.session.getNode("/");
+        assertSame(rootNode, this.session.getRootNode());
+
+        Node node1 = rootNode.addNode("node1");
+        node1.setProperty("prop1a", "value1a");
+        node1.setProperty("prop1b", "value1b");
+
+        Node node2 = rootNode.addNode("node2");
+        node2.setProperty("prop2", "value2");
+
+        assertSame(node1, rootNode.getNode("node1"));
+        assertSame(node1, this.session.getNode("/node1"));
+        assertSame(node1, this.session.getItem("/node1"));
+        assertSame(node1, this.session.getNodeByIdentifier(node1.getIdentifier()));
+        assertTrue(this.session.nodeExists("/node1"));
+        assertTrue(this.session.itemExists("/node1"));
+        assertSame(node2, rootNode.getNode("node2"));
+        assertSame(node2, this.session.getNode("/node2"));
+        assertSame(node2, this.session.getItem("/node2"));
+        assertSame(node2, this.session.getNodeByIdentifier(node2.getIdentifier()));
+        assertTrue(this.session.nodeExists("/node2"));
+        assertTrue(this.session.itemExists("/node2"));
+
+        Property prop1a = node1.getProperty("prop1a");
+        Property prop1b = node1.getProperty("prop1b");
+        Property prop2 = node2.getProperty("prop2");
+
+        assertSame(prop1a, this.session.getProperty("/node1/prop1a"));
+        assertSame(prop1a, this.session.getItem("/node1/prop1a"));
+        assertTrue(this.session.propertyExists("/node1/prop1a"));
+        assertTrue(this.session.itemExists("/node1/prop1a"));
+        assertSame(prop1b, this.session.getProperty("/node1/prop1b"));
+        assertSame(prop1b, this.session.getItem("/node1/prop1b"));
+        assertTrue(this.session.propertyExists("/node1/prop1b"));
+        assertTrue(this.session.itemExists("/node1/prop1b"));
+        assertSame(prop2, this.session.getProperty("/node2/prop2"));
+        assertSame(prop2, this.session.getItem("/node2/prop2"));
+        assertTrue(this.session.propertyExists("/node2/prop2"));
+        assertTrue(this.session.itemExists("/node2/prop2"));
+
+        assertEquals("value1a", prop1a.getString());
+        assertEquals("value1b", prop1b.getString());
+        assertEquals("value2", prop2.getString());
+
+        assertFalse(this.session.propertyExists("/node1"));
+        assertFalse(this.session.nodeExists("/node1/prop1a"));
+
+        assertEquals(JcrConstants.NT_UNSTRUCTURED, node1.getPrimaryNodeType().getName());
+        assertTrue(node1.isNodeType(JcrConstants.NT_UNSTRUCTURED));
+        assertTrue(node1.getPrimaryNodeType().isNodeType(JcrConstants.NT_UNSTRUCTURED));
+
+    }
+
+    @Test
+    public void testNodeRemove() throws RepositoryException {
+        Node rootNode = this.session.getRootNode();
+        Node node1 = rootNode.addNode("node1");
+        assertTrue(this.session.itemExists("/node1"));
+        node1.remove();
+        assertFalse(this.session.itemExists("/node1"));
+        assertFalse(rootNode.getNodes().hasNext());
+    }
+
+    @Test
+    public void testNodesWithSpecialNames() throws RepositoryException {
+        Node rootNode = this.session.getRootNode();
+
+        Node node1 = rootNode.addNode("node1.ext");
+        Node node11 = node1.addNode("Node Name With Spaces");
+        node11.setProperty("prop11", "value11");
+        Node node12 = node1.addNode("node12_ext");
+        node12.setProperty("prop12", "value12");
+
+        assertTrue(this.session.itemExists("/node1.ext"));
+        assertTrue(this.session.itemExists("/node1.ext/Node Name With Spaces"));
+        assertTrue(this.session.itemExists("/node1.ext/node12_ext"));
+
+        assertEquals("value11", node11.getProperty("prop11").getString());
+        assertEquals("value12", node12.getProperty("prop12").getString());
+
+        NodeIterator nodes = node1.getNodes();
+        assertEquals(2, nodes.getSize());
+    }
+
+    @Test
+    public void testItemsExists() throws RepositoryException {
+        assertFalse(this.session.nodeExists("/node1"));
+        assertFalse(this.session.itemExists("/node2"));
+        assertFalse(this.session.propertyExists("/node1/prop1"));
+    }
+
+    @Test(expected = PathNotFoundException.class)
+    public void testNodeNotFoundException() throws RepositoryException {
+        this.session.getNode("/node1");
+    }
+
+    @Test(expected = PathNotFoundException.class)
+    public void testPropertyNotFoundException() throws RepositoryException {
+        this.session.getProperty("/node1/prop1");
+    }
+
+    @Test(expected = PathNotFoundException.class)
+    public void testItemNotFoundException() throws RepositoryException {
+        this.session.getItem("/node2");
+    }
+
+    @Test(expected = ItemNotFoundException.class)
+    public void testIdentifierFoundException() throws RepositoryException {
+        this.session.getNodeByIdentifier("unknown");
+    }
+
+    @Test
+    public void testNamespaces() throws RepositoryException {
+        // test initial namespaces
+        assertArrayEquals(new String[] { "jcr" }, this.session.getNamespacePrefixes());
+        assertEquals("http://www.jcp.org/jcr/1.0", this.session.getNamespaceURI("jcr"));
+        assertEquals("jcr", this.session.getNamespacePrefix("http://www.jcp.org/jcr/1.0"));
+
+        // add dummy namespace
+        this.session.setNamespacePrefix("dummy", "http://mydummy");
+
+        assertEquals(ImmutableSet.of("jcr", "dummy"), ImmutableSet.copyOf(this.session.getNamespacePrefixes()));
+        assertEquals("http://mydummy", this.session.getNamespaceURI("dummy"));
+        assertEquals("dummy", this.session.getNamespacePrefix("http://mydummy"));
+
+        // test via namespace registry
+        NamespaceRegistry namespaceRegistry = this.session.getWorkspace().getNamespaceRegistry();
+
+        assertEquals(ImmutableSet.of("jcr", "dummy"), ImmutableSet.copyOf(namespaceRegistry.getPrefixes()));
+        assertEquals(ImmutableSet.of("http://www.jcp.org/jcr/1.0", "http://mydummy"),
+                ImmutableSet.copyOf(namespaceRegistry.getURIs()));
+        assertEquals("http://mydummy", namespaceRegistry.getURI("dummy"));
+        assertEquals("dummy", namespaceRegistry.getPrefix("http://mydummy"));
+
+        // remove dummy namespace
+        namespaceRegistry.unregisterNamespace("dummy");
+
+        assertEquals(ImmutableSet.of("jcr"), ImmutableSet.copyOf(this.session.getNamespacePrefixes()));
+        assertEquals("http://www.jcp.org/jcr/1.0", this.session.getNamespaceURI("jcr"));
+        assertEquals("jcr", this.session.getNamespacePrefix("http://www.jcp.org/jcr/1.0"));
+    }
+
+    @Test
+    public void testUserId() {
+        assertEquals("mockedUserId", this.session.getUserID());
+    }
+
+    @Test
+    public void testSaveRefresh() throws RepositoryException {
+        // methods can be called without any effect
+        assertFalse(this.session.hasPendingChanges());
+        this.session.save();
+        this.session.refresh(true);
+        this.session.refresh(false);
+    }
+
+    @Test
+    public void testGetRepository() {
+        assertNotNull(this.session.getRepository());
+    }
+
+    @Test
+    public void testCheckPermission() throws RepositoryException {
+        this.session.checkPermission("/any/path", "anyActions");
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockSessionTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,64 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Workspace;
+import javax.jcr.observation.ObservationManager;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class MockWorkspaceTest {
+
+    private Workspace underTest;
+
+    @Before
+    public void setUp() {
+        underTest = MockJcr.newSession().getWorkspace();
+    }
+
+    @Test
+    public void testName() {
+        assertEquals(MockJcr.DEFAULT_WORKSPACE, underTest.getName());
+    }
+
+    @Test
+    public void testNameSpaceRegistry() throws RepositoryException {
+        assertNotNull(underTest.getNamespaceRegistry());
+    }
+
+    @Test
+    public void testObservationManager() throws RepositoryException {
+        // just mage sure listener methods can be called, although they do
+        // nothing
+        ObservationManager observationManager = underTest.getObservationManager();
+        observationManager.addEventListener(null, 0, null, false, null, null, false);
+        observationManager.removeEventListener(null);
+    }
+
+    @Test
+    public void testNodeTypeManager() throws RepositoryException {
+        assertNotNull(underTest.getNodeTypeManager());
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/MockWorkspaceTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java (added)
+++ sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,221 @@
+/*
+ * 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.sling.testing.mock.jcr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+public class ResourceUtilTest {
+
+    @Test
+    public void testResolveRelativeSegments() {
+
+        assertEquals("/", ResourceUtil.normalize("/"));
+        assertEquals("/", ResourceUtil.normalize("///"));
+
+        assertEquals("/a/b/c", ResourceUtil.normalize("/a//b/c"));
+        assertEquals("/a/b/c", ResourceUtil.normalize("/a/b//c"));
+        assertEquals("/a/b/c", ResourceUtil.normalize("/a///b///c"));
+        assertEquals("/a/b/c", ResourceUtil.normalize("/a/b/c/"));
+        assertEquals("/a/b/c", ResourceUtil.normalize("/a/b/c//"));
+        assertEquals("/a/b/c", ResourceUtil.normalize("/a/b/c///"));
+
+        assertEquals("/az/bz/cz", ResourceUtil.normalize("/az//bz/cz"));
+        assertEquals("/az/bz/cz", ResourceUtil.normalize("/az/bz//cz"));
+        assertEquals("/az/bz/cz", ResourceUtil.normalize("/az///bz///cz"));
+        assertEquals("/az/bz/cz", ResourceUtil.normalize("/az/bz/cz/"));
+        assertEquals("/az/bz/cz", ResourceUtil.normalize("/az/bz/cz//"));
+        assertEquals("/az/bz/cz", ResourceUtil.normalize("/az/bz/cz///"));
+
+        assertEquals("/a", ResourceUtil.normalize("/a"));
+        assertEquals("/a", ResourceUtil.normalize("//a"));
+        assertEquals("/a", ResourceUtil.normalize("///a"));
+
+        assertEquals("/az", ResourceUtil.normalize("/az"));
+        assertEquals("/az", ResourceUtil.normalize("//az"));
+        assertEquals("/az", ResourceUtil.normalize("///az"));
+
+        assertEquals("/", ResourceUtil.normalize("/."));
+        assertEquals("/a", ResourceUtil.normalize("/a/."));
+        assertEquals("/a", ResourceUtil.normalize("/./a"));
+        assertEquals("/a/b", ResourceUtil.normalize("/a/./b"));
+        assertEquals("/a/b", ResourceUtil.normalize("/a/b/."));
+        assertEquals("/a/b", ResourceUtil.normalize("/a/./b/."));
+
+        assertEquals("/", ResourceUtil.normalize("/."));
+        assertEquals("/az", ResourceUtil.normalize("/az/."));
+        assertEquals("/az", ResourceUtil.normalize("/./az"));
+        assertEquals("/az/bz", ResourceUtil.normalize("/az/./bz"));
+        assertEquals("/az/bz", ResourceUtil.normalize("/az/bz/."));
+        assertEquals("/az/bz", ResourceUtil.normalize("/az/./bz/."));
+
+        assertNull(ResourceUtil.normalize("/.."));
+        assertNull(ResourceUtil.normalize("/.."));
+        assertEquals("/", ResourceUtil.normalize("/a/.."));
+        assertEquals("/a", ResourceUtil.normalize("/a/b/.."));
+        assertEquals("/", ResourceUtil.normalize("/a/b/../.."));
+        assertNull(ResourceUtil.normalize("/a/b/../../.."));
+
+        assertNull(ResourceUtil.normalize("/.."));
+        assertNull(ResourceUtil.normalize("/.."));
+        assertEquals("/", ResourceUtil.normalize("/az/.."));
+        assertEquals("/az", ResourceUtil.normalize("/az/bz/.."));
+        assertEquals("/", ResourceUtil.normalize("/az/bz/../.."));
+        assertNull(ResourceUtil.normalize("/az/bz/../../.."));
+
+        assertEquals("/b", ResourceUtil.normalize("/a/../b"));
+        assertEquals("/a/c", ResourceUtil.normalize("/a/b/../c"));
+        assertEquals("/c", ResourceUtil.normalize("/a/b/../../c"));
+        assertNull(ResourceUtil.normalize("/a/b/../../../c"));
+
+        assertEquals("/bz", ResourceUtil.normalize("/az/../bz"));
+        assertEquals("/az/cz", ResourceUtil.normalize("/az/bz/../cz"));
+        assertEquals("/cz", ResourceUtil.normalize("/az/bz/../../cz"));
+        assertNull(ResourceUtil.normalize("/az/bz/../../../cz"));
+
+        assertEquals("/...", ResourceUtil.normalize("/..."));
+        assertEquals("/a/...", ResourceUtil.normalize("/a/..."));
+        assertEquals("/a/b/...", ResourceUtil.normalize("/a/b/..."));
+
+        assertEquals("/az/...", ResourceUtil.normalize("/az/..."));
+        assertEquals("/az/bz/...", ResourceUtil.normalize("/az/bz/..."));
+
+        try {
+            ResourceUtil.normalize(null);
+            fail("Resolving null expects NullPointerException");
+        } catch (NullPointerException npe) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testResolveRelativeSegmentsRelative() {
+        assertEquals("a/b", ResourceUtil.normalize("a/b"));
+        assertEquals("a", ResourceUtil.normalize("a/b/.."));
+
+        assertEquals("b", ResourceUtil.normalize("a/../b"));
+        assertEquals("a/c", ResourceUtil.normalize("a/b/../c"));
+        assertEquals("c", ResourceUtil.normalize("a/b/../../c"));
+        assertEquals("", ResourceUtil.normalize("a/b/../.."));
+        assertEquals("a/c/d", ResourceUtil.normalize("a/b/../c/d"));
+        assertNull(ResourceUtil.normalize("a/b/../../../c"));
+
+        assertEquals("a/b/c", ResourceUtil.normalize("a/b/c"));
+        assertEquals("az/bz/cz", ResourceUtil.normalize("az/bz/cz"));
+        assertEquals("", ResourceUtil.normalize(""));
+    }
+
+    @Test
+    public void testGetParent() {
+        assertNull(ResourceUtil.getParent("/"));
+        assertNull(ResourceUtil.getParent("/.."));
+
+        assertEquals("/", ResourceUtil.getParent("/b"));
+        assertEquals("b/c", ResourceUtil.getParent("b/c/d"));
+        assertEquals("/b/c", ResourceUtil.getParent("/b/c/d"));
+
+        assertNull(ResourceUtil.getParent("b"));
+        assertNull(ResourceUtil.getParent("/b/.."));
+
+        assertEquals("security:/", ResourceUtil.getParent("security:/b"));
+        assertEquals("security:/b", ResourceUtil.getParent("security:/b/c"));
+        assertEquals("security:/b/c", ResourceUtil.getParent("security:/b/c/d"));
+    }
+
+    @Test
+    public void testGetName() {
+        assertEquals("", ResourceUtil.getName("/"));
+        assertEquals("", ResourceUtil.getName("/a/.."));
+
+        assertEquals("c", ResourceUtil.getName("c"));
+        assertEquals("c", ResourceUtil.getName("/c"));
+
+        assertEquals("c", ResourceUtil.getName("b/c"));
+        assertEquals("c", ResourceUtil.getName("/b/c"));
+
+        assertEquals("c", ResourceUtil.getName("b/c/"));
+        assertEquals("c", ResourceUtil.getName("/b/c/"));
+
+        assertEquals("b", ResourceUtil.getName("b/c/.."));
+        assertEquals("b", ResourceUtil.getName("/b/c/.."));
+        assertEquals("", ResourceUtil.getName("/b/c/../.."));
+    }
+
+    @Test
+    public void testGetParentLevel() throws Exception {
+        boolean caughtNullPointerException = false;
+        try {
+            ResourceUtil.getParent(null, 4);
+        } catch (NullPointerException e) {
+            // Expected exception
+            caughtNullPointerException = true;
+        } catch (Exception e) {
+            fail("Expected NullPointerException, but caught " + e.getClass().getName() + " instead.");
+        }
+        if (!caughtNullPointerException) {
+            fail("Expected NullPointerException, but no exception was thrown.");
+        }
+
+        boolean caughtIllegalArgumentException = false;
+        try {
+            ResourceUtil.getParent("/a/b", -2);
+        } catch (IllegalArgumentException e) {
+            // Expected exception
+            caughtIllegalArgumentException = true;
+        } catch (Exception e) {
+            fail("Expected IllegalArgumentException, but caught " + e.getClass().getName() + " instead.");
+        }
+        if (!caughtIllegalArgumentException) {
+            fail("Expected IllegalArgumentException, but no exception was thrown.");
+        }
+
+        assertNull(ResourceUtil.getParent("/a", 4));
+        assertNull(ResourceUtil.getParent("/", 1));
+        assertNull(ResourceUtil.getParent("b/c", 2));
+        assertNull(ResourceUtil.getParent("/b/..", 1));
+        assertNull(ResourceUtil.getParent("b", 1));
+        assertNull(ResourceUtil.getParent("", 3));
+        assertNull(ResourceUtil.getParent("/..", 1));
+        assertNull(ResourceUtil.getParent("security:/b", 2));
+        assertNull(ResourceUtil.getParent("/b///", 2));
+
+        assertEquals("", ResourceUtil.getParent("", 0));
+        assertEquals("b", ResourceUtil.getParent("b", 0));
+        assertEquals("/", ResourceUtil.getParent("/", 0));
+        assertEquals("/a/b", ResourceUtil.getParent("/a/b", 0));
+        assertEquals("security:/b", ResourceUtil.getParent("security:/b", 0));
+
+        assertEquals("/", ResourceUtil.getParent("/b", 1));
+        assertEquals("b", ResourceUtil.getParent("b/c", 1));
+        assertEquals("b/c", ResourceUtil.getParent("b/c/d", 1));
+        assertEquals("/b/c", ResourceUtil.getParent("/b/c/d", 1));
+        assertEquals("security:/", ResourceUtil.getParent("security:/b", 1));
+        assertEquals("security:/b", ResourceUtil.getParent("security:/b/c", 1));
+        assertEquals("security:/b/c", ResourceUtil.getParent("security:/b/c/d", 1));
+
+        assertEquals("b", ResourceUtil.getParent("b/c/d", 2));
+        assertEquals("b/c", ResourceUtil.getParent("b/c/d/e", 2));
+        assertEquals("/", ResourceUtil.getParent("/b/c/d", 3));
+        assertEquals("/", ResourceUtil.getParent("/b///", 1));
+    }
+
+}

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/jcr-mock/src/test/java/org/apache/sling/testing/mock/jcr/ResourceUtilTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain