Skip to content

Commit 872c1a1

Browse files
Add database tests
1 parent 515b7da commit 872c1a1

File tree

5 files changed

+153
-2
lines changed
  • firebase-database/src
    • androidAndroidTest/kotlin/dev/gitlive/firebase/database
    • androidMain/kotlin/dev/gitlive/firebase/database
    • commonTest/kotlin/dev/gitlive/firebase/database
    • iosTest/kotlin/dev/gitlive/firebase/database
    • jsTest/kotlin/dev/gitlive/firebase/database

5 files changed

+153
-2
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:JvmName("tests")
6+
package dev.gitlive.firebase.database
7+
8+
import androidx.test.platform.app.InstrumentationRegistry
9+
import kotlinx.coroutines.runBlocking
10+
11+
actual val emulatorHost: String = "10.0.2.2"
12+
13+
actual val context: Any = InstrumentationRegistry.getInstrumentation().targetContext
14+
15+
actual fun runTest(test: suspend () -> Unit) = runBlocking { test() }

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@ import dev.gitlive.firebase.database.ChildEvent.Type
1313
import dev.gitlive.firebase.decode
1414
import dev.gitlive.firebase.safeOffer
1515
import kotlinx.coroutines.CompletableDeferred
16-
import kotlinx.coroutines.FlowPreview
1716
import kotlinx.coroutines.channels.awaitClose
1817
import kotlinx.coroutines.coroutineScope
1918
import kotlinx.coroutines.flow.Flow
2019
import kotlinx.coroutines.flow.callbackFlow
2120
import kotlinx.coroutines.flow.filter
2221
import kotlinx.coroutines.flow.produceIn
23-
import kotlinx.coroutines.runBlocking
2422
import kotlinx.coroutines.selects.select
2523
import kotlinx.coroutines.tasks.asDeferred
2624
import kotlinx.coroutines.tasks.await
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package dev.gitlive.firebase.database
2+
3+
import dev.gitlive.firebase.*
4+
import kotlinx.coroutines.flow.first
5+
import kotlinx.serialization.*
6+
import kotlin.test.*
7+
8+
expect val emulatorHost: String
9+
expect val context: Any
10+
expect fun runTest(test: suspend () -> Unit)
11+
12+
class FirebaseDatabaseTest {
13+
14+
@Serializable
15+
data class DatabaseTest(val prop: String, val likes: Int = 0)
16+
17+
@BeforeTest
18+
fun initializeFirebase() {
19+
Firebase
20+
.takeIf { Firebase.apps(context).isEmpty() }
21+
?.apply {
22+
initialize(
23+
context,
24+
FirebaseOptions(
25+
applicationId = "1:846484016111:ios:dd1f6688bad7af768c841a",
26+
apiKey = "AIzaSyCK87dcMFhzCz_kJVs2cT2AVlqOTLuyWV0",
27+
databaseUrl = "http://fir-kotlin-sdk.firebaseio.com",
28+
storageBucket = "fir-kotlin-sdk.appspot.com",
29+
projectId = "fir-kotlin-sdk",
30+
gcmSenderId = "846484016111"
31+
)
32+
)
33+
Firebase.database.useEmulator(emulatorHost, 9000)
34+
}
35+
}
36+
37+
@AfterTest
38+
fun tearDown() {
39+
Firebase
40+
.takeIf { Firebase.apps(context).isNotEmpty() }
41+
?.apply { app.delete() }
42+
}
43+
44+
@Test
45+
fun testBasicIncrementTransaction() = runTest {
46+
val data = DatabaseTest("post1", 2)
47+
val userRef = Firebase.database.reference("users/user_1/post_id_1")
48+
setupDatabase(userRef, data, DatabaseTest.serializer())
49+
50+
// Check database before transaction
51+
val userDocBefore = userRef.valueEvents.first().value(DatabaseTest.serializer())
52+
assertEquals(data.prop, userDocBefore.prop)
53+
assertEquals(data.likes, userDocBefore.likes)
54+
55+
// Run transaction
56+
userRef.runTransaction(DatabaseTest.serializer()) { DatabaseTest(data.prop, it.likes + 1) }
57+
58+
// Check the database after transaction
59+
val userDocAfter = userRef.valueEvents.first().value(DatabaseTest.serializer())
60+
assertEquals(data.prop, userDocAfter.prop)
61+
assertEquals(data.likes, userDocAfter.likes + 1)
62+
}
63+
64+
@Test
65+
fun testBasicDecrementTransaction() = runTest {
66+
val data = DatabaseTest("post2", 2)
67+
val userRef = Firebase.database.reference("users/user_1/post_id_2")
68+
setupDatabase(userRef, data, DatabaseTest.serializer())
69+
70+
// Check database before transaction
71+
val userDocBefore = userRef.valueEvents.first().value(DatabaseTest.serializer())
72+
assertEquals(data.prop, userDocBefore.prop)
73+
assertEquals(data.likes, userDocBefore.likes)
74+
75+
// Run transaction
76+
userRef.runTransaction(DatabaseTest.serializer()) { DatabaseTest(data.prop, it.likes - 1) }
77+
78+
// Check the database after transaction
79+
val userDocAfter = userRef.valueEvents.first().value(DatabaseTest.serializer())
80+
assertEquals(data.prop, userDocAfter.prop)
81+
assertEquals(data.likes, userDocAfter.likes - 1)
82+
}
83+
84+
private suspend fun <T> setupDatabase(ref: DatabaseReference, data: T, strategy: SerializationStrategy<T>) {
85+
try {
86+
ref.setValue(strategy, data)
87+
} catch (err: DatabaseException) {
88+
println(err)
89+
}
90+
}
91+
92+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package dev.gitlive.firebase.database
2+
3+
import kotlinx.coroutines.*
4+
import platform.Foundation.*
5+
6+
actual val emulatorHost: String = "localhost"
7+
8+
actual val context: Any = Unit
9+
10+
actual fun runTest(test: suspend () -> Unit) = runBlocking {
11+
val testRun = MainScope().async { test() }
12+
while (testRun.isActive) {
13+
NSRunLoop.mainRunLoop.runMode(
14+
NSDefaultRunLoopMode,
15+
beforeDate = NSDate.create(timeInterval = 1.0, sinceDate = NSDate())
16+
)
17+
yield()
18+
}
19+
testRun.await()
20+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dev.gitlive.firebase.database
2+
3+
import kotlinx.coroutines.GlobalScope
4+
import kotlinx.coroutines.promise
5+
6+
actual val emulatorHost: String = "localhost"
7+
8+
actual val context: Any = Unit
9+
10+
actual fun runTest(test: suspend () -> Unit) = GlobalScope
11+
.promise {
12+
try {
13+
test()
14+
} catch (e: Throwable) {
15+
e.log()
16+
throw e
17+
}
18+
}.asDynamic()
19+
20+
internal fun Throwable.log() {
21+
console.error(this)
22+
cause?.let {
23+
console.error("Caused by:")
24+
it.log()
25+
}
26+
}

0 commit comments

Comments
 (0)