aboutsummaryrefslogtreecommitdiff
path: root/app/src/androidTest/kotlin/com/pitchedapps/frost
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/androidTest/kotlin/com/pitchedapps/frost')
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt48
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt48
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt85
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt54
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt62
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt145
6 files changed, 442 insertions, 0 deletions
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt
new file mode 100644
index 00000000..bae56e2f
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/BaseDbTest.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import android.content.Context
+import androidx.room.Room
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+
+@RunWith(AndroidJUnit4::class)
+abstract class BaseDbTest {
+
+ protected lateinit var db: FrostDatabase
+
+ @BeforeTest
+ fun before() {
+ val context = ApplicationProvider.getApplicationContext<Context>()
+ val privateDb = Room.inMemoryDatabaseBuilder(
+ context, FrostPrivateDatabase::class.java
+ ).build()
+ val publicDb = Room.inMemoryDatabaseBuilder(
+ context, FrostPublicDatabase::class.java
+ ).build()
+ db = FrostDatabase(privateDb, publicDb)
+ }
+
+ @AfterTest
+ fun after() {
+ db.close()
+ }
+}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt
new file mode 100644
index 00000000..417c6678
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CacheDbTest.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import kotlinx.coroutines.runBlocking
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+class CacheDbTest : BaseDbTest() {
+
+ private val dao get() = db.cacheDao()
+ private val cookieDao get() = db.cookieDao()
+
+ private fun cookie(id: Long) = CookieEntity(id, "name$id", "cookie$id")
+
+ @Test
+ fun save() {
+ val cookie = cookie(1L)
+ val type = "test"
+ val content = "long test".repeat(10000)
+ runBlocking {
+ cookieDao.save(cookie)
+ dao.save(cookie.id, type, content)
+ val cache = dao.select(cookie.id, type) ?: fail("Cache not found")
+ assertEquals(content, cache.contents, "Content mismatch")
+ assertTrue(
+ System.currentTimeMillis() - cache.lastUpdated < 500,
+ "Cache retrieval took over 500ms (${System.currentTimeMillis() - cache.lastUpdated})"
+ )
+ }
+ }
+}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt
new file mode 100644
index 00000000..327ead86
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieDbTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import kotlinx.coroutines.runBlocking
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNull
+
+class CookieDbTest : BaseDbTest() {
+
+ private val dao get() = db.cookieDao()
+
+ @Test
+ fun basicCookie() {
+ val cookie = CookieEntity(id = 1234L, name = "testName", cookie = "testCookie")
+ runBlocking {
+ dao.save(cookie)
+ val cookies = dao.selectAll()
+ assertEquals(listOf(cookie), cookies, "Cookie mismatch")
+ }
+ }
+
+ @Test
+ fun deleteCookie() {
+ val cookie = CookieEntity(id = 1234L, name = "testName", cookie = "testCookie")
+
+ runBlocking {
+ dao.save(cookie)
+ dao.deleteById(cookie.id + 1)
+ assertEquals(
+ listOf(cookie),
+ dao.selectAll(),
+ "Cookie list should be the same after inexistent deletion"
+ )
+ dao.deleteById(cookie.id)
+ assertEquals(emptyList(), dao.selectAll(), "Cookie list should be empty after deletion")
+ }
+ }
+
+ @Test
+ fun insertReplaceCookie() {
+ val cookie = CookieEntity(id = 1234L, name = "testName", cookie = "testCookie")
+ runBlocking {
+ dao.save(cookie)
+ assertEquals(listOf(cookie), dao.selectAll(), "Cookie insertion failed")
+ dao.save(cookie.copy(name = "testName2"))
+ assertEquals(
+ listOf(cookie.copy(name = "testName2")),
+ dao.selectAll(),
+ "Cookie replacement failed"
+ )
+ dao.save(cookie.copy(id = 123L))
+ assertEquals(
+ setOf(cookie.copy(id = 123L), cookie.copy(name = "testName2")),
+ dao.selectAll().toSet(),
+ "New cookie insertion failed"
+ )
+ }
+ }
+
+ @Test
+ fun selectCookie() {
+ val cookie = CookieEntity(id = 1234L, name = "testName", cookie = "testCookie")
+ runBlocking {
+ dao.save(cookie)
+ assertEquals(cookie, dao.selectById(cookie.id), "Cookie selection failed")
+ assertNull(dao.selectById(cookie.id + 1), "Inexistent cookie selection failed")
+ }
+ }
+}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt
new file mode 100644
index 00000000..c79d212e
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/DatabaseTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.runner.RunWith
+import org.koin.error.NoBeanDefFoundException
+import org.koin.standalone.get
+import org.koin.test.KoinTest
+import kotlin.reflect.KClass
+import kotlin.reflect.full.functions
+import kotlin.test.Test
+import kotlin.test.assertTrue
+
+@RunWith(AndroidJUnit4::class)
+class DatabaseTest : KoinTest {
+
+ inline fun <reified T : Any> hasKoin() = hasKoin(T::class)
+
+ fun <T : Any> hasKoin(klazz: KClass<T>): Boolean =
+ try {
+ get<T>(clazz = klazz)
+ true
+ } catch (e: NoBeanDefFoundException) {
+ false
+ }
+
+ /**
+ * Database and all daos should be loaded as components
+ */
+ @Test
+ fun testKoins() {
+ hasKoin<FrostDatabase>()
+ val members = FrostDatabase::class.java.kotlin.functions.filter { it.name.endsWith("Dao") }
+ .mapNotNull { it.returnType.classifier as? KClass<*> }
+ assertTrue(members.isNotEmpty(), "Failed to find dao interfaces")
+ val missingKoins = (members + FrostDatabase::class).filter { !hasKoin(it) }
+ assertTrue(missingKoins.isEmpty(), "Missing koins: $missingKoins")
+ }
+}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt
new file mode 100644
index 00000000..add9f509
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/GenericDbTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2019 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import com.pitchedapps.frost.facebook.FbItem
+import com.pitchedapps.frost.facebook.defaultTabs
+import kotlinx.coroutines.runBlocking
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class GenericDbTest : BaseDbTest() {
+
+ private val dao get() = db.genericDao()
+
+ /**
+ * Note that order is also preserved here
+ */
+ @Test
+ fun save() {
+ val tabs = listOf(FbItem.ACTIVITY_LOG, FbItem.BIRTHDAYS, FbItem.EVENTS, FbItem.MARKETPLACE, FbItem.ACTIVITY_LOG)
+ runBlocking {
+ dao.saveTabs(tabs)
+ assertEquals(tabs, dao.getTabs(), "Tab saving failed")
+ val newTabs = listOf(FbItem.PAGES, FbItem.MENU)
+ dao.saveTabs(newTabs)
+ assertEquals(newTabs, dao.getTabs(), "Tab overwrite failed")
+ }
+ }
+
+ @Test
+ fun defaultRetrieve() {
+ runBlocking {
+ assertEquals(defaultTabs(), dao.getTabs(), "Default retrieval failed")
+ }
+ }
+
+ @Test
+ fun ignoreErrors() {
+ runBlocking {
+ dao.save(GenericEntity(GenericDao.TYPE_TABS, "${FbItem.ACTIVITY_LOG.name},unknown,${FbItem.EVENTS.name}"))
+ assertEquals(
+ listOf(FbItem.ACTIVITY_LOG, FbItem.EVENTS),
+ dao.getTabs(),
+ "Tab fetching does not ignore unknown names"
+ )
+ }
+ }
+}
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt
new file mode 100644
index 00000000..45a09cbe
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/NotificationDbTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2019 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import com.pitchedapps.frost.services.NOTIF_CHANNEL_GENERAL
+import com.pitchedapps.frost.services.NOTIF_CHANNEL_MESSAGES
+import com.pitchedapps.frost.services.NotificationContent
+import kotlinx.coroutines.runBlocking
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+
+class NotificationDbTest : BaseDbTest() {
+
+ private val dao get() = db.notifDao()
+
+ private fun cookie(id: Long) = CookieEntity(id, "name$id", "cookie$id")
+
+ private fun notifContent(id: Long, cookie: CookieEntity, time: Long = id) = NotificationContent(
+ data = cookie,
+ id = id,
+ href = "",
+ title = null,
+ text = "",
+ timestamp = time,
+ profileUrl = null,
+ unread = true
+ )
+
+ @Test
+ fun saveAndRetrieve() {
+ val cookie = cookie(12345L)
+ // Unique unsorted ids
+ val notifs = listOf(0L, 4L, 2L, 6L, 99L, 3L).map { notifContent(it, cookie) }
+ runBlocking {
+ db.cookieDao().save(cookie)
+ dao.saveNotifications(NOTIF_CHANNEL_GENERAL, notifs)
+ val dbNotifs = dao.selectNotifications(cookie.id, NOTIF_CHANNEL_GENERAL)
+ assertEquals(notifs.sortedByDescending { it.timestamp }, dbNotifs, "Incorrect notification list received")
+ }
+ }
+
+ @Test
+ fun selectConditions() {
+ runBlocking {
+ val cookie1 = cookie(12345L)
+ val cookie2 = cookie(12L)
+ val notifs1 = (0L..2L).map { notifContent(it, cookie1) }
+ val notifs2 = (5L..10L).map { notifContent(it, cookie2) }
+ db.cookieDao().save(cookie1)
+ db.cookieDao().save(cookie2)
+ dao.saveNotifications(NOTIF_CHANNEL_GENERAL, notifs1)
+ dao.saveNotifications(NOTIF_CHANNEL_MESSAGES, notifs2)
+ assertEquals(
+ emptyList(),
+ dao.selectNotifications(cookie1.id, NOTIF_CHANNEL_MESSAGES),
+ "Filtering by type did not work for cookie1"
+ )
+ assertEquals(
+ notifs1.sortedByDescending { it.timestamp },
+ dao.selectNotifications(cookie1.id, NOTIF_CHANNEL_GENERAL),
+ "Selection for cookie1 failed"
+ )
+ assertEquals(
+ emptyList(),
+ dao.selectNotifications(cookie2.id, NOTIF_CHANNEL_GENERAL),
+ "Filtering by type did not work for cookie2"
+ )
+ assertEquals(
+ notifs2.sortedByDescending { it.timestamp },
+ dao.selectNotifications(cookie2.id, NOTIF_CHANNEL_MESSAGES),
+ "Selection for cookie2 failed"
+ )
+ }
+ }
+
+ /**
+ * Primary key is both id and userId, in the event that the same notification to multiple users has the same id
+ */
+ @Test
+ fun primaryKeyCheck() {
+ runBlocking {
+ val cookie1 = cookie(12345L)
+ val cookie2 = cookie(12L)
+ val notifs1 = (0L..2L).map { notifContent(it, cookie1) }
+ val notifs2 = notifs1.map { it.copy(data = cookie2) }
+ db.cookieDao().save(cookie1)
+ db.cookieDao().save(cookie2)
+ assertTrue(dao.saveNotifications(NOTIF_CHANNEL_GENERAL, notifs1), "Notif1 save failed")
+ assertTrue(dao.saveNotifications(NOTIF_CHANNEL_GENERAL, notifs2), "Notif2 save failed")
+ }
+ }
+
+ @Test
+ fun cascadeDeletion() {
+ val cookie = cookie(12345L)
+ // Unique unsorted ids
+ val notifs = listOf(0L, 4L, 2L, 6L, 99L, 3L).map { notifContent(it, cookie) }
+ runBlocking {
+ db.cookieDao().save(cookie)
+ dao.saveNotifications(NOTIF_CHANNEL_GENERAL, notifs)
+ db.cookieDao().deleteById(cookie.id)
+ val dbNotifs = dao.selectNotifications(cookie.id, NOTIF_CHANNEL_GENERAL)
+ assertTrue(dbNotifs.isEmpty(), "Cascade deletion failed")
+ }
+ }
+
+ @Test
+ fun latestEpoch() {
+ val cookie = cookie(12345L)
+ // Unique unsorted ids
+ val notifs = listOf(0L, 4L, 2L, 6L, 99L, 3L).map { notifContent(it, cookie) }
+ runBlocking {
+ assertEquals(-1L, dao.latestEpoch(cookie.id, NOTIF_CHANNEL_GENERAL), "Default epoch failed")
+ db.cookieDao().save(cookie)
+ dao.saveNotifications(NOTIF_CHANNEL_GENERAL, notifs)
+ assertEquals(99L, dao.latestEpoch(cookie.id, NOTIF_CHANNEL_GENERAL), "Latest epoch failed")
+ }
+ }
+
+ @Test
+ fun insertionWithInvalidCookies() {
+ runBlocking {
+ assertFalse(
+ dao.saveNotifications(NOTIF_CHANNEL_GENERAL, listOf(notifContent(1L, cookie(2L)))),
+ "Notif save should not have passed without relevant cookie entries"
+ )
+ }
+ }
+}