Skip to content

Commit 426736f

Browse files
committed
- CustomDynamicVariableGenerator shall receive rundown in the hook
- Major refactoring Signed-off-by: Gopal S Akshintala <[email protected]>
1 parent 6215cf7 commit 426736f

File tree

23 files changed

+1496
-1431
lines changed

23 files changed

+1496
-1431
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies {
3535
compileOnly(libs.jetbrains.annotations)
3636
testImplementation(libs.truth)
3737
testImplementation(libs.json.assert)
38+
testImplementation(libs.mockk)
3839
}
3940

4041
testing {

docs/revoman.exe.log

Lines changed: 1233 additions & 1241 deletions
Large diffs are not rendered by default.

gradle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ org.gradle.parallel=true
1212
org.gradle.jvmargs=-XX:+UseParallelGC
1313

1414
moshix.generateProguardRules=false
15+
16+
kapt.include.compile.classpath=false

libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ spring = "5.3.31" # 5.3.31 Compatable with Java 11
2525
json-assert = "1.5.1"
2626
nexus-publish = "2.0.0-rc-2"
2727
kotlinx-datetime = "0.6.0-RC.2"
28+
mockk = "1.13.10"
2829

2930
# Common dependencies
3031
junit = "5.10.2"
@@ -66,6 +67,7 @@ mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" }
6667
spring-beans = { module = "org.springframework:spring-beans", version.ref = "spring" }
6768
json-assert = { module = "org.skyscreamer:jsonassert", version.ref = "json-assert" }
6869
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime-jvm", version.ref = "kotlinx-datetime" }
70+
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
6971

7072
# Gradle plugins
7173
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }

src/integrationTest/java/com/salesforce/revoman/integration/core/pq/PQE2EWithSMTest.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,14 @@ void revUpPQ() {
6767
"$quoteFieldsToQuery", "LineItemCount, CalculationStatus",
6868
"$qliFieldsToQuery", "Id, Product2Id",
6969
"$qlrFieldsToQuery", "Id, QuoteId, MainQuoteLineId, AssociatedQuoteLineId"))
70-
.customDynamicVariable( // <5>
71-
"$quantity", ignore -> String.valueOf(Random.Default.nextInt(10) + 1))
70+
.customDynamicVariableGenerators(
71+
Map.of( // <5>
72+
"$quantity",
73+
(ignore1, ignore2, ignore3) ->
74+
String.valueOf(Random.Default.nextInt(10) + 1),
75+
"$requestName",
76+
(ignore1, currentStepReport, ignore3) ->
77+
currentStepReport.step.rawPMStep.getName()))
7278
.haltOnFailureOfTypeExcept(
7379
HTTP_STATUS,
7480
afterAllStepsContainingHeader("ignoreHTTPStatusUnsuccessful")) // <6>

src/integrationTest/resources/pm-templates/pq/[sm] pq.postman_collection.json

Lines changed: 40 additions & 25 deletions
Large diffs are not rendered by default.

