/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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.onlab.util;

import com.google.common.collect.Lists;
import org.junit.Test;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.junit.Assert.*;
import static org.onlab.util.BoundedThreadPool.*;
import static org.onlab.util.Tools.namedThreads;

/**
 * Test of BoundedThreadPool.
 */
public final class BoundedThreadPoolTest {

    @Test
    public void simpleJob() {
        final Thread myThread = Thread.currentThread();
        final AtomicBoolean sameThread = new AtomicBoolean(true);
        final CountDownLatch latch = new CountDownLatch(1);

        BoundedThreadPool exec = newSingleThreadExecutor(namedThreads("test"));
        exec.submit(() -> {
            sameThread.set(myThread.equals(Thread.currentThread()));
            latch.countDown();
        });

        try {
            assertTrue("Job not run", latch.await(100, TimeUnit.MILLISECONDS));
            assertFalse("Runnable used caller thread", sameThread.get());
        } catch (InterruptedException e) {
            fail();
        } finally {
            exec.shutdown();
        }

        // TODO perhaps move to tearDown
        try {
            assertTrue(exec.awaitTermination(1, TimeUnit.SECONDS));
        } catch (InterruptedException e) {
            fail();
        }
    }

    private List<CountDownLatch> fillExecutor(BoundedThreadPool exec) {
        int numThreads = exec.getMaximumPoolSize();
        List<CountDownLatch> latches = Lists.newArrayList();
        final CountDownLatch started = new CountDownLatch(numThreads);
        List<CountDownLatch> finished = Lists.newArrayList();

        // seed the executor's threads
        for (int i = 0; i < numThreads; i++) {
            final CountDownLatch latch = new CountDownLatch(1);
            final CountDownLatch fin = new CountDownLatch(1);
            latches.add(latch);
            finished.add(fin);
            exec.submit(() -> {
                try {
                    started.countDown();
                    latch.await();
                    fin.countDown();
                } catch (InterruptedException e) {
                    fail();
                }
            });
        }
        try {
            assertTrue(started.await(100, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }
        // fill the queue
        CountDownLatch startedBlocked = new CountDownLatch(1);
        while (exec.getQueue().remainingCapacity() > 0) {
            final CountDownLatch latch = new CountDownLatch(1);
            latches.add(latch);
            exec.submit(() -> {
                try {
                    startedBlocked.countDown();
                    latch.await();
                } catch (InterruptedException e) {
                    fail();
                }
            });
        }

        latches.remove(0).countDown(); // release one of the executors
        // ... we need to do this because load is recomputed when jobs are taken
        // Note: For this to work, 1 / numThreads must be less than the load threshold (0.2)

        // verify that the old job has terminated
        try {
            assertTrue("Job didn't finish",
                       finished.remove(0).await(100, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }

        // verify that a previously blocked thread has started
        try {
            assertTrue(startedBlocked.await(10, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }


        // add another job to fill the queue
        final CountDownLatch latch = new CountDownLatch(1);
        latches.add(latch);
        exec.submit(() -> {
            try {
                latch.await();
            } catch (InterruptedException e) {
                fail();
            }
        });
        assertEquals(exec.getQueue().size(), maxQueueSize);

        return latches;
    }

    @Test
    public void releaseOneThread() {
        maxQueueSize = 10;
        BoundedThreadPool exec = newFixedThreadPool(4, namedThreads("test"));
        List<CountDownLatch> latches = fillExecutor(exec);

        CountDownLatch myLatch = new CountDownLatch(1);
        ExecutorService myExec = Executors.newSingleThreadExecutor();
        Future<Thread> expected = myExec.submit(Thread::currentThread);

        assertEquals(exec.getQueue().size(), maxQueueSize);
        long start = System.nanoTime();
        Future<Thread> actual = myExec.submit(() -> {
            return exec.submit(() -> {
                myLatch.countDown();
                return Thread.currentThread();
            }).get();
        });

        try {
            assertFalse("Thread should still be blocked",
                        myLatch.await(10, TimeUnit.MILLISECONDS));

            latches.remove(0).countDown(); // release the first thread
            assertFalse("Thread should still be blocked",
                        myLatch.await(10, TimeUnit.MILLISECONDS));
            latches.remove(0).countDown(); // release the second thread

            assertTrue("Thread should be unblocked",
                       myLatch.await(10, TimeUnit.MILLISECONDS));
            long delta = System.nanoTime() - start;
            double load = exec.getQueue().size() / (double) maxQueueSize;
            assertTrue("Load is greater than threshold", load <= 0.8);
            assertTrue("Load is less than threshold", load >= 0.6);
            assertEquals("Work done on wrong thread", expected.get(), actual.get());
            assertTrue("Took more than one second", delta < Math.pow(10, 9));
        } catch (InterruptedException | ExecutionException e) {
            fail();
        } finally {
            latches.forEach(CountDownLatch::countDown);
            exec.shutdown();
        }

        // TODO perhaps move to tearDown
        try {
            assertTrue(exec.awaitTermination(1, TimeUnit.SECONDS));
        } catch (InterruptedException e) {
            fail();
        }

    }

    @Test
    public void highLoadTimeout() {
        maxQueueSize = 10;
        BoundedThreadPool exec = newFixedThreadPool(2, namedThreads("test"));
        List<CountDownLatch> latches = fillExecutor(exec);

        // true if the job is executed and it is done on the test thread
        final AtomicBoolean sameThread = new AtomicBoolean(false);
        final Thread myThread = Thread.currentThread();
        long start = System.nanoTime();
        exec.submit(() -> {
            sameThread.set(myThread.equals(Thread.currentThread()));
        });

        long delta = System.nanoTime() - start;
        assertEquals(maxQueueSize, exec.getQueue().size());
        assertTrue("Work done on wrong thread (or didn't happen)", sameThread.get());
        assertTrue("Took less than one second. Actual: " + delta / 1_000_000.0 + "ms",
                   delta > Math.pow(10, 9));
        assertTrue("Took more than two seconds", delta < 2 * Math.pow(10, 9));
        latches.forEach(CountDownLatch::countDown);
        exec.shutdown();

        // TODO perhaps move to tearDown
        try {
            assertTrue(exec.awaitTermination(1, TimeUnit.SECONDS));
        } catch (InterruptedException e) {
            fail();
        }
    }
}