Skip to content

Commit

Permalink
chore: slight performance improvement on the JSON parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Ronald Holshausen committed Jun 14, 2020
1 parent dde272b commit 801cb88
Show file tree
Hide file tree
Showing 23 changed files with 359 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void provider2Fails() throws IOException {
mockTestProvider2.validateResultWith((result, t) -> {
assertThat(t, is(instanceOf(AssertionError.class)));
assertThat(t.getMessage(), is("The following mismatched requests occurred:\n" +
"BodyMismatch: Expected 'larry' but received 'farry'"));
"BodyMismatch: Expected 'larry' (String) but received 'farry' (String)"));
assertThat(result, is(instanceOf(PactVerificationResult.Mismatches.class)));
PactVerificationResult.Mismatches error = (PactVerificationResult.Mismatches) result;
assertThat(error.getMismatches(), hasSize(1));
Expand Down Expand Up @@ -152,7 +152,7 @@ public void bothprovidersFail() throws IOException {
mockTestProvider2.validateResultWith((result, t) -> {
assertThat(t, is(instanceOf(AssertionError.class)));
assertThat(t.getMessage(), is("The following mismatched requests occurred:\n" +
"BodyMismatch: Expected 'larry' but received 'farry'"));
"BodyMismatch: Expected 'larry' (String) but received 'farry' (String)"));
assertThat(result, is(instanceOf(PactVerificationResult.Mismatches.class)));
PactVerificationResult.Mismatches error = (PactVerificationResult.Mismatches) result;
assertThat(error.getMismatches(), hasSize(1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object JsonBodyMatcher : BodyMatcher, KLogging() {

private fun valueOf(value: Any?) = when (value) {
is String -> "'$value'"
is JsonValue.StringValue -> "'${value.value}'"
is JsonValue.StringValue -> "'${value.asString()}'"
is JsonValue -> value.serialise()
null -> "null"
else -> value.toString()
Expand All @@ -47,7 +47,7 @@ object JsonBodyMatcher : BodyMatcher, KLogging() {
value is List<*> -> "List"
value is JsonValue.Array -> "List"
value is JsonValue.Null -> "Null"
value is JsonValue && (value.isNumber || value.isString || value.isBoolean) -> "Primitive"
value is JsonValue -> value.name
value == null -> "Null"
else -> value.javaClass.simpleName
}
Expand Down Expand Up @@ -190,7 +190,7 @@ object JsonBodyMatcher : BodyMatcher, KLogging() {
if (expected == actual) {
emptyList()
} else {
listOf(BodyMismatch(expected, actual, "Expected ${valueOf(expected)} but received ${valueOf(actual)}",
listOf(BodyMismatch(expected, actual, "Expected ${valueOf(expected)} (${typeOf(expected)}) but received ${valueOf(actual)} (${typeOf(actual)})",
path.joinToString(".")))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,11 @@ fun matchDecimal(actual: Any?): Boolean {
actual is Float -> true
actual is Double -> true
actual is BigDecimal && (actual == BigDecimal.ZERO || actual.scale() > 0) -> true
actual is JsonValue.Decimal && (actual.value == BigDecimal.ZERO || actual.value.scale() > 0) -> true
actual is JsonValue.Integer -> decimalRegex.matches(actual.toString())
actual is JsonValue.Decimal -> {
val bigDecimal = actual.toBigDecimal()
bigDecimal == BigDecimal.ZERO || bigDecimal.scale() > 0
}
actual is JsonValue.Integer -> decimalRegex.matches(actual.asString())
else -> false
}
logger.debug { "${valueOf(actual)} (${typeOf(actual)}) matches decimal number -> $result" }
Expand All @@ -256,7 +259,7 @@ fun matchInteger(actual: Any?): Boolean {
actual is BigInteger -> true
actual is JsonValue.Integer -> true
actual is BigDecimal && actual.scale() == 0 -> true
actual is JsonValue.Decimal -> integerRegex.matches(actual.value.toString())
actual is JsonValue.Decimal -> integerRegex.matches(actual.asString())
else -> false
}
logger.debug { "${valueOf(actual)} (${typeOf(actual)}) matches integer -> $result" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class JsonBodyMatcherSpec extends Specification {
expect:
matcher.matchBody(expectedBody, actualBody, true, matchers).find {
it instanceof BodyMismatch &&
it.mismatch.contains('Expected 100 but received 101')
it.mismatch.contains('Expected 100 (Integer) but received 101 (Integer)')
}

where:
Expand All @@ -224,7 +224,7 @@ class JsonBodyMatcherSpec extends Specification {
expect:
matcher.matchBody(expectedBody, actualBody, true, matchers).find {
it instanceof BodyMismatch &&
it.mismatch.contains('Type mismatch: Expected List [100,100] but received Primitive 100')
it.mismatch.contains('Type mismatch: Expected List [100,100] but received Integer 100')
}

where:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,23 @@ class MatcherExecutorSpec extends Specification {
MatcherExecutorKt.domatch(EqualsMatcher.INSTANCE, path, expected, actual, mismatchFactory).empty == mustBeEmpty

where:
expected | actual || mustBeEmpty
'100' | '100' || true
100 | '100' || false
100 | 100 || true
new JsonValue.Integer(100) | new JsonValue.Integer(100) || true
null | null || true
'100' | null || false
null | 100 || false
JsonValue.Null.INSTANCE | null || true
null | JsonValue.Null.INSTANCE || true
JsonValue.Null.INSTANCE | JsonValue.Null.INSTANCE || true
xml('<a/>') | xml('<a/>') || true
xml('<a/>') | xml('<b/>') || false
xml('<e xmlns="a"/>') | xml('<a:e xmlns:a="a"/>') || true
xml('<a:e xmlns:a="a"/>') | xml('<b:e xmlns:b="a"/>') || true
xml('<e xmlns="a"/>') | xml('<e xmlns="b"/>') || false
json('"hello"') | json('"hello"') || true
expected | actual || mustBeEmpty
'100' | '100' || true
100 | '100' || false
100 | 100 || true
new JsonValue.Integer('100'.chars) | new JsonValue.Integer('100'.chars) || true
null | null || true
'100' | null || false
null | 100 || false
JsonValue.Null.INSTANCE | null || true
null | JsonValue.Null.INSTANCE || true
JsonValue.Null.INSTANCE | JsonValue.Null.INSTANCE || true
xml('<a/>') | xml('<a/>') || true
xml('<a/>') | xml('<b/>') || false
xml('<e xmlns="a"/>') | xml('<a:e xmlns:a="a"/>') || true
xml('<a:e xmlns:a="a"/>') | xml('<b:e xmlns:b="a"/>') || true
xml('<e xmlns="a"/>') | xml('<e xmlns="b"/>') || false
json('"hello"') | json('"hello"') || true
}

@Unroll
Expand All @@ -70,11 +70,11 @@ class MatcherExecutorSpec extends Specification {
MatcherExecutorKt.domatch(new RegexMatcher(regex), path, expected, actual, mismatchFactory).empty == mustBeEmpty

where:
expected | actual | regex || mustBeEmpty
'Harry' | 'Happy' | 'Ha[a-z]*' || true
'Harry' | null | 'Ha[a-z]*' || false
'100' | 20123 | '\\d+' || true
'100' | new JsonValue.Integer(20123) | '\\d+' || true
expected | actual | regex || mustBeEmpty
'Harry' | 'Happy' | 'Ha[a-z]*' || true
'Harry' | null | 'Ha[a-z]*' || false
'100' | 20123 | '\\d+' || true
'100' | new JsonValue.Integer('20123'.chars) | '\\d+' || true
}

@Unroll
Expand Down Expand Up @@ -111,29 +111,29 @@ class MatcherExecutorSpec extends Specification {
mustBeEmpty

where:
numberType | expected | actual || mustBeEmpty
INTEGER | 100 | 'Some other string' || false
DECIMAL | 100.0 | 'Some other string' || false
NUMBER | 100 | 'Some other string' || false
INTEGER | 100 | 200.3 || false
NUMBER | 100 | 200.3 || true
DECIMAL | 100.0 | 200.3 || true
INTEGER | 100 | 200 || true
INTEGER | 100 | new JsonValue.Integer(200) || true
NUMBER | 100 | 200 || true
DECIMAL | 100.0 | 200 || false
INTEGER | 100 | false || false
DECIMAL | 100.0 | false || false
NUMBER | 100 | false || false
INTEGER | 100 | null || false
DECIMAL | 100.0 | null || false
NUMBER | 100 | null || false
INTEGER | 100 | [200.3] || false
DECIMAL | 100.0 | [200.3] || false
NUMBER | 100 | [200.3] || false
INTEGER | 100 | [a: 200.3, b: 200, c: 300] || false
DECIMAL | 100.0 | [a: 200.3, b: 200, c: 300] || false
NUMBER | 100 | [a: 200.3, b: 200, c: 300] || false
numberType | expected | actual || mustBeEmpty
INTEGER | 100 | 'Some other string' || false
DECIMAL | 100.0 | 'Some other string' || false
NUMBER | 100 | 'Some other string' || false
INTEGER | 100 | 200.3 || false
NUMBER | 100 | 200.3 || true
DECIMAL | 100.0 | 200.3 || true
INTEGER | 100 | 200 || true
INTEGER | 100 | new JsonValue.Integer('200'.chars) || true
NUMBER | 100 | 200 || true
DECIMAL | 100.0 | 200 || false
INTEGER | 100 | false || false
DECIMAL | 100.0 | false || false
NUMBER | 100 | false || false
INTEGER | 100 | null || false
DECIMAL | 100.0 | null || false
NUMBER | 100 | null || false
INTEGER | 100 | [200.3] || false
DECIMAL | 100.0 | [200.3] || false
NUMBER | 100 | [200.3] || false
INTEGER | 100 | [a: 200.3, b: 200, c: 300] || false
DECIMAL | 100.0 | [a: 200.3, b: 200, c: 300] || false
NUMBER | 100 | [a: 200.3, b: 200, c: 300] || false
}

@Unroll
Expand Down Expand Up @@ -259,18 +259,18 @@ class MatcherExecutorSpec extends Specification {

where:

value | result
new JsonValue.Decimal(0) | true
'100' | false
100 | false
100.0 | true
100.0 as float | true
100.0 as double | true
100 as int | false
100 as long | false
100 as BigInteger | false
BigInteger.ZERO | false
BigDecimal.ZERO | true
value | result
new JsonValue.Decimal('0'.chars) | true
'100' | false
100 | false
100.0 | true
100.0 as float | true
100.0 as double | true
100 as int | false
100 as long | false
100 as BigInteger | false
BigInteger.ZERO | false
BigDecimal.ZERO | true
}

@Unroll
Expand Down
1 change: 1 addition & 0 deletions core/model/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies {
testRuntime project(path: project.path, configuration: 'testJars')
testCompile "org.codehaus.groovy:groovy:${project.groovyVersion}"
testCompile "org.codehaus.groovy:groovy-datetime:${project.groovyVersion}"
testCompile "org.codehaus.groovy:groovy-json:${project.groovyVersion}"
testRuntime "org.junit.vintage:junit-vintage-engine:${project.junit5Version}"
testImplementation 'io.kotlintest:kotlintest-runner-junit5:3.3.2'
testCompile('org.spockframework:spock-core:2.0-M2-groovy-3.0') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ abstract class BaseRequest : HttpPart() {
}
entry.key to list
}
is JsonValue.StringValue -> queryStringToMap(query.value)
is JsonValue.StringValue -> queryStringToMap(query.asString())
else -> emptyMap()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ abstract class HttpPart {
fun extractBody(json: JsonValue.Object, contentType: ContentType): OptionalBody {
return when (val b = json["body"]) {
is JsonValue.Null -> OptionalBody.nullBody()
is JsonValue.StringValue -> decodeBody(b.value, contentType)
is JsonValue.StringValue -> decodeBody(b.asString(), contentType)
else -> decodeBody(b.serialise(), contentType)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class Response @JvmOverloads constructor(
val statusJson = json["status"]
when {
statusJson.isNumber -> statusJson.asNumber().toInt()
statusJson is JsonValue.StringValue -> statusJson.value.toInt()
statusJson is JsonValue.StringValue -> statusJson.asString().toInt()
else -> DEFAULT_STATUS
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class Message @JvmOverloads constructor(
val contents = if (json.has("contents")) {
when (val contents = json["contents"]) {
is JsonValue.Null -> OptionalBody.nullBody()
is JsonValue.StringValue -> OptionalBody.body(contents.value.toByteArray(contentType.asCharset()),
is JsonValue.StringValue -> OptionalBody.body(contents.asString().toByteArray(contentType.asCharset()),
contentType)
else -> OptionalBody.body(contents.serialise().toByteArray(contentType.asCharset()), contentType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class HttpPartSpec extends Specification {

def 'handles base64 encoded bodies'() {
given:
def json = new JsonValue.Object([body: new JsonValue.StringValue('aGVsbG8=')])
def json = new JsonValue.Object([body: new JsonValue.StringValue('aGVsbG8='.chars)])

expect:
HttpPart.extractBody(json, ContentType.fromString('application/zip'))
Expand All @@ -55,7 +55,7 @@ class HttpPartSpec extends Specification {

def 'returns the raw body if it can not be decoded'() {
given:
def json = new JsonValue.Object([body: new JsonValue.StringValue('hello')])
def json = new JsonValue.Object([body: new JsonValue.StringValue('hello'.chars)])

expect:
HttpPart.extractBody(json, ContentType.fromString('application/zip'))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class PactReaderTransformSpec extends Specification {
def 'converts provider state to camel case'() {
given:
jsonMap.get('interactions').asArray().get(0).asObject().add('provider_state',
new JsonValue.StringValue('provider state'))
new JsonValue.StringValue('provider state'.chars))

when:
def result = DefaultPactReader.INSTANCE.transformJson(jsonMap)
Expand Down Expand Up @@ -120,9 +120,9 @@ class PactReaderTransformSpec extends Specification {
def 'handles both a snake and camel case provider state'() {
given:
jsonMap.get('interactions').asArray().get(0).asObject().add('provider_state',
new JsonValue.StringValue('provider state'))
new JsonValue.StringValue('provider state'.chars))
jsonMap.get('interactions').asArray().get(0).asObject().add('providerState',
new JsonValue.StringValue('provider state 2'))
new JsonValue.StringValue('provider state 2'.chars))

when:
def result = DefaultPactReader.INSTANCE.transformJson(jsonMap)
Expand Down Expand Up @@ -223,7 +223,7 @@ class PactReaderTransformSpec extends Specification {
def 'converts the http methods to upper case'() {
given:
jsonMap.get('interactions').asArray().get(0).asObject().get('request').asObject()
.add('method', new JsonValue.StringValue('post'))
.add('method', new JsonValue.StringValue('post'.chars))

when:
def result = DefaultPactReader.INSTANCE.transformJson(jsonMap)
Expand Down
Loading

0 comments on commit 801cb88

Please sign in to comment.