/*
* 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.util;
import rabbit.ui.IProvider;
import com.google.common.base.Predicates;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
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.when;
import org.eclipse.jface.viewers.TreePath;
import org.junit.Test;
import org.mockito.Mockito;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import java.util.Arrays;
import java.util.Collections;
import java.util.Observable;
import java.util.Observer;
/**
* Tests for a {@link TreePathValueProvider}.
*/
public class TreePathValueProviderTest {
@Test(expected = NullPointerException.class)
public void constructorShouldThrowAnExceptionIfCategorizerIsNull() {
create(null, newProvider(), newConverter());
}
@Test(expected = NullPointerException.class)
public void constructorShouldThrowAnExceptionIfConverterisNull() {
create(mock(ICategorizer.class), null, newConverter());
}
@Test(expected = NullPointerException.class)
public void constructorShouldThrowAnExceptionIfProviderIsNull() {
create(mock(ICategorizer.class), newProvider(), null);
}
@Test
public void getCategorizerShouldReturnTheCategorizer() {
ICategorizer categorizer = mock(ICategorizer.class);
TreePathValueProvider v = create(categorizer, newProvider(), newConverter());
assertThat(v.getCategorizer(), is(categorizer));
}
@Test
public void getConverterShouldReturnTheConverter() {
IConverter<TreePath> converter = newConverter();
TreePathValueProvider v = create(
mock(ICategorizer.class),
newProvider(),
converter);
assertThat(v.getConverter(), is(converter));
}
@Test
public void getMaxValueShouldReturnTheValueThatHasBeenSet() {
long max = 123;
TreePathValueProvider v = create();
v.setMaxValue(max);
assertThat(v.getMaxValue(), is(max));
}
@Test
public void getProviderShouldReturnTheProvider() {
IProvider<TreePath> provider = newProvider();
TreePathValueProvider v = create(
mock(ICategorizer.class),
provider,
newConverter());
assertThat(v.getProvider(), is(provider));
}
@Test
public void getValueShouldReturn0ForNullArguments() {
assertThat(create().getValue(null), is(Long.valueOf(0)));
}
@Test
public void getValueShouldReturnTheSumOfTheChildrenValueForAParentPath() {
TreePath leaf1 = new TreePath(new Object[]{"1", "2", "3"});
TreePath leaf2 = new TreePath(new Object[]{"1", "2", "4"});
TreePath leaf3 = new TreePath(new Object[]{"1", "5", "6"});
TreePath parentOf1n2 = new TreePath(new Object[]{"1", "2"});
TreePath parentOfAll = new TreePath(new Object[]{"1"});
@SuppressWarnings("unchecked")
IConverter<TreePath> converter = mock(IConverter.class);
given(converter.convert(leaf1)).willReturn(Long.valueOf(1));
given(converter.convert(leaf2)).willReturn(Long.valueOf(2));
given(converter.convert(leaf3)).willReturn(Long.valueOf(3));
@SuppressWarnings("unchecked")
IProvider<TreePath> provider = mock(IProvider.class);
given(provider.get()).willReturn(Arrays.asList(leaf1, leaf2, leaf3));
TreePathValueProvider values = create(
mock(ICategorizer.class),
provider,
converter);
long value = converter.convert(leaf1) + converter.convert(leaf2);
assertThat(values.getValue(parentOf1n2), equalTo(value));
value += converter.convert(leaf3);
assertThat(values.getValue(parentOfAll), equalTo(value));
}
@Test
public void getValueShouldReturnTheValueOfALeafPathSuppliedByTheConverter() {
TreePath leaf = new TreePath(new Object[]{""});
long value = 123;
@SuppressWarnings("unchecked")
IConverter<TreePath> c = mock(IConverter.class);
given(c.convert(leaf)).willReturn(Long.valueOf(value));
@SuppressWarnings("unchecked")
IProvider<TreePath> provider = mock(IProvider.class);
given(provider.get()).willReturn(Arrays.asList(leaf));
TreePathValueProvider p = create(mock(ICategorizer.class), provider, c);
assertThat(p.getValue(leaf), is(value));
}
@Test
public void getVirsualCategoryShouldReturnTheCategoryThatHasBeenSet() {
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.hasCategory(category)).willReturn(TRUE);
TreePathValueProvider v = create(categorizer, newProvider(), newConverter());
v.setVisualCategory(category);
assertThat(v.getVisualCategory(), is(category));
}
@Test
public void setVisualCategoryShouldNotifyObserversWhenTheCategoryIsChanged() {
// Given we have an observer observing on the provider:
final int[] updateCount = {0};
Observer observer = new Observer() {
@Override
public void update(Observable ob, Object arg) {
// Updates the counter when notified:
updateCount[0]++;
}
};
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.hasCategory(category)).willReturn(TRUE);
TreePathValueProvider provider = create(categorizer, newProvider(),
newConverter());
provider.addObserver(observer);
// When the provider's category is changed to a different category:
assertThat(provider.setVisualCategory(category), is(TRUE));
// Then the observer should have been notified:
assertThat(updateCount[0], equalTo(1));
}
@Test
public void setVisualCategoryShouldNotNotifyObserversWhenTheCategoryIsUnchanged() {
// Given we have a provider who's category has been set:
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.hasCategory(category)).willReturn(TRUE);
TreePathValueProvider provider = create(categorizer, newProvider(),
newConverter());
provider.setVisualCategory(category);
// And we have an observer observing on the provider:
final int[] updateCount = {0};
Observer observer = new Observer() {
@Override
public void update(Observable ob, Object arg) {
// Updates the counter when notified:
updateCount[0]++;
}
};
provider.addObserver(observer);
// When we call the change category method with the same category:
assertThat(provider.setVisualCategory(provider.getVisualCategory()),
is(TRUE));
// Then the observer should not be notified because the actual category is
// not changed:
assertThat(updateCount[0], equalTo(0));
}
@Test
public void setVisualCategoryShouldAcceptKnownCategories() {
// Given that a categorizer has a given category:
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.hasCategory(category)).willReturn(true);
// When changing the provider's category to this category, should be OK:
TreePathValueProvider p = create(categorizer, newProvider(), newConverter());
assertThat(p.setVisualCategory(category), is(true));
assertThat(p.getVisualCategory(), is(category));
}
@Test
public void setVisualCategoryShouldRejectUnknownCategories() {
ICategorizer c = mock(ICategorizer.class);
given(c.hasCategory(Mockito.<ICategory> any())).willReturn(FALSE);
TreePathValueProvider provider = create(c, newProvider(), newConverter());
ICategory category = mock(ICategory.class);
assertThat(provider.setVisualCategory(category), is(FALSE));
assertThat(provider.getVisualCategory(), is(not(category)));
}
@Test
public void setMaxValueWithCategoryAndPredicateShouldCalculateTheCorrectValue() {
// @formatter:off
// Given we have a tree that looks like the following:
// + - 1 - 2 - 3 // Value of this path = 1
// \ \
// \ 4 // Value of this path = 10
// \
// 2 - 2 - 2 // Value of this path = 2
// @formatter:on
TreePath leaf1 = new TreePath(new Object[]{"1", "2", "3"});
TreePath leaf2 = new TreePath(new Object[]{"1", "2", "4"});
TreePath leaf3 = new TreePath(new Object[]{"2", "2", "2"});
// And elements belong to the same category:
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.getCategory("2")).willReturn(category);
given(categorizer.getCategory("1")).willReturn(category);
given(categorizer.getCategory("3")).willReturn(category);
given(categorizer.getCategory("4")).willReturn(category);
// And each path has a different value:
@SuppressWarnings("unchecked")
IConverter<TreePath> converter = mock(IConverter.class);
given(converter.convert(leaf1)).willReturn(Long.valueOf(1));
given(converter.convert(leaf2)).willReturn(Long.valueOf(10));
given(converter.convert(leaf3)).willReturn(Long.valueOf(2));
@SuppressWarnings("unchecked")
IProvider<TreePath> provider = mock(IProvider.class);
given(provider.get()).willReturn(Arrays.asList(leaf1, leaf2, leaf3));
// When we call setMaxValue with predicate to say we only want element "3":
TreePathValueProvider v = create(categorizer, provider, converter);
v.setMaxValue(category, Predicates.<Object> equalTo("3"));
// @formatter:off
// Then the maximum value should have been set to the value of the element "3" that has the
// highest value, which is the one in bracket, with value of 1:
// + - 1 - 2 -(3) // Value of this path = 1
// \ \
// \ 4 // Value of this path = 10
// \
// 2 - 2 - 2 // Value of this path = 2
// @formatter:on
assertThat(v.getMaxValue(), equalTo(1L));
}
@Test
public void setMaxValueWithCategoryShouldCalculateTheCorrectValue_1() {
// @formatter:off
// Given we have a tree that looks like the following:
// + - 1 - 2 - 3 // Value of this path = 1
// \ \
// \ 4 // Value of this path = 10
// \
// 2 - 2 - 2 // Value of this path = 2
// @formatter:on
TreePath leaf1 = new TreePath(new Object[]{"1", "2", "3"});
TreePath leaf2 = new TreePath(new Object[]{"1", "2", "4"});
TreePath leaf3 = new TreePath(new Object[]{"2", "2", "2"});
// And element "2" belongs to a different category:
ICategory theCategory = mock(ICategory.class);
ICategory tmpCategory = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.getCategory("2")).willReturn(theCategory);
given(categorizer.getCategory("1")).willReturn(tmpCategory);
given(categorizer.getCategory("3")).willReturn(tmpCategory);
given(categorizer.getCategory("4")).willReturn(tmpCategory);
// And each path has a different value:
@SuppressWarnings("unchecked")
IConverter<TreePath> converter = mock(IConverter.class);
given(converter.convert(leaf1)).willReturn(Long.valueOf(1));
given(converter.convert(leaf2)).willReturn(Long.valueOf(10));
given(converter.convert(leaf3)).willReturn(Long.valueOf(2));
@SuppressWarnings("unchecked")
IProvider<TreePath> provider = mock(IProvider.class);
given(provider.get()).willReturn(Arrays.asList(leaf1, leaf2, leaf3));
// When we call setMaxValue with element "2"'s category:
TreePathValueProvider v = create(categorizer, provider, converter);
v.setMaxValue(theCategory);
// @formatter:off
// Then the maximum value should have been set to the value of the element "2" that has the
// highest value, which is the one in bracket, with value of 11 (1 + 10):
// + - 1 -(2)- 3 // Value of this path = 1
// \ \
// \ 4 // Value of this path = 10
// \
// 2 - 2 - 2 // Value of this path = 2
// @formatter:on
assertThat(v.getMaxValue(),
equalTo(converter.convert(leaf1) + converter.convert(leaf2)));
}
@Test
public void setMaxValueWithCategoryShouldCalculateTheCorrectValue_2() {
// Given our tree has only one path:
TreePath leaf1 = new TreePath(new Object[]{"1", "2", "3"});
// And the value of this path is 100:
@SuppressWarnings("unchecked")
IConverter<TreePath> converter = mock(IConverter.class);
given(converter.convert(leaf1)).willReturn(Long.valueOf(100));
// And each element in the path corresponds to a category:
ICategory theCategory = mock(ICategory.class);
ICategory tmpCategory = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.getCategory("2")).willReturn(theCategory);
given(categorizer.getCategory("1")).willReturn(tmpCategory);
given(categorizer.getCategory("3")).willReturn(tmpCategory);
@SuppressWarnings("unchecked")
IProvider<TreePath> provider = mock(IProvider.class);
given(provider.get()).willReturn(Arrays.asList(leaf1));
// When we call setMaxValue with the category belonging to one of the
// elements of the path:
TreePathValueProvider v = create(categorizer, provider, converter);
v.setMaxValue(theCategory);
// Then the maximum value is set to the value of the tree path:
assertThat(v.getMaxValue(), equalTo(converter.convert(leaf1)));
}
@Test
public void setMaxValueWithCategoryShouldCalculateTheCorrectValue_3() {
// @formatter:off
// If we have a tree like the following, where the element "2" appears at multiple places at
// different levels:
//
// + - 1 - 2 - 3 // Value of this path is 1
// \
// 2 - 2 - 4 // Value of this path is 10
// \
// 3 - 2 // Value of this path is 2
//
// @formatter:on
TreePath leaf1 = new TreePath(new Object[]{"1", "2", "3"});
TreePath leaf2 = new TreePath(new Object[]{"2", "2", "4"});
TreePath leaf3 = new TreePath(new Object[]{"2", "3", "2"});
// And element "2" belongs to a different category:
ICategory theCategory = mock(ICategory.class);
ICategory tmpCategory = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.getCategory("2")).willReturn(theCategory);
given(categorizer.getCategory("1")).willReturn(tmpCategory);
given(categorizer.getCategory("3")).willReturn(tmpCategory);
given(categorizer.getCategory("4")).willReturn(tmpCategory);
// And each path has a different:
@SuppressWarnings("unchecked")
IConverter<TreePath> converter = mock(IConverter.class);
given(converter.convert(leaf1)).willReturn(Long.valueOf(1));
given(converter.convert(leaf2)).willReturn(Long.valueOf(10));
given(converter.convert(leaf3)).willReturn(Long.valueOf(2));
@SuppressWarnings("unchecked")
IProvider<TreePath> provider = mock(IProvider.class);
given(provider.get()).willReturn(Arrays.asList(leaf1, leaf2, leaf3));
// When we call setMaxValue(ICategory) using the category belonging to the
// element "2"
TreePathValueProvider v = create(categorizer, provider, converter);
v.setMaxValue(theCategory);
// @formatter:off
// Then then the maximum value should be set to 12 in this example, which is the value of the
// highest element "2" in the tree (the one in bracket below):
//
// + - 1 - 2 - 3 // Value of this path is 1
// \
// (2)- 2 - 4 // Value of this path is 10
// \
// 3 - 2 // Value of this path is 2
//
// @formatter:on
assertThat(v.getMaxValue(),
equalTo(converter.convert(leaf2) + converter.convert(leaf3)));
}
@Test
public void shouldNotPaintIfTheCategoryOfTheObjectIsNotTheVisualCategory() {
// Given a category is set to a provider:
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.hasCategory(category)).willReturn(TRUE);
TreePathValueProvider v = create(categorizer, newProvider(), newConverter());
v.setVisualCategory(category);
// When an object belongs to a different category:
Object element = Integer.valueOf(0);
category = mock(ICategory.class);
given(categorizer.getCategory(element)).willReturn(category);
// Then it should not be painted:
assertThat(v.shouldPaint(""), is(FALSE));
}
@Test
public void shouldPaintIfTheCategoryOfTheObjectIsTheVisualCategory() {
ICategory category = mock(ICategory.class);
ICategorizer categorizer = mock(ICategorizer.class);
given(categorizer.getCategory(any())).willReturn(category);
given(categorizer.hasCategory(category)).willReturn(TRUE);
TreePathValueProvider v = create(categorizer, newProvider(), newConverter());
v.setVisualCategory(category);
assertThat(v.shouldPaint(""), is(TRUE));
}
private TreePathValueProvider create() {
return create(mock(ICategorizer.class), newProvider(), newConverter());
}
private TreePathValueProvider create(
ICategorizer categorizer,
IProvider<TreePath> treePathProvider,
IConverter<TreePath> treePathValueProvider) {
return new TreePathValueProvider(
categorizer,
treePathProvider,
treePathValueProvider);
}
private IConverter<TreePath> newConverter() {
@SuppressWarnings("unchecked")
IConverter<TreePath> mock = mock(IConverter.class);
when(mock.convert(Mockito.<TreePath> any())).thenReturn(Long.valueOf(0));
return mock;
}
private IProvider<TreePath> newProvider() {
@SuppressWarnings("unchecked")
IProvider<TreePath> mock = mock(IProvider.class);
when(mock.get()).thenReturn(Collections.<TreePath> emptyList());
return mock;
}
}