package cc.redberry.pipe.util;

import cc.redberry.pipe.InputPort;
import cc.redberry.pipe.OutputPort;
import cc.redberry.pipe.blocks.Buffer;
import org.apache.commons.math.random.RandomDataImpl;
import org.apache.commons.math.random.Well19937c;
import org.junit.Assert;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicInteger;

public class OrderedOutputPortTest {
    @Test
    public void test1() throws Exception {
        RandomDataImpl rdi = new RandomDataImpl(new Well19937c());
        final int[] randomPermutation = rdi.nextPermutation(500, 500);

        int threadCount = 30;

        final AtomicInteger index = new AtomicInteger(randomPermutation.length - 1);
        Thread[] threads = new Thread[threadCount];

        final Buffer<Integer> buffer = new Buffer<>();

        for (int i = 0; i < threadCount; ++i) {
            final InputPort<Integer> ip = buffer.createInputPort();
            threads[i] = new Thread() {
                @Override
                public void run() {
                    int i;
                    while ((i = index.getAndDecrement()) >= 0) {
                        ip.put(randomPermutation[i]);
                    }
                    ip.put(null);
                }
            };
        }

        for (int i = 0; i < threadCount; ++i) {
            threads[i].start();
        }

        OutputPort<Integer> ordered = new OrderedOutputPort<>(buffer, new Indexer<Integer>() {
            @Override
            public long getIndex(Integer object) {
                return object;
            }
        });

        Integer i;
        int assertI = 0;

        while ((i = ordered.take()) != null) {
            Assert.assertEquals(assertI++, i.intValue());
        }
    }
}
