// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/support/RateLimitConstants.java
// public static final String HEADER_REMAINING = "X-RateLimit-Remaining";
// 
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/Rate.java
// @Entity
// public class Rate {
// 
//     @Id
//     @Column(name = "rate_key")
//     private String key;
//     private Long remaining;
//     private Long remainingQuota;
//     private Long reset;
//     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy HH:mm:ss")
//     private Date expiration;
// 
//     public Rate() {
//     }
// 
//     public Rate(String key, Long remaining, Long remainingQuota, Long reset, Date expiration) {
//         this.key = key;
//         this.remaining = remaining;
//         this.remainingQuota = remainingQuota;
//         this.reset = reset;
//         this.expiration = expiration;
//     }
// 
//     public String getKey() {
//         return key;
//     }
// 
//     public void setKey(String key) {
//         this.key = key;
//     }
// 
//     public Long getRemaining() {
//         return remaining;
//     }
// 
//     public void setRemaining(Long remaining) {
//         this.remaining = remaining;
//     }
// 
//     public Long getRemainingQuota() {
//         return remainingQuota;
//     }
// 
//     public void setRemainingQuota(Long remainingQuota) {
//         this.remainingQuota = remainingQuota;
//     }
// 
//     public Long getReset() {
//         return reset;
//     }
// 
//     public void setReset(Long reset) {
//         this.reset = reset;
//     }
// 
//     public Date getExpiration() {
//         return expiration;
//     }
// 
//     public void setExpiration(Date expiration) {
//         this.expiration = expiration;
//     }
// }
// 
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/repository/ConsulRateLimiter.java
// public class ConsulRateLimiter extends AbstractRateLimiter {
// 
//     private static Logger log = LoggerFactory.getLogger(ConsulRateLimiter.class);
// 
//     private final ConsulClient consulClient;
//     private final ObjectMapper objectMapper;
// 
//     public ConsulRateLimiter(RateLimiterErrorHandler rateLimiterErrorHandler,
//         ConsulClient consulClient, ObjectMapper objectMapper) {
//         super(rateLimiterErrorHandler);
//         this.consulClient = consulClient;
//         this.objectMapper = objectMapper;
//     }
// 
//     @Override
//     protected Rate getRate(final String key) {
//         Rate rate = null;
//         GetValue value = this.consulClient.getKVValue(buildValidConsulKey(key)).getValue();
//         if (value != null && value.getDecodedValue() != null) {
//             try {
//                 rate = this.objectMapper.readValue(value.getDecodedValue(), Rate.class);
//             } catch (IOException e) {
//                 log.error("Failed to deserialize Rate", e);
//             }
//         }
//         return rate;
//     }
// 
//     @Override
//     protected void saveRate(Rate rate) {
//         String value = "";
//         try {
//             value = this.objectMapper.writeValueAsString(rate);
//         } catch (JsonProcessingException e) {
//             log.error("Failed to serialize Rate", e);
//         }
// 
//         if (hasText(value)) {
//             this.consulClient.setKVValue(buildValidConsulKey(rate.getKey()), value);
//         }
//     }
// 
//     // Slash will corrupt Consul Call , to be changed to _
//     private String buildValidConsulKey(String key){
//         if(isNotBlank(key)){
//             return key.replaceAll("/", "_");
//         }
//         return key;
//     }
// 
// }
// 
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/repository/RateLimiterErrorHandler.java
// public interface RateLimiterErrorHandler {
// 
//     void handleSaveError(String key, Exception e);
// 
//     void handleFetchError(String key, Exception e);
// 
//     void handleError(String msg, Exception e);
// 
// }


import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitConstants.HEADER_REMAINING;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.Response;
import com.ecwid.consul.v1.kv.model.GetValue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.Rate;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.ConsulRateLimiter;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.RateLimiterErrorHandler;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
package com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.filters.pre;



/**
 * @author Marcos Barbero
 * @since 2017-08-28
 */
public class ConsulRateLimitPreFilterTest extends BaseRateLimitPreFilterTest {

    private ConsulClient consulClient;
    private ObjectMapper objectMapper = new ObjectMapper();

