Skip to content

Commit

Permalink
sqlcipher migration
Browse files Browse the repository at this point in the history
We can only run tests with encrypted database from command line, where db is not cleared after each test. Hence we add cleanup to some tests (WIP)
Add helper to call delete with workaround for sqlcipher/sqlcipher-android#50
  • Loading branch information
mtotschnig committed Oct 22, 2024
1 parent ec9d9e4 commit 1f062cb
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 101 deletions.
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ securityCrypto = "1.1.0-alpha06"
simpledialogfragments = "09a642bc42"
slf4jApi = "2.0.13"
snakeyaml = "2.2"
sqlcipher = "4.5.4"
sqlcipher = "4.6.1"
taptargetview = "1.13.3"
tesseract4androidOpenmp = "4.7.0"
mlkitTextRecognition = "16.0.1"
Expand All @@ -111,7 +111,7 @@ accompanist-themeadapter-material3 = { module = "com.google.accompanist:accompan
acra-core = { module = "ch.acra:acra-core", version.ref = "acraVersion" }
acra-dialog = { module = "ch.acra:acra-dialog", version.ref = "acraVersion" }
acra-mail = { module = "ch.acra:acra-mail", version.ref = "acraVersion" }
android-database-sqlcipher = { module = "net.zetetic:android-database-sqlcipher", version.ref = "sqlcipher" }
android-database-sqlcipher = { module = "net.zetetic:sqlcipher-android", version.ref = "sqlcipher" }
android-image-cropper = { module = "com.github.mtotschnig:Android-Image-Cropper", version.ref = "androidImageCropper" }
android-state = { module = "com.evernote:android-state", version.ref = "evernote" }
android-state-processor = { module = "com.evernote:android-state-processor", version.ref = "evernote" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.adevinta.android.barista.internal.matcher.HelperMatchers
import com.google.common.truth.Truth.assertThat
import org.hamcrest.CoreMatchers.containsString
import org.hamcrest.Matchers
import org.junit.After
import org.junit.Test
import org.totschnig.myexpenses.R
import org.totschnig.myexpenses.activity.Action
Expand All @@ -37,6 +38,10 @@ import org.totschnig.myexpenses.compose.TEST_TAG_EDIT_TEXT
import org.totschnig.myexpenses.compose.TEST_TAG_POSITIVE_BUTTON
import org.totschnig.myexpenses.contract.TransactionsContract.Transactions
import org.totschnig.myexpenses.db2.FLAG_NEUTRAL
import org.totschnig.myexpenses.db2.deleteAccount
import org.totschnig.myexpenses.db2.deleteBudget
import org.totschnig.myexpenses.db2.deleteCategory
import org.totschnig.myexpenses.db2.deleteTemplate
import org.totschnig.myexpenses.model.CurrencyUnit
import org.totschnig.myexpenses.model.Grouping
import org.totschnig.myexpenses.model.Money
Expand All @@ -55,14 +60,22 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
private lateinit var account: org.totschnig.myexpenses.model2.Account
private var categoryId: Long = 0
private var origListSize = 0
private var controlCategory: Long = 0

private fun baseFixture() {
account = buildAccount("Test account 1")
categoryId = writeCategory(label = "TestCategory")
writeCategory(label = "Control Category")
controlCategory = writeCategory(label = "Control Category")
origListSize = repository.count(TransactionProvider.CATEGORIES_URI)
}

@After
fun clearDb() {
repository.deleteAccount(account.id)
repository.deleteCategory(categoryId)
repository.deleteCategory(controlCategory)
}

private fun launch() =
ActivityScenario.launch<ManageCategories>(
Intent(targetContext, ManageCategories::class.java).also {
Expand All @@ -73,18 +86,18 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
testScenario = it
}

private fun fixtureWithMappedTransaction() {
private fun fixtureWithMappedTransaction(): Long {
baseFixture()
with(Transaction.getNewInstance(account.id, homeCurrency)) {
return with(Transaction.getNewInstance(account.id, homeCurrency)) {
amount = Money(homeCurrency, -1200L)
catId = categoryId
save(contentResolver)
ContentUris.parseId(save(contentResolver)!!)
}
}

private fun fixtureWithMappedTemplate() {
private fun fixtureWithMappedTemplate(): Long {
baseFixture()
with(
return with(
Template(
contentResolver,
account.id,
Expand All @@ -95,11 +108,11 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
) {
amount = Money(CurrencyUnit(Currency.getInstance("USD")), -1200L)
catId = categoryId
save(contentResolver)
ContentUris.parseId(save(contentResolver)!!)
}
}

private fun fixtureWithMappedBudget() {
private fun fixtureWithMappedBudget(): Long {
baseFixture()
val budget = Budget(
0L,
Expand All @@ -121,6 +134,7 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
)!!
)
setCategoryBudget(budgetId, categoryId, 50000)
return budgetId
}

private fun setCategoryBudget(
Expand Down Expand Up @@ -161,8 +175,9 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {

@Test
fun shouldNotDeleteCategoryMappedToTransaction() {
fixtureWithMappedTransaction()
val transactionId = fixtureWithMappedTransaction()
launch().use {
assertTextAtPosition("TestCategory", 0)
callDelete()
onView(withId(com.google.android.material.R.id.snackbar_text))
.check(
Expand All @@ -176,11 +191,12 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
)
assertThat(repository.count(TransactionProvider.CATEGORIES_URI)).isEqualTo(origListSize)
}
repository.deleteTransaction(transactionId)
}

@Test
fun shouldNotDeleteCategoryMappedToTemplate() {
fixtureWithMappedTemplate()
val templateId = fixtureWithMappedTemplate()
launch().use {
callDelete()
onView(withId(com.google.android.material.R.id.snackbar_text))
Expand All @@ -194,12 +210,13 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
)
)
assertThat(repository.count(TransactionProvider.CATEGORIES_URI)).isEqualTo(origListSize)
repository.deleteTemplate(templateId)
}
}

@Test
fun shouldNotDeleteCategoryMappedToBudget() {
fixtureWithMappedBudget()
val budgetId = fixtureWithMappedBudget()
launch().use {
callDelete(false)
onView(withText(containsString(getString(R.string.warning_delete_category_with_budget)))).check(
Expand All @@ -208,6 +225,7 @@ class CategoriesCabTest : BaseComposeTest<ManageCategories>() {
onView(withText(R.string.response_no)).perform(click())
assertThat(repository.count(TransactionProvider.CATEGORIES_URI)).isEqualTo(origListSize)
}
repository.deleteBudget(budgetId)
}

private fun callDelete(withConfirmation: Boolean = true, position: Int = 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,16 @@ package org.totschnig.myexpenses.test.espresso
import android.content.ContentUris
import androidx.compose.ui.test.isDisplayed
import androidx.compose.ui.test.onNodeWithText
import androidx.test.espresso.Espresso.onData
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.withId
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.instanceOf
import org.junit.After
import org.totschnig.myexpenses.R
import org.totschnig.myexpenses.activity.ExpenseEdit
import org.totschnig.myexpenses.adapter.IdHolder
import org.totschnig.myexpenses.contract.TransactionsContract.Transactions
import org.totschnig.myexpenses.db2.deleteAccount
import org.totschnig.myexpenses.model.CurrencyUnit
import org.totschnig.myexpenses.model.Money
import org.totschnig.myexpenses.model.Transaction
import org.totschnig.myexpenses.model2.Account
import org.totschnig.myexpenses.provider.DatabaseConstants
import org.totschnig.myexpenses.testutils.withAccount
import java.util.Currency
import kotlin.math.absoluteValue
import kotlin.math.sign
Expand All @@ -27,22 +21,18 @@ import kotlin.test.Test
class CriterionReachedTest : BaseExpenseEditTest() {
val currency = CurrencyUnit(Currency.getInstance("USD"))

lateinit var account2: Account

fun fixture(criterion: Long, withAccount2: Boolean, openingBalance: Long = 0) {
fun fixture(criterion: Long, openingBalance: Long = 0) {
account1 = Account(
label = "Test label 1",
currency = currency.code,
criterion = criterion,
openingBalance = openingBalance
).createIn(repository)
if (withAccount2) {
account2 = Account(
label = "Test label 2",
currency = currency.code,
criterion = criterion
).createIn(repository)
}
}

@After
fun cleanup() {
repository.deleteAccount(account1.id)
}

@Test
Expand Down Expand Up @@ -184,7 +174,7 @@ class CriterionReachedTest : BaseExpenseEditTest() {
expectedTitle: Int?,
openingBalance: Long = 0,
) {
fixture(criterion, false, openingBalance)
fixture(criterion, openingBalance)
launchForResult(intentForNewTransaction.apply {
putExtra(ExpenseEdit.KEY_INCOME, amount > 0)
putExtra(Transactions.OPERATION_TYPE, Transactions.TYPE_TRANSACTION)
Expand All @@ -205,7 +195,7 @@ class CriterionReachedTest : BaseExpenseEditTest() {
editedAmount: Int,
expectedTitle: Int?,
) {
fixture(criterion, false)
fixture(criterion)
val transactionId = Transaction.getNewInstance(account1.id, currency).let {
it.amount = Money(currency, existingAmount)
ContentUris.parseId(it.save(contentResolver)!!)
Expand Down Expand Up @@ -233,7 +223,12 @@ class CriterionReachedTest : BaseExpenseEditTest() {
editedAmount: Int,
expectedTitle: Int?,
) {
fixture(criterion, true)
fixture(criterion)
val account2 = Account(
label = "Test label 2",
currency = currency.code,
criterion = criterion
).createIn(repository)
val transactionId = Transaction.getNewInstance(account1.id, currency).let {
it.amount = Money(currency, existingAmount)
ContentUris.parseId(it.save(contentResolver)!!)
Expand All @@ -254,5 +249,6 @@ class CriterionReachedTest : BaseExpenseEditTest() {
assertFinishing()
}
}
repository.deleteAccount(account2.id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withSubstring
import androidx.test.espresso.matcher.ViewMatchers.withText
import org.junit.After
import org.totschnig.myexpenses.R
import org.totschnig.myexpenses.contract.TransactionsContract.Transactions
import org.totschnig.myexpenses.db2.deleteAccount
import org.totschnig.myexpenses.model.CurrencyUnit
import org.totschnig.myexpenses.model.Money
import org.totschnig.myexpenses.model.Transfer
Expand All @@ -31,13 +33,17 @@ class CriterionReachedTestTransfer : BaseExpenseEditTest() {
currency = currency.code,
criterion = -10000
).createIn(repository)
if (true) {
account2 = Account(
label = "Saving",
currency = currency.code,
criterion = 5000
).createIn(repository)
}
account2 = Account(
label = "Saving",
currency = currency.code,
criterion = 5000
).createIn(repository)
}

@After
fun cleanup() {
repository.deleteAccount(account1.id)
repository.deleteAccount(account2.id)
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.totschnig.myexpenses.test.espresso

import android.content.ContentUris
import android.content.Intent
import androidx.annotation.StringRes
import androidx.compose.ui.test.junit4.createEmptyComposeRule
Expand All @@ -17,12 +18,15 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import org.assertj.core.api.Assertions.assertThat
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.containsString
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.totschnig.myexpenses.R
import org.totschnig.myexpenses.activity.DistributionActivity
import org.totschnig.myexpenses.activity.ProtectedFragmentActivity
import org.totschnig.myexpenses.db2.FLAG_INCOME
import org.totschnig.myexpenses.db2.deleteAccount
import org.totschnig.myexpenses.db2.deleteCategory
import org.totschnig.myexpenses.model.Money
import org.totschnig.myexpenses.model.Transaction
import org.totschnig.myexpenses.model2.Account
Expand All @@ -36,6 +40,12 @@ class DistributionTest : BaseUiTest<DistributionActivity>() {

private lateinit var account: Account

private var categoryExpenseId = 0L
private var categoryIncomeId = 0L
private var transactionExpenseId = 0L
private var transactionIncomeId = 0L


private fun baseFixture(
showIncome: Boolean = false,
showExpense: Boolean = true,
Expand All @@ -56,21 +66,39 @@ class DistributionTest : BaseUiTest<DistributionActivity>() {
showExpense: Boolean = true
) {
baseFixture(showIncome, showExpense) {
val categoryExpenseId = writeCategory("Expense")
val categoryIncomeId = writeCategory("Income", type = FLAG_INCOME)
with(Transaction.getNewInstance(account.id, homeCurrency)) {
categoryExpenseId = writeCategory("Expense")
categoryIncomeId = writeCategory("Income", type = FLAG_INCOME)
transactionExpenseId = with(Transaction.getNewInstance(account.id, homeCurrency)) {
amount = Money(homeCurrency, -1200L)
catId = categoryExpenseId
save(contentResolver)
ContentUris.parseId(save(contentResolver)!!)
}
with(Transaction.getNewInstance(account.id, homeCurrency)) {
transactionIncomeId = with(Transaction.getNewInstance(account.id, homeCurrency)) {
amount = Money(homeCurrency, 3400L)
catId = categoryIncomeId
save(contentResolver)
ContentUris.parseId(save(contentResolver)!!)
}
}
}

@After
fun cleanup() {
if (transactionExpenseId != 0L) {
repository.deleteTransaction(transactionExpenseId)
}
if (transactionIncomeId != 0L) {
repository.deleteTransaction(transactionIncomeId)
}
if (categoryExpenseId != 0L) {
repository.deleteCategory(categoryExpenseId)
}
if (categoryIncomeId != 0L) {
repository.deleteCategory(categoryIncomeId)
}
repository.deleteAccount(account.id)
}


private fun assertIncome() {
onView(allOf(withText(containsString("Income")), withText(containsString("34"))))
.inRoot(isDialog())
Expand Down
Loading

0 comments on commit 1f062cb

Please sign in to comment.