From ac8de37b6fb5d6fc41abec7d87285b167eede4c5 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Wed, 8 Jan 2025 16:49:12 +0100 Subject: [PATCH 1/2] Remove test account type (#1224) * [WIP] Remove "test account" account type * Fix tests --- app/src/androidTest/AndroidManifest.xml | 17 --- .../davdroid/resource/LocalAddressBookTest.kt | 30 ++--- .../davdroid/resource/LocalCalendarTest.kt | 2 +- .../davdroid/resource/LocalEventTest.kt | 50 ++++---- .../davdroid/resource/LocalGroupTest.kt | 65 +++++----- .../davdroid/resource/LocalTestAddressBook.kt | 49 ++++++-- .../CachedGroupMembershipHandlerTest.kt | 64 +++++----- .../contactrow/GroupMembershipBuilderTest.kt | 82 +++++++------ .../contactrow/GroupMembershipHandlerTest.kt | 99 ++++++++-------- .../davdroid/settings/AccountSettingsTest.kt | 6 +- .../AccountSettingsMigration17Test.kt | 4 +- .../davdroid/sync/SyncAdapterServicesTest.kt | 8 +- .../bitfire/davdroid/sync/SyncManagerTest.kt | 6 +- .../sync/account/AccountsCleanupWorkerTest.kt | 72 +++++------ .../sync/account/SystemAccountUtilsTest.kt | 13 +- .../davdroid/sync/account/TestAccount.kt | 53 +++++++++ .../sync/account/TestAccountAuthenticator.kt | 112 ------------------ .../sync/worker/PeriodicSyncWorkerTest.kt | 15 +-- .../sync/worker/SyncWorkerManagerTest.kt | 6 +- app/src/androidTest/res/values/strings.xml | 1 - .../res/xml/test_account_authenticator.xml | 5 - app/src/main/res/xml/sync_calendars.xml | 6 +- app/src/main/res/xml/sync_contacts.xml | 6 +- app/src/main/res/xml/sync_notes.xml | 6 +- app/src/main/res/xml/sync_opentasks.xml | 6 +- app/src/main/res/xml/sync_tasks_org.xml | 6 +- 26 files changed, 364 insertions(+), 425 deletions(-) create mode 100644 app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccount.kt delete mode 100644 app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccountAuthenticator.kt delete mode 100644 app/src/androidTest/res/xml/test_account_authenticator.xml diff --git a/app/src/androidTest/AndroidManifest.xml b/app/src/androidTest/AndroidManifest.xml index 4db39a251..8278e3aa4 100644 --- a/app/src/androidTest/AndroidManifest.xml +++ b/app/src/androidTest/AndroidManifest.xml @@ -7,21 +7,4 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalAddressBookTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalAddressBookTest.kt index 5b3356eed..7de546919 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalAddressBookTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalAddressBookTest.kt @@ -6,7 +6,6 @@ package at.bitfire.davdroid.resource import android.Manifest import android.accounts.Account -import android.accounts.AccountManager import android.content.ContentProviderClient import android.content.ContentUris import android.content.Context @@ -14,7 +13,6 @@ import android.provider.ContactsContract import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import at.bitfire.vcard4android.Contact -import at.bitfire.vcard4android.GroupMethod import at.bitfire.vcard4android.LabeledProperty import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule @@ -24,7 +22,7 @@ import org.junit.After import org.junit.AfterClass import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse -import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.BeforeClass import org.junit.ClassRule @@ -36,16 +34,12 @@ import javax.inject.Inject @HiltAndroidTest class LocalAddressBookTest { + @Inject @ApplicationContext + lateinit var context: Context + @get:Rule val hiltRule = HiltAndroidRule(this) - @Inject - lateinit var addressbookFactory: LocalTestAddressBook.Factory - - @Inject - @ApplicationContext - lateinit var context: Context - val account = Account("Test Account", "Test Account Type") lateinit var addressBook: LocalTestAddressBook @@ -54,15 +48,13 @@ class LocalAddressBookTest { fun setUp() { hiltRule.inject() - addressBook = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES) - LocalTestAddressBook.createAccount(context) + addressBook = LocalTestAddressBook.create(context, account, provider) } @After fun tearDown() { // remove address book - val accountManager = AccountManager.get(context) - accountManager.removeAccountExplicitly(addressBook.addressBookAccount) + addressBook.remove() } @@ -87,7 +79,7 @@ class LocalAddressBookTest { // rename address book val newName = "New Name" addressBook.renameAccount(newName) - assertEquals(Account(newName, LocalTestAddressBook.ACCOUNT.type), addressBook.addressBookAccount) + assertEquals(newName, addressBook.addressBookAccount.name) // check whether contact is still here (including data rows) and not dirty val result = addressBook.findContactById(id) @@ -115,8 +107,8 @@ class LocalAddressBookTest { // rename address book val newName = "New Name" - addressBook.renameAccount(newName) - assertEquals(Account(newName, LocalTestAddressBook.ACCOUNT.type), addressBook.addressBookAccount) + assertTrue(addressBook.renameAccount(newName)) + assertEquals(newName, addressBook.addressBookAccount.name) // check whether group is still here and not dirty val result = addressBook.findGroupById(id) @@ -126,6 +118,7 @@ class LocalAddressBookTest { assertEquals("Test Group", group.displayName) } + companion object { @JvmField @@ -137,9 +130,8 @@ class LocalAddressBookTest { @BeforeClass @JvmStatic fun connect() { - val context = InstrumentationRegistry.getInstrumentation().targetContext + val context = InstrumentationRegistry.getInstrumentation().context provider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)!! - assertNotNull(provider) } @AfterClass diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt index f875d1213..9fc942b0a 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt @@ -119,7 +119,7 @@ class LocalCalendarTest { } @Test - // Flaky, Needs single or rec init of CalendarProvider (InitCalendarProviderRule) + // Needs InitCalendarProviderRule fun testDeleteDirtyEventsWithoutInstances_Recurring_Instances() { val event = Event().apply { dtStart = DtStart("20220120T010203Z") diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt index 01a3ac645..4b15c3add 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt @@ -12,7 +12,6 @@ import android.os.Build import android.provider.CalendarContract import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL import android.provider.CalendarContract.Events -import androidx.datastore.dataStore import androidx.test.platform.app.InstrumentationRegistry import at.bitfire.davdroid.InitCalendarProviderRule import at.bitfire.ical4android.AndroidCalendar @@ -41,29 +40,6 @@ import java.util.UUID class LocalEventTest { - companion object { - - @JvmField - @ClassRule - val initCalendarProviderRule: TestRule = InitCalendarProviderRule.getInstance() - - private lateinit var provider: ContentProviderClient - - @BeforeClass - @JvmStatic - fun setUpClass() { - val context = InstrumentationRegistry.getInstrumentation().targetContext - provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! - } - - @AfterClass - @JvmStatic - fun tearDownClass() { - provider.closeCompat() - } - - } - private val account = Account("LocalCalendarTest", ACCOUNT_TYPE_LOCAL) private lateinit var calendar: LocalCalendar @@ -482,4 +458,28 @@ class LocalEventTest { } } -} + + companion object { + + @JvmField + @ClassRule + val initCalendarProviderRule: TestRule = InitCalendarProviderRule.getInstance() + + private lateinit var provider: ContentProviderClient + + @BeforeClass + @JvmStatic + fun setUpClass() { + val context = InstrumentationRegistry.getInstrumentation().targetContext + provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! + } + + @AfterClass + @JvmStatic + fun tearDownClass() { + provider.closeCompat() + } + + } + +} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalGroupTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalGroupTest.kt index d2da3dba7..8f07d48c9 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalGroupTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalGroupTest.kt @@ -21,6 +21,7 @@ import at.bitfire.vcard4android.GroupMethod import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest +import org.junit.After import org.junit.AfterClass import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -37,39 +38,12 @@ import javax.inject.Inject @HiltAndroidTest class LocalGroupTest { - companion object { - - @JvmField - @ClassRule - val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)!! - - private lateinit var provider: ContentProviderClient - - @BeforeClass - @JvmStatic - fun connect() { - val context = InstrumentationRegistry.getInstrumentation().targetContext - provider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)!! - assertNotNull(provider) - } - - @AfterClass - @JvmStatic - fun disconnect() { - provider.close() - } - } + @Inject @ApplicationContext + lateinit var context: Context @get:Rule val hiltRule = HiltAndroidRule(this) - @Inject - @ApplicationContext - lateinit var context: Context - - @Inject - lateinit var addressbookFactory: LocalTestAddressBook.Factory - val account = Account("Test Account", "Test Account Type") private lateinit var addressBookGroupsAsCategories: LocalTestAddressBook private lateinit var addressBookGroupsAsVCards: LocalTestAddressBook @@ -78,14 +52,20 @@ class LocalGroupTest { fun setup() { hiltRule.inject() - addressBookGroupsAsCategories = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES) - addressBookGroupsAsVCards = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS) + addressBookGroupsAsCategories = LocalTestAddressBook.create(context, account, provider, GroupMethod.CATEGORIES) + addressBookGroupsAsVCards = LocalTestAddressBook.create(context, account, provider, GroupMethod.GROUP_VCARDS) // clear contacts addressBookGroupsAsCategories.clear() addressBookGroupsAsVCards.clear() } + @After + fun tearDown() { + addressBookGroupsAsCategories.remove() + addressBookGroupsAsVCards.remove() + } + @Test fun testApplyPendingMemberships_addPendingMembership() { @@ -279,4 +259,27 @@ class LocalGroupTest { add() } + + companion object { + + @JvmField + @ClassRule + val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)!! + + private lateinit var provider: ContentProviderClient + + @BeforeClass + @JvmStatic + fun connect() { + val context = InstrumentationRegistry.getInstrumentation().context + provider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)!! + } + + @AfterClass + @JvmStatic + fun disconnect() { + provider.close() + } + } + } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalTestAddressBook.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalTestAddressBook.kt index 6ada3200d..0c501b898 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalTestAddressBook.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalTestAddressBook.kt @@ -10,6 +10,7 @@ import android.content.ContentProviderClient import android.content.ContentUris import android.content.Context import android.provider.ContactsContract +import at.bitfire.davdroid.R import at.bitfire.davdroid.repository.DavCollectionRepository import at.bitfire.davdroid.repository.DavServiceRepository import at.bitfire.davdroid.settings.AccountSettings @@ -18,25 +19,30 @@ import at.bitfire.vcard4android.GroupMethod import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import dagger.hilt.InstallIn +import dagger.hilt.android.EntryPointAccessors import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent import org.junit.Assert.assertTrue import java.io.FileNotFoundException import java.util.Optional +import java.util.concurrent.atomic.AtomicInteger import java.util.logging.Logger class LocalTestAddressBook @AssistedInject constructor( @Assisted account: Account, + @Assisted("addressBook") addressBookAccount: Account, @Assisted provider: ContentProviderClient, @Assisted override val groupMethod: GroupMethod, accountSettingsFactory: AccountSettings.Factory, collectionRepository: DavCollectionRepository, - @ApplicationContext context: Context, + @ApplicationContext private val context: Context, logger: Logger, serviceRepository: DavServiceRepository, syncFramework: SyncFrameworkIntegration ): LocalAddressBook( account = account, - _addressBookAccount = ACCOUNT, + _addressBookAccount = addressBookAccount, provider = provider, accountSettingsFactory = accountSettingsFactory, collectionRepository = collectionRepository, @@ -49,7 +55,7 @@ class LocalTestAddressBook @AssistedInject constructor( @AssistedFactory interface Factory { - fun create(account: Account, provider: ContentProviderClient, groupMethod: GroupMethod): LocalTestAddressBook + fun create(account: Account, @Assisted("addressBook") addressBookAccount: Account, provider: ContentProviderClient, groupMethod: GroupMethod): LocalTestAddressBook } override var readOnly: Boolean @@ -97,14 +103,43 @@ class LocalTestAddressBook @AssistedInject constructor( throw FileNotFoundException() } + fun remove() { + val accountManager = AccountManager.get(context) + assertTrue(accountManager.removeAccountExplicitly(addressBookAccount)) + } + companion object { - val ACCOUNT = Account("LocalTestAddressBook", "at.bitfire.davdroid.test") + @dagger.hilt.EntryPoint + @InstallIn(SingletonComponent::class) + interface EntryPoint { + fun localTestAddressBookFactory(): Factory + } + + val counter = AtomicInteger() + + /** + * Creates a [at.bitfire.davdroid.resource.LocalTestAddressBook]. + * + * Make sure to delete it with [at.bitfire.davdroid.resource.LocalTestAddressBook.remove] or [removeAll] after use. + */ + fun create(context: Context, account: Account, provider: ContentProviderClient, groupMethod: GroupMethod = GroupMethod.GROUP_VCARDS): LocalTestAddressBook { + // create new address book account + val addressBookAccount = Account("Test Address Book ${counter.incrementAndGet()}", context.getString(R.string.account_type_address_book)) + val accountManager = AccountManager.get(context) + assertTrue(accountManager.addAccountExplicitly(addressBookAccount, null, null)) + + // return address book with this account + val entryPoint = EntryPointAccessors.fromApplication(context) + val factory = entryPoint.localTestAddressBookFactory() + return factory.create(account, addressBookAccount, provider, groupMethod) + } - fun createAccount(context: Context) { - val am = AccountManager.get(context) - assertTrue("Couldn't create account for local test address-book", am.addAccountExplicitly(ACCOUNT, null, null)) + fun removeAll(context: Context) { + val accountManager = AccountManager.get(context) + for (account in accountManager.getAccountsByType(context.getString(R.string.account_type_address_book))) + accountManager.removeAccountExplicitly(account) } } diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/CachedGroupMembershipHandlerTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/CachedGroupMembershipHandlerTest.kt index 88b8479d5..18429a5c2 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/CachedGroupMembershipHandlerTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/CachedGroupMembershipHandlerTest.kt @@ -32,6 +32,38 @@ import javax.inject.Inject @HiltAndroidTest class CachedGroupMembershipHandlerTest { + @Inject + @ApplicationContext + lateinit var context: Context + + @get:Rule + val hiltRule = HiltAndroidRule(this) + + val account = Account("Test Account", "Test Account Type") + + @Before + fun inject() { + hiltRule.inject() + } + + + @Test + fun testMembership() { + val addressBook = LocalTestAddressBook.create(context, account, provider, GroupMethod.GROUP_VCARDS) + try { + val contact = Contact() + val localContact = LocalContact(addressBook, contact, null, null, 0) + CachedGroupMembershipHandler(localContact).handle(ContentValues().apply { + put(CachedGroupMembership.GROUP_ID, 123456) + put(CachedGroupMembership.RAW_CONTACT_ID, 789) + }, contact) + assertArrayEquals(arrayOf(123456L), localContact.cachedGroupMemberships.toArray()) + } finally { + addressBook.remove() + } + } + + companion object { @JvmField @@ -55,36 +87,4 @@ class CachedGroupMembershipHandlerTest { } - - @Inject - lateinit var addressbookFactory: LocalTestAddressBook.Factory - - @Inject - @ApplicationContext - lateinit var context: Context - - @get:Rule - val hiltRule = HiltAndroidRule(this) - - val account = Account("Test Account", "Test Account Type") - - @Before - fun inject() { - hiltRule.inject() - } - - - @Test - fun testMembership() { - val addressBook = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS) - - val contact = Contact() - val localContact = LocalContact(addressBook, contact, null, null, 0) - CachedGroupMembershipHandler(localContact).handle(ContentValues().apply { - put(CachedGroupMembership.GROUP_ID, 123456) - put(CachedGroupMembership.RAW_CONTACT_ID, 789) - }, contact) - assertArrayEquals(arrayOf(123456L), localContact.cachedGroupMemberships.toArray()) - } - } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt index f41aafe77..4868bd0d7 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipBuilderTest.kt @@ -31,41 +31,15 @@ import javax.inject.Inject @HiltAndroidTest class GroupMembershipBuilderTest { - companion object { - - @JvmField - @ClassRule - val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)!! - - private lateinit var provider: ContentProviderClient - - @BeforeClass - @JvmStatic - fun connect() { - val context: Context = InstrumentationRegistry.getInstrumentation().targetContext - provider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)!! - } - - @AfterClass - @JvmStatic - fun disconnect() { - provider.close() - } - - } + @Inject @ApplicationContext + lateinit var context: Context @get:Rule val hiltRule = HiltAndroidRule(this) - @Inject - lateinit var addressbookFactory: LocalTestAddressBook.Factory - - @Inject - @ApplicationContext - lateinit var context: Context - val account = Account("Test Account", "Test Account Type") + @Before fun inject() { hiltRule.inject() @@ -77,11 +51,15 @@ class GroupMembershipBuilderTest { val contact = Contact().apply { categories += "TEST GROUP" } - 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]) - assertEquals(addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP"), result[0].values[GroupMembership.GROUP_ROW_ID]) + val addressBookGroupsAsCategories = LocalTestAddressBook.create(context, account, provider, GroupMethod.CATEGORIES) + try { + GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsCategories, false).build().also { result -> + assertEquals(1, result.size) + assertEquals(GroupMembership.CONTENT_ITEM_TYPE, result[0].values[GroupMembership.MIMETYPE]) + assertEquals(addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP"), result[0].values[GroupMembership.GROUP_ROW_ID]) + } + } finally { + addressBookGroupsAsCategories.remove() } } @@ -90,11 +68,39 @@ class GroupMembershipBuilderTest { val contact = Contact().apply { categories += "TEST GROUP" } - 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) + val addressBookGroupsAsVCards = LocalTestAddressBook.create(context, account, provider, GroupMethod.GROUP_VCARDS) + try { + GroupMembershipBuilder(Uri.EMPTY, null, contact, addressBookGroupsAsVCards, false).build().also { result -> + // group membership is constructed during post-processing + assertEquals(0, result.size) + } + } finally { + addressBookGroupsAsVCards.remove() + } + } + + + companion object { + + @JvmField + @ClassRule + val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)!! + + private lateinit var provider: ContentProviderClient + + @BeforeClass + @JvmStatic + fun connect() { + val context: Context = InstrumentationRegistry.getInstrumentation().context + provider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)!! + } + + @AfterClass + @JvmStatic + fun disconnect() { + provider.close() } + } } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipHandlerTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipHandlerTest.kt index fff590aa5..c463e4452 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipHandlerTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/contactrow/GroupMembershipHandlerTest.kt @@ -34,6 +34,58 @@ import javax.inject.Inject @HiltAndroidTest class GroupMembershipHandlerTest { + @Inject @ApplicationContext + lateinit var context: Context + + @get:Rule + var hiltRule = HiltAndroidRule(this) + + val account = Account("Test Account", "Test Account Type") + + @Before + fun inject() { + hiltRule.inject() + } + + + @Test + fun testMembership_GroupsAsCategories() { + val addressBookGroupsAsCategories = LocalTestAddressBook.create(context, account, provider, GroupMethod.CATEGORIES) + try { + val addressBookGroupsAsCategoriesGroup = addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP") + + val contact = Contact() + val localContact = LocalContact(addressBookGroupsAsCategories, contact, null, null, 0) + GroupMembershipHandler(localContact).handle(ContentValues().apply { + put(CachedGroupMembership.GROUP_ID, addressBookGroupsAsCategoriesGroup) + put(CachedGroupMembership.RAW_CONTACT_ID, -1) + }, contact) + assertArrayEquals(arrayOf(addressBookGroupsAsCategoriesGroup), localContact.groupMemberships.toArray()) + assertArrayEquals(arrayOf("TEST GROUP"), contact.categories.toArray()) + } finally { + addressBookGroupsAsCategories.remove() + } + } + + + @Test + fun testMembership_GroupsAsVCards() { + val addressBookGroupsAsVCards = LocalTestAddressBook.create(context, account, provider, GroupMethod.GROUP_VCARDS) + try { + val contact = Contact() + val localContact = LocalContact(addressBookGroupsAsVCards, contact, null, null, 0) + GroupMembershipHandler(localContact).handle(ContentValues().apply { + put(CachedGroupMembership.GROUP_ID, 12345) // because the group name is not queried and put into CATEGORIES, the group doesn't have to really exist + put(CachedGroupMembership.RAW_CONTACT_ID, -1) + }, contact) + assertArrayEquals(arrayOf(12345L), localContact.groupMemberships.toArray()) + assertTrue(contact.categories.isEmpty()) + } finally { + addressBookGroupsAsVCards.remove() + } + } + + companion object { @JvmField @@ -58,51 +110,4 @@ class GroupMembershipHandlerTest { } - @Inject - lateinit var addressbookFactory: LocalTestAddressBook.Factory - - @Inject @ApplicationContext - lateinit var context: Context - - @get:Rule - var hiltRule = HiltAndroidRule(this) - - val account = Account("Test Account", "Test Account Type") - - @Before - fun inject() { - hiltRule.inject() - } - - - @Test - fun testMembership_GroupsAsCategories() { - val addressBookGroupsAsCategories = addressbookFactory.create(account, provider, GroupMethod.CATEGORIES) - val addressBookGroupsAsCategoriesGroup = addressBookGroupsAsCategories.findOrCreateGroup("TEST GROUP") - - val contact = Contact() - val localContact = LocalContact(addressBookGroupsAsCategories, contact, null, null, 0) - GroupMembershipHandler(localContact).handle(ContentValues().apply { - put(CachedGroupMembership.GROUP_ID, addressBookGroupsAsCategoriesGroup) - put(CachedGroupMembership.RAW_CONTACT_ID, -1) - }, contact) - assertArrayEquals(arrayOf(addressBookGroupsAsCategoriesGroup), localContact.groupMemberships.toArray()) - assertArrayEquals(arrayOf("TEST GROUP"), contact.categories.toArray()) - } - - - @Test - fun testMembership_GroupsAsVCards() { - val addressBookGroupsAsVCards = addressbookFactory.create(account, provider, GroupMethod.GROUP_VCARDS) - - val contact = Contact() - val localContact = LocalContact(addressBookGroupsAsVCards, contact, null, null, 0) - GroupMembershipHandler(localContact).handle(ContentValues().apply { - put(CachedGroupMembership.GROUP_ID, 12345) // because the group name is not queried and put into CATEGORIES, the group doesn't have to really exist - put(CachedGroupMembership.RAW_CONTACT_ID, -1) - }, contact) - assertArrayEquals(arrayOf(12345L), localContact.groupMemberships.toArray()) - assertTrue(contact.categories.isEmpty()) - } - } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/AccountSettingsTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/AccountSettingsTest.kt index a9d98b686..67eb29a8a 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/AccountSettingsTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/AccountSettingsTest.kt @@ -7,7 +7,7 @@ package at.bitfire.davdroid.settings import android.accounts.AccountManager import android.content.Context import at.bitfire.davdroid.TestUtils -import at.bitfire.davdroid.sync.account.TestAccountAuthenticator +import at.bitfire.davdroid.sync.account.TestAccount import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest @@ -39,7 +39,7 @@ class AccountSettingsTest { @Test(expected = IllegalArgumentException::class) fun testUpdate_MissingMigrations() { - TestAccountAuthenticator.provide(version = 1) { account -> + TestAccount.provide(version = 1) { account -> // will run AccountSettings.update accountSettingsFactory.create(account, abortOnMissingMigration = true) } @@ -47,7 +47,7 @@ class AccountSettingsTest { @Test fun testUpdate_RunAllMigrations() { - TestAccountAuthenticator.provide(version = 6) { account -> + TestAccount.provide(version = 6) { account -> // will run AccountSettings.update accountSettingsFactory.create(account, abortOnMissingMigration = true) diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/migration/AccountSettingsMigration17Test.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/migration/AccountSettingsMigration17Test.kt index 2e4d18630..b45de7891 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/migration/AccountSettingsMigration17Test.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/settings/migration/AccountSettingsMigration17Test.kt @@ -13,7 +13,7 @@ import at.bitfire.davdroid.db.AppDatabase import at.bitfire.davdroid.db.Collection import at.bitfire.davdroid.db.Service import at.bitfire.davdroid.resource.LocalAddressBook -import at.bitfire.davdroid.sync.account.TestAccountAuthenticator +import at.bitfire.davdroid.sync.account.TestAccount import at.bitfire.davdroid.sync.account.setAndVerifyUserData import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule @@ -53,7 +53,7 @@ class AccountSettingsMigration17Test { @Test fun testMigrate_OldAddressBook_CollectionInDB() { - TestAccountAuthenticator.provide(version = 16) { account -> + TestAccount.provide(version = 16) { account -> val accountManager = AccountManager.get(context) val addressBookAccountType = context.getString(R.string.account_type_address_book) var addressBookAccount = Account("Address Book", addressBookAccountType) diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncAdapterServicesTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncAdapterServicesTest.kt index 371fb9c40..6dfe5a615 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncAdapterServicesTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncAdapterServicesTest.kt @@ -16,7 +16,7 @@ import at.bitfire.davdroid.TestUtils import at.bitfire.davdroid.repository.DavCollectionRepository import at.bitfire.davdroid.repository.DavServiceRepository import at.bitfire.davdroid.settings.AccountSettings -import at.bitfire.davdroid.sync.account.TestAccountAuthenticator +import at.bitfire.davdroid.sync.account.TestAccount import at.bitfire.davdroid.sync.worker.SyncWorkerManager import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule @@ -29,7 +29,6 @@ import io.mockk.mockk import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.unmockkAll -import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow @@ -43,6 +42,7 @@ import org.junit.Test import org.junit.rules.Timeout import java.util.logging.Logger import javax.inject.Inject +import kotlin.coroutines.cancellation.CancellationException @HiltAndroidTest class SyncAdapterServicesTest { @@ -84,12 +84,12 @@ class SyncAdapterServicesTest { hiltRule.inject() TestUtils.setUpWorkManager(context, workerFactory) - account = TestAccountAuthenticator.create() + account = TestAccount.create() } @After fun tearDown() { - TestAccountAuthenticator.remove(account) + TestAccount.remove(account) unmockkAll() } diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncManagerTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncManagerTest.kt index 219baba6e..d9d9e8174 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncManagerTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/SyncManagerTest.kt @@ -19,7 +19,7 @@ import at.bitfire.davdroid.db.SyncState import at.bitfire.davdroid.network.HttpClient import at.bitfire.davdroid.repository.DavSyncStatsRepository import at.bitfire.davdroid.settings.AccountSettings -import at.bitfire.davdroid.sync.account.TestAccountAuthenticator +import at.bitfire.davdroid.sync.account.TestAccount import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -78,14 +78,14 @@ class SyncManagerTest { hiltRule.inject() TestUtils.setUpWorkManager(context, workerFactory) - account = TestAccountAuthenticator.create() + account = TestAccount.create() server.start() } @After fun tearDown() { - TestAccountAuthenticator.remove(account) + TestAccount.remove(account) // clear annoying syncError notifications NotificationManagerCompat.from(context).cancelAll() diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/AccountsCleanupWorkerTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/AccountsCleanupWorkerTest.kt index 1bd531e23..bdd80ff68 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/AccountsCleanupWorkerTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/AccountsCleanupWorkerTest.kt @@ -11,12 +11,11 @@ import at.bitfire.davdroid.TestUtils import at.bitfire.davdroid.db.AppDatabase import at.bitfire.davdroid.db.Service import at.bitfire.davdroid.resource.LocalAddressBook +import at.bitfire.davdroid.resource.LocalTestAddressBook 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 @@ -36,8 +35,7 @@ class AccountsCleanupWorkerTest { @Inject lateinit var accountsCleanupWorkerFactory: AccountsCleanupWorker.Factory - @Inject - @ApplicationContext + @Inject @ApplicationContext lateinit var context: Context @Inject @@ -59,15 +57,14 @@ class AccountsCleanupWorkerTest { hiltRule.inject() TestUtils.setUpWorkManager(context, workerFactory) - service = createTestService(Service.TYPE_CARDDAV) - - // Prepare test account accountManager = AccountManager.get(context) + service = createTestService() + addressBookAccountType = context.getString(R.string.account_type_address_book) - addressBookAccount = Account( - "Fancy address book account", - addressBookAccountType - ) + addressBookAccount = Account("Fancy address book account", addressBookAccountType) + + // Make sure there are no address books + LocalTestAddressBook.removeAll(context) } @After @@ -95,27 +92,24 @@ class AccountsCleanupWorkerTest { @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)) + TestAccount.provide { existingAccount -> + // Insert services, one that reference the existing account and one that references an invalid account + db.serviceDao().insertOrReplace(Service(id = 1, accountName = existingAccount.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)) + 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(context) - .setWorkerFactory(workerFactory) - .build() - worker.cleanUpServices() + // Create worker and run the method + val worker = TestListenableWorkerBuilder(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)) + // Verify that one service is deleted and the other one is kept + assertNotNull(db.serviceDao().get(1)) + assertNull(db.serviceDao().get(2)) + } } @@ -123,9 +117,7 @@ class AccountsCleanupWorkerTest { fun testCleanUpAddressBooks_deletesAddressBookWithoutAccount() { // Create address book account without corresponding account assertTrue(accountManager.addAccountExplicitly(addressBookAccount, null, null)) - - val addressBookAccounts = accountManager.getAccountsByType(addressBookAccountType) - assertEquals(addressBookAccount, addressBookAccounts.firstOrNull()) + assertEquals(listOf(addressBookAccount), accountManager.getAccountsByType(addressBookAccountType).toList()) // Create worker and run the method val worker = TestListenableWorkerBuilder(context) @@ -139,16 +131,14 @@ class AccountsCleanupWorkerTest { @Test fun testCleanUpAddressBooks_keepsAddressBookWithAccount() { - TestAccountAuthenticator.provide { account -> + TestAccount.provide { existingAccount -> // Create address book account _with_ corresponding account and verify val userData = Bundle(2).apply { - putString(LocalAddressBook.USER_DATA_ACCOUNT_NAME, account.name) - putString(LocalAddressBook.USER_DATA_ACCOUNT_TYPE, account.type) + putString(LocalAddressBook.USER_DATA_ACCOUNT_NAME, existingAccount.name) + putString(LocalAddressBook.USER_DATA_ACCOUNT_TYPE, existingAccount.type) } assertTrue(accountManager.addAccountExplicitly(addressBookAccount, null, userData)) - - val addressBookAccounts = accountManager.getAccountsByType(addressBookAccountType) - assertEquals(addressBookAccount, addressBookAccounts.firstOrNull()) + assertEquals(listOf(addressBookAccount), accountManager.getAccountsByType(addressBookAccountType).toList()) // Create worker and run the method val worker = TestListenableWorkerBuilder(context) @@ -157,15 +147,15 @@ class AccountsCleanupWorkerTest { worker.cleanUpAddressBooks() // Verify account was _not_ deleted - assertEquals(addressBookAccount, addressBookAccounts.firstOrNull()) + assertEquals(listOf(addressBookAccount), accountManager.getAccountsByType(addressBookAccountType).toList()) } } // helpers - private fun createTestService(serviceType: String): Service { - val service = Service(id=0, accountName="test", type=serviceType, principal = null) + private fun createTestService(): Service { + val service = Service(id=0, accountName="test", type=Service.TYPE_CARDDAV, principal = null) val serviceId = db.serviceDao().insertOrReplace(service) return db.serviceDao().get(serviceId)!! } diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/SystemAccountUtilsTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/SystemAccountUtilsTest.kt index 446a973f2..b05b36d27 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/SystemAccountUtilsTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/SystemAccountUtilsTest.kt @@ -8,9 +8,8 @@ import android.accounts.Account import android.accounts.AccountManager import android.content.Context import android.os.Bundle -import androidx.test.platform.app.InstrumentationRegistry +import at.bitfire.davdroid.R import at.bitfire.davdroid.settings.SettingsManager -import at.bitfire.davdroid.test.R import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest @@ -27,19 +26,12 @@ class SystemAccountUtilsTest { @get:Rule val hiltRule = HiltAndroidRule(this) - @Inject - @ApplicationContext + @Inject @ApplicationContext lateinit var context: Context - val testContext = InstrumentationRegistry.getInstrumentation().context @Inject lateinit var settingsManager: SettingsManager - val account = Account( - "AccountUtilsTest", - testContext.getString(R.string.account_type_test) - ) - @Before fun setUp() { hiltRule.inject() @@ -52,6 +44,7 @@ class SystemAccountUtilsTest { userData.putString("int", "1") userData.putString("string", "abc/\"-") + val account = Account("AccountUtilsTest", context.getString(R.string.account_type)) val manager = AccountManager.get(context) try { assertTrue(SystemAccountUtils.createAccount(context, account, userData)) diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccount.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccount.kt new file mode 100644 index 000000000..58fe2d2c9 --- /dev/null +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccount.kt @@ -0,0 +1,53 @@ +/*************************************************************************************************** + * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details. + **************************************************************************************************/ +package at.bitfire.davdroid.sync.account + +import android.accounts.Account +import android.accounts.AccountManager +import androidx.test.platform.app.InstrumentationRegistry +import at.bitfire.davdroid.R +import at.bitfire.davdroid.settings.AccountSettings +import org.junit.Assert.assertTrue + +object TestAccount { + + private val targetContext by lazy { InstrumentationRegistry.getInstrumentation().targetContext } + + /** + * Creates a test account, usually in the `Before` setUp of a test. + * + * Remove it with [remove]. + */ + fun create(version: Int = AccountSettings.CURRENT_VERSION): Account { + val accountType = targetContext.getString(R.string.account_type) + val account = Account("Test Account", accountType) + + val initialData = AccountSettings.initialUserData(null) + initialData.putString(AccountSettings.KEY_SETTINGS_VERSION, version.toString()) + assertTrue(SystemAccountUtils.createAccount(targetContext, account, initialData)) + + return account + } + + /** + * Removes a test account, usually in the `@After` tearDown of a test. + */ + fun remove(account: Account) { + val am = AccountManager.get(targetContext) + assertTrue(am.removeAccountExplicitly(account)) + } + + /** + * 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) + try { + block(account) + } finally { + remove(account) + } + } + +} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccountAuthenticator.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccountAuthenticator.kt deleted file mode 100644 index f71e0801e..000000000 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccountAuthenticator.kt +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************************************** - * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details. - **************************************************************************************************/ -package at.bitfire.davdroid.sync.account - -import android.accounts.AbstractAccountAuthenticator -import android.accounts.Account -import android.accounts.AccountAuthenticatorResponse -import android.accounts.AccountManager -import android.app.Service -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.test.platform.app.InstrumentationRegistry -import at.bitfire.davdroid.settings.AccountSettings -import at.bitfire.davdroid.test.R -import org.junit.Assert.assertTrue -import java.util.concurrent.atomic.AtomicInteger - -/** - * Handles the test account type, which has no sync adapters and side effects that run unintentionally. - * - * Usually used like this: - * - * ``` - * lateinit var account: Account - * - * @Before - * fun setUp() { - * account = TestAccountAuthenticator.create() - * - * // You can now use the test account. - * } - * - * @After - * fun tearDown() { - * TestAccountAuthenticator.remove(account) - * } - * ``` - */ -class TestAccountAuthenticator: Service() { - - companion object { - - private val context by lazy { InstrumentationRegistry.getInstrumentation().context } - val counter = AtomicInteger(0) - - /** - * Creates a test account, usually in the `Before` setUp of a test. - * - * Remove it with [remove]. - */ - fun create(version: Int = AccountSettings.CURRENT_VERSION): Account { - val accountType = context.getString(R.string.account_type_test) - val account = Account("Test Account No. ${counter.incrementAndGet()}", accountType) - - val initialData = AccountSettings.initialUserData(null) - initialData.putString(AccountSettings.KEY_SETTINGS_VERSION, version.toString()) - assertTrue(SystemAccountUtils.createAccount(context, account, initialData)) - - return account - } - - /** - * Removes a test account, usually in the `@After` tearDown of a test. - */ - fun remove(account: Account) { - val am = AccountManager.get(context) - assertTrue(am.removeAccountExplicitly(account)) - } - - /** - * 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) - try { - block(account) - } finally { - remove(account) - } - } - - } - - - private lateinit var accountAuthenticator: AccountAuthenticator - - - override fun onCreate() { - accountAuthenticator = AccountAuthenticator(this) - } - - override fun onBind(intent: Intent?) = - accountAuthenticator.iBinder.takeIf { intent?.action == AccountManager.ACTION_AUTHENTICATOR_INTENT } - - - private class AccountAuthenticator( - val context: Context - ): AbstractAccountAuthenticator(context) { - - override fun addAccount(response: AccountAuthenticatorResponse?, accountType: String?, authTokenType: String?, requiredFeatures: Array?, options: Bundle?) = null - override fun editProperties(response: AccountAuthenticatorResponse?, accountType: String?) = null - override fun getAuthTokenLabel(p0: String?) = null - override fun confirmCredentials(p0: AccountAuthenticatorResponse?, p1: Account?, p2: Bundle?) = null - override fun updateCredentials(p0: AccountAuthenticatorResponse?, p1: Account?, p2: String?, p3: Bundle?) = null - override fun getAuthToken(p0: AccountAuthenticatorResponse?, p1: Account?, p2: String?, p3: Bundle?) = null - override fun hasFeatures(p0: AccountAuthenticatorResponse?, p1: Account?, p2: Array?) = null - - } - -} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/PeriodicSyncWorkerTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/PeriodicSyncWorkerTest.kt index 455c83e2f..63200307f 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/PeriodicSyncWorkerTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/PeriodicSyncWorkerTest.kt @@ -6,17 +6,16 @@ package at.bitfire.davdroid.sync.worker import android.accounts.Account import android.content.Context -import androidx.test.platform.app.InstrumentationRegistry import androidx.work.ListenableWorker import androidx.work.WorkManager import androidx.work.WorkerFactory import androidx.work.WorkerParameters import androidx.work.testing.TestListenableWorkerBuilder import androidx.work.workDataOf +import at.bitfire.davdroid.R import at.bitfire.davdroid.TestUtils import at.bitfire.davdroid.sync.SyncDataType -import at.bitfire.davdroid.sync.account.TestAccountAuthenticator -import at.bitfire.davdroid.test.R +import at.bitfire.davdroid.sync.account.TestAccount import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest @@ -33,10 +32,8 @@ import javax.inject.Inject @HiltAndroidTest class PeriodicSyncWorkerTest { - @Inject - @ApplicationContext + @Inject @ApplicationContext lateinit var context: Context - val testContext = InstrumentationRegistry.getInstrumentation().context @Inject lateinit var syncWorkerFactory: PeriodicSyncWorker.Factory @@ -51,18 +48,18 @@ class PeriodicSyncWorkerTest { hiltRule.inject() TestUtils.setUpWorkManager(context) - account = TestAccountAuthenticator.create() + account = TestAccount.create() } @After fun tearDown() { - TestAccountAuthenticator.remove(account) + TestAccount.remove(account) } @Test fun doWork_cancelsItselfOnInvalidAccount() { - val invalidAccount = Account("invalid", testContext.getString(R.string.account_type_test)) + val invalidAccount = Account("invalid", context.getString(R.string.account_type)) // Run PeriodicSyncWorker as TestWorker val inputData = workDataOf( diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/SyncWorkerManagerTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/SyncWorkerManagerTest.kt index b28864a39..c7f8be84c 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/SyncWorkerManagerTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/sync/worker/SyncWorkerManagerTest.kt @@ -10,7 +10,7 @@ import androidx.hilt.work.HiltWorkerFactory import at.bitfire.davdroid.TestUtils import at.bitfire.davdroid.TestUtils.workScheduledOrRunning import at.bitfire.davdroid.sync.SyncDataType -import at.bitfire.davdroid.sync.account.TestAccountAuthenticator +import at.bitfire.davdroid.sync.account.TestAccount import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest @@ -46,12 +46,12 @@ class SyncWorkerManagerTest { hiltRule.inject() TestUtils.setUpWorkManager(context, workerFactory) - account = TestAccountAuthenticator.create() + account = TestAccount.create() } @After fun tearDown() { - TestAccountAuthenticator.remove(account) + TestAccount.remove(account) } diff --git a/app/src/androidTest/res/values/strings.xml b/app/src/androidTest/res/values/strings.xml index 8daf014d1..75c07e1a5 100644 --- a/app/src/androidTest/res/values/strings.xml +++ b/app/src/androidTest/res/values/strings.xml @@ -10,6 +10,5 @@ Davx5Test - at.bitfire.davdroid.test \ No newline at end of file diff --git a/app/src/androidTest/res/xml/test_account_authenticator.xml b/app/src/androidTest/res/xml/test_account_authenticator.xml deleted file mode 100644 index 948c49a44..000000000 --- a/app/src/androidTest/res/xml/test_account_authenticator.xml +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/app/src/main/res/xml/sync_calendars.xml b/app/src/main/res/xml/sync_calendars.xml index 7b01f2054..d047b5d56 100644 --- a/app/src/main/res/xml/sync_calendars.xml +++ b/app/src/main/res/xml/sync_calendars.xml @@ -1,6 +1,6 @@ \ No newline at end of file + android:supportsUploading="true" + android:allowParallelSyncs="true" /> \ No newline at end of file diff --git a/app/src/main/res/xml/sync_contacts.xml b/app/src/main/res/xml/sync_contacts.xml index 87b67ec1c..23a5173a1 100644 --- a/app/src/main/res/xml/sync_contacts.xml +++ b/app/src/main/res/xml/sync_contacts.xml @@ -1,6 +1,6 @@ \ No newline at end of file + android:supportsUploading="true" + android:allowParallelSyncs="true" /> \ No newline at end of file diff --git a/app/src/main/res/xml/sync_notes.xml b/app/src/main/res/xml/sync_notes.xml index 1db9a29d0..d571b982f 100644 --- a/app/src/main/res/xml/sync_notes.xml +++ b/app/src/main/res/xml/sync_notes.xml @@ -1,6 +1,6 @@ \ No newline at end of file + android:supportsUploading="true" + android:allowParallelSyncs="true" /> \ No newline at end of file diff --git a/app/src/main/res/xml/sync_opentasks.xml b/app/src/main/res/xml/sync_opentasks.xml index dfa5c7984..6e82cdf2c 100644 --- a/app/src/main/res/xml/sync_opentasks.xml +++ b/app/src/main/res/xml/sync_opentasks.xml @@ -1,6 +1,6 @@ \ No newline at end of file + android:supportsUploading="true" + android:allowParallelSyncs="true" /> \ No newline at end of file diff --git a/app/src/main/res/xml/sync_tasks_org.xml b/app/src/main/res/xml/sync_tasks_org.xml index ecd712be5..f93254975 100644 --- a/app/src/main/res/xml/sync_tasks_org.xml +++ b/app/src/main/res/xml/sync_tasks_org.xml @@ -1,6 +1,6 @@ \ No newline at end of file + android:supportsUploading="true" + android:allowParallelSyncs="true" /> \ No newline at end of file From 843013a0f0820497cf73799d59e144e69dcb7632 Mon Sep 17 00:00:00 2001 From: Sunik Kupfer Date: Thu, 9 Jan 2025 12:08:11 +0100 Subject: [PATCH 2/2] Use StringDef to annotate possible service and collection types (#1227) * Add StringDef annotation to collection type param * Add StringDef annotation to service type param --- .../main/kotlin/at/bitfire/davdroid/db/Collection.kt | 12 +++++++++++- .../main/kotlin/at/bitfire/davdroid/db/Service.kt | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt index e79668823..1fbc0269f 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt @@ -4,6 +4,7 @@ package at.bitfire.davdroid.db +import androidx.annotation.StringDef import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey @@ -29,6 +30,14 @@ import at.bitfire.ical4android.util.DateUtils import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +@Retention(AnnotationRetention.SOURCE) +@StringDef( + Collection.TYPE_ADDRESSBOOK, + Collection.TYPE_CALENDAR, + Collection.TYPE_WEBCAL +) +annotation class CollectionType + @Entity(tableName = "collection", foreignKeys = [ ForeignKey(entity = Service::class, parentColumns = arrayOf("id"), childColumns = arrayOf("serviceId"), onDelete = ForeignKey.CASCADE), @@ -67,7 +76,8 @@ data class Collection( /** * Type of service. CalDAV or CardDAV */ - var type: String, + @CollectionType + val type: String, /** * Address where this collection lives - with trailing slash diff --git a/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt b/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt index 074d7f84d..66837d951 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/db/Service.kt @@ -4,11 +4,16 @@ package at.bitfire.davdroid.db +import androidx.annotation.StringDef import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey import okhttp3.HttpUrl +@Retention(AnnotationRetention.SOURCE) +@StringDef(Service.TYPE_CALDAV, Service.TYPE_CARDDAV) +annotation class ServiceType + /** * A service entity. * @@ -24,6 +29,8 @@ data class Service( var id: Long, var accountName: String, + + @ServiceType var type: String, var principal: HttpUrl?