Permalink
Browse files

#60 fixed bug #58 added extension to support more flexible verificati…

…on - and added plugins for coverage and checkstyle however coverage restrictions are not yet set as some classes do not meet the required targets
  • Loading branch information...
1 parent 8aeffb7 commit d370329043040652f2853b9c87287238c7bd30da @jamesdbloom committed Aug 17, 2014
Showing with 1,979 additions and 161 deletions.
  1. +2 −0 build.sh
  2. +205 −0 checkstyle.xml
  3. +10 −6 mockserver-client-java/src/main/java/org/mockserver/client/http/ApacheHttpClient.java
  4. +3 −1 mockserver-client-java/src/main/java/org/mockserver/client/proxy/ProxyClient.java
  5. +69 −5 mockserver-client-java/src/main/java/org/mockserver/client/server/MockServerClient.java
  6. +7 −0 mockserver-client-java/src/test/java/org/mockserver/client/http/ApacheHttpClientTest.java
  7. +124 −1 mockserver-client-java/src/test/java/org/mockserver/client/server/MockServerClientTest.java
  8. +3 −1 mockserver-core/src/main/java/org/mockserver/client/serialization/ExpectationSerializer.java
  9. +13 −11 mockserver-core/src/main/java/org/mockserver/client/serialization/model/ExpectationDTO.java
  10. +24 −22 mockserver-core/src/main/java/org/mockserver/client/serialization/model/HttpRequestDTO.java
  11. +15 −13 mockserver-core/src/main/java/org/mockserver/client/serialization/model/HttpResponseDTO.java
  12. +1 −0 mockserver-core/src/main/java/org/mockserver/matchers/BodyMatcher.java
  13. +130 −0 mockserver-core/src/main/java/org/mockserver/matchers/HttpResponseMatcher.java
  14. +27 −0 mockserver-core/src/main/java/org/mockserver/matchers/IntegerMatcher.java
  15. +0 −8 mockserver-core/src/main/java/org/mockserver/matchers/JsonStringMatcher.java
  16. +2 −9 mockserver-core/src/main/java/org/mockserver/matchers/ParameterStringMatcher.java
  17. +0 −5 mockserver-core/src/main/java/org/mockserver/matchers/RegexStringMatcher.java
  18. +4 −2 mockserver-core/src/main/java/org/mockserver/mock/Expectation.java
  19. +3 −0 mockserver-core/src/main/java/org/mockserver/model/HttpRequest.java
  20. +9 −0 mockserver-core/src/main/java/org/mockserver/model/HttpResponse.java
  21. +3 −1 mockserver-core/src/main/java/org/mockserver/proxy/filters/Filters.java
  22. +3 −3 mockserver-core/src/main/java/org/mockserver/proxy/filters/LogFilter.java
  23. +15 −19 mockserver-core/src/main/java/org/mockserver/socket/KeyStoreFactory.java
  24. +2 −2 mockserver-core/src/main/java/org/mockserver/socket/SSLFactory.java
  25. +1 −0 mockserver-core/src/main/java/org/mockserver/streams/IOStreamUtils.java
  26. +2 −2 ...va/org/mockserver/client/http → mockserver-core/src/main/java/org/mockserver/url}/URLEncoder.java
  27. +22 −0 mockserver-core/src/main/java/org/mockserver/url/URLParser.java
  28. +1 −0 ...erver-client-java → mockserver-core}/src/test/java/org/mockserver/client/http/URLEncoderTest.java
  29. +1 −1 mockserver-core/src/test/java/org/mockserver/client/serialization/HttpRequestSerializerTest.java
  30. +229 −0 mockserver-core/src/test/java/org/mockserver/client/serialization/ObjectMapperFactoryTest.java
  31. +11 −0 mockserver-core/src/test/java/org/mockserver/client/serialization/model/DelayDTOTest.java
  32. +63 −1 mockserver-core/src/test/java/org/mockserver/client/serialization/model/ExpectationDTOTest.java
  33. +151 −0 mockserver-core/src/test/java/org/mockserver/client/serialization/model/HttpRequestDTOTest.java
  34. +117 −0 mockserver-core/src/test/java/org/mockserver/client/serialization/model/HttpResponseDTOTest.java
  35. +68 −5 mockserver-core/src/test/java/org/mockserver/matchers/HttpRequestMatcherTest.java
  36. +201 −0 mockserver-core/src/test/java/org/mockserver/matchers/HttpResponseMatcherTest.java
  37. +25 −0 mockserver-core/src/test/java/org/mockserver/matchers/IntegerMatcherTest.java
  38. +33 −0 mockserver-core/src/test/java/org/mockserver/mock/ExpectationTest.java
  39. +13 −1 mockserver-core/src/test/java/org/mockserver/model/CookieTest.java
  40. +13 −1 mockserver-core/src/test/java/org/mockserver/model/HeaderTest.java
  41. +13 −1 mockserver-core/src/test/java/org/mockserver/model/ParameterTest.java
  42. +43 −0 mockserver-core/src/test/java/org/mockserver/url/URLParserTest.java
  43. +2 −3 mockserver-examples/src/main/java/org/mockserver/servicebackend/BookServer.java
  44. +55 −1 mockserver-integration-testing/pom.xml
  45. +3 −1 mockserver-netty/src/main/java/org/mockserver/cli/Main.java
  46. +7 −1 mockserver-netty/src/main/java/org/mockserver/mappers/NettyToMockServerRequestMapper.java
  47. +5 −3 mockserver-netty/src/main/java/org/mockserver/mockserver/MockServer.java
  48. +6 −5 mockserver-netty/src/main/java/org/mockserver/model/NettyHttpRequest.java
  49. +15 −5 mockserver-netty/src/main/java/org/mockserver/proxy/http/HttpProxy.java
  50. +1 −1 mockserver-netty/src/main/java/org/mockserver/proxy/http/relay/BasicHttpDecoder.java
  51. +5 −4 mockserver-netty/src/main/java/org/mockserver/proxy/http/relay/RelayConnectHandler.java
  52. +13 −0 mockserver-netty/src/test/java/org/mockserver/mappers/NettyToMockServerRequestMapperTest.java
  53. +2 −4 mockserver-netty/src/test/java/org/mockserver/model/NettyHttpRequestTest.java
  54. +182 −10 pom.xml
  55. +2 −2 www.mock-server.com/index.html
View
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+export MAVEN_OPTS='-XX:MaxPermSize=1024m -Xmx1024m'
+
# java 1.7 build
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home
echo
View
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!-- This is a checkstyle configuration file. For descriptions of
+what the following rules do, please see the checkstyle configuration
+page at http://checkstyle.sourceforge.net/config.html -->
+
+<module name="Checker">
+
+ <module name="FileTabCharacter">
+ <!-- Checks that there are no tab characters in the file.
+ -->
+ </module>
+
+ <module name="RegexpSingleline">
+ <!-- Checks that FIXME is not used in comments. TODO is preferred.
+ -->
+ <property name="format" value="((//.*)|(\*.*))FIXME"/>
+ <property name="message" value='TODO is preferred to FIXME. e.g. "TODO(johndoe): Refactor when v2 is released."'/>
+ </module>
+
+ <module name="RegexpSingleline">
+ <!-- Checks that TODOs are named. (Actually, just that they are followed
+ by an open paren.)
+ -->
+ <property name="format" value="((//.*)|(\*.*))TODO[^(]"/>
+ <property name="message" value='All TODOs should be named. e.g. "TODO(johndoe): Refactor when v2 is released."'/>
+ </module>
+
+
+ <!-- All Java AST specific tests live under TreeWalker module. -->
+ <module name="TreeWalker">
+
+ <!--
+
+ IMPORT CHECKS
+
+ -->
+
+ <module name="RedundantImport">
+ <!-- Checks for redundant import statements. -->
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="ImportOrder">
+ <!-- This ensures that static imports go last. -->
+ <property name="option" value="under"/>
+ <property name="ordered" value="false"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <!--
+ NAMING CHECKS
+ -->
+
+ <!-- Item 38 - Adhere to generally accepted naming conventions -->
+
+ <module name="PackageName">
+ <!-- Validates identifiers for package names against the
+ supplied expression. -->
+ <!-- Here the default checkstyle rule restricts package name parts to
+ seven characters, this is not in line with common practice at Google.
+ -->
+ <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="StaticVariableNameCheck">
+ <!-- Validates static, non-final fields against the supplied expression "^[a-z][a-zA-Z0-9]*_?$". -->
+ <metadata name="altname" value="StaticVariableName"/>
+ <property name="applyToPublic" value="true"/>
+ <property name="applyToProtected" value="true"/>
+ <property name="applyToPackage" value="true"/>
+ <property name="applyToPrivate" value="true"/>
+ <property name="format" value="^[a-z][a-zA-Z0-9]*_?$"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="MemberNameCheck">
+ <!-- Validates non-static members against the supplied expression. -->
+ <metadata name="altname" value="MemberName"/>
+ <property name="applyToPublic" value="true"/>
+ <property name="applyToProtected" value="true"/>
+ <property name="applyToPackage" value="true"/>
+ <property name="applyToPrivate" value="true"/>
+ <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="MethodNameCheck">
+ <!-- Validates identifiers for method names. -->
+ <metadata name="altname" value="MethodName"/>
+ <property name="format" value="^[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <!--
+
+ LENGTH and CODING CHECKS
+
+ -->
+
+ <module name="LeftCurly">
+ <!-- Checks for placement of the left curly brace ('{'). -->
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="RightCurly">
+ <!-- Checks right curlies on CATCH, ELSE, and TRY blocks are on
+ the same line. e.g., the following example is fine:
+ <pre>
+ if {
+ ...
+ } else
+ </pre>
+ -->
+ <!-- This next example is not fine:
+ <pre>
+ if {
+ ...
+ }
+ else
+ </pre>
+ -->
+ <property name="option" value="same"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <!-- Checks for braces around if and else blocks -->
+ <module name="NeedBraces">
+ <property name="tokens" value="LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="UpperEll">
+ <!-- Checks that long constants are defined with an upper ell.-->
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="FallThrough">
+ <!-- Warn about falling through to the next case statement. Similar to
+ javac -Xlint:fallthrough, but the check is suppressed if a single-line comment
+ on the last non-blank line preceding the fallen-into case contains 'fall through' (or
+ some other variants which we don't publicized to promote consistency).
+ -->
+ <property name="reliefPattern" value="fall through|Fall through|fallthru|Fallthru|falls through|Falls through|fallthrough|Fallthrough|No break|NO break|no break|continue on"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <!--
+
+ WHITESPACE CHECKS
+
+ -->
+
+ <module name="WhitespaceAround">
+ <!-- Checks that various tokens are surrounded by whitespace.
+ This includes most binary operators and keywords followed
+ by regular or curly braces.
+ -->
+ <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR,
+ BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN,
+ EQUAL, GE, GT, LAND, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
+ LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
+ LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,
+ MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
+ SL, SL_ASSIGN, SR_ASSIGN, STAR, STAR_ASSIGN"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="WhitespaceAfter">
+ <!-- Checks that commas, semicolons and typecasts are followed by
+ whitespace.
+ -->
+ <property name="tokens" value="COMMA, SEMI, TYPECAST"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="NoWhitespaceAfter">
+ <!-- Checks that there is no whitespace after various unary operators.
+ Linebreaks are allowed.
+ -->
+ <property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS"/>
+ <property name="allowLineBreaks" value="true"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="NoWhitespaceBefore">
+ <!-- Checks that there is no whitespace before various unary operators.
+ Linebreaks are allowed.
+ -->
+ <property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
+ <property name="allowLineBreaks" value="true"/>
+ <property name="severity" value="error"/>
+ </module>
+
+ <module name="ParenPad">
+ <!-- Checks that there is no whitespace before close parens or after
+ open parens.
+ -->
+ <property name="severity" value="error"/>
+ </module>
+
+ </module>
+</module>
@@ -1,5 +1,6 @@
package org.mockserver.client.http;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import io.netty.handler.codec.http.QueryStringDecoder;
import org.apache.commons.lang3.StringUtils;
@@ -23,6 +24,7 @@
import org.mockserver.mappers.ApacheHttpClientToMockServerResponseMapper;
import org.mockserver.model.*;
import org.mockserver.socket.SSLFactory;
+import org.mockserver.url.URLEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,6 +41,12 @@
*/
public class ApacheHttpClient {
+ @VisibleForTesting
+ static final TrustStrategy trustStrategy = new TrustStrategy() {
+ public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ return true;
+ }
+ };
private static final Logger logger = LoggerFactory.getLogger(ApacheHttpClient.class);
private ApacheHttpClientToMockServerResponseMapper apacheHttpClientToMockServerResponseMapper = new ApacheHttpClientToMockServerResponseMapper();
private CloseableHttpClient httpClient;
@@ -51,17 +59,13 @@ public ApacheHttpClient(boolean isSecure) {
.setSslcontext(
SSLContexts
.custom()
- .loadTrustMaterial(SSLFactory.getInstance().buildKeyStore(), new TrustStrategy() {
- public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- return true;
- }
- })
+ .loadTrustMaterial(SSLFactory.getInstance().buildKeyStore(), trustStrategy)
.build()
)
.setHostnameVerifier(new AllowAllHostnameVerifier());
}
- // TODO the section below if commented out as it is still experimental
+ // TODO(jamesdbloom) the section below if commented out as it is still experimental
// System.getProperty("http.keepAlive", "false");
// httpClientBuilder
// .setKeepAliveStrategy(new ConnectionKeepAliveStrategy() {
@@ -145,7 +145,9 @@ public ProxyClient verify(HttpRequest httpRequest) throws AssertionError {
* @throws AssertionError if the request has not been found
*/
public ProxyClient verify(HttpRequest httpRequest, Times times) throws AssertionError {
- if (httpRequest == null) throw new IllegalArgumentException("verify(HttpRequest) requires a non null HttpRequest object");
+ if (httpRequest == null) {
+ throw new IllegalArgumentException("verify(HttpRequest) requires a non null HttpRequest object");
+ }
Expectation[] expectations = retrieveAsExpectations(httpRequest);
if (expectations == null) {
@@ -4,12 +4,17 @@
import org.mockserver.client.http.ApacheHttpClient;
import org.mockserver.client.serialization.ExpectationSerializer;
import org.mockserver.client.serialization.HttpRequestSerializer;
+import org.mockserver.matchers.HttpResponseMatcher;
import org.mockserver.matchers.Times;
import org.mockserver.mock.Expectation;
import org.mockserver.model.HttpRequest;
+import org.mockserver.model.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* @author jamesdbloom
*/
@@ -46,8 +51,12 @@ public MockServerClient(String host, int port) {
* @param contextPath the context path that the MockServer war is deployed to
*/
public MockServerClient(String host, int port, String contextPath) {
- if (StringUtils.isEmpty(host)) throw new IllegalArgumentException("Host can not be null or empty");
- if (contextPath == null) throw new IllegalArgumentException("ContextPath can not be null");
+ if (StringUtils.isEmpty(host)) {
+ throw new IllegalArgumentException("Host can not be null or empty");
+ }
+ if (contextPath == null) {
+ throw new IllegalArgumentException("ContextPath can not be null");
+ }
this.port = port;
this.uriBase = "http://" + host + ":" + port + (contextPath.length() > 0 && !contextPath.startsWith("/") ? "/" : "") + contextPath;
this.apacheHttpClient = new ApacheHttpClient(false);
@@ -199,9 +208,40 @@ public MockServerClient verify(HttpRequest... httpRequests) throws AssertionErro
* @throws AssertionError if the request has not been found
*/
public MockServerClient verify(HttpRequest httpRequest, org.mockserver.client.proxy.Times times) throws AssertionError {
- if (httpRequest == null) throw new IllegalArgumentException("verify(HttpRequest) requires a non null HttpRequest object");
+ return verify(httpRequest, null, times);
+ }
- Expectation[] expectations = retrieveAsExpectations(httpRequest);
+ /**
+ * Verify a request has been sent for a specific expected response example:
+ *
+ * mockServerClient
+ * .verify(
+ * request()
+ * .withPath("/some_path")
+ * .withBody("some_request_body"),
+ * Times.exactly(3)
+ * );
+ *
+ * This version is useful if multiple requests have been configured with different
+ * responses the needs to confirm that an exact response has been received.
+ *
+ * Times supports multiple static factory methods:
+ *
+ * once() - verify the request was only received once
+ * exactly(n) - verify the request was only received exactly n times
+ * atLeast(n) - verify the request was only received at least n times
+ *
+ * @param httpRequest the http request that must be matched for this verification to pass
+ * @param httpResponse the http response that must be matched for this verification to pass
+ * @param times the number of times this request must be matched
+ * @throws AssertionError if the request has not been found
+ */
+ public MockServerClient verify(HttpRequest httpRequest, HttpResponse httpResponse, org.mockserver.client.proxy.Times times) throws AssertionError {
+ if (httpRequest == null) {
+ throw new IllegalArgumentException("verify(HttpRequest) requires a non null HttpRequest object");
+ }
+
+ Expectation[] expectations = retrieveAsExpectations(httpRequest, httpResponse);
if (expectations == null) {
throw new AssertionError("Expected " + httpRequestSerializer.serialize(httpRequest) + butFoundAssertionErrorMessage());
}
@@ -229,7 +269,31 @@ private String butFoundAssertionErrorMessage() {
* @return an array of all expectations that have been recorded by the proxy
*/
public Expectation[] retrieveAsExpectations(HttpRequest httpRequest) {
- return expectationSerializer.deserializeArray(apacheHttpClient.sendPUTRequest(uriBase, "/retrieve", (httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "")));
+ return retrieveAsExpectations(httpRequest, null);
+ }
+
+ /**
+ * Retrieve the recorded requests that match the httpRequest parameter as expectations, use null for the parameter to retrieve all requests
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
+ * @param httpResponse the http response that is matched against when deciding whether to return each expectation, use null for the parameter to retrieve for all requests
+ * @return an array of all expectations that have been recorded by the proxy
+ */
+ public Expectation[] retrieveAsExpectations(HttpRequest httpRequest, HttpResponse httpResponse) {
+ Expectation[] expectations = expectationSerializer.deserializeArray(apacheHttpClient.sendPUTRequest(uriBase, "/retrieve", (httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "")));
+
+ if (httpResponse != null) {
+ List<Expectation> matchingExpectations = new ArrayList<Expectation>();
+ HttpResponseMatcher httpResponseMatcher = new HttpResponseMatcher(httpResponse);
+ for (Expectation expectation : expectations) {
+ if (httpResponseMatcher.matches(expectation.getHttpResponse(false))) {
+ matchingExpectations.add(expectation);
+ }
+ }
+ expectations = matchingExpectations.toArray(new Expectation[matchingExpectations.size()]);
+ }
+
+ return expectations;
}
/**
Oops, something went wrong.

0 comments on commit d370329

Please sign in to comment.