Skip to content

Commit 7d83a95

Browse files
author
Ronald Holshausen
committedOct 27, 2019
fix: let invalid path exceptions propogate so verification fails #957
1 parent 05ca602 commit 7d83a95

File tree

4 files changed

+77
-25
lines changed

4 files changed

+77
-25
lines changed
 

‎core/matchers/src/main/kotlin/au/com/dius/pact/core/matchers/Matchers.kt

+12-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package au.com.dius.pact.core.matchers
22

33
import au.com.dius.pact.core.matchers.util.corresponds
44
import au.com.dius.pact.core.matchers.util.tails
5-
import au.com.dius.pact.core.model.InvalidPathExpression
65
import au.com.dius.pact.core.model.PathToken
76
import au.com.dius.pact.core.model.matchingrules.MatchingRuleGroup
87
import au.com.dius.pact.core.model.matchingrules.MatchingRules
@@ -28,34 +27,24 @@ object Matchers : KLogging() {
2827
}
2928

3029
fun matchesPath(pathExp: String, path: List<String>): Int {
31-
return try {
32-
val parseResult = parsePath(pathExp)
33-
val filter = tails(path.reversed()).filter { l ->
34-
corresponds(l.reversed(), parseResult) { pathElement, pathToken ->
35-
matchesToken(pathElement, pathToken) != 0
36-
}
37-
}
38-
if (filter.isNotEmpty()) {
39-
filter.maxBy { seq -> seq.size }?.size ?: 0
40-
} else {
41-
0
30+
val parseResult = parsePath(pathExp)
31+
val filter = tails(path.reversed()).filter { l ->
32+
corresponds(l.reversed(), parseResult) { pathElement, pathToken ->
33+
matchesToken(pathElement, pathToken) != 0
4234
}
43-
} catch (e: InvalidPathExpression) {
44-
logger.warn(e) { "Path expression $pathExp is invalid, ignoring" }
35+
}
36+
return if (filter.isNotEmpty()) {
37+
filter.maxBy { seq -> seq.size }?.size ?: 0
38+
} else {
4539
0
4640
}
4741
}
4842

4943
fun calculatePathWeight(pathExp: String, path: List<String>): Int {
50-
return try {
51-
val parseResult = parsePath(pathExp)
52-
path.zip(parseResult).asSequence().map {
53-
matchesToken(it.first, it.second)
54-
}.reduce { acc, i -> acc * i }
55-
} catch (e: InvalidPathExpression) {
56-
logger.warn(e) { "Path expression $pathExp is invalid, ignoring" }
57-
0
58-
}
44+
val parseResult = parsePath(pathExp)
45+
return path.zip(parseResult).asSequence().map {
46+
matchesToken(it.first, it.second)
47+
}.reduce { acc, i -> acc * i }
5948
}
6049

6150
fun resolveMatchers(

‎core/matchers/src/test/groovy/au/com/dius/pact/core/matchers/MatchersSpec.groovy

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package au.com.dius.pact.core.matchers
22

3+
import au.com.dius.pact.core.model.InvalidPathExpression
34
import au.com.dius.pact.core.model.OptionalBody
45
import au.com.dius.pact.core.model.matchingrules.Category
56
import au.com.dius.pact.core.model.matchingrules.EqualsMatcher
@@ -238,6 +239,22 @@ class MatchersSpec extends Specification {
238239
Matchers.INSTANCE.matchesPath('$[*]', ['$', 'str']) == 0
239240
}
240241

242+
def 'path matching - throws an exception if path is invalid'() {
243+
when:
244+
Matchers.INSTANCE.matchesPath("\$.serviceNode.entity.status.thirdNode['@description]", ['a'])
245+
246+
then:
247+
thrown(InvalidPathExpression)
248+
}
249+
250+
def 'calculatePathWeight - throws an exception if path is invalid'() {
251+
when:
252+
Matchers.INSTANCE.calculatePathWeight("\$.serviceNode.entity.status.thirdNode['@description]", ['a'])
253+
254+
then:
255+
thrown(InvalidPathExpression)
256+
}
257+
241258
def 'resolveMatchers returns all matchers for the general case'() {
242259
given:
243260
def matchers = new MatchingRulesImpl()

‎provider/pact-jvm-provider/src/main/kotlin/au/com/dius/pact/provider/ProviderVerifier.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -419,16 +419,17 @@ open class ProviderVerifier @JvmOverloads constructor (
419419
reporters.forEach { it.finaliseReport() }
420420
}
421421

422+
@JvmOverloads
422423
fun verifyInteraction(
423424
provider: IProviderInfo,
424425
consumer: IConsumerInfo,
425426
failures: MutableMap<String, Any>,
426-
interaction: Interaction
427+
interaction: Interaction,
428+
providerClient: ProviderClient = ProviderClient(provider, HttpClientFactory())
427429
): TestResult {
428430
var interactionMessage = "Verifying a pact between ${consumer.name} and ${provider.name}" +
429431
" - ${interaction.description} "
430432

431-
val providerClient = ProviderClient(provider, HttpClientFactory())
432433
val stateChangeResult = stateChangeHandler.executeStateChange(this, provider, consumer, interaction, interactionMessage,
433434
failures, providerClient)
434435
if (stateChangeResult.stateChangeResult is Ok) {

‎provider/pact-jvm-provider/src/test/groovy/au/com/dius/pact/provider/ProviderVerifierSpec.groovy

+45
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import au.com.dius.pact.core.model.BrokerUrlSource
44
import au.com.dius.pact.core.model.Consumer
55
import au.com.dius.pact.core.model.FileSource
66
import au.com.dius.pact.core.model.Interaction
7+
import au.com.dius.pact.core.model.InvalidPathExpression
78
import au.com.dius.pact.core.model.OptionalBody
89
import au.com.dius.pact.core.model.Pact
910
import au.com.dius.pact.core.model.PactReader
@@ -16,12 +17,16 @@ import au.com.dius.pact.core.model.Response
1617
import au.com.dius.pact.core.model.UnknownPactSource
1718
import au.com.dius.pact.core.model.UrlSource
1819
import au.com.dius.pact.core.model.generators.Generators
20+
import au.com.dius.pact.core.model.matchingrules.MatchingRules
1921
import au.com.dius.pact.core.model.matchingrules.MatchingRulesImpl
22+
import au.com.dius.pact.core.model.matchingrules.RegexMatcher
2023
import au.com.dius.pact.core.model.messaging.Message
2124
import au.com.dius.pact.core.pactbroker.TestResult
2225
import au.com.dius.pact.core.pactbroker.PactBrokerClient
2326
import au.com.dius.pact.provider.reporters.VerifierReporter
2427
import au.com.dius.pact.com.github.michaelbull.result.Ok
28+
import groovy.json.JsonOutput
29+
import org.apache.http.entity.ContentType
2530
import spock.lang.Specification
2631
import spock.lang.Unroll
2732
import spock.util.environment.RestoreSystemProperties
@@ -584,6 +589,46 @@ class ProviderVerifierSpec extends Specification {
584589
result.results[0].interactionId == '1234'
585590
}
586591

592+
def 'verifyInteraction returns an error result if any matcher paths are invalid'() {
593+
given:
594+
ProviderInfo provider = new ProviderInfo('Test Provider')
595+
ConsumerInfo consumer = new ConsumerInfo(name: 'Test Consumer', pactSource: UnknownPactSource.INSTANCE)
596+
def failures = [:]
597+
MatchingRules matchingRules = new MatchingRulesImpl()
598+
matchingRules.addCategory('body')
599+
.addRule("\$.serviceNode.entity.status.thirdNode['@description]", new RegexMatcher('.*'))
600+
def json = JsonOutput.toJson([
601+
serviceNode: [
602+
entity: [
603+
status: [
604+
thirdNode: [
605+
'@description': 'Test'
606+
]
607+
]
608+
]
609+
]
610+
])
611+
Interaction interaction = new RequestResponseInteraction('Test Interaction',
612+
[new ProviderState('Test State')], new Request(),
613+
new Response(200, [:], OptionalBody.body(json.bytes), matchingRules), '1234')
614+
def client = Mock(ProviderClient)
615+
client.makeRequest(_) >> [
616+
statusCode: 200,
617+
headers: [:],
618+
contentType: ContentType.APPLICATION_JSON,
619+
data: json
620+
]
621+
622+
when:
623+
def result = verifier.verifyInteraction(provider, consumer, failures, interaction, client)
624+
625+
then:
626+
result instanceof TestResult.Failed
627+
result.results.size() == 1
628+
result.results[0].message == 'Request to provider failed with an exception'
629+
result.results[0].exception instanceof InvalidPathExpression
630+
}
631+
587632
def 'verifyResponseFromProvider returns an error result if the request to the provider fails with an exception'() {
588633
given:
589634
ProviderInfo provider = new ProviderInfo('Test Provider')

0 commit comments

Comments
 (0)
Please sign in to comment.