package org.junit.runner.notification;

import org.junit.Test;
import org.junit.runner.Description;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertTrue;

/**
 * Testing RunNotifier in concurrent access.
 *
 * @author Tibor Digana (tibor17)
 * @version 4.12
 * @since 4.12
 */
public final class ConcurrentRunNotifierTest {
    private static final long TIMEOUT = 3;
    private final RunNotifier fNotifier = new RunNotifier();

    private static class ConcurrentRunListener extends RunListener {
        final AtomicInteger fTestStarted = new AtomicInteger(0);

        @Override
        public void testStarted(Description description) throws Exception {
            fTestStarted.incrementAndGet();
        }
    }

    @Test
    public void realUsage() throws Exception {
        ConcurrentRunListener listener1 = new ConcurrentRunListener();
        ConcurrentRunListener listener2 = new ConcurrentRunListener();
        fNotifier.addListener(listener1);
        fNotifier.addListener(listener2);

        final int numParallelTests = 4;
        ExecutorService pool = Executors.newFixedThreadPool(numParallelTests);
        for (int i = 0; i < numParallelTests; ++i) {
            pool.submit(new Runnable() {
                public void run() {
                    fNotifier.fireTestStarted(null);
                }
            });
        }
        pool.shutdown();
        assertTrue(pool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));

        fNotifier.removeListener(listener1);
        fNotifier.removeListener(listener2);

        assertThat(listener1.fTestStarted.get(), is(numParallelTests));
        assertThat(listener2.fTestStarted.get(), is(numParallelTests));
    }

    private static class ExaminedListener extends RunListener {
        final boolean throwFromTestStarted;
        volatile boolean hasTestFailure = false;

        ExaminedListener(boolean throwFromTestStarted) {
            this.throwFromTestStarted = throwFromTestStarted;
        }

        @Override
        public void testStarted(Description description) throws Exception {
            if (throwFromTestStarted) {
                throw new Exception();
            }
        }

        @Override
        public void testFailure(Failure failure) throws Exception {
            hasTestFailure = true;
        }
    }

    private abstract class AbstractConcurrentFailuresTest {

        protected abstract void addListener(ExaminedListener listener);

        public void test() throws Exception {
            int totalListenersFailures = 0;

            Random random = new Random(42);
            ExaminedListener[] examinedListeners = new ExaminedListener[1000];
            for (int i = 0; i < examinedListeners.length; ++i) {
                boolean fail = random.nextDouble() >= 0.5d;
                if (fail) {
                    ++totalListenersFailures;
                }
                examinedListeners[i] = new ExaminedListener(fail);
            }

            final AtomicBoolean condition = new AtomicBoolean(true);
            final CyclicBarrier trigger = new CyclicBarrier(2);
            final CountDownLatch latch = new CountDownLatch(10);

            ExecutorService notificationsPool = Executors.newFixedThreadPool(4);
            notificationsPool.submit(new Callable<Void>() {
                public Void call() throws Exception {
                    trigger.await();
                    while (condition.get()) {
                        fNotifier.fireTestStarted(null);
                        latch.countDown();
                    }
                    fNotifier.fireTestStarted(null);
                    return null;
                }
            });

            // Wait for callable to start
            trigger.await(TIMEOUT, TimeUnit.SECONDS);

            // Wait for callable to fire a few events
            latch.await(TIMEOUT, TimeUnit.SECONDS);

            for (ExaminedListener examinedListener : examinedListeners) {
              addListener(examinedListener);
            }

            notificationsPool.shutdown();
            condition.set(false);
            assertTrue(notificationsPool.awaitTermination(TIMEOUT, TimeUnit.SECONDS));

            if (totalListenersFailures != 0) {
                // If no listener failures, then all the listeners do not report any failure.
                int countTestFailures = examinedListeners.length - countReportedTestFailures(examinedListeners);
                assertThat(totalListenersFailures, is(countTestFailures));
            }
        }
    }

    /**
     * Verifies that listeners added while tests are run concurrently are
     * notified about test failures.
     */
    @Test
    public void reportConcurrentFailuresAfterAddListener() throws Exception {
        new AbstractConcurrentFailuresTest() {
            @Override
            protected void addListener(ExaminedListener listener) {
                fNotifier.addListener(listener);
            }
        }.test();
    }

    /**
     * Verifies that listeners added with addFirstListener() while tests are run concurrently are
     * notified about test failures.
     */
    @Test
    public void reportConcurrentFailuresAfterAddFirstListener() throws Exception {
        new AbstractConcurrentFailuresTest() {
            @Override
            protected void addListener(ExaminedListener listener) {
                fNotifier.addFirstListener(listener);
            }
        }.test();
    }

    private static int countReportedTestFailures(ExaminedListener[] listeners) {
        int count = 0;
        for (ExaminedListener listener : listeners) {
            if (listener.hasTestFailure) {
                ++count;
            }
        }
        return count;
    }
}
