/* * Copyright 2015 Goldman Sachs. * * 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.gs.collections.impl.block.factory; import java.io.IOException; import java.util.Map; import com.gs.collections.api.block.function.Function; import com.gs.collections.api.block.function.primitive.DoubleFunction; import com.gs.collections.api.block.function.primitive.IntFunction; import com.gs.collections.api.block.function.primitive.LongFunction; import com.gs.collections.api.block.function.primitive.ShortFunction; import com.gs.collections.api.collection.MutableCollection; import com.gs.collections.api.list.ImmutableList; import com.gs.collections.api.list.MutableList; import com.gs.collections.api.map.MutableMap; import com.gs.collections.api.set.MutableSet; import com.gs.collections.api.tuple.Pair; import com.gs.collections.impl.block.function.primitive.IntegerFunctionImpl; import com.gs.collections.impl.block.function.primitive.LongFunctionImpl; import com.gs.collections.impl.factory.Lists; import com.gs.collections.impl.list.Interval; import com.gs.collections.impl.list.mutable.FastList; import com.gs.collections.impl.map.mutable.UnifiedMap; import com.gs.collections.impl.set.mutable.SetAdapter; import com.gs.collections.impl.set.mutable.UnifiedSet; import com.gs.collections.impl.test.Verify; import com.gs.collections.impl.test.domain.Person; import com.gs.collections.impl.tuple.Tuples; import org.junit.Assert; import org.junit.Test; import static com.gs.collections.impl.factory.Iterables.iList; public class FunctionsTest { private static final Function<String, Integer> STRING_LENGTH = String::length; private static final Function<Integer, Boolean> IS_ODD = object -> Boolean.valueOf(object.intValue() % 2 != 0); private static final Function<Boolean, String> BOOLEAN_STRING = String::valueOf; @Test public void throwing() { Verify.assertThrowsWithCause( RuntimeException.class, IOException.class, () -> Functions.throwing(a -> { throw new IOException(); }).valueOf(null)); } @Test public void getPassThru() { Object object = new Object(); Assert.assertSame(object, Functions.getPassThru().valueOf(object)); } @Test public void getFixedValue() { Assert.assertEquals(Integer.valueOf(5), Functions.getFixedValue(5).valueOf(null)); } @Test public void getToClass() { Assert.assertSame(Integer.class, Functions.getToClass().valueOf(0)); } @Test public void getMathSinFunction() { Function<Number, Double> function = Functions.getMathSinFunction(); Assert.assertEquals(Math.sin(1.0), function.valueOf(1), 0.0); } @Test public void getNumberPassThru() { Function<Number, Number> function = Functions.getNumberPassThru(); Assert.assertEquals(1, function.valueOf(1)); } @Test public void getIntegerPassThru() { Function<Integer, Integer> function = Functions.getIntegerPassThru(); Assert.assertEquals(Integer.valueOf(1), function.valueOf(1)); Assert.assertEquals("IntegerPassThruFunction", function.toString()); } @Test public void getLongPassThru() { Function<Long, Long> function = Functions.getLongPassThru(); Assert.assertEquals(Long.valueOf(1), function.valueOf(1L)); Assert.assertEquals(Long.valueOf(1L), Long.valueOf(((LongFunction<Long>) function).longValueOf(1L))); Assert.assertEquals("LongPassThruFunction", function.toString()); } @Test public void getDoublePassThru() { Function<Double, Double> function = Functions.getDoublePassThru(); Assert.assertEquals(Double.valueOf(1).doubleValue(), function.valueOf(1.0).doubleValue(), 0.0); Assert.assertEquals(Double.valueOf(1).doubleValue(), ((DoubleFunction<Double>) function).doubleValueOf(1.0), 0.0); Assert.assertEquals("DoublePassThruFunction", function.toString()); } @Test public void getStringPassThru() { Function<String, String> function = Functions.getStringPassThru(); Assert.assertEquals("hello", function.valueOf("hello")); } @Test public void getStringTrim() { Assert.assertEquals("hello", Functions.getStringTrim().valueOf(" hello ")); } @Test public void getToString() { Function<Object, String> function = Functions.getToString(); Assert.assertEquals("1", function.valueOf(1)); Assert.assertEquals("null", function.valueOf(null)); } @Test public void getDefaultToString() { Function<Object, String> function = Functions.getNullSafeToString("N/A"); Assert.assertEquals("1", function.valueOf(1)); Assert.assertEquals("N/A", function.valueOf(null)); } @Test public void getStringToInteger() { Function<String, Integer> function = Functions.getStringToInteger(); Assert.assertEquals(Integer.valueOf(1), function.valueOf("1")); } @Test public void firstNotNullValue() { Function<Object, Integer> function1 = Functions.firstNotNullValue(Functions.<Object, Integer>getFixedValue(null), Functions.getFixedValue(1), Functions.getFixedValue(2)); Assert.assertEquals(Integer.valueOf(1), function1.valueOf(null)); Function<Object, Integer> function2 = Functions.firstNotNullValue(Functions.<Object, Integer>getFixedValue(null), Functions.getFixedValue(null)); Assert.assertNull(function2.valueOf(null)); } @Test public void firstNotEmptyStringValue() { Function<Object, String> function1 = Functions.firstNotEmptyStringValue(Functions.getFixedValue(""), Functions.getFixedValue("hello"), Functions.getFixedValue("")); Assert.assertEquals("hello", function1.valueOf(null)); Function<Object, String> function2 = Functions.firstNotEmptyStringValue(Functions.getFixedValue(""), Functions.getFixedValue("")); Assert.assertNull(function2.valueOf(null)); } @Test public void firstNotEmptyCollectionValue() { Function<Object, ImmutableList<String>> function1 = Functions.firstNotEmptyCollectionValue( Functions.getFixedValue(Lists.immutable.<String>of()), Functions.getFixedValue(Lists.immutable.of("hello")), Functions.getFixedValue(Lists.immutable.<String>of())); Assert.assertEquals(iList("hello"), function1.valueOf(null)); Function<Object, ImmutableList<String>> function2 = Functions.firstNotEmptyCollectionValue( Functions.getFixedValue(Lists.immutable.<String>of()), Functions.getFixedValue(Lists.immutable.<String>of())); Assert.assertNull(function2.valueOf(null)); } @Test public void ifTrue() { String result = "1"; Assert.assertSame(result, Functions.ifTrue(Predicates.alwaysTrue(), Functions.getPassThru()).valueOf(result)); Assert.assertNull(result, Functions.ifTrue(Predicates.alwaysFalse(), Functions.getPassThru()).valueOf(result)); } @Test public void ifElse() { String result1 = "1"; String result2 = "2"; Assert.assertSame(result1, Functions.ifElse(Predicates.alwaysTrue(), Functions.getFixedValue(result1), Functions.getFixedValue(result2)).valueOf(null)); Assert.assertSame(result2, Functions.ifElse(Predicates.alwaysFalse(), Functions.getFixedValue(result1), Functions.getFixedValue(result2)).valueOf(null)); Verify.assertContains("IfFunction", Functions.ifElse(Predicates.alwaysTrue(), Functions.getFixedValue(result1), Functions.getFixedValue(result2)).toString()); } @Test public void synchronizedEach() { Function<Integer, String> function = Functions.synchronizedEach(Object::toString); Verify.assertSetsEqual( UnifiedSet.newSetWith("1", "2", "3"), UnifiedSet.newSetWith(1, 2, 3).collect(function)); } @Test public void chains() { Function<String, Integer> toInteger = Functions.getStringToInteger(); Function<Object, String> toString = String::valueOf; Assert.assertEquals("42", Functions.chain(toInteger, toString).valueOf("42")); Assert.assertEquals(Integer.valueOf(42), Functions.chain(toString, toInteger).valueOf(42)); Function<String, Integer> chain = Functions.chain(toInteger, toString).chain(toInteger); Assert.assertEquals(Integer.valueOf(42), chain.valueOf("42")); Assert.assertEquals("42", Functions.chain(toString, toInteger).chain(toString).valueOf(42)); Assert.assertEquals("42", Functions.chain(toInteger, toString).chain(toInteger).chain(toString).valueOf("42")); Assert.assertEquals(Integer.valueOf(42), Functions.chain(toString, toInteger).chain(toString).chain(toInteger).valueOf(42)); Assert.assertEquals(Integer.valueOf(42), Functions.chain(toInteger, toString).chain(toInteger).chain(toString).chain(toInteger).valueOf("42")); Assert.assertEquals(Integer.valueOf(42), Functions.chain(toString, toInteger).chain(toString).chain(toInteger).chain(toString).chain(toInteger).valueOf(42)); } @Test public void chain_two() { Function<Boolean, Integer> chain = Functions.chain(BOOLEAN_STRING, STRING_LENGTH); Assert.assertEquals(Integer.valueOf(5), chain.valueOf(Boolean.FALSE)); } @Test public void chain_three() { Function<String, String> chain = Functions.chain(STRING_LENGTH, IS_ODD).chain(BOOLEAN_STRING); Assert.assertEquals("true", chain.valueOf("foo")); } @Test public void chain_four() { Function<Integer, Boolean> chain = Functions.chain(IS_ODD, BOOLEAN_STRING).chain(STRING_LENGTH).chain(IS_ODD); Assert.assertEquals(Boolean.TRUE, chain.valueOf(Integer.valueOf(4))); } @Test public void chainBoolean() { Function<String, Integer> toInteger = Functions.getStringToInteger(); Functions.BooleanFunctionChain<String, Integer> booleanFunctionChain = Functions.chainBoolean(toInteger, integerObject -> integerObject.intValue() >= 0); Assert.assertTrue(booleanFunctionChain.booleanValueOf("45")); Assert.assertFalse(booleanFunctionChain.booleanValueOf("-45")); } @Test public void chainByte() { Function<String, Integer> toInteger = Functions.getStringToInteger(); Functions.ByteFunctionChain<String, Integer> byteFunctionChain = Functions.chainByte(toInteger, Integer::byteValue); Assert.assertEquals((byte) 45, byteFunctionChain.byteValueOf("45")); Assert.assertEquals((byte) -45, byteFunctionChain.byteValueOf("-45")); } @Test public void chainChar() { Function<Object, String> toString = String::valueOf; Functions.CharFunctionChain<Object, String> charFunctionChain = Functions.chainChar(toString, stringObject -> stringObject.charAt(0)); Assert.assertEquals('g', charFunctionChain.charValueOf("gscollections")); Assert.assertEquals('-', charFunctionChain.charValueOf("-4")); } @Test public void chainDouble() { Function<String, Integer> toInteger = Functions.getStringToInteger(); Functions.DoubleFunctionChain<String, Integer> doubleFunctionChain = Functions.chainDouble(toInteger, Integer::doubleValue); Assert.assertEquals(146.0, doubleFunctionChain.doubleValueOf("146"), 0.0); Assert.assertEquals(-456.0, doubleFunctionChain.doubleValueOf("-456"), 0.0); } @Test public void chainFloat() { Functions.FloatFunctionChain<Integer, String> floatFunctionChain = Functions.chainFloat(String::valueOf, stringObject -> Float.valueOf(stringObject).floatValue()); Assert.assertEquals(146.0, floatFunctionChain.floatValueOf(146), 0.0); Assert.assertEquals(-456.0, floatFunctionChain.floatValueOf(-456), 0.0); } @Test public void chainInt() { Function<Float, String> toString = String::valueOf; IntFunction<String> stringToLength = new IntegerFunctionImpl<String>() { public int intValueOf(String stringObject) { return stringObject.length(); } }; Functions.IntFunctionChain<Float, String> intFunctionChain = Functions.chainInt(toString, stringToLength); Assert.assertEquals(5, intFunctionChain.intValueOf(Float.valueOf(145))); Assert.assertEquals(6, intFunctionChain.intValueOf(Float.valueOf(-145))); } @Test public void chainLong() { Function<Float, String> toString = String::valueOf; LongFunction<String> stringToLengthLong = stringObject -> Long.valueOf(stringObject.length()).longValue(); Functions.LongFunctionChain<Float, String> longFunctionChain = Functions.chainLong(toString, stringToLengthLong); Assert.assertEquals(5L, longFunctionChain.longValueOf(Float.valueOf(145))); Assert.assertEquals(6L, longFunctionChain.longValueOf(Float.valueOf(-145))); } @Test public void chainShort() { Functions.ShortFunctionChain<Integer, String> shortFunctionChain = Functions.chainShort(String::valueOf, stringObject -> Short.valueOf(stringObject).shortValue()); Assert.assertEquals((short) 145, shortFunctionChain.shortValueOf(145)); Assert.assertEquals((short) -145, shortFunctionChain.shortValueOf(-145)); } @Test public void chain_two_chainBoolean() { Functions.FunctionChain<Boolean, String, Integer> chain = Functions.chain(String::valueOf, STRING_LENGTH); Functions.BooleanFunctionChain<Boolean, Integer> booleanChain = chain.chainBoolean(integerObject -> integerObject.intValue() >= 0); Assert.assertTrue(booleanChain.booleanValueOf(Boolean.TRUE)); } @Test public void chain_two_chainByte() { Functions.FunctionChain<Boolean, String, Integer> chain = Functions.chain(String::valueOf, STRING_LENGTH); Functions.ByteFunctionChain<Boolean, Integer> byteChain = chain.chainByte(Integer::byteValue); Assert.assertEquals((byte) 5, byteChain.byteValueOf(Boolean.FALSE)); } @Test public void chain_three_chainChar() { Functions.FunctionChain<String, Boolean, String> chain = Functions.chain(STRING_LENGTH, IS_ODD).chain(BOOLEAN_STRING); Functions.CharFunctionChain<String, String> charChain = chain.chainChar(stringObject -> stringObject.charAt(0)); Assert.assertEquals('t', charChain.charValueOf("foo")); } @Test public void chain_three_chainDouble() { Functions.FunctionChain<Boolean, String, Integer> chain = Functions.chain(String::valueOf, STRING_LENGTH); Functions.DoubleFunctionChain<Boolean, Integer> doubleChain = chain.chainDouble(Integer::doubleValue); Assert.assertEquals(4.0, doubleChain.doubleValueOf(Boolean.TRUE), 0.0); } @Test public void chain_three_chainFloat() { Functions.FunctionChain<String, Boolean, String> chain = Functions.chain(STRING_LENGTH, IS_ODD).chain(BOOLEAN_STRING); Functions.FloatFunctionChain<String, String> floatChain = chain.chainFloat(stringObject -> Integer.valueOf(stringObject.length()).floatValue()); Assert.assertEquals(5.0, floatChain.floatValueOf("12.2"), 0); } @Test public void chain_three_chainInt() { Functions.FunctionChain<String, Boolean, String> chain = Functions.chain(STRING_LENGTH, IS_ODD).chain(BOOLEAN_STRING); IntFunction<String> stringToLength = new IntegerFunctionImpl<String>() { public int intValueOf(String stringObject) { return stringObject.length(); } }; Functions.IntFunctionChain<String, String> intChain = chain.chainInt(stringToLength); Assert.assertEquals(4, intChain.intValueOf("gsc")); Assert.assertNotEquals(4, intChain.intValueOf("kata")); } @Test public void chain_three_chainLong() { Functions.FunctionChain<String, Boolean, String> chain = Functions.chain(STRING_LENGTH, IS_ODD).chain(BOOLEAN_STRING); LongFunction<String> stringToLengthLong = stringObject -> Long.valueOf(stringObject.length()).longValue(); Functions.LongFunctionChain<String, String> longChain = chain.chainLong(stringToLengthLong); Assert.assertEquals(4L, longChain.longValueOf("gsc")); Assert.assertNotEquals(4L, longChain.longValueOf("kata")); } @Test public void chain_three_chainShort() { Functions.FunctionChain<String, Boolean, String> chain = Functions.chain(STRING_LENGTH, IS_ODD).chain(BOOLEAN_STRING); ShortFunction<String> stringToShort = stringObject -> Integer.valueOf(stringObject.length()).shortValue(); Functions.ShortFunctionChain<String, String> shortChain = chain.chainShort(stringToShort); Assert.assertEquals((short) 4, shortChain.shortValueOf("gsc")); Assert.assertNotEquals((short) 4, shortChain.shortValueOf("kata")); } @Test public void intValueFunctionToComparator() { MutableList<Integer> list = Interval.oneTo(100).toList().shuffleThis(); Function<Integer, Integer> function = Integer::intValue; list.sortThis(Comparators.byFunction(function)); Assert.assertEquals(Interval.oneTo(100).toList(), list); } @Test public void doubleValueFunctionToComparator() { MutableList<Double> list = FastList.newListWith(5.0, 4.0, 3.0, 2.0, 1.0).shuffleThis(); Function<Double, Double> function = Double::doubleValue; list.sortThis(Comparators.byFunction(function)); Assert.assertEquals(FastList.newListWith(1.0, 2.0, 3.0, 4.0, 5.0), list); } @Test public void longValueFunctionToComparator() { MutableList<Long> list = FastList.newListWith(5L, 4L, 3L, 2L, 1L).shuffleThis(); list.sortThis(Comparators.byFunction(new LongFunctionImpl<Long>() { public long longValueOf(Long each) { return each.longValue(); } })); Assert.assertEquals(FastList.newListWith(1L, 2L, 3L, 4L, 5L), list); } @Test public void classFunctionToString() { Assert.assertEquals("object.getClass()", Functions.getToClass().toString()); } @Test public void mathSinToString() { Assert.assertEquals("Math.sin()", Functions.getMathSinFunction().toString()); } @Test public void mathStringToIntegerToString() { Assert.assertEquals("stringToInteger", Functions.getStringToInteger().toString()); } @Test public void pair() { Person john = new Person("John", "Smith"); Person jane = new Person("Jane", "Smith"); Person johnDoe = new Person("John", "Doe"); MutableList<Person> people = FastList.newListWith(john, jane, johnDoe); MutableList<Person> sorted = people.sortThisBy(Functions.pair(Person.TO_LAST, Person.TO_FIRST)); Assert.assertEquals(FastList.newListWith(johnDoe, jane, john), sorted); } @Test public void key() { MutableMap<String, Integer> map = UnifiedMap.newWithKeysValues("One", 1); MutableSet<Map.Entry<String, Integer>> entries = SetAdapter.adapt(map.entrySet()); MutableSet<String> keys = entries.collect(Functions.<String>getKeyFunction()); Assert.assertEquals(UnifiedSet.newSetWith("One"), keys); } @Test public void value() { MutableMap<String, Integer> map = UnifiedMap.newWithKeysValues("One", 1); MutableSet<Map.Entry<String, Integer>> entries = SetAdapter.adapt(map.entrySet()); MutableSet<Integer> values = entries.collect(Functions.<Integer>getValueFunction()); Assert.assertEquals(UnifiedSet.newSetWith(1), values); } @Test public void size() { ImmutableList<ImmutableList<Integer>> list = Lists.immutable.of(Lists.immutable.of(1), Lists.immutable.of(1, 2), Lists.immutable.of(1, 2, 3)); ImmutableList<Integer> sizes = list.collect(Functions.getSizeOf()); Assert.assertEquals(FastList.newListWith(1, 2, 3), sizes); } @Test public void squaredCollection() { MutableCollection<Integer> squareCollection = FastList.newListWith(1, 2, 3, 4, 5).collect(Functions.squaredInteger()); Verify.assertContainsAll(squareCollection, 1, 4, 9, 16, 25); } @Test public void withDefault() { Object expected = new Object(); Assert.assertSame(expected, Functions.withDefault(Functions.getFixedValue(null), expected).valueOf(new Object())); Object expected2 = new Object(); Assert.assertSame(expected2, Functions.withDefault(Functions.getFixedValue(expected2), expected).valueOf(new Object())); } @Test public void nullSafe() { Object expected = new Object(); Function<Object, Object> throwsFunction = new ThrowsFunction(); Assert.assertSame(expected, Functions.nullSafe(throwsFunction, expected).valueOf(null)); Assert.assertSame(expected, Functions.nullSafe(Functions.getFixedValue(expected)).valueOf(new Object())); Assert.assertNull(Functions.nullSafe(throwsFunction).valueOf(null)); } @Test public void classForName() { Class<?> objectClass = Functions.classForName().valueOf("java.lang.Object"); Assert.assertSame(Object.class, objectClass); } @Test public void bind_function2_parameter() { MutableCollection<Integer> multiplied = FastList.newListWith(1, 2, 3, 4, 5).collect(Functions.bind((value, parameter) -> value * parameter, 2)); Verify.assertContainsAll(multiplied, 2, 4, 6, 8, 10); } @Test public void swappedPair() { Pair<Integer, String> pair1 = Tuples.pair(1, "One"); Pair<Integer, String> pair2 = Tuples.pair(2, "Two"); Pair<Integer, String> pair3 = Tuples.pair(3, "Three"); Pair<Integer, String> pair4 = Tuples.pair(4, "Four"); MutableList<Pair<Integer, String>> testList = FastList.<Pair<Integer, String>>newListWith(pair1, pair2, pair3, pair4); MutableList<Pair<String, Integer>> actual = testList.collect(Functions.swappedPair()); MutableList<Pair<String, Integer>> expected = FastList.<Pair<String, Integer>>newListWith(Tuples.pair("One", 1), Tuples.pair("Two", 2), Tuples.pair("Three", 3), Tuples.pair("Four", 4)); Assert.assertEquals(expected, actual); } @Test public void getTrue() { Assert.assertTrue(Functions.getTrue().valueOf(false)); } @Test public void getFalse() { Assert.assertFalse(Functions.getFalse().valueOf(true)); } private static class ThrowsFunction implements Function<Object, Object> { @Override public Object valueOf(Object object) { throw new RuntimeException(); } } @Test public void classIsNonInstantiable() { Verify.assertClassNonInstantiable(Functions.class); } }