Kotlin: different Kotlin objects referencing the same WebGPU object match using ==/.equals()

Bug: 374752552
Test: ObjectTest.*
Change-Id: I5ebd1f1b1a3c4b3c5fec3d503995cc15b245bde4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/216935
Commit-Queue: Jim Blackler <jimblackler@google.com>
Reviewed-by: Alex Benton <bentonian@google.com>
Auto-Submit: Jim Blackler <jimblackler@google.com>
diff --git a/generator/templates/art/api_kotlin_object.kt b/generator/templates/art/api_kotlin_object.kt
index f170bc6c..edeee32 100644
--- a/generator/templates/art/api_kotlin_object.kt
+++ b/generator/templates/art/api_kotlin_object.kt
@@ -51,4 +51,11 @@
         {% endif %}
     {% endfor %}
     external override fun close();
+
+    //* By default, the equals() function implements referential equality.
+    //* see: https://kotlinlang.org/docs/equality.html#structural-equality
+    //* We convert to structural equality (in Kotlin) which acts as referential equality check for
+    //* the underlying Dawn object.
+    override fun equals(other: Any?): Boolean =
+        other is {{ obj.name.CamelCase() }} && other.handle == handle
 }
diff --git a/tools/android/webgpu/src/androidTest/java/android/dawn/ObjectTest.kt b/tools/android/webgpu/src/androidTest/java/android/dawn/ObjectTest.kt
new file mode 100644
index 0000000..7f0524d
--- /dev/null
+++ b/tools/android/webgpu/src/androidTest/java/android/dawn/ObjectTest.kt
@@ -0,0 +1,47 @@
+package android.dawn
+
+import android.dawn.helper.Util
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ObjectTest {
+    init {
+        Util  // Hack to force library initialization.
+    }
+
+    @Test
+    fun sameObjectCompare() {
+        val surface = createInstance().createSurface()
+
+        val texture1 = surface.getCurrentTexture().texture
+
+        val texture2 = surface.getCurrentTexture().texture
+
+        assert(texture1 == texture2) {
+            "== matches two Kotlin objects representing the same Dawn object"
+        }
+
+        assert(texture1.equals(texture2)) {
+            ".equals() matches two Kotlin objects representing the same Dawn object"
+        }
+    }
+
+    @Test
+    fun differentObjectCompare() {
+        val instance = createInstance()
+
+        val surface1 = instance.createSurface()
+
+        val surface2 = instance.createSurface()
+
+        assert(!(surface1 == surface2)) {
+            "== fails to match two Kotlin objects representing different Dawn objects"
+        }
+
+        assert(!surface1.equals(surface2)) {
+            ".equals fails to match two Kotlin objects representing different Dawn objects"
+        }
+    }
+}