/* * Quasar: lightweight threads and actors for the JVM. * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.strands.channels.transfer; import co.paralleluniverse.common.test.Matchers; import co.paralleluniverse.common.test.TestUtil; import co.paralleluniverse.common.util.ConcurrentSet; import co.paralleluniverse.common.util.Debug; import co.paralleluniverse.fibers.Fiber; import co.paralleluniverse.fibers.FiberForkJoinScheduler; import co.paralleluniverse.fibers.FiberScheduler; import co.paralleluniverse.fibers.SuspendExecution; import co.paralleluniverse.strands.SuspendableAction2; import co.paralleluniverse.strands.SuspendableRunnable; import co.paralleluniverse.strands.channels.Channel; import co.paralleluniverse.strands.channels.Channels; import co.paralleluniverse.strands.channels.Channels.OverflowPolicy; import com.google.common.collect.ImmutableSet; import java.util.Arrays; import java.util.Collection; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; /** * * @author circlespainter */ @RunWith(Parameterized.class) public class PipelineTest { @Rule public TestName name = new TestName(); @Rule public TestRule watchman = TestUtil.WATCHMAN; private final int mailboxSize; private final OverflowPolicy policy; private final boolean singleConsumer; private final boolean singleProducer; private final FiberScheduler scheduler; private final int parallelism; public PipelineTest(final int mailboxSize, final OverflowPolicy policy, final boolean singleConsumer, final boolean singleProducer, final int parallelism) { scheduler = new FiberForkJoinScheduler("test", 4, null, false); this.mailboxSize = mailboxSize; this.policy = policy; this.singleConsumer = singleConsumer; this.singleProducer = singleProducer; this.parallelism = parallelism; } @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ {5, OverflowPolicy.THROW, true, false, 0}, {5, OverflowPolicy.THROW, false, false, 0}, {5, OverflowPolicy.BLOCK, true, false, 0}, {5, OverflowPolicy.BLOCK, false, false, 0}, {1, OverflowPolicy.BLOCK, false, false, 0}, {-1, OverflowPolicy.THROW, true, false, 0}, {5, OverflowPolicy.DISPLACE, true, false, 0}, {0, OverflowPolicy.BLOCK, false, false, 0}, {5, OverflowPolicy.THROW, true, false, 2}, {5, OverflowPolicy.THROW, false, false, 2}, {5, OverflowPolicy.BLOCK, true, false, 2}, {5, OverflowPolicy.BLOCK, false, false, 2}, {1, OverflowPolicy.BLOCK, false, false, 2}, {-1, OverflowPolicy.THROW, true, false, 2}, {5, OverflowPolicy.DISPLACE, true, false, 2}, {0, OverflowPolicy.BLOCK, false, false, 2}, }); } private <Message> Channel<Message> newChannel() { return Channels.newChannel(mailboxSize, policy, singleProducer, singleConsumer); } @Test public void testPipeline() throws Exception { final Channel<Integer> i = newChannel(); final Channel<Integer> o = newChannel(); final Pipeline<Integer, Integer> p = new Pipeline<>( i, o, new SuspendableAction2<Integer, Channel<Integer>>() { @Override public void call(final Integer i, final Channel<Integer> out) throws SuspendExecution, InterruptedException { out.send(i + 1); out.close(); } }, parallelism); final Fiber<Long> pf = new Fiber("pipeline", scheduler, p).start(); final Fiber receiver = new Fiber("receiver", scheduler, new SuspendableRunnable() { @Override public void run() throws SuspendExecution, InterruptedException { final Integer m1 = o.receive(); final Integer m2 = o.receive(); final Integer m3 = o.receive(); final Integer m4 = o.receive(); assertThat(m1, notNullValue()); assertThat(m2, notNullValue()); assertThat(m3, notNullValue()); assertThat(m4, notNullValue()); assertThat(ImmutableSet.of(m1, m2, m3, m4), equalTo(ImmutableSet.of(2, 3, 4, 5))); try { pf.join(); } catch (ExecutionException ex) { // It should never happen throw new AssertionError(ex); } assertNull(o.tryReceive()); // This is needed, else `isClosed` could return false assertTrue(o.isClosed()); // Can be used reliably only in owner (receiver) } }).start(); i.send(1); i.send(2); i.send(3); i.send(4); i.close(); long transferred = pf.get(); // Join pipeline assertThat(transferred, equalTo(p.getTransferred())); assertThat(transferred, equalTo(4l)); receiver.join(); } }