@Test public void shouldUseDifferentBucketsWhenUsingValidPartitionKey() throws Exception { FakeTimeService time = new FakeTimeService(0); Expression<String> expr = Expression.valueOf("${matches(exchange.foo, 'bar-00') ?'bucket-00' :''}", String.class); ThrottlingFilter filter = new ThrottlingFilter(time, 1, duration("3 seconds"), expr); Handler handler = new ResponseHandler(Status.OK); // The time does not need to advance Exchange exchange = new Exchange(); Promise<Response, NeverThrowsException> promise; exchange.put("foo", "bar-00"); promise = filter.filter(exchange, new Request(), handler); assertThat(promise.get().getStatus()).isEqualTo(Status.OK); exchange.put("foo", "bar-00"); promise = filter.filter(exchange, new Request(), handler); assertThat(promise.get().getStatus()).isEqualTo(Status.TOO_MANY_REQUESTS); exchange.put("foo", "bar-01"); promise = filter.filter(exchange, new Request(), handler); assertThat(promise.get().getStatus()).isEqualTo(Status.OK); }
@Test public void shouldThrottleRequests() throws Exception { FakeTimeService time = new FakeTimeService(0); ThrottlingFilter filter = new ThrottlingFilter(time, 1, duration("3 seconds"), DEFAULT_PARTITION_EXPR); // This one has to call the handler as there are enough tokens in the bucket. Handler handler1 = mock(Handler.class, "handler1"); filter.filter(mock(Context.class), new Request(), handler1); verify(handler1).handle(any(Context.class), any(Request.class)); time.advance(duration("2 seconds")); // This one does not have to be called as there is no token anymore in the bucket. Handler handler2 = mock(Handler.class, "handler2"); Promise<Response, NeverThrowsException> promise2 = filter.filter(mock(Context.class), new Request(), handler2); verifyZeroInteractions(handler2); assertThat(promise2.get().getStatus()).isEqualTo(Status.TOO_MANY_REQUESTS); time.advance(duration("4 seconds")); // This one has to call the handler as the bucket has been refilled. Handler handler3 = mock(Handler.class, "handler3"); filter.filter(mock(Context.class), new Request(), handler3); verify(handler3).handle(any(Context.class), any(Request.class)); }
@Test public void shouldUseDefaultValueWithExpressionEvaluatingNull() throws Exception { FakeTimeService time = new FakeTimeService(0); Expression<String> expr = Expression.valueOf("${exchange.bar}", String.class); ThrottlingFilter filter = new ThrottlingFilter(time, 1, duration("3 seconds"), expr); Handler handler = new ResponseHandler(Status.OK); // The time does not need to advance Exchange exchange = new Exchange(); Promise<Response, NeverThrowsException> promise; promise = filter.filter(exchange, new Request(), handler); assertThat(promise.get().getStatus()).isEqualTo(Status.INTERNAL_SERVER_ERROR); }
@Test public void shouldThrottleConcurrentRequests() throws Exception { CountDownLatch latch1 = new CountDownLatch(1); CountDownLatch latch2 = new CountDownLatch(1); FakeTimeService time = new FakeTimeService(0); final ThrottlingFilter filter = new ThrottlingFilter(time, 1, duration("3 seconds"), DEFAULT_PARTITION_EXPR); // This one has to be called as there are enough tokens in the bucket. final Handler handler1 = new LatchHandler(latch1, latch2); Runnable r = new Runnable() { @Override public void run() { filter.filter(mock(Context.class), new Request(), handler1); } }; Thread t1 = new Thread(r); t1.setName("Filter for request #1"); t1.start(); latch2.await(); time.advance(duration("2 seconds")); try { // This one does not have to be called as there no token anymore in the bucket. Handler handler2 = mock(Handler.class, "handler2"); Promise<Response, NeverThrowsException> promise2 = filter.filter(mock(Context.class), new Request(), handler2); verifyZeroInteractions(handler2); Response response = promise2.get(20, TimeUnit.SECONDS); assertThat(response.getStatus()).isEqualTo(Status.TOO_MANY_REQUESTS); assertThat(response.getHeaders().getFirst("Retry-After")).isEqualTo("1"); } finally { latch1.countDown(); t1.join(); } }
@Test(dataProvider = "annotatedRequestHandlerData") public void testQueryCollectionAnnotatedRequestHandler( Class<?> requestHandler, boolean collection, boolean create, boolean read, boolean update, boolean delete, boolean patch, boolean resourceAction, boolean collectionAction, boolean query) throws Exception { // Given Object provider = requestHandler.newInstance(); Connection connection = Resources.newInternalConnection(createHandler(collection, provider)); QueryRequest req = Requests.newQueryRequest("/test"); // When Promise<QueryResult, ResourceException> promise = connection.queryAsync(new RootContext(), req, mock(QueryResourceHandler.class)); // Then if (query && collection) { AssertJPromiseAssert.assertThat(promise).succeeded(); QueryResult result = promise.get(); Assertions.assertThat(result.getPagedResultsCookie()).isEqualTo("query"); } else if (collection) { AssertJPromiseAssert.assertThat(promise) .failedWithException() .isInstanceOf(NotSupportedException.class); } else { AssertJPromiseAssert.assertThat(promise) .failedWithException() .isInstanceOf(BadRequestException.class); } }