// Copyright 2010 The Apache Software Foundation // // 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 org.apache.tapestry5.func; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.testng.annotations.Test; public class MapperTest extends BaseFuncTest { protected Mapper<Integer, Flow<Integer>> sequencer = new Mapper<Integer, Flow<Integer>>() { @Override public Flow<Integer> map(Integer value) { Flow<Integer> flow = F.flow(); for (int i = 0; i < value; i++) flow = flow.append(value); return flow; } }; @Test public void map() { List<String> source = Arrays.asList("Mary", "had", "a", "little", "lamb"); List<Integer> lengths = F.flow(source).map(stringToLength).toList(); assertListsEquals(lengths, 4, 3, 1, 6, 4); } @Test public void flow_map() { assertFlowValues(F.flow("Mary", "had", "a", "little", "lamb").map(stringToLength), 4, 3, 1, 6, 4); } @Test public void map_of_filtered_empty_is_empty() { assertTrue(filteredEmpty.map(new Mapper<Integer, Integer>() { @Override public Integer map(Integer value) { unreachable(); return value; } }).isEmpty()); } @Test public void mapcat_on_empty_flow_is_empty() { Flow<Integer> flow = F.flow(); assertSame(flow.mapcat(sequencer), flow); assertTrue(filteredEmpty.mapcat(sequencer).isEmpty()); } @Test public void mapcat() { Flow<Integer> flow = F.flow(3, 1, 2); assertFlowValues(flow.mapcat(sequencer), 3, 3, 3, 1, 2, 2); } @Test public void count_of_a_mapped_filtered_empty_flow() { Flow<Integer> flow = F.flow("Mary", "had", "etc.").filter(F.isNull()).map(stringToLength); assertTrue(flow.isEmpty()); assertEquals(flow.count(), 0); } @Test public void toString_mapper() { Flow<Integer> flow = F.flow(1, 2, 3); assertFlowValues(flow.map(F.<Integer> stringValueOf()), "1", "2", "3"); } @Test public void no_excess_mapping() { final AtomicInteger count = new AtomicInteger(); Mapper<Integer, Integer> doubler = new Mapper<Integer, Integer>() { @Override public Integer map(Integer value) { count.incrementAndGet(); return value * 2; } }; assertFlowValues(F.range(1, 100).filter(F.gt(10)).map(doubler).take(3), 22, 24, 26); assertEquals(count.get(), 3); count.set(0); // Because of laziness, its possible to count all the values in some mapped lists, without // ever actually running the mapper to determine the final value. assertEquals(F.range(1, 100).map(doubler).count(), 99); assertEquals(count.get(), 0); // Because values are now lazily evaluated as well as flows, we can count the size of a flow // without ever actually calculating (via the mapper) an output value. Flow<Integer> flow = F.range(1, 100).map(doubler).concat(F.range(1, 10).map(doubler)); assertEquals(flow.count(), 108); assertEquals(count.get(), 0); assertFlowValues(flow.take(2), 2, 4); assertEquals(count.get(), 2); count.set(0); // Isn't this nifty; take-ing from a flow will create a flow that references parts // of the original flow, and previously computed values (2 and 4) are still accessible! assertFlowValues(flow.take(3), 2, 4, 6); assertEquals(count.get(), 1); } @Test public void map2_empty_is_the_empty_flow() { Flow<Integer> flow = F.flow(1, 2, 3); assertSame(flow.map(F.ADD_INTS, filteredEmpty), F.EMPTY_FLOW); assertSame(filteredEmpty.map(F.ADD_INTS, flow), F.EMPTY_FLOW); } @Test public void map2() { Flow<Integer> left = F.range(10, 13); Flow<Integer> right = F.series(20, 2); assertFlowValues(left.map(F.ADD_INTS, right), 10 + 20, 11 + 22, 12 + 24); } }