blob: 42af9313fe21b3731f31e3a4308a37fdc275d151 [file] [log] [blame]
/*
* 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.secondary;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.document.AbstractDocumentNodeState;
import org.apache.jackrabbit.oak.plugins.document.DocumentMKBuilderProvider;
import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
import org.apache.jackrabbit.oak.plugins.document.NodeStateDiffer;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
import org.apache.jackrabbit.oak.spi.filter.PathFilter;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import static com.google.common.collect.ImmutableList.of;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class SecondaryStoreObserverTest {
private final List<String> empty = Collections.emptyList();
@Rule
public DocumentMKBuilderProvider builderProvider = new DocumentMKBuilderProvider();
private DocumentNodeStore primary;
private NodeStore secondary;
@Before
public void setUp() throws IOException {
primary = builderProvider.newBuilder().getNodeStore();
secondary = new MemoryNodeStore();
}
@Test
public void basicSetup() throws Exception{
PathFilter pathFilter = new PathFilter(of("/a"), empty);
SecondaryStoreObserver observer = createBuilder(pathFilter).buildObserver();
primary.addObserver(observer);
NodeBuilder nb = primary.getRoot().builder();
create(nb, "/a/b", "/a/c", "/x/y/z");
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
dump(secondaryRoot(), "/a");
dump(primary.getRoot(), "/a");
assertEquals(secondaryRoot().getChildNode("a"),
primary.getRoot().getChildNode("a"));
}
@Test
public void childNodeAdded() throws Exception{
PathFilter pathFilter = new PathFilter(of("/a"), empty);
SecondaryStoreObserver observer = createBuilder(pathFilter).buildObserver();
primary.addObserver(observer);
NodeBuilder nb = primary.getRoot().builder();
create(nb, "/a/b", "/a/c", "/x/y/z");
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
nb = primary.getRoot().builder();
create(nb, "/a/d");
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
assertMetaState(primary.getRoot(), secondaryRoot(), "/a/d");
assertMetaState(primary.getRoot(), secondaryRoot(), "/a");
}
@Test
public void childNodeChangedAndExclude() throws Exception{
PathFilter pathFilter = new PathFilter(of("/a"), of("a/b"));
SecondaryStoreObserver observer = createBuilder(pathFilter).buildObserver();
primary.addObserver(observer);
NodeBuilder nb = primary.getRoot().builder();
create(nb, "/a/b", "/a/c", "/x/y/z");
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
nb = primary.getRoot().builder();
create(nb, "/a/d", "/a/b/e");
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
assertMetaState(primary.getRoot(), secondaryRoot(), "/a/d");
}
@Test
public void childNodeDeleted() throws Exception{
PathFilter pathFilter = new PathFilter(of("/a"), empty);
SecondaryStoreObserver observer = createBuilder(pathFilter).buildObserver();
primary.addObserver(observer);
NodeBuilder nb = primary.getRoot().builder();
create(nb, "/a/b", "/a/c", "/x/y/z");
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
nb = primary.getRoot().builder();
nb.child("a").child("c").remove();
primary.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
assertFalse(NodeStateUtils.getNode(secondaryRoot(), "/a/c").exists());
}
private NodeState secondaryRoot() {
return DelegatingDocumentNodeState.wrap(secondary.getRoot(), NodeStateDiffer.DEFAULT_DIFFER);
}
private SecondaryStoreBuilder createBuilder(PathFilter pathFilter) {
return new SecondaryStoreBuilder(secondary).pathFilter(pathFilter);
}
private static void assertMetaState(NodeState root1, NodeState root2, String path){
assertMetaState(documentState(root1, path), documentState(root2, path));
}
private static void assertMetaState(AbstractDocumentNodeState a, AbstractDocumentNodeState b){
assertEquals(a.getLastRevision(), b.getLastRevision());
assertEquals(a.getRootRevision(), b.getRootRevision());
assertEquals(a.getPath(), b.getPath());
}
static AbstractDocumentNodeState documentState(NodeState root, String path){
return (AbstractDocumentNodeState) NodeStateUtils.getNode(root, path);
}
private static void dump(NodeState root, String path){
NodeState state = NodeStateUtils.getNode(root, path);
System.out.println(NodeStateUtils.toString(state));
}
static NodeState create(NodeBuilder b, String ... paths){
for (String path : paths){
NodeBuilder cb = b;
for (String pathElement : PathUtils.elements(path)){
cb = cb.child(pathElement);
}
}
return b.getNodeState();
}
}