Skip to content

Commit 7941f11

Browse files
committed
Cleanup & reenable tests
1 parent dc54714 commit 7941f11

File tree

12 files changed

+212
-158
lines changed

12 files changed

+212
-158
lines changed

firebase-common/src/androidMain/kotlin/dev/gitlive/firebase/_encoders.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import kotlinx.serialization.descriptors.StructureKind
1010
import java.lang.IllegalArgumentException
1111
import kotlin.collections.set
1212

13-
actual data class EncodedObject(actual val raw: Map<String, Any?>) {
13+
actual data class EncodedObject(actual val raw: Map<String, Any?>) : Map<String, Any?> by raw {
1414
actual companion object {
1515
actual val emptyEncodedObject: EncodedObject = EncodedObject(emptyMap())
1616
}
17-
val android: Map<String, Any?> get() = raw
1817
}
1918

2019
@PublishedApi

firebase-common/src/commonMain/kotlin/dev/gitlive/firebase/encoders.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ import kotlinx.serialization.encoding.CompositeEncoder
1111
import kotlinx.serialization.encoding.Encoder
1212
import kotlinx.serialization.modules.SerializersModule
1313

14+
/**
15+
* Platform specific object for storing encoded data that can be used for methods that explicitly require an object.
16+
* This is essentially a [Map] of [String] and [Any]? (as represented by [raw]) but since [encode] gives a platform specific value, this method wraps that.
17+
*
18+
* Created using [encodeAsObject]
19+
*/
1420
expect class EncodedObject {
1521
companion object {
1622
val emptyEncodedObject: EncodedObject
@@ -40,12 +46,12 @@ inline fun <reified T> encode(value: T, buildSettings: EncodeSettings.Builder.()
4046
encode(value, EncodeSettings.BuilderImpl().apply(buildSettings).buildEncodeSettings())
4147

4248
inline fun <T : Any> encodeAsObject(strategy: SerializationStrategy<T>, value: T, buildSettings: EncodeSettings.Builder.() -> Unit = {}): EncodedObject {
43-
val encoded = encode(strategy, value, buildSettings) ?: throw IllegalArgumentException("$value was encoded as null. Must be of the form Map<Key, Value>")
44-
return encoded.asNativeMap()?.asEncodedObject() ?: throw IllegalArgumentException("$value was encoded as ${encoded::class}. Must be of the form Map<Key, Value>")
49+
val encoded = encode(strategy, value, buildSettings) ?: throw IllegalArgumentException("$value was encoded as null. Must be of the form Map<String, Any?>")
50+
return encoded.asNativeMap()?.asEncodedObject() ?: throw IllegalArgumentException("$value was encoded as ${encoded::class}. Must be of the form Map<String, Any?>")
4551
}
4652
inline fun <reified T : Any> encodeAsObject(value: T, buildSettings: EncodeSettings.Builder.() -> Unit = {}): EncodedObject {
47-
val encoded = encode(value, buildSettings) ?: throw IllegalArgumentException("$value was encoded as null. Must be of the form Map<Key, Value>")
48-
return encoded.asNativeMap()?.asEncodedObject() ?: throw IllegalArgumentException("$value was encoded as ${encoded::class}. Must be of the form Map<Key, Value>")
53+
val encoded = encode(value, buildSettings) ?: throw IllegalArgumentException("$value was encoded as null. Must be of the form Map<String, Any?>")
54+
return encoded.asNativeMap()?.asEncodedObject() ?: throw IllegalArgumentException("$value was encoded as ${encoded::class}. Must be of the form Map<String, Any?>")
4955
}
5056

5157
@PublishedApi

firebase-common/src/commonTest/kotlin/dev/gitlive/firebase/EncodersTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import kotlinx.serialization.modules.polymorphic
1515
import kotlin.jvm.JvmInline
1616
import kotlin.test.Test
1717
import kotlin.test.assertEquals
18+
import kotlin.test.assertFailsWith
1819
import kotlin.test.assertNull
1920

2021
@Serializable
@@ -416,6 +417,31 @@ class EncodersTest {
416417
)
417418
}
418419

420+
@Test
421+
fun encodeAsObject() {
422+
val testDataClass = TestData(mapOf("key" to "value"), mapOf(1 to 1), true, null, ValueClass(42))
423+
val encodedObject = encodeAsObject(TestData.serializer(), testDataClass) { encodeDefaults = false }
424+
425+
assertEquals(mapOf("map" to nativeMapOf("key" to "value"), "otherMap" to nativeMapOf(1 to 1), "bool" to true, "valueClass" to 42), encodedObject.raw)
426+
427+
val testMap = mapOf("one" to 1, "two" to null, "three" to false)
428+
assertEquals(testMap, encodeAsObject(testMap).raw)
429+
430+
assertEquals(emptyMap(), encodeAsObject(TestObject).raw)
431+
432+
assertFailsWith<IllegalArgumentException> { encodeAsObject(true) }
433+
assertFailsWith<IllegalArgumentException> { encodeAsObject(42) }
434+
assertFailsWith<IllegalArgumentException> { encodeAsObject(8.toShort()) }
435+
assertFailsWith<IllegalArgumentException> { encodeAsObject(Int.MAX_VALUE.toLong() + 3) }
436+
assertFailsWith<IllegalArgumentException> { encodeAsObject(0x03F) }
437+
assertFailsWith<IllegalArgumentException> { encodeAsObject(3.33) }
438+
assertFailsWith<IllegalArgumentException> { encodeAsObject(6.65f) }
439+
assertFailsWith<IllegalArgumentException> { encodeAsObject("Test") }
440+
assertFailsWith<IllegalArgumentException> { encodeAsObject(ValueClass(2)) }
441+
assertFailsWith<IllegalArgumentException> { encodeAsObject(mapOf(1 to "one")) }
442+
assertFailsWith<IllegalArgumentException> { encodeAsObject(listOf("one")) }
443+
}
444+
419445
private inline fun <reified T> assertEncode(value: T) {
420446
val encoded = encode(value)
421447
assertEquals(value, encoded)

firebase-common/src/iosMain/kotlin/dev/gitlive/firebase/_encoders.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ import kotlinx.serialization.descriptors.SerialDescriptor
99
import kotlinx.serialization.descriptors.StructureKind
1010
import kotlin.collections.set
1111

12-
actual data class EncodedObject(actual val raw: Map<String, Any?>) {
12+
actual data class EncodedObject(actual val raw: Map<String, Any?>) : Map<Any?, Any?> by raw.mapKeys({ (key, _) -> key as? Any }) {
1313
actual companion object {
1414
actual val emptyEncodedObject: EncodedObject = EncodedObject(emptyMap())
1515
}
16-
17-
val ios: Map<Any?, *> get() = raw.mapKeys { (key, _) -> key as? Any }
1816
}
1917

2018
@PublishedApi

firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/_encoders.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ import kotlinx.serialization.descriptors.StructureKind
1010
import kotlin.js.Json
1111
import kotlin.js.json
1212

13-
actual data class EncodedObject(private val keyValues: List<Pair<String, Any?>>) {
13+
actual data class EncodedObject(private val keyValues: List<Pair<String, Any?>>) : Json by json(*keyValues.toTypedArray()) {
1414
actual companion object {
1515
actual val emptyEncodedObject: EncodedObject = EncodedObject(emptyList())
1616
}
1717

1818
actual val raw get() = keyValues.toMap()
19-
val json get() = json(*keyValues.toTypedArray())
2019
}
2120

2221

firebase-database/src/androidMain/kotlin/dev/gitlive/firebase/database/database.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ internal actual class NativeDatabaseReference internal constructor(
207207
.run { Unit }
208208

209209
actual suspend fun updateEncodedChildren(encodedUpdate: EncodedObject) =
210-
android.updateChildren(encodedUpdate.android)
210+
android.updateChildren(encodedUpdate)
211211
.run { if(persistenceEnabled) await() else awaitWhileOnline(database) }
212212
.run { Unit }
213213

@@ -297,7 +297,7 @@ internal actual class NativeOnDisconnect internal constructor(
297297
.run { Unit }
298298

299299
actual suspend fun updateEncodedChildren(encodedUpdate: EncodedObject) =
300-
android.updateChildren(encodedUpdate.android)
300+
android.updateChildren(encodedUpdate)
301301
.run { if(persistenceEnabled) await() else awaitWhileOnline(database) }
302302
.run { Unit }
303303
}

firebase-database/src/commonTest/kotlin/dev/gitlive/firebase/database/database.kt

Lines changed: 134 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import kotlin.test.AfterTest
1717
import kotlin.test.BeforeTest
1818
import kotlin.test.Test
1919
import kotlin.test.assertEquals
20+
import kotlin.test.assertFailsWith
2021
import kotlin.test.assertFalse
2122
import kotlin.test.assertTrue
2223
import kotlin.time.Duration.Companion.minutes
@@ -62,116 +63,142 @@ class FirebaseDatabaseTest {
6263
}
6364
}
6465

65-
// @Test
66-
// fun testSetValue() = runTest {
67-
// ensureDatabaseConnected()
68-
// val testValue = "test"
69-
// val testReference = database.reference("testPath")
70-
//
71-
// testReference.setValue(testValue)
72-
//
73-
// val testReferenceValue = testReference
74-
// .valueEvents
75-
// .first()
76-
// .value<String>()
77-
//
78-
// assertEquals(testValue, testReferenceValue)
79-
// }
80-
//
81-
// @Test
82-
// fun testChildCount() = runTest {
83-
// setupRealtimeData()
84-
// val dataSnapshot = database
85-
// .reference("FirebaseRealtimeDatabaseTest")
86-
// .valueEvents
87-
// .first()
88-
//
89-
// val firebaseDatabaseChildCount = dataSnapshot.children.count()
90-
// assertEquals(3, firebaseDatabaseChildCount)
91-
// }
92-
//
93-
// @Test
94-
// fun testBasicIncrementTransaction() = runTest {
95-
// ensureDatabaseConnected()
96-
// val data = DatabaseTest("PostOne", 2)
97-
// val userRef = database.reference("users/user_1/post_id_1")
98-
// setupDatabase(userRef, data, DatabaseTest.serializer())
99-
//
100-
// // Check database before transaction
101-
// val userDocBefore = userRef.valueEvents.first().value(DatabaseTest.serializer())
102-
// assertEquals(data.title, userDocBefore.title)
103-
// assertEquals(data.likes, userDocBefore.likes)
104-
//
105-
// // Run transaction
106-
// val transactionSnapshot = userRef.runTransaction(DatabaseTest.serializer()) { it.copy(likes = it.likes + 1) }
107-
// val userDocAfter = transactionSnapshot.value(DatabaseTest.serializer())
108-
//
109-
// // Check the database after transaction
110-
// assertEquals(data.title, userDocAfter.title)
111-
// assertEquals(data.likes + 1, userDocAfter.likes)
112-
// }
113-
//
114-
// @Test
115-
// fun testBasicDecrementTransaction() = runTest {
116-
// ensureDatabaseConnected()
117-
// val data = DatabaseTest("PostTwo", 2)
118-
// val userRef = database.reference("users/user_1/post_id_2")
119-
// setupDatabase(userRef, data, DatabaseTest.serializer())
120-
//
121-
// // Check database before transaction
122-
// val userDocBefore = userRef.valueEvents.first().value(DatabaseTest.serializer())
123-
// assertEquals(data.title, userDocBefore.title)
124-
// assertEquals(data.likes, userDocBefore.likes)
125-
//
126-
// // Run transaction
127-
// val transactionSnapshot = userRef.runTransaction(DatabaseTest.serializer()) { it.copy(likes = it.likes - 1) }
128-
// val userDocAfter = transactionSnapshot.value(DatabaseTest.serializer())
129-
//
130-
// // Check the database after transaction
131-
// assertEquals(data.title, userDocAfter.title)
132-
// assertEquals(data.likes - 1, userDocAfter.likes)
133-
// }
134-
//
135-
// @Test
136-
// fun testSetServerTimestamp() = runTest {
137-
// ensureDatabaseConnected()
138-
// val testReference = database.reference("testSetServerTimestamp")
139-
//
140-
// testReference.setValue(ServerValue.TIMESTAMP)
141-
//
142-
// val timestamp = testReference
143-
// .valueEvents
144-
// .first()
145-
// .value<Long>()
146-
//
147-
// assertTrue(timestamp > 0)
148-
// }
149-
//
150-
// @Test
151-
// fun testIncrement() = runTest {
152-
// ensureDatabaseConnected()
153-
// val testReference = database.reference("testIncrement")
154-
//
155-
// testReference.setValue(2.0)
156-
//
157-
// val value = testReference
158-
// .valueEvents
159-
// .first()
160-
// .value<Double>()
161-
//
162-
// assertEquals(2.0, value)
163-
//
164-
// testReference.setValue(ServerValue.increment(5.0))
165-
// val updatedValue = testReference
166-
// .valueEvents
167-
// .first()
168-
// .value<Double>()
169-
//
170-
// assertEquals(7.0, updatedValue)
171-
// }
66+
@Test
67+
fun testSetValue() = runTest {
68+
ensureDatabaseConnected()
69+
val testValue = "test"
70+
val testReference = database.reference("testPath")
71+
72+
testReference.setValue(testValue)
73+
74+
val testReferenceValue = testReference
75+
.valueEvents
76+
.first()
77+
.value<String>()
78+
79+
assertEquals(testValue, testReferenceValue)
80+
}
81+
82+
@Test
83+
fun testChildCount() = runTest {
84+
setupRealtimeData()
85+
val dataSnapshot = database
86+
.reference("FirebaseRealtimeDatabaseTest")
87+
.valueEvents
88+
.first()
89+
90+
val firebaseDatabaseChildCount = dataSnapshot.child("values").children.count()
91+
assertEquals(3, firebaseDatabaseChildCount)
92+
}
93+
94+
@Test
95+
fun testBasicIncrementTransaction() = runTest {
96+
ensureDatabaseConnected()
97+
val data = DatabaseTest("PostOne", 2)
98+
val userRef = database.reference("users/user_1/post_id_1")
99+
setupDatabase(userRef, data, DatabaseTest.serializer())
100+
101+
// Check database before transaction
102+
val userDocBefore = userRef.valueEvents.first().value(DatabaseTest.serializer())
103+
assertEquals(data.title, userDocBefore.title)
104+
assertEquals(data.likes, userDocBefore.likes)
105+
106+
// Run transaction
107+
val transactionSnapshot = userRef.runTransaction(DatabaseTest.serializer()) { it.copy(likes = it.likes + 1) }
108+
val userDocAfter = transactionSnapshot.value(DatabaseTest.serializer())
109+
110+
// Check the database after transaction
111+
assertEquals(data.title, userDocAfter.title)
112+
assertEquals(data.likes + 1, userDocAfter.likes)
113+
}
114+
115+
@Test
116+
fun testBasicDecrementTransaction() = runTest {
117+
ensureDatabaseConnected()
118+
val data = DatabaseTest("PostTwo", 2)
119+
val userRef = database.reference("users/user_1/post_id_2")
120+
setupDatabase(userRef, data, DatabaseTest.serializer())
121+
122+
// Check database before transaction
123+
val userDocBefore = userRef.valueEvents.first().value(DatabaseTest.serializer())
124+
assertEquals(data.title, userDocBefore.title)
125+
assertEquals(data.likes, userDocBefore.likes)
126+
127+
// Run transaction
128+
val transactionSnapshot = userRef.runTransaction(DatabaseTest.serializer()) { it.copy(likes = it.likes - 1) }
129+
val userDocAfter = transactionSnapshot.value(DatabaseTest.serializer())
130+
131+
// Check the database after transaction
132+
assertEquals(data.title, userDocAfter.title)
133+
assertEquals(data.likes - 1, userDocAfter.likes)
134+
}
135+
136+
@Test
137+
fun testSetServerTimestamp() = runTest {
138+
ensureDatabaseConnected()
139+
val testReference = database.reference("testSetServerTimestamp")
140+
141+
testReference.setValue(ServerValue.TIMESTAMP)
142+
143+
val timestamp = testReference
144+
.valueEvents
145+
.first()
146+
.value<Long>()
147+
148+
assertTrue(timestamp > 0)
149+
}
150+
151+
@Test
152+
fun testIncrement() = runTest {
153+
ensureDatabaseConnected()
154+
val testReference = database.reference("testIncrement")
155+
156+
testReference.setValue(2.0)
157+
158+
val value = testReference
159+
.valueEvents
160+
.first()
161+
.value<Double>()
162+
163+
assertEquals(2.0, value)
164+
165+
testReference.setValue(ServerValue.increment(5.0))
166+
val updatedValue = testReference
167+
.valueEvents
168+
.first()
169+
.value<Double>()
170+
171+
assertEquals(7.0, updatedValue)
172+
}
173+
174+
@Test
175+
fun testBreakRules() = runTest {
176+
ensureDatabaseConnected()
177+
val reference = database
178+
.reference("FirebaseRealtimeDatabaseTest")
179+
val child = reference.child("lastActivity")
180+
assertFailsWith<DatabaseException> {
181+
child.setValue("stringNotAllowed")
182+
}
183+
child.setValue(2)
184+
assertFailsWith<DatabaseException> {
185+
reference.updateChildren(mapOf("lastActivity" to "stringNotAllowed"))
186+
}
187+
}
172188

173189
@Test
174190
fun testUpdateChildren() = runTest {
191+
setupRealtimeData()
192+
val reference = database
193+
.reference("FirebaseRealtimeDatabaseTest")
194+
val valueEvents = reference.child("lastActivity").valueEvents
195+
assertTrue(valueEvents.first().exists)
196+
reference.updateChildren(mapOf("test" to false, "nested" to mapOf("lastActivity" to null), "lastActivity" to null))
197+
assertFalse(valueEvents.first().exists)
198+
}
199+
200+
@Test
201+
fun testUpdateChildrenOnDisconnect() = runTest {
175202
setupRealtimeData()
176203
val reference = database
177204
.reference("FirebaseRealtimeDatabaseTest")

0 commit comments

Comments
 (0)