Skip to content

Commit 57b92bb

Browse files
author
luigi
committed
fix error message and add double nested list unique items test
1 parent 07693cb commit 57b92bb

File tree

8 files changed

+65
-7
lines changed

8 files changed

+65
-7
lines changed

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/contraints/ConstraintUtilsGenerator.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ internal class ConstraintUtilsGenerator(
4747
write("is Boolean,")
4848
write("is java.time.Instant,")
4949
write("is Number -> v == other.v")
50+
write("is ByteArray -> v.contentEquals(other.v as ByteArray)")
5051
withBlock("is List<*> -> {", "}") {
5152
write("val o = other.v as List<*>")
5253
write("v.size == o.size && v.indices.all { i -> Wrapped(v[i]) == Wrapped(o[i]) }")
@@ -60,6 +61,7 @@ internal class ConstraintUtilsGenerator(
6061
}
6162
withBlock("override fun hashCode(): Int = when (v) {", "}") {
6263
write("null -> 0")
64+
write("is ByteArray -> v.contentHashCode()")
6365
write("is List<*> -> v.fold(1) { acc, e -> 31 * acc + Wrapped(e).hashCode() }")
6466
write("is Map<*, *> -> v.entries.fold(1) { acc, (k, e) -> 31 * acc + Wrapped(k).hashCode() xor Wrapped(e).hashCode() }")
6567
write("else -> v.hashCode()")

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/contraints/LengthConstraint.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal class LengthConstraint(val memberPrefix: String, val memberName: String
1111
val max = trait.max.orElse(null)
1212
writer.write("if (${memberPrefix}$memberName == null) { return }")
1313
writer.withBlock("require(${memberPrefix}$memberName is List<*> || ${memberPrefix}$memberName is Map<*, *> || ${memberPrefix}$memberName is String || ${memberPrefix}$memberName is java.sql.Blob) {", "}") {
14-
write("\"Length trait supports only List, Map, String, or Blob, but type \${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S} was given\"", "null")
14+
write("\"The `length` trait can be applied only to List, Map, String, or Blob, but variable `$memberName` is of type `\${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S}`.\"", "null")
1515
}
1616

1717
if (max != null && min != null) {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/contraints/PatternConstraint.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal class PatternConstraint(val memberPrefix: String, val memberName: Strin
88
override fun render() {
99
writer.write("if (${memberPrefix}$memberName == null) { return }")
1010
writer.withBlock("require(${memberPrefix}$memberName is String) {", "}") {
11-
write("\"Pattern trait supports only String, but type \${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S} was given\"", "null")
11+
write("\"The `pattern` trait can be applied only to String, but variable `$memberName` is of type `\${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S}`.\"", "null")
1212
}
1313
writer.write("val ${memberName}Pattern = #S", trait.pattern)
1414
.write("val ${memberName}Regex = Regex(${memberName}Pattern)")

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/contraints/RangeConstraint.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ internal class RangeConstraint(val memberPrefix: String, val memberName: String,
1010
val max = trait.max.orElse(null)
1111
writer.write("if (${memberPrefix}$memberName == null) { return }")
1212
writer.withBlock("require(${memberPrefix}$memberName is Number) {", "}") {
13-
write("\"Range trait supports only Number, but type \${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S} was given\"", "null")
13+
write("\"The `range` trait can be applied only to Number, but variable `$memberName` is of type `\${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S}`.\"", "null")
1414
}
1515

1616
if (max != null && min != null) {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/contraints/UniqueItemsConstraint.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ internal class UniqueItemsConstraint(val memberPrefix: String, val memberName: S
99
override fun render() {
1010
writer.write("if (${memberPrefix}$memberName == null) { return }")
1111
writer.withBlock("require(${memberPrefix}$memberName is List<*>) {", "}") {
12-
write("\"Unique items trait supports only List, but type \${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S} was given\"", "null")
12+
write("\"The `uniqueItems` trait can be applied only to List, but variable `$memberName` is of type `\${${memberPrefix}$memberName?.javaClass?.simpleName ?: #S}`.\"", "null")
1313
}
1414
writer.write("require(#T(${memberPrefix}$memberName)) { #S }", ServiceTypes(pkgName).hasAllUniqueElements, "$memberName must have unique items")
1515
}

tests/codegen/service-codegen-tests/model/service-constraints-test.smithy

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ service ServiceConstraintsTest {
1515
RangeConstraintTest,
1616
UniqueItemsConstraintTest,
1717
NestedUniqueItemsConstraintTest,
18+
DoubleNestedUniqueItemsConstraintTest,
1819
]
1920
}
2021

@@ -131,6 +132,20 @@ structure NestedUniqueItemsConstraintTestInput {
131132
@output
132133
structure NestedUniqueItemsConstraintTestOutput {}
133134

135+
@http(method: "POST", uri: "/double-nested-unique-items-constraint", code: 201)
136+
operation DoubleNestedUniqueItemsConstraintTest {
137+
input: DoubleNestedUniqueItemsConstraintTestInput
138+
output: DoubleNestedUniqueItemsConstraintTestOutput
139+
}
140+
141+
@input
142+
structure DoubleNestedUniqueItemsConstraintTestInput {
143+
doubleNestedUniqueItemsListInput: UniqueItemsListWrapContainer
144+
}
145+
146+
@output
147+
structure DoubleNestedUniqueItemsConstraintTestOutput {}
148+
134149

135150

136151
list NotUniqueItemsList {
@@ -147,6 +162,11 @@ list UniqueItemsListWrap {
147162
member: UniqueItemsList
148163
}
149164

165+
@uniqueItems
166+
list UniqueItemsListWrapContainer {
167+
member: UniqueItemsListWrap
168+
}
169+
150170
map MyMap {
151171
key: String
152172
value: String

tests/codegen/service-codegen-tests/src/test/kotlin/com/test/ServiceConstraintsTest.kt

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ServiceConstraintsTest {
2525
val requestBodyLimit: Long = 10L * 1024 * 1024
2626
val port: Int = ServerSocket(0).use { it.localPort }
2727

28-
val portListnerTimeout = 10L
28+
val portListenerTimeout = 180L
2929

3030
val baseUrl = "http://localhost:$port"
3131

@@ -36,8 +36,8 @@ class ServiceConstraintsTest {
3636
@BeforeAll
3737
fun boot() {
3838
proc = startService("netty", port, closeGracePeriodMillis, closeTimeoutMillis, requestBodyLimit, projectDir)
39-
val ready = waitForPort(port, portListnerTimeout, proc)
40-
assertTrue(ready, "Service did not start within $portListnerTimeout s")
39+
val ready = waitForPort(port, portListenerTimeout, proc)
40+
assertTrue(ready, "Service did not start within $portListenerTimeout s")
4141
}
4242

4343
@AfterAll
@@ -535,4 +535,37 @@ class ServiceConstraintsTest {
535535
assertEquals(400, body.code)
536536
assertEquals("member must have unique items", body.message)
537537
}
538+
539+
@Test
540+
fun `checks unique items constraint providing non-unique nested nested list`() {
541+
val cbor = Cbor { }
542+
val doubleNestedUniqueItemsListInput = listOf(
543+
listOf(listOf("0"), listOf("1", "2"), listOf("6"), listOf("9", "10", "11")),
544+
listOf(listOf("2"), listOf("7", "2"), listOf("4"), listOf("5", "6", "5")),
545+
listOf(listOf("1"), listOf("1", "2"), listOf("4"), listOf("5", "6", "7")),
546+
)
547+
548+
val requestBytes = cbor.encodeToByteArray(
549+
DoubleNestedUniqueItemsConstraintTestRequest.serializer(),
550+
DoubleNestedUniqueItemsConstraintTestRequest(doubleNestedUniqueItemsListInput),
551+
)
552+
553+
val response = sendRequest(
554+
"$baseUrl/double-nested-unique-items-constraint",
555+
"POST",
556+
requestBytes,
557+
"application/cbor",
558+
"application/cbor",
559+
"correctToken",
560+
)
561+
assertIs<HttpResponse<ByteArray>>(response)
562+
assertEquals(400, response.statusCode(), "Expected 400")
563+
564+
val body = cbor.decodeFromByteArray(
565+
ErrorResponse.serializer(),
566+
response.body(),
567+
)
568+
assertEquals(400, body.code)
569+
assertEquals("member must have unique items", body.message)
570+
}
538571
}

tests/codegen/service-codegen-tests/src/test/kotlin/com/test/ServiceDataClasses.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@ data class UniqueItemsConstraintTestRequest(val notUniqueItemsListInput: List<St
4141

4242
@Serializable
4343
data class NestedUniqueItemsConstraintTestRequest(val nestedUniqueItemsListInput: List<List<String>>)
44+
45+
@Serializable
46+
data class DoubleNestedUniqueItemsConstraintTestRequest(val doubleNestedUniqueItemsListInput: List<List<List<String>>>)

0 commit comments

Comments
 (0)