252 lines
8.6 KiB
Kotlin
252 lines
8.6 KiB
Kotlin
package com.keylesspalace.tusky
|
|
|
|
import androidx.room.Room
|
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
import androidx.test.platform.app.InstrumentationRegistry
|
|
import com.keylesspalace.tusky.db.*
|
|
import com.keylesspalace.tusky.entity.Status
|
|
import com.keylesspalace.tusky.repository.TimelineRepository
|
|
import org.junit.After
|
|
import org.junit.Assert.assertEquals
|
|
import org.junit.Assert.assertNull
|
|
import org.junit.Before
|
|
import org.junit.Test
|
|
import org.junit.runner.RunWith
|
|
|
|
@RunWith(AndroidJUnit4::class)
|
|
class TimelineDAOTest {
|
|
private lateinit var timelineDao: TimelineDao
|
|
private lateinit var db: AppDatabase
|
|
|
|
@Before
|
|
fun createDb() {
|
|
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
|
db = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
|
|
timelineDao = db.timelineDao()
|
|
}
|
|
|
|
@After
|
|
fun closeDb() {
|
|
db.close()
|
|
}
|
|
|
|
@Test
|
|
fun insertGetStatus() {
|
|
val setOne = makeStatus(statusId = 3)
|
|
val setTwo = makeStatus(statusId = 20, reblog = true)
|
|
val ignoredOne = makeStatus(statusId = 1)
|
|
val ignoredTwo = makeStatus(accountId = 2)
|
|
|
|
for ((status, author, reblogger) in listOf(setOne, setTwo, ignoredOne, ignoredTwo)) {
|
|
timelineDao.insertInTransaction(status, author, reblogger)
|
|
}
|
|
|
|
val resultsFromDb = timelineDao.getStatusesForAccount(setOne.first.timelineUserId,
|
|
maxId = "21", sinceId = ignoredOne.first.serverId, limit = 10)
|
|
.blockingGet()
|
|
|
|
assertEquals(2, resultsFromDb.size)
|
|
for ((set, fromDb) in listOf(setTwo, setOne).zip(resultsFromDb)) {
|
|
val (status, author, reblogger) = set
|
|
assertEquals(status, fromDb.status)
|
|
assertEquals(author, fromDb.account)
|
|
assertEquals(reblogger, fromDb.reblogAccount)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun doNotOverwrite() {
|
|
val (status, author) = makeStatus()
|
|
timelineDao.insertInTransaction(status, author, null)
|
|
|
|
val placeholder = createPlaceholder(status.serverId, status.timelineUserId)
|
|
|
|
timelineDao.insertStatusIfNotThere(placeholder)
|
|
|
|
val fromDb = timelineDao.getStatusesForAccount(status.timelineUserId, null, null, 10)
|
|
.blockingGet()
|
|
val result = fromDb.first()
|
|
|
|
assertEquals(1, fromDb.size)
|
|
assertEquals(author, result.account)
|
|
assertEquals(status, result.status)
|
|
assertNull(result.reblogAccount)
|
|
|
|
}
|
|
|
|
@Test
|
|
fun cleanup() {
|
|
val now = System.currentTimeMillis()
|
|
val oldDate = now - TimelineRepository.CLEANUP_INTERVAL - 20_000
|
|
val oldByThisAccount = makeStatus(
|
|
statusId = 5,
|
|
createdAt = oldDate
|
|
)
|
|
val oldByAnotherAccount = makeStatus(
|
|
statusId = 10,
|
|
createdAt = oldDate,
|
|
authorServerId = "100"
|
|
)
|
|
val oldForAnotherAccount = makeStatus(
|
|
accountId = 2,
|
|
statusId = 20,
|
|
authorServerId = "200",
|
|
createdAt = oldDate
|
|
)
|
|
val recentByThisAccount = makeStatus(
|
|
statusId = 30,
|
|
createdAt = System.currentTimeMillis()
|
|
)
|
|
val recentByAnotherAccount = makeStatus(
|
|
statusId = 60,
|
|
createdAt = System.currentTimeMillis(),
|
|
authorServerId = "200"
|
|
)
|
|
|
|
for ((status, author, reblogAuthor) in listOf(oldByThisAccount, oldByAnotherAccount,
|
|
oldForAnotherAccount, recentByThisAccount, recentByAnotherAccount)) {
|
|
timelineDao.insertInTransaction(status, author, reblogAuthor)
|
|
}
|
|
|
|
timelineDao.cleanup(1, "20", now - TimelineRepository.CLEANUP_INTERVAL)
|
|
|
|
assertEquals(
|
|
listOf(recentByAnotherAccount, recentByThisAccount, oldByThisAccount),
|
|
timelineDao.getStatusesForAccount(1, null, null, 100).blockingGet()
|
|
.map { it.toTriple() }
|
|
)
|
|
|
|
assertEquals(
|
|
listOf(oldForAnotherAccount),
|
|
timelineDao.getStatusesForAccount(2, null, null, 100).blockingGet()
|
|
.map { it.toTriple() }
|
|
)
|
|
}
|
|
|
|
@Test
|
|
fun overwriteDeletedStatus() {
|
|
|
|
val oldStatuses = listOf(
|
|
makeStatus(statusId = 3),
|
|
makeStatus(statusId = 2),
|
|
makeStatus(statusId = 1)
|
|
)
|
|
|
|
timelineDao.deleteRange(1, oldStatuses.last().first.serverId, oldStatuses.first().first.serverId)
|
|
|
|
for ((status, author, reblogAuthor) in oldStatuses) {
|
|
timelineDao.insertInTransaction(status, author, reblogAuthor)
|
|
}
|
|
|
|
// status 2 gets deleted, newly loaded status contain only 1 + 3
|
|
val newStatuses = listOf(
|
|
makeStatus(statusId = 3),
|
|
makeStatus(statusId = 1)
|
|
)
|
|
|
|
timelineDao.deleteRange(1, newStatuses.last().first.serverId, newStatuses.first().first.serverId)
|
|
|
|
for ((status, author, reblogAuthor) in newStatuses) {
|
|
timelineDao.insertInTransaction(status, author, reblogAuthor)
|
|
}
|
|
|
|
//make sure status 2 is no longer in db
|
|
|
|
assertEquals(
|
|
newStatuses,
|
|
timelineDao.getStatusesForAccount(1, null, null, 100).blockingGet()
|
|
.map { it.toTriple() }
|
|
)
|
|
}
|
|
|
|
private fun makeStatus(
|
|
accountId: Long = 1,
|
|
statusId: Long = 10,
|
|
reblog: Boolean = false,
|
|
createdAt: Long = statusId,
|
|
authorServerId: String = "20"
|
|
): Triple<TimelineStatusEntity, TimelineAccountEntity, TimelineAccountEntity?> {
|
|
val author = TimelineAccountEntity(
|
|
authorServerId,
|
|
accountId,
|
|
"localUsername",
|
|
"username",
|
|
"displayName",
|
|
"blah",
|
|
"avatar",
|
|
"[\"tusky\": \"http://tusky.cool/emoji.jpg\"]",
|
|
false
|
|
)
|
|
|
|
val reblogAuthor = if (reblog) {
|
|
TimelineAccountEntity(
|
|
"R$authorServerId",
|
|
accountId,
|
|
"RlocalUsername",
|
|
"Rusername",
|
|
"RdisplayName",
|
|
"Rblah",
|
|
"Ravatar",
|
|
"[]",
|
|
false
|
|
)
|
|
} else null
|
|
|
|
|
|
val even = accountId % 2 == 0L
|
|
val status = TimelineStatusEntity(
|
|
serverId = statusId.toString(),
|
|
url = "url$statusId",
|
|
timelineUserId = accountId,
|
|
authorServerId = authorServerId,
|
|
inReplyToId = "inReplyToId$statusId",
|
|
inReplyToAccountId = "inReplyToAccountId$statusId",
|
|
content = "Content!$statusId",
|
|
createdAt = createdAt,
|
|
emojis = "emojis$statusId",
|
|
reblogsCount = 1 * statusId.toInt(),
|
|
favouritesCount = 2 * statusId.toInt(),
|
|
reblogged = even,
|
|
favourited = !even,
|
|
sensitive = even,
|
|
spoilerText = "spoier$statusId",
|
|
visibility = Status.Visibility.PRIVATE,
|
|
attachments = "attachments$accountId",
|
|
mentions = "mentions$accountId",
|
|
application = "application$accountId",
|
|
reblogServerId = if (reblog) (statusId * 100).toString() else null,
|
|
reblogAccountId = reblogAuthor?.serverId,
|
|
poll = null
|
|
)
|
|
return Triple(status, author, reblogAuthor)
|
|
}
|
|
|
|
private fun createPlaceholder(serverId: String, timelineUserId: Long): TimelineStatusEntity {
|
|
return TimelineStatusEntity(
|
|
serverId = serverId,
|
|
url = null,
|
|
timelineUserId = timelineUserId,
|
|
authorServerId = null,
|
|
inReplyToId = null,
|
|
inReplyToAccountId = null,
|
|
content = null,
|
|
createdAt = 0L,
|
|
emojis = null,
|
|
reblogsCount = 0,
|
|
favouritesCount = 0,
|
|
reblogged = false,
|
|
favourited = false,
|
|
sensitive = false,
|
|
spoilerText = null,
|
|
visibility = null,
|
|
attachments = null,
|
|
mentions = null,
|
|
application = null,
|
|
reblogServerId = null,
|
|
reblogAccountId = null,
|
|
poll = null
|
|
)
|
|
}
|
|
|
|
private fun TimelineStatusWithAccount.toTriple() = Triple(status, account, reblogAccount)
|
|
} |