/*
 * Copyright 2015-present 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  {

    private static final int FAIL_TIMEOUT = 1000; //ms

    @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(FAIL_TIMEOUT, 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(FAIL_TIMEOUT, 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(FAIL_TIMEOUT, TimeUnit.MILLISECONDS));
            assertEquals(waitLatch.getCount(), numThreads / 2);
        } catch (InterruptedException e) {
            fail();
        }
        b.set(true);
        try {
            assertTrue(waitLatch.await(FAIL_TIMEOUT, 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(FAIL_TIMEOUT, 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)));
    }

}
