blob: ed21ec60bba1e3585d70d206300e7f7e10fb55d7 [file] [log] [blame]
/*
* Copyright (C) 2008 The Guava Authors
*
* 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 com.google.common.collect;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newLinkedList;
import static java.util.Arrays.asList;
import static java.util.Collections.nCopies;
import static org.truth0.Truth.ASSERT;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.testing.CollectionTestSuiteBuilder;
import com.google.common.collect.testing.TestStringCollectionGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.testing.NullPointerTester;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Tests for {@link Collections2}.
*
* @author Chris Povirk
* @author Jared Levy
*/
@GwtCompatible(emulated = true)
public class Collections2Test extends TestCase {
@GwtIncompatible("suite")
public static Test suite() {
TestSuite suite = new TestSuite(Collections2Test.class.getSimpleName());
suite.addTest(testsForFilter());
suite.addTest(testsForFilterAll());
suite.addTest(testsForFilterLinkedList());
suite.addTest(testsForFilterNoNulls());
suite.addTest(testsForFilterFiltered());
suite.addTest(testsForTransform());
suite.addTestSuite(Collections2Test.class);
return suite;
}
static final Predicate<String> NOT_YYY_ZZZ = new Predicate<String>() {
@Override
public boolean apply(String input) {
return !"yyy".equals(input) && !"zzz".equals(input);
}
};
static final Predicate<String> LENGTH_1 = new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.length() == 1;
}
};
static final Predicate<String> STARTS_WITH_VOWEL = new Predicate<String>() {
@Override
public boolean apply(String input) {
return asList('a', 'e', 'i', 'o', 'u').contains(input.charAt(0));
}
};
@GwtIncompatible("suite")
private static Test testsForFilter() {
return CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override public Collection<String> create(String[] elements) {
List<String> unfiltered = newArrayList();
unfiltered.add("yyy");
Collections.addAll(unfiltered, elements);
unfiltered.add("zzz");
return Collections2.filter(unfiltered, NOT_YYY_ZZZ);
}
})
.named("Collections2.filter")
.withFeatures(
CollectionFeature.SUPPORTS_ADD,
CollectionFeature.SUPPORTS_REMOVE,
CollectionFeature.ALLOWS_NULL_VALUES,
CollectionFeature.KNOWN_ORDER,
CollectionSize.ANY)
.createTestSuite();
}
@GwtIncompatible("suite")
private static Test testsForFilterAll() {
return CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override public Collection<String> create(String[] elements) {
List<String> unfiltered = newArrayList();
Collections.addAll(unfiltered, elements);
return Collections2.filter(unfiltered, NOT_YYY_ZZZ);
}
})
.named("Collections2.filter")
.withFeatures(
CollectionFeature.SUPPORTS_ADD,
CollectionFeature.SUPPORTS_REMOVE,
CollectionFeature.ALLOWS_NULL_VALUES,
CollectionFeature.KNOWN_ORDER,
CollectionSize.ANY)
.createTestSuite();
}
@GwtIncompatible("suite")
private static Test testsForFilterLinkedList() {
return CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override public Collection<String> create(String[] elements) {
List<String> unfiltered = newLinkedList();
unfiltered.add("yyy");
Collections.addAll(unfiltered, elements);
unfiltered.add("zzz");
return Collections2.filter(unfiltered, NOT_YYY_ZZZ);
}
})
.named("Collections2.filter")
.withFeatures(
CollectionFeature.SUPPORTS_ADD,
CollectionFeature.SUPPORTS_REMOVE,
CollectionFeature.ALLOWS_NULL_VALUES,
CollectionFeature.KNOWN_ORDER,
CollectionSize.ANY)
.createTestSuite();
}
@GwtIncompatible("suite")
private static Test testsForFilterNoNulls() {
return CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override public Collection<String> create(String[] elements) {
List<String> unfiltered = newArrayList();
unfiltered.add("yyy");
unfiltered.addAll(ImmutableList.copyOf(elements));
unfiltered.add("zzz");
return Collections2.filter(unfiltered, LENGTH_1);
}
})
.named("Collections2.filter, no nulls")
.withFeatures(
CollectionFeature.SUPPORTS_ADD,
CollectionFeature.SUPPORTS_REMOVE,
CollectionFeature.ALLOWS_NULL_QUERIES,
CollectionFeature.KNOWN_ORDER,
CollectionSize.ANY)
.createTestSuite();
}
@GwtIncompatible("suite")
private static Test testsForFilterFiltered() {
return CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override public Collection<String> create(String[] elements) {
List<String> unfiltered = newArrayList();
unfiltered.add("yyy");
unfiltered.addAll(ImmutableList.copyOf(elements));
unfiltered.add("zzz");
unfiltered.add("abc");
return Collections2.filter(
Collections2.filter(unfiltered, LENGTH_1), NOT_YYY_ZZZ);
}
})
.named("Collections2.filter, filtered input")
.withFeatures(
CollectionFeature.SUPPORTS_ADD,
CollectionFeature.SUPPORTS_REMOVE,
CollectionFeature.KNOWN_ORDER,
CollectionFeature.ALLOWS_NULL_QUERIES,
CollectionSize.ANY)
.createTestSuite();
}
private static final Function<String, String> REMOVE_FIRST_CHAR
= new Function<String, String>() {
@Override
public String apply(String from) {
return ((from == null) || "".equals(from))
? null : from.substring(1);
}
};
@GwtIncompatible("suite")
private static Test testsForTransform() {
return CollectionTestSuiteBuilder.using(
new TestStringCollectionGenerator() {
@Override public Collection<String> create(String[] elements) {
List<String> list = newArrayList();
for (String element : elements) {
list.add((element == null) ? null : "q" + element);
}
return Collections2.transform(list, REMOVE_FIRST_CHAR);
}
})
.named("Collections2.transform")
.withFeatures(
CollectionFeature.REMOVE_OPERATIONS,
CollectionFeature.ALLOWS_NULL_VALUES,
CollectionFeature.KNOWN_ORDER,
CollectionSize.ANY)
.createTestSuite();
}
@GwtIncompatible("NullPointerTester")
public void testNullPointerExceptions() {
NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(Collections2.class);
}
public void testOrderedPermutationSetEmpty() {
List<Integer> list = newArrayList();
Collection<List<Integer>> permutationSet =
Collections2.orderedPermutations(list);
assertEquals(1, permutationSet.size());
ASSERT.that(permutationSet).has().item(list);
Iterator<List<Integer>> permutations = permutationSet.iterator();
assertNextPermutation(Lists.<Integer>newArrayList(), permutations);
assertNoMorePermutations(permutations);
}
public void testOrderedPermutationSetOneElement() {
List<Integer> list = newArrayList(1);
Iterator<List<Integer>> permutations =
Collections2.orderedPermutations(list).iterator();
assertNextPermutation(newArrayList(1), permutations);
assertNoMorePermutations(permutations);
}
public void testOrderedPermutationSetThreeElements() {
List<String> list = newArrayList("b", "a", "c");
Iterator<List<String>> permutations =
Collections2.orderedPermutations(list).iterator();
assertNextPermutation(newArrayList("a", "b", "c"), permutations);
assertNextPermutation(newArrayList("a", "c", "b"), permutations);
assertNextPermutation(newArrayList("b", "a", "c"), permutations);
assertNextPermutation(newArrayList("b", "c", "a"), permutations);
assertNextPermutation(newArrayList("c", "a", "b"), permutations);
assertNextPermutation(newArrayList("c", "b", "a"), permutations);
assertNoMorePermutations(permutations);
}
public void testOrderedPermutationSetRepeatedElements() {
List<Integer> list = newArrayList(1, 1, 2, 2);
Iterator<List<Integer>> permutations =
Collections2.orderedPermutations(list, Ordering.natural()).iterator();
assertNextPermutation(newArrayList(1, 1, 2, 2), permutations);
assertNextPermutation(newArrayList(1, 2, 1, 2), permutations);
assertNextPermutation(newArrayList(1, 2, 2, 1), permutations);
assertNextPermutation(newArrayList(2, 1, 1, 2), permutations);
assertNextPermutation(newArrayList(2, 1, 2, 1), permutations);
assertNextPermutation(newArrayList(2, 2, 1, 1), permutations);
assertNoMorePermutations(permutations);
}
public void testOrderedPermutationSetRepeatedElementsSize() {
List<Integer> list = newArrayList(1, 1, 1, 1, 2, 2, 3);
Collection<List<Integer>> permutations =
Collections2.orderedPermutations(list, Ordering.natural());
assertPermutationsCount(105, permutations);
}
public void testOrderedPermutationSetSizeOverflow() {
// 12 elements won't overflow
assertEquals(479001600 /*12!*/, Collections2.orderedPermutations(
newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)).size());
// 13 elements overflow an int
assertEquals(Integer.MAX_VALUE, Collections2.orderedPermutations(
newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)).size());
// 21 elements overflow a long
assertEquals(Integer.MAX_VALUE, Collections2.orderedPermutations(
newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21)).size());
// Almost force an overflow in the binomial coefficient calculation
assertEquals(1391975640 /*C(34,14)*/, Collections2.orderedPermutations(
concat(nCopies(20, 1), nCopies(14, 2))).size());
// Do force an overflow in the binomial coefficient calculation
assertEquals(Integer.MAX_VALUE, Collections2.orderedPermutations(
concat(nCopies(21, 1), nCopies(14, 2))).size());
}
public void testOrderedPermutationSetContains() {
List<Integer> list = newArrayList(3, 2, 1);
Collection<List<Integer>> permutationSet =
Collections2.orderedPermutations(list);
assertTrue(permutationSet.contains(newArrayList(1, 2, 3)));
assertTrue(permutationSet.contains(newArrayList(2, 3, 1)));
assertFalse(permutationSet.contains(newArrayList(1, 2)));
assertFalse(permutationSet.contains(newArrayList(1, 1, 2, 3)));
assertFalse(permutationSet.contains(newArrayList(1, 2, 3, 4)));
assertFalse(permutationSet.contains(null));
}
public void testPermutationSetEmpty() {
Collection<List<Integer>> permutationSet =
Collections2.permutations(Collections.<Integer>emptyList());
assertEquals(1, permutationSet.size());
assertTrue(permutationSet.contains(Collections.<Integer> emptyList()));
Iterator<List<Integer>> permutations = permutationSet.iterator();
assertNextPermutation(Collections.<Integer> emptyList(), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetOneElement() {
Iterator<List<Integer>> permutations =
Collections2.permutations(Collections.<Integer> singletonList(1))
.iterator();
assertNextPermutation(newArrayList(1), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetTwoElements() {
Iterator<List<Integer>> permutations = Collections2.permutations(
newArrayList(1, 2)).iterator();
assertNextPermutation(newArrayList(1, 2), permutations);
assertNextPermutation(newArrayList(2, 1), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetThreeElements() {
Iterator<List<Integer>> permutations = Collections2.permutations(
newArrayList(1, 2, 3)).iterator();
assertNextPermutation(newArrayList(1, 2, 3), permutations);
assertNextPermutation(newArrayList(1, 3, 2), permutations);
assertNextPermutation(newArrayList(3, 1, 2), permutations);
assertNextPermutation(newArrayList(3, 2, 1), permutations);
assertNextPermutation(newArrayList(2, 3, 1), permutations);
assertNextPermutation(newArrayList(2, 1, 3), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetThreeElementsOutOfOrder() {
Iterator<List<Integer>> permutations = Collections2.permutations(
newArrayList(3, 2, 1)).iterator();
assertNextPermutation(newArrayList(3, 2, 1), permutations);
assertNextPermutation(newArrayList(3, 1, 2), permutations);
assertNextPermutation(newArrayList(1, 3, 2), permutations);
assertNextPermutation(newArrayList(1, 2, 3), permutations);
assertNextPermutation(newArrayList(2, 1, 3), permutations);
assertNextPermutation(newArrayList(2, 3, 1), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetThreeRepeatedElements() {
Iterator<List<Integer>> permutations = Collections2.permutations(
newArrayList(1, 1, 2)).iterator();
assertNextPermutation(newArrayList(1, 1, 2), permutations);
assertNextPermutation(newArrayList(1, 2, 1), permutations);
assertNextPermutation(newArrayList(2, 1, 1), permutations);
assertNextPermutation(newArrayList(2, 1, 1), permutations);
assertNextPermutation(newArrayList(1, 2, 1), permutations);
assertNextPermutation(newArrayList(1, 1, 2), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetFourElements() {
Iterator<List<Integer>> permutations = Collections2.permutations(
newArrayList(1, 2, 3, 4)).iterator();
assertNextPermutation(newArrayList(1, 2, 3, 4), permutations);
assertNextPermutation(newArrayList(1, 2, 4, 3), permutations);
assertNextPermutation(newArrayList(1, 4, 2, 3), permutations);
assertNextPermutation(newArrayList(4, 1, 2, 3), permutations);
assertNextPermutation(newArrayList(4, 1, 3, 2), permutations);
assertNextPermutation(newArrayList(1, 4, 3, 2), permutations);
assertNextPermutation(newArrayList(1, 3, 4, 2), permutations);
assertNextPermutation(newArrayList(1, 3, 2, 4), permutations);
assertNextPermutation(newArrayList(3, 1, 2, 4), permutations);
assertNextPermutation(newArrayList(3, 1, 4, 2), permutations);
assertNextPermutation(newArrayList(3, 4, 1, 2), permutations);
assertNextPermutation(newArrayList(4, 3, 1, 2), permutations);
assertNextPermutation(newArrayList(4, 3, 2, 1), permutations);
assertNextPermutation(newArrayList(3, 4, 2, 1), permutations);
assertNextPermutation(newArrayList(3, 2, 4, 1), permutations);
assertNextPermutation(newArrayList(3, 2, 1, 4), permutations);
assertNextPermutation(newArrayList(2, 3, 1, 4), permutations);
assertNextPermutation(newArrayList(2, 3, 4, 1), permutations);
assertNextPermutation(newArrayList(2, 4, 3, 1), permutations);
assertNextPermutation(newArrayList(4, 2, 3, 1), permutations);
assertNextPermutation(newArrayList(4, 2, 1, 3), permutations);
assertNextPermutation(newArrayList(2, 4, 1, 3), permutations);
assertNextPermutation(newArrayList(2, 1, 4, 3), permutations);
assertNextPermutation(newArrayList(2, 1, 3, 4), permutations);
assertNoMorePermutations(permutations);
}
public void testPermutationSetSize() {
assertPermutationsCount(1,
Collections2.permutations(Collections.<Integer>emptyList()));
assertPermutationsCount(1, Collections2.permutations(newArrayList(1)));
assertPermutationsCount(2, Collections2.permutations(newArrayList(1, 2)));
assertPermutationsCount(6,
Collections2.permutations(newArrayList(1, 2, 3)));
assertPermutationsCount(5040,
Collections2.permutations(newArrayList(1, 2, 3, 4, 5, 6, 7)));
assertPermutationsCount(40320,
Collections2.permutations(newArrayList(1, 2, 3, 4, 5, 6, 7, 8)));
}
public void testPermutationSetSizeOverflow() {
// 13 elements overflow an int
assertEquals(Integer.MAX_VALUE, Collections2.permutations(newArrayList(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)).size());
// 21 elements overflow a long
assertEquals(Integer.MAX_VALUE, Collections2.orderedPermutations(
newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20)).size());
assertEquals(Integer.MAX_VALUE, Collections2.orderedPermutations(
newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21)).size());
}
public void testPermutationSetContains() {
List<Integer> list = newArrayList(3, 2, 1);
Collection<List<Integer>> permutationSet =
Collections2.permutations(list);
assertTrue(permutationSet.contains(newArrayList(1, 2, 3)));
assertTrue(permutationSet.contains(newArrayList(2, 3, 1)));
assertFalse(permutationSet.contains(newArrayList(1, 2)));
assertFalse(permutationSet.contains(newArrayList(1, 1, 2, 3)));
assertFalse(permutationSet.contains(newArrayList(1, 2, 3, 4)));
assertFalse(permutationSet.contains(null));
}
private <T> void assertNextPermutation(List<T> expectedPermutation,
Iterator<List<T>> permutations) {
assertTrue("Expected another permutation, but there was none.",
permutations.hasNext());
assertEquals(expectedPermutation, permutations.next());
}
private <T> void assertNoMorePermutations(
Iterator<List<T>> permutations) {
assertFalse("Expected no more permutations, but there was one.",
permutations.hasNext());
try {
permutations.next();
fail("Expected NoSuchElementException.");
} catch (NoSuchElementException expected) {}
}
private <T> void assertPermutationsCount(int expected,
Collection<List<T>> permutationSet) {
assertEquals(expected, permutationSet.size());
Iterator<List<T>> permutations = permutationSet.iterator();
for (int i = 0; i < expected; i++) {
assertTrue(permutations.hasNext());
permutations.next();
}
assertNoMorePermutations(permutations);
}
public void testToStringImplWithNullEntries() throws Exception {
List<String> list = Lists.newArrayList();
list.add("foo");
list.add(null);
assertEquals(list.toString(), Collections2.toStringImpl(list));
}
}