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.assertj:assertj-core:3.11.1'
|
||||||
testImplementation "org.mockito:mockito-inline:4.10.0"
|
testImplementation "org.mockito:mockito-inline:4.10.0"
|
||||||
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
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:mockito-android:4.10.0"
|
||||||
androidTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
androidTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
|
||||||
testImplementation "androidx.test:core:$testCoreVersion"
|
testImplementation "androidx.test:core:$testCoreVersion"
|
||||||
@ -226,7 +222,7 @@ android {
|
|||||||
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
|
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
|
||||||
|
|
||||||
resConfigs autoResConfig()
|
resConfigs autoResConfig()
|
||||||
testInstrumentationRunner "network.loki.messenger.util.HiltApplicationRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
// The following argument makes the Android Test Orchestrator run its
|
// The following argument makes the Android Test Orchestrator run its
|
||||||
// "pm clear" command after each test invocation. This command ensures
|
// "pm clear" command after each test invocation. This command ensures
|
||||||
// that the app's state is completely cleared between tests.
|
// 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.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
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.ConfigBase
|
||||||
import network.loki.messenger.libsession_util.Contacts
|
import network.loki.messenger.libsession_util.Contacts
|
||||||
import network.loki.messenger.libsession_util.util.Contact
|
import network.loki.messenger.libsession_util.util.Contact
|
||||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
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.spy
|
||||||
import org.mockito.kotlin.verify
|
import org.mockito.kotlin.verify
|
||||||
import org.mockito.kotlin.whenever
|
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.utilities.KeyHelper
|
import org.session.libsignal.utilities.KeyHelper
|
||||||
@ -26,17 +22,10 @@ import org.thoughtcrime.securesms.ApplicationContext
|
|||||||
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@CustomTestApplication(ApplicationContext::class)
|
|
||||||
interface HiltApplicationContext
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@HiltAndroidTest
|
|
||||||
class LibSessionTests {
|
class LibSessionTests {
|
||||||
|
|
||||||
@get:Rule
|
|
||||||
val hiltRule = HiltAndroidRule(this)
|
|
||||||
|
|
||||||
private fun randomSeedBytes() = (0 until 16).map { Random.nextInt(UByte.MAX_VALUE.toInt()).toByte() }
|
private fun randomSeedBytes() = (0 until 16).map { Random.nextInt(UByte.MAX_VALUE.toInt()).toByte() }
|
||||||
private fun randomKeyPair() = KeyPairUtilities.generate(randomSeedBytes().toByteArray())
|
private fun randomKeyPair() = KeyPairUtilities.generate(randomSeedBytes().toByteArray())
|
||||||
private fun randomSessionId() = randomKeyPair().x25519KeyPair.hexEncodedPublicKey
|
private fun randomSessionId() = randomKeyPair().x25519KeyPair.hexEncodedPublicKey
|
||||||
@ -86,8 +75,9 @@ class LibSessionTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun migration_one_to_ones() {
|
fun migration_one_to_ones() {
|
||||||
val storageSpy = spy(MessagingModuleConfiguration.shared.storage)
|
val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||||
whenever(MessagingModuleConfiguration.shared.storage).thenReturn(storageSpy)
|
val storageSpy = spy(app.storage)
|
||||||
|
app.storage = storageSpy
|
||||||
|
|
||||||
val newContactId = randomSessionId()
|
val newContactId = randomSessionId()
|
||||||
val singleContact = Contact(
|
val singleContact = Contact(
|
||||||
@ -98,7 +88,10 @@ class LibSessionTests {
|
|||||||
val newContactMerge = buildContactMessage(listOf(singleContact))
|
val newContactMerge = buildContactMessage(listOf(singleContact))
|
||||||
val contacts = MessagingModuleConfiguration.shared.configFactory.contacts!!
|
val contacts = MessagingModuleConfiguration.shared.configFactory.contacts!!
|
||||||
fakePollNewConfig(contacts, newContactMerge)
|
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
|
* @author Moxie Marlinspike
|
||||||
*/
|
*/
|
||||||
@HiltAndroidApp
|
@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";
|
public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ public class ApplicationContext extends BaseApplication implements DefaultLifecy
|
|||||||
private PersistentLogger persistentLogger;
|
private PersistentLogger persistentLogger;
|
||||||
|
|
||||||
@Inject LokiAPIDatabase lokiAPIDatabase;
|
@Inject LokiAPIDatabase lokiAPIDatabase;
|
||||||
@Inject Storage storage;
|
@Inject public Storage storage;
|
||||||
@Inject MessageDataProvider messageDataProvider;
|
@Inject MessageDataProvider messageDataProvider;
|
||||||
@Inject JobDatabase jobDatabase;
|
@Inject JobDatabase jobDatabase;
|
||||||
@Inject TextSecurePreferences textSecurePreferences;
|
@Inject TextSecurePreferences textSecurePreferences;
|
||||||
@ -209,6 +209,7 @@ public class ApplicationContext extends BaseApplication implements DefaultLifecy
|
|||||||
}
|
}
|
||||||
storage.notifyConfigUpdates(forConfigObject);
|
storage.notifyConfigUpdates(forConfigObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
DatabaseModule.init(this);
|
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 org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
class ConfigFactory(private val context: Context,
|
class ConfigFactory(
|
||||||
|
private val context: Context,
|
||||||
private val configDatabase: ConfigDatabase,
|
private val configDatabase: ConfigDatabase,
|
||||||
private val maybeGetUserInfo: ()->Pair<ByteArray, String>?):
|
private val maybeGetUserInfo: () -> Pair<ByteArray, String>?
|
||||||
|
) :
|
||||||
ConfigFactoryProtocol {
|
ConfigFactoryProtocol {
|
||||||
|
|
||||||
fun keyPairChanged() { // this should only happen restoring or clearing data
|
fun keyPairChanged() { // this should only happen restoring or clearing data
|
||||||
@ -36,17 +38,25 @@ class ConfigFactory(private val context: Context,
|
|||||||
private var _convoVolatileConfig: ConversationVolatileConfig? = null
|
private var _convoVolatileConfig: ConversationVolatileConfig? = null
|
||||||
private val userGroupsLock = Object()
|
private val userGroupsLock = Object()
|
||||||
private var _userGroups: UserGroupsConfig? = null
|
private var _userGroups: UserGroupsConfig? = null
|
||||||
private val factoryExecutor = Executors.newSingleThreadExecutor()
|
|
||||||
|
|
||||||
private val listeners: MutableList<ConfigFactoryUpdateListener> = mutableListOf()
|
private val listeners: MutableList<ConfigFactoryUpdateListener> = mutableListOf()
|
||||||
fun registerListener(listener: ConfigFactoryUpdateListener) { listeners += listener }
|
fun registerListener(listener: ConfigFactoryUpdateListener) {
|
||||||
fun unregisterListener(listener: ConfigFactoryUpdateListener) { listeners -= listener }
|
listeners += listener
|
||||||
|
}
|
||||||
|
|
||||||
override val user: UserProfile? get() = synchronized(userLock) {
|
fun unregisterListener(listener: ConfigFactoryUpdateListener) {
|
||||||
|
listeners -= listener
|
||||||
|
}
|
||||||
|
|
||||||
|
override val user: UserProfile?
|
||||||
|
get() = synchronized(userLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled) return null
|
if (!ConfigBase.isNewConfigEnabled) return null
|
||||||
if (_userConfig == null) {
|
if (_userConfig == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||||
val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey)
|
val userDump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.USER_PROFILE.name,
|
||||||
|
publicKey
|
||||||
|
)
|
||||||
_userConfig = if (userDump != null) {
|
_userConfig = if (userDump != null) {
|
||||||
UserProfile.newInstance(secretKey, userDump)
|
UserProfile.newInstance(secretKey, userDump)
|
||||||
} else {
|
} else {
|
||||||
@ -58,11 +68,15 @@ class ConfigFactory(private val context: Context,
|
|||||||
_userConfig
|
_userConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
override val contacts: Contacts? get() = synchronized(contactsLock) {
|
override val contacts: Contacts?
|
||||||
|
get() = synchronized(contactsLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled) return null
|
if (!ConfigBase.isNewConfigEnabled) return null
|
||||||
if (_contacts == null) {
|
if (_contacts == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||||
val contactsDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.CONTACTS.name, publicKey)
|
val contactsDump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.CONTACTS.name,
|
||||||
|
publicKey
|
||||||
|
)
|
||||||
_contacts = if (contactsDump != null) {
|
_contacts = if (contactsDump != null) {
|
||||||
Contacts.newInstance(secretKey, contactsDump)
|
Contacts.newInstance(secretKey, contactsDump)
|
||||||
} else {
|
} else {
|
||||||
@ -74,15 +88,20 @@ class ConfigFactory(private val context: Context,
|
|||||||
_contacts
|
_contacts
|
||||||
}
|
}
|
||||||
|
|
||||||
override val convoVolatile: ConversationVolatileConfig? get() = synchronized(convoVolatileLock) {
|
override val convoVolatile: ConversationVolatileConfig?
|
||||||
|
get() = synchronized(convoVolatileLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled) return null
|
if (!ConfigBase.isNewConfigEnabled) return null
|
||||||
if (_convoVolatileConfig == null) {
|
if (_convoVolatileConfig == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||||
val convoDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name, publicKey)
|
val convoDump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name,
|
||||||
|
publicKey
|
||||||
|
)
|
||||||
_convoVolatileConfig = if (convoDump != null) {
|
_convoVolatileConfig = if (convoDump != null) {
|
||||||
ConversationVolatileConfig.newInstance(secretKey, convoDump)
|
ConversationVolatileConfig.newInstance(secretKey, convoDump)
|
||||||
} else {
|
} else {
|
||||||
ConfigurationMessageUtilities.generateConversationVolatileDump(context)?.let { dump ->
|
ConfigurationMessageUtilities.generateConversationVolatileDump(context)
|
||||||
|
?.let { dump ->
|
||||||
ConversationVolatileConfig.newInstance(secretKey, dump)
|
ConversationVolatileConfig.newInstance(secretKey, dump)
|
||||||
} ?: ConversationVolatileConfig.newInstance(secretKey)
|
} ?: ConversationVolatileConfig.newInstance(secretKey)
|
||||||
}
|
}
|
||||||
@ -90,11 +109,15 @@ class ConfigFactory(private val context: Context,
|
|||||||
_convoVolatileConfig
|
_convoVolatileConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
override val userGroups: UserGroupsConfig? get() = synchronized(userGroupsLock) {
|
override val userGroups: UserGroupsConfig?
|
||||||
|
get() = synchronized(userGroupsLock) {
|
||||||
if (!ConfigBase.isNewConfigEnabled) return null
|
if (!ConfigBase.isNewConfigEnabled) return null
|
||||||
if (_userGroups == null) {
|
if (_userGroups == null) {
|
||||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||||
val userGroupsDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.GROUPS.name, publicKey)
|
val userGroupsDump = configDatabase.retrieveConfigAndHashes(
|
||||||
|
SharedConfigMessage.Kind.GROUPS.name,
|
||||||
|
publicKey
|
||||||
|
)
|
||||||
_userGroups = if (userGroupsDump != null) {
|
_userGroups = if (userGroupsDump != null) {
|
||||||
UserGroupsConfig.Companion.newInstance(secretKey, userGroupsDump)
|
UserGroupsConfig.Companion.newInstance(secretKey, userGroupsDump)
|
||||||
} else {
|
} else {
|
||||||
@ -106,7 +129,8 @@ class ConfigFactory(private val context: Context,
|
|||||||
_userGroups
|
_userGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUserConfigs(): List<ConfigBase> = listOfNotNull(user, contacts, convoVolatile, userGroups)
|
override fun getUserConfigs(): List<ConfigBase> =
|
||||||
|
listOfNotNull(user, contacts, convoVolatile, userGroups)
|
||||||
|
|
||||||
|
|
||||||
private fun persistUserConfigDump() = synchronized(userLock) {
|
private fun persistUserConfigDump() = synchronized(userLock) {
|
||||||
@ -121,10 +145,14 @@ class ConfigFactory(private val context: Context,
|
|||||||
configDatabase.storeConfig(SharedConfigMessage.Kind.CONTACTS.name, publicKey, dumped)
|
configDatabase.storeConfig(SharedConfigMessage.Kind.CONTACTS.name, publicKey, dumped)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun persistConvoVolatileConfigDump() = synchronized (convoVolatileLock) {
|
private fun persistConvoVolatileConfigDump() = synchronized(convoVolatileLock) {
|
||||||
val dumped = convoVolatile?.dump() ?: return
|
val dumped = convoVolatile?.dump() ?: return
|
||||||
val (_, publicKey) = maybeGetUserInfo() ?: 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) {
|
private fun persistUserGroupsConfigDump() = synchronized(userGroupsLock) {
|
||||||
@ -134,7 +162,6 @@ class ConfigFactory(private val context: Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun persist(forConfigObject: ConfigBase) {
|
override fun persist(forConfigObject: ConfigBase) {
|
||||||
factoryExecutor.submit {
|
|
||||||
try {
|
try {
|
||||||
listeners.forEach { listener ->
|
listeners.forEach { listener ->
|
||||||
listener.notifyUpdates(forConfigObject)
|
listener.notifyUpdates(forConfigObject)
|
||||||
@ -146,10 +173,8 @@ class ConfigFactory(private val context: Context,
|
|||||||
is UserGroupsConfig -> persistUserGroupsConfigDump()
|
is UserGroupsConfig -> persistUserGroupsConfigDump()
|
||||||
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
|
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
|
||||||
}
|
}
|
||||||
} catch (e: Exception){
|
} catch (e: Exception) {
|
||||||
Log.e("Loki-DBG", e)
|
Log.e("Loki-DBG", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user