// Path: src/test/java/com/github/vbauer/caesar/basic/BasicTest.java
// @RunWith(BlockJUnit4ClassRunner.class)
// public abstract class BasicTest {
// 
//     protected final boolean checkUtilConstructorContract(final Class<?>... utilClasses) {
//         Assert.assertTrue(utilClasses.length > 0);
// 
//         PrivateConstructorChecker
//             .forClasses(utilClasses)
//             .expectedTypeOfException(UnsupportedOperationException.class)
//             .check();
// 
//         return true;
//     }
// 
// }
// 
// Path: src/test/java/com/github/vbauer/caesar/bean/SimpleAsync.java
// @Timeout(5)
// public interface SimpleAsync {
// 
//     Future<Integer> getId();
// 
//     Future<Boolean> timeout();
// 
// }
// 
// Path: src/test/java/com/github/vbauer/caesar/bean/SimpleSync.java
// public class SimpleSync {
// 
//     public static final boolean TIMEOUT_VALUE = true;
//     private final int id;
// 
// 
//     public SimpleSync(final int id) {
//         this.id = id;
//     }
// 
// 
//     public int getId() {
//         return id;
//     }
// 
//     public Boolean timeout() throws InterruptedException {
//         Thread.sleep(1000);
//         return TIMEOUT_VALUE;
//     }
// 
// 
//     @Override
//     public int hashCode() {
//         return id;
//     }
// 
//     @Override
//     public boolean equals(final Object obj) {
//         if (obj instanceof SimpleSync) {
//             final SimpleSync other = (SimpleSync) obj;
//             return other.getId() == getId();
//         }
//         return false;
//     }
// 
//     @Override
//     public String toString() {
//         return String.valueOf(getId());
//     }
// 
// }
// 
// Path: src/main/java/com/github/vbauer/caesar/exception/UnsupportedTimeoutException.java
// @SuppressWarnings("serial")
// public class UnsupportedTimeoutException extends AbstractCaesarException {
// 
//     private final Executor executor;
// 
// 
//     public UnsupportedTimeoutException(final Executor executor) {
//         this.executor = executor;
//     }
// 
// 
//     public Executor getExecutor() {
//         return executor;
//     }
// 
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public String getMessage() {
//         return String.format(
//             "%s does not support timeouts. Use %s.",
//             getExecutor(), ScheduledExecutorService.class
//         );
//     }
// 
// }
// 
// Path: src/main/java/com/github/vbauer/caesar/proxy/AsyncProxyCreator.java
// public final class AsyncProxyCreator {
// 
//     private AsyncProxyCreator() {
//         throw new UnsupportedOperationException();
//     }
// 
// 
//     public static <SYNC, ASYNC> ASYNC create(
//         final SYNC bean, final Class<ASYNC> asyncInterface, final ExecutorService executor
//     ) {
//         return create(bean, asyncInterface, executor, true);
//     }
// 
//     @SuppressWarnings("unchecked")
//     public static <SYNC, ASYNC> ASYNC create(
//         final SYNC bean, final Class<ASYNC> asyncInterface, final ExecutorService executor, final boolean validate
//     ) {
//         final AsyncInvocationHandler handler = AsyncInvocationHandler.create(bean, executor);
//         final Class<?> beanClass = bean.getClass();
//         final ClassLoader classLoader = beanClass.getClassLoader();
//         final Class<?>[] interfaces = {
//             asyncInterface,
//         };
// 
//         final ASYNC proxy = (ASYNC) Proxy.newProxyInstance(classLoader, interfaces, handler);
//         return validate ? validate(proxy, handler) : proxy;
//     }
// 
// 
//     private static <T> T validate(final T proxy, final AsyncInvocationHandler handler) {
//         final Class<?> targetClass = ReflectionUtils.getClassWithoutProxies(proxy);
//         final Method[] methods = targetClass.getDeclaredMethods();
// 
//         for (final Method method : methods) {
//             final AsyncMethodRunner runner = handler.findAsyncMethodRunner(method);
//             if (runner == null) {
//                 throw new MissedSyncMethodException(method);
//             }
//         }
// 
//         return proxy;
//     }
// 
// }


import com.github.vbauer.caesar.basic.BasicTest;
import com.github.vbauer.caesar.bean.SimpleAsync;
import com.github.vbauer.caesar.bean.SimpleSync;
import com.github.vbauer.caesar.exception.UnsupportedTimeoutException;
import com.github.vbauer.caesar.proxy.AsyncProxyCreator;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
package com.github.vbauer.caesar.annotation;



/**
 * @author Vladislav Bauer
 */

public class TimeoutAnnotationTest extends BasicTest {

    @Test
    public void testGoodExecutorService() throws Exception {
        final ExecutorService executor = Executors.newScheduledThreadPool(1);
        try {
            final SimpleAsync proxy = createProxy(executor);
            Assert.assertEquals(SimpleSync.TIMEOUT_VALUE, proxy.timeout().get());
        } finally {
            executor.shutdown();
        }
    }

    @Test(expected = UnsupportedTimeoutException.class)
    public void testBadExecutorService() throws Exception {
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        try {
            final SimpleAsync proxy = createProxy(executor);
            Assert.fail(String.valueOf(proxy.timeout().get()));
        } finally {
            executor.shutdown();
        }
    }

    private SimpleAsync createProxy(final ExecutorService executor) {
        final SimpleSync bean = new SimpleSync(1);
// Path: src/test/java/com/github/vbauer/caesar/basic/BasicTest.java
// @RunWith(BlockJUnit4ClassRunner.class)
// public abstract class BasicTest {
// 
//     protected final boolean checkUtilConstructorContract(final Class<?>... utilClasses) {
//         Assert.assertTrue(utilClasses.length > 0);
// 
//         PrivateConstructorChecker
//             .forClasses(utilClasses)
//             .expectedTypeOfException(UnsupportedOperationException.class)
//             .check();
// 
//         return true;
//     }
// 
// }
// 
// Path: src/test/java/com/github/vbauer/caesar/bean/SimpleAsync.java
// @Timeout(5)
// public interface SimpleAsync {
// 
//     Future<Integer> getId();
// 
//     Future<Boolean> timeout();
// 
// }
// 
// Path: src/test/java/com/github/vbauer/caesar/bean/SimpleSync.java
// public class SimpleSync {
// 
//     public static final boolean TIMEOUT_VALUE = true;
//     private final int id;
// 
// 
//     public SimpleSync(final int id) {
//         this.id = id;
//     }
// 
// 
//     public int getId() {
//         return id;
//     }
// 
//     public Boolean timeout() throws InterruptedException {
//         Thread.sleep(1000);
//         return TIMEOUT_VALUE;
//     }
// 
// 
//     @Override
//     public int hashCode() {
//         return id;
//     }
// 
//     @Override
//     public boolean equals(final Object obj) {
//         if (obj instanceof SimpleSync) {
//             final SimpleSync other = (SimpleSync) obj;
//             return other.getId() == getId();
//         }
//         return false;
//     }
// 
//     @Override
//     public String toString() {
//         return String.valueOf(getId());
//     }
// 
// }
// 
// Path: src/main/java/com/github/vbauer/caesar/exception/UnsupportedTimeoutException.java
// @SuppressWarnings("serial")
// public class UnsupportedTimeoutException extends AbstractCaesarException {
// 
//     private final Executor executor;
// 
// 
//     public UnsupportedTimeoutException(final Executor executor) {
//         this.executor = executor;
//     }
// 
// 
//     public Executor getExecutor() {
//         return executor;
//     }
// 
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public String getMessage() {
//         return String.format(
//             "%s does not support timeouts. Use %s.",
//             getExecutor(), ScheduledExecutorService.class
//         );
//     }
// 
// }
// 
// Path: src/main/java/com/github/vbauer/caesar/proxy/AsyncProxyCreator.java
// public final class AsyncProxyCreator {
// 
//     private AsyncProxyCreator() {
//         throw new UnsupportedOperationException();
//     }
// 
// 
//     public static <SYNC, ASYNC> ASYNC create(
//         final SYNC bean, final Class<ASYNC> asyncInterface, final ExecutorService executor
//     ) {
//         return create(bean, asyncInterface, executor, true);
//     }
// 
//     @SuppressWarnings("unchecked")
//     public static <SYNC, ASYNC> ASYNC create(
//         final SYNC bean, final Class<ASYNC> asyncInterface, final ExecutorService executor, final boolean validate
//     ) {
//         final AsyncInvocationHandler handler = AsyncInvocationHandler.create(bean, executor);
//         final Class<?> beanClass = bean.getClass();
//         final ClassLoader classLoader = beanClass.getClassLoader();
//         final Class<?>[] interfaces = {
//             asyncInterface,
//         };
// 
//         final ASYNC proxy = (ASYNC) Proxy.newProxyInstance(classLoader, interfaces, handler);
//         return validate ? validate(proxy, handler) : proxy;
//     }
// 
// 
//     private static <T> T validate(final T proxy, final AsyncInvocationHandler handler) {
//         final Class<?> targetClass = ReflectionUtils.getClassWithoutProxies(proxy);
//         final Method[] methods = targetClass.getDeclaredMethods();
// 
//         for (final Method method : methods) {
//             final AsyncMethodRunner runner = handler.findAsyncMethodRunner(method);
//             if (runner == null) {
//                 throw new MissedSyncMethodException(method);
//             }
//         }
// 
//         return proxy;
//     }
// 
// }


// Path: src/test/java/com/github/vbauer/caesar/annotation/TimeoutAnnotationTest.java
import com.github.vbauer.caesar.basic.BasicTest;
import com.github.vbauer.caesar.bean.SimpleAsync;
import com.github.vbauer.caesar.bean.SimpleSync;
import com.github.vbauer.caesar.exception.UnsupportedTimeoutException;
import com.github.vbauer.caesar.proxy.AsyncProxyCreator;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

package com.github.vbauer.caesar.annotation;



/**
 * @author Vladislav Bauer
 */

public class TimeoutAnnotationTest extends BasicTest {

    @Test
    public void testGoodExecutorService() throws Exception {
        final ExecutorService executor = Executors.newScheduledThreadPool(1);
        try {
            final SimpleAsync proxy = createProxy(executor);
            Assert.assertEquals(SimpleSync.TIMEOUT_VALUE, proxy.timeout().get());
        } finally {
            executor.shutdown();
        }
    }

    @Test(expected = UnsupportedTimeoutException.class)
    public void testBadExecutorService() throws Exception {
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        try {
            final SimpleAsync proxy = createProxy(executor);
            Assert.fail(String.valueOf(proxy.timeout().get()));
        } finally {
            executor.shutdown();
        }
    }

    private SimpleAsync createProxy(final ExecutorService executor) {
        final SimpleSync bean = new SimpleSync(1);
        return AsyncProxyCreator.create(bean, SimpleAsync.class, executor);