/*
* ModeShape (http://www.modeshape.org)
*
* Licensed 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.modeshape.jcr.value.basic;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.modeshape.jcr.value.Name;
import org.modeshape.jcr.value.Path;
/**
* @author Randall Hauch
* @author John Verhaeg
*/
public class ChildPathTest extends AbstractPathTest {
protected Path parent;
protected Path root;
protected Path.Segment childSegment;
@Before
@Override
public void beforeEach() {
super.beforeEach();
// parent = mock(Path.class);
parent = path("/a/b/c");
childSegment = segment("d");
path = new ChildPath(parent, childSegment);
root = RootPath.INSTANCE;
}
protected Path path( String path ) {
path = path.trim();
if ("/".equals(path)) return RootPath.INSTANCE;
boolean absolute = path.startsWith("/");
path = path.replaceAll("^/+", "").replaceAll("/+$", ""); // remove leading and trailing slashes
String[] segmentStrings = path.split("/");
List<Path.Segment> segments = new ArrayList<Path.Segment>(segmentStrings.length);
for (String segmentString : segmentStrings) {
Name name = new BasicName("", segmentString);
Path.Segment segment = new BasicPathSegment(name);
segments.add(segment);
}
return new BasicPath(segments, absolute);
}
protected Path.Segment segment( String segment ) {
Name name = new BasicName("", segment);
return new BasicPathSegment(name);
}
@Test
public void shouldReturnParentForAncestorOfDegreeOne() {
assertThat(path.getAncestor(1), is(sameInstance(parent)));
assertThat(path.getParent(), is(sameInstance(parent)));
}
@Test
public void shouldDelegateToParentForAncestorOfDegreeGreaterThanOne() {
parent = mock(Path.class);
when(parent.getAncestor(anyInt())).thenReturn(null);
path = new ChildPath(parent, segment("d"));
for (int i = 2; i != 10; ++i) {
path.getAncestor(i);
verify(parent).getAncestor(i - 1);
}
}
@Test
public void shouldConsiderChildPathToBeDecendantOfParent() {
assertThat(path.isDescendantOf(parent), is(true));
}
@Test
public void shouldConsiderChildPathToNotBeAncestorOfParent() {
assertThat(path.isAncestorOf(parent), is(false));
}
@Test
public void shouldConsiderParentNotBeDecendantOfChildPath() {
assertThat(parent.isDescendantOf(path), is(false));
}
@Test
public void shouldConsiderPathDecendantOfOtherPathIfParentIsAtOrBelowOtherPath() {
parent = mock(Path.class);
path = new ChildPath(parent, segment("d"));
Path other = mock(Path.class);
when(parent.isAtOrBelow(other)).thenReturn(true);
assertThat(path.isDescendantOf(other), is(true));
verify(parent).isAtOrBelow(other);
when(parent.isAtOrBelow(other)).thenReturn(false);
assertThat(path.isDescendantOf(other), is(false));
verify(parent, times(2)).isAtOrBelow(other);
}
@Test
public void shouldConsiderPathDecendantOfOtherParentPath() {
assertThat(path.isDescendantOf(parent), is(true));
}
@Test
public void shouldReturnChildSegmentFromGetLastSegment() {
assertThat(path.getLastSegment(), is(sameInstance(childSegment)));
}
@Test
public void shouldReturnChildSegmentFromGetSegmentWithIndexOfSizeMinusOne() {
assertThat(path.getSegment(path.size() - 1), is(sameInstance(childSegment)));
}
@Test
public void shouldDelegateGetSegmentToParentIfIndexNotEqualToSizeMinusOne() {
Path.Segment segment = mock(Path.Segment.class);
parent = mock(Path.class);
when(parent.size()).thenReturn(10);
path = new ChildPath(parent, segment("d"));
when(parent.getSegment(anyInt())).thenReturn(segment);
for (int i = 0; i < path.size() - 1; ++i) {
assertThat(path.getSegment(i), is(sameInstance(segment)));
}
verify(parent, times(parent.size())).getSegment(anyInt());
}
@Test
public void shouldReturnParentInstanceFromGetParent() {
assertThat(path.getParent(), is(sameInstance(parent)));
}
@Test
public void shouldConsiderAsNotNormalizedAPathWithParentSegmentAtEnd() {
path = new ChildPath(parent, Path.PARENT_SEGMENT);
assertThat(path.isAbsolute(), is(parent.isAbsolute()));
assertThat(path.isNormalized(), is(false));
}
@Test
public void shouldConsiderAsNormalizedARelativePathWithParentSegmentAtFront() {
parent = path("../../a/b/c/d");
path = new ChildPath(parent, segment("e"));
assertThat(path.isNormalized(), is(true));
}
@Test
public void shouldConsiderAsNormalizedAnAbsolutePathWithParentSegmentAtFront() {
parent = path("/../a/b");
path = new ChildPath(parent, segment("c"));
assertThat(path.isNormalized(), is(false));
}
@Test
public void shouldConsiderAsNormalizedPathWithAllParentReferences() {
parent = path("../../../../..");
path = new ChildPath(parent, Path.PARENT_SEGMENT);
assertThat(path.isNormalized(), is(true));
}
@Test
public void shouldConsiderAsNotNormalizedPathWithMostParentReferencesAndOneNonParentReferenceInMiddle() {
parent = path("../../a/b/../..");
path = new ChildPath(parent, Path.PARENT_SEGMENT);
assertThat(path.isNormalized(), is(false));
}
// @Test
// public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
// Path other = mock(Path.class);
// when(other.isRoot()).thenReturn(true);
// assertThat(root.getCommonAncestor(other).isRoot(), is(true));
//
// when(other.isRoot()).thenReturn(false);
// assertThat(root.getCommonAncestor(other).isRoot(), is(true));
// }
//
// @Test
// public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
// Path other = mock(Path.class);
// when(other.size()).thenReturn(1);
// assertThat(root.isAncestorOf(other), is(true));
// assertThat(root.isAncestorOf(root), is(false));
// }
//
// @Test
// public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
// Path other = mock(Path.class);
// assertThat(root.isDescendantOf(other), is(false));
// assertThat(root.isDescendantOf(root), is(false));
// }
//
// @Test
// public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
// assertThat(root.hasSameAncestor(root), is(true));
// }
//
// @Test
// public void shouldBeNormalized() {
// assertThat(root.isNormalized(), is(true));
// }
//
// @Test
// public void shouldReturnSelfForGetNormalized() {
// assertThat(root.getNormalizedPath(), is(sameInstance(root)));
// }
//
// @Test
// public void shouldReturnSelfForGetCanonicalPath() {
// assertThat(root.getCanonicalPath(), is(sameInstance(root)));
// }
//
// @Test
// public void shouldReturnSizeOfZero() {
// assertThat(root.size(), is(0));
// }
//
// @Test
// public void shouldReturnEmptyIteratorOverSegments() {
// assertThat(root.iterator(), is(notNullValue()));
// assertThat(root.iterator().hasNext(), is(false));
// }
//
// @Test( expected = IndexOutOfBoundsException.class )
// public void shouldFailToReturnSegmentAtIndexZero() {
// root.getSegment(0);
// }
//
// @Test( expected = IndexOutOfBoundsException.class )
// public void shouldFailToReturnSegmentAtPositiveIndex() {
// root.getSegment(1);
// }
//
// @Test
// public void shouldReturnEmptySegmentsArray() {
// assertThat(root.getSegmentsArray(), is(notNullValue()));
// assertThat(root.getSegmentsArray().length, is(0));
// }
//
// @Test
// public void shouldReturnEmptySegmentsList() {
// assertThat(root.getSegmentsList(), is(notNullValue()));
// assertThat(root.getSegmentsList().isEmpty(), is(true));
// }
//
// @Test
// public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
// NamespaceRegistry registry = mock(NamespaceRegistry.class);
// TextEncoder encoder = mock(TextEncoder.class);
// when(encoder.encode("/")).thenReturn("/");
// assertThat(root.getString(), is("/"));
// assertThat(root.getString(registry), is("/"));
// assertThat(root.getString(registry, encoder), is("/"));
// assertThat(root.getString(registry, encoder, encoder), is("/"));
// assertThat(root.getString(encoder), is("/"));
// }
//
// @Test
// public void shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
// TextEncoder encoder = mock(TextEncoder.class);
// when(encoder.encode("/")).thenReturn("/");
// assertThat(root.getString((NamespaceRegistry)null, encoder, encoder), is("/"));
// }
//
// @Test
// public void shouldAllowNullTextEncoder() {
// assertThat(root.getString((TextEncoder)null), is("/"));
// }
//
// @Test
// public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
// NamespaceRegistry registry = mock(NamespaceRegistry.class);
// assertThat(root.getString(registry, (TextEncoder)null), is("/"));
// }
//
// @Test
// public void shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry() {
// NamespaceRegistry registry = mock(NamespaceRegistry.class);
// TextEncoder encoder = mock(TextEncoder.class);
// assertThat(root.getString(registry, encoder, (TextEncoder)null), is("/"));
// }
//
// @Test( expected = IndexOutOfBoundsException.class )
// public void shouldNotAllowSubpathStartingAtOne() {
// root.subpath(1);
// }
//
// @Test( expected = IndexOutOfBoundsException.class )
// public void shouldNotAllowSubpathStartingAtMoreThanOne() {
// root.subpath(2);
// }
//
// @Test( expected = IndexOutOfBoundsException.class )
// public void shouldNotAllowSubpathEndingAtMoreThanZero() {
// root.subpath(0, 1);
// }
//
// @Test
// public void shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
// List<Path.Segment> segments = new ArrayList<Path.Segment>();
// segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
// Path other = new BasicPath(segments, true);
//
// assertThat(root.relativeTo(other).toString(), is(".."));
//
// segments.add(new BasicPathSegment(new BasicName("http://example.com", "b")));
// other = new BasicPath(segments, true);
// assertThat(root.relativeTo(other).toString(), is("../.."));
//
// String expected = "..";
// segments.clear();
// for (int i = 1; i != 100; ++i) {
// segments.add(new BasicPathSegment(new BasicName("http://example.com", "b" + i)));
// other = new BasicPath(segments, true);
// assertThat(root.relativeTo(other).toString(), is(expected));
// expected = expected + "/..";
// }
// }
//
// @Test
// public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
// List<Path.Segment> segments = new ArrayList<Path.Segment>();
// segments.add(new BasicPathSegment(new BasicName("http://example.com", "a")));
// Path other = mock(Path.class);
// when(other.isAbsolute()).thenReturn(false);
// when(other.getSegmentsList()).thenReturn(segments);
// Path resolved = root.resolve(other);
// assertThat(resolved.getSegmentsList(), is(segments));
// assertThat(resolved.isAbsolute(), is(true));
// }
//
// @Test( expected = InvalidPathException.class )
// public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
// Path other = mock(Path.class);
// when(other.isAbsolute()).thenReturn(true);
// root.resolve(other);
// }
//
// @Test
// public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
// Path other = mock(Path.class);
// when(other.isRoot()).thenReturn(false);
// assertThat(root.compareTo(other), is(-1));
// assertThat(root.equals(other), is(false));
// }
//
// @Test
// public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
// Path other = mock(Path.class);
// when(other.isRoot()).thenReturn(true);
// assertThat(root.compareTo(other), is(0));
// assertThat(root.equals(other), is(true));
// assertThat(root.equals(root), is(true));
// }
}