From 6da0cb25acd24a37ea9ed134308397308a14af1a Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 23 Dec 2016 14:26:29 +0100 Subject: [PATCH] Unescaping escaped quotes without this change we're escapng an already escaped quotes in a regex with this change we're doing a hack to unescape a double escaped quote fixes #169 --- .../util/DelegatingJsonVerifiable.java | 18 +++++++--- .../MockMvcMethodBodyBuilderSpec.groovy | 36 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java index aff8c210d0..92af31d149 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java @@ -16,13 +16,13 @@ package org.springframework.cloud.contract.verifier.util; +import static org.apache.commons.lang3.StringEscapeUtils.escapeJava; + import java.util.LinkedList; import java.util.regex.Pattern; import com.toomuchcoding.jsonassert.JsonVerifiable; -import static org.apache.commons.lang3.StringEscapeUtils.escapeJava; - /** * Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list * of String method commands that need to be executed to assert JSONs. @@ -191,14 +191,24 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { public MethodBufferingJsonVerifiable matches(String value) { DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.matches(value), this.methodsBuffer); if (this.delegate.isAssertingAValueInArray()) { - readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value)); + readyToCheck.appendMethodWithQuotedValue("matches", escapedHackedJavaText(value)); readyToCheck.methodsBuffer.offer(".value()"); } else { - readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value)); + readyToCheck.appendMethodWithQuotedValue("matches", escapedHackedJavaText(value)); } return readyToCheck; } + /** + * We need to escape the pattern in order for the produced text to be compilable. + * The problem is that sometimes we get quotes that already escaped. If we escape them + * we get code that doesn't compile. That's why we're doing this hack to unescape + * an double escaped text. Related to https://github.com/spring-cloud/spring-cloud-contract/issues/169 + */ + private String escapedHackedJavaText(String value) { + return escapeJava(value).replace("\\\"", "\""); + } + @Override public MethodBufferingJsonVerifiable isEqualTo(Boolean value) { DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer); diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy index 7510a8cd54..099f9000bb 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy @@ -2004,4 +2004,40 @@ World.'''""" "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' } + + @Issue('#169') + def "should escape quotes properly using [#methodBuilderName]"() { + given: + Contract contractDsl = Contract.make { + request { + method 'POST' + url '/foo' + body( + xyz: 'abc' + ) + headers { header('Content-Type', 'application/json;charset=UTF-8') } + } + response { + status 200 + body( + bar: $(producer(regex('some value \u0022with quote\u0022|bar'))) + ) + headers { header('Content-Type': 'application/json;charset=UTF-8') } + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: +// test.contains('assertThatJson(parsedJson).field("bar").matches("some value \\"with quote\\"|bar")') +// and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + where: + //order is inverted cause Intellij didn't parse this properly + methodBuilderName | methodBuilder | expectedAssertion + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + } }