net.node42.filter.SimpleTimeoutLoadLimitingFilterTest.java Source code

Java tutorial

Introduction

Here is the source code for net.node42.filter.SimpleTimeoutLoadLimitingFilterTest.java

Source

package net.node42.filter;

// Copyright 2013 Mark Roderick

//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.mock.web.MockFilterConfig;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import static com.jayway.awaitility.Awaitility.await;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;

public class SimpleTimeoutLoadLimitingFilterTest {

    // STATELESS to run individual @Tests concurrently

    @Test
    public void testDefaultSettings() throws Exception {
        final SimpleTimeoutLoadLimitingFilter target = new SimpleTimeoutLoadLimitingFilter();
        final MockFilterConfig filterConfig = new MockFilterConfig(new MockServletContext());

        target.init(filterConfig);
        assertThat(target.maxConcurrentRequests).isNotNull()
                .isEqualTo(SimpleTimeoutLoadLimitingFilter.REQUEST_COUNT_CONCURRENT_MAX_DEFAULT);
        assertThat(target.requestCountCheckInterval).isNotNull()
                .isEqualTo(SimpleTimeoutLoadLimitingFilter.REQUEST_COUNT_CHECK_INTERVAL_DEFAULT);
        assertThat(target.requestTimeoutMillis).isNotNull()
                .isEqualTo(SimpleTimeoutLoadLimitingFilter.REQUEST_TIMEOUT_DEFAULT);
        assertThat(target.timeoutResponseContent).isNotNull()
                .isEqualTo(SimpleTimeoutLoadLimitingFilter.CONTENT_TIMEOUT_DEFAULT);
    }

    @Test
    public void testSpecifiedSettings() throws Exception {
        final SimpleTimeoutLoadLimitingFilter target = new SimpleTimeoutLoadLimitingFilter();
        final MockFilterConfig filterConfig = new MockFilterConfig(new MockServletContext());
        filterConfig.addInitParameter("request_count_concurrent_max", "1");
        filterConfig.addInitParameter("request_count_check_interval", "1000");
        filterConfig.addInitParameter("request_timeout", "2000");
        filterConfig.addInitParameter("response_timeout_file_name", "target/test-classes/ILuvLinux.txt");

        target.init(filterConfig);
        assertThat(target.maxConcurrentRequests).isNotNull().isEqualTo(1);
        assertThat(target.requestCountCheckInterval).isNotNull().isEqualTo(1000L);
        assertThat(target.requestTimeoutMillis).isNotNull().isEqualTo(2000L);
        assertThat(target.timeoutResponseContent).isNotNull()
                .isEqualTo("It's true.\n\nThis is just a stub file for targeting some unit tests.");
    }

    @Test
    public void testConcurrentCountIncrementation() throws Exception {

        final SimpleTimeoutLoadLimitingFilter target = new SimpleTimeoutLoadLimitingFilter();
        final MockFilterConfig filterConfig = new MockFilterConfig(new MockServletContext());
        target.init(filterConfig);

        final MockHttpServletRequest request = new MockHttpServletRequest();
        final MockHttpServletResponse response = new MockHttpServletResponse();
        response.setWriterAccessAllowed(true);
        final FilterChain filterChain = mock(FilterChain.class);

        doAnswer(new Answer() {
            @Override
            public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
                Thread.sleep(7000L);
                return null;
            }
        }).when(filterChain).doFilter(any(ServletRequest.class), any(ServletResponse.class));

        // Reusing the request/response object for multiple calls. Safe, but they are not viable to inspect for state.
        await().atMost(2, TimeUnit.SECONDS).untilAtomic(target.ACTIVE_REQUESTS, equalTo(0));
        runLoadLimitingFilter(target, request, response, filterChain);
        await().atMost(2, TimeUnit.SECONDS).untilAtomic(target.ACTIVE_REQUESTS, equalTo(1));
        runLoadLimitingFilter(target, request, response, filterChain);
        await().atMost(2, TimeUnit.SECONDS).untilAtomic(target.ACTIVE_REQUESTS, equalTo(2));

        target.destroy();
    }

    @Test
    public void testTimeoutResponseReturned() throws Exception {
        final SimpleTimeoutLoadLimitingFilter target = new SimpleTimeoutLoadLimitingFilter();
        final MockFilterConfig filterConfig = new MockFilterConfig(new MockServletContext());
        // Nothing gets through, and it times out immediately...
        filterConfig.addInitParameter("request_count_concurrent_max", "0");
        filterConfig.addInitParameter("request_timeout", "-1000");
        target.init(filterConfig);

        final MockHttpServletRequest request = new MockHttpServletRequest();
        final MockHttpServletResponse response = new MockHttpServletResponse();
        response.setWriterAccessAllowed(true);
        final FilterChain filterChain = mock(FilterChain.class);

        runLoadLimitingFilter(target, request, response, filterChain);
        await().atMost(2, TimeUnit.SECONDS).untilAtomic(target.ACTIVE_REQUESTS, equalTo(0));
        assertThat(response.getContentAsString()).isNotNull().isNotEmpty()
                .isEqualTo(SimpleTimeoutLoadLimitingFilter.CONTENT_TIMEOUT_DEFAULT);
    }

    @Test
    public void testDestroy() throws Exception {
        final SimpleTimeoutLoadLimitingFilter target = new SimpleTimeoutLoadLimitingFilter();
        final MockFilterConfig filterConfig = new MockFilterConfig(new MockServletContext());
        filterConfig.addInitParameter("request_count_concurrent_max", "0");
        filterConfig.addInitParameter("request_count_check_interval", "200");
        filterConfig.addInitParameter("request_timeout", "10000");

        target.init(filterConfig);
        assertThat(target.maxConcurrentRequests).isEqualTo(0);
        assertThat(target.requestCountCheckInterval).isEqualTo(200L);
        assertThat(target.requestTimeoutMillis).isEqualTo(10000);

        final MockHttpServletRequest request = new MockHttpServletRequest();
        final MockHttpServletResponse response = new MockHttpServletResponse();
        response.setWriterAccessAllowed(true);
        final FilterChain filterChain = mock(FilterChain.class);

        runLoadLimitingFilter(target, request, response, filterChain);
        assertThat(response.getContentLength()).isEqualTo(0); // Verify we haven't written a timeout message

        target.destroy();
        assertThat(target.DESTROY.get()).isEqualTo(true);
        await().atMost(5, TimeUnit.SECONDS).until(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return !response.getContentAsString().isEmpty();
            }
        });
        assertThat(response.getContentAsString()).isNotEmpty()
                .isEqualTo(SimpleTimeoutLoadLimitingFilter.CONTENT_TIMEOUT_DEFAULT);
    }

    // HELPER METHODS...

    private void runLoadLimitingFilter(final SimpleTimeoutLoadLimitingFilter target,
            final MockHttpServletRequest request, final MockHttpServletResponse response,
            final FilterChain filterChain) {

        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    target.doFilter(request, response, filterChain);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ServletException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}