/*
 * 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 org.apache.commons.lang.mutable.MutableBoolean;
import org.junit.Ignore;
import org.junit.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

/**
 * Tests of the BlockingBoolean utility.
 */
public class BlockingBooleanTest  {

    @Test
    public void basics() {
        BlockingBoolean b = new BlockingBoolean(false);
        assertEquals(false, b.get());
        b.set(true);
        assertEquals(true, b.get());
        b.set(true);
        assertEquals(true, b.get());
        b.set(false);
        assertEquals(false, b.get());
    }

    private void waitChange(boolean value, int numThreads) {
        BlockingBoolean b = new BlockingBoolean(!value);

        CountDownLatch latch = new CountDownLatch(numThreads);
        ExecutorService exec = Executors.newFixedThreadPool(numThreads);
        for (int i = 0; i < numThreads; i++) {
            exec.submit(() -> {
                try {
                    b.await(value);
                    latch.countDown();
                } catch (InterruptedException e) {
                    fail();
                }
            });
        }
        b.set(value);
        try {
            assertTrue(latch.await(10, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }
        exec.shutdown();
    }

    @Test
    public void waitTrueChange() {
        waitChange(true, 4);
    }

    @Test
    public void waitFalseChange() {
        waitChange(false, 4);
    }

    @Test
    public void waitSame() {
        BlockingBoolean b = new BlockingBoolean(true);

        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService exec = Executors.newSingleThreadExecutor();
        exec.submit(() -> {
            try {
                b.await(true);
                latch.countDown();
            } catch (InterruptedException e) {
                fail();
            }
        });
        try {
            assertTrue(latch.await(10, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }
        exec.shutdown();
    }

    @Test
    public void someWait() {
        BlockingBoolean b = new BlockingBoolean(false);

        int numThreads = 4;
        CountDownLatch sameLatch = new CountDownLatch(numThreads / 2);
        CountDownLatch waitLatch = new CountDownLatch(numThreads / 2);

        ExecutorService exec = Executors.newFixedThreadPool(numThreads);
        for (int i = 0; i < numThreads; i++) {
            final boolean value = (i % 2 == 1);
            exec.submit(() -> {
                try {
                    b.await(value);
                    if (value) {
                        waitLatch.countDown();
                    } else {
                        sameLatch.countDown();
                    }
                } catch (InterruptedException e) {
                    fail();
                }
            });
        }
        try {
            assertTrue(sameLatch.await(10, TimeUnit.MILLISECONDS));
            assertEquals(waitLatch.getCount(), numThreads / 2);
        } catch (InterruptedException e) {
            fail();
        }
        b.set(true);
        try {
            assertTrue(waitLatch.await(10, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }
        exec.shutdown();
    }

    @Test
    public void waitTimeout() {
        BlockingBoolean b = new BlockingBoolean(true);

        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService exec = Executors.newSingleThreadExecutor();
        exec.submit(() -> {
            try {
                if (!b.await(false, 1, TimeUnit.NANOSECONDS)) {
                    latch.countDown();
                } else {
                    fail();
                }
            } catch (InterruptedException e) {
                fail();
            }
        });
        try {
            assertTrue(latch.await(10, TimeUnit.MILLISECONDS));
        } catch (InterruptedException e) {
            fail();
        }
        exec.shutdown();

    }

    @Test
    @Ignore
    public void samePerf() {
        int iters = 10_000;

        BlockingBoolean b1 = new BlockingBoolean(false);
        long t1 = System.nanoTime();
        for (int i = 0; i < iters; i++) {
            b1.set(false);
        }
        long t2 = System.nanoTime();
        MutableBoolean b2 = new MutableBoolean(false);
        for (int i = 0; i < iters; i++) {
            b2.setValue(false);
        }
        long t3 = System.nanoTime();
        System.out.println((t2 - t1) + " " + (t3 - t2) + " " + ((t2 - t1) <= (t3 - t2)));
    }

    @Test
    @Ignore
    public void changePerf() {
        int iters = 10_000;

        BlockingBoolean b1 = new BlockingBoolean(false);
        boolean v = true;
        long t1 = System.nanoTime();
        for (int i = 0; i < iters; i++) {
            b1.set(v);
            v = !v;
        }
        long t2 = System.nanoTime();
        MutableBoolean b2 = new MutableBoolean(false);
        for (int i = 0; i < iters; i++) {
            b2.setValue(v);
            v = !v;
        }
        long t3 = System.nanoTime();
        System.out.println((t2 - t1) + " " + (t3 - t2) + " " + ((t2 - t1) <= (t3 - t2)));
    }

}
