/* * 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)); // } }