<commit_before>package io.sniffy.servlet;

import io.sniffy.BaseTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static io.sniffy.servlet.SnifferFilter.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class SnifferFilterTest extends BaseTest {

    @Mock
    private FilterChain filterChain;

    private MockHttpServletResponse httpServletResponse;
    private MockServletContext servletContext;
    private MockHttpServletRequest requestWithPathAndQueryParameter;
    private MockHttpServletRequest requestWithPath;
    private MockHttpServletRequest requestContextWithoutTrailingSlash;
    private MockHttpServletRequest requestContext;
    private SnifferFilter filter;

    @Before
    public void setupServletApiMocks() {
        httpServletResponse = new MockHttpServletResponse();
        servletContext = new MockServletContext("/petclinic");
        requestWithPathAndQueryParameter = MockMvcRequestBuilders.get("/petclinic/foo/bar?baz").contextPath("/petclinic").buildRequest(servletContext);
        requestWithPath = MockMvcRequestBuilders.get("/petclinic/foo/bar/").contextPath("/petclinic").buildRequest(servletContext);
        requestContextWithoutTrailingSlash = MockMvcRequestBuilders.get("/petclinic").contextPath("/petclinic").buildRequest(servletContext);
        requestContext = MockMvcRequestBuilders.get("/petclinic/").contextPath("/petclinic").buildRequest(servletContext);
        filter = new SnifferFilter();
    }

    private FilterConfig getFilterConfig() {
        FilterConfig filterConfig = mock(FilterConfig.class);
        when(filterConfig.getInitParameter("inject-html")).thenReturn("true");
        when(filterConfig.getInitParameter("exclude-pattern")).thenReturn("^/baz/.*$");
        ServletContext servletContext = mock(ServletContext.class);
        when(filterConfig.getServletContext()).thenReturn(servletContext);
        when(servletContext.getContextPath()).thenReturn("/petclinic");
        return filterConfig;
    }

    @Test
    public void testUnitializedFilter() throws IOException, ServletException {

        SnifferFilter filter = new SnifferFilter();
        filter.setInjectHtml(true);

        filter.doFilter(requestWithPathAndQueryParameter, httpServletResponse, filterChain);

        assertTrue(httpServletResponse.getHeaderNames().contains(HEADER_NUMBER_OF_QUERIES));

    }

    @Test
    public void testFilterSniffyInjected() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");

        SnifferFilter filter = new SnifferFilter();
        filter.init(getFilterConfig());

        filter.doFilter(requestWithPathAndQueryParameter, httpServletResponse, filterChain);

        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(httpServletResponse.getContentAsString().getBytes()));

        String sniffyJsSrc = doc.getElementsByTagName("script").item(0).getAttributes().getNamedItem("src").getNodeValue();

        assertTrue(sniffyJsSrc + " must be a relative path", sniffyJsSrc.startsWith("../" + SNIFFER_URI_PREFIX));

        String requestDetailsUrl = httpServletResponse.getHeader(HEADER_REQUEST_DETAILS);

        assertTrue(requestDetailsUrl + " must be a relative path", requestDetailsUrl.startsWith("../" + REQUEST_URI_PREFIX));
    }

    private void answerWithContent(String actualContent) throws IOException, ServletException {
        doAnswer(invocation -> {
            Thread.sleep(1);
            HttpServletResponse response = (HttpServletResponse) invocation.getArguments()[1];
            response.setContentType("text/html");
            PrintWriter printWriter = response.getWriter();
            printWriter.append(actualContent);
            Thread.sleep(1);
            return null;
        }).when(filterChain).doFilter(any(), any());
    }

    @Test
    public void testFilterSniffyInjected_RequestWithPath() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");

        SnifferFilter filter = new SnifferFilter();
        filter.init(getFilterConfig());

        filter.doFilter(requestWithPath, httpServletResponse, filterChain);

        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(httpServletResponse.getContentAsString().getBytes()));

        String sniffyJsSrc = doc.getElementsByTagName("script").item(0).getAttributes().getNamedItem("src").getNodeValue();

        assertTrue(sniffyJsSrc + " must be a relative path", sniffyJsSrc.startsWith("../../" + SNIFFER_URI_PREFIX));

        String requestDetailsUrl = httpServletResponse.getHeader(HEADER_REQUEST_DETAILS);

        assertTrue(requestDetailsUrl + " must be a relative path", requestDetailsUrl.startsWith("../../" + REQUEST_URI_PREFIX));

    }

    @Test
    public void testFilterSniffyInjected_ContextWithoutTrailingSlash() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");

        SnifferFilter filter = new SnifferFilter();
        filter.init(getFilterConfig());

        filter.doFilter(requestContextWithoutTrailingSlash, httpServletResponse, filterChain);

        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(httpServletResponse.getContentAsString().getBytes()));

        Node scriptTag = doc.getElementsByTagName("script").item(0);
        assertNull(scriptTag.getAttributes().getNamedItem("src"));
        assertTrue(scriptTag.getTextContent().contains("document.write"));

        String requestDetailsUrl = httpServletResponse.getHeader(HEADER_REQUEST_DETAILS);

        assertTrue(requestDetailsUrl + " must be a relative path", requestDetailsUrl.startsWith("./" + REQUEST_URI_PREFIX));

    }

    @Test
    public void testFilterSniffyInjected_Context() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");<commit_msg>Method names should not contain underscores<commit_after>package io.sniffy.servlet;

