/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.jexl3;

import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.commons.jexl3.internal.Script;
import org.junit.Assert;
import org.junit.Test;

/**
 * Tests around asynchronous script execution and interrupts.
 */
@SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
public class ScriptCallableTest extends JexlTestCase {
    //Logger LOGGER = Logger.getLogger(VarTest.class.getName());
    public ScriptCallableTest() {
        super("ScriptCallableTest");
    }

    @Test
    public void testFuture() throws Exception {
        JexlScript e = JEXL.createScript("while(true);");
        FutureTask<Object> future = new FutureTask<Object>(e.callable(null));

        ExecutorService executor = Executors.newFixedThreadPool(1);
        executor.submit(future);
        Object t = 42;
        try {
            t = future.get(100, TimeUnit.MILLISECONDS);
            Assert.fail("should have timed out");
        } catch (TimeoutException xtimeout) {
            // ok, ignore
            future.cancel(true);
        } finally {
            executor.shutdown();
        }

        Assert.assertTrue(future.isCancelled());
        Assert.assertEquals(42, t);
    }

    @Test
    public void testCallableCancel() throws Exception {
        final Semaphore latch = new Semaphore(0);
        JexlContext ctxt = new MapContext();
        ctxt.set("latch", latch);

        JexlScript e = JEXL.createScript("latch.release(); while(true);");
        final Script.Callable c = (Script.Callable) e.callable(ctxt);
        Object t = 42;
        Callable<Object> kc = new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                latch.acquire();
                return c.cancel();
            }
        };
        ExecutorService executor = Executors.newFixedThreadPool(2);
        Future<?> future = executor.submit(c);
        Future<?> kfc = executor.submit(kc);
        try {
            Assert.assertTrue((Boolean) kfc.get());
            t = future.get();
            Assert.fail("should have been cancelled");
        } catch (ExecutionException xexec) {
            // ok, ignore
            Assert.assertTrue(xexec.getCause() instanceof JexlException.Cancel);
        } finally {
            executor.shutdown();
        }
        Assert.assertTrue(c.isCancelled());
    }

    @Test
    public void testCallableTimeout() throws Exception {
        final Semaphore latch = new Semaphore(0);
        JexlContext ctxt = new MapContext();
        ctxt.set("latch", latch);

        JexlScript e = JEXL.createScript("latch.release(); while(true);");
        Callable<Object> c = e.callable(ctxt);
        Object t = 42;

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<?> future = executor.submit(c);
        try {
            latch.acquire();
            t = future.get(100, TimeUnit.MILLISECONDS);
            Assert.fail("should have timed out");
        } catch (TimeoutException xtimeout) {
            // ok, ignore
            future.cancel(true);
        } finally {
            executor.shutdown();
        }
        Assert.assertTrue(future.isCancelled());
        Assert.assertEquals(42, t);
    }

    @Test
    public void testCallableClosure() throws Exception {
        JexlScript e = JEXL.createScript("function(t) {while(t);}");
        Callable<Object> c = e.callable(null, Boolean.TRUE);
        Object t = 42;

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<?> future = executor.submit(c);
        try {
            t = future.get(100, TimeUnit.MILLISECONDS);
            Assert.fail("should have timed out");
        } catch (TimeoutException xtimeout) {
            // ok, ignore
            future.cancel(true);
        } finally {
            executor.shutdown();
        }
        Assert.assertTrue(future.isCancelled());
        Assert.assertEquals(42, t);
    }

    public static class TestContext extends MapContext implements JexlContext.NamespaceResolver {
        @Override
        public Object resolveNamespace(String name) {
            return name == null ? this : null;
        }

        public int wait(int s) throws InterruptedException {
            Thread.sleep(1000 * s);
            return s;
        }

        public int waitInterrupt(int s) {
            try {
                Thread.sleep(1000 * s);
                return s;
            } catch (InterruptedException xint) {
                Thread.currentThread().interrupt();
            }
            return -1;
        }

        public int runForever() {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }
            }
            return 1;
        }

        public int interrupt() throws InterruptedException {
            Thread.currentThread().interrupt();
            return 42;
        }

        public void sleep(long millis) throws InterruptedException {
            try {
                Thread.sleep(millis);
            } catch (InterruptedException xint) {
                throw xint;
            }
        }

        public int hangs(Object t) {
            return 1;
        }
    }

    @Test
    public void testNoWait() throws Exception {
        JexlScript e = JEXL.createScript("wait(0)");
        Callable<Object> c = e.callable(new TestContext());

        ExecutorService executor = Executors.newFixedThreadPool(1);
        try {
            Future<?> future = executor.submit(c);
            Object t = future.get(2, TimeUnit.SECONDS);
            Assert.assertTrue(future.isDone());
            Assert.assertEquals(0, t);
        } finally {
            executor.shutdown();
        }
    }

    @Test
    public void testWait() throws Exception {
        JexlScript e = JEXL.createScript("wait(1)");
        Callable<Object> c = e.callable(new TestContext());

        ExecutorService executor = Executors.newFixedThreadPool(1);
        try {
            Future<?> future = executor.submit(c);
            Object t = future.get(2, TimeUnit.SECONDS);
            Assert.assertEquals(1, t);
        } finally {
            executor.shutdown();
        }
    }

    @Test
    public void testCancelWait() throws Exception {
        JexlScript e = JEXL.createScript("wait(10)");
        Callable<Object> c = e.callable(new TestContext());

        ExecutorService executor = Executors.newFixedThreadPool(1);
        try {
            Future<?> future = executor.submit(c);
            Object t = 42;
            try {
                t = future.get(100, TimeUnit.MILLISECONDS);
                Assert.fail("should have timed out");
            } catch (TimeoutException xtimeout) {
                // ok, ignore
                future.cancel(true);
            }
            Assert.assertTrue(future.isCancelled());
            Assert.assertEquals(42, t);
        } finally {
            executor.shutdown();
        }
    }

    @Test
    public void testCancelWaitInterrupt() throws Exception {
        JexlScript e = JEXL.createScript("waitInterrupt(42)");
        Callable<Object> c = e.callable(new TestContext());

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<?> future = executor.submit(c);
        Object t = 42;

        try {
            t = future.get(100, TimeUnit.MILLISECONDS);
            Assert.fail("should have timed out");
        } catch (TimeoutException xtimeout) {
            // ok, ignore
            future.cancel(true);
        } finally {
            executor.shutdown();
        }
        Assert.assertTrue(future.isCancelled());
        Assert.assertEquals(42, t);
    }

    @Test
    public void testCancelForever() throws Exception {
        final Semaphore latch = new Semaphore(0);
        JexlContext ctxt = new TestContext();
        ctxt.set("latch", latch);

        JexlScript e = JEXL.createScript("latch.release(); runForever()");
        Callable<Object> c = e.callable(ctxt);

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<?> future = executor.submit(c);
        Object t = 42;

        try {
            latch.acquire();
            t = future.get(100, TimeUnit.MILLISECONDS);
            Assert.fail("should have timed out");
        } catch (TimeoutException xtimeout) {
            // ok, ignore
            future.cancel(true);
        } finally {
            executor.shutdown();
        }
        Assert.assertTrue(future.isCancelled());
        Assert.assertEquals(42, t);
    }

    @Test
    public void testCancelLoopWait() throws Exception {
        JexlScript e = JEXL.createScript("while (true) { wait(10) }");
        Callable<Object> c = e.callable(new TestContext());

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<?> future = executor.submit(c);
        Object t = 42;

        try {
            t = future.get(100, TimeUnit.MILLISECONDS);
            Assert.fail("should have timed out");
        } catch (TimeoutException xtimeout) {
            future.cancel(true);
        } finally {
            executor.shutdown();
        }
        Assert.assertTrue(future.isCancelled());
        Assert.assertEquals(42, t);
    }

    @Test
    public void testInterruptVerboseStrict() throws Exception {
        runInterrupt(new JexlBuilder().silent(false).strict(true).create());
    }

    @Test
    public void testInterruptVerboseLenient() throws Exception {
        runInterrupt(new JexlBuilder().silent(false).strict(false).create());
    }

    @Test
    public void testInterruptSilentStrict() throws Exception {
        runInterrupt(new JexlBuilder().silent(true).strict(true).create());
    }

    @Test
    public void testInterruptSilentLenient() throws Exception {
        runInterrupt(new JexlBuilder().silent(true).strict(false).create());
    }

    @Test
    public void testInterruptCancellable() throws Exception {
        runInterrupt(new JexlBuilder().silent(true).strict(true).cancellable(true).create());
    }

    /**
     * Redundant test with previous ones but impervious to JEXL engine configuation.
     * @param silent silent engine flag
     * @param strict strict (aka not lenient) engine flag
     * @throws Exception if there is a regression
     */
    private void runInterrupt(JexlEngine jexl) throws Exception {
        ExecutorService exec = Executors.newFixedThreadPool(2);
        try {
            JexlContext ctxt = new TestContext();

            // run an interrupt
            JexlScript sint = jexl.createScript("interrupt(); return 42");
            Object t = null;
            Script.Callable c = (Script.Callable) sint.callable(ctxt);
            try {
                t = c.call();
                if (c.isCancellable()) {
                    Assert.fail("should have thrown a Cancel");
                }
            } catch (JexlException.Cancel xjexl) {
                if (!c.isCancellable()) {
                    Assert.fail("should not have thrown " + xjexl);
                }
            }
            Assert.assertTrue(c.isCancelled());
            Assert.assertNotEquals(42, t);

            // self interrupt
            Future<Object> f = null;
            c = (Script.Callable) sint.callable(ctxt);
            try {
                f = exec.submit(c);
                t = f.get();
                if (c.isCancellable()) {
                    Assert.fail("should have thrown a Cancel");
                }
            } catch (ExecutionException xexec) {
                if (!c.isCancellable()) {
                    Assert.fail("should not have thrown " + xexec);
                }
            }
            Assert.assertTrue(c.isCancelled());
            Assert.assertNotEquals(42, t);

            // timeout a sleep
            JexlScript ssleep = jexl.createScript("sleep(30000); return 42");
            try {
                f = exec.submit(ssleep.callable(ctxt));
                t = f.get(100L, TimeUnit.MILLISECONDS);
                Assert.fail("should timeout");
            } catch (TimeoutException xtimeout) {
                if (f != null) {
                    f.cancel(true);
                }
            }
            Assert.assertNotEquals(42, t);

            // cancel a sleep
            try {
                final Future<Object> fc = exec.submit(ssleep.callable(ctxt));
                Runnable cancels = new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(200L);
                        } catch (Exception xignore) {

                        }
                        fc.cancel(true);
                    }
                };
                exec.submit(cancels);
                t = fc.get();
                Assert.fail("should be cancelled");
            } catch (CancellationException xexec) {
                // this is the expected result
            }

            // timeout a while(true)
            JexlScript swhile = jexl.createScript("while(true); return 42");
            try {
                f = exec.submit(swhile.callable(ctxt));
                t = f.get(100L, TimeUnit.MILLISECONDS);
                Assert.fail("should timeout");
            } catch (TimeoutException xtimeout) {
                if (f != null) {
                    f.cancel(true);
                }
            }
            Assert.assertNotEquals(42, t);

            // cancel a while(true)
            try {
                final Future<Object> fc = exec.submit(swhile.callable(ctxt));
                Runnable cancels = new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(200L);
                        } catch (Exception xignore) {

                        }
                        fc.cancel(true);
                    }
                };
                exec.submit(cancels);
                t = fc.get();
                Assert.fail("should be cancelled");
            } catch (CancellationException xexec) {
                // this is the expected result
            }
            Assert.assertNotEquals(42, t);
        } finally {
            exec.shutdown();
        }
    }

    @Test
    public void testHangs() throws Exception {
        JexlScript e = JEXL.createScript("hangs()");
        Callable<Object> c = e.callable(new TestContext());

        ExecutorService executor = Executors.newFixedThreadPool(1);
        try {
            Future<?> future = executor.submit(c);
            Object t = future.get(1, TimeUnit.SECONDS);
            Assert.fail("hangs should not be solved");
        } catch(ExecutionException xexec) {
            Assert.assertTrue(xexec.getCause() instanceof JexlException.Method);
        } finally {
            executor.shutdown();
        }
    }
}
