Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
au.com.dius.pact.provider.StateChange.kt Maven / Gradle / Ivy
package au.com.dius.pact.provider
import au.com.dius.pact.com.github.michaelbull.result.Err
import au.com.dius.pact.com.github.michaelbull.result.Ok
import au.com.dius.pact.com.github.michaelbull.result.Result
import au.com.dius.pact.com.github.michaelbull.result.mapEither
import au.com.dius.pact.com.github.michaelbull.result.unwrap
import au.com.dius.pact.core.model.Interaction
import au.com.dius.pact.core.model.ProviderState
import au.com.dius.pact.core.support.Json
import com.google.gson.JsonParser
import groovy.lang.Closure
import mu.KLogging
import org.apache.http.HttpEntity
import org.apache.http.entity.ContentType
import org.apache.http.util.EntityUtils
import java.net.URI
import java.net.URISyntaxException
import java.net.URL
data class StateChangeResult @JvmOverloads constructor (
val stateChangeResult: Result, Exception>,
val message: String = ""
)
interface StateChange {
fun executeStateChange(
verifier: IProviderVerifier,
provider: IProviderInfo,
consumer: IConsumerInfo,
interaction: Interaction,
interactionMessage: String,
failures: MutableMap,
providerClient: ProviderClient
): StateChangeResult
fun stateChange(
verifier: IProviderVerifier,
state: ProviderState,
provider: IProviderInfo,
consumer: IConsumerInfo,
isSetup: Boolean,
providerClient: ProviderClient
): Result, Exception>
fun executeStateChangeTeardown(
verifier: IProviderVerifier,
interaction: Interaction,
provider: IProviderInfo,
consumer: IConsumerInfo,
providerClient: ProviderClient
)
}
/**
* Class containing all the state change logic
*/
object DefaultStateChange : StateChange, KLogging() {
override fun executeStateChange(
verifier: IProviderVerifier,
provider: IProviderInfo,
consumer: IConsumerInfo,
interaction: Interaction,
interactionMessage: String,
failures: MutableMap,
providerClient: ProviderClient
): StateChangeResult {
var message = interactionMessage
var stateChangeResult: Result, Exception> = Ok(emptyMap())
if (interaction.providerStates.isNotEmpty()) {
val iterator = interaction.providerStates.iterator()
var first = true
while (stateChangeResult is Ok && iterator.hasNext()) {
val providerState = iterator.next()
val result = stateChange(verifier, providerState, provider, consumer, true, providerClient)
logger.debug { "State Change: \"$providerState\" -> $result" }
stateChangeResult = result.mapEither({
if (first) {
message += " Given ${providerState.name}"
first = false
} else {
message += " And ${providerState.name}"
}
stateChangeResult.unwrap().plus(it)
}, {
failures[message] = it.message.toString()
it
})
}
}
return StateChangeResult(stateChangeResult, message)
}
override fun stateChange(
verifier: IProviderVerifier,
state: ProviderState,
provider: IProviderInfo,
consumer: IConsumerInfo,
isSetup: Boolean,
providerClient: ProviderClient
): Result, Exception> {
verifier.reportStateForInteraction(state.name, provider, consumer, isSetup)
try {
var stateChangeHandler = consumer.stateChange
var stateChangeUsesBody = consumer.stateChangeUsesBody
if (stateChangeHandler == null) {
stateChangeHandler = provider.stateChangeUrl
stateChangeUsesBody = provider.stateChangeUsesBody
}
if (stateChangeHandler == null || (stateChangeHandler is String && stateChangeHandler.isBlank())) {
verifier.reporters.forEach { it.warnStateChangeIgnored(state.name, provider, consumer) }
return Ok(emptyMap())
} else if (verifier.checkBuildSpecificTask.apply(stateChangeHandler)) {
logger.debug { "Invoking build specific task $stateChangeHandler" }
verifier.executeBuildSpecificTask.accept(stateChangeHandler, state)
return Ok(emptyMap())
} else if (stateChangeHandler is Closure<*>) {
val result = if (provider.stateChangeTeardown) {
stateChangeHandler.call(state, if (isSetup) "setup" else "teardown")
} else {
stateChangeHandler.call(state)
}
logger.debug { "Invoked state change closure -> $result" }
if (result !is URL) {
return Ok(if (result is Map<*, *>) result as Map else emptyMap())
}
stateChangeHandler = result
}
return executeHttpStateChangeRequest(verifier, stateChangeHandler, stateChangeUsesBody, state, provider, isSetup,
providerClient)
} catch (e: Exception) {
verifier.reporters.forEach {
it.stateChangeRequestFailedWithException(state.name, provider, consumer, isSetup, e,
verifier.projectHasProperty.apply(ProviderVerifier.PACT_SHOW_STACKTRACE))
}
return Err(e)
}
}
override fun executeStateChangeTeardown(
verifier: IProviderVerifier,
interaction: Interaction,
provider: IProviderInfo,
consumer: IConsumerInfo,
providerClient: ProviderClient
) {
interaction.providerStates.forEach {
stateChange(verifier, it, provider, consumer, false, providerClient)
}
}
private fun executeHttpStateChangeRequest(
verifier: IProviderVerifier,
stateChangeHandler: Any,
useBody: Boolean,
state: ProviderState,
provider: IProviderInfo,
isSetup: Boolean,
providerClient: ProviderClient
): Result, Exception> {
return try {
val url = stateChangeHandler as? URI ?: URI(stateChangeHandler.toString())
val response = providerClient.makeStateChangeRequest(url, state, useBody, isSetup, provider.stateChangeTeardown)
logger.debug { "Invoked state change $url -> ${response?.statusLine}" }
response?.use {
if (response.statusLine.statusCode >= 400) {
verifier.reporters.forEach {
it.stateChangeRequestFailed(state.name, provider, isSetup, response.statusLine.toString())
}
Err(Exception("State Change Request Failed - ${response.statusLine}"))
} else {
parseJsonResponse(response.entity)
}
} ?: Ok(emptyMap())
} catch (ex: URISyntaxException) {
verifier.reporters.forEach {
it.warnStateChangeIgnoredDueToInvalidUrl(state.name, provider, isSetup, stateChangeHandler)
}
Ok(emptyMap())
}
}
private fun parseJsonResponse(entity: HttpEntity?): Result, Exception> {
return if (entity != null && ContentType.get(entity).mimeType == ContentType.APPLICATION_JSON.mimeType) {
val body = EntityUtils.toString(entity)
Ok(Json.toMap(JsonParser().parse(body)))
} else {
Ok(emptyMap())
}
}
}