content: package ro.isdc.wro.http;
  
  import static org.junit.Assert.assertEquals;
  import static org.mockito.Mockito.verify;
  import static org.mockito.Mockito.when;
  
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.InputStream;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.zip.GZIPInputStream;
  
  import javax.servlet.FilterChain;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.apache.commons.io.IOUtils;
  import org.junit.After;
  import org.junit.AfterClass;
  import org.junit.Before;
  import org.junit.BeforeClass;
  import org.junit.Test;
  import org.mockito.Mock;
  import org.mockito.Mockito;
  import org.mockito.MockitoAnnotations;
  import org.mockito.invocation.InvocationOnMock;
  import org.mockito.stubbing.Answer;
  
  import ro.isdc.wro.config.Context;
  import ro.isdc.wro.http.support.DelegatingServletInputStream;
  import ro.isdc.wro.http.support.DelegatingServletOutputStream;
  import ro.isdc.wro.util.io.NullOutputStream;
  
  
  /**
   * @author Alex Objelean
   */
  public class TestGzipFilter {
    private GzipFilter victim;
    @Mock
    private HttpServletRequest mockRequest;
    @Mock
    private HttpServletResponse mockResponse;
    @Mock
    private FilterChain mockFilterChain;
    
    @BeforeClass
    public static void onBeforeClass() {
      assertEquals(0, Context.countActive());
    }
    
    @AfterClass
    public static void onAfterClass() {
      assertEquals(0, Context.countActive());
    }
    
    @Before
    public void setUp()
        throws Exception {
      victim = new GzipFilter();
      MockitoAnnotations.initMocks(this);
      when(mockRequest.getInputStream()).thenReturn(
          new DelegatingServletInputStream(new ByteArrayInputStream("".getBytes())));
      when(mockResponse.getOutputStream()).thenReturn(new DelegatingServletOutputStream(new NullOutputStream()));
      // mock chaining
      Mockito.doAnswer(new Answer<Void>() {
        public Void answer(final InvocationOnMock invocation)
            throws Throwable {
          final ServletRequest request = (ServletRequest) invocation.getArguments()[0];
          final ServletResponse response = (ServletResponse) invocation.getArguments()[1];
          IOUtils.copy(request.getInputStream(), response.getOutputStream());
          return null;
        }
      }).when(mockFilterChain).doFilter(Mockito.any(HttpServletRequest.class), Mockito.any(HttpServletResponse.class));
    }
    
    
    @After
    public void tearDown() {
      Context.unset();
    }
    
    @Test
    public void shouldChainWhenGzipIsNotSupported()
        throws Exception {
      victim.doFilter(mockRequest, mockResponse, mockFilterChain);
      verify(mockFilterChain, Mockito.times(1)).doFilter(mockRequest, mockResponse);
    }
    
    @Test
    public void shouldGzipWhenGzipSupported()
        throws Exception {
      markGzipAsAllowed();
      final String content = "sampleContent";
      final InputStream sourceStream = new ByteArrayInputStream(content.getBytes());
      final ByteArrayOutputStream targetStream = new ByteArrayOutputStream();
      
      when(mockRequest.getInputStream()).thenReturn(new DelegatingServletInputStream(sourceStream));
      when(mockResponse.getOutputStream()).thenReturn(new DelegatingServletOutputStream(targetStream));
      
      victim.doFilter(mockRequest, mockResponse, mockFilterChain);
      
      // not the same response is chained
      verify(mockFilterChain, Mockito.never()).doFilter(mockRequest, mockResponse);
      // chain is invoked but with a different response
      verify(mockFilterChain, Mockito.times(1)).doFilter(Mockito.eq(mockRequest), Mockito.any(HttpServletResponse.class));
      
      final InputStream ungzippedStream = new GZIPInputStream(new ByteArrayInputStream(targetStream.toByteArray()));
      
      assertEquals(content, IOUtils.toString(ungzippedStream));
    }
    
    private void markGzipAsAllowed() {
      final String headerName = "Accept-Encoding";
      when(mockRequest.getHeaderNames()).thenReturn(Collections.enumeration(Arrays.asList(headerName)));
      when(mockRequest.getHeader(headerName)).thenReturn("gzip");
    }
  }
  