// Path: tenacity-core/src/main/java/com/yammer/tenacity/core/logging/ExceptionLogger.java
// public abstract class ExceptionLogger<E extends Exception> {
// 
//     protected final Class<E> clazz;
//     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
// 
//     /**
//      * Specify the class that this exception logger can handle
//      */
//     protected ExceptionLogger() {
//         this.clazz = Generics.getTypeParameter(this.getClass(), Exception.class);
//     }
// 
//     /**
//      * Make sure you check that this ExceptionLogger can actually handle the type of exception
//      */
//     public boolean canHandleException(Exception exception) {
//         return this.clazz.isInstance(exception);
//     }
// 
//     @SuppressWarnings("unchecked")
//     /**
//      * Actually log the exception
//      * @throws IllegalStateException it relieves an exception that it can't log
//      */
//     public <T> void log(Exception exception, HystrixInvokableInfo<T> commandInstance) {
//         checkState(canHandleException(exception));
// 
//         logException((E) exception, commandInstance);
//     }
// 
//     /**
//      * @param exception the exception that you should log
//      * @param commandInstance you get access to the command that failed, so you can specify what kind it was
//      */
//     protected abstract <T> void logException(E exception, HystrixInvokableInfo<T> commandInstance);
// }
// 
// Path: tenacity-core/src/main/java/com/yammer/tenacity/core/logging/ExceptionLoggingCommandHook.java
// public class ExceptionLoggingCommandHook extends HystrixCommandExecutionHook {
// 
//     private final List<ExceptionLogger<? extends Exception>> exceptionLoggers;
// 
//     /**
//      * Empty constructor only sets the DefaultExceptionLogger, which will log every type of exception
//      */
//     public ExceptionLoggingCommandHook() {
//         this(new DefaultExceptionLogger());
//     }
// 
//     public ExceptionLoggingCommandHook(ExceptionLogger<? extends Exception> exceptionLogger) {
//         this(ImmutableList.of(exceptionLogger));
//     }
// 
//     public ExceptionLoggingCommandHook(Iterable<ExceptionLogger<? extends Exception>> exceptionLoggers) {
//         this.exceptionLoggers = ImmutableList.copyOf(exceptionLoggers);
//     }
// 
//     @SuppressWarnings("unchecked")
//     @Override
//     public <T> Exception onExecutionError(HystrixInvokable<T> commandInstance, Exception exception) {
//         for (ExceptionLogger<? extends Exception> logger: exceptionLoggers) {
//             if (logger.canHandleException(exception) && isHystrixInvokableInfo(commandInstance)) {
//                 logger.log(exception, (HystrixInvokableInfo<T>)commandInstance);
//                 return exception;
//             }
//         }
// 
//         return exception;
//     }
// 
//     private <T> boolean isHystrixInvokableInfo(HystrixInvokable<T> commandInstance) {
//         return commandInstance instanceof HystrixInvokableInfo;
//     }
// }
// 
// Path: tenacity-testing/src/main/java/com/yammer/tenacity/testing/TenacityTestRule.java
// public class TenacityTestRule implements TestRule {
//     private void setup() {
//         resetStreams();
//         Hystrix.reset();
//         final AbstractConfiguration configuration = ConfigurationManager.getConfigInstance();
//         configuration.setProperty("hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds", "100");
//     }
// 
//     public void teardown() {
//         Hystrix.reset(1, TimeUnit.SECONDS);
//         ConfigurationManager.getConfigInstance().clear();
//     }
// 
//     private void resetStreams() {
//         /* BucketedCounterStream */
//         CumulativeCommandEventCounterStream.reset();
//         RollingCommandEventCounterStream.reset();
//         CumulativeCollapserEventCounterStream.reset();
//         RollingCollapserEventCounterStream.reset();
//         CumulativeThreadPoolEventCounterStream.reset();
//         RollingThreadPoolEventCounterStream.reset();
//         HealthCountsStream.reset();
//         /* --------------------- */
// 
//         /* RollingConcurrencyStream */
//         RollingThreadPoolMaxConcurrencyStream.reset();
//         RollingCommandMaxConcurrencyStream.reset();
//         /* ------------------------ */
// 
//         /* RollingDistributionStream */
//         RollingCommandLatencyDistributionStream.reset();
//         RollingCommandUserLatencyDistributionStream.reset();
//         RollingCollapserBatchSizeDistributionStream.reset();
//         /* ------------------------- */
//     }
// 
//     @Override
//     public Statement apply(final Statement base, Description description) {
//         return new Statement() {
//             @Override
//             public void evaluate() throws Throwable {
//                 try {
//                     setup();
//                     base.evaluate();
//                 } finally {
//                     teardown();
//                 }
//             }
//         };
//     }
// }


import com.google.common.collect.ImmutableList;
import com.netflix.hystrix.HystrixCommand;
import com.yammer.tenacity.core.logging.ExceptionLogger;
import com.yammer.tenacity.core.logging.ExceptionLoggingCommandHook;
import com.yammer.tenacity.testing.TenacityTestRule;
import com.yammer.tenacity.tests.TenacityFailingCommand;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
package com.yammer.tenacity.tests.logging;



@RunWith(MockitoJUnitRunner.class)
public class ExceptionLoggingCommandHookTest {

    @Rule
    public final TenacityTestRule tenacityTestRule = new TenacityTestRule();

