// Path: ratelimitj-core/src/main/java/es/moki/ratelimitj/core/limiter/concurrent/Baton.java
// public interface Baton {
// 
//     void release();
// 
//     <T> Optional<T> get(Supplier<T> action);
// 
//     void doAction(Runnable action);
// 
//     boolean hasAcquired();
// }
// 
// Path: ratelimitj-core/src/main/java/es/moki/ratelimitj/core/limiter/concurrent/ConcurrentLimitRule.java
// @ParametersAreNonnullByDefault
// public class ConcurrentLimitRule {
// 
//     private final int concurrentLimit;
//     private final long timeoutMillis;
//     private final String name;
// 
//     private ConcurrentLimitRule(int concurrentLimit, long timeoutMillis) {
//         this(concurrentLimit, timeoutMillis, null);
//     }
// 
//     private ConcurrentLimitRule(int concurrentLimit, long timeoutMillis, String name) {
//         this.concurrentLimit = concurrentLimit;
//         this.timeoutMillis = timeoutMillis;
//         this.name = name;
//     }
// 
//     /**
//      * Initialise a concurrent rate limit.
//      *
//      * @param concurrentLimit The concurrent limit.
//      * @param timeOutUnit     The time unit.
//      * @param timeOut         A timeOut for the checkout baton.
//      * @return A concurrent limit rule.
//      */
//     public static ConcurrentLimitRule of(int concurrentLimit, TimeUnit timeOutUnit, long timeOut) {
//         requireNonNull(timeOutUnit, "time out unit can not be null");
//         return new ConcurrentLimitRule(concurrentLimit, timeOutUnit.toMillis(timeOut));
//     }
// 
//     /**
//      * Applies a name to the rate limit that is useful for metrics.
//      *
//      * @param name Defines a descriptive name for the rule limit.
//      * @return a limit rule
//      */
//     public ConcurrentLimitRule withName(String name) {
//         return new ConcurrentLimitRule(this.concurrentLimit, this.timeoutMillis, name);
//     }
// 
//     public int getConcurrentLimit() {
//         return concurrentLimit;
//     }
// 
//     public long getTimeoutMillis() {
//         return timeoutMillis;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || !(o instanceof ConcurrentLimitRule)) {
//             return false;
//         }
//         ConcurrentLimitRule that = (ConcurrentLimitRule) o;
//         return concurrentLimit == that.concurrentLimit &&
//                 timeoutMillis == that.timeoutMillis &&
//                 Objects.equals(name, that.name);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(concurrentLimit, timeoutMillis, name);
//     }
// }
// 
// Path: ratelimitj-test/src/main/java/es/moki/ratelimitj/test/limiter/concurrent/AbstractSyncConcurrentRateLimiterTest.java
// public class AbstractSyncConcurrentRateLimiterTest {
// }


import es.moki.ratelimitj.core.limiter.concurrent.Baton;
import es.moki.ratelimitj.core.limiter.concurrent.ConcurrentLimitRule;
import es.moki.ratelimitj.test.limiter.concurrent.AbstractSyncConcurrentRateLimiterTest;
import org.junit.jupiter.api.Test;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
package es.moki.ratelimitj.inmemory.concurrent;





class InMemoryConcurrentSyncRequestRateLimiterTest extends AbstractSyncConcurrentRateLimiterTest {

    @Test
    void shouldPreventConcurrentRequests() {
        InMemoryConcurrentRequestRateLimiter limiter = new InMemoryConcurrentRequestRateLimiter(
// Path: ratelimitj-core/src/main/java/es/moki/ratelimitj/core/limiter/concurrent/Baton.java
// public interface Baton {
// 
//     void release();
// 
//     <T> Optional<T> get(Supplier<T> action);
// 
//     void doAction(Runnable action);
// 
//     boolean hasAcquired();
// }
// 
// Path: ratelimitj-core/src/main/java/es/moki/ratelimitj/core/limiter/concurrent/ConcurrentLimitRule.java
// @ParametersAreNonnullByDefault
// public class ConcurrentLimitRule {
// 
//     private final int concurrentLimit;
//     private final long timeoutMillis;
//     private final String name;
// 
//     private ConcurrentLimitRule(int concurrentLimit, long timeoutMillis) {
//         this(concurrentLimit, timeoutMillis, null);
//     }
// 
//     private ConcurrentLimitRule(int concurrentLimit, long timeoutMillis, String name) {
//         this.concurrentLimit = concurrentLimit;
//         this.timeoutMillis = timeoutMillis;
//         this.name = name;
//     }
// 
//     /**
//      * Initialise a concurrent rate limit.
//      *
//      * @param concurrentLimit The concurrent limit.
//      * @param timeOutUnit     The time unit.
//      * @param timeOut         A timeOut for the checkout baton.
//      * @return A concurrent limit rule.
//      */
//     public static ConcurrentLimitRule of(int concurrentLimit, TimeUnit timeOutUnit, long timeOut) {
//         requireNonNull(timeOutUnit, "time out unit can not be null");
//         return new ConcurrentLimitRule(concurrentLimit, timeOutUnit.toMillis(timeOut));
//     }
// 
//     /**
//      * Applies a name to the rate limit that is useful for metrics.
//      *
//      * @param name Defines a descriptive name for the rule limit.
//      * @return a limit rule
//      */
//     public ConcurrentLimitRule withName(String name) {
//         return new ConcurrentLimitRule(this.concurrentLimit, this.timeoutMillis, name);
//     }
// 
//     public int getConcurrentLimit() {
//         return concurrentLimit;
//     }
// 
//     public long getTimeoutMillis() {
//         return timeoutMillis;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || !(o instanceof ConcurrentLimitRule)) {
//             return false;
//         }
//         ConcurrentLimitRule that = (ConcurrentLimitRule) o;
//         return concurrentLimit == that.concurrentLimit &&
//                 timeoutMillis == that.timeoutMillis &&
//                 Objects.equals(name, that.name);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(concurrentLimit, timeoutMillis, name);
//     }
// }
// 
// Path: ratelimitj-test/src/main/java/es/moki/ratelimitj/test/limiter/concurrent/AbstractSyncConcurrentRateLimiterTest.java
// public class AbstractSyncConcurrentRateLimiterTest {
// }


// Path: ratelimitj-inmemory/src/test/java/es/moki/ratelimitj/inmemory/concurrent/InMemoryConcurrentSyncRequestRateLimiterTest.java
import es.moki.ratelimitj.core.limiter.concurrent.Baton;
import es.moki.ratelimitj.core.limiter.concurrent.ConcurrentLimitRule;
import es.moki.ratelimitj.test.limiter.concurrent.AbstractSyncConcurrentRateLimiterTest;
import org.junit.jupiter.api.Test;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;

package es.moki.ratelimitj.inmemory.concurrent;





class InMemoryConcurrentSyncRequestRateLimiterTest extends AbstractSyncConcurrentRateLimiterTest {

    @Test
    void shouldPreventConcurrentRequests() {
        InMemoryConcurrentRequestRateLimiter limiter = new InMemoryConcurrentRequestRateLimiter(
                ConcurrentLimitRule.of(2, TimeUnit.MINUTES, 1));