Skip to content

Commit

Permalink
Fix error in RealmAny.equals when comparing similarly typed object
Browse files Browse the repository at this point in the history
  • Loading branch information
rorbech committed Sep 18, 2023
1 parent b3406e3 commit 79bc85a
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,27 +127,27 @@ internal class RealmAnyImpl<T : Any> 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down

0 comments on commit 79bc85a

Please sign in to comment.