/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.commons.collections4; import static org.apache.commons.collections4.functors.EqualPredicate.equalPredicate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.apache.commons.collections4.bag.HashBag; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Tests for IterableUtils. * * @since 4.1 * @version $Id$ */ public class IterableUtilsTest { /** * Iterable of {@link Integer}s */ private Iterable<Integer> iterableA = null; /** * Iterable of {@link Long}s */ private Iterable<Long> iterableB = null; /** * An empty Iterable. */ private Iterable<Integer> emptyIterable = null; @Before public void setUp() { Collection<Integer> collectionA = new ArrayList<Integer>(); collectionA.add(1); collectionA.add(2); collectionA.add(2); collectionA.add(3); collectionA.add(3); collectionA.add(3); collectionA.add(4); collectionA.add(4); collectionA.add(4); collectionA.add(4); iterableA = collectionA; Collection<Long> collectionB = new LinkedList<Long>(); collectionB.add(5L); collectionB.add(4L); collectionB.add(4L); collectionB.add(3L); collectionB.add(3L); collectionB.add(3L); collectionB.add(2L); collectionB.add(2L); collectionB.add(2L); collectionB.add(2L); iterableB = collectionB; emptyIterable = Collections.emptyList(); } private static Predicate<Number> EQUALS_TWO = new Predicate<Number>() { @Override public boolean evaluate(final Number input) { return input.intValue() == 2; } }; private static Predicate<Number> EVEN = new Predicate<Number>() { @Override public boolean evaluate(final Number input) { return input.intValue() % 2 == 0; } }; // ----------------------------------------------------------------------- @Test public void forEach() { final List<Integer> listA = new ArrayList<Integer>(); listA.add(1); final List<Integer> listB = new ArrayList<Integer>(); listB.add(2); final Closure<List<Integer>> testClosure = ClosureUtils.invokerClosure("clear"); final Collection<List<Integer>> col = new ArrayList<List<Integer>>(); col.add(listA); col.add(listB); IterableUtils.forEach(col, testClosure); assertTrue(listA.isEmpty() && listB.isEmpty()); try { IterableUtils.forEach(col, null); fail("expecting NullPointerException"); } catch (NullPointerException npe) { // expected } IterableUtils.forEach(null, testClosure); // null should be OK col.add(null); IterableUtils.forEach(col, testClosure); } @Test(expected = FunctorException.class) public void forEachFailure() { final Closure<String> testClosure = ClosureUtils.invokerClosure("clear"); final Collection<String> col = new ArrayList<String>(); col.add("x"); IterableUtils.forEach(col, testClosure); } @Test public void forEachButLast() { final List<Integer> listA = new ArrayList<Integer>(); listA.add(1); final List<Integer> listB = new ArrayList<Integer>(); listB.add(2); final Closure<List<Integer>> testClosure = ClosureUtils.invokerClosure("clear"); final Collection<List<Integer>> col = new ArrayList<List<Integer>>(); col.add(listA); col.add(listB); List<Integer> last = IterableUtils.forEachButLast(col, testClosure); assertTrue(listA.isEmpty() && !listB.isEmpty()); assertSame(listB, last); try { IterableUtils.forEachButLast(col, null); fail("expecting NullPointerException"); } catch (NullPointerException npe) { // expected } IterableUtils.forEachButLast(null, testClosure); // null should be OK col.add(null); col.add(null); last = IterableUtils.forEachButLast(col, testClosure); assertNull(last); } @Test public void containsWithEquator() { final List<String> base = new ArrayList<String>(); base.add("AC"); base.add("BB"); base.add("CA"); final Equator<String> secondLetterEquator = new Equator<String>() { @Override public boolean equate(String o1, String o2) { return o1.charAt(1) == o2.charAt(1); } @Override public int hash(String o) { return o.charAt(1); } }; assertFalse(base.contains("CC")); assertTrue(IterableUtils.contains(base, "AC", secondLetterEquator)); assertTrue(IterableUtils.contains(base, "CC", secondLetterEquator)); assertFalse(IterableUtils.contains(base, "CX", secondLetterEquator)); assertFalse(IterableUtils.contains(null, null, secondLetterEquator)); try { IterableUtils.contains(base, "AC", null); fail("expecting NullPointerException"); } catch (final NullPointerException npe) { } // this is what we want } @Test public void frequency() { // null iterable test assertEquals(0, IterableUtils.frequency(null, 1)); assertEquals(1, IterableUtils.frequency(iterableA, 1)); assertEquals(2, IterableUtils.frequency(iterableA, 2)); assertEquals(3, IterableUtils.frequency(iterableA, 3)); assertEquals(4, IterableUtils.frequency(iterableA, 4)); assertEquals(0, IterableUtils.frequency(iterableA, 5)); assertEquals(0, IterableUtils.frequency(iterableB, 1L)); assertEquals(4, IterableUtils.frequency(iterableB, 2L)); assertEquals(3, IterableUtils.frequency(iterableB, 3L)); assertEquals(2, IterableUtils.frequency(iterableB, 4L)); assertEquals(1, IterableUtils.frequency(iterableB, 5L)); // Ensure that generic bounds accept valid parameters, but return // expected results // e.g. no longs in the "int" Iterable<Number>, and vice versa. Iterable<Number> iterableIntAsNumber = Arrays.<Number>asList(1, 2, 3, 4, 5); Iterable<Number> iterableLongAsNumber = Arrays.<Number>asList(1L, 2L, 3L, 4L, 5L); assertEquals(0, IterableUtils.frequency(iterableIntAsNumber, 2L)); assertEquals(0, IterableUtils.frequency(iterableLongAsNumber, 2)); final Set<String> set = new HashSet<String>(); set.add("A"); set.add("C"); set.add("E"); set.add("E"); assertEquals(1, IterableUtils.frequency(set, "A")); assertEquals(0, IterableUtils.frequency(set, "B")); assertEquals(1, IterableUtils.frequency(set, "C")); assertEquals(0, IterableUtils.frequency(set, "D")); assertEquals(1, IterableUtils.frequency(set, "E")); final Bag<String> bag = new HashBag<String>(); bag.add("A", 3); bag.add("C"); bag.add("E"); bag.add("E"); assertEquals(3, IterableUtils.frequency(bag, "A")); assertEquals(0, IterableUtils.frequency(bag, "B")); assertEquals(1, IterableUtils.frequency(bag, "C")); assertEquals(0, IterableUtils.frequency(bag, "D")); assertEquals(2, IterableUtils.frequency(bag, "E")); } @Test public void frequencyOfNull() { final List<String> list = new ArrayList<String>(); assertEquals(0, IterableUtils.frequency(list, null)); list.add("A"); assertEquals(0, IterableUtils.frequency(list, null)); list.add(null); assertEquals(1, IterableUtils.frequency(list, null)); list.add("B"); assertEquals(1, IterableUtils.frequency(list, null)); list.add(null); assertEquals(2, IterableUtils.frequency(list, null)); list.add("B"); assertEquals(2, IterableUtils.frequency(list, null)); list.add(null); assertEquals(3, IterableUtils.frequency(list, null)); } @Test public void find() { Predicate<Number> testPredicate = equalPredicate((Number) 4); Integer test = IterableUtils.find(iterableA, testPredicate); assertTrue(test.equals(4)); testPredicate = equalPredicate((Number) 45); test = IterableUtils.find(iterableA, testPredicate); assertTrue(test == null); assertNull(IterableUtils.find(null,testPredicate)); try { assertNull(IterableUtils.find(iterableA, null)); fail("expecting NullPointerException"); } catch (final NullPointerException npe) { // expected } } @Test public void indexOf() { Predicate<Number> testPredicate = equalPredicate((Number) 4); int index = IterableUtils.indexOf(iterableA, testPredicate); assertEquals(6, index); testPredicate = equalPredicate((Number) 45); index = IterableUtils.indexOf(iterableA, testPredicate); assertEquals(-1, index); assertEquals(-1, IterableUtils.indexOf(null, testPredicate)); try { assertNull(IterableUtils.indexOf(iterableA, null)); fail("expecting NullPointerException"); } catch (final NullPointerException npe) { // expected } } @Test public void countMatches() { assertEquals(4, IterableUtils.countMatches(iterableB, EQUALS_TWO)); assertEquals(0, IterableUtils.countMatches(null, EQUALS_TWO)); try { assertEquals(0, IterableUtils.countMatches(iterableA, null)); fail("predicate must not be null"); } catch (NullPointerException ex) { // expected } try { assertEquals(0, IterableUtils.countMatches(null, null)); fail("predicate must not be null"); } catch (NullPointerException ex) { // expected } } @Test public void matchesAny() { final List<Integer> list = new ArrayList<Integer>(); try { assertFalse(IterableUtils.matchesAny(null, null)); fail("predicate must not be null"); } catch (NullPointerException ex) { // expected } try { assertFalse(IterableUtils.matchesAny(list, null)); fail("predicate must not be null"); } catch (NullPointerException ex) { // expected } assertFalse(IterableUtils.matchesAny(null, EQUALS_TWO)); assertFalse(IterableUtils.matchesAny(list, EQUALS_TWO)); list.add(1); list.add(3); list.add(4); assertFalse(IterableUtils.matchesAny(list, EQUALS_TWO)); list.add(2); assertEquals(true, IterableUtils.matchesAny(list, EQUALS_TWO)); } @Test public void matchesAll() { try { assertFalse(IterableUtils.matchesAll(null, null)); fail("predicate must not be null"); } catch (NullPointerException ex) { // expected } try { assertFalse(IterableUtils.matchesAll(iterableA, null)); fail("predicate must not be null"); } catch (NullPointerException ex) { // expected } Predicate<Integer> lessThanFive = new Predicate<Integer>() { @Override public boolean evaluate(Integer object) { return object < 5; } }; assertTrue(IterableUtils.matchesAll(iterableA, lessThanFive)); Predicate<Integer> lessThanFour = new Predicate<Integer>() { @Override public boolean evaluate(Integer object) { return object < 4; } }; assertFalse(IterableUtils.matchesAll(iterableA, lessThanFour)); assertTrue(IterableUtils.matchesAll(null, lessThanFour)); assertTrue(IterableUtils.matchesAll(emptyIterable, lessThanFour)); } @Test(expected = IndexOutOfBoundsException.class) public void getFromIterable() throws Exception { // Collection, entry exists final Bag<String> bag = new HashBag<String>(); bag.add("element", 1); assertEquals("element", IterableUtils.get(bag, 0)); // Collection, non-existent entry IterableUtils.get(bag, 1); } @SuppressWarnings("unchecked") @Test public void partition() { List<Integer> input = new ArrayList<Integer>(); input.add(1); input.add(2); input.add(3); input.add(4); List<List<Integer>> partitions = IterableUtils.partition(input, EQUALS_TWO); assertEquals(2, partitions.size()); // first partition contains 2 Collection<Integer> partition = partitions.get(0); assertEquals(1, partition.size()); assertEquals(2, CollectionUtils.extractSingleton(partition).intValue()); // second partition contains 1, 3, and 4 Integer[] expected = {1, 3, 4}; partition = partitions.get(1); Assert.assertArrayEquals(expected, partition.toArray()); partitions = IterableUtils.partition((List<Integer>) null, EQUALS_TWO); assertEquals(2, partitions.size()); assertTrue(partitions.get(0).isEmpty()); assertTrue(partitions.get(1).isEmpty()); partitions = IterableUtils.partition(input); assertEquals(1, partitions.size()); assertEquals(input, partitions.get(0)); try { IterableUtils.partition(input, (Predicate<Integer>) null); fail("expecting NullPointerException"); } catch (NullPointerException npe) { // expected } } @SuppressWarnings("unchecked") @Test public void partitionMultiplePredicates() { List<Integer> input = new ArrayList<Integer>(); input.add(1); input.add(2); input.add(3); input.add(4); List<List<Integer>> partitions = IterableUtils.partition(input, EQUALS_TWO, EVEN); // first partition contains 2 Collection<Integer> partition = partitions.get(0); assertEquals(1, partition.size()); assertEquals(2, partition.iterator().next().intValue()); // second partition contains 4 partition = partitions.get(1); assertEquals(1, partition.size()); assertEquals(4, partition.iterator().next().intValue()); // third partition contains 1 and 3 Integer[] expected = {1, 3}; partition = partitions.get(2); Assert.assertArrayEquals(expected, partition.toArray()); try { IterableUtils.partition(input, EQUALS_TWO, null); } catch (NullPointerException npe) { // expected } } @Test public void testToString() { String result = IterableUtils.toString(iterableA); assertEquals("[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]", result); result = IterableUtils.toString(new ArrayList<Integer>()); assertEquals("[]", result); result = IterableUtils.toString(null); assertEquals("[]", result); result = IterableUtils.toString(iterableA, new Transformer<Integer, String>() { @Override public String transform(Integer input) { return new Integer(input * 2).toString(); } }); assertEquals("[2, 4, 4, 6, 6, 6, 8, 8, 8, 8]", result); result = IterableUtils.toString(new ArrayList<Integer>(), new Transformer<Integer, String>() { @Override public String transform(Integer input) { fail("not supposed to reach here"); return ""; } }); assertEquals("[]", result); result = IterableUtils.toString(null, new Transformer<Integer, String>() { @Override public String transform(Integer input) { fail("not supposed to reach here"); return ""; } }); assertEquals("[]", result); } @Test public void testToStringDelimiter() { Transformer<Integer, String> transformer = new Transformer<Integer, String>() { @Override public String transform(Integer input) { return new Integer(input * 2).toString(); } }; String result = IterableUtils.toString(iterableA, transformer, "", "", ""); assertEquals("2446668888", result); result = IterableUtils.toString(iterableA, transformer, ",", "", ""); assertEquals("2,4,4,6,6,6,8,8,8,8", result); result = IterableUtils.toString(iterableA, transformer, "", "[", "]"); assertEquals("[2446668888]", result); result = IterableUtils.toString(iterableA, transformer, ",", "[", "]"); assertEquals("[2,4,4,6,6,6,8,8,8,8]", result); result = IterableUtils.toString(iterableA, transformer, ",", "[[", "]]"); assertEquals("[[2,4,4,6,6,6,8,8,8,8]]", result); result = IterableUtils.toString(iterableA, transformer, ",,", "[", "]"); assertEquals("[2,,4,,4,,6,,6,,6,,8,,8,,8,,8]", result); result = IterableUtils.toString(iterableA, transformer, ",,", "((", "))"); assertEquals("((2,,4,,4,,6,,6,,6,,8,,8,,8,,8))", result); result = IterableUtils.toString(new ArrayList<Integer>(), transformer, "", "(", ")"); assertEquals("()", result); result = IterableUtils.toString(new ArrayList<Integer>(), transformer, "", "", ""); assertEquals("", result); } @Test public void testToStringWithNullArguments() { String result = IterableUtils.toString(null, new Transformer<Integer, String>() { @Override public String transform(Integer input) { fail("not supposed to reach here"); return ""; } }, "", "(", ")"); assertEquals("()", result); try { IterableUtils.toString(new ArrayList<Integer>(), null, "", "(", ")"); fail("expecting NullPointerException"); } catch (final NullPointerException ex) { // expected } try { IterableUtils.toString(new ArrayList<Integer>(), new Transformer<Integer, String>() { @Override public String transform(Integer input) { fail("not supposed to reach here"); return ""; } }, null, "(", ")"); fail("expecting NullPointerException"); } catch (final NullPointerException ex) { // expected } try { IterableUtils.toString(new ArrayList<Integer>(), new Transformer<Integer, String>() { @Override public String transform(Integer input) { fail("not supposed to reach here"); return ""; } }, "", null, ")"); fail("expecting NullPointerException"); } catch (final NullPointerException ex) { // expected } try { IterableUtils.toString(new ArrayList<Integer>(), new Transformer<Integer, String>() { @Override public String transform(Integer input) { fail("not supposed to reach here"); return ""; } }, "", "(", null); fail("expecting NullPointerException"); } catch (final NullPointerException ex) { // expected } } }