// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/properties/RateLimitProperties.java
// public static class Policy {
//     /**
//      * Refresh interval window (in seconds).
//      */
//     @NotNull
//     @DurationUnit(ChronoUnit.SECONDS)
//     private Duration refreshInterval = Duration.ofSeconds(60);
// 
//     /**
//      * Request number limit per refresh interval window.
//      */
//     private Long limit;
// 
//     /**
//      * Request time limit per refresh interval window (in seconds).
//      */
//     @DurationUnit(ChronoUnit.SECONDS)
//     private Duration quota;
// 
//     private boolean breakOnMatch;
// 
//     @Valid
//     @NotNull
//     @NestedConfigurationProperty
//     private List<MatchType> type = Lists.newArrayList();
// 
//     public Duration getRefreshInterval() {
//         return refreshInterval;
//     }
// 
//     public void setRefreshInterval(Duration refreshInterval) {
//         this.refreshInterval = refreshInterval;
//     }
// 
//     public Long getLimit() {
//         return limit;
//     }
// 
//     public void setLimit(Long limit) {
//         this.limit = limit;
//     }
// 
//     public Duration getQuota() {
//         return quota;
//     }
// 
//     public void setQuota(Duration quota) {
//         this.quota = quota;
//     }
// 
//     public boolean isBreakOnMatch() {
//         return breakOnMatch;
//     }
// 
//     public void setBreakOnMatch(boolean breakOnMatch) {
//         this.breakOnMatch = breakOnMatch;
//     }
// 
//     public List<MatchType> getType() {
//         return type;
//     }
// 
//     public void setType(List<MatchType> type) {
//         this.type = type;
//     }
// 
//     public static class MatchType {
// 
//         @Valid
//         @NotNull
//         private RateLimitType type;
// 
//         private String matcher;
// 
//         public MatchType(@Valid @NotNull RateLimitType type, String matcher) {
//             this.type = type;
//             this.matcher = matcher;
//         }
// 
//         public boolean apply(HttpServletRequest request, Route route, RateLimitUtils rateLimitUtils) {
//             return StringUtils.isEmpty(matcher) || type.apply(request, route, rateLimitUtils, matcher);
//         }
// 
//         public String key(HttpServletRequest request, Route route, RateLimitUtils rateLimitUtils) {
//             return type.key(request, route, rateLimitUtils, matcher) +
//                     (StringUtils.isEmpty(matcher) ? StringUtils.EMPTY : (":" + matcher));
//         }
// 
//         public RateLimitType getType() {
//             return type;
//         }
// 
//         public void setType(RateLimitType type) {
//             this.type = type;
//         }
// 
//         public String getMatcher() {
//             return matcher;
//         }
// 
//         public void setMatcher(String matcher) {
//             this.matcher = matcher;
//         }
//     }
// }


import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties.Policy;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
package com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties;



@SpringBootTest(classes = RateLimitPropertiesTest.TestConfiguration.class)
@ActiveProfiles("test-duration")
class RateLimitPropertiesTest {
    @Autowired
    private RateLimitProperties properties;

    @Test
    void should_populate_policies() {
        Map<String, List<Policy>> policyList = this.properties.getPolicyList();
        assertThat(policyList).containsKeys("defaultValues", "withoutUnit", "withSeconds", "withMinutes");
        assertAll("Should populate policies list.",
            () -> assertThat(this.properties.getPolicies("defaultValues")).isNotEmpty(),
            () -> assertThat(this.properties.getPolicies("withoutUnit")).isNotEmpty(),
            () -> assertThat(this.properties.getPolicies("withSeconds")).isNotEmpty(),
            () -> assertThat(this.properties.getPolicies("withMinutes")).isNotEmpty()
        );
    }

    @ParameterizedTest(name = "[{index}] Service \"{0}\" should have: refreshInterval = {1} and quota = {2}.")
    @MethodSource("refreshIntervalDs")
    void should_populate_refreshinterval(String serviceId, Duration expectedRefreshInterval, Duration expectedQuota) {
      List<Policy> policies = this.properties.getPolicies(serviceId);
      assertThat(policies).hasSize(1);
      assertEquals(policies.get(0).getRefreshInterval(), expectedRefreshInterval);
      assertEquals(policies.get(0).getQuota(), expectedQuota);
    }

    private static Stream<Arguments> refreshIntervalDs() {
// Path: spring-cloud-zuul-ratelimit-core/src/main/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/properties/RateLimitProperties.java
// public static class Policy {
//     /**
//      * Refresh interval window (in seconds).
//      */
//     @NotNull
//     @DurationUnit(ChronoUnit.SECONDS)
//     private Duration refreshInterval = Duration.ofSeconds(60);
// 
//     /**
//      * Request number limit per refresh interval window.
//      */
//     private Long limit;
// 
//     /**
//      * Request time limit per refresh interval window (in seconds).
//      */
//     @DurationUnit(ChronoUnit.SECONDS)
//     private Duration quota;
// 
//     private boolean breakOnMatch;
// 
//     @Valid
//     @NotNull
//     @NestedConfigurationProperty
//     private List<MatchType> type = Lists.newArrayList();
// 
//     public Duration getRefreshInterval() {
//         return refreshInterval;
//     }
// 
//     public void setRefreshInterval(Duration refreshInterval) {
//         this.refreshInterval = refreshInterval;
//     }
// 
//     public Long getLimit() {
//         return limit;
//     }
// 
//     public void setLimit(Long limit) {
//         this.limit = limit;
//     }
// 
//     public Duration getQuota() {
//         return quota;
//     }
// 
//     public void setQuota(Duration quota) {
//         this.quota = quota;
//     }
// 
//     public boolean isBreakOnMatch() {
//         return breakOnMatch;
//     }
// 
//     public void setBreakOnMatch(boolean breakOnMatch) {
//         this.breakOnMatch = breakOnMatch;
//     }
// 
//     public List<MatchType> getType() {
//         return type;
//     }
// 
//     public void setType(List<MatchType> type) {
//         this.type = type;
//     }
// 
//     public static class MatchType {
// 
//         @Valid
//         @NotNull
//         private RateLimitType type;
// 
//         private String matcher;
// 
//         public MatchType(@Valid @NotNull RateLimitType type, String matcher) {
//             this.type = type;
//             this.matcher = matcher;
//         }
// 
//         public boolean apply(HttpServletRequest request, Route route, RateLimitUtils rateLimitUtils) {
//             return StringUtils.isEmpty(matcher) || type.apply(request, route, rateLimitUtils, matcher);
//         }
// 
//         public String key(HttpServletRequest request, Route route, RateLimitUtils rateLimitUtils) {
//             return type.key(request, route, rateLimitUtils, matcher) +
//                     (StringUtils.isEmpty(matcher) ? StringUtils.EMPTY : (":" + matcher));
//         }
// 
//         public RateLimitType getType() {
//             return type;
//         }
// 
//         public void setType(RateLimitType type) {
//             this.type = type;
//         }
// 
//         public String getMatcher() {
//             return matcher;
//         }
// 
//         public void setMatcher(String matcher) {
//             this.matcher = matcher;
//         }
//     }
// }


// Path: spring-cloud-zuul-ratelimit-core/src/test/java/com/marcosbarbero/cloud/autoconfigure/zuul/ratelimit/config/properties/RateLimitPropertiesTest.java
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties.Policy;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

package com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties;



@SpringBootTest(classes = RateLimitPropertiesTest.TestConfiguration.class)
@ActiveProfiles("test-duration")
class RateLimitPropertiesTest {
    @Autowired
    private RateLimitProperties properties;

    @Test
    void should_populate_policies() {
        Map<String, List<Policy>> policyList = this.properties.getPolicyList();
        assertThat(policyList).containsKeys("defaultValues", "withoutUnit", "withSeconds", "withMinutes");
        assertAll("Should populate policies list.",
            () -> assertThat(this.properties.getPolicies("defaultValues")).isNotEmpty(),
            () -> assertThat(this.properties.getPolicies("withoutUnit")).isNotEmpty(),
            () -> assertThat(this.properties.getPolicies("withSeconds")).isNotEmpty(),
            () -> assertThat(this.properties.getPolicies("withMinutes")).isNotEmpty()
        );
    }

    @ParameterizedTest(name = "[{index}] Service \"{0}\" should have: refreshInterval = {1} and quota = {2}.")
    @MethodSource("refreshIntervalDs")
    void should_populate_refreshinterval(String serviceId, Duration expectedRefreshInterval, Duration expectedQuota) {
      List<Policy> policies = this.properties.getPolicies(serviceId);
      assertThat(policies).hasSize(1);
      assertEquals(policies.get(0).getRefreshInterval(), expectedRefreshInterval);
      assertEquals(policies.get(0).getQuota(), expectedQuota);
    }

    private static Stream<Arguments> refreshIntervalDs() {
      return Stream.of(