From 98e2623dbab9926dc38581a2e648b223333df511 Mon Sep 17 00:00:00 2001 From: Natan Vieira Date: Fri, 17 Mar 2023 18:01:05 -0300 Subject: [PATCH] Update blueprint properties and tests --- .../blueprint/parser/BlueprintParser.kt | 6 +- .../service/blueprint/parser/Constraints.kt | 6 + .../service/blueprint/parser/Properties.kt | 72 +++++++++++ .../service/blueprint/parser/Property.kt | 50 ++------ .../service/blueprint/parser/ParserTest.kt | 4 +- .../blueprint/parser/ParserTestUtils.kt | 7 +- .../service/blueprint/parser/ReadTest.kt | 112 ++++++++++-------- .../parser/TopLevelPropertiesParserTest.kt | 62 ---------- 8 files changed, 158 insertions(+), 161 deletions(-) create mode 100644 services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Properties.kt delete mode 100644 services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/TopLevelPropertiesParserTest.kt diff --git a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/BlueprintParser.kt b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/BlueprintParser.kt index efb1a51d..e6000369 100644 --- a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/BlueprintParser.kt +++ b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/BlueprintParser.kt @@ -9,7 +9,6 @@ import com.typesafe.config.ConfigSyntax import com.typesafe.config.ConfigValue import com.typesafe.config.ConfigValueType import kotlinx.serialization.SerializationException -import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonNull @@ -191,10 +190,7 @@ internal class BlueprintParser(private val supportedProperties: List = return } - private fun checkPropertyAndNodeKindEquality( - kind: KClass, - nodeType: ConfigValueType - ) { + private fun checkPropertyAndNodeKindEquality(kind: KClass, nodeType: ConfigValueType) { val targetNodeType = nodeValueTypeFromKind(kind) if (nodeType != targetNodeType) { error("Wrong value type. Expected: $targetNodeType, given: $nodeType") diff --git a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Constraints.kt b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Constraints.kt index 41b7be57..8c99c378 100644 --- a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Constraints.kt +++ b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Constraints.kt @@ -26,3 +26,9 @@ internal object NotBlankPropertyConstraint : PropertyConstraint { check(value.isNotBlank()) { "${property.qualifiedName} cannot be blank" } } } + +internal object EnvironmentVariableConstraint : PropertyConstraint { + override fun check(property: Property, actualKind: KClass?, value: Any?) { + // TODO + } +} diff --git a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Properties.kt b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Properties.kt new file mode 100644 index 00000000..8a005540 --- /dev/null +++ b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Properties.kt @@ -0,0 +1,72 @@ +package org.katan.service.blueprint.parser + +import org.katan.service.blueprint.parser.PropertyKind.Literal +import org.katan.service.blueprint.parser.PropertyKind.Mixed +import org.katan.service.blueprint.parser.PropertyKind.Multiple +import org.katan.service.blueprint.parser.PropertyKind.Struct + +internal object Properties { + val Name = Property( + qualifiedName = "name", + kind = Literal, + constraints = listOf(RequiredPropertyConstraint, NotBlankPropertyConstraint) + ) + val Version = Property( + qualifiedName = "version", + kind = Literal, + constraints = listOf(RequiredPropertyConstraint, NotBlankPropertyConstraint) + ) + val Build = Property( + qualifiedName = "build", + kind = Struct + ) + val Entrypoint = Property( + qualifiedName = "build.entrypoint", + kind = Literal + ) + val Image = Property( + qualifiedName = "build.image", + kind = Mixed( + Literal, + Multiple(Struct) + ), + constraints = listOf(RequiredPropertyConstraint) + ) + val ImageReference = Property( + qualifiedName = "build.image.ref", + kind = Literal, + constraints = listOf(RequiredPropertyConstraint) + ) + val ImageTag = Property( + qualifiedName = "build.image.tag", + kind = Literal, + constraints = listOf(RequiredPropertyConstraint) + ) + val Instance = Property( + qualifiedName = "build.instance", + kind = Struct + ) + val InstanceName = Property( + qualifiedName = "build.instance.name", + kind = Literal + ) + val Options = Property( + qualifiedName = "options", + kind = Struct + ) + val OptionsId = Property( + qualifiedName = "options.id", + kind = Literal, + constraints = listOf(RequiredPropertyConstraint) + ) + val OptionsType = Property( + qualifiedName = "options.type", + kind = Literal, + constraints = listOf(RequiredPropertyConstraint) + ) + val OptionsEnv = Property( + qualifiedName = "options.env", + kind = Literal, + constraints = listOf(EnvironmentVariableConstraint) + ) +} diff --git a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Property.kt b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Property.kt index 4f84a6e7..0a654fed 100644 --- a/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Property.kt +++ b/services/blueprint-service/src/main/kotlin/org/katan/service/blueprint/parser/Property.kt @@ -1,6 +1,5 @@ package org.katan.service.blueprint.parser -import org.katan.service.blueprint.parser.PropertyKind.Literal import org.katan.service.blueprint.parser.PropertyKind.Mixed import org.katan.service.blueprint.parser.PropertyKind.Multiple import kotlin.reflect.KClass @@ -13,7 +12,7 @@ internal data class Property( val constraints: List = listOf() ) { - val name: String get() = qualifiedName.substringAfterLast(PROPERTY_NAME_SEPARATOR) + val nameStructure: List get() = qualifiedName.split(PROPERTY_NAME_SEPARATOR) fun supports(kind: KClass): Boolean { return supports(this.kind, kind) @@ -52,44 +51,11 @@ internal val AllSupportedProperties: List = listOf( Properties.Entrypoint, Properties.Image, Properties.ImageReference, - Properties.ImageTag + Properties.ImageTag, + Properties.Instance, + Properties.InstanceName, + Properties.Options, + Properties.OptionsId, + Properties.OptionsType, + Properties.OptionsEnv ) - -internal object Properties { - val Name = Property( - qualifiedName = "name", - kind = Literal, - constraints = listOf(RequiredPropertyConstraint, NotBlankPropertyConstraint) - ) - val Version = Property( - qualifiedName = "version", - kind = Literal, - constraints = listOf(RequiredPropertyConstraint, NotBlankPropertyConstraint) - ) - val Build = Property( - qualifiedName = "build", - kind = PropertyKind.Struct - ) - val Entrypoint = Property( - qualifiedName = "build.entrypoint", - kind = Literal - ) - val Image = Property( - qualifiedName = "build.image", - kind = Mixed( - Literal, - Multiple(PropertyKind.Struct) - ), - constraints = listOf(RequiredPropertyConstraint) - ) - val ImageReference = Property( - qualifiedName = "build.image.ref", - kind = Literal, - constraints = listOf(RequiredPropertyConstraint) - ) - val ImageTag = Property( - qualifiedName = "build.image.tag", - kind = Literal, - constraints = listOf(RequiredPropertyConstraint) - ) -} diff --git a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTest.kt b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTest.kt index 6efdd5c0..47203c18 100644 --- a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTest.kt +++ b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTest.kt @@ -15,9 +15,7 @@ class ParserTest { ) assertFailsWith { - withParserTest(listOf(property)) { - read(input) - } + withParserTest(input, property) } } } diff --git a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTestUtils.kt b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTestUtils.kt index d091e214..cd490b3c 100644 --- a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTestUtils.kt +++ b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ParserTestUtils.kt @@ -1,9 +1,9 @@ package org.katan.service.blueprint.parser -private val parser = BlueprintParser() +import kotlinx.serialization.json.JsonObject internal inline fun withParserTest(crossinline block: BlueprintParser.() -> R): R { - return block(parser) + return block(BlueprintParser()) } internal inline fun withParserTest( @@ -12,3 +12,6 @@ internal inline fun withParserTest( ): R { return block(BlueprintParser(supportedProperties.toList())) } + +internal fun withParserTest(input: String, vararg supportedProperties: Property): JsonObject = + BlueprintParser(supportedProperties.toList()).read(input) diff --git a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ReadTest.kt b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ReadTest.kt index 8f9df903..77d72637 100644 --- a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ReadTest.kt +++ b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/ReadTest.kt @@ -20,6 +20,7 @@ class ReadTest { """.trimIndent() val result = withParserTest( + input, Property( qualifiedName = "root", kind = PropertyKind.Struct @@ -28,9 +29,7 @@ class ReadTest { qualifiedName = "root.nested", kind = PropertyKind.Numeric ) - ) { - read(input) - } + ) assertEquals( expected = buildJsonObject { @@ -43,7 +42,7 @@ class ReadTest { } @Test - fun `deep nested struct`() { + fun `multi-level nested struct`() { val input = """ root { nested-1 = 1 @@ -55,6 +54,7 @@ class ReadTest { """.trimIndent() val result = withParserTest( + input, Property( qualifiedName = "root", kind = PropertyKind.Struct @@ -71,9 +71,7 @@ class ReadTest { qualifiedName = "root.nested-2.nested-2-1", kind = PropertyKind.Literal ) - ) { - read(input) - } + ) assertEquals( expected = buildJsonObject { @@ -89,19 +87,15 @@ class ReadTest { } @Test - fun `accept number in numeric list`() { + fun `number in list of numeric`() { val input = """ root = [1, 2, 3, 4] """.trimIndent() val result = withParserTest( - Property( - qualifiedName = "root", - kind = PropertyKind.Multiple(PropertyKind.Numeric) - ) - ) { - read(input) - } + input, + Property("root", PropertyKind.Multiple(PropertyKind.Numeric)) + ) assertEquals( expected = buildJsonObject { @@ -115,19 +109,15 @@ class ReadTest { } @Test - fun `accept string in literals list`() { + fun `string in list of literals`() { val input = """ root = ["a", "b", "c"] """.trimIndent() val result = withParserTest( - Property( - qualifiedName = "root", - kind = PropertyKind.Multiple(PropertyKind.Literal) - ) - ) { - read(input) - } + input, + Property("root", PropertyKind.Multiple(PropertyKind.Literal)) + ) assertEquals( expected = buildJsonObject { @@ -142,19 +132,15 @@ class ReadTest { } @Test - fun `accept null in null list`() { + fun `null in list of nulls`() { val input = """ root = [null, null, null] """.trimIndent() val result = withParserTest( - Property( - qualifiedName = "root", - kind = PropertyKind.Multiple(PropertyKind.Null) - ) - ) { - read(input) - } + input, + Property("root", PropertyKind.Multiple(PropertyKind.Null)) + ) assertEquals( expected = buildJsonObject { @@ -170,19 +156,21 @@ class ReadTest { } @Test - fun `accept number in mixed numeric and literal`() { + fun `number in mixed of numeric and literal`() { val input = """ value = 1 """.trimIndent() val result = withParserTest( + input, Property( - qualifiedName = "value", - kind = PropertyKind.Mixed(PropertyKind.Numeric, PropertyKind.Literal) + "value", + PropertyKind.Mixed( + PropertyKind.Numeric, + PropertyKind.Literal + ) ) - ) { - read(input) - } + ) assertEquals( expected = buildJsonObject { @@ -193,19 +181,21 @@ class ReadTest { } @Test - fun `accept string in mixed numeric and literal`() { + fun `string in mixed of numeric and literal`() { val input = """ value = "1" """.trimIndent() val result = withParserTest( + input, Property( - qualifiedName = "value", - kind = PropertyKind.Mixed(PropertyKind.Numeric, PropertyKind.Literal) + "value", + PropertyKind.Mixed( + PropertyKind.Numeric, + PropertyKind.Literal + ) ) - ) { - read(input) - } + ) assertEquals( expected = buildJsonObject { @@ -216,7 +206,7 @@ class ReadTest { } @Test - fun `accept list in multiple of struct with mixed kind`() { + fun `multiple of struct with mixed kind`() { val input = """ data = [{ a = "test 1" @@ -233,6 +223,7 @@ class ReadTest { """.trimIndent() val result = withParserTest( + input, Property( qualifiedName = "data", kind = PropertyKind.Multiple(PropertyKind.Struct) @@ -253,9 +244,7 @@ class ReadTest { qualifiedName = "data.b.c", kind = PropertyKind.TrueOrFalse ) - ) { - read(input) - } + ) assertEquals( expected = buildJsonObject { @@ -288,4 +277,33 @@ class ReadTest { actual = result ) } + + @Test + fun `unnamed struct in struct of structs`() { + val input = """ + data { + "A" { + key = 1 + } + } + """.trimIndent() + + val result = withParserTest( + input, + Property("data", PropertyKind.Struct), + Property("data.*", PropertyKind.Struct), + Property("data.*.key", PropertyKind.Literal) + ) + assertEquals( + expected = buildJsonObject { + put( + "A", + buildJsonObject { + put("key", 1) + } + ) + }, + actual = result + ) + } } diff --git a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/TopLevelPropertiesParserTest.kt b/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/TopLevelPropertiesParserTest.kt deleted file mode 100644 index 7dde6cda..00000000 --- a/services/blueprint-service/src/test/kotlin/org/katan/service/blueprint/parser/TopLevelPropertiesParserTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -package org.katan.service.blueprint.parser - -// class TopLevelPropertiesParserTest { -// -// @Test -// fun `missing property 'name'`() { -// val input = """ -// version = "test" -// """.trimIndent() -// -// val exception = withParserTest { -// assertFailsWith { -// parse(input) -// } -// } -// assertEquals(Properties.Name, exception.property) -// } -// -// @Test -// fun `missing property 'version'`() { -// val input = """ -// name = "test" -// """.trimIndent() -// -// val exception = withParserTest { -// assertFailsWith { -// parse(input) -// } -// } -// assertEquals(Properties.Version, exception.property) -// } -// -// @Test -// fun `blank property 'name'`() { -// val input = """ -// name = "" -// version = "0.0.0" -// """.trimIndent() -// -// val exception = withParserTest { -// assertFailsWith { -// parse(input) -// } -// } -// assertEquals(Properties.Name, exception.property) -// } -// -// @Test -// fun `blank property 'version'`() { -// val input = """ -// name = "test" -// version = "" -// """.trimIndent() -// -// val exception = withParserTest { -// assertFailsWith { -// parse(input) -// } -// } -// assertEquals(Properties.Version, exception.property) -// } -// }