src/main/kotlin/com/salesforce/revoman/ReVoman.kt

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ import com.salesforce.revoman.internal.exe.unmarshallResponse
2525
import com.salesforce.revoman.internal.json.initMoshi
2626
import com.salesforce.revoman.internal.postman.Info
2727
import com.salesforce.revoman.internal.postman.RegexReplacer
28-
import com.salesforce.revoman.internal.postman.initPmEnvironment
28+
import com.salesforce.revoman.internal.postman.dynamicVariableGenerator
29+
import com.salesforce.revoman.internal.postman.mergeEnvs
2930
import com.salesforce.revoman.internal.postman.pm
3031
import com.salesforce.revoman.internal.postman.template.Template
3132
import com.salesforce.revoman.output.Rundown
3233
import com.salesforce.revoman.output.report.Step
3334
import com.salesforce.revoman.output.report.StepReport
35+
import com.salesforce.revoman.output.report.StepReport.Companion.toArrow
3436
import com.salesforce.revoman.output.report.StepReport.Companion.toVavr
3537
import com.salesforce.revoman.output.report.TxnInfo
3638
import com.squareup.moshi.Moshi
@@ -44,11 +46,7 @@ object ReVoman {
4446
@JvmStatic
4547
@OptIn(ExperimentalStdlibApi::class)
4648
fun revUp(kick: Kick): Rundown {
47-
initPmEnvironment(
48-
kick.environmentPaths(),
49-
kick.dynamicEnvironmentsFlattened(),
50-
kick.customDynamicVariables()
51-
)
49+
val environment = mergeEnvs(kick.environmentPaths(), kick.dynamicEnvironmentsFlattened())
5250
val pmTemplateAdapter = Moshi.Builder().build().adapter<Template>()
5351
val pmStepsDeepFlattened =
5452
kick
@@ -61,21 +59,25 @@ object ReVoman {
6159
val stepNameToReport =
6260
executeStepsSerially(
6361
pmStepsDeepFlattened,
62+
environment,
6463
kick,
6564
initMoshi(
6665
kick.customAdaptersForMarshalling(),
6766
kick.customAdaptersFromRequestConfig() + kick.customAdaptersFromResponseConfig(),
6867
kick.typesToIgnoreForMarshalling()
6968
)
7069
)
71-
return Rundown(stepNameToReport, pm.environment, kick.haltOnFailureOfTypeExcept())
70+
return Rundown(stepNameToReport, kick.haltOnFailureOfTypeExcept())
7271
}
7372

7473
private fun executeStepsSerially(
7574
pmStepsFlattened: List<Step>,
75+
environment: Map<String, String?>,
7676
kick: Kick,
7777
moshiReVoman: ConfigurableMoshi,
7878
): List<StepReport> {
79+
pm.environment.clear()
80+
pm.environment.putAll(environment)
7981
var haltExecution = false
8082
return pmStepsFlattened
8183
.asSequence()
@@ -85,46 +87,65 @@ object ReVoman {
8587
logger.info { "***** Executing Step: $step *****" }
8688
val itemWithRegex = step.rawPMStep
8789
pm.info = Info(step.name)
90+
val stepReport = StepReport(step)
91+
val rundown = Rundown(stepReports + stepReport, kick.haltOnFailureOfTypeExcept())
92+
val regexReplacer =
93+
RegexReplacer(
94+
pm.environment,
95+
kick.customDynamicVariableGenerators(),
96+
::dynamicVariableGenerator
97+
)
98+
pm.environment.putAll(regexReplacer.replaceVariablesInEnv(stepReport, rundown))
8899
val pmRequest: com.salesforce.revoman.internal.postman.template.Request =
89-
RegexReplacer(pm.environment, kick.customDynamicVariables())
90-
.replaceRegex(itemWithRegex.request)
100+
regexReplacer.replaceVariablesInRequest(itemWithRegex.request, stepReport, rundown)
91101
val currentStepReport: StepReport = // --------### UNMARSHALL-REQUEST ###--------
92102
unmarshallRequest(step, pmRequest, kick, moshiReVoman, stepReports)
93103
.mapLeft { StepReport(step, Left(it)) }
94104
.flatMap { requestInfo: TxnInfo<Request> -> // --------### PRE-HOOKS ###--------
95105
preHookExe(step, kick, requestInfo, stepReports)?.let {
96106
Left(StepReport(step, Right(requestInfo), it))
97-
} ?: Right(requestInfo)
107+
} ?: Right(StepReport(step, Right(requestInfo)))
98108
}
99-
.flatMap { requestInfo: TxnInfo<Request> -> // --------### HTTP-REQUEST ###--------
100-
val item = RegexReplacer(pm.environment).replaceRegex(itemWithRegex)
109+
.flatMap { sr: StepReport -> // --------### HTTP-REQUEST ###--------
110+
val item =
111+
regexReplacer.replaceVariablesInPmItem(
112+
itemWithRegex,
113+
sr,
114+
Rundown(stepReports + sr, kick.haltOnFailureOfTypeExcept())
115+
)
101116
val httpRequest = item.request.toHttpRequest()
102117
fireHttpRequest(step, item.auth, httpRequest, kick.insecureHttp())
103118
.mapLeft { StepReport(step, Left(it)) }
104119
.map {
105-
StepReport(step, Right(requestInfo.copy(httpMsg = httpRequest)), null, Right(it))
120+
StepReport(
121+
step,
122+
sr.requestInfo?.toArrow()?.map { txnInfo ->
123+
txnInfo.copy(httpMsg = httpRequest)
124+
},
125+
null,
126+
Right(it)
127+
)
106128
}
107129
}
108-
.flatMap { stepReport: StepReport -> // --------### TESTS-JS ###--------
130+
.flatMap { sr: StepReport -> // --------### TESTS-JS ###--------
109131
executeTestsJS(
110132
step,
111133
itemWithRegex.event,
112-
kick.customDynamicVariables(),
134+
regexReplacer,
113135
pmRequest,
114-
stepReport
136+
sr,
137+
Rundown(stepReports + sr, kick.haltOnFailureOfTypeExcept())
115138
)
116-
.mapLeft { stepReport.copy(responseInfo = left(it)) }
117-
.map { stepReport }
139+
.mapLeft { sr.copy(responseInfo = left(it)) }
140+
.map { sr }
118141
}
119-
.flatMap { stepReport: StepReport -> // ---### UNMARSHALL RESPONSE ###---
120-
unmarshallResponse(stepReport, kick, moshiReVoman, stepReports)
121-
.mapLeft { stepReport.copy(responseInfo = Left(it).toVavr()) }
122-
.map { stepReport.copy(responseInfo = Right(it).toVavr()) }
142+
.flatMap { sr: StepReport -> // ---### UNMARSHALL RESPONSE ###---
143+
unmarshallResponse(sr, kick, moshiReVoman, stepReports)
144+
.mapLeft { sr.copy(responseInfo = Left(it).toVavr()) }
145+
.map { sr.copy(responseInfo = Right(it).toVavr()) }
123146
}
124-
.map { stepReport: StepReport -> // --------### POST-HOOKS ###--------
125-
stepReport.copy(
126-
postHookFailure = postHookExe(stepReport, kick, stepReports + stepReport)
127-
)
147+
.map { sr: StepReport -> // --------### POST-HOOKS ###--------
148+
sr.copy(postHookFailure = postHookExe(sr, kick, stepReports + sr))
128149
}
129150
.merge()
130151
.copy(

src/main/kotlin/com/salesforce/revoman/input/config/KickDef.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import com.salesforce.revoman.input.config.StepPick.ExeStepPick
1111
import com.salesforce.revoman.input.config.StepPick.PostTxnStepPick
1212
import com.salesforce.revoman.input.config.StepPick.PreTxnStepPick
1313
import com.salesforce.revoman.output.ExeType
14+
import com.salesforce.revoman.output.Rundown
15+
import com.salesforce.revoman.output.report.StepReport
1416
import com.squareup.moshi.JsonAdapter
1517
import com.squareup.moshi.JsonAdapter.Factory
1618
import io.vavr.control.Either
@@ -34,7 +36,7 @@ internal interface KickDef {
3436
if (dynamicEnvironments().isEmpty()) emptyMap()
3537
else dynamicEnvironments().reduce { acc, map -> acc + map }
3638

37-
fun customDynamicVariables(): Map<String, (String) -> String>
39+
fun customDynamicVariableGenerators(): Map<String, CustomDynamicVariableGenerator>
3840

3941
@Value.Default fun haltOnAnyFailure(): Boolean = false
4042

@@ -93,6 +95,10 @@ internal interface KickDef {
9395
}
9496
}
9597

98+
fun interface CustomDynamicVariableGenerator {
99+
fun generate(variableName: String, currentStepReport: StepReport, rundown: Rundown): String
100+
}
101+
96102
@Target(AnnotationTarget.CLASS)
97103
@Retention(AnnotationRetention.SOURCE)
98104
@Value.Style(

src/main/kotlin/com/salesforce/revoman/input/json/JsonPojoUtils.kt

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import org.immutables.value.Value
2424
* @param jsonFilePath The path to the JSON file
2525
* @param customAdapters A list of custom JSON adapters to be used during the parsing process
2626
* @param customAdaptersWithType A map of custom JSON adapters with their respective types
27-
* @param typesToSkip A set of types to be skipped during the parsing process
27+
* @param skipTypes A set of types to be skipped during the parsing process
2828
* @param <PojoT> The type of the POJO to be created
2929
* @return the parsed POJO or null if the parsing fails
3030
*/
@@ -34,9 +34,9 @@ fun <PojoT : Any> jsonFileToPojo(
3434
jsonFilePath: String,
3535
customAdapters: List<Any> = emptyList(),
3636
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
37-
typesToSkip: Set<Class<out Any>> = emptySet()
37+
skipTypes: Set<Class<out Any>> = emptySet()
3838
): PojoT? {
39-
val jsonAdapter = initMoshi<PojoT>(customAdapters, customAdaptersWithType, typesToSkip, pojoType)
39+
val jsonAdapter = initMoshi<PojoT>(customAdapters, customAdaptersWithType, skipTypes, pojoType)
4040
return jsonAdapter.fromJson(bufferFileInResources(jsonFilePath))
4141
}
4242

@@ -46,22 +46,16 @@ fun <PojoT : Any> jsonFileToPojo(jsonFile: JsonFile<PojoT>): PojoT? =
4646
jsonFile.jsonFilePath(),
4747
jsonFile.customAdapters(),
4848
jsonFile.customAdaptersWithType(),
49-
jsonFile.typesToSkip()
49+
jsonFile.skipTypes()
5050
)
5151

5252
inline fun <reified PojoT : Any> jsonFileToPojo(
5353
jsonFilePath: String,
5454
customAdapters: List<Any> = emptyList(),
5555
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
56-
typesToSkip: Set<Class<out Any>> = emptySet()
56+
skipTypes: Set<Class<out Any>> = emptySet()
5757
): PojoT? =
58-
jsonFileToPojo(
59-
PojoT::class.java,
60-
jsonFilePath,
61-
customAdapters,
62-
customAdaptersWithType,
63-
typesToSkip
64-
)
58+
jsonFileToPojo(PojoT::class.java, jsonFilePath, customAdapters, customAdaptersWithType, skipTypes)
6559

6660
/**
6761
* A generic function that parses a JSON string into a POJO (Plain Old Java Object) of type PojoT.
@@ -71,7 +65,7 @@ inline fun <reified PojoT : Any> jsonFileToPojo(
7165
* @param jsonStr The JSON string to be parsed.
7266
* @param customAdapters A list of custom adapters to be used during the parsing process.
7367
* @param customAdaptersWithType A map of custom adapters with their respective types.
74-
* @param typesToSkip A set of classes to be skipped during the parsing process.
68+
* @param skipTypes A set of classes to be skipped during the parsing process.
7569
* @return The parsed POJO of type PojoT.
7670
*/
7771
@JvmOverloads
@@ -80,9 +74,9 @@ fun <PojoT : Any> jsonToPojo(
8074
jsonStr: String,
8175
customAdapters: List<Any> = emptyList(),
8276
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
83-
typesToSkip: Set<Class<out Any>> = emptySet()
77+
skipTypes: Set<Class<out Any>> = emptySet()
8478
): PojoT? {
85-
val jsonAdapter = initMoshi<PojoT>(customAdapters, customAdaptersWithType, typesToSkip, pojoType)
79+
val jsonAdapter = initMoshi<PojoT>(customAdapters, customAdaptersWithType, skipTypes, pojoType)
8680
return jsonAdapter.fromJson(jsonStr)
8781
}
8882

@@ -92,16 +86,16 @@ fun <PojoT : Any> jsonToPojo(jsonString: JsonString<PojoT>): PojoT? =
9286
jsonString.jsonString(),
9387
jsonString.customAdapters(),
9488
jsonString.customAdaptersWithType(),
95-
jsonString.typesToSkip()
89+
jsonString.skipTypes()
9690
)
9791

9892
inline fun <reified PojoT : Any> jsonToPojo(
9993
jsonStr: String,
10094
customAdapters: List<Any> = emptyList(),
10195
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
102-
typesToSkip: Set<Class<out Any>> = emptySet()
96+
skipTypes: Set<Class<out Any>> = emptySet()
10397
): PojoT? =
104-
jsonToPojo(PojoT::class.java, jsonStr, customAdapters, customAdaptersWithType, typesToSkip)
98+
jsonToPojo(PojoT::class.java, jsonStr, customAdapters, customAdaptersWithType, skipTypes)
10599

106100
/**
107101
* Generate a JSON string from a POJO object.
@@ -110,7 +104,7 @@ inline fun <reified PojoT : Any> jsonToPojo(
110104
* @param pojo The POJO object to be converted to JSON.
111105
* @param customAdapters A list of custom adapters for Moshi to use during the conversion.
112106
* @param customAdaptersWithType A map of custom adapters with their respective types.
113-
* @param typesToSkip A set of classes to ignore during the conversion.
107+
* @param skipTypes A set of classes to ignore during the conversion.
114108
* @param indent An optional string for pretty-printing the JSON output.
115109
* @param <PojoT> The type of the POJO object.
116110
* @return A JSON string or null if the input is null.
@@ -121,10 +115,10 @@ fun <PojoT : Any> pojoToJson(
121115
pojo: PojoT,
122116
customAdapters: List<Any> = emptyList(),
123117
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
124-
typesToSkip: Set<Class<out Any>> = emptySet(),
118+
skipTypes: Set<Class<out Any>> = emptySet(),
125119
indent: String? = " "
126120
): String? {
127-
val jsonAdapter = initMoshi<PojoT>(customAdapters, customAdaptersWithType, typesToSkip, pojoType)
121+
val jsonAdapter = initMoshi<PojoT>(customAdapters, customAdaptersWithType, skipTypes, pojoType)
128122
return (indent?.let { jsonAdapter.indent(indent) } ?: jsonAdapter).toJson(pojo)
129123
}
130124

@@ -134,27 +128,27 @@ fun <PojoT : Any> pojoToJson(config: Pojo<PojoT>): String? =
134128
config.pojo(),
135129
config.customAdapters(),
136130
config.customAdaptersWithType(),
137-
config.typesToSkip(),
131+
config.skipTypes(),
138132
config.indent()
139133
)
140134

141135
inline fun <reified PojoT : Any> pojoToJson(
142136
pojo: PojoT,
143137
customAdapters: List<Any> = emptyList(),
144138
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
145-
typesToSkip: Set<Class<out Any>> = emptySet(),
139+
skipTypes: Set<Class<out Any>> = emptySet(),
146140
indent: String? = " "
147141
): String? =
148-
pojoToJson(PojoT::class.java, pojo, customAdapters, customAdaptersWithType, typesToSkip, indent)
142+
pojoToJson(PojoT::class.java, pojo, customAdapters, customAdaptersWithType, skipTypes, indent)
149143

150144
@SuppressWarnings("kotlin:S3923")
151145
private fun <PojoT : Any> initMoshi(
152146
customAdapters: List<Any> = emptyList(),
153147
customAdaptersWithType: Map<Type, List<Either<JsonAdapter<Any>, Factory>>> = emptyMap(),
154-
typesToSkip: Set<Class<out Any>> = emptySet(),
148+
skipTypes: Set<Class<out Any>> = emptySet(),
155149
pojoType: Type
156150
): JsonAdapter<PojoT> {
157-
val moshiBuilder = buildMoshi(customAdapters, customAdaptersWithType, typesToSkip)
151+
val moshiBuilder = buildMoshi(customAdapters, customAdaptersWithType, skipTypes)
158152
return moshiBuilder.build().adapter(pojoType)
159153
}
160154

@@ -169,7 +163,7 @@ internal interface PojoDef<PojoT> {
169163

170164
fun customAdaptersWithType(): Map<Type, List<Either<JsonAdapter<Any>, Factory>>>
171165

172-
fun typesToSkip(): Set<Class<out Any>>
166+
fun skipTypes(): Set<Class<out Any>>
173167

174168
@Value.Default fun indent(): String = " "
175169
}
@@ -196,7 +190,7 @@ internal interface JsonConfig<PojoT> {
196190

197191
fun customAdaptersWithType(): Map<Type, List<Either<JsonAdapter<Any>, Factory>>>
198192

199-
fun typesToSkip(): Set<Class<out Any>>
193+
fun skipTypes(): Set<Class<out Any>>
200194
}
201195

202196
@ConfigForJson

src/main/kotlin/com/salesforce/revoman/internal/exe/ExeUtils.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import arrow.core.Either.Left
1414
import arrow.core.Either.Right
1515
import com.salesforce.revoman.input.config.Kick
1616
import com.salesforce.revoman.input.config.StepPick.ExeStepPick
17-
import com.salesforce.revoman.internal.postman.pm
1817
import com.salesforce.revoman.internal.postman.template.Item
1918
import com.salesforce.revoman.output.ExeType
2019
import com.salesforce.revoman.output.Rundown
@@ -109,11 +108,7 @@ internal fun shouldHaltExecution(
109108
currentStepReport.exeTypeForFailure == exeType &&
110109
postTxnPick.pick(
111110
currentStepReport,
112-
Rundown(
113-
stepReports + currentStepReport,
114-
pm.environment,
115-
kick.haltOnFailureOfTypeExcept(),
116-
),
111+
Rundown(stepReports + currentStepReport, kick.haltOnFailureOfTypeExcept()),
117112
)
118113
}
119114
?.any { it }

0 commit comments

Comments
 (0)