    private Rate rate(long remaining) {
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/support/RateLimitConstants.java
// public static final String HEADER_REMAINING = "X-RateLimit-Remaining";
// 
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/Rate.java
// @Entity
// public class Rate {
// 
//     @Id
//     @Column(name = "rate_key")
//     private String key;
//     private Long remaining;
//     private Long remainingQuota;
//     private Long reset;
//     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy HH:mm:ss")
//     private Date expiration;
// 
//     public Rate() {
//     }
// 
//     public Rate(String key, Long remaining, Long remainingQuota, Long reset, Date expiration) {
//         this.key = key;
//         this.remaining = remaining;
//         this.remainingQuota = remainingQuota;
//         this.reset = reset;
//         this.expiration = expiration;
//     }
// 
//     public String getKey() {
//         return key;
//     }
// 
//     public void setKey(String key) {
//         this.key = key;
//     }
// 
//     public Long getRemaining() {
//         return remaining;
//     }
// 
//     public void setRemaining(Long remaining) {
//         this.remaining = remaining;
//     }
// 
//     public Long getRemainingQuota() {
//         return remainingQuota;
//     }
// 
//     public void setRemainingQuota(Long remainingQuota) {
//         this.remainingQuota = remainingQuota;
//     }
// 
//     public Long getReset() {
//         return reset;
//     }
// 
//     public void setReset(Long reset) {
//         this.reset = reset;
//     }
// 
//     public Date getExpiration() {
//         return expiration;
//     }
// 
//     public void setExpiration(Date expiration) {
//         this.expiration = expiration;
//     }
// }
// 
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/repository/ConsulRateLimiter.java
// public class ConsulRateLimiter extends AbstractRateLimiter {
// 
//     private static Logger log = LoggerFactory.getLogger(ConsulRateLimiter.class);
// 
//     private final ConsulClient consulClient;
//     private final ObjectMapper objectMapper;
// 
//     public ConsulRateLimiter(RateLimiterErrorHandler rateLimiterErrorHandler,
//         ConsulClient consulClient, ObjectMapper objectMapper) {
//         super(rateLimiterErrorHandler);
//         this.consulClient = consulClient;
//         this.objectMapper = objectMapper;
//     }
// 
//     @Override
//     protected Rate getRate(final String key) {
//         Rate rate = null;
//         GetValue value = this.consulClient.getKVValue(buildValidConsulKey(key)).getValue();
//         if (value != null && value.getDecodedValue() != null) {
//             try {
//                 rate = this.objectMapper.readValue(value.getDecodedValue(), Rate.class);
//             } catch (IOException e) {
//                 log.error("Failed to deserialize Rate", e);
//             }
//         }
//         return rate;
//     }
// 
//     @Override
//     protected void saveRate(Rate rate) {
//         String value = "";
//         try {
//             value = this.objectMapper.writeValueAsString(rate);
//         } catch (JsonProcessingException e) {
//             log.error("Failed to serialize Rate", e);
//         }
// 
//         if (hasText(value)) {
//             this.consulClient.setKVValue(buildValidConsulKey(rate.getKey()), value);
//         }
//     }
// 
//     // Slash will corrupt Consul Call , to be changed to _
//     private String buildValidConsulKey(String key){
//         if(isNotBlank(key)){
//             return key.replaceAll("/", "_");
//         }
//         return key;
//     }
// 
// }
// 
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/repository/RateLimiterErrorHandler.java
// public interface RateLimiterErrorHandler {
// 
//     void handleSaveError(String key, Exception e);
// 
//     void handleFetchError(String key, Exception e);
// 
//     void handleError(String msg, Exception e);
// 
// }


// Path: spring-cloud-zuul-ratelimit-core/src/test/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/filters/pre/ConsulRateLimitPreFilterTest.java
import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitConstants.HEADER_REMAINING;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.Response;
import com.ecwid.consul.v1.kv.model.GetValue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.Rate;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.ConsulRateLimiter;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.RateLimiterErrorHandler;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

package com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.filters.pre;



/**
 * @author Marcos Barbero
 * @since 2017-08-28
 */
public class ConsulRateLimitPreFilterTest extends BaseRateLimitPreFilterTest {

    private ConsulClient consulClient;
    private ObjectMapper objectMapper = new ObjectMapper();

    private Rate rate(long remaining) {
        return new Rate("key", remaining, 2000L, 100L, new Date(System.currentTimeMillis() + SECONDS.toMillis(2)));