// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/calls/CallContext.java
// public interface CallContext {
// 
//     /**
//      * Adds an aspect to the context.
//      */
//     void withAspect(Class<?> aspectClass);
// 
//     Weaver getConfiguredWeaver();
// 
//     void from(Class<?> sourceType);
// 
//     void from(CallSource source);
// 
//     CallSource getConfiguredCallSource();
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/calls/CallTarget.java
// public abstract class CallTarget {
// 
//     /**
//      * @throws NoSuchMethodException If the target is invalid
//      */
//     protected CallTarget(Object targetInstance,
//                          String targetMethodName,
//                          Class<?>[] argumentTypes)
//         throws NoSuchMethodException {
// 
//         checkTargetValidity(targetInstance, targetMethodName, argumentTypes);
//     }
// 
//     protected abstract void checkTargetValidity(Object targetInstance,
//                                                 String targetMethodName,
//                                                 Class<?>[] argumentTypes)
//         throws NoSuchMethodException;
// 
//     public abstract Object getTargetInstance();
// 
//     public abstract Class<?> getTargetClass();
// 
//     public abstract String getTargetMethodName();
// 
//     public abstract Method getTargetMethod();
// 
//     public abstract Class<?>[] getArgumentTypes();
// 
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/calls/MethodCaller.java
// public interface MethodCaller {
// 
//     /**
//      * Do the call to the target.
//      * 
//      * @throws IllegalArgumentException If {@code argumentValues} dont't match the target method
//      *         arguments (wrong number, wrong type, ...).
//      * @throws EncapsulatedExceptionThrownByTarget An exception throw by the target method and
//      *         encapsulated.
//      * @return The result of the call on the target. For void targets, null is returned.
//      */
//     Object doCall(Object[] argumentValues);
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/exceptions/EncapsulatedExceptionThrownByTarget.java
// public class EncapsulatedExceptionThrownByTarget extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     public EncapsulatedExceptionThrownByTarget(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public EncapsulatedExceptionThrownByTarget(Throwable cause) {
//         super(cause);
//     }
// 
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/exceptions/Mock4AjException.java
// public class Mock4AjException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     public Mock4AjException(final String message, final Throwable cause) {
//         super(message, cause);
//     }
// 
//     public Mock4AjException(final String message) {
//         super(message);
//     }
// 
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/internal/calls/CallerGenerator.java
// public interface CallerGenerator {
// 
//     MethodCaller generateMethodCaller(CallTarget target, CallContext callContext);
// 
// }


