Skip to content

Commit

Permalink
feat: Add support for plugin GenerateContentRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
rholshausen committed Dec 14, 2022
1 parent 6acc512 commit ccaf27e
Show file tree
Hide file tree
Showing 26 changed files with 755 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
api 'org.apache.httpcomponents.client5:httpclient5:5.1.3'
api 'org.apache.httpcomponents.client5:httpclient5-fluent:5.1.3'
api 'org.json:json:20220924'
api 'io.pact.plugin.driver:core:0.2.1'

implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.apache.commons:commons-lang3:3.12.0'
Expand All @@ -45,7 +46,6 @@ dependencies {
implementation 'io.netty:netty-handler:4.1.84.Final'
implementation 'org.apache.groovy:groovy:4.0.6'
implementation 'org.apache.groovy:groovy-json:4.0.6'
implementation 'io.pact.plugin.driver:core:0.2.0'

testImplementation 'org.apache.groovy:groovy:4.0.6'
testImplementation 'org.apache.groovy:groovy-json:4.0.6'
Expand Down
6 changes: 3 additions & 3 deletions consumer/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ dependencies {
api project(':core:matchers')
api 'org.apache.httpcomponents.client5:httpclient5'
api 'org.json:json'
api('io.pact.plugin.driver:core') {
exclude group: 'au.com.dius.pact.core'
}

implementation 'org.apache.httpcomponents.client5:httpclient5-fluent'
implementation 'com.googlecode.java-diff-utils:diffutils:1.3.0'
Expand All @@ -21,9 +24,6 @@ dependencies {
implementation 'org.slf4j:slf4j-api'
implementation 'io.ktor:ktor-server-netty'
implementation 'io.ktor:ktor-network-tls-certificates'
implementation('io.pact.plugin.driver:core') {
exclude group: 'au.com.dius.pact.core'
}
implementation 'org.apache.commons:commons-lang3'
implementation 'com.github.mifmif:generex:1.0.2'
implementation 'org.apache.commons:commons-io:1.3.2'
Expand Down
6 changes: 3 additions & 3 deletions consumer/groovy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ group = 'au.com.dius.pact.consumer'

dependencies {
api project(":consumer")
api('io.pact.plugin.driver:core') {
exclude group: 'au.com.dius.pact.core'
}

implementation 'org.apache.groovy:groovy'
implementation 'org.apache.groovy:groovy-json'
implementation 'org.apache.httpcomponents.client5:httpclient5'
implementation 'com.github.mifmif:generex:1.0.2'
implementation 'org.apache.commons:commons-lang3'
implementation 'org.apache.commons:commons-collections4'
implementation('io.pact.plugin.driver:core') {
exclude group: 'au.com.dius.pact.core'
}

testImplementation 'junit:junit'
testImplementation 'ch.qos.logback:logback-classic'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package au.com.dius.pact.consumer.groovy

import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.generators.Category
import au.com.dius.pact.core.model.generators.Generators
import au.com.dius.pact.core.model.generators.ProviderStateGenerator
Expand Down Expand Up @@ -36,6 +37,14 @@ class PactBodyBuilder extends GroovyBuilder {
private path = DOLLAR
private final bodyStack = []

PactBodyBuilder() {
super(PactSpecVersion.V4)
}

PactBodyBuilder(PactSpecVersion pactVersion) {
super(pactVersion ?: PactSpecVersion.V4)
}

String getBody() {
if (shouldPrettyPrint()) {
new JsonBuilder(bodyRepresentation).toPrettyString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,11 @@ class PactBuilder extends GroovyBuilder {
List interactions = []
List<ProviderState> providerStates = []
boolean requestState
PactSpecVersion specVersion = PactSpecVersion.V3

PactBuilder(PactSpecVersion version = PactSpecVersion.V3) {
this.specVersion = version
PactBuilder(PactSpecVersion version = PactSpecVersion.V4) {
super(version)

if (specVersion == PactSpecVersion.V4) {
if (pactVersion == PactSpecVersion.V4) {
pact = new V4Pact(new Consumer(), new Provider())
}
}
Expand Down Expand Up @@ -118,7 +117,7 @@ class PactBuilder extends GroovyBuilder {
*/
PactBuilder uponReceiving(String requestDescription) {
updateInteractions()
if (this.specVersion == PactSpecVersion.V4) {
if (this.pactVersion == PactSpecVersion.V4) {
this.currentInteraction = new V4Interaction.SynchronousHttp('', requestDescription, providerStates)
} else {
this.currentInteraction = new RequestResponseInteraction(requestDescription, providerStates)
Expand Down Expand Up @@ -265,7 +264,7 @@ class PactBuilder extends GroovyBuilder {
updateInteractions()
this.pact.interactions.addAll(interactions)

MockProviderConfig config = MockProviderConfig.httpConfig(LOCALHOST, port ?: 0, specVersion,
MockProviderConfig config = MockProviderConfig.httpConfig(LOCALHOST, port ?: 0, pactVersion,
MockServerImplementation.Default)

def runTest = closure
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,26 @@ import au.com.dius.pact.core.model.OptionalBody
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.Provider
import au.com.dius.pact.core.model.ProviderState
import au.com.dius.pact.core.model.messaging.Message
import au.com.dius.pact.core.model.messaging.MessagePact
import au.com.dius.pact.core.model.V4Interaction
import au.com.dius.pact.core.model.V4Pact
import au.com.dius.pact.core.model.messaging.MessageInteraction
import au.com.dius.pact.core.model.v4.MessageContents
import au.com.dius.pact.core.support.BuiltToolConfig
import au.com.dius.pact.core.support.MetricEvent
import au.com.dius.pact.core.support.Metrics

/**
* Pact builder for consumer tests for messaging
* Pact builder for consumer tests for asynchronous messaging
*/
class PactMessageBuilder extends GroovyBuilder {
Consumer consumer
Provider provider
List<ProviderState> providerStates = []
List messages = []
List<V4Interaction.AsynchronousMessage> messages = []

PactMessageBuilder(PactSpecVersion pactVersion) {
super(pactVersion ?: PactSpecVersion.V4)
}

/**
* Service consumer
Expand Down Expand Up @@ -52,12 +58,33 @@ class PactMessageBuilder extends GroovyBuilder {
this
}

/**
* Enable the plugin
* @param name Plugin Name
* @param version Plugin Version
*/
@Override
PactMessageBuilder usingPlugin(String name, String version) {
super.usingPlugin(name, version) as PactMessageBuilder
}

/**
* Enable the plugin
* @param name Plugin Name
* @return
*/
@Override
PactMessageBuilder usingPlugin(String name) {
super.usingPlugin(name) as PactMessageBuilder
}

/**
* Description of the message to be received
* @param description
*/
PactMessageBuilder expectsToReceive(String description) {
messages << new Message(description, providerStates)
PactMessageBuilder expectsToReceive(String description, String key = '') {
def message = new V4Interaction.AsynchronousMessage(key, description, new MessageContents(), null, providerStates)
messages << message
this
}

Expand All @@ -69,18 +96,20 @@ class PactMessageBuilder extends GroovyBuilder {
if (messages.empty) {
throw new InvalidPactException('expectsToReceive is required before withMetaData')
}
Message message = messages.last()
message.metadata = metadata.collectEntries {
V4Interaction.AsynchronousMessage message = messages.last()
message.withMetadata(metadata.collectEntries {
if (it.value instanceof Matcher) {
message.matchingRules.addCategory('metadata').addRule(it.key, it.value.matcher)
message.contents.matchingRules.addCategory('metadata').addRule(it.key, it.value.matcher)
if (it.value.generator) {
message.generators.addGenerator(au.com.dius.pact.model.generators.Category.METADATA, it.value.generator)
message.contents.generators.addGenerator(
au.com.dius.pact.model.generators.Category.METADATA, it.key, it.value.generator
)
}
[it.key, it.value.value]
} else {
[it.key, it.value]
}
}
})
this
}

Expand All @@ -95,19 +124,23 @@ class PactMessageBuilder extends GroovyBuilder {
throw new InvalidPactException('expectsToReceive is required before withContent')
}

V4Interaction.AsynchronousMessage message = messages.last()
def contentType = ContentType.JSON.contentType

def messageContents = message.contents
if (options.contentType) {
contentType = options.contentType
messages.last().metadata.contentType = options.contentType
} else if (messages.last().metadata.contentType) {
contentType = messages.last().metadata.contentType
messageContents.metadata.contentType = options.contentType
} else if (messageContents.metadata.contentType) {
contentType = messageContents.metadata.contentType
}

def body = new PactBodyBuilder(mimetype: contentType, prettyPrintBody: options.prettyPrint)
closure.delegate = body
closure.call()
messages.last().contents = OptionalBody.body(body.body.bytes, new ContentType(contentType))
messages.last().matchingRules.addCategory(body.matchers)
messageContents.matchingRules.addCategory(body.matchers)
message.contents = new MessageContents(OptionalBody.body(body.body.bytes, new ContentType(contentType)),
messageContents.metadata, messageContents.matchingRules, messageContents.generators, messageContents.partName)

this
}
Expand All @@ -117,10 +150,10 @@ class PactMessageBuilder extends GroovyBuilder {
* @param closure
*/
void run(Closure closure) {
def pact = new MessagePact(provider, consumer, messages)
def pact = new V4Pact(consumer, provider, messages)
def results = messages.collect {
try {
closure.call(it)
closure.call(it as MessageInteraction)
} catch (ex) {
ex
}
Expand All @@ -131,7 +164,13 @@ class PactMessageBuilder extends GroovyBuilder {
if (results.any { it instanceof Throwable }) {
throw new MessagePactFailedException(results.findAll { it instanceof Throwable })
} else {
pact.write(BuiltToolConfig.pactDirectory, PactSpecVersion.V3)
if (pactVersion >= PactSpecVersion.V4) {
pact.write(BuiltToolConfig.INSTANCE.pactDirectory, pactVersion)
} else {
pact.asMessagePact()
.expect { "Error converting Pact to V3 format - $it" }
.write(BuiltToolConfig.INSTANCE.pactDirectory, pactVersion)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
package au.com.dius.pact.consumer.groovy

import au.com.dius.pact.consumer.interactionCatalogueEntries
import au.com.dius.pact.core.matchers.MatchingConfig
import au.com.dius.pact.core.matchers.matcherCatalogueEntries
import au.com.dius.pact.core.model.IHttpPart
import au.com.dius.pact.core.model.OptionalBody
import au.com.dius.pact.core.model.PactSpecVersion
import au.com.dius.pact.core.model.generators.Generators
import au.com.dius.pact.core.model.generators.ProviderStateGenerator
import au.com.dius.pact.core.model.matchingrules.MatchingRuleCategory
import au.com.dius.pact.core.model.matchingrules.MatchingRules
import au.com.dius.pact.core.model.queryStringToMap
import au.com.dius.pact.core.support.expressions.DataType
import au.com.dius.pact.core.support.property
import au.com.dius.pact.core.support.Result
import groovy.json.JsonBuilder
import io.pact.plugins.jvm.core.CatalogueManager
import io.pact.plugins.jvm.core.DefaultPluginManager
import io.pact.plugins.jvm.core.PactPlugin
import io.pact.plugins.jvm.core.PactPluginNotFoundException
import mu.KLogging
import java.util.regex.Pattern

open class BaseBuilder : Matchers() {
open class BaseBuilder(
var pactVersion: PactSpecVersion = PactSpecVersion.V4,
val plugins: MutableList<PactPlugin> = mutableListOf()
) : Matchers() {

init {
CatalogueManager.registerCoreEntries(
MatchingConfig.contentMatcherCatalogueEntries() +
matcherCatalogueEntries() + interactionCatalogueEntries() + MatchingConfig.contentHandlerCatalogueEntries()
)
}

protected fun setupBody(data: Map<String, Any>, httpPart: IHttpPart): OptionalBody {
return if (data.containsKey(BODY)) {
val body = data[BODY]
Expand Down Expand Up @@ -128,6 +148,36 @@ open class BaseBuilder : Matchers() {
}
}

/**
* Enable a plugin
*/
open fun usingPlugin(name: String, version: String? = null): BaseBuilder {
val plugin = findPlugin(name, version)
if (plugin == null) {
when (val result = DefaultPluginManager.loadPlugin(name, version)) {
is Result.Ok -> plugins.add(result.value)
is Result.Err -> {
logger.error { result.error }
throw PactPluginNotFoundException(name, version)
}
}
}
return this
}

/**
* Enable a plugin
*/
open fun usingPlugin(name: String) = usingPlugin(name, null)

private fun findPlugin(name: String, version: String?): PactPlugin? {
return if (version == null) {
plugins.filter { it.manifest.name == name }.maxByOrNull { it.manifest.version }
} else {
plugins.find { it.manifest.name == name && it.manifest.version == version }
}
}

companion object : KLogging() {
const val CONTENT_TYPE = "Content-Type"
const val JSON = "application/json"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package au.com.dius.pact.consumer.groovy

import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.exists

object BuilderUtils {
@JvmStatic
fun textFile(filePath: String): String {
var path = Paths.get(filePath)
if (!path.exists()) {
val cwd = Path.of("").toAbsolutePath()
path = cwd.resolve(filePath).toAbsolutePath()
}
return path.toFile().bufferedReader().readText()
}

@JvmStatic
fun filePath(filePath: String): String {
var path = Paths.get(filePath).toAbsolutePath()
if (!path.exists()) {
val cwd = Path.of("").toAbsolutePath()
path = cwd.resolve(filePath).toAbsolutePath()
}
return path.normalize().toString()
}
}
Loading

0 comments on commit ccaf27e

Please sign in to comment.