    private final HystrixCommand<String> failedCommand = new TenacityFailingCommand();
// Path: tenacity-core/src/main/java/com/yammer/tenacity/core/logging/ExceptionLogger.java
// public abstract class ExceptionLogger<E extends Exception> {
// 
//     protected final Class<E> clazz;
//     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
// 
//     /**
//      * Specify the class that this exception logger can handle
//      */
//     protected ExceptionLogger() {
//         this.clazz = Generics.getTypeParameter(this.getClass(), Exception.class);
//     }
// 
//     /**
//      * Make sure you check that this ExceptionLogger can actually handle the type of exception
//      */
//     public boolean canHandleException(Exception exception) {
//         return this.clazz.isInstance(exception);
//     }
// 
//     @SuppressWarnings("unchecked")
//     /**
//      * Actually log the exception
//      * @throws IllegalStateException it relieves an exception that it can't log
//      */
//     public <T> void log(Exception exception, HystrixInvokableInfo<T> commandInstance) {
//         checkState(canHandleException(exception));
// 
//         logException((E) exception, commandInstance);
//     }
// 
//     /**
//      * @param exception the exception that you should log
//      * @param commandInstance you get access to the command that failed, so you can specify what kind it was
//      */
//     protected abstract <T> void logException(E exception, HystrixInvokableInfo<T> commandInstance);
// }
// 
// Path: tenacity-core/src/main/java/com/yammer/tenacity/core/logging/ExceptionLoggingCommandHook.java
// public class ExceptionLoggingCommandHook extends HystrixCommandExecutionHook {
// 
//     private final List<ExceptionLogger<? extends Exception>> exceptionLoggers;
// 
//     /**
//      * Empty constructor only sets the DefaultExceptionLogger, which will log every type of exception
//      */
//     public ExceptionLoggingCommandHook() {
//         this(new DefaultExceptionLogger());
//     }
// 
//     public ExceptionLoggingCommandHook(ExceptionLogger<? extends Exception> exceptionLogger) {
//         this(ImmutableList.of(exceptionLogger));
//     }
// 
//     public ExceptionLoggingCommandHook(Iterable<ExceptionLogger<? extends Exception>> exceptionLoggers) {
//         this.exceptionLoggers = ImmutableList.copyOf(exceptionLoggers);
//     }
// 
//     @SuppressWarnings("unchecked")
//     @Override
//     public <T> Exception onExecutionError(HystrixInvokable<T> commandInstance, Exception exception) {
//         for (ExceptionLogger<? extends Exception> logger: exceptionLoggers) {
//             if (logger.canHandleException(exception) && isHystrixInvokableInfo(commandInstance)) {
//                 logger.log(exception, (HystrixInvokableInfo<T>)commandInstance);
//                 return exception;
//             }
//         }
// 
//         return exception;
//     }
// 
//     private <T> boolean isHystrixInvokableInfo(HystrixInvokable<T> commandInstance) {
//         return commandInstance instanceof HystrixInvokableInfo;
//     }
// }
// 
// Path: tenacity-testing/src/main/java/com/yammer/tenacity/testing/TenacityTestRule.java
// public class TenacityTestRule implements TestRule {
//     private void setup() {
//         resetStreams();
//         Hystrix.reset();
//         final AbstractConfiguration configuration = ConfigurationManager.getConfigInstance();
//         configuration.setProperty("hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds", "100");
//     }
// 
//     public void teardown() {
//         Hystrix.reset(1, TimeUnit.SECONDS);
//         ConfigurationManager.getConfigInstance().clear();
//     }
// 
//     private void resetStreams() {
//         /* BucketedCounterStream */
//         CumulativeCommandEventCounterStream.reset();
//         RollingCommandEventCounterStream.reset();
//         CumulativeCollapserEventCounterStream.reset();
//         RollingCollapserEventCounterStream.reset();
//         CumulativeThreadPoolEventCounterStream.reset();
//         RollingThreadPoolEventCounterStream.reset();
//         HealthCountsStream.reset();
//         /* --------------------- */
// 
//         /* RollingConcurrencyStream */
//         RollingThreadPoolMaxConcurrencyStream.reset();
//         RollingCommandMaxConcurrencyStream.reset();
//         /* ------------------------ */
// 
//         /* RollingDistributionStream */
//         RollingCommandLatencyDistributionStream.reset();
//         RollingCommandUserLatencyDistributionStream.reset();
//         RollingCollapserBatchSizeDistributionStream.reset();
//         /* ------------------------- */
//     }
// 
//     @Override
//     public Statement apply(final Statement base, Description description) {
//         return new Statement() {
//             @Override
//             public void evaluate() throws Throwable {
//                 try {
//                     setup();
//                     base.evaluate();
//                 } finally {
//                     teardown();
//                 }
//             }
//         };
//     }
// }


// Path: tenacity-core/src/test/java/com/yammer/tenacity/tests/logging/ExceptionLoggingCommandHookTest.java
import com.google.common.collect.ImmutableList;
import com.netflix.hystrix.HystrixCommand;
import com.yammer.tenacity.core.logging.ExceptionLogger;
import com.yammer.tenacity.core.logging.ExceptionLoggingCommandHook;
import com.yammer.tenacity.testing.TenacityTestRule;
import com.yammer.tenacity.tests.TenacityFailingCommand;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

package com.yammer.tenacity.tests.logging;



@RunWith(MockitoJUnitRunner.class)
public class ExceptionLoggingCommandHookTest {

    @Rule
    public final TenacityTestRule tenacityTestRule = new TenacityTestRule();

    private final HystrixCommand<String> failedCommand = new TenacityFailingCommand();
    private final Exception exception = new Exception();