diff --git a/CHANGELOG.md b/CHANGELOG.md index 7621882b9c..851a84d9ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed * `Realm.getNumberOfActiveVersions` now returns the actual number of active versions. (Core issue [#6960](https://github.com/realm/realm-core/pull/6960)) +* Fix error in `RealmAny.equals` that would sometime return true when comparing RealmAnys wrapping same type but different values. ### Compatibility * File format: Generates Realms with file format v23. diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt index 0a2791fab8..d1ae02c778 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmAnyImpl.kt @@ -127,27 +127,27 @@ internal class RealmAnyImpl constructor( if (other.type != this.type) return false if (clazz == ByteArray::class) { if (other.internalValue !is ByteArray) return false - if (!other.internalValue.contentEquals(this.internalValue as ByteArray)) return false + return other.internalValue.contentEquals(this.internalValue as ByteArray) } else if (internalValue is BsonObjectId) { if (other.clazz != BsonObjectId::class) return false - if (other.internalValue != this.internalValue) return false + return other.internalValue == this.internalValue } else if (internalValue is RealmObject) { if (other.clazz != this.clazz) return false - if (other.internalValue !== this.internalValue) return false + return other.internalValue == this.internalValue } else if (internalValue is Number) { // Numerics are the same as long as their value is the same - when (other.internalValue) { - is Char -> if (other.internalValue.code.toLong() != internalValue.toLong()) return false - is Number -> if (other.internalValue.toLong() != this.internalValue.toLong()) return false + return when (other.internalValue) { + is Char -> other.internalValue.code.toLong() == internalValue.toLong() + is Number -> other.internalValue.toLong() == this.internalValue.toLong() else -> return false } } else if (internalValue is Char) { // We are comparing chars - when (other.internalValue) { - is Char -> if (other.internalValue.code.toLong() != internalValue.toLong()) return false - is Number -> if (other.internalValue.toLong() != this.internalValue.toLong()) return false + return when (other.internalValue) { + is Char -> other.internalValue.code.toLong() == internalValue.toLong() + is Number -> other.internalValue.toLong() == this.internalValue.toLong() else -> return false } } - return true + return internalValue == other.internalValue } override fun hashCode(): Int { diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmAnyTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmAnyTests.kt index 843fbd29c2..c3b6aedaa6 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmAnyTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/RealmAnyTests.kt @@ -58,6 +58,7 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertIs +import kotlin.test.assertNotEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.fail @@ -421,6 +422,66 @@ class RealmAnyTests { } } + @Test + fun equals() { + RealmAny.Type.values().forEach { type -> + when (type) { + RealmAny.Type.INT -> { + assertEquals(RealmAny.create(1), RealmAny.create(1)) + assertNotEquals(RealmAny.create(1), RealmAny.create(2)) + } + RealmAny.Type.BOOL -> { + assertEquals(RealmAny.create(true), RealmAny.create(true)) + assertNotEquals(RealmAny.create(true), RealmAny.create(false)) + } + RealmAny.Type.STRING -> { + assertEquals(RealmAny.create("Realm"), RealmAny.create("Realm")) + assertNotEquals(RealmAny.create("Realm"), RealmAny.create("Not Realm")) + } + RealmAny.Type.BINARY -> { + assertEquals( + RealmAny.create(byteArrayOf(1, 2)), RealmAny.create(byteArrayOf(1, 2)) + ) + assertNotEquals( + RealmAny.create(byteArrayOf(1, 2)), RealmAny.create(byteArrayOf(2, 1)) + ) + } + RealmAny.Type.TIMESTAMP -> { + val now = RealmInstant.now() + assertEquals(RealmAny.create(now), RealmAny.create(now)) + assertNotEquals(RealmAny.create(RealmInstant.from(1, 1)), RealmAny.create(now)) + } + RealmAny.Type.FLOAT -> { + assertEquals(RealmAny.create(1.0f), RealmAny.create(1.0f)) + assertNotEquals(RealmAny.create(1.0f), RealmAny.create(2.0f)) + } + RealmAny.Type.DOUBLE -> { + assertEquals(RealmAny.create(1.0), RealmAny.create(1.0)) + assertNotEquals(RealmAny.create(1.0), RealmAny.create(2.0)) + } + RealmAny.Type.DECIMAL128 -> { + assertEquals(RealmAny.create(Decimal128("1E64")), RealmAny.create(Decimal128("1E64"))) + assertNotEquals(RealmAny.create(Decimal128("1E64")), RealmAny.create(Decimal128("-1E64"))) + } + RealmAny.Type.OBJECT_ID -> { + val value = ObjectId() + assertEquals(RealmAny.create(value), RealmAny.create(value)) + assertNotEquals(RealmAny.create(ObjectId()), RealmAny.create(value)) + } + RealmAny.Type.UUID -> { + val value = RealmUUID.random() + assertEquals(RealmAny.create(value), RealmAny.create(value)) + assertNotEquals(RealmAny.create(RealmUUID.random()), RealmAny.create(value)) + } + RealmAny.Type.OBJECT -> { + val realmObject = Sample() + assertEquals(RealmAny.create(realmObject), RealmAny.create(realmObject)) + assertNotEquals(RealmAny.create(Sample()), RealmAny.create(realmObject)) + } + } + } + } + @Test fun embeddedObject_worksInsideParent() { val embeddedChild = EmbeddedChild("CHILD")