-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add flagd java provider integration tests
- Loading branch information
1 parent
b0a5d08
commit 3006381
Showing
10 changed files
with
707 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
{ | ||
"$schema": "https://flagd.dev/schema/v0/flags.json", | ||
"flags": { | ||
"boolean-flag-1": { | ||
"state": "ENABLED", | ||
"variants": { | ||
"on": true, | ||
"off": false | ||
}, | ||
"defaultVariant": "on" | ||
}, | ||
"string-variant-flag-1": { | ||
"state": "ENABLED", | ||
"defaultVariant": "key-1", | ||
"variants": { | ||
"key-1": "string-value-1", | ||
"key-2": "string-value-1" | ||
}, | ||
"targeting": {} | ||
}, | ||
"int-variant-flag-1": { | ||
"state": "ENABLED", | ||
"defaultVariant": "key-1", | ||
"variants": { | ||
"key-1": 13, | ||
"key-2": 88 | ||
}, | ||
"targeting": {} | ||
}, | ||
"double-variant-flag-1": { | ||
"state": "ENABLED", | ||
"defaultVariant": "key-2", | ||
"variants": { | ||
"key-1": 88.0, | ||
"key-2": 17.1 | ||
}, | ||
"targeting": {} | ||
}, | ||
"structure-variant-flag-1": { | ||
"state": "ENABLED", | ||
"defaultVariant": "structure-1", | ||
"variants": { | ||
"structure-1": { | ||
"field": "string", | ||
"intField": 33 | ||
}, | ||
"structure-2": { | ||
"field": "other", | ||
"intField": 10001 | ||
} | ||
}, | ||
"targeting": {} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
187 changes: 187 additions & 0 deletions
187
...ider-java-it/src/test/scala/io/cardell/openfeature/java/provider/JavaProviderItTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
/* | ||
* Copyright 2023 Alex Cardell | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.cardell.openfeature.provider.java | ||
|
||
import cats.effect.IO | ||
import cats.effect.kernel.Resource | ||
import cats.syntax.all._ | ||
import com.dimafeng.testcontainers.ContainerDef | ||
import com.dimafeng.testcontainers.DockerComposeContainer | ||
import com.dimafeng.testcontainers.ExposedService | ||
import com.dimafeng.testcontainers.munit.TestContainerForAll | ||
import dev.openfeature.contrib.providers.flagd.FlagdOptions | ||
import dev.openfeature.contrib.providers.flagd.FlagdProvider | ||
import java.io.File | ||
import munit.CatsEffectSuite | ||
import org.testcontainers.containers.wait.strategy.Wait | ||
|
||
import io.cardell.openfeature.EvaluationContext | ||
import io.cardell.openfeature.FeatureClient | ||
import io.cardell.openfeature.OpenFeature | ||
|
||
class JavaProviderItTest extends CatsEffectSuite with TestContainerForAll { | ||
|
||
override val containerDef: ContainerDef = DockerComposeContainer.Def( | ||
new File("docker-compose.yaml"), | ||
exposedServices = Seq( | ||
ExposedService( | ||
"flagd", | ||
8013, | ||
Wait.forLogMessage("^.*watching filepath.*", 1) | ||
) | ||
), | ||
tailChildContainers = true | ||
) | ||
|
||
def flagd(containers: Containers): Resource[IO, FeatureClient[IO]] = { | ||
val container = | ||
containers | ||
.asInstanceOf[DockerComposeContainer] | ||
.getContainerByServiceName("flagd") | ||
.get | ||
|
||
val flagdProvder = | ||
new FlagdProvider( | ||
FlagdOptions | ||
.builder() | ||
.host(container.getHost()) | ||
.port(container.getMappedPort(8013).toInt) | ||
.build() | ||
) | ||
|
||
JavaProvider | ||
.resource[IO](flagdProvder) | ||
.map(OpenFeature[IO]) | ||
.evalMap(_.client) | ||
} | ||
|
||
val evaluationContext = EvaluationContext.empty | ||
|
||
test("can fetch boolean flag") { | ||
val expected = true | ||
|
||
withContainers { containers => | ||
flagd(containers) | ||
.use { provider => | ||
for { | ||
res <- provider.getBooleanDetails( | ||
"boolean-flag-1", | ||
false, | ||
EvaluationContext.empty | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
test("uses default when boolean flag missing") { | ||
val expected = false | ||
|
||
withContainers { containers => | ||
flagd(containers).use { provider => | ||
for { | ||
res <- provider.getBooleanDetails( | ||
"no-flag", | ||
false, | ||
EvaluationContext.empty | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
test("can resolve string value for provider variant flag") { | ||
val expected = "string-value-1" | ||
|
||
withContainers { containers => | ||
flagd(containers).use { provider => | ||
for { | ||
res <- provider.getStringDetails( | ||
"string-variant-flag-1", | ||
"default-string", | ||
evaluationContext | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
test("uses default when string flag missing") { | ||
val expected = "some-string" | ||
|
||
withContainers { containers => | ||
flagd(containers).use { provider => | ||
for { | ||
res <- provider.getStringDetails( | ||
"no-flag", | ||
expected, | ||
EvaluationContext.empty | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
test("can resolve int value for provider variant flag") { | ||
val expected = 13 | ||
|
||
withContainers { containers => | ||
flagd(containers).use { provider => | ||
for { | ||
res <- provider.getIntDetails( | ||
"int-variant-flag-1", | ||
99, | ||
evaluationContext | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
test("can resolve double value for provider variant flag") { | ||
val expected = 17.1 | ||
|
||
withContainers { containers => | ||
flagd(containers).use { provider => | ||
for { | ||
res <- provider.getDoubleDetails( | ||
"double-variant-flag-1", | ||
99.9, | ||
evaluationContext | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
test("can deserialise variant match") { | ||
val expected = TestVariant("string", 33) | ||
|
||
withContainers { containers => | ||
flagd(containers).use { provider => | ||
for { | ||
res <- provider.getStructureDetails[TestVariant]( | ||
"structure-variant-flag-1", | ||
TestVariant("a", 0), | ||
evaluationContext | ||
) | ||
} yield assertEquals(res.value, expected) | ||
} | ||
} | ||
} | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
...re/provider-java-it/src/test/scala/io/cardell/openfeature/java/provider/TestVariant.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright 2023 Alex Cardell | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.cardell.openfeature.provider.java | ||
|
||
import io.cardell.openfeature.FlagValue | ||
import io.cardell.openfeature.FlagValue.IntValue | ||
import io.cardell.openfeature.FlagValue.StringValue | ||
import io.cardell.openfeature.Structure | ||
import io.cardell.openfeature.StructureDecoder | ||
import io.cardell.openfeature.StructureDecoderError | ||
import io.cardell.openfeature.StructureEncoder | ||
|
||
case class TestVariant(field: String, intField: Int) | ||
|
||
object TestVariant { | ||
|
||
implicit val sd: StructureDecoder[TestVariant] = | ||
new StructureDecoder[TestVariant] { | ||
|
||
def decodeStructure( | ||
s: Structure | ||
): Either[StructureDecoderError, TestVariant] = { | ||
val maybeStruct = | ||
for { | ||
field <- s.values.get("field") | ||
intField <- s.values.get("intField") | ||
variant <- | ||
(field, intField) match { | ||
case (StringValue(s), IntValue(i)) => Some(TestVariant(s, i)) | ||
case _ => None | ||
} | ||
} yield variant | ||
|
||
maybeStruct match { | ||
case None => | ||
Left( | ||
StructureDecoderError( | ||
new Throwable( | ||
"some fields missing converting TestVariant to Structure" | ||
) | ||
) | ||
) | ||
case Some(value) => Right(value) | ||
} | ||
|
||
} | ||
|
||
} | ||
|
||
implicit val se: StructureEncoder[TestVariant] = | ||
new StructureEncoder[TestVariant] { | ||
|
||
def encodeStructure( | ||
in: TestVariant | ||
): Structure = Structure( | ||
Map( | ||
"field" -> StringValue(in.field), | ||
"intField" -> IntValue(in.intField) | ||
) | ||
) | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.