Skip to content

Commit

Permalink
Address book accounts: bind to accounts (again) (#1184)
Browse files Browse the repository at this point in the history
* [WIP] Scope address book acounts to accounts again

* [WIP] Tests

* Fix LocalAddressBookStoreTest

* Adapt AccountsCleanupWorker

* Migration to assign accounts to address books (again)

* Change account in address books on account rename
  • Loading branch information
rfc2822 authored Dec 21, 2024
1 parent 5890b3c commit 03a52e9
Show file tree
Hide file tree
Showing 23 changed files with 499 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,24 @@ class LocalAddressBookStoreTest {
@SpyK
lateinit var context: Context

val account: Account = Account("[email protected]", "Mock Account Type")
val account by lazy { Account("Test Account", context.getString(R.string.account_type)) }
val addressBookAccount by lazy { Account("[email protected]", context.getString(R.string.account_type_address_book)) }

val provider = mockk<ContentProviderClient>(relaxed = true)
val addressBook: LocalAddressBook = mockk(relaxed = true) {
every { account } answers { this@LocalAddressBookStoreTest.account }
every { updateSyncFrameworkSettings() } just runs
every { addressBookAccount } returns account
every { addressBookAccount } answers { this@LocalAddressBookStoreTest.addressBookAccount }
every { settings } returns LocalAddressBookStore.contactsProviderSettings
}

@Suppress("unused") // used by @InjectMockKs LocalAddressBookStore
@RelaxedMockK
lateinit var collectionRepository: DavCollectionRepository

@Suppress("unused") // used by @InjectMockKs LocalAddressBookStore
val localAddressBookFactory = mockk<LocalAddressBook.Factory> {
every { create(account, provider) } returns addressBook
every { create(any(), any(), provider) } returns addressBook
}

@Inject
Expand All @@ -69,6 +74,7 @@ class LocalAddressBookStoreTest {
@RelaxedMockK
lateinit var settingsManager: SettingsManager

@Suppress("unused") // used by @InjectMockKs LocalAddressBookStore
val serviceRepository = mockk<DavServiceRepository>(relaxed = true) {
every { get(any<Long>()) } returns null
every { get(200) } returns mockk<Service> {
Expand Down Expand Up @@ -132,26 +138,28 @@ class LocalAddressBookStoreTest {

@Test
fun test_create_createAccountReturnsNull() {
val collection = mockk<Collection>(relaxed = true) {
val collection = mockk<Collection>(relaxed = true) {
every { serviceId } returns 200
every { id } returns 1
every { url } returns "https://example.com/addressbook/funnyfriends".toHttpUrl()
}
every { localAddressBookStore.createAccount(any(), any(), any()) } returns null
every { localAddressBookStore.createAddressBookAccount(any(), any(), any(), any()) } returns null
assertEquals(null, localAddressBookStore.create(provider, collection))
}

@Test
fun test_create_createAccountReturnsAccount() {
val collection = mockk<Collection>(relaxed = true) {
val collection = mockk<Collection>(relaxed = true) {
every { serviceId } returns 200
every { id } returns 1
every { url } returns "https://example.com/addressbook/funnyfriends".toHttpUrl()
}
every { localAddressBookStore.createAccount(any(), any(), any()) } returns account
every { localAddressBookStore.createAddressBookAccount(any(), any(), any(), any()) } returns addressBookAccount
every { addressBook.readOnly } returns true
val addrBook = localAddressBookStore.create(provider, collection)!!

verify(exactly = 1) { addressBook.updateSyncFrameworkSettings() }
assertEquals(account, addrBook.addressBookAccount)
assertEquals(addressBookAccount, addrBook.addressBookAccount)
assertEquals(LocalAddressBookStore.contactsProviderSettings, addrBook.settings)
assertEquals(true, addrBook.readOnly)

Expand All @@ -164,8 +172,8 @@ class LocalAddressBookStoreTest {
fun test_createAccount_succeeds() {
mockkObject(SystemAccountUtils)
every { SystemAccountUtils.createAccount(any(), any(), any()) } returns true
val result: Account = localAddressBookStore.createAccount(
"[email protected]", 42, "https://example.com/addressbook/funnyfriends"
val result: Account = localAddressBookStore.createAddressBookAccount(
account, "[email protected]", 42, "https://example.com/addressbook/funnyfriends"
)!!
verify(exactly = 1) { SystemAccountUtils.createAccount(any(), any(), any()) }
assertEquals("[email protected]", result.name)
Expand All @@ -174,14 +182,26 @@ class LocalAddressBookStoreTest {


@Test
fun test_getAll_noCorrespondingCollection() {
// account doesn't have an associated Collection in the database
fun test_getAll_differentAccount() {
val accountManager = AccountManager.get(context)
mockkObject(accountManager)
every { accountManager.getAccountsByType(any()) } returns arrayOf(addressBookAccount)
every { accountManager.getUserData(addressBookAccount, LocalAddressBook.USER_DATA_ACCOUNT_NAME) } returns "Another Unrelated Account"
every { accountManager.getUserData(addressBookAccount, LocalAddressBook.USER_DATA_ACCOUNT_TYPE) } returns account.type
val result = localAddressBookStore.getAll(account, provider)
assertTrue(result.isEmpty())
}

@Test
fun test_getAll_sameAccount() {
val accountManager = AccountManager.get(context)
mockkObject(accountManager)
every { accountManager.getAccountsByType(any()) } returns arrayOf(account)
every { accountManager.getAccountsByType(any()) } returns arrayOf(addressBookAccount)
every { accountManager.getUserData(addressBookAccount, LocalAddressBook.USER_DATA_ACCOUNT_NAME) } returns account.name
every { accountManager.getUserData(addressBookAccount, LocalAddressBook.USER_DATA_ACCOUNT_TYPE) } returns account.type
val result = localAddressBookStore.getAll(account, provider)
assertEquals(1, result.size)
assertEquals(account, result.first().addressBookAccount)
assertEquals(addressBookAccount, result.first().addressBookAccount)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ class LocalAddressBookTest {
@ApplicationContext
lateinit var context: Context

val account = Account("Test Account", "Test Account Type")
lateinit var addressBook: LocalTestAddressBook


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

addressBook = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
addressBook = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES)
LocalTestAddressBook.createAccount(context)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package at.bitfire.davdroid.resource

import android.Manifest
import android.accounts.Account
import android.content.ContentProviderClient
import android.content.ContentUris
import android.content.ContentValues
Expand Down Expand Up @@ -69,16 +70,16 @@ class LocalGroupTest {
@Inject
lateinit var addressbookFactory: LocalTestAddressBook.Factory


val account = Account("Test Account", "Test Account Type")
private lateinit var addressBookGroupsAsCategories: LocalTestAddressBook
private lateinit var addressBookGroupsAsVCards: LocalTestAddressBook

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

addressBookGroupsAsCategories = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
addressBookGroupsAsVCards = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)
addressBookGroupsAsCategories = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES)
addressBookGroupsAsVCards = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS)

// clear contacts
addressBookGroupsAsCategories.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import java.util.Optional
import java.util.logging.Logger

class LocalTestAddressBook @AssistedInject constructor(
@Assisted account: Account,
@Assisted provider: ContentProviderClient,
@Assisted override val groupMethod: GroupMethod,
accountSettingsFactory: AccountSettings.Factory,
Expand All @@ -34,6 +35,7 @@ class LocalTestAddressBook @AssistedInject constructor(
serviceRepository: DavServiceRepository,
syncFramework: SyncFrameworkIntegration
): LocalAddressBook(
account = account,
_addressBookAccount = ACCOUNT,
provider = provider,
accountSettingsFactory = accountSettingsFactory,
Expand All @@ -47,7 +49,7 @@ class LocalTestAddressBook @AssistedInject constructor(

@AssistedFactory
interface Factory {
fun create(provider: ContentProviderClient, groupMethod: GroupMethod): LocalTestAddressBook
fun create(account: Account, provider: ContentProviderClient, groupMethod: GroupMethod): LocalTestAddressBook
}

override var readOnly: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package at.bitfire.davdroid.resource.contactrow

import android.Manifest
import android.accounts.Account
import android.content.ContentProviderClient
import android.content.ContentValues
import android.content.Context
Expand Down Expand Up @@ -65,6 +66,8 @@ class CachedGroupMembershipHandlerTest {
@get:Rule
val hiltRule = HiltAndroidRule(this)

val account = Account("Test Account", "Test Account Type")

@Before
fun inject() {
hiltRule.inject()
Expand All @@ -73,7 +76,7 @@ class CachedGroupMembershipHandlerTest {

@Test
fun testMembership() {
val addressBook = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)
val addressBook = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS)

val contact = Contact()
val localContact = LocalContact(addressBook, contact, null, null, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package at.bitfire.davdroid.resource.contactrow

import android.Manifest
import android.accounts.Account
import android.content.ContentProviderClient
import android.content.Context
import android.net.Uri
Expand Down Expand Up @@ -63,6 +64,8 @@ class GroupMembershipBuilderTest {
@ApplicationContext
lateinit var context: Context

val account = Account("Test Account", "Test Account Type")

@Before
fun inject() {
hiltRule.inject()
Expand All @@ -74,7 +77,7 @@ class GroupMembershipBuilderTest {
val contact = Contact().apply {
categories += "TEST GROUP"
}
val addressBookGroupsAsCategories = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
val addressBookGroupsAsCategories = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES)
GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsCategories, false).build().also { result ->
assertEquals(1, result.size)
assertEquals(GroupMembership.CONTENT_ITEM_TYPE, result[0].values[GroupMembership.MIMETYPE])
Expand All @@ -87,7 +90,7 @@ class GroupMembershipBuilderTest {
val contact = Contact().apply {
categories += "TEST GROUP"
}
val addressBookGroupsAsVCards = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)
val addressBookGroupsAsVCards = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS)
GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsVCards, false).build().also { result ->
// group membership is constructed during post-processing
assertEquals(0, result.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package at.bitfire.davdroid.resource.contactrow

import android.Manifest
import android.accounts.Account
import android.content.ContentProviderClient
import android.content.ContentValues
import android.content.Context
Expand Down Expand Up @@ -66,6 +67,8 @@ class GroupMembershipHandlerTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)

val account = Account("Test Account", "Test Account Type")

@Before
fun inject() {
hiltRule.inject()
Expand All @@ -74,7 +77,7 @@ class GroupMembershipHandlerTest {

@Test
fun testMembership_GroupsAsCategories() {
val addressBookGroupsAsCategories = addressbookFactory.create(provider, GroupMethod.CATEGORIES)
val addressBookGroupsAsCategories = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES)
val addressBookGroupsAsCategoriesGroup = addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP")

val contact = Contact()
Expand All @@ -90,7 +93,7 @@ class GroupMembershipHandlerTest {

@Test
fun testMembership_GroupsAsVCards() {
val addressBookGroupsAsVCards = addressbookFactory.create(provider, GroupMethod.GROUP_VCARDS)
val addressBookGroupsAsVCards = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS)

val contact = Contact()
val localContact = LocalContact(addressBookGroupsAsVCards, contact, null, null, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

package at.bitfire.davdroid.settings

import android.accounts.Account
import android.accounts.AccountManager
import android.content.Context
import at.bitfire.davdroid.sync.account.TestAccountAuthenticator
Expand Down Expand Up @@ -38,15 +37,15 @@ class AccountSettingsTest {

@Test(expected = IllegalArgumentException::class)
fun testUpdate_MissingMigrations() {
provideAccount(version = 1) { account ->
TestAccountAuthenticator.provide(version = 1) { account ->
// will run AccountSettings.update
accountSettingsFactory.create(account, abortOnMissingMigration = true)
}
}

@Test
fun testUpdate_RunAllMigrations() {
provideAccount(version = 6) { account ->
TestAccountAuthenticator.provide(version = 6) { account ->
// will run AccountSettings.update
accountSettingsFactory.create(account, abortOnMissingMigration = true)

Expand All @@ -56,14 +55,4 @@ class AccountSettingsTest {
}
}


private fun provideAccount(version: Int, block: (Account) -> Unit) {
val account = TestAccountAuthenticator.create(version = version)
try {
block(account)
} finally {
TestAccountAuthenticator.remove(account)
}
}

}
Loading

0 comments on commit 03a52e9

Please sign in to comment.