/* * Copyright 2010 The Rabbit Eclipse Plug-in Project * * 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 rabbit.ui.internal.viewers; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Sets.newHashSet; import com.google.common.collect.Lists; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.Viewer; import org.junit.Before; import org.junit.Test; import static java.util.Arrays.asList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Observable; import java.util.Observer; import java.util.Set; /** * Tests for a {@link TreePathContentProvider}. */ public class TreePathContentProviderTest { private static final Object[] EMPTY_ARRAY = {}; private TreePathContentProvider content; @Before public void before() { TreePath path1 = new TreePath(new Object[]{"1", "2", "3"}); TreePath path2 = new TreePath(new Object[]{"a", "b"}); ITreePathBuilder builder = mock(ITreePathBuilder.class); when(builder.build(any())).thenReturn(Arrays.asList(path1, path2)); content = create(builder); // Call once to initialize: content.inputChanged(null, null, null); } @Test public void getChildrenShouldReturnAnEmptyArrayIfParentHasNoChildren() { // Given a non-null parent has no children: TreePath parent = new TreePath(new Object[]{this}); // When asking for the children of the parent: Object[] children = content.getChildren(parent); // The an empty array is returned: assertThat(children, is(EMPTY_ARRAY)); } @Test public void getChildrenShouldReturnAnEmtpyArrayIfParentIsNull() { // Given a parent path is null: TreePath parent = null; // When asking for the children of the null object: Object[] children = content.getChildren(parent); // The an empty array should be returned as the children: assertThat(children, is(EMPTY_ARRAY)); } @Test public void getChildrenShouldReturnTheDistinctChildrenOfAParent() { // Given a tree path has 3 children, 2 of which are equal: TreePath branch = new TreePath(new Object[]{0, 1}); TreePath leaf1 = branch.createChildPath(2); TreePath leaf2 = branch.createChildPath(3); TreePath leaf3 = branch.createChildPath(3); Object input = new Object(); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(input)).willReturn(asList(leaf1, leaf2, leaf3)); content = create(builder); // When asking for the children of the parent path: content.inputChanged(null, null, input); // Sets the input. List<Object> children = newArrayList(content.getChildren(branch)); // Then the distinct children should be returned: List<Object> expected = newArrayList(newHashSet( // Get unique children leaf1.getLastSegment(), leaf2.getLastSegment(), leaf3.getLastSegment())); assertThat(children, is(equalTo(expected))); } @Test public void getElementsShouldReturnAnEmptyArrayIfAllLeavesAreEmptyPaths() { // Given all tree paths are empty paths: Object input = new Object(); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(input)).willReturn( asList(TreePath.EMPTY, new TreePath(new Object[0]))); content = create(builder); // When set and ask for elements: content.inputChanged(null, null, input); Object[] elements = content.getElements(input); // Then an empty array is returned: assertThat(elements, is(EMPTY_ARRAY)); } @Test public void getElementsShouldReturnAnEmptyArrayIfInputHasNoElements() { // Given an non-null input element that has no child elements: Object input = this; ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(any())).willReturn(Collections.<TreePath> emptyList()); content = create(builder); content.inputChanged(null, null, null); // When asking for the child elements of the input: Object[] elements = content.getElements(input); // Then an empty array is returned: assertThat(elements, is(EMPTY_ARRAY)); } @Test public void getElementsShouldReturnTheDistinctElementsOfAllLeaves() { // Given we have 3 leaves, the 0th segments of 2 of them are equal:: TreePath leaf1 = new TreePath(new Object[]{0, 1}); TreePath leaf2 = new TreePath(new Object[]{2, 3}); TreePath leaf3 = new TreePath(new Object[]{9, 8}); Object input = new Object(); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(input)).willReturn(asList(leaf1, leaf2, leaf3)); content = create(builder); // When asking for elements of the new input: content.inputChanged(null, null, input); List<Object> actual = newArrayList(content.getElements(input)); // Then the distinct first elements of each leave is returned: List<Object> expected = newArrayList(newHashSet( // Get distinct elements leaf1.getFirstSegment(), leaf2.getFirstSegment(), leaf3.getFirstSegment())); assertThat(actual, is(equalTo(expected))); } @Test public void getParentsShouldReturnAnEmptyArrayIsChildHasNoParents() { // Given a non-null child that has no possible parents: Object child = this; // When asking for the possible parents of the child: TreePath[] parents = content.getParents(child); // Then an empty array is returned as the parents: assertThat(parents, is(EMPTY_ARRAY)); } @Test public void getParentsShouldReturnAnEmptyArrayIsChildIsNull() { // Given a child is null: Object child = null; // When asking for possible parents of the child: TreePath[] parents = content.getParents(child); // Then an empty array is returned: assertThat(parents, is(EMPTY_ARRAY)); } @Test public void getParentsShouldReturnTheParentsOfAChild() { // Given we have two leaves that have the same last segments: Object child = "Child"; TreePath leaf1 = new TreePath(new Object[]{0, child}); TreePath leaf2 = new TreePath(new Object[]{2, child}); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build("input")).willReturn(asList(leaf1, leaf2)); content = create(builder); // When getting the parents of the child: content.inputChanged(null, null, "input"); Set<TreePath> actual = newHashSet(content.getParents(child)); // Then the parent path of the two leaves should be returned:e Set<TreePath> expected = newHashSet( leaf1.getParentPath(), leaf2.getParentPath()); assertThat(actual, is(expected)); } @Test public void getShouldReturnAnEmptyCollectionWhenFirstConstructed() { assertThat(create(mock(ITreePathBuilder.class)).get().isEmpty(), is(true)); } @Test(expected = UnsupportedOperationException.class) public void getShouldReturnAnImmutableCollection() { content.get().add(new TreePath(new Object[]{})); } @Test public void getShouldReturnTheTreePathsCurrentlyInUse() { List<TreePath> paths = Lists.newArrayList(); paths.add(new TreePath(new Object[]{})); paths.add(new TreePath(new Object[]{"a", "b"})); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(any())).willReturn(paths); content = create(builder); content.inputChanged(null, null, null); assertEquals(paths, content.get()); } @Test public void hasChildrenShouldReturnFalseIfTheGivenPathHasNoChildren() { // Given a non-null parent has no children: TreePath parent = new TreePath(new Object[]{this}); // When asking whether the parent has children or not: boolean hasChildren = content.hasChildren(parent); // Then false is returned: assertThat(hasChildren, is(false)); } @Test public void hasChildrenShouldReturnFalseIfTheGivenPathIsNull() { // Given a parent is null: TreePath parent = null; // When asking whether the parent has children: boolean hasChildren = content.hasChildren(parent); // Then false is returned: assertThat(hasChildren, is(not(true))); } @Test public void hasChildrenShouldReturnTrueIfTheGivenPathHasChildren() { // Given a parent has children: TreePath parent = new TreePath(new Object[]{0, 1, 2}); TreePath leaf = parent.createChildPath(100); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(any())).willReturn(Arrays.asList(leaf)); content = create(builder); // When asking whether the parent has children: content.inputChanged(null, null, ""); boolean hasChildren = content.hasChildren(parent); // Then true is returned: assertThat(hasChildren, is(true)); } @Test public void inputChangedShouldAcceptNullableNewInput() { content.inputChanged(mock(Viewer.class), "", null); // No exception } @Test public void inputChangedShouldAcceptNullableOldInput() { content.inputChanged(mock(Viewer.class), null, ""); // No exception } @Test public void inputChangedShouldAcceptNullableViewer() { content.inputChanged(null, "", ""); // No exception } @Test public void shouldAlwaysReturnTheDataOfTheLatestInput() { // Given that an input has already been set: List<TreePath> input1 = asList(new TreePath(new Object[]{"a", "b"})); ITreePathBuilder builder = mock(ITreePathBuilder.class); given(builder.build(input1)).willReturn(input1); content = create(builder); content.inputChanged(null, null, input1); // When new input is set, gets the new root elements: TreePath input2 = new TreePath(new Object[]{0, 1}); given(builder.build(input2)).willReturn(asList(input2)); content.inputChanged(null, input1, input2); Object[] elements = content.getElements(input2); // Then data from new input should be returned: Object[] expected = new Object[]{input2.getFirstSegment()}; assertThat(elements, is(expected)); } @Test public void shouldBuildTheTreePathsOnInputChange() { // Given a content provider is built with a tree path builder: Object input = new Object(); ITreePathBuilder builder = mock(ITreePathBuilder.class); content = create(builder); // When input is set: content.inputChanged(null, null, input); // Then the content provider should have called the tree path builder: verify(builder).build(input); } @Test(expected = NullPointerException.class) public void shouldThrowAnExceptionIfConstructedWithoutATreePathBulder() { content = create(null); } @Test public void shouldNotifyObserversOnInputChange() { final int[] updateCount = {0}; Observer observer = new Observer() { @Override public void update(Observable arg0, Object arg1) { updateCount[0]++; } }; TreePathContentProvider provider = create(mock(ITreePathBuilder.class)); provider.addObserver(observer); provider.inputChanged(null, null, null); assertThat(updateCount[0], is(1)); } /** * Creates a content provider for testing. */ private TreePathContentProvider create(ITreePathBuilder builder) { return new TreePathContentProvider(builder); } }