mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 11:05:25 +00:00
fix: remove hilt testing, add spy on app context storage field instead, update libsession-util to fixed sodium cmake branch
This commit is contained in:
parent
c445267ed9
commit
2d1c0b3c02
@ -127,10 +127,6 @@ dependencies {
|
||||
testImplementation 'org.assertj:assertj-core:3.11.1'
|
||||
testImplementation "org.mockito:mockito-inline:4.10.0"
|
||||
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
||||
|
||||
androidTestImplementation "com.google.dagger:hilt-android-testing:$daggerVersion"
|
||||
kaptAndroidTest "com.google.dagger:hilt-android-compiler:$daggerVersion"
|
||||
|
||||
androidTestImplementation "org.mockito:mockito-android:4.10.0"
|
||||
androidTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
||||
testImplementation "androidx.test:core:$testCoreVersion"
|
||||
@ -226,7 +222,7 @@ android {
|
||||
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
|
||||
|
||||
resConfigs autoResConfig()
|
||||
testInstrumentationRunner "network.loki.messenger.util.HiltApplicationRunner"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
// The following argument makes the Android Test Orchestrator run its
|
||||
// "pm clear" command after each test invocation. This command ensures
|
||||
// that the app's state is completely cleared between tests.
|
||||
|
@ -3,21 +3,17 @@ package network.loki.messenger
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import dagger.hilt.android.testing.CustomTestApplication
|
||||
import dagger.hilt.android.testing.HiltAndroidRule
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import network.loki.messenger.libsession_util.Contacts
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.argThat
|
||||
import org.mockito.kotlin.eq
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.utilities.KeyHelper
|
||||
@ -26,17 +22,10 @@ import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||
import kotlin.random.Random
|
||||
|
||||
@CustomTestApplication(ApplicationContext::class)
|
||||
interface HiltApplicationContext
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@SmallTest
|
||||
@HiltAndroidTest
|
||||
class LibSessionTests {
|
||||
|
||||
@get:Rule
|
||||
val hiltRule = HiltAndroidRule(this)
|
||||
|
||||
private fun randomSeedBytes() = (0 until 16).map { Random.nextInt(UByte.MAX_VALUE.toInt()).toByte() }
|
||||
private fun randomKeyPair() = KeyPairUtilities.generate(randomSeedBytes().toByteArray())
|
||||
private fun randomSessionId() = randomKeyPair().x25519KeyPair.hexEncodedPublicKey
|
||||
@ -86,8 +75,9 @@ class LibSessionTests {
|
||||
|
||||
@Test
|
||||
fun migration_one_to_ones() {
|
||||
val storageSpy = spy(MessagingModuleConfiguration.shared.storage)
|
||||
whenever(MessagingModuleConfiguration.shared.storage).thenReturn(storageSpy)
|
||||
val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
val storageSpy = spy(app.storage)
|
||||
app.storage = storageSpy
|
||||
|
||||
val newContactId = randomSessionId()
|
||||
val singleContact = Contact(
|
||||
@ -98,7 +88,10 @@ class LibSessionTests {
|
||||
val newContactMerge = buildContactMessage(listOf(singleContact))
|
||||
val contacts = MessagingModuleConfiguration.shared.configFactory.contacts!!
|
||||
fakePollNewConfig(contacts, newContactMerge)
|
||||
verify(storageSpy).addLibSessionContacts(any())
|
||||
verify(storageSpy).addLibSessionContacts(argThat {
|
||||
first().let { it.id == newContactId && it.approved } && size == 1
|
||||
})
|
||||
verify(storageSpy).setRecipientApproved(argThat { address.serialize() == newContactId }, eq(true))
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package network.loki.messenger.util
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.test.runner.AndroidJUnitRunner
|
||||
import network.loki.messenger.HiltApplicationContext
|
||||
|
||||
class HiltApplicationRunner: AndroidJUnitRunner() {
|
||||
|
||||
override fun newApplication(
|
||||
cl: ClassLoader?,
|
||||
className: String?,
|
||||
context: Context?
|
||||
): Application {
|
||||
return super.newApplication(cl, HiltApplicationContext::class.java.name, context)
|
||||
}
|
||||
}
|
@ -127,7 +127,7 @@ import network.loki.messenger.libsession_util.UserProfile;
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
@HiltAndroidApp
|
||||
public class ApplicationContext extends BaseApplication implements DefaultLifecycleObserver, ConfigFactoryUpdateListener {
|
||||
public class ApplicationContext extends Application implements DefaultLifecycleObserver, ConfigFactoryUpdateListener {
|
||||
|
||||
public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
|
||||
|
||||
@ -149,7 +149,7 @@ public class ApplicationContext extends BaseApplication implements DefaultLifecy
|
||||
private PersistentLogger persistentLogger;
|
||||
|
||||
@Inject LokiAPIDatabase lokiAPIDatabase;
|
||||
@Inject Storage storage;
|
||||
@Inject public Storage storage;
|
||||
@Inject MessageDataProvider messageDataProvider;
|
||||
@Inject JobDatabase jobDatabase;
|
||||
@Inject TextSecurePreferences textSecurePreferences;
|
||||
@ -209,6 +209,7 @@ public class ApplicationContext extends BaseApplication implements DefaultLifecy
|
||||
}
|
||||
storage.notifyConfigUpdates(forConfigObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
DatabaseModule.init(this);
|
||||
|
@ -1,19 +0,0 @@
|
||||
package org.thoughtcrime.securesms
|
||||
|
||||
import android.app.Application
|
||||
import org.session.libsession.database.MessageDataProvider
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.database.JobDatabase
|
||||
import org.thoughtcrime.securesms.database.LokiAPIDatabase
|
||||
import org.thoughtcrime.securesms.database.Storage
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class BaseApplication: Application() {
|
||||
lateinit var lokiAPIDatabase: LokiAPIDatabase
|
||||
lateinit var storage: Storage
|
||||
lateinit var messageDataProvider: MessageDataProvider
|
||||
lateinit var jobDatabase: JobDatabase
|
||||
lateinit var textSecurePreferences: TextSecurePreferences
|
||||
lateinit var configFactory: ConfigFactory
|
||||
}
|
@ -14,9 +14,11 @@ import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class ConfigFactory(private val context: Context,
|
||||
private val configDatabase: ConfigDatabase,
|
||||
private val maybeGetUserInfo: ()->Pair<ByteArray, String>?):
|
||||
class ConfigFactory(
|
||||
private val context: Context,
|
||||
private val configDatabase: ConfigDatabase,
|
||||
private val maybeGetUserInfo: () -> Pair<ByteArray, String>?
|
||||
) :
|
||||
ConfigFactoryProtocol {
|
||||
|
||||
fun keyPairChanged() { // this should only happen restoring or clearing data
|
||||
@ -36,77 +38,99 @@ class ConfigFactory(private val context: Context,
|
||||
private var _convoVolatileConfig: ConversationVolatileConfig? = null
|
||||
private val userGroupsLock = Object()
|
||||
private var _userGroups: UserGroupsConfig? = null
|
||||
private val factoryExecutor = Executors.newSingleThreadExecutor()
|
||||
|
||||
private val listeners: MutableList<ConfigFactoryUpdateListener> = mutableListOf()
|
||||
fun registerListener(listener: ConfigFactoryUpdateListener) { listeners += listener }
|
||||
fun unregisterListener(listener: ConfigFactoryUpdateListener) { listeners -= listener }
|
||||
|
||||
override val user: UserProfile? get() = synchronized(userLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_userConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey)
|
||||
_userConfig = if (userDump != null) {
|
||||
UserProfile.newInstance(secretKey, userDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateUserProfileConfigDump()?.let { dump ->
|
||||
UserProfile.newInstance(secretKey, dump)
|
||||
} ?: UserProfile.newInstance(secretKey)
|
||||
}
|
||||
}
|
||||
_userConfig
|
||||
fun registerListener(listener: ConfigFactoryUpdateListener) {
|
||||
listeners += listener
|
||||
}
|
||||
|
||||
override val contacts: Contacts? get() = synchronized(contactsLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_contacts == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val contactsDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.CONTACTS.name, publicKey)
|
||||
_contacts = if (contactsDump != null) {
|
||||
Contacts.newInstance(secretKey, contactsDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateContactConfigDump()?.let { dump ->
|
||||
Contacts.newInstance(secretKey, dump)
|
||||
} ?: Contacts.newInstance(secretKey)
|
||||
}
|
||||
}
|
||||
_contacts
|
||||
fun unregisterListener(listener: ConfigFactoryUpdateListener) {
|
||||
listeners -= listener
|
||||
}
|
||||
|
||||
override val convoVolatile: ConversationVolatileConfig? get() = synchronized(convoVolatileLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_convoVolatileConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val convoDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name, publicKey)
|
||||
_convoVolatileConfig = if (convoDump != null) {
|
||||
ConversationVolatileConfig.newInstance(secretKey, convoDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateConversationVolatileDump(context)?.let { dump ->
|
||||
ConversationVolatileConfig.newInstance(secretKey, dump)
|
||||
} ?: ConversationVolatileConfig.newInstance(secretKey)
|
||||
override val user: UserProfile?
|
||||
get() = synchronized(userLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_userConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val userDump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.USER_PROFILE.name,
|
||||
publicKey
|
||||
)
|
||||
_userConfig = if (userDump != null) {
|
||||
UserProfile.newInstance(secretKey, userDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateUserProfileConfigDump()?.let { dump ->
|
||||
UserProfile.newInstance(secretKey, dump)
|
||||
} ?: UserProfile.newInstance(secretKey)
|
||||
}
|
||||
}
|
||||
_userConfig
|
||||
}
|
||||
_convoVolatileConfig
|
||||
}
|
||||
|
||||
override val userGroups: UserGroupsConfig? get() = synchronized(userGroupsLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_userGroups == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val userGroupsDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.GROUPS.name, publicKey)
|
||||
_userGroups = if (userGroupsDump != null) {
|
||||
UserGroupsConfig.Companion.newInstance(secretKey, userGroupsDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateUserGroupDump(context)?.let { dump ->
|
||||
UserGroupsConfig.Companion.newInstance(secretKey, dump)
|
||||
} ?: UserGroupsConfig.newInstance(secretKey)
|
||||
override val contacts: Contacts?
|
||||
get() = synchronized(contactsLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_contacts == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val contactsDump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.CONTACTS.name,
|
||||
publicKey
|
||||
)
|
||||
_contacts = if (contactsDump != null) {
|
||||
Contacts.newInstance(secretKey, contactsDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateContactConfigDump()?.let { dump ->
|
||||
Contacts.newInstance(secretKey, dump)
|
||||
} ?: Contacts.newInstance(secretKey)
|
||||
}
|
||||
}
|
||||
_contacts
|
||||
}
|
||||
_userGroups
|
||||
}
|
||||
|
||||
override fun getUserConfigs(): List<ConfigBase> = listOfNotNull(user, contacts, convoVolatile, userGroups)
|
||||
override val convoVolatile: ConversationVolatileConfig?
|
||||
get() = synchronized(convoVolatileLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_convoVolatileConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val convoDump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name,
|
||||
publicKey
|
||||
)
|
||||
_convoVolatileConfig = if (convoDump != null) {
|
||||
ConversationVolatileConfig.newInstance(secretKey, convoDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateConversationVolatileDump(context)
|
||||
?.let { dump ->
|
||||
ConversationVolatileConfig.newInstance(secretKey, dump)
|
||||
} ?: ConversationVolatileConfig.newInstance(secretKey)
|
||||
}
|
||||
}
|
||||
_convoVolatileConfig
|
||||
}
|
||||
|
||||
override val userGroups: UserGroupsConfig?
|
||||
get() = synchronized(userGroupsLock) {
|
||||
if (!ConfigBase.isNewConfigEnabled) return null
|
||||
if (_userGroups == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
val userGroupsDump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.GROUPS.name,
|
||||
publicKey
|
||||
)
|
||||
_userGroups = if (userGroupsDump != null) {
|
||||
UserGroupsConfig.Companion.newInstance(secretKey, userGroupsDump)
|
||||
} else {
|
||||
ConfigurationMessageUtilities.generateUserGroupDump(context)?.let { dump ->
|
||||
UserGroupsConfig.Companion.newInstance(secretKey, dump)
|
||||
} ?: UserGroupsConfig.newInstance(secretKey)
|
||||
}
|
||||
}
|
||||
_userGroups
|
||||
}
|
||||
|
||||
override fun getUserConfigs(): List<ConfigBase> =
|
||||
listOfNotNull(user, contacts, convoVolatile, userGroups)
|
||||
|
||||
|
||||
private fun persistUserConfigDump() = synchronized(userLock) {
|
||||
@ -121,10 +145,14 @@ class ConfigFactory(private val context: Context,
|
||||
configDatabase.storeConfig(SharedConfigMessage.Kind.CONTACTS.name, publicKey, dumped)
|
||||
}
|
||||
|
||||
private fun persistConvoVolatileConfigDump() = synchronized (convoVolatileLock) {
|
||||
private fun persistConvoVolatileConfigDump() = synchronized(convoVolatileLock) {
|
||||
val dumped = convoVolatile?.dump() ?: return
|
||||
val (_, publicKey) = maybeGetUserInfo() ?: return
|
||||
configDatabase.storeConfig(SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name, publicKey, dumped)
|
||||
configDatabase.storeConfig(
|
||||
SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name,
|
||||
publicKey,
|
||||
dumped
|
||||
)
|
||||
}
|
||||
|
||||
private fun persistUserGroupsConfigDump() = synchronized(userGroupsLock) {
|
||||
@ -134,22 +162,19 @@ class ConfigFactory(private val context: Context,
|
||||
}
|
||||
|
||||
override fun persist(forConfigObject: ConfigBase) {
|
||||
factoryExecutor.submit {
|
||||
try {
|
||||
listeners.forEach { listener ->
|
||||
listener.notifyUpdates(forConfigObject)
|
||||
}
|
||||
when (forConfigObject) {
|
||||
is UserProfile -> persistUserConfigDump()
|
||||
is Contacts -> persistContactsConfigDump()
|
||||
is ConversationVolatileConfig -> persistConvoVolatileConfigDump()
|
||||
is UserGroupsConfig -> persistUserGroupsConfigDump()
|
||||
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
|
||||
}
|
||||
} catch (e: Exception){
|
||||
Log.e("Loki-DBG", e)
|
||||
try {
|
||||
listeners.forEach { listener ->
|
||||
listener.notifyUpdates(forConfigObject)
|
||||
}
|
||||
when (forConfigObject) {
|
||||
is UserProfile -> persistUserConfigDump()
|
||||
is Contacts -> persistContactsConfigDump()
|
||||
is ConversationVolatileConfig -> persistConvoVolatileConfigDump()
|
||||
is UserGroupsConfig -> persistUserGroupsConfigDump()
|
||||
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("Loki-DBG", e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user