Skip to content

Commit 40b9326

Browse files
Separate exposures from evaluations in the test to improve performance
1 parent 138cfe6 commit 40b9326

File tree

2 files changed

+45
-26
lines changed

2 files changed

+45
-26
lines changed

dd-smoke-tests/openfeature/src/test/groovy/datadog/smoketest/springboot/OpenFeatureProviderSmokeTest.groovy

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,28 @@
11
package datadog.smoketest.springboot
22

3-
import com.squareup.moshi.Moshi
43
import datadog.remoteconfig.Capabilities
54
import datadog.remoteconfig.Product
65
import datadog.smoketest.AbstractServerSmokeTest
7-
import datadog.trace.api.featureflag.exposure.ExposuresRequest
86
import groovy.json.JsonOutput
97
import groovy.json.JsonSlurper
108
import java.nio.file.Files
119
import java.nio.file.Paths
1210
import okhttp3.MediaType
1311
import okhttp3.Request
1412
import okhttp3.RequestBody
15-
import okio.Okio
1613
import spock.lang.Shared
14+
import spock.lang.Stepwise
1715
import spock.util.concurrent.PollingConditions
1816

19-
class OpenFeatureProviderSmokeTest extends AbstractServerSmokeTest {
17+
/** Due to the exposure cache it's important to run the tests in the specified order */
18+
@Stepwise
19+
class OpenFeatureProviderSmokeTest extends AbstractServerSmokeTest {
2020

2121
@Shared
2222
private final rcPayload = new JsonSlurper().parse(fetchResource("config/flags-v1.json")).with { json ->
2323
return JsonOutput.toJson(json.data.attributes)
2424
}
2525

26-
@Shared
27-
private final moshi = new Moshi.Builder().build().adapter(ExposuresRequest)
28-
29-
@Shared
30-
private final exposurePoll = new PollingConditions(timeout: 5, initialDelay: 0, delay: 0.1D, factor: 2)
31-
3226
@Override
3327
ProcessBuilder createProcessBuilder() {
3428
setRemoteConfig("datadog/2/FFE_FLAGS/1/config", rcPayload)
@@ -51,21 +45,57 @@ class OpenFeatureProviderSmokeTest extends AbstractServerSmokeTest {
5145
if (!path.contains('api/v2/exposures')) {
5246
return null
5347
}
54-
return moshi.fromJson(Okio.buffer(Okio.source(new ByteArrayInputStream(body))))
48+
return new JsonSlurper().parse(body)
5549
}
5650
}
5751

5852
void 'test remote config'() {
5953
when:
60-
final rcRequest = waitForRcClientRequest {req ->
61-
decodeProducts(req).find {it == Product.FFE_FLAGS } != null
54+
final rcRequest = waitForRcClientRequest { req ->
55+
decodeProducts(req).find { it == Product.FFE_FLAGS } != null
6256
}
6357

6458
then:
6559
final capabilities = decodeCapabilities(rcRequest)
6660
hasCapability(capabilities, Capabilities.CAPABILITY_FFE_FLAG_CONFIGURATION_RULES)
6761
}
6862

63+
void 'test open feature exposures'() {
64+
setup:
65+
setRemoteConfig("datadog/2/FFE_FLAGS/1/config", rcPayload)
66+
final url = "http://localhost:${httpPort}/openfeature/evaluate"
67+
final testCases = parseTestCases().findAll {
68+
it.result.flagMetadata?.doLog
69+
}
70+
71+
when:
72+
final responses = testCases.collect {
73+
testCase ->
74+
final request = new Request.Builder()
75+
.url(url)
76+
.post(RequestBody.create(MediaType.parse('application/json'), JsonOutput.toJson(testCase)))
77+
.build()
78+
client.newCall(request).execute()
79+
}
80+
81+
then:
82+
responses.every {
83+
it.code() == 200
84+
}
85+
new PollingConditions(timeout: 10).eventually {
86+
final requests = evpProxyMessages*.getV2() as List<Map<String, Object>>
87+
final events = requests*.exposures.flatten()
88+
assert events.size() == testCases.size()
89+
testCases.each {
90+
testCase ->
91+
assert events.find {
92+
event ->
93+
event.flag.key == testCase.flag && event.subject.id == testCase.targetingKey
94+
} != null : "Unable to find exposure with flag=${testCase.flag} and targetingKey=${testCase.targetingKey}"
95+
}
96+
}
97+
}
98+
6999
void 'test open feature evaluation'() {
70100
setup:
71101
setRemoteConfig("datadog/2/FFE_FLAGS/1/config", rcPayload)
@@ -84,14 +114,6 @@ class OpenFeatureProviderSmokeTest extends AbstractServerSmokeTest {
84114
responseBody.value == testCase.result.value
85115
responseBody.variant == testCase.result.variant
86116
responseBody.flagMetadata?.allocationKey == testCase.result.flagMetadata?.allocationKey
87-
if (testCase.result.flagMetadata?.doLog) {
88-
waitForEvpProxyMessage(exposurePoll) {
89-
final exposure = it.v2 as ExposuresRequest
90-
return exposure.exposures.first().with {
91-
it.flag.key == testCase.flag && it.subject.id == testCase.targetingKey
92-
}
93-
}
94-
}
95117

96118
where:
97119
testCase << parseTestCases()
@@ -123,7 +145,7 @@ class OpenFeatureProviderSmokeTest extends AbstractServerSmokeTest {
123145
}
124146

125147
private static Set<Product> decodeProducts(final Map<String, Object> request) {
126-
return request.client.products.collect { Product.valueOf(it)}
148+
return request.client.products.collect { Product.valueOf(it) }
127149
}
128150

129151
private static long decodeCapabilities(final Map<String, Object> request) {

dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,10 @@ abstract class AbstractSmokeTest extends ProcessManager {
183183
if (decoded) {
184184
evpProxyMessages.add(new Tuple2<>(path, decoded))
185185
}
186-
response.status(200).send()
187186
} catch (Throwable t) {
188-
println("=== Failure during evp proxy message decoding ===")
189-
t.printStackTrace(System.out)
190187
evpProxyMessageDecodingFailure = t
191-
throw t
192188
}
189+
response.status(200).send()
193190
}
194191
}
195192
}

0 commit comments

Comments
 (0)