blob: 82624093b84c7b4c12cf81fe8aef8e8e22b7cff3 [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.core;
import static org.apache.jackrabbit.oak.api.Type.LONG;
import static org.apache.jackrabbit.oak.api.Type.STRING;
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 static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.OakBaseTest;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Tree.Status;
import org.apache.jackrabbit.oak.fixture.NodeStoreFixture;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.memory.LongPropertyState;
import org.apache.jackrabbit.oak.plugins.memory.StringBasedBlob;
import org.apache.jackrabbit.oak.plugins.tree.TreeConstants;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* MutableTreeTest...
*/
public class MutableTreeTest extends OakBaseTest {
private Root root;
public MutableTreeTest(NodeStoreFixture fixture) {
super(fixture);
}
@Before
public void setUp() throws CommitFailedException {
ContentSession session = createContentSession();
// Add test content
root = session.getLatestRoot();
Tree tree = root.getTree("/");
tree.setProperty("a", 1);
tree.setProperty("b", 2);
tree.setProperty("c", 3);
tree.addChild("x");
tree.addChild("y");
tree.addChild("z");
root.commit();
// Acquire a fresh new root to avoid problems from lingering state
root = session.getLatestRoot();
}
@After
public void tearDown() {
root = null;
}
@Test
public void getChild() {
Tree tree = root.getTree("/");
Tree child = tree.getChild("any");
assertFalse(child.exists());
child = tree.getChild("x");
assertTrue(child.exists());
}
@Test
public void getProperty() {
Tree tree = root.getTree("/");
PropertyState propertyState = tree.getProperty("any");
assertNull(propertyState);
propertyState = tree.getProperty("a");
assertNotNull(propertyState);
assertFalse(propertyState.isArray());
assertEquals(LONG, propertyState.getType());
assertEquals(1, (long) propertyState.getValue(LONG));
}
@Test
public void getChildren() {
Tree tree = root.getTree("/");
Iterable<Tree> children = tree.getChildren();
Set<String> expectedPaths = new HashSet<String>();
Collections.addAll(expectedPaths, "/x", "/y", "/z");
for (Tree child : children) {
assertTrue(expectedPaths.remove(child.getPath()));
}
assertTrue(expectedPaths.isEmpty());
assertEquals(3, tree.getChildrenCount(4));
}
@Test
public void getProperties() {
Tree tree = root.getTree("/");
Set<PropertyState> expectedProperties = Sets.newHashSet(
LongPropertyState.createLongProperty("a", 1L),
LongPropertyState.createLongProperty("b", 2L),
LongPropertyState.createLongProperty("c", 3L));
Iterable<? extends PropertyState> properties = tree.getProperties();
for (PropertyState property : properties) {
assertTrue(expectedProperties.remove(property));
}
assertTrue(expectedProperties.isEmpty());
assertEquals(3, tree.getPropertyCount());
}
@Test
public void addChild() throws CommitFailedException {
Tree tree = root.getTree("/");
assertFalse(tree.hasChild("new"));
Tree added = tree.addChild("new");
assertTrue(added.exists());
assertEquals("new", added.getName());
assertTrue(tree.hasChild("new"));
root.commit();
assertTrue(tree.hasChild("new"));
tree.getChild("new").addChild("more");
assertTrue(tree.getChild("new").hasChild("more"));
}
@Test
public void addExistingChild() throws CommitFailedException {
Tree tree = root.getTree("/");
assertFalse(tree.hasChild("new"));
tree.addChild("new");
root.commit();
assertTrue(tree.hasChild("new"));
Tree added = tree.addChild("new");
assertTrue(added.exists());
assertEquals("new", added.getName());
}
@Test
public void removeChild() throws CommitFailedException {
Tree tree = root.getTree("/");
assertTrue(tree.hasChild("x"));
tree.getChild("x").remove();
assertFalse(tree.hasChild("x"));
root.commit();
assertFalse(tree.hasChild("x"));
}
@Test
public void removeNew() {
Tree tree = root.getTree("/");
Tree t = tree.addChild("new");
tree.getChild("new").remove();
assertFalse(t.exists());
assertFalse(tree.getChild("new").exists());
}
@Test
public void setProperty() throws CommitFailedException {
Tree tree = root.getTree("/");
assertFalse(tree.hasProperty("new"));
tree.setProperty("new", "value");
PropertyState property = tree.getProperty("new");
assertNotNull(property);
assertEquals("new", property.getName());
assertEquals("value", property.getValue(STRING));
root.commit();
property = tree.getProperty("new");
assertNotNull(property);
assertEquals("new", property.getName());
assertEquals("value", property.getValue(STRING));
}
@Test
public void removeProperty() throws CommitFailedException {
Tree tree = root.getTree("/");
assertTrue(tree.hasProperty("a"));
tree.removeProperty("a");
assertFalse(tree.hasProperty("a"));
root.commit();
assertFalse(tree.hasProperty("a"));
}
@Test
public void getChildrenCount() {
Tree tree = root.getTree("/");
assertEquals(3, tree.getChildrenCount(4));
tree.getChild("x").remove();
assertEquals(2, tree.getChildrenCount(3));
tree.addChild("a");
assertEquals(3, tree.getChildrenCount(3));
tree.addChild("x");
assertEquals(4, tree.getChildrenCount(5));
}
@Test
public void getPropertyCount() {
Tree tree = root.getTree("/");
assertEquals(3, tree.getPropertyCount());
tree.setProperty("a", "foo");
assertEquals(3, tree.getPropertyCount());
tree.removeProperty("a");
assertEquals(2, tree.getPropertyCount());
tree.setProperty("x", "foo");
assertEquals(3, tree.getPropertyCount());
tree.setProperty("a", "foo");
assertEquals(4, tree.getPropertyCount());
}
@Test
public void addAndRemoveProperty() throws CommitFailedException {
Tree tree = root.getTree("/");
tree.setProperty("P0", "V1");
root.commit();
assertTrue(tree.hasProperty("P0"));
tree.removeProperty("P0");
root.commit();
assertFalse(tree.hasProperty("P0"));
}
@Test
public void nodeStatus() throws CommitFailedException {
Tree tree = root.getTree("/");
tree.addChild("new");
assertEquals(Tree.Status.NEW, tree.getChild("new").getStatus());
root.commit();
assertEquals(Tree.Status.UNCHANGED, tree.getChild("new").getStatus());
Tree added = tree.getChild("new");
added.addChild("another");
assertEquals(Tree.Status.MODIFIED, tree.getChild("new").getStatus());
root.commit();
assertEquals(Tree.Status.UNCHANGED, tree.getChild("new").getStatus());
tree.getChild("new").getChild("another").remove();
assertEquals(Tree.Status.MODIFIED, tree.getChild("new").getStatus());
root.commit();
assertEquals(Tree.Status.UNCHANGED, tree.getChild("new").getStatus());
assertFalse(tree.getChild("new").getChild("another").exists());
Tree x = root.getTree("/x");
Tree y = x.addChild("y");
x.remove();
assertFalse(x.exists());
assertFalse(y.exists());
}
@Test
public void isNew() throws CommitFailedException {
Tree tree = root.getTree("/");
tree.addChild("c");
root.commit();
tree.getChild("c").remove();
Tree c = tree.addChild("c");
assertEquals(Status.NEW, c.getStatus());
}
@Test
public void modifiedAfterRebase() throws CommitFailedException {
Tree tree = root.getTree("/");
tree.addChild("new");
assertEquals(Status.MODIFIED, tree.getStatus());
root.rebase();
assertEquals(Status.MODIFIED, tree.getStatus());
}
@Test
public void propertyStatus() throws CommitFailedException {
Tree tree = root.getTree("/");
tree.setProperty("new", "value1");
assertEquals(Tree.Status.NEW, tree.getPropertyStatus("new"));
root.commit();
assertEquals(Tree.Status.UNCHANGED, tree.getPropertyStatus("new"));
tree.setProperty("new", "value2");
assertEquals(Tree.Status.MODIFIED, tree.getPropertyStatus("new"));
root.commit();
assertEquals(Tree.Status.UNCHANGED, tree.getPropertyStatus("new"));
tree.removeProperty("new");
assertNull(tree.getPropertyStatus("new"));
root.commit();
assertNull(tree.getPropertyStatus("new"));
Tree x = root.getTree("/x");
x.setProperty("y", "value1");
x.remove();
}
@Test
public void noTransitiveModifiedStatus() throws CommitFailedException {
Tree tree = root.getTree("/");
tree.addChild("one").addChild("two");
root.commit();
tree.getChild("one").getChild("two").addChild("three");
assertEquals(Tree.Status.UNCHANGED, tree.getChild("one").getStatus());
assertEquals(Tree.Status.MODIFIED, tree.getChild("one").getChild("two").getStatus());
}
@Test
public void largeChildList() throws CommitFailedException {
Tree tree = root.getTree("/");
Set<String> added = new HashSet<String>();
Tree large = tree.addChild("large");
for (int c = 0; c < 10000; c++) {
String name = "n" + c;
added.add(name);
large.addChild(name);
}
root.commit();
for (Tree child : large.getChildren()) {
assertTrue(added.remove(child.getName()));
}
assertTrue(added.isEmpty());
}
@Test
public void testSetOrderableChildrenSetsProperty() throws Exception {
Tree tree = root.getTree("/").addChild("test");
tree.setOrderableChildren(true);
assertTrue(((MutableTree) tree).getNodeState().hasProperty(TreeConstants.OAK_CHILD_ORDER));
tree.setOrderableChildren(false);
assertFalse(((MutableTree) tree).getNodeState().hasProperty(TreeConstants.OAK_CHILD_ORDER));
tree.setOrderableChildren(true);
root.commit();
assertTrue(((MutableTree) tree).getNodeState().hasProperty(TreeConstants.OAK_CHILD_ORDER));
tree.setOrderableChildren(false);
root.commit();
assertFalse(((MutableTree) tree).getNodeState().hasProperty(TreeConstants.OAK_CHILD_ORDER));
}
@Test
public void testSetOrderableChildren() throws Exception {
Tree tree = root.getTree("/").addChild("test2");
tree.setOrderableChildren(true);
String[] childNames = new String[]{"a", "b", "c", "d"};
for (String name : childNames) {
tree.addChild(name);
}
int index = 0;
for (Tree child : tree.getChildren()) {
assertEquals(childNames[index++], child.getName());
}
}
@Test
public void testDisconnectAfterRefresh() {
Tree x = root.getTree("/x");
x.setProperty("p", "any");
Tree xx = x.addChild("xx");
xx.setProperty("q", "any");
assertEquals(Status.MODIFIED, x.getStatus());
assertEquals(Status.NEW, x.getPropertyStatus("p"));
assertEquals(Status.NEW, xx.getStatus());
assertEquals(Status.NEW, xx.getPropertyStatus("q"));
root.refresh();
assertEquals(Status.UNCHANGED, x.getStatus());
assertNull(x.getPropertyStatus("p"));
assertFalse(xx.exists());
}
@Test
public void testDisconnectAfterRemove() {
Tree x = root.getTree("/x");
x.setProperty("p", "any");
Tree xx = x.addChild("xx");
xx.setProperty("q", "any");
assertEquals(Status.MODIFIED, x.getStatus());
assertEquals(Status.NEW, x.getPropertyStatus("p"));
assertEquals(Status.NEW, xx.getStatus());
assertEquals(Status.NEW, xx.getPropertyStatus("q"));
root.getTree("/x").remove();
assertFalse(x.exists());
assertFalse(xx.exists());
}
@Test
public void testBlob() throws CommitFailedException, IOException {
Blob expected = new StringBasedBlob("test blob");
root.getTree("/x").setProperty("blob", expected);
root.commit();
Blob actual = root.getTree("/x").getProperty("blob").getValue(Type.BINARY);
assertEquals(expected, actual);
assertTrue(expected.getNewStream().available() >= 0);
assertTrue(actual.getNewStream().available() >= 0);
}
}