/** * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite * contributors * * This file is part of EvoSuite. * * EvoSuite is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3.0 of the License, or * (at your option) any later version. * * EvoSuite is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>. */ package org.evosuite.runtime.javaee.javax.servlet.http; import org.evosuite.runtime.annotation.Constraints; import org.evosuite.runtime.annotation.EvoSuiteAssertionOnly; import org.evosuite.runtime.annotation.EvoSuiteClassExclude; import org.evosuite.runtime.annotation.EvoSuiteInclude; import org.evosuite.runtime.javaee.TestDataJavaEE; import org.evosuite.runtime.javaee.javax.servlet.EvoAsyncContext; import org.evosuite.runtime.javaee.javax.servlet.EvoServletState; import org.evosuite.runtime.vnet.VirtualNetwork; import java.io.BufferedReader; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.Principal; import java.util.*; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpUpgradeHandler; import javax.servlet.http.Part; /** * Class used to create HttpServletRequest to unit test Java EE servlet applications. * * Created by Andrea Arcuri on 20/05/15. */ @EvoSuiteClassExclude public class EvoHttpServletRequest implements HttpServletRequest { public static final String TEXT_XML_CONTENT_FORMAT = "text/xml"; public static final String TEXT_HTML_CONTENT_FORMAT = "text/html"; public static final String MULTIPART_FORM_CONTENT_FORMAT = "multipart/form-data"; private String contextPath; private String servletPath; private Integer requestedSessionId; private HttpMethod method; private String contentType; private String protocol; //network related private String localAddr; private String localName; private int localPort; private String remoteAddr; private String remoteHost; private int remotePort; private Map<String, String[]> parameters; private AsyncContext asyncContext; private Map<String, EvoPart> parts; private String principalName; public EvoHttpServletRequest(){ /* Note: quite a few of these fields could be good to be set by the test cases directly, but they might just increase the search space without any real benefit. Should carefully check what is actually used in practice */ contextPath = "/EvoSuiteContext"; servletPath = "/EvoSuiteServlet"; requestedSessionId = null; asGET(); contentType = null; //TODO check unsure if null only in GET protocol = "HTTP/1.1"; localName = "MockedJavaEEServer"; localAddr = VirtualNetwork.getInstance().dnsResolve(localName); localPort = 80; remoteHost = "MockedRemoteEvoSuiteRequestClient"; remoteAddr = VirtualNetwork.getInstance().dnsResolve(remoteHost); remotePort = 61386; //any would do parameters = new LinkedHashMap<>(); asyncContext = null; parts = new LinkedHashMap<>(); } // ------- super classes overridden methods --------------- @Override public AsyncContext getAsyncContext() throws IllegalStateException { if(asyncContext == null) { throw new IllegalStateException("Async context not initialized"); } return asyncContext; } @EvoSuiteAssertionOnly @Override public boolean isAsyncStarted() { if(asyncContext==null){ //TODO check on asyncContext if "dispatch" or "complete" were called (need new is* method for that) return false; } return true; } @EvoSuiteAssertionOnly @Override public boolean isAsyncSupported() { Servlet sut = EvoServletState.getServlet(); WebServlet annotation = sut.getClass().getAnnotation(WebServlet.class); if(annotation == null){ return false; //TODO: unsure if really correct. need more investigation } return annotation.asyncSupported(); } @Override public AsyncContext startAsync() throws IllegalStateException { if(!isAsyncSupported() || EvoServletState.getResponse().isCommitted()){ /* TODO Need also to handle: - this request is within the scope of a filter - this method is called again without any asynchronous dispatch (resulting from one of the AsyncContext.dispatch methods), is called outside the scope of any such dispatch, or is called again within the scope of the same dispatch */ throw new IllegalStateException("Cannot start async"); } if(asyncContext==null){ asyncContext = new EvoAsyncContext(); } else { //should re-init, as per JavaDoc } return asyncContext; } @Override public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1) throws IllegalStateException { // TODO Auto-generated method stub return null; } @Override public Object getAttribute(String arg0) { // TODO Auto-generated method stub return null; } @Override public Enumeration<String> getAttributeNames() { // TODO Auto-generated method stub return null; } @Override public String getCharacterEncoding() { // TODO Auto-generated method stub return null; } @Override public int getContentLength() { // TODO Auto-generated method stub return 0; } @Override public long getContentLengthLong() { // TODO Auto-generated method stub return 0; } @Override public String getContentType() { TestDataJavaEE.getInstance().accessContentType(); return contentType; } @Override public DispatcherType getDispatcherType() { // TODO Auto-generated method stub return null; } @Override public ServletInputStream getInputStream() throws IOException { // TODO Auto-generated method stub return null; } @Override public String getLocalAddr() { return localAddr; } @Override public String getLocalName() { return localName; } @Override public int getLocalPort() { return localPort; } @Override public Locale getLocale() { // TODO Auto-generated method stub return null; } @Override public Enumeration<Locale> getLocales() { // TODO Auto-generated method stub return null; } @Override public String getParameter(String arg0) { if(arg0 != null){ TestDataJavaEE.getInstance().accessedHttpRequestParameter(arg0); } String[] params = getParameterValues(arg0); if(params != null){ return params[0]; } return null; } @Override public Map<String, String[]> getParameterMap() { /* here all the fuzz is to check if the existence of any specific property is checked for. this is actually done in some of the tested SUTs */ return Collections.unmodifiableMap(new LinkedHashMap<String, String[]>() { { this.putAll(parameters); } @Override public Set<String> keySet() { final Set<String> set = super.keySet(); return Collections.unmodifiableSet(new LinkedHashSet<String>() { { this.addAll(set); } @Override public boolean contains(Object k) { if (!(k instanceof String)) { return false; } String val = (String) k; if (val != null && !val.trim().isEmpty()) { TestDataJavaEE.getInstance().accessedHttpRequestParameter(val); } return super.contains(val); } }); } @Override public boolean containsKey(Object k) { if (!(k instanceof String)) { return false; } String key = (String) k; if (key != null && !key.trim().isEmpty()) { TestDataJavaEE.getInstance().accessedHttpRequestParameter(key); } return super.containsKey(key); } }); } @Override public Enumeration<String> getParameterNames() { return Collections.enumeration(parameters.keySet()); } @Override public String[] getParameterValues(String arg0) { return parameters.get(arg0); } @Override public String getProtocol() { return protocol; } @Override public BufferedReader getReader() throws IOException { // TODO Auto-generated method stub return null; } @Override public String getRealPath(String arg0) { // TODO Auto-generated method stub return null; } @Override public String getRemoteAddr() { return remoteAddr; } @Override public String getRemoteHost() { return remoteHost; } @Override public int getRemotePort() { return remotePort; } @Override public RequestDispatcher getRequestDispatcher(String arg0) { // TODO Auto-generated method stub return null; } @Override public String getScheme() { // TODO Auto-generated method stub return null; } @Override public String getServerName() { // TODO Auto-generated method stub return null; } @Override public int getServerPort() { // TODO Auto-generated method stub return 0; } @Override public ServletContext getServletContext() { // TODO Auto-generated method stub return null; } @Override public boolean isSecure() { // TODO Auto-generated method stub return false; } @Override public void removeAttribute(String arg0) { // TODO Auto-generated method stub } @Override public void setAttribute(String arg0, Object arg1) { // TODO Auto-generated method stub } @Override public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException { // TODO Auto-generated method stub } @Override public boolean authenticate(HttpServletResponse arg0) throws IOException, ServletException { // TODO Auto-generated method stub return false; } @Override public String changeSessionId() throws IllegalStateException{ if(requestedSessionId == null){ throw new IllegalStateException("No current session id"); } requestedSessionId++; return requestedSessionId.toString(); } @Override public String getAuthType() { // TODO Auto-generated method stub return null; } @Override public String getContextPath() { return contextPath; } @Override public Cookie[] getCookies() { // TODO Auto-generated method stub return null; } @Override public long getDateHeader(String arg0) { // TODO Auto-generated method stub return 0; } @Override public String getHeader(String arg0) { // TODO Auto-generated method stub return null; } @Override public Enumeration<String> getHeaderNames() { // TODO Auto-generated method stub return null; } @Override public Enumeration<String> getHeaders(String arg0) { // TODO Auto-generated method stub return null; } @Override public int getIntHeader(String arg0) { // TODO Auto-generated method stub return 0; } @Override public String getMethod() { return method.toString(); } @Override public Part getPart(String arg0) throws IOException, ServletException { if(!MULTIPART_FORM_CONTENT_FORMAT.equals(contentType)){ throw new ServletException("Cannot access parts if request is not of type "+MULTIPART_FORM_CONTENT_FORMAT); } TestDataJavaEE.getInstance().accessPart(arg0); return parts.get(arg0); } @Override public Collection<Part> getParts() throws IOException, ServletException { if(!MULTIPART_FORM_CONTENT_FORMAT.equals(contentType)) { throw new ServletException("Cannot access parts if request is not of type "+MULTIPART_FORM_CONTENT_FORMAT); } TestDataJavaEE.getInstance().accessPart(null); return new ArrayList<Part>(){{addAll(parts.values());}}; } @Override public String getPathInfo() { // TODO Auto-generated method stub return null; } @Override public String getPathTranslated() { // TODO Auto-generated method stub return null; } @Override public String getQueryString() { // TODO Auto-generated method stub return null; } @Override public String getRemoteUser() { // TODO Auto-generated method stub return null; } @Override public String getRequestURI() { return getContextPath()+getServletPath(); } @Override public StringBuffer getRequestURL() { // TODO Auto-generated method stub return null; } @Override public String getRequestedSessionId() { return requestedSessionId == null ? null : requestedSessionId.toString(); } @Override public String getServletPath() { return servletPath; } @Override public HttpSession getSession() { // TODO Auto-generated method stub return null; } @Override public HttpSession getSession(boolean arg0) { // TODO Auto-generated method stub return null; } @Override public Principal getUserPrincipal() { if(principalName == null || principalName.trim().isEmpty()) { return null; } return new Principal() { @Override public String getName() { return principalName; } }; } @Override public boolean isRequestedSessionIdFromCookie() { // TODO Auto-generated method stub return false; } @Override public boolean isRequestedSessionIdFromURL() { // TODO Auto-generated method stub return false; } @Override public boolean isRequestedSessionIdFromUrl() { // TODO Auto-generated method stub return false; } @Override public boolean isRequestedSessionIdValid() { // TODO Auto-generated method stub return false; } @Override public boolean isUserInRole(String arg0) { // TODO Auto-generated method stub return false; } @Override public void login(String arg0, String arg1) throws ServletException { // TODO Auto-generated method stub } @Override public void logout() throws ServletException { // TODO Auto-generated method stub } @Override public <T extends HttpUpgradeHandler> T upgrade(Class<T> arg0) throws IOException, ServletException { // TODO Auto-generated method stub return null; } @Override public String toString() { //TODO: might need more stuff return EvoHttpServletRequest.class.getSimpleName() + " [ " + getMethod() + " " + getRequestURI() + " ]"; } // --------- public methods used only in EvoSuite ------------------- @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asGET","asPUT","as"}) public void asPOST(){ setHttpMethod(HttpMethod.POST); } @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asPOST","asPUT","as"}) public void asGET(){ setHttpMethod(HttpMethod.GET); } @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asGET","asPOST","as"}) public void asPUT(){ setHttpMethod(HttpMethod.PUT); } @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asGET","asPOST","asPUT"}, noNullInputs = true) public void as(HttpMethod m){ setHttpMethod(m); } @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asMultipartFormData","asTextHtml"}, dependOnProperties = TestDataJavaEE.HTTP_REQUEST_CONTENT_TYPE) public void asTextXml(){ setContentType(TEXT_XML_CONTENT_FORMAT); } @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asTextXml","asMultipartFormData"}, dependOnProperties = TestDataJavaEE.HTTP_REQUEST_CONTENT_TYPE) public void asTextHtml(){ setContentType(TEXT_HTML_CONTENT_FORMAT); } @EvoSuiteInclude @Constraints(atMostOnce = true , excludeOthers = {"asTextXml","asTextHtml"}, dependOnProperties = TestDataJavaEE.HTTP_REQUEST_CONTENT_TYPE, after="asPOST") public void asMultipartFormData(){ setContentType(MULTIPART_FORM_CONTENT_FORMAT); } @EvoSuiteInclude @Constraints(dependOnProperties = TestDataJavaEE.HTTP_REQUEST_PARAM, after = "asMultipartFormData") public void addParam(String key, String value) throws IllegalArgumentException { if(key==null || value==null){ throw new IllegalArgumentException("Null input"); } String[] params = parameters.get(key); if(params==null){ params = new String[]{value}; } else { params = Arrays.copyOf(params,params.length+1); params[params.length-1] = value; } parameters.put(key, params); } @EvoSuiteInclude @Constraints(dependOnProperties = TestDataJavaEE.HTTP_REQUEST_PART) public void addPart(EvoPart p){ parts.put(p.getName(), p); } @EvoSuiteInclude @Constraints(dependOnProperties = TestDataJavaEE.HTTP_REQUEST_PRINCIPAL) public void setPrincipalName(String principalName) { this.principalName = principalName; } // --------- private methods ----------------------------------------- private void setHttpMethod(HttpMethod m) throws IllegalArgumentException { if(m == null) { throw new IllegalArgumentException("Null input"); } method = m; } /** * * @param type can be null */ private void setContentType(String type) { contentType = type; } }