| /******************************************************************************* |
| * Copyright (c) 2011, 2017 itemis AG (http://www.itemis.eu) and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| *******************************************************************************/ |
| package org.eclipse.xtext.xbase.tests.lib; |
| |
| import static com.google.common.collect.Lists.*; |
| import static com.google.common.collect.Sets.*; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.xtext.xbase.lib.Functions; |
| import org.eclipse.xtext.xbase.lib.Functions.Function1; |
| import org.eclipse.xtext.xbase.lib.IterableExtensions; |
| import org.eclipse.xtext.xbase.lib.Pair; |
| import org.eclipse.xtext.xbase.lib.Procedures.Procedure2; |
| import org.junit.Test; |
| |
| import com.google.common.collect.ForwardingCollection; |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Sets; |
| |
| /** |
| * @author Sebastian Zarnekow - Initial contribution and API |
| * @author Karsten Thoms - testMap, testFlatMap |
| */ |
| public class IterableExtensionsTest extends BaseIterablesIteratorsTest<Iterable<Integer>> { |
| |
| @Override |
| protected Iterable<Integer>[] testData(Integer... elements) { |
| @SuppressWarnings("unchecked") |
| Iterable<Integer>[] result = new Iterable[] { |
| Lists.newArrayList(elements), |
| Lists.newLinkedList(Lists.newArrayList(elements)), |
| Sets.newLinkedHashSet(Lists.newArrayList(elements)), |
| Sets.newTreeSet(Lists.newArrayList(elements)) |
| }; |
| return result; |
| } |
| |
| @Override |
| protected Iterable<Integer>[] nullableTestData(Integer... elements) { |
| @SuppressWarnings("unchecked") |
| Iterable<Integer>[] result = new Iterable[] { |
| Lists.newArrayList(elements), |
| Lists.newLinkedList(Lists.newArrayList(elements)), |
| Sets.newLinkedHashSet(Lists.newArrayList(elements)), |
| // Sets.newTreeSet(Lists.newArrayList(elements)) null is not allowed |
| }; |
| return result; |
| } |
| |
| @Override |
| protected Iterable<Integer> dummy() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| protected boolean is(Iterable<Integer> input, Integer... elements) { |
| return Iterables.elementsEqual(input, Lists.newArrayList(elements)); |
| } |
| |
| @Override |
| protected Iterable<Integer> operator_plus(Iterable<Integer> first, Iterable<Integer> second) { |
| return IterableExtensions.operator_plus(first, second); |
| } |
| |
| @Override |
| protected Integer findFirst(Iterable<Integer> input, Function1<Integer, Boolean> filter) { |
| return IterableExtensions.findFirst(input, filter); |
| } |
| |
| @Override |
| protected Integer findLast(Iterable<Integer> input, Function1<Integer, Boolean> filter) { |
| return IterableExtensions.findLast(input, filter); |
| } |
| |
| @Override |
| protected Integer last(Iterable<Integer> input) { |
| return IterableExtensions.last(input); |
| } |
| |
| @Override |
| protected Integer head(Iterable<Integer> input) { |
| return IterableExtensions.head(input); |
| } |
| |
| @Override |
| protected void forEach(Iterable<Integer> input, Procedure2<Integer, Integer> proc) { |
| IterableExtensions.forEach(input, proc); |
| } |
| |
| @Override |
| protected Iterable<Integer> takeWhile(Iterable<Integer> input, Function1<Integer, Boolean> filter) { |
| return IterableExtensions.takeWhile(input, filter); |
| } |
| |
| @Override |
| protected Iterable<Integer> dropWhile(Iterable<Integer> input, Function1<Integer, Boolean> filter) { |
| return IterableExtensions.dropWhile(input, filter); |
| } |
| |
| @Override |
| protected Integer max(Iterable<Integer> input) { |
| return IterableExtensions.max(input); |
| } |
| |
| @Override |
| protected Integer max(Iterable<Integer> input, Comparator<? super Integer> comparator) { |
| return IterableExtensions.max(input, comparator); |
| } |
| |
| @Override |
| protected Integer maxBy(Iterable<Integer> input, Function1<? super Integer, String> compareBy) { |
| return IterableExtensions.maxBy(input, compareBy); |
| } |
| |
| @Override |
| protected Integer min(Iterable<Integer> input) { |
| return IterableExtensions.min(input); |
| } |
| |
| @Override |
| protected Integer min(Iterable<Integer> input, Comparator<? super Integer> comparator) { |
| return IterableExtensions.min(input, comparator); |
| } |
| |
| @Override |
| protected Integer minBy(Iterable<Integer> input, Function1<? super Integer, String> compareBy) { |
| return IterableExtensions.minBy(input, compareBy); |
| } |
| |
| @Test public void testJoinWithNull() { |
| List<String> list = Lists.newArrayList("a", null, "c"); |
| String string = IterableExtensions.join(list, ","); |
| assertEquals("a,null,c", string); |
| } |
| |
| @Test public void testSortBy() throws Exception { |
| List<? extends CharSequence> list = newArrayList("foo","bar","baz"); |
| List<? extends CharSequence> sorted = IterableExtensions.sortBy(list, new Functions.Function1<CharSequence, String>() { |
| @Override |
| public String apply(CharSequence p) { |
| return p.toString(); |
| } |
| }); |
| assertNotSame(list, sorted); |
| assertEquals(sorted, newArrayList("bar","baz","foo")); |
| } |
| |
| @Test public void testFilterNull() throws Exception { |
| Iterator<String> iter = IterableExtensions.filterNull(newArrayList("foo", null, "bar")).iterator(); |
| assertEquals("foo", iter.next()); |
| assertEquals("bar", iter.next()); |
| assertFalse(iter.hasNext()); |
| } |
| |
| @Test public void testJoinWithBeforeAndAfter() throws Exception { |
| ArrayList<String> list = newArrayList("foo", "bar"); |
| ArrayList<String> singletonList = newArrayList("foo"); |
| ArrayList<String> emptylist = new ArrayList<String>(); |
| |
| final Functions.Function1<String, String> function = new Functions.Function1<String, String>() { |
| @Override |
| public String apply(String p) { |
| return p; |
| } |
| }; |
| assertEquals("<foo,bar>", IterableExtensions.join(list, "<", ",", ">", function)); |
| assertEquals("<foo>", IterableExtensions.join(singletonList, "<", ",", ">", function)); |
| assertEquals("", IterableExtensions.join(emptylist, "<", ",", ">", function)); |
| |
| assertEquals("foo,bar>", IterableExtensions.join(list, null, ",", ">", function)); |
| assertEquals("foo>", IterableExtensions.join(singletonList, null, ",", ">", function)); |
| assertEquals("", IterableExtensions.join(emptylist, null, ",", ">", function)); |
| |
| assertEquals("<foobar>", IterableExtensions.join(list, "<", null, ">", function)); |
| assertEquals("<foo>", IterableExtensions.join(singletonList, "<", null, ">", function)); |
| assertEquals("", IterableExtensions.join(emptylist, "<", null, ">", function)); |
| |
| assertEquals("<foo,bar", IterableExtensions.join(list, "<", ",", null, function)); |
| assertEquals("<foo", IterableExtensions.join(singletonList, "<", ",", null, function)); |
| assertEquals("", IterableExtensions.join(emptylist, "<", ",", null, function)); |
| } |
| |
| @Test public void testIndexed() { |
| Iterator<Pair<Integer, String>> result = IterableExtensions.indexed(newArrayList("foo", "bar")).iterator(); |
| assertEquals(new Pair<Integer, String>(0, "foo"), result.next()); |
| assertEquals(new Pair<Integer, String>(1, "bar"), result.next()); |
| assertFalse(result.hasNext()); |
| } |
| |
| class A {} |
| interface C {} |
| class B extends A implements C {} |
| class D extends A {} |
| |
| @Test public void testReject() { |
| List<Integer> nullList = new ArrayList<>(); |
| nullList.add(null); |
| List<Object> objects = newArrayList(1, 2, null, 4l, "String"); |
| assertEquals(newArrayList(1, 2, null, 4l), newArrayList(IterableExtensions.reject(objects, String.class))); |
| assertEquals(nullList, newArrayList(IterableExtensions.reject(objects, Object.class))); |
| |
| List<Integer> integerObjects = newArrayList(1, 2, null, 4); |
| assertEquals(nullList, newArrayList(IterableExtensions.reject(integerObjects, Integer.class))); |
| |
| List<A> bObjects = newArrayList(new B(), new B(), new D()); |
| assertEquals(0, IterableExtensions.size(IterableExtensions.reject(bObjects, A.class))); |
| assertEquals(1, IterableExtensions.size(IterableExtensions.reject(bObjects, B.class))); |
| assertEquals(1, IterableExtensions.size(IterableExtensions.reject(bObjects, C.class))); |
| assertEquals(2, IterableExtensions.size(IterableExtensions.reject(bObjects, D.class))); |
| |
| Function1<Integer, Boolean> function = new Function1<Integer, Boolean>() { |
| @Override |
| public Boolean apply(Integer p) { |
| return p % 2 == 0; |
| } |
| }; |
| assertEquals(newArrayList(1,3,5),newArrayList(IterableExtensions.reject(newArrayList(1,2,3,4,5), function))); |
| Function1<Integer, Boolean> functionNullSafe = new Function1<Integer, Boolean>() { |
| @Override |
| public Boolean apply(Integer p) { |
| return p == null || p % 2 == 0; |
| } |
| }; |
| assertEquals(newArrayList(1,5),newArrayList(IterableExtensions.reject(newArrayList(1,2,null,4,5), functionNullSafe))); |
| try { |
| newArrayList(IterableExtensions.reject(null, function)); |
| fail("NullPointerException expected"); |
| } catch (NullPointerException e) { |
| // expected NPE |
| } |
| try { |
| Function1<? super Integer, Boolean> nullFn = null; |
| newArrayList(IterableExtensions.reject(newArrayList(1,2,3), nullFn)); |
| fail("NullPointerException expected"); |
| } catch (NullPointerException e) { |
| // expected NPE |
| } |
| try { |
| Class<Integer> nullClass = null; |
| newArrayList(IterableExtensions.reject(newArrayList(1,2,3), nullClass)); |
| fail("NullPointerException expected"); |
| } catch (NullPointerException e) { |
| // expected NPE |
| } |
| Function1<Integer, Boolean> brokenFunction = new Function1<Integer, Boolean>() { |
| @Override |
| public Boolean apply(Integer p) { |
| return null; |
| } |
| }; |
| try { |
| newArrayList(IterableExtensions.reject(newArrayList(1,2,3), brokenFunction)); |
| fail("NullPointerException expected"); |
| } catch (NullPointerException e) { |
| // expected NPE |
| } |
| } |
| |
| @Test public void testMap () { |
| ArrayList<String> list = newArrayList("foo", "bar"); |
| |
| final Functions.Function1<String, String> function = new Functions.Function1<String, String>() { |
| @Override |
| public String apply(String p) { |
| return "Hello "+p; |
| } |
| }; |
| |
| assertEquals(newArrayList("Hello foo", "Hello bar"), newArrayList(IterableExtensions.map(list, function))); |
| |
| // test that the returned iterator supports remove on the underyling list |
| // therefore we need a function that maps to the same object contained in the list |
| final Functions.Function1<String, String> functionForRemove = new Functions.Function1<String, String>() { |
| @Override |
| public String apply(String p) { |
| return "foo".equals(p) ? p : "Hello "+p; |
| } |
| }; |
| |
| assertTrue(list.contains("foo")); |
| assertEquals(2, list.size()); |
| assertEquals(newArrayList("foo", "Hello bar"), newArrayList(IterableExtensions.map(list, functionForRemove))); |
| Iterator<String> iterator = IterableExtensions.map(list, functionForRemove).iterator(); |
| iterator.next(); |
| iterator.remove(); |
| |
| assertTrue(!list.contains("foo")); |
| assertEquals(1, list.size()); |
| } |
| |
| @Test public void testFlatMap () { |
| ArrayList<String> list = newArrayList("foo", "bar"); |
| |
| final Functions.Function1<String, Iterable<String>> function = new Functions.Function1<String, Iterable<String>>() { |
| @Override |
| public Iterable<String> apply(String p) { |
| return newArrayList("Hello", p); |
| } |
| }; |
| assertEquals(newArrayList("Hello", "foo", "Hello", "bar"), newArrayList(IterableExtensions.flatMap(list, function))); |
| } |
| |
| @Test public void testContains() { |
| ArrayList<String> list = newArrayList("element1", "element2", "element3", null); |
| |
| assertTrue(IterableExtensions.contains(list, "element3")); |
| assertTrue(IterableExtensions.contains(list, new String("element3"))); |
| assertTrue(IterableExtensions.contains(list, null)); |
| |
| assertFalse(IterableExtensions.contains(list, "element4")); |
| assertFalse(IterableExtensions.contains(list, new String("element4"))); |
| } |
| |
| private static class TestableCollection<T> extends ForwardingCollection<T> { |
| |
| private Collection<T> original; |
| boolean containsWasCalled; |
| Object containsParameter; |
| |
| public TestableCollection(Collection<T> original) { |
| super(); |
| this.original = original; |
| } |
| |
| @Override |
| protected Collection<T> delegate() { |
| return original; |
| } |
| |
| @Override |
| public boolean contains(Object object) { |
| containsWasCalled = true; |
| containsParameter = object; |
| return super.contains(object); |
| } |
| } |
| |
| @Test public void testContainsOnCollection() { |
| //GIVEN a collection, declared as an iterable |
| TestableCollection<String> collection = new TestableCollection<String>(newHashSet("element1", "element2", "element3")); |
| |
| //WHEN we call the contains method via the IterableExtensions |
| IterableExtensions.contains(collection, "element1"); |
| |
| //THEN we expect that the collection's native contains method was used |
| assertTrue("IterableExtensions.contains didn't use the collection's native contains method", |
| collection.containsWasCalled); |
| assertEquals("element1", collection.containsParameter); |
| } |
| } |