import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import info.rubico.mock4aj.api.calls.CallContext;
import info.rubico.mock4aj.api.calls.CallTarget;
import info.rubico.mock4aj.api.calls.MethodCaller;
import info.rubico.mock4aj.api.exceptions.EncapsulatedExceptionThrownByTarget;
import info.rubico.mock4aj.api.exceptions.Mock4AjException;
import info.rubico.mock4aj.internal.calls.CallerGenerator;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;
import net.sf.cglib.core.ReflectUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
    }

    @Test
    public void givenAnAjExceptionWhenCallThenExceptionIsNotBoxedTwice() throws Throwable {
        doThrow(new Mock4AjException("aa")).when(callerMock).doCall(NO_ARGS);
        try {
            simulateCall(targetObjectMock, GET_TIME_METHOD);
            fail();
        }
        catch (Mock4AjException exception) {
            assertNull("Mock4AjException should not be boxed twice.", exception.getCause());
        }
    }

    @Test
    public void givenMethodWithArgumentsWhenCallThenArgumentsArePassedToTheCaller() throws Throwable {
        final long time = 5L;
        simulateCall(targetObjectMock, SET_TIME_METHOD, time);
        verify(callerMock).doCall(new Object[] { time });
    }

    private Object simulateCall(Object target, Method method, Object... args) throws Throwable { // NOPMD
        return callback.intercept(clientOfTheCallbackMock, method, args, null);
    }

    private static CallContext anyContext() {
        return (CallContext) anyObject();
    }

    private static CallTarget anyTarget() {
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/calls/CallContext.java
// public interface CallContext {
// 
//     /**
//      * Adds an aspect to the context.
//      */
//     void withAspect(Class<?> aspectClass);
// 
//     Weaver getConfiguredWeaver();
// 
//     void from(Class<?> sourceType);
// 
//     void from(CallSource source);
// 
//     CallSource getConfiguredCallSource();
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/calls/CallTarget.java
// public abstract class CallTarget {
// 
//     /**
//      * @throws NoSuchMethodException If the target is invalid
//      */
//     protected CallTarget(Object targetInstance,
//                          String targetMethodName,
//                          Class<?>[] argumentTypes)
//         throws NoSuchMethodException {
// 
//         checkTargetValidity(targetInstance, targetMethodName, argumentTypes);
//     }
// 
//     protected abstract void checkTargetValidity(Object targetInstance,
//                                                 String targetMethodName,
//                                                 Class<?>[] argumentTypes)
//         throws NoSuchMethodException;
// 
//     public abstract Object getTargetInstance();
// 
//     public abstract Class<?> getTargetClass();
// 
//     public abstract String getTargetMethodName();
// 
//     public abstract Method getTargetMethod();
// 
//     public abstract Class<?>[] getArgumentTypes();
// 
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/calls/MethodCaller.java
// public interface MethodCaller {
// 
//     /**
//      * Do the call to the target.
//      * 
//      * @throws IllegalArgumentException If {@code argumentValues} dont't match the target method
//      *         arguments (wrong number, wrong type, ...).
//      * @throws EncapsulatedExceptionThrownByTarget An exception throw by the target method and
//      *         encapsulated.
//      * @return The result of the call on the target. For void targets, null is returned.
//      */
//     Object doCall(Object[] argumentValues);
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/exceptions/EncapsulatedExceptionThrownByTarget.java
// public class EncapsulatedExceptionThrownByTarget extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     public EncapsulatedExceptionThrownByTarget(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public EncapsulatedExceptionThrownByTarget(Throwable cause) {
//         super(cause);
//     }
// 
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/api/exceptions/Mock4AjException.java
// public class Mock4AjException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     public Mock4AjException(final String message, final Throwable cause) {
//         super(message, cause);
//     }
// 
//     public Mock4AjException(final String message) {
//         super(message);
//     }
// 
// }
// 
// Path: mock4aj-core/src/main/java/info/rubico/mock4aj/internal/calls/CallerGenerator.java
// public interface CallerGenerator {
// 
//     MethodCaller generateMethodCaller(CallTarget target, CallContext callContext);
// 
// }


// Path: mock4aj-core/src/test/java/info/rubico/mock4aj/codegen/cglib/calls/selector/CglibSimulateCallInterceptorTest.java
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import info.rubico.mock4aj.api.calls.CallContext;
import info.rubico.mock4aj.api.calls.CallTarget;
import info.rubico.mock4aj.api.calls.MethodCaller;
import info.rubico.mock4aj.api.exceptions.EncapsulatedExceptionThrownByTarget;
import info.rubico.mock4aj.api.exceptions.Mock4AjException;
import info.rubico.mock4aj.internal.calls.CallerGenerator;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;
import net.sf.cglib.core.ReflectUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

    }

    @Test
    public void givenAnAjExceptionWhenCallThenExceptionIsNotBoxedTwice() throws Throwable {
        doThrow(new Mock4AjException("aa")).when(callerMock).doCall(NO_ARGS);
        try {
            simulateCall(targetObjectMock, GET_TIME_METHOD);
            fail();
        }
        catch (Mock4AjException exception) {
            assertNull("Mock4AjException should not be boxed twice.", exception.getCause());
        }
    }

    @Test
    public void givenMethodWithArgumentsWhenCallThenArgumentsArePassedToTheCaller() throws Throwable {
        final long time = 5L;
        simulateCall(targetObjectMock, SET_TIME_METHOD, time);
        verify(callerMock).doCall(new Object[] { time });
    }

    private Object simulateCall(Object target, Method method, Object... args) throws Throwable { // NOPMD
        return callback.intercept(clientOfTheCallbackMock, method, args, null);
    }

    private static CallContext anyContext() {
        return (CallContext) anyObject();
    }

    private static CallTarget anyTarget() {
        return (CallTarget) anyObject();