import io.sniffy.BaseTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static io.sniffy.servlet.SnifferFilter.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class SnifferFilterTest extends BaseTest {

    @Mock
    private FilterChain filterChain;

    private MockHttpServletResponse httpServletResponse;
    private MockServletContext servletContext;
    private MockHttpServletRequest requestWithPathAndQueryParameter;
    private MockHttpServletRequest requestWithPath;
    private MockHttpServletRequest requestContextWithoutTrailingSlash;
    private MockHttpServletRequest requestContext;
    private SnifferFilter filter;

    @Before
    public void setupServletApiMocks() {
        httpServletResponse = new MockHttpServletResponse();
        servletContext = new MockServletContext("/petclinic");
        requestWithPathAndQueryParameter = MockMvcRequestBuilders.get("/petclinic/foo/bar?baz").contextPath("/petclinic").buildRequest(servletContext);
        requestWithPath = MockMvcRequestBuilders.get("/petclinic/foo/bar/").contextPath("/petclinic").buildRequest(servletContext);
        requestContextWithoutTrailingSlash = MockMvcRequestBuilders.get("/petclinic").contextPath("/petclinic").buildRequest(servletContext);
        requestContext = MockMvcRequestBuilders.get("/petclinic/").contextPath("/petclinic").buildRequest(servletContext);
        filter = new SnifferFilter();
    }

    private FilterConfig getFilterConfig() {
        FilterConfig filterConfig = mock(FilterConfig.class);
        when(filterConfig.getInitParameter("inject-html")).thenReturn("true");
        when(filterConfig.getInitParameter("exclude-pattern")).thenReturn("^/baz/.*$");
        ServletContext servletContext = mock(ServletContext.class);
        when(filterConfig.getServletContext()).thenReturn(servletContext);
        when(servletContext.getContextPath()).thenReturn("/petclinic");
        return filterConfig;
    }

    @Test
    public void testUnitializedFilter() throws IOException, ServletException {

        SnifferFilter filter = new SnifferFilter();
        filter.setInjectHtml(true);

        filter.doFilter(requestWithPathAndQueryParameter, httpServletResponse, filterChain);

        assertTrue(httpServletResponse.getHeaderNames().contains(HEADER_NUMBER_OF_QUERIES));

    }

    @Test
    public void testFilterSniffyInjected() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");

        SnifferFilter filter = new SnifferFilter();
        filter.init(getFilterConfig());

        filter.doFilter(requestWithPathAndQueryParameter, httpServletResponse, filterChain);

        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(httpServletResponse.getContentAsString().getBytes()));

        String sniffyJsSrc = doc.getElementsByTagName("script").item(0).getAttributes().getNamedItem("src").getNodeValue();

        assertTrue(sniffyJsSrc + " must be a relative path", sniffyJsSrc.startsWith("../" + SNIFFER_URI_PREFIX));

        String requestDetailsUrl = httpServletResponse.getHeader(HEADER_REQUEST_DETAILS);

        assertTrue(requestDetailsUrl + " must be a relative path", requestDetailsUrl.startsWith("../" + REQUEST_URI_PREFIX));
    }

    private void answerWithContent(String actualContent) throws IOException, ServletException {
        doAnswer(invocation -> {
            Thread.sleep(1);
            HttpServletResponse response = (HttpServletResponse) invocation.getArguments()[1];
            response.setContentType("text/html");
            PrintWriter printWriter = response.getWriter();
            printWriter.append(actualContent);
            Thread.sleep(1);
            return null;
        }).when(filterChain).doFilter(any(), any());
    }

    @Test
    public void testFilterSniffyInjectedRequestWithPath() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");

        SnifferFilter filter = new SnifferFilter();
        filter.init(getFilterConfig());

        filter.doFilter(requestWithPath, httpServletResponse, filterChain);

        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(httpServletResponse.getContentAsString().getBytes()));

        String sniffyJsSrc = doc.getElementsByTagName("script").item(0).getAttributes().getNamedItem("src").getNodeValue();

        assertTrue(sniffyJsSrc + " must be a relative path", sniffyJsSrc.startsWith("../../" + SNIFFER_URI_PREFIX));

        String requestDetailsUrl = httpServletResponse.getHeader(HEADER_REQUEST_DETAILS);

        assertTrue(requestDetailsUrl + " must be a relative path", requestDetailsUrl.startsWith("../../" + REQUEST_URI_PREFIX));

    }

    @Test
    public void testFilterSniffyInjectedContextWithoutTrailingSlash() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");

        SnifferFilter filter = new SnifferFilter();
        filter.init(getFilterConfig());

        filter.doFilter(requestContextWithoutTrailingSlash, httpServletResponse, filterChain);

        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(httpServletResponse.getContentAsString().getBytes()));

        Node scriptTag = doc.getElementsByTagName("script").item(0);
        assertNull(scriptTag.getAttributes().getNamedItem("src"));
        assertTrue(scriptTag.getTextContent().contains("document.write"));

        String requestDetailsUrl = httpServletResponse.getHeader(HEADER_REQUEST_DETAILS);

        assertTrue(requestDetailsUrl + " must be a relative path", requestDetailsUrl.startsWith("./" + REQUEST_URI_PREFIX));

    }

    @Test
    public void testFilterSniffyInjectedContext() throws IOException, ServletException, ParserConfigurationException, SAXException {

        answerWithContent("<html><head><title>Title</title></head><body>Hello, World!</body></html>");
{'fraction_non_alphanumeric': 0.10840286446357007, 'fraction_numerical': 0.0010511792917679522, 'mean_word_length': 4.9183514774494554, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3436280', 'n_tokens_mistral': 3953, 'n_tokens_neox': 3887, 'n_words': 654}