Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rfc2822 committed Dec 30, 2024
1 parent ea25201 commit a43d493
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/

package at.bitfire.davdroid.repository

import android.content.Context
import at.bitfire.davdroid.R
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.sync.account.TestAccountAuthenticator
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject
import at.bitfire.davdroid.db.Account as DbAccount

@HiltAndroidTest
class AccountRepositoryTest {

@Inject
lateinit var accountRepository: AccountRepository

@Inject @ApplicationContext
lateinit var context: Context

@Inject
lateinit var db: AppDatabase

@get:Rule
val hiltRule = HiltAndroidRule(this)

@Before
fun setUp() {
hiltRule.inject()
}


@Test
fun testRemoveOrphanedInDb() {
TestAccountAuthenticator.provide(accountType = context.getString(R.string.account_type)) { systemAccount ->
val dao = db.accountDao()
dao.insertOrIgnore(DbAccount(id = 1, name = systemAccount.name))
dao.insertOrIgnore(DbAccount(id = 2, name = "no-corresponding-system-account"))

accountRepository.removeOrphanedInDb()

// now the account without a corresponding system account should be removed
assertEquals(listOf(DbAccount(id = 1, name = systemAccount.name)), db.accountDao().getAll())
}
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package at.bitfire.davdroid.repository

import android.accounts.Account
import android.content.Context
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.db.Service
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.sync.account.TestAccountAuthenticator
import dagger.Lazy
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.testing.HiltAndroidRule
Expand All @@ -18,6 +20,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject
import at.bitfire.davdroid.db.Account as DbAccount

@HiltAndroidTest
class DavCollectionRepositoryTest {
Expand All @@ -41,26 +44,34 @@ class DavCollectionRepositoryTest {
@Inject
lateinit var serviceRepository: DavServiceRepository

var service: Service? = null
lateinit var account: Account
var serviceId: Long = 0L

@Before
fun setUp() {
hiltRule.inject()
service = createTestService(Service.TYPE_CARDDAV)!!

account = TestAccountAuthenticator.create()
db.accountDao().insertOrIgnore(DbAccount(name = account.name))

val service = Service(id=0, accountName=account.name, type= Service.TYPE_CALDAV, principal = null)
serviceId = serviceRepository.insertOrReplace(service)
}

@After
fun cleanUp() {
db.close()

serviceRepository.deleteAll()
TestAccountAuthenticator.remove(account)
}


@Test
fun testOnChangeListener_setForceReadOnly() = runBlocking {
val collectionId = db.collectionDao().insertOrUpdateByUrl(
Collection(
serviceId = service!!.id,
serviceId = serviceId,
type = Collection.TYPE_ADDRESSBOOK,
url = "https://example.com".toHttpUrl(),
forceReadOnly = false,
Expand Down Expand Up @@ -94,10 +105,4 @@ class DavCollectionRepositoryTest {

// Test helpers and dependencies

private fun createTestService(serviceType: String) : Service? {
val service = Service(id=0, accountName="test", type=serviceType, principal = null)
val serviceId = serviceRepository.insertOrReplace(service)
return serviceRepository.get(serviceId)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,61 @@

package at.bitfire.davdroid.repository

import android.accounts.Account
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.HomeSet
import at.bitfire.davdroid.db.Service
import at.bitfire.davdroid.sync.account.TestAccountAuthenticator
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject
import at.bitfire.davdroid.db.Account as DbAccount

@HiltAndroidTest
class DavHomeSetRepositoryTest {

@get:Rule
var hiltRule = HiltAndroidRule(this)

@Inject
lateinit var db: AppDatabase

@Inject
lateinit var repository: DavHomeSetRepository

@Inject
lateinit var serviceRepository: DavServiceRepository

lateinit var account: Account
var serviceId: Long = 0L


@Before
fun setUp() {
hiltRule.inject()

account = TestAccountAuthenticator.create()
db.accountDao().insertOrIgnore(DbAccount(name = account.name))

val service = Service(id=0, accountName=account.name, type= Service.TYPE_CALDAV, principal = null)
serviceId = serviceRepository.insertOrReplace(service)
}

@After
fun tearDown() {
TestAccountAuthenticator.remove(account)
}


@Test
fun testInsertOrUpdate() {
// should insert new row or update (upsert) existing row - without changing its key!
val serviceId = createTestService()

val entry1 = HomeSet(id=0, serviceId=serviceId, personal=true, url="https://example.com/1".toHttpUrl())
val insertId1 = repository.insertOrUpdateByUrl(entry1)
assertEquals(1L, insertId1)
Expand All @@ -57,8 +78,6 @@ class DavHomeSetRepositoryTest {
@Test
fun testDelete() {
// should delete row with given primary key (id)
val serviceId = createTestService()

val entry1 = HomeSet(id=1, serviceId=serviceId, personal=true, url= "https://example.com/1".toHttpUrl())

val insertId1 = repository.insertOrUpdateByUrl(entry1)
Expand All @@ -69,10 +88,4 @@ class DavHomeSetRepositoryTest {
assertEquals(null, repository.getById(1L))
}


private fun createTestService() : Long {
val service = Service(id=0, accountName="test", type= Service.TYPE_CALDAV, principal = null)
return serviceRepository.insertOrReplace(service)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject
import at.bitfire.davdroid.db.Account as DbAccount

@HiltAndroidTest
class AccountSettingsMigration17Test {
Expand Down Expand Up @@ -66,6 +67,7 @@ class AccountSettingsMigration17Test {
accountManager.setAndVerifyUserData(addressBookAccount, LocalAddressBook.USER_DATA_URL, url)

// and is known in database
db.accountDao().insertOrIgnore(DbAccount(name = account.name))
db.serviceDao().insertOrReplace(
Service(
id = 1, accountName = account.name, type = Service.TYPE_CARDDAV, principal = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@ import at.bitfire.davdroid.settings.SettingsManager
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import io.mockk.every
import io.mockk.mockkObject
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject
import at.bitfire.davdroid.db.Account as DbAccount

@HiltAndroidTest
class AccountsCleanupWorkerTest {
Expand All @@ -49,20 +46,22 @@ class AccountsCleanupWorkerTest {
@Inject
lateinit var workerFactory: HiltWorkerFactory

lateinit var accountManager: AccountManager
lateinit var account: Account
lateinit var service: Service

val accountManager by lazy { AccountManager.get(context) }
lateinit var addressBookAccountType: String
lateinit var addressBookAccount: Account
lateinit var service: Service

@Before
fun setUp() {
hiltRule.inject()
TestUtils.setUpWorkManager(context, workerFactory)

service = createTestService(Service.TYPE_CARDDAV)
account = TestAccountAuthenticator.create()
db.accountDao().insertOrIgnore(DbAccount(name = account.name))

// Prepare test account
accountManager = AccountManager.get(context)
addressBookAccountType = context.getString(R.string.account_type_address_book)
addressBookAccount = Account(
"Fancy address book account",
Expand All @@ -74,48 +73,8 @@ class AccountsCleanupWorkerTest {
fun tearDown() {
// Remove the account here in any case; Nice to have when the test fails
accountManager.removeAccountExplicitly(addressBookAccount)
}


@Test
fun testCleanUpServices_noAccount() {
// Insert service that reference to invalid account
db.serviceDao().insertOrReplace(Service(id = 1, accountName = "test", type = Service.TYPE_CALDAV, principal = null))
assertNotNull(db.serviceDao().get(1))

// Create worker and run the method
val worker = TestListenableWorkerBuilder<AccountsCleanupWorker>(context)
.setWorkerFactory(workerFactory)
.build()
worker.cleanUpServices()

// Verify that service is deleted
assertNull(db.serviceDao().get(1))
}

@Test
fun testCleanUpServices_oneAccount() {
val account = Account("test", "test")
val accountManager = AccountManager.get(context)
mockkObject(accountManager)
every { accountManager.getAccountsByType(context.getString(R.string.account_type)) } returns arrayOf(account)

// Insert services, one that reference the existing account and one that references an invalid account
db.serviceDao().insertOrReplace(Service(id = 1, accountName = account.name, type = Service.TYPE_CALDAV, principal = null))
assertNotNull(db.serviceDao().get(1))

db.serviceDao().insertOrReplace(Service(id = 2, accountName = "not existing", type = Service.TYPE_CARDDAV, principal = null))
assertNotNull(db.serviceDao().get(2))

// Create worker and run the method
val worker = TestListenableWorkerBuilder<AccountsCleanupWorker>(context)
.setWorkerFactory(workerFactory)
.build()
worker.cleanUpServices()

// Verify that one service is deleted and the other one is kept
assertNotNull(db.serviceDao().get(1))
assertNull(db.serviceDao().get(2))
TestAccountAuthenticator.remove(account)
}


Expand Down Expand Up @@ -161,13 +120,4 @@ class AccountsCleanupWorkerTest {
}
}


// helpers

private fun createTestService(serviceType: String): Service {
val service = Service(id=0, accountName="test", type=serviceType, principal = null)
val serviceId = db.serviceDao().insertOrReplace(service)
return db.serviceDao().get(serviceId)!!
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ class TestAccountAuthenticator: Service() {
*
* Remove it with [remove].
*/
fun create(version: Int = AccountSettings.CURRENT_VERSION): Account {
val accountType = context.getString(R.string.account_type_test)
fun create(version: Int = AccountSettings.CURRENT_VERSION, accountType: String = context.getString(R.string.account_type_test)): Account {
val account = Account("Test Account No. ${counter.incrementAndGet()}", accountType)

val initialData = AccountSettings.initialUserData(null)
Expand All @@ -72,8 +71,8 @@ class TestAccountAuthenticator: Service() {
/**
* Convenience method to create a test account and remove it after executing the block.
*/
fun provide(version: Int = AccountSettings.CURRENT_VERSION, block: (Account) -> Unit) {
val account = create(version)
fun provide(version: Int = AccountSettings.CURRENT_VERSION, accountType: String = context.getString(R.string.account_type_test), block: (Account) -> Unit) {
val account = create(version, accountType)
try {
block(account)
} finally {
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/kotlin/at/bitfire/davdroid/db/AccountDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,24 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import org.jetbrains.annotations.TestOnly

@Dao
interface AccountDao {

@TestOnly
@Query("SELECT * FROM account")
fun getAll(): List<Account>

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertOrIgnore(account: Account)

@Query("DELETE FROM account WHERE name=:name")
fun deleteByName(name: String)

@Query("DELETE FROM account WHERE name NOT IN (:names)")
fun deleteExceptNames(names: List<String>)

@Query("UPDATE account SET name=:newName WHERE name=:oldName")
fun rename(oldName: String, newName: String)

Expand Down
3 changes: 0 additions & 3 deletions app/src/main/kotlin/at/bitfire/davdroid/db/ServiceDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,4 @@ interface ServiceDao {
@Query("DELETE FROM service WHERE accountName NOT IN (:accountNames)")
fun deleteExceptAccounts(accountNames: Array<String>)

@Query("UPDATE service SET accountName=:newName WHERE accountName=:oldName")
suspend fun renameAccount(oldName: String, newName: String)

}
Loading

0 comments on commit a43d493

Please sign in to comment.