diff --git a/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/endpoints/DefaultEndpointProviderTestGenerator.kt b/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/endpoints/DefaultEndpointProviderTestGenerator.kt index a6f4be3ac8..97d3f4569b 100644 --- a/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/endpoints/DefaultEndpointProviderTestGenerator.kt +++ b/codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/endpoints/DefaultEndpointProviderTestGenerator.kt @@ -61,7 +61,6 @@ class DefaultEndpointProviderTestGenerator( fun render() { writer.addImport("*", namespace = "kotlin.test") writer.withBlock("public class #L {", "}", CLASS_NAME) { - writer.write("") writer.withBlock( "private fun expectEqualEndpoints(expected: #1T, actual: #1T) {", "}", @@ -79,19 +78,15 @@ class DefaultEndpointProviderTestGenerator( RuntimeTypes.Core.Collections.toMutableAttributes, ) writer.write( - "if (actual.attributes.contains(#1T)) newActualAttributes.remove(#1T)", + "newActualAttributes.remove(#T)", RuntimeTypes.Core.BusinessMetrics.ServiceEndpointOverride, ) writer.write( - "if (actual.attributes.contains(#1T)) newActualAttributes.remove(#1T)", + "newActualAttributes.remove(#T)", RuntimeTypes.Core.BusinessMetrics.AccountIdBasedEndpointAccountId, ) writer.write( - "val newActualAttributesOrEmpty = if (newActualAttributes.isEmpty) #T() else newActualAttributes", - RuntimeTypes.Core.Collections.emptyAttributes, - ) - writer.write( - "val newActual = #T(actual.uri, actual.headers, newActualAttributesOrEmpty)", + "val newActual = #T(actual.uri, actual.headers, newActualAttributes)", RuntimeTypes.SmithyClient.Endpoints.Endpoint, ) writer.write("assertEquals(expected, newActual)") diff --git a/runtime/protocol/http/api/http.api b/runtime/protocol/http/api/http.api index 6e2863bf8f..3f4c29414f 100644 --- a/runtime/protocol/http/api/http.api +++ b/runtime/protocol/http/api/http.api @@ -52,6 +52,7 @@ public final class aws/smithy/kotlin/runtime/http/HeadersBuilder : aws/smithy/ko public abstract class aws/smithy/kotlin/runtime/http/HttpBody { public static final field Companion Laws/smithy/kotlin/runtime/http/HttpBody$Companion; + public fun equals (Ljava/lang/Object;)Z public fun getContentLength ()Ljava/lang/Long; public fun isDuplex ()Z public fun isOneShot ()Z @@ -74,6 +75,7 @@ public final class aws/smithy/kotlin/runtime/http/HttpBody$Companion { public final class aws/smithy/kotlin/runtime/http/HttpBody$Empty : aws/smithy/kotlin/runtime/http/HttpBody { public static final field INSTANCE Laws/smithy/kotlin/runtime/http/HttpBody$Empty; + public fun equals (Ljava/lang/Object;)Z public fun getContentLength ()Ljava/lang/Long; public final fun isOneShot ()Z } diff --git a/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/DeferredHeaders.kt b/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/DeferredHeaders.kt index d410be45e9..db134a7146 100644 --- a/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/DeferredHeaders.kt +++ b/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/DeferredHeaders.kt @@ -35,6 +35,7 @@ private object EmptyDeferredHeaders : DeferredHeaders { override fun entries(): Set>>> = emptySet() override fun contains(name: String): Boolean = false override fun isEmpty(): Boolean = true + override fun equals(other: Any?): Boolean = other is DeferredHeaders && other.isEmpty() } /** diff --git a/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/Headers.kt b/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/Headers.kt index d73832f612..b9611fa450 100644 --- a/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/Headers.kt +++ b/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/Headers.kt @@ -32,6 +32,7 @@ private object EmptyHeaders : Headers { override fun entries(): Set>> = emptySet() override fun contains(name: String): Boolean = false override fun isEmpty(): Boolean = true + override fun equals(other: Any?): Boolean = other is Headers && other.isEmpty() } /** diff --git a/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/HttpBody.kt b/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/HttpBody.kt index df70ae8461..ed8ef428bf 100644 --- a/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/HttpBody.kt +++ b/runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/HttpBody.kt @@ -35,12 +35,19 @@ public sealed class HttpBody { */ public open val isDuplex: Boolean = false + override fun equals(other: Any?): Boolean = + other is HttpBody && + other.contentLength == contentLength && + other.isOneShot == isOneShot && + other.isDuplex == isDuplex + /** * Variant of a [HttpBody] without a payload */ public object Empty : HttpBody() { final override val isOneShot: Boolean = false override val contentLength: Long = 0 + override fun equals(other: Any?): Boolean = other is HttpBody && other.contentLength == contentLength } /** diff --git a/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/DeferredHeadersTest.kt b/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/DeferredHeadersTest.kt new file mode 100644 index 0000000000..18e15a287f --- /dev/null +++ b/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/DeferredHeadersTest.kt @@ -0,0 +1,22 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.smithy.kotlin.runtime.http + +import kotlin.test.Test +import kotlin.test.assertEquals + +class DeferredHeadersTest { + @Test + fun testEmptyEquals() { + val explicitlyEmpty = DeferredHeaders.Empty + val implicitlyEmpty = DeferredHeadersBuilder().build() + + assertEquals(implicitlyEmpty, explicitlyEmpty) + assertEquals(explicitlyEmpty, implicitlyEmpty) + + assertEquals(explicitlyEmpty, explicitlyEmpty) + assertEquals(implicitlyEmpty, implicitlyEmpty) + } +} diff --git a/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HeadersTest.kt b/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HeadersTest.kt index 6059c58d79..12287dcc8d 100644 --- a/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HeadersTest.kt +++ b/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HeadersTest.kt @@ -55,4 +55,16 @@ class HeadersTest { assertEquals(firstExpected.entries, first.entries()) assertEquals(secondExpected.entries, second.entries()) } + + @Test + fun testEmptyEquals() { + val explicitlyEmpty = Headers.Empty + val implicitlyEmpty = HeadersBuilder().build() + + assertEquals(implicitlyEmpty, explicitlyEmpty) + assertEquals(explicitlyEmpty, implicitlyEmpty) + + assertEquals(explicitlyEmpty, explicitlyEmpty) + assertEquals(implicitlyEmpty, implicitlyEmpty) + } } diff --git a/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HttpBodyTest.kt b/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HttpBodyTest.kt index 1458eb3d32..844d054166 100644 --- a/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HttpBodyTest.kt +++ b/runtime/protocol/http/common/test/aws/smithy/kotlin/runtime/http/HttpBodyTest.kt @@ -79,4 +79,16 @@ class HttpBodyTest { assertEquals(expected, body.readAll()!!.decodeToString()) } + + @Test + fun testEmptyEquals() { + val explicitlyEmpty = HttpBody.Empty + val implicitlyEmpty = HttpBody.fromBytes(byteArrayOf()) + + assertEquals(implicitlyEmpty, explicitlyEmpty) + assertEquals(explicitlyEmpty, implicitlyEmpty) + + assertEquals(implicitlyEmpty, implicitlyEmpty) + assertEquals(explicitlyEmpty, explicitlyEmpty) + } } diff --git a/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/collections/Attributes.kt b/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/collections/Attributes.kt index f13e169223..1fffcc82a2 100644 --- a/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/collections/Attributes.kt +++ b/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/collections/Attributes.kt @@ -172,6 +172,7 @@ private object EmptyAttributes : Attributes { override val keys: Set> = emptySet() override fun contains(key: AttributeKey<*>): Boolean = false override fun getOrNull(key: AttributeKey): T? = null + override fun equals(other: Any?): Boolean = other is Attributes && other.isEmpty } /** diff --git a/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/collections/AttributesTest.kt b/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/collections/AttributesTest.kt index c91db10f06..27a00bc107 100644 --- a/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/collections/AttributesTest.kt +++ b/runtime/runtime-core/common/test/aws/smithy/kotlin/runtime/collections/AttributesTest.kt @@ -125,4 +125,16 @@ class AttributesTest { assertEquals("foo", attrs[attr1]) assertEquals(57, attrs[attr2]) } + + @Test + fun testEmptyEquals() { + val explicitlyEmpty = emptyAttributes() + val implicitlyEmpty = AttributesBuilder().attributes + + assertEquals(implicitlyEmpty, explicitlyEmpty) + assertEquals(explicitlyEmpty, implicitlyEmpty) + + assertEquals(explicitlyEmpty, explicitlyEmpty) + assertEquals(implicitlyEmpty, implicitlyEmpty) + } }