escapes all generated strings by Xeger so that the code is java compatible

related to gh-589

fixes gh-588
This commit is contained in:
Marcin Grzejszczak
2018-03-21 11:35:29 +01:00
parent f70c1dbfdd
commit 4e08f77996
7 changed files with 58 additions and 8 deletions

View File

@@ -16,14 +16,13 @@
package org.springframework.cloud.contract.spec.internal
import java.util.regex.Pattern
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import repackaged.nl.flotsam.xeger.Xeger
import java.util.regex.Pattern
/**
* Represents an input for messaging. The input can be a message or some
* action inside the application.

View File

@@ -20,6 +20,7 @@ import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import org.apache.commons.lang3.StringEscapeUtils
import repackaged.nl.flotsam.xeger.Xeger
import java.util.regex.Pattern
@@ -74,7 +75,7 @@ class OutputMessage extends Common {
DslProperty value(ServerDslProperty server) {
Object value = server.clientValue
if (server.clientValue instanceof Pattern) {
value = new Xeger(((Pattern)server.clientValue).pattern()).generate()
value = StringEscapeUtils.escapeJava(new Xeger(((Pattern)server.clientValue).pattern()).generate())
}
return new DslProperty(value, server.serverValue)
}

View File

@@ -20,6 +20,8 @@ import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import org.apache.commons.lang3.StringEscapeUtils
import org.springframework.cloud.contract.spec.util.RegexpUtils
import repackaged.nl.flotsam.xeger.Xeger
@@ -186,7 +188,7 @@ class Request extends Common {
DslProperty value(ClientDslProperty client) {
Object clientValue = client.clientValue
if (client.clientValue instanceof Pattern && client.isSingleValue()) {
clientValue = new Xeger(((Pattern)client.clientValue).pattern()).generate()
clientValue = StringEscapeUtils.escapeJava(new Xeger(((Pattern)client.clientValue).pattern()).generate())
} else if (client.clientValue instanceof Pattern && !client.isSingleValue()) {
clientValue = client.serverValue
}

View File

@@ -16,14 +16,15 @@
package org.springframework.cloud.contract.spec.internal
import java.util.regex.Pattern
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import org.springframework.cloud.contract.spec.util.RegexpUtils
import repackaged.nl.flotsam.xeger.Xeger
import java.util.regex.Pattern
import org.springframework.cloud.contract.spec.util.RegexpUtils
/**
* Represents the response side of the HTTP communication
*

View File

@@ -21,7 +21,7 @@ import groovy.transform.CompileStatic
import java.util.regex.Pattern
/**
* Useful utility methods to work with regular expresisons
* Useful utility methods to work with regular expressions
*
* @since 1.0.2
*/

View File

@@ -27,6 +27,7 @@ import dk.brics.automaton.Automaton;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.State;
import dk.brics.automaton.Transition;
import org.apache.commons.lang3.StringUtils;
/**
* An object that will generate text from a regular expression. In a way, it's the opposite of a regular expression
@@ -59,6 +60,15 @@ public class Xeger {
.replace("\\s", "[ \t\r\n]"); // Used s="White"Space
this.automaton = new RegExp(pattern).toAutomaton();
this.random = random;
String generatedCharsSysProp = System
.getProperty("springCloudContractGeneratedCharsFromRegex");
String generatedCharsEnvVar = System
.getenv("SPRING_CLOUD_CONTRACT_GENERATED_CHARS_FROM_REGEX");
if (StringUtils.isNotEmpty(generatedCharsSysProp)) {
ITERATION_LIMIT = Integer.parseInt(generatedCharsSysProp);
} else if (StringUtils.isNotEmpty(generatedCharsEnvVar)) {
ITERATION_LIMIT = Integer.parseInt(generatedCharsEnvVar);
}
}
/**

View File

@@ -141,6 +141,43 @@ DocumentContext parsedJson = JsonPath.parse(json);
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
}
@Issue('#521')
def "should always escape generated chars [#methodBuilderName]"() {
expect:
[1..200].each {
Contract contractDsl = Contract.make {
request {
method GET()
urlPath('/v1/users') {
queryParameters {
parameter 'userId': value(regex(nonBlank()))
}
}
}
response {
status 200
body([
ok: value(regex(nonBlank()))
])
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
assert !test.contains('REGEXP>>')
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
}
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
}
@Issue('#269')
def "should work with execute and keys with dots [#methodBuilderName]"() {
given: