package es.usc.citius.common.parallel;

import org.junit.Test;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;

import static org.junit.Assert.assertEquals;


public class ParallelTest {
    @Test
    public void testForEach() throws Exception {
        Set<String> text = new HashSet<String>(Arrays.asList("0", "00", "000", "0000"));
        Collection<Integer> result = Parallel.ForEach(text, new Parallel.F<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        });

        int total = 0;
        for(Integer i : result) {total += i;}
        assertEquals(10, total);
    }

    @Test
    public void testFor() throws Exception {
        final AtomicInteger counter = new AtomicInteger(0);
        Parallel.For(0, 1000, new Parallel.Action<Long>() {
            @Override
            public void doAction(Long element) {
                counter.incrementAndGet();
            }
        });
        assertEquals(1000, counter.intValue());
    }

    private Iterable<Integer> iterable(final Integer size){
        return new Iterable<Integer>() {
             @Override
             public Iterator<Integer> iterator() {
                 return new Iterator<Integer>() {
                     int counter=0;
                     @Override
                     public boolean hasNext() {
                         return counter < size;
                     }

                     @Override
                     public Integer next() {
                         return counter++;
                     }

                     @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
                 };
             }
        };
    }

    @Test
    public void testOneThread() throws ExecutionException, InterruptedException {
        final ConcurrentHashMap<Long, String> map = new ConcurrentHashMap<Long, String>();
        new Parallel.ForEach(iterable(10000))
                .withFixedThreads(1)
                .apply(new Parallel.Action<Integer>() {
                    public void doAction(Integer element) {
                        map.put(Thread.currentThread().getId(), "");
                    }
                }).values();

        assertEquals(1, map.keySet().size());
    }

    @Test
    public void testFourThread() throws ExecutionException, InterruptedException {
        final ConcurrentHashMap<Long, String> map = new ConcurrentHashMap<Long, String>();
        new Parallel.ForEach(iterable(10000))
                .withFixedThreads(4)
                .apply(new Parallel.Action<Integer>() {
                    public void doAction(Integer element) {
                        map.put(Thread.currentThread().getId(), "");
                    }
                }).values();

        assertEquals(4, map.keySet().size());
    }
}

@@ -77,16 +77,54 @@
 util.*;%0A
+import java.util.concurrent.Callable;%0A
 import j
@@ -3073,11 +3073,503 @@
 );%0A    %7D
+%0A%0A    @Test%0A    public void testPrepareTasks() throws Exception %7B%0A        Callable%3CParallel.TaskHandler%3CInteger%3E%3E tasks = new Parallel.ForEach%3CInteger, Integer%3E(iterable(10))%0A                .prepare(new Parallel.F%3CInteger, Integer%3E() %7B%0A                    @Override%0A                    public Integer apply(Integer integer) %7B%0A                        return integer;%0A                    %7D%0A                %7D);%0A        assertEquals(10, new HashSet%3CInteger%3E(tasks.call().values()).size());%0A    %7D
 %0A%7D%0A

Test added to cover prepare() function