mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 19:56:02 +01:00
Prevent group leave event from bumping conversation.
This commit is contained in:
committed by
Alex Hart
parent
b4465953d8
commit
5e968eb831
@@ -0,0 +1,89 @@
|
||||
package org.thoughtcrime.securesms.testing
|
||||
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecret
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import java.security.SecureRandom
|
||||
import android.database.sqlite.SQLiteDatabase as AndroidSQLiteDatabase
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase as SQLCipherSQLiteDatabase
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase as SignalSQLiteDatabase
|
||||
|
||||
/**
|
||||
* Proxy [SQLCipherOpenHelper] to the [TestSQLiteOpenHelper] interface.
|
||||
*/
|
||||
class ProxySQLCipherOpenHelper(
|
||||
context: Context,
|
||||
val readableDatabase: AndroidSQLiteDatabase,
|
||||
val writableDatabase: AndroidSQLiteDatabase,
|
||||
) : SQLCipherOpenHelper(context, DatabaseSecret(ByteArray(32).apply { SecureRandom().nextBytes(this) })) {
|
||||
|
||||
constructor(context: Context, testOpenHelper: TestSQLiteOpenHelper) : this(context, testOpenHelper.readableDatabase, testOpenHelper.writableDatabase)
|
||||
|
||||
override fun close() {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getDatabaseName(): String {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun setWriteAheadLoggingEnabled(enabled: Boolean) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun onConfigure(db: SQLCipherSQLiteDatabase) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun onBeforeDelete(db: SQLCipherSQLiteDatabase?) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun onDowngrade(db: SQLCipherSQLiteDatabase?, oldVersion: Int, newVersion: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun onOpen(db: SQLCipherSQLiteDatabase?) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun onCreate(db: SQLCipherSQLiteDatabase?) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLCipherSQLiteDatabase?, oldVersion: Int, newVersion: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getReadableDatabase(): SQLCipherSQLiteDatabase {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getWritableDatabase(): SQLCipherSQLiteDatabase {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getRawReadableDatabase(): SQLCipherSQLiteDatabase {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getRawWritableDatabase(): SQLCipherSQLiteDatabase {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getSignalReadableDatabase(): SignalSQLiteDatabase {
|
||||
return ProxySignalSQLiteDatabase(readableDatabase)
|
||||
}
|
||||
|
||||
override fun getSignalWritableDatabase(): SignalSQLiteDatabase {
|
||||
return ProxySignalSQLiteDatabase(writableDatabase)
|
||||
}
|
||||
|
||||
override fun getSqlCipherDatabase(): SQLCipherSQLiteDatabase {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun markCurrent(db: SQLCipherSQLiteDatabase?) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package org.thoughtcrime.securesms.testing
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import java.util.Locale
|
||||
import android.database.sqlite.SQLiteDatabase as AndroidSQLiteDatabase
|
||||
import android.database.sqlite.SQLiteTransactionListener as AndroidSQLiteTransactionListener
|
||||
import net.zetetic.database.sqlcipher.SQLiteStatement as SQLCipherSQLiteStatement
|
||||
import net.zetetic.database.sqlcipher.SQLiteTransactionListener as SQLCipherSQLiteTransactionListener
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase as SignalSQLiteDatabase
|
||||
|
||||
/**
|
||||
* Partial implementation of [SignalSQLiteDatabase] using an instance of [AndroidSQLiteDatabase] instead
|
||||
* of SQLCipher.
|
||||
*/
|
||||
class ProxySignalSQLiteDatabase(private val database: AndroidSQLiteDatabase) : SignalSQLiteDatabase(null) {
|
||||
override fun getSqlCipherDatabase(): net.zetetic.database.sqlcipher.SQLiteDatabase {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun beginTransaction() {
|
||||
database.beginTransaction()
|
||||
}
|
||||
|
||||
override fun endTransaction() {
|
||||
database.endTransaction()
|
||||
}
|
||||
|
||||
override fun setTransactionSuccessful() {
|
||||
database.setTransactionSuccessful()
|
||||
}
|
||||
|
||||
override fun query(distinct: Boolean, table: String?, columns: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, groupBy: String?, having: String?, orderBy: String?, limit: String?): Cursor {
|
||||
return database.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)
|
||||
}
|
||||
|
||||
override fun queryWithFactory(
|
||||
cursorFactory: net.zetetic.database.sqlcipher.SQLiteDatabase.CursorFactory?,
|
||||
distinct: Boolean,
|
||||
table: String?,
|
||||
columns: Array<out String>?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?,
|
||||
groupBy: String?,
|
||||
having: String?,
|
||||
orderBy: String?,
|
||||
limit: String?
|
||||
): Cursor {
|
||||
return database.queryWithFactory(null, distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)
|
||||
}
|
||||
|
||||
override fun query(table: String?, columns: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, groupBy: String?, having: String?, orderBy: String?): Cursor {
|
||||
return database.query(table, columns, selection, selectionArgs, groupBy, having, orderBy)
|
||||
}
|
||||
|
||||
override fun query(table: String?, columns: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, groupBy: String?, having: String?, orderBy: String?, limit: String?): Cursor {
|
||||
return database.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)
|
||||
}
|
||||
|
||||
override fun rawQuery(sql: String?, selectionArgs: Array<out String>?): Cursor {
|
||||
return database.rawQuery(sql, selectionArgs)
|
||||
}
|
||||
|
||||
override fun rawQuery(sql: String?, args: Array<out Any>?): Cursor {
|
||||
return database.rawQuery(sql, args?.map(Any::toString)?.toTypedArray())
|
||||
}
|
||||
|
||||
override fun rawQueryWithFactory(cursorFactory: net.zetetic.database.sqlcipher.SQLiteDatabase.CursorFactory?, sql: String?, selectionArgs: Array<out String>?, editTable: String?): Cursor {
|
||||
return database.rawQueryWithFactory(null, sql, selectionArgs, editTable)
|
||||
}
|
||||
|
||||
override fun rawQuery(sql: String?, selectionArgs: Array<out String>?, initialRead: Int, maxRead: Int): Cursor {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun insert(table: String?, nullColumnHack: String?, values: ContentValues?): Long {
|
||||
return database.insert(table, nullColumnHack, values)
|
||||
}
|
||||
|
||||
override fun insertOrThrow(table: String?, nullColumnHack: String?, values: ContentValues?): Long {
|
||||
return database.insertOrThrow(table, nullColumnHack, values)
|
||||
}
|
||||
|
||||
override fun replace(table: String?, nullColumnHack: String?, initialValues: ContentValues?): Long {
|
||||
return database.replace(table, nullColumnHack, initialValues)
|
||||
}
|
||||
|
||||
override fun replaceOrThrow(table: String?, nullColumnHack: String?, initialValues: ContentValues?): Long {
|
||||
return database.replaceOrThrow(table, nullColumnHack, initialValues)
|
||||
}
|
||||
|
||||
override fun insertWithOnConflict(table: String?, nullColumnHack: String?, initialValues: ContentValues?, conflictAlgorithm: Int): Long {
|
||||
return database.insertWithOnConflict(table, nullColumnHack, initialValues, conflictAlgorithm)
|
||||
}
|
||||
|
||||
override fun delete(table: String?, whereClause: String?, whereArgs: Array<out String>?): Int {
|
||||
return database.delete(table, whereClause, whereArgs)
|
||||
}
|
||||
|
||||
override fun update(table: String?, values: ContentValues?, whereClause: String?, whereArgs: Array<out String>?): Int {
|
||||
return database.update(table, values, whereClause, whereArgs)
|
||||
}
|
||||
|
||||
override fun updateWithOnConflict(table: String?, values: ContentValues?, whereClause: String?, whereArgs: Array<out String>?, conflictAlgorithm: Int): Int {
|
||||
return database.updateWithOnConflict(table, values, whereClause, whereArgs, conflictAlgorithm)
|
||||
}
|
||||
|
||||
override fun execSQL(sql: String?) {
|
||||
database.execSQL(sql)
|
||||
}
|
||||
|
||||
override fun rawExecSQL(sql: String?) {
|
||||
database.execSQL(sql)
|
||||
}
|
||||
|
||||
override fun execSQL(sql: String?, bindArgs: Array<out Any>?) {
|
||||
database.execSQL(sql, bindArgs)
|
||||
}
|
||||
|
||||
override fun enableWriteAheadLogging(): Boolean {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun disableWriteAheadLogging() {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun isWriteAheadLoggingEnabled(): Boolean {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun setForeignKeyConstraintsEnabled(enable: Boolean) {
|
||||
database.setForeignKeyConstraintsEnabled(enable)
|
||||
}
|
||||
|
||||
override fun beginTransactionWithListener(transactionListener: SQLCipherSQLiteTransactionListener?) {
|
||||
database.beginTransactionWithListener(object : AndroidSQLiteTransactionListener {
|
||||
override fun onBegin() {
|
||||
transactionListener?.onBegin()
|
||||
}
|
||||
|
||||
override fun onCommit() {
|
||||
transactionListener?.onCommit()
|
||||
}
|
||||
|
||||
override fun onRollback() {
|
||||
transactionListener?.onRollback()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun beginTransactionNonExclusive() {
|
||||
database.beginTransactionNonExclusive()
|
||||
}
|
||||
|
||||
override fun beginTransactionWithListenerNonExclusive(transactionListener: SQLCipherSQLiteTransactionListener?) {
|
||||
database.beginTransactionWithListenerNonExclusive(object : AndroidSQLiteTransactionListener {
|
||||
override fun onBegin() {
|
||||
transactionListener?.onBegin()
|
||||
}
|
||||
|
||||
override fun onCommit() {
|
||||
transactionListener?.onCommit()
|
||||
}
|
||||
|
||||
override fun onRollback() {
|
||||
transactionListener?.onRollback()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun inTransaction(): Boolean {
|
||||
return database.inTransaction()
|
||||
}
|
||||
|
||||
override fun isDbLockedByCurrentThread(): Boolean {
|
||||
return database.isDbLockedByCurrentThread
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun isDbLockedByOtherThreads(): Boolean {
|
||||
return database.isDbLockedByOtherThreads
|
||||
}
|
||||
|
||||
override fun yieldIfContendedSafely(): Boolean {
|
||||
return database.yieldIfContendedSafely()
|
||||
}
|
||||
|
||||
override fun yieldIfContendedSafely(sleepAfterYieldDelay: Long): Boolean {
|
||||
return database.yieldIfContendedSafely(sleepAfterYieldDelay)
|
||||
}
|
||||
|
||||
override fun getVersion(): Int {
|
||||
return database.version
|
||||
}
|
||||
|
||||
override fun setVersion(version: Int) {
|
||||
database.version = version
|
||||
}
|
||||
|
||||
override fun getMaximumSize(): Long {
|
||||
return database.maximumSize
|
||||
}
|
||||
|
||||
override fun setMaximumSize(numBytes: Long): Long {
|
||||
return database.setMaximumSize(numBytes)
|
||||
}
|
||||
|
||||
override fun getPageSize(): Long {
|
||||
return database.pageSize
|
||||
}
|
||||
|
||||
override fun setPageSize(numBytes: Long) {
|
||||
database.pageSize = numBytes
|
||||
}
|
||||
|
||||
override fun compileStatement(sql: String?): SQLCipherSQLiteStatement {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun isReadOnly(): Boolean {
|
||||
return database.isReadOnly
|
||||
}
|
||||
|
||||
override fun isOpen(): Boolean {
|
||||
return database.isOpen
|
||||
}
|
||||
|
||||
override fun needUpgrade(newVersion: Int): Boolean {
|
||||
return database.needUpgrade(newVersion)
|
||||
}
|
||||
|
||||
override fun setLocale(locale: Locale?) {
|
||||
database.setLocale(locale)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.thoughtcrime.securesms.testing
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Helper for creating/reading a database for unit tests.
|
||||
*/
|
||||
object TestDatabaseUtil {
|
||||
|
||||
/**
|
||||
* Create an in-memory only database that is empty. Can pass [onCreate] to do similar operations
|
||||
* one would do in a open helper's onCreate.
|
||||
*/
|
||||
fun inMemoryDatabase(onCreate: OnCreate): ProxySQLCipherOpenHelper {
|
||||
val testSQLiteOpenHelper = TestSQLiteOpenHelper(ApplicationProvider.getApplicationContext(), onCreate)
|
||||
return ProxySQLCipherOpenHelper(ApplicationProvider.getApplicationContext(), testSQLiteOpenHelper)
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a database file located in app/src/test/resources/db. Currently only reads
|
||||
* are allowed due to weird caching of the file resulting in non-deterministic tests.
|
||||
*/
|
||||
fun fromFileDatabase(name: String): ProxySQLCipherOpenHelper {
|
||||
val databaseFile = File(javaClass.getResource("/db/$name")!!.file)
|
||||
val sqliteDatabase = SQLiteDatabase.openDatabase(databaseFile.absolutePath, null, SQLiteDatabase.OPEN_READONLY)
|
||||
return ProxySQLCipherOpenHelper(ApplicationProvider.getApplicationContext(), sqliteDatabase, sqliteDatabase)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.thoughtcrime.securesms.testing
|
||||
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase as AndroidSQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper as AndroidSQLiteOpenHelper
|
||||
|
||||
typealias OnCreate = AndroidSQLiteDatabase.() -> Unit
|
||||
|
||||
/**
|
||||
* [AndroidSQLiteOpenHelper] for use in unit tests.
|
||||
*/
|
||||
class TestSQLiteOpenHelper(context: Context, private val onCreate: OnCreate) : AndroidSQLiteOpenHelper(context, "test", null, 1) {
|
||||
|
||||
fun setup() {
|
||||
onCreate(writableDatabase)
|
||||
}
|
||||
|
||||
override fun onCreate(db: AndroidSQLiteDatabase) {
|
||||
onCreate.invoke(db)
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: AndroidSQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
// no upgrade
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user