org.htmlunit.MockWebConnection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xlt Show documentation
Show all versions of xlt Show documentation
XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.
/*
* Copyright (c) 2002-2024 Gargoyle Software Inc.
*
* 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
* https://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.
*/
package org.htmlunit;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.htmlunit.util.MimeType;
import org.htmlunit.util.NameValuePair;
/**
* A fake {@link WebConnection} designed to mock out the actual HTTP connections.
*
* @author Mike Bowler
* @author Noboru Sinohara
* @author Marc Guillemot
* @author Brad Clarke
* @author Ahmed Ashour
* @author Ronald Brill
*/
public class MockWebConnection implements WebConnection {
private static final Log LOG = LogFactory.getLog(MockWebConnection.class);
private final Map throwableMap_ = new HashMap<>();
private final Map responseMap_ = new HashMap<>();
private RawResponseData defaultResponse_;
private WebRequest lastRequest_;
private int requestCount_;
private final List requestedUrls_ = Collections.synchronizedList(new ArrayList<>());
/**
* Contains the raw data configured for a response.
*/
public static class RawResponseData {
private final List headers_;
private final byte[] byteContent_;
private final String stringContent_;
private final int statusCode_;
private final String statusMessage_;
private Charset charset_;
RawResponseData(final byte[] byteContent, final int statusCode, final String statusMessage,
final String contentType, final List headers) {
byteContent_ = byteContent;
stringContent_ = null;
statusCode_ = statusCode;
statusMessage_ = statusMessage;
headers_ = compileHeaders(headers, contentType);
}
RawResponseData(final String stringContent, final Charset charset, final int statusCode,
final String statusMessage, final String contentType, final List headers) {
byteContent_ = null;
charset_ = charset;
stringContent_ = stringContent;
statusCode_ = statusCode;
statusMessage_ = statusMessage;
headers_ = compileHeaders(headers, contentType);
}
private static List compileHeaders(final List headers, final String contentType) {
final List compiledHeaders = new ArrayList<>();
if (headers != null) {
compiledHeaders.addAll(headers);
}
if (contentType != null) {
compiledHeaders.add(new NameValuePair(HttpHeader.CONTENT_TYPE, contentType));
}
return compiledHeaders;
}
WebResponseData asWebResponseData() {
final byte[] content;
if (byteContent_ != null) {
content = byteContent_;
}
else if (stringContent_ == null) {
content = new byte[] {};
}
else {
content = stringContent_.getBytes(charset_);
}
return new WebResponseData(content, statusCode_, statusMessage_, headers_);
}
/**
* Gets the configured headers.
* @return the headers
*/
public List getHeaders() {
return headers_;
}
/**
* Gets the configured content bytes.
* @return {@code null} if a String content has been configured
*/
public byte[] getByteContent() {
return byteContent_;
}
/**
* Gets the configured content String.
* @return {@code null} if a byte content has been configured
*/
public String getStringContent() {
return stringContent_;
}
/**
* Gets the configured status code.
* @return the status code
*/
public int getStatusCode() {
return statusCode_;
}
/**
* Gets the configured status message.
* @return the message
*/
public String getStatusMessage() {
return statusMessage_;
}
/**
* Gets the configured charset.
* @return {@code null} for byte content
*/
public Charset getCharset() {
return charset_;
}
}
/**
* {@inheritDoc}
*/
@Override
public WebResponse getResponse(final WebRequest request) throws IOException {
final RawResponseData rawResponse = getRawResponse(request);
return new WebResponse(rawResponse.asWebResponseData(), request, 0);
}
/**
* Gets the raw response configured for the request.
* @param request the request
* @return the raw response
* @throws IOException if defined
*/
public RawResponseData getRawResponse(final WebRequest request) throws IOException {
final URL url = request.getUrl();
if (LOG.isDebugEnabled()) {
LOG.debug("Getting response for " + url.toExternalForm());
}
lastRequest_ = request;
requestCount_++;
requestedUrls_.add(url);
String urlString = url.toExternalForm();
final IOException throwable = throwableMap_.get(urlString);
if (throwable != null) {
throw throwable;
}
RawResponseData rawResponse = responseMap_.get(urlString);
if (rawResponse == null) {
// try to find without query params
final int queryStart = urlString.lastIndexOf('?');
if (queryStart > -1) {
urlString = urlString.substring(0, queryStart);
rawResponse = responseMap_.get(urlString);
}
// fall back to default
if (rawResponse == null) {
rawResponse = defaultResponse_;
if (rawResponse == null) {
throw new IllegalStateException("No response specified that can handle URL "
+ request.getHttpMethod()
+ " [" + urlString + "]");
}
}
}
return rawResponse;
}
/**
* Gets the list of requested URLs.
* @return the list of relative URLs
*/
public List getRequestedUrls() {
return Collections.unmodifiableList(requestedUrls_);
}
/**
* Gets the list of requested URLs relative to the provided URL.
* @param relativeTo what should be removed from the requested URLs.
* @return the list of relative URLs
*/
public List getRequestedUrls(final URL relativeTo) {
final String baseUrl = relativeTo.toString();
final List response = new ArrayList<>();
for (final URL url : requestedUrls_) {
String s = url.toString();
if (s.startsWith(baseUrl)) {
s = s.substring(baseUrl.length());
}
response.add(s);
}
return Collections.unmodifiableList(response);
}
/**
* Returns the method that was used in the last call to submitRequest().
*
* @return the method that was used in the last call to submitRequest()
*/
public HttpMethod getLastMethod() {
return lastRequest_.getHttpMethod();
}
/**
* Returns the parameters that were used in the last call to submitRequest().
*
* @return the parameters that were used in the last call to submitRequest()
*/
public List getLastParameters() {
return lastRequest_.getRequestParameters();
}
/**
* Sets the response that will be returned when the specified URL is requested.
* @param url the URL that will return the given response
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
* @param headers the response headers to return
*/
public void setResponse(final URL url, final String content, final int statusCode,
final String statusMessage, final String contentType,
final List headers) {
setResponse(
url,
content,
statusCode,
statusMessage,
contentType,
ISO_8859_1,
headers);
}
/**
* Sets the response that will be returned when the specified URL is requested.
* @param url the URL that will return the given response
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
* @param charset the charset
* @param headers the response headers to return
*/
public void setResponse(final URL url, final String content, final int statusCode,
final String statusMessage, final String contentType, final Charset charset,
final List headers) {
final RawResponseData responseEntry = buildRawResponseData(content, charset, statusCode, statusMessage,
contentType, headers);
responseMap_.put(url.toExternalForm(), responseEntry);
}
/**
* Sets the exception that will be thrown when the specified URL is requested.
* @param url the URL that will force the exception
* @param throwable the Throwable
*/
public void setThrowable(final URL url, final IOException throwable) {
throwableMap_.put(url.toExternalForm(), throwable);
}
/**
* Sets the response that will be returned when the specified URL is requested.
* @param url the URL that will return the given response
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
* @param headers the response headers to return
*/
public void setResponse(final URL url, final byte[] content, final int statusCode,
final String statusMessage, final String contentType,
final List headers) {
final RawResponseData responseEntry = buildRawResponseData(content, statusCode, statusMessage, contentType,
headers);
responseMap_.put(url.toExternalForm(), responseEntry);
}
private static RawResponseData buildRawResponseData(final byte[] content, final int statusCode,
final String statusMessage, final String contentType, final List headers) {
return new RawResponseData(content, statusCode, statusMessage, contentType, headers);
}
private static RawResponseData buildRawResponseData(final String content, Charset charset, final int statusCode,
final String statusMessage, final String contentType, final List headers) {
if (charset == null) {
charset = ISO_8859_1;
}
return new RawResponseData(content, charset, statusCode, statusMessage, contentType, headers);
}
/**
* Convenient method that is the same as calling
* {@link #setResponse(URL,String,int,String,String,List)} with a status
* of "200 OK", a content type of "text/html" and no additional headers.
*
* @param url the URL that will return the given response
* @param content the content to return
*/
public void setResponse(final URL url, final String content) {
setResponse(url, content, 200, "OK", MimeType.TEXT_HTML, null);
}
/**
* Convenient method that is the same as calling
* {@link #setResponse(URL,String,int,String,String,List)} with a status
* of "200 OK" and no additional headers.
*
* @param url the URL that will return the given response
* @param content the content to return
* @param contentType the content type to return
*/
public void setResponse(final URL url, final String content, final String contentType) {
setResponse(url, content, 200, "OK", contentType, null);
}
/**
* Convenient method that is the same as calling
* {@link #setResponse(URL, String, int, String, String, Charset, List)} with a status
* of "200 OK" and no additional headers.
*
* @param url the URL that will return the given response
* @param content the content to return
* @param contentType the content type to return
* @param charset the charset
*/
public void setResponse(final URL url, final String content, final String contentType, final Charset charset) {
setResponse(url, content, 200, "OK", contentType, charset, null);
}
/**
* Specify a generic HTML page that will be returned when the given URL is specified.
* The page will contain only minimal HTML to satisfy the HTML parser but will contain
* the specified title so that tests can check for titleText.
*
* @param url the URL that will return the given response
* @param title the title of the page
*/
public void setResponseAsGenericHtml(final URL url, final String title) {
final String content = "" + title + " ";
setResponse(url, content);
}
/**
* Sets the response that will be returned when a URL is requested that does
* not have a specific content set for it.
*
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
*/
public void setDefaultResponse(final String content, final int statusCode,
final String statusMessage, final String contentType) {
defaultResponse_ = buildRawResponseData(content, null, statusCode, statusMessage, contentType, null);
}
/**
* Sets the response that will be returned when a URL is requested that does
* not have a specific content set for it.
*
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
*/
public void setDefaultResponse(final byte[] content, final int statusCode,
final String statusMessage, final String contentType) {
defaultResponse_ = buildRawResponseData(content, statusCode, statusMessage, contentType, null);
}
/**
* Sets the response that will be returned when a URL is requested that does
* not have a specific content set for it.
*
* @param content the content to return
*/
public void setDefaultResponse(final String content) {
setDefaultResponse(content, 200, "OK", MimeType.TEXT_HTML);
}
/**
* Sets the response that will be returned when a URL is requested that does
* not have a specific content set for it.
*
* @param content the content to return
* @param contentType the content type to return
*/
public void setDefaultResponse(final String content, final String contentType) {
setDefaultResponse(content, 200, "OK", contentType, null);
}
/**
* Sets the response that will be returned when a URL is requested that does
* not have a specific content set for it.
*
* @param content the content to return
* @param contentType the content type to return
* @param charset the charset
*/
public void setDefaultResponse(final String content, final String contentType, final Charset charset) {
setDefaultResponse(content, 200, "OK", contentType, charset, null);
}
/**
* Sets the response that will be returned when the specified URL is requested.
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
* @param headers the response headers to return
*/
public void setDefaultResponse(final String content, final int statusCode,
final String statusMessage, final String contentType,
final List headers) {
defaultResponse_ = buildRawResponseData(content, null, statusCode, statusMessage, contentType, headers);
}
/**
* Sets the response that will be returned when the specified URL is requested.
* @param content the content to return
* @param statusCode the status code to return
* @param statusMessage the status message to return
* @param contentType the content type to return
* @param charset the charset
* @param headers the response headers to return
*/
public void setDefaultResponse(final String content, final int statusCode,
final String statusMessage, final String contentType, final Charset charset,
final List headers) {
defaultResponse_ = buildRawResponseData(content, charset, statusCode, statusMessage, contentType, headers);
}
/**
* Returns the additional headers that were used in the in the last call
* to {@link #getResponse(WebRequest)}.
* @return the additional headers that were used in the in the last call
* to {@link #getResponse(WebRequest)}
*/
public Map getLastAdditionalHeaders() {
return lastRequest_.getAdditionalHeaders();
}
/**
* Returns the {@link WebRequest} that was used in the in the last call
* to {@link #getResponse(WebRequest)}.
* @return the {@link WebRequest} that was used in the in the last call
* to {@link #getResponse(WebRequest)}
*/
public WebRequest getLastWebRequest() {
return lastRequest_;
}
/**
* Returns the number of requests made to this mock web connection.
* @return the number of requests made to this mock web connection
*/
public int getRequestCount() {
return requestCount_;
}
/**
* Indicates if a response has already been configured for this URL.
* @param url the url
* @return {@code false} if no response has been configured
*/
public boolean hasResponse(final URL url) {
return responseMap_.containsKey(url.toExternalForm());
}
/**
* {@inheritDoc}
*/
@Override
public void close() {
clear();
}
/**
* Resets this.
*/
public void clear() {
throwableMap_.clear();
responseMap_.clear();
defaultResponse_ = null;
lastRequest_ = null;
requestCount_ = 0;
requestedUrls_.clear();
}
}