mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 20:18:36 +00:00
Fix avatar loading in OS views when app is not running.
This commit is contained in:
committed by
mtang-signal
parent
8a4d9fc635
commit
71b5a9f865
@@ -153,6 +153,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
|
||||
DatabaseSecretProvider.getOrCreateDatabaseSecret(this),
|
||||
AttachmentSecretProvider.getInstance(this).getOrCreateAttachmentSecret());
|
||||
})
|
||||
.addBlocking("signal-store", () -> SignalStore.init(this))
|
||||
.addBlocking("logging", () -> {
|
||||
initializeLogging();
|
||||
Log.i(TAG, "onCreate()");
|
||||
|
||||
@@ -188,7 +188,7 @@ object BackupRepository {
|
||||
}
|
||||
|
||||
val db = KeyValueDatabase.createWithName(context, "$baseName.db")
|
||||
SignalStore(KeyValueStore(db))
|
||||
SignalStore(context, KeyValueStore(db))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.emoji
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.thoughtcrime.securesms.components.emoji.Emoji
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel
|
||||
@@ -122,7 +123,8 @@ class EmojiSource(
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadAssetBasedEmojis(): EmojiSource {
|
||||
@VisibleForTesting
|
||||
fun loadAssetBasedEmojis(): EmojiSource {
|
||||
val emojiData: InputStream = AppDependencies.application.assets.open("emoji/emoji_data.json")
|
||||
|
||||
emojiData.use {
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.preference.PreferenceManager
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.libsignal.protocol.IdentityKey
|
||||
@@ -73,17 +72,10 @@ class AccountValues internal constructor(store: KeyValueStore) : SignalStoreValu
|
||||
private const val KEY_USERNAME_SYNC_STATE = "phoneNumberPrivacy.usernameSyncState"
|
||||
private const val KEY_USERNAME_SYNC_ERROR_COUNT = "phoneNumberPrivacy.usernameErrorCount"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_E164 = "account.e164"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_ACI = "account.aci"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_PNI = "account.pni"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_IS_REGISTERED = "account.is_registered"
|
||||
private const val KEY_E164 = "account.e164"
|
||||
private const val KEY_ACI = "account.aci"
|
||||
private const val KEY_PNI = "account.pni"
|
||||
private const val KEY_IS_REGISTERED = "account.is_registered"
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
|
||||
/**
|
||||
* Values for managing enable/disable state and corresponding alerts for Notification Profiles.
|
||||
*/
|
||||
@@ -12,14 +10,9 @@ class NotificationProfileValues(store: KeyValueStore) : SignalStoreValues(store)
|
||||
private const val KEY_LAST_PROFILE_POPUP_TIME = "np.last_profile_popup_time"
|
||||
private const val KEY_SEEN_TOOLTIP = "np.seen_tooltip"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_MANUALLY_ENABLED_PROFILE = "np.manually_enabled_profile"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_MANUALLY_ENABLED_UNTIL = "np.manually_enabled_until"
|
||||
|
||||
@VisibleForTesting
|
||||
const val KEY_MANUALLY_DISABLED_AT = "np.manually_disabled_at"
|
||||
private const val KEY_MANUALLY_ENABLED_PROFILE = "np.manually_enabled_profile"
|
||||
private const val KEY_MANUALLY_ENABLED_UNTIL = "np.manually_enabled_until"
|
||||
private const val KEY_MANUALLY_DISABLED_AT = "np.manually_disabled_at"
|
||||
}
|
||||
|
||||
public override fun onFirstEverAppLaunch() = Unit
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
@@ -33,6 +32,7 @@ class PaymentsValues internal constructor(store: KeyValueStore) : SignalStoreVal
|
||||
companion object {
|
||||
private val TAG = Log.tag(PaymentsValues::class.java)
|
||||
|
||||
private const val MOB_PAYMENTS_ENABLED = "mob_payments_enabled"
|
||||
private const val PAYMENTS_ENTROPY = "payments_entropy"
|
||||
private const val MOB_LEDGER = "mob_ledger"
|
||||
private const val PAYMENTS_CURRENT_CURRENCY = "payments_current_currency"
|
||||
@@ -50,9 +50,6 @@ class PaymentsValues internal constructor(store: KeyValueStore) : SignalStoreVal
|
||||
private const val SHOW_SAVE_RECOVERY_PHRASE = "mob_show_save_recovery_phrase"
|
||||
|
||||
private val LARGE_BALANCE_THRESHOLD = Money.mobileCoin(BigDecimal.valueOf(500))
|
||||
|
||||
@VisibleForTesting
|
||||
const val MOB_PAYMENTS_ENABLED = "mob_payments_enabled"
|
||||
}
|
||||
|
||||
@get:JvmName("isPaymentLockEnabled")
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import android.app.Application
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import org.signal.core.util.ResettableLazy
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies.application
|
||||
|
||||
/**
|
||||
* Simple, encrypted key-value store.
|
||||
*/
|
||||
class SignalStore(private val store: KeyValueStore) {
|
||||
class SignalStore(context: Application, private val store: KeyValueStore) {
|
||||
|
||||
val accountValues = AccountValues(store)
|
||||
val svrValues = SvrValues(store)
|
||||
@@ -39,15 +38,22 @@ class SignalStore(private val store: KeyValueStore) {
|
||||
val apkUpdateValues = ApkUpdateValues(store)
|
||||
val backupValues = BackupValues(store)
|
||||
|
||||
val plainTextValues = PlainTextSharedPrefsDataStore(application)
|
||||
val plainTextValues = PlainTextSharedPrefsDataStore(context)
|
||||
|
||||
companion object {
|
||||
|
||||
private var instanceOverride: SignalStore? = null
|
||||
private val _instance = ResettableLazy {
|
||||
instanceOverride ?: SignalStore(KeyValueStore(KeyValueDatabase.getInstance(application)))
|
||||
private var instance: SignalStore? = null
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Application) {
|
||||
if (instance == null) {
|
||||
synchronized(SignalStore::class.java) {
|
||||
if (instance == null) {
|
||||
instance = SignalStore(context, KeyValueStore(KeyValueDatabase.getInstance(context)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private val instance by _instance
|
||||
|
||||
@JvmStatic
|
||||
fun onFirstEverAppLaunch() {
|
||||
@@ -114,7 +120,7 @@ class SignalStore(private val store: KeyValueStore) {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
fun resetCache() {
|
||||
instance.store.resetCache()
|
||||
instance!!.store.resetCache()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,144 +128,144 @@ class SignalStore(private val store: KeyValueStore) {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun onPostBackupRestore() {
|
||||
instance.store.resetCache()
|
||||
instance!!.store.resetCache()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("account")
|
||||
val account: AccountValues
|
||||
get() = instance.accountValues
|
||||
get() = instance!!.accountValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("svr")
|
||||
val svr: SvrValues
|
||||
get() = instance.svrValues
|
||||
get() = instance!!.svrValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("registration")
|
||||
val registration: RegistrationValues
|
||||
get() = instance.registrationValues
|
||||
get() = instance!!.registrationValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("pin")
|
||||
val pin: PinValues
|
||||
get() = instance.pinValues
|
||||
get() = instance!!.pinValues
|
||||
|
||||
val remoteConfig: RemoteConfigValues
|
||||
get() = instance.remoteConfigValues
|
||||
get() = instance!!.remoteConfigValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("storageService")
|
||||
val storageService: StorageServiceValues
|
||||
get() = instance.storageServiceValues
|
||||
get() = instance!!.storageServiceValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("uiHints")
|
||||
val uiHints: UiHintValues
|
||||
get() = instance.uiHintValues
|
||||
get() = instance!!.uiHintValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("tooltips")
|
||||
val tooltips: TooltipValues
|
||||
get() = instance.tooltipValues
|
||||
get() = instance!!.tooltipValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("misc")
|
||||
val misc: MiscellaneousValues
|
||||
get() = instance.miscValues
|
||||
get() = instance!!.miscValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("internal")
|
||||
val internal: InternalValues
|
||||
get() = instance.internalValues
|
||||
get() = instance!!.internalValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("emoji")
|
||||
val emoji: EmojiValues
|
||||
get() = instance.emojiValues
|
||||
get() = instance!!.emojiValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("settings")
|
||||
val settings: SettingsValues
|
||||
get() = instance.settingsValues
|
||||
get() = instance!!.settingsValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("certificate")
|
||||
val certificate: CertificateValues
|
||||
get() = instance.certificateValues
|
||||
get() = instance!!.certificateValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("phoneNumberPrivacy")
|
||||
val phoneNumberPrivacy: PhoneNumberPrivacyValues
|
||||
get() = instance.phoneNumberPrivacyValues
|
||||
get() = instance!!.phoneNumberPrivacyValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("onboarding")
|
||||
val onboarding: OnboardingValues
|
||||
get() = instance.onboardingValues
|
||||
get() = instance!!.onboardingValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("wallpaper")
|
||||
val wallpaper: WallpaperValues
|
||||
get() = instance.wallpaperValues
|
||||
get() = instance!!.wallpaperValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("payments")
|
||||
val payments: PaymentsValues
|
||||
get() = instance.paymentsValues
|
||||
get() = instance!!.paymentsValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("inAppPayments")
|
||||
val inAppPayments: InAppPaymentValues
|
||||
get() = instance.inAppPaymentValues
|
||||
get() = instance!!.inAppPaymentValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("proxy")
|
||||
val proxy: ProxyValues
|
||||
get() = instance.proxyValues
|
||||
get() = instance!!.proxyValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("rateLimit")
|
||||
val rateLimit: RateLimitValues
|
||||
get() = instance.rateLimitValues
|
||||
get() = instance!!.rateLimitValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("chatColors")
|
||||
val chatColors: ChatColorsValues
|
||||
get() = instance.chatColorsValues
|
||||
get() = instance!!.chatColorsValues
|
||||
|
||||
val imageEditor: ImageEditorValues
|
||||
get() = instance.imageEditorValues
|
||||
get() = instance!!.imageEditorValues
|
||||
|
||||
val notificationProfile: NotificationProfileValues
|
||||
get() = instance.notificationProfileValues
|
||||
get() = instance!!.notificationProfileValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("releaseChannel")
|
||||
val releaseChannel: ReleaseChannelValues
|
||||
get() = instance.releaseChannelValues
|
||||
get() = instance!!.releaseChannelValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("story")
|
||||
val story: StoryValues
|
||||
get() = instance.storyValues
|
||||
get() = instance!!.storyValues
|
||||
|
||||
val apkUpdate: ApkUpdateValues
|
||||
get() = instance.apkUpdateValues
|
||||
get() = instance!!.apkUpdateValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("backup")
|
||||
val backup: BackupValues
|
||||
get() = instance.backupValues
|
||||
get() = instance!!.backupValues
|
||||
|
||||
val groupsV2AciAuthorizationCache: GroupsV2AuthorizationSignalStoreCache
|
||||
get() = GroupsV2AuthorizationSignalStoreCache.createAciCache(instance.store)
|
||||
get() = GroupsV2AuthorizationSignalStoreCache.createAciCache(instance!!.store)
|
||||
|
||||
val plaintext: PlainTextSharedPrefsDataStore
|
||||
get() = instance.plainTextValues
|
||||
get() = instance!!.plainTextValues
|
||||
|
||||
fun getPreferenceDataStore(): PreferenceDataStore {
|
||||
return SignalPreferenceDataStore(instance.store)
|
||||
return SignalPreferenceDataStore(instance!!.store)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,25 +274,7 @@ class SignalStore(private val store: KeyValueStore) {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun blockUntilAllWritesFinished() {
|
||||
instance.store.blockUntilAllWritesFinished()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows you to set a custom KeyValueStore to read from. Only for testing!
|
||||
*/
|
||||
@VisibleForTesting
|
||||
fun testInject(store: KeyValueStore) {
|
||||
instanceOverride = SignalStore(store)
|
||||
_instance.reset()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows you to set a custom SignalStore to read from. Only for testing!
|
||||
*/
|
||||
@VisibleForTesting
|
||||
fun testInject(store: SignalStore) {
|
||||
instanceOverride = store
|
||||
_instance.reset()
|
||||
instance!!.store.blockUntilAllWritesFinished()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.thoughtcrime.securesms.providers
|
||||
|
||||
import android.app.Application
|
||||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.Intent
|
||||
@@ -15,10 +16,16 @@ import android.net.Uri
|
||||
import android.os.ParcelFileDescriptor
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.BuildConfig
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.SqlCipherLibraryLoader
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientCreator
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService
|
||||
import org.thoughtcrime.securesms.util.AdaptiveBitmapMetrics
|
||||
@@ -54,6 +61,21 @@ class AvatarProvider : BaseContentProvider() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun init(): Application? {
|
||||
val application = context as? ApplicationContext ?: return null
|
||||
|
||||
SqlCipherLibraryLoader.load()
|
||||
SignalDatabase.init(
|
||||
application,
|
||||
DatabaseSecretProvider.getOrCreateDatabaseSecret(application),
|
||||
AttachmentSecretProvider.getInstance(application).getOrCreateAttachmentSecret()
|
||||
)
|
||||
|
||||
SignalStore.init(application)
|
||||
|
||||
return application
|
||||
}
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
if (VERBOSE) Log.i(TAG, "onCreate called")
|
||||
return true
|
||||
@@ -63,7 +85,9 @@ class AvatarProvider : BaseContentProvider() {
|
||||
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
|
||||
if (VERBOSE) Log.i(TAG, "openFile() called!")
|
||||
|
||||
if (KeyCachingService.isLocked(context)) {
|
||||
val application = init() ?: return null
|
||||
|
||||
if (KeyCachingService.isLocked(application)) {
|
||||
Log.w(TAG, "masterSecret was null, abandoning.")
|
||||
return null
|
||||
}
|
||||
@@ -76,7 +100,7 @@ class AvatarProvider : BaseContentProvider() {
|
||||
if (uriMatcher.match(uri) == AVATAR) {
|
||||
if (VERBOSE) Log.i(TAG, "Loading avatar.")
|
||||
try {
|
||||
val recipient = getRecipientId(uri)?.let { Recipient.resolved(it) } ?: return null
|
||||
val recipient = getRecipientId(uri)?.let { RecipientCreator.forRecord(application, SignalDatabase.recipients.getRecord(it)) } ?: return null
|
||||
return getParcelFileDescriptorForAvatar(recipient)
|
||||
} catch (ioe: IOException) {
|
||||
Log.w(TAG, ioe)
|
||||
@@ -91,6 +115,8 @@ class AvatarProvider : BaseContentProvider() {
|
||||
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {
|
||||
if (VERBOSE) Log.i(TAG, "query() called: $uri")
|
||||
|
||||
val application = init() ?: return null
|
||||
|
||||
if (SignalDatabase.instance == null) {
|
||||
Log.w(TAG, "SignalDatabase unavailable")
|
||||
return null
|
||||
@@ -99,8 +125,8 @@ class AvatarProvider : BaseContentProvider() {
|
||||
if (uriMatcher.match(uri) == AVATAR) {
|
||||
val recipientId = getRecipientId(uri) ?: return null
|
||||
|
||||
if (AvatarHelper.hasAvatar(context!!, recipientId)) {
|
||||
val file: File = AvatarHelper.getAvatarFile(context!!, recipientId)
|
||||
if (AvatarHelper.hasAvatar(application, recipientId)) {
|
||||
val file: File = AvatarHelper.getAvatarFile(application, recipientId)
|
||||
if (file.exists()) {
|
||||
return createCursor(projection, file.name, file.length())
|
||||
}
|
||||
@@ -115,6 +141,8 @@ class AvatarProvider : BaseContentProvider() {
|
||||
override fun getType(uri: Uri): String? {
|
||||
if (VERBOSE) Log.i(TAG, "getType() called: $uri")
|
||||
|
||||
init() ?: return null
|
||||
|
||||
if (SignalDatabase.instance == null) {
|
||||
Log.w(TAG, "SignalDatabase unavailable")
|
||||
return null
|
||||
|
||||
@@ -9,24 +9,15 @@ import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable;
|
||||
import org.thoughtcrime.securesms.database.DistributionListTables;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
import org.thoughtcrime.securesms.database.model.RecipientRecord;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -198,62 +189,11 @@ public final class LiveRecipient {
|
||||
}
|
||||
|
||||
private @NonNull Recipient fetchAndCacheRecipientFromDisk(@NonNull RecipientId id) {
|
||||
RecipientRecord record = recipientTable.getRecord(id);
|
||||
|
||||
Recipient recipient;
|
||||
if (record.getGroupId() != null) {
|
||||
recipient = getGroupRecipientDetails(record);
|
||||
} else if (record.getDistributionListId() != null) {
|
||||
recipient = getDistributionListRecipientDetails(record);
|
||||
} else if (record.getCallLinkRoomId() != null) {
|
||||
recipient = getCallLinkRecipientDetails(record);
|
||||
} else {
|
||||
recipient = RecipientCreator.forIndividual(context, record);
|
||||
}
|
||||
|
||||
Recipient recipient = RecipientCreator.forRecord(context, recipientTable.getRecord(id));
|
||||
RecipientIdCache.INSTANCE.put(recipient);
|
||||
return recipient;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull Recipient getGroupRecipientDetails(@NonNull RecipientRecord record) {
|
||||
Optional<GroupRecord> groupRecord = groupDatabase.getGroup(record.getId());
|
||||
|
||||
if (groupRecord.isPresent()) {
|
||||
return RecipientCreator.forGroup(groupRecord.get(), record);
|
||||
} else {
|
||||
return RecipientCreator.forUnknownGroup(record.getId(), record.getGroupId());
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull Recipient getDistributionListRecipientDetails(@NonNull RecipientRecord record) {
|
||||
DistributionListRecord groupRecord = distributionListTables.getList(Objects.requireNonNull(record.getDistributionListId()));
|
||||
|
||||
// TODO [stories] We'll have to see what the perf is like for very large distribution lists. We may not be able to support fetching all the members.
|
||||
if (groupRecord != null) {
|
||||
String title = groupRecord.isUnknown() ? null : groupRecord.getName();
|
||||
List<RecipientId> members = Stream.of(groupRecord.getMembers()).filterNot(RecipientId::isUnknown).toList();
|
||||
|
||||
return RecipientCreator.forDistributionList(title, members, record);
|
||||
}
|
||||
|
||||
return RecipientCreator.forDistributionList(null, null, record);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull Recipient getCallLinkRecipientDetails(@NonNull RecipientRecord record) {
|
||||
CallLinkTable.CallLink callLink = SignalDatabase.callLinks().getCallLinkByRoomId(Objects.requireNonNull(record.getCallLinkRoomId()));
|
||||
|
||||
if (callLink != null) {
|
||||
String name = callLink.getState().getName();
|
||||
|
||||
return RecipientCreator.forCallLink(name, record, callLink.getAvatarColor());
|
||||
}
|
||||
|
||||
return RecipientCreator.forCallLink(null, record, AvatarColor.UNKNOWN);
|
||||
}
|
||||
|
||||
synchronized void set(@NonNull Recipient recipient) {
|
||||
this.recipient.set(recipient);
|
||||
this.liveData.postValue(recipient);
|
||||
|
||||
@@ -2,8 +2,10 @@ package org.thoughtcrime.securesms.recipients
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.database.model.RecipientRecord
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
@@ -101,6 +103,22 @@ object RecipientCreator {
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@WorkerThread
|
||||
fun forRecord(context: Context, record: RecipientRecord): Recipient {
|
||||
val recipient = if (record.groupId != null) {
|
||||
getGroupRecipientDetails(record)
|
||||
} else if (record.distributionListId != null) {
|
||||
getDistributionListRecipientDetails(record)
|
||||
} else if (record.callLinkRoomId != null) {
|
||||
getCallLinkRecipientDetails(record)
|
||||
} else {
|
||||
forIndividual(context, record)
|
||||
}
|
||||
|
||||
return recipient
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun forUnknown(): Recipient {
|
||||
return Recipient.UNKNOWN
|
||||
@@ -186,4 +204,43 @@ object RecipientCreator {
|
||||
note = record.note
|
||||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getGroupRecipientDetails(record: RecipientRecord): Recipient {
|
||||
val groupRecord = SignalDatabase.groups.getGroup(record.id)
|
||||
|
||||
return if (groupRecord.isPresent) {
|
||||
forGroup(groupRecord.get(), record)
|
||||
} else {
|
||||
forUnknownGroup(record.id, record.groupId)
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getDistributionListRecipientDetails(record: RecipientRecord): Recipient {
|
||||
val groupRecord = SignalDatabase.distributionLists.getList(record.distributionListId!!)
|
||||
|
||||
// TODO [stories] We'll have to see what the perf is like for very large distribution lists. We may not be able to support fetching all the members.
|
||||
if (groupRecord != null) {
|
||||
val title = if (groupRecord.isUnknown) null else groupRecord.name
|
||||
val members = groupRecord.members.filterNot { it.isUnknown }
|
||||
|
||||
return forDistributionList(title, members, record)
|
||||
}
|
||||
|
||||
return forDistributionList(null, null, record)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getCallLinkRecipientDetails(record: RecipientRecord): Recipient {
|
||||
val callLink = SignalDatabase.callLinks.getCallLinkByRoomId(record.callLinkRoomId!!)
|
||||
|
||||
if (callLink != null) {
|
||||
val name = callLink.state.name
|
||||
|
||||
return forCallLink(name, record, callLink.avatarColor)
|
||||
}
|
||||
|
||||
return forCallLink(null, record, AvatarColor.UNKNOWN)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.thoughtcrime.securesms
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
|
||||
import org.thoughtcrime.securesms.keyvalue.MockKeyValuePersistentStorage
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
|
||||
/**
|
||||
* Rule to setup [SignalStore] with a mock [KeyValueDataSet]. Must be used with Roboelectric.
|
||||
*
|
||||
* Can provide [defaultValues] to set the same values before each test and use [dataSet] directly to add any
|
||||
* test specific values.
|
||||
*
|
||||
* The [dataSet] is reset at the beginning of each test to an empty state.
|
||||
*/
|
||||
class SignalStoreRule @JvmOverloads constructor(private val defaultValues: KeyValueDataSet.() -> Unit = {}) : TestRule {
|
||||
var dataSet = KeyValueDataSet()
|
||||
private set
|
||||
|
||||
override fun apply(base: Statement, description: Description): Statement {
|
||||
return object : Statement() {
|
||||
@Throws(Throwable::class)
|
||||
override fun evaluate() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
dataSet = KeyValueDataSet()
|
||||
SignalStore.testInject(KeyValueStore(MockKeyValuePersistentStorage.withDataSet(dataSet)))
|
||||
defaultValues.invoke(dataSet)
|
||||
|
||||
base.evaluate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,50 +2,34 @@ package org.thoughtcrime.securesms.components.emoji
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockedStatic
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource.Companion.refresh
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
|
||||
import org.thoughtcrime.securesms.keyvalue.MockKeyValuePersistentStorage
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource
|
||||
|
||||
@RunWith(ParameterizedRobolectricTestRunner::class)
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
class EmojiUtilTest_isEmoji(private val input: String?, private val output: Boolean) {
|
||||
@Rule
|
||||
@JvmField
|
||||
val rule: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
private val applicationDependenciesMockedStatic: MockedStatic<AppDependencies>? = null
|
||||
|
||||
@Mock
|
||||
private val attachmentSecretProviderMockedStatic: MockedStatic<AttachmentSecretProvider>? = null
|
||||
|
||||
@Throws(Exception::class)
|
||||
@Test
|
||||
fun isEmoji() {
|
||||
val application = ApplicationProvider.getApplicationContext<Application>()
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
Mockito.`when`(AppDependencies.application).thenReturn(application)
|
||||
Mockito.`when`(AttachmentSecretProvider.getInstance(ArgumentMatchers.any())).thenThrow(RuntimeException::class.java)
|
||||
SignalStore.testInject(KeyValueStore(MockKeyValuePersistentStorage.withDataSet(KeyValueDataSet())))
|
||||
refresh()
|
||||
val source = EmojiSource.loadAssetBasedEmojis()
|
||||
|
||||
Assert.assertEquals(output, EmojiUtil.isEmoji(input))
|
||||
mockkObject(EmojiSource) {
|
||||
every { EmojiSource.latest } returns source
|
||||
Assert.assertEquals(output, EmojiUtil.isEmoji(input))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -4,6 +4,8 @@ import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkAll
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -12,12 +14,9 @@ import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.assertIs
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.keyvalue.AccountValues
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
|
||||
import org.thoughtcrime.securesms.keyvalue.MockKeyValuePersistentStorage
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import java.util.UUID
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@@ -32,15 +31,13 @@ class CrashConfigTest {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
val store = KeyValueStore(
|
||||
MockKeyValuePersistentStorage.withDataSet(
|
||||
KeyValueDataSet().apply {
|
||||
putString(AccountValues.KEY_ACI, UUID.randomUUID().toString())
|
||||
}
|
||||
)
|
||||
)
|
||||
mockkObject(SignalStore)
|
||||
every { SignalStore.account.aci } returns ServiceId.ACI.from(UUID.randomUUID())
|
||||
}
|
||||
|
||||
SignalStore.testInject(store)
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -6,13 +6,15 @@ import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.slot
|
||||
import io.mockk.unmockkAll
|
||||
import io.mockk.verify
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers
|
||||
import org.hamcrest.Matchers.`is`
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
@@ -28,15 +30,18 @@ import org.signal.storageservice.protos.groups.GroupChangeResponse
|
||||
import org.signal.storageservice.protos.groups.Member
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember
|
||||
import org.thoughtcrime.securesms.SignalStoreRule
|
||||
import org.thoughtcrime.securesms.TestZkGroupServer
|
||||
import org.thoughtcrime.securesms.database.GroupStateTestData
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.member
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupCandidateHelper
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.testutil.SystemOutLogger
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
|
||||
@@ -73,12 +78,17 @@ class GroupManagerV2Test_edit {
|
||||
|
||||
private lateinit var manager: GroupManagerV2
|
||||
|
||||
@get:Rule
|
||||
val signalStore: SignalStoreRule = SignalStoreRule()
|
||||
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
@Before
|
||||
fun setUp() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
mockkObject(RemoteConfig)
|
||||
mockkObject(SignalStore)
|
||||
every { RemoteConfig.internalUser } returns false
|
||||
|
||||
ThreadUtil.enforceAssertions = false
|
||||
Log.initialize(SystemOutLogger())
|
||||
SignalProtocolLoggerProvider.setProvider(CustomSignalProtocolLogger())
|
||||
@@ -106,6 +116,11 @@ class GroupManagerV2Test_edit {
|
||||
)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
private fun given(init: GroupStateTestData.() -> Unit) {
|
||||
val data = GroupStateTestData(masterKey, groupOperations)
|
||||
data.init()
|
||||
|
||||
@@ -2,13 +2,14 @@ package org.thoughtcrime.securesms.groups.v2.processing
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.spyk
|
||||
import io.mockk.unmockkObject
|
||||
import io.mockk.unmockkAll
|
||||
import io.mockk.unmockkStatic
|
||||
import io.mockk.verify
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
@@ -16,7 +17,6 @@ import org.hamcrest.Matchers.hasItem
|
||||
import org.hamcrest.Matchers.`is`
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
@@ -32,7 +32,6 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroupChange
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedString
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedTimer
|
||||
import org.thoughtcrime.securesms.SignalStoreRule
|
||||
import org.thoughtcrime.securesms.database.GroupStateTestData
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
@@ -46,6 +45,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.requestingMember
|
||||
import org.thoughtcrime.securesms.database.setNewDescription
|
||||
import org.thoughtcrime.securesms.database.setNewTitle
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.GroupNotAMemberException
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2Authorization
|
||||
@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor.Pr
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager
|
||||
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob
|
||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.testutil.SystemOutLogger
|
||||
@@ -100,11 +101,15 @@ class GroupsV2StateProcessorTest {
|
||||
|
||||
private lateinit var processor: GroupsV2StateProcessor
|
||||
|
||||
@get:Rule
|
||||
val signalStore: SignalStoreRule = SignalStoreRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
mockkObject(SignalStore)
|
||||
every { SignalStore.internal.gv2IgnoreP2PChanges() } returns false
|
||||
|
||||
Log.initialize(SystemOutLogger())
|
||||
SignalProtocolLoggerProvider.setProvider(CustomSignalProtocolLogger())
|
||||
|
||||
@@ -138,11 +143,7 @@ class GroupsV2StateProcessorTest {
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkStatic(AppDependencies::class)
|
||||
unmockkObject(SignalDatabase)
|
||||
unmockkObject(ProfileAndMessageHelper)
|
||||
unmockkStatic(DecryptedGroupUtil::class)
|
||||
unmockkStatic(Recipient::class)
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
private fun given(init: GroupStateTestData.() -> Unit) {
|
||||
|
||||
@@ -3,7 +3,10 @@ package org.thoughtcrime.securesms.keyvalue
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkAll
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -18,6 +21,8 @@ import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
class PaymentsValuesTest {
|
||||
|
||||
private lateinit var paymentValues: PaymentsValues
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
@@ -25,29 +30,32 @@ class PaymentsValuesTest {
|
||||
}
|
||||
|
||||
mockkObject(RemoteConfig)
|
||||
mockkObject(SignalStore)
|
||||
|
||||
paymentValues = mockk()
|
||||
every { paymentValues.paymentsAvailability } answers { callOriginal() }
|
||||
|
||||
every { SignalStore.payments } returns paymentValues
|
||||
|
||||
every { SignalStore.account.isRegistered } returns true
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when unregistered, expect NOT_IN_REGION`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, false)
|
||||
}
|
||||
)
|
||||
every { SignalStore.account.isRegistered } returns false
|
||||
|
||||
assertEquals(PaymentsAvailability.NOT_IN_REGION, SignalStore.payments.paymentsAvailability)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when flag disabled and no account, expect DISABLED_REMOTELY`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, true)
|
||||
putString(AccountValues.KEY_E164, "+15551234567")
|
||||
putBoolean(PaymentsValues.MOB_PAYMENTS_ENABLED, false)
|
||||
}
|
||||
)
|
||||
|
||||
every { SignalStore.account.e164 } returns "+15551234567"
|
||||
every { paymentValues.mobileCoinPaymentsEnabled() } returns false
|
||||
every { RemoteConfig.payments } returns false
|
||||
every { RemoteConfig.paymentsCountryBlocklist } returns ""
|
||||
|
||||
@@ -56,14 +64,8 @@ class PaymentsValuesTest {
|
||||
|
||||
@Test
|
||||
fun `when flag disabled but has account, expect WITHDRAW_ONLY`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, true)
|
||||
putString(AccountValues.KEY_E164, "+15551234567")
|
||||
putBoolean(PaymentsValues.MOB_PAYMENTS_ENABLED, true)
|
||||
}
|
||||
)
|
||||
|
||||
every { SignalStore.account.e164 } returns "+15551234567"
|
||||
every { paymentValues.mobileCoinPaymentsEnabled() } returns true
|
||||
every { RemoteConfig.payments } returns false
|
||||
every { RemoteConfig.paymentsCountryBlocklist } returns ""
|
||||
|
||||
@@ -72,14 +74,8 @@ class PaymentsValuesTest {
|
||||
|
||||
@Test
|
||||
fun `when flag enabled and no account, expect REGISTRATION_AVAILABLE`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, true)
|
||||
putString(AccountValues.KEY_E164, "+15551234567")
|
||||
putBoolean(PaymentsValues.MOB_PAYMENTS_ENABLED, false)
|
||||
}
|
||||
)
|
||||
|
||||
every { SignalStore.account.e164 } returns "+15551234567"
|
||||
every { paymentValues.mobileCoinPaymentsEnabled() } returns false
|
||||
every { RemoteConfig.payments } returns true
|
||||
every { RemoteConfig.paymentsCountryBlocklist } returns ""
|
||||
|
||||
@@ -88,14 +84,8 @@ class PaymentsValuesTest {
|
||||
|
||||
@Test
|
||||
fun `when flag enabled and has account, expect WITHDRAW_AND_SEND`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, true)
|
||||
putString(AccountValues.KEY_E164, "+15551234567")
|
||||
putBoolean(PaymentsValues.MOB_PAYMENTS_ENABLED, true)
|
||||
}
|
||||
)
|
||||
|
||||
every { SignalStore.account.e164 } returns "+15551234567"
|
||||
every { paymentValues.mobileCoinPaymentsEnabled() } returns true
|
||||
every { RemoteConfig.payments } returns true
|
||||
every { RemoteConfig.paymentsCountryBlocklist } returns ""
|
||||
|
||||
@@ -104,14 +94,8 @@ class PaymentsValuesTest {
|
||||
|
||||
@Test
|
||||
fun `when flag enabled and no account and in the country blocklist, expect NOT_IN_REGION`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, true)
|
||||
putString(AccountValues.KEY_E164, "+15551234567")
|
||||
putBoolean(PaymentsValues.MOB_PAYMENTS_ENABLED, false)
|
||||
}
|
||||
)
|
||||
|
||||
every { SignalStore.account.e164 } returns "+15551234567"
|
||||
every { paymentValues.mobileCoinPaymentsEnabled() } returns false
|
||||
every { RemoteConfig.payments } returns true
|
||||
every { RemoteConfig.paymentsCountryBlocklist } returns "1"
|
||||
|
||||
@@ -120,31 +104,11 @@ class PaymentsValuesTest {
|
||||
|
||||
@Test
|
||||
fun `when flag enabled and has account and in the country blocklist, expect WITHDRAW_ONLY`() {
|
||||
setupStore(
|
||||
KeyValueDataSet().apply {
|
||||
putBoolean(AccountValues.KEY_IS_REGISTERED, true)
|
||||
putString(AccountValues.KEY_E164, "+15551234567")
|
||||
putBoolean(PaymentsValues.MOB_PAYMENTS_ENABLED, true)
|
||||
}
|
||||
)
|
||||
|
||||
every { SignalStore.account.e164 } returns "+15551234567"
|
||||
every { paymentValues.mobileCoinPaymentsEnabled() } returns true
|
||||
every { RemoteConfig.payments } returns true
|
||||
every { RemoteConfig.paymentsCountryBlocklist } returns "1"
|
||||
|
||||
assertEquals(PaymentsAvailability.WITHDRAW_ONLY, SignalStore.payments.paymentsAvailability)
|
||||
}
|
||||
|
||||
/**
|
||||
* Account values will overwrite some values upon first access, so this takes care of that
|
||||
*/
|
||||
private fun setupStore(dataset: KeyValueDataSet) {
|
||||
val store = KeyValueStore(
|
||||
MockKeyValuePersistentStorage.withDataSet(
|
||||
dataset.apply {
|
||||
putString(AccountValues.KEY_ACI, "")
|
||||
}
|
||||
)
|
||||
)
|
||||
SignalStore.testInject(store)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.megaphone
|
||||
|
||||
import android.app.Application
|
||||
import android.net.Uri
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
@@ -15,15 +16,15 @@ import org.junit.After
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.SignalStoreRule
|
||||
import org.thoughtcrime.securesms.database.RemoteMegaphoneTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.RemoteMegaphoneRecord
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.util.toMillis
|
||||
import java.time.LocalDateTime
|
||||
import java.util.UUID
|
||||
@@ -36,11 +37,11 @@ import java.util.UUID
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
class RemoteMegaphoneRepositoryTest {
|
||||
|
||||
@get:Rule
|
||||
val signalStore: SignalStoreRule = SignalStoreRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
package org.thoughtcrime.securesms.notifications.profiles
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkAll
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers.`is`
|
||||
import org.hamcrest.Matchers.nullValue
|
||||
import org.junit.Rule
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.SignalStoreRule
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.keyvalue.NotificationProfileValues
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.toMillis
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDateTime
|
||||
@@ -43,8 +51,26 @@ class NotificationProfilesTest {
|
||||
schedule = NotificationProfileSchedule(2)
|
||||
)
|
||||
|
||||
@get:Rule
|
||||
val signalStore: SignalStoreRule = SignalStoreRule()
|
||||
private lateinit var notificationProfileValues: NotificationProfileValues
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
notificationProfileValues = mockk()
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns 0
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns 0
|
||||
|
||||
mockkObject(SignalStore)
|
||||
every { SignalStore.notificationProfile } returns notificationProfileValues
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when no profiles then return null`() {
|
||||
@@ -59,9 +85,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when first is not enabled and second is manually enabled forever then return second`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, second.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, 5000L)
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns second.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns Long.MAX_VALUE
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns 5000L
|
||||
|
||||
val profiles = listOf(first, second)
|
||||
assertThat("active profile is profile second", NotificationProfiles.getActiveProfile(profiles, 3000L, utc), `is`(profiles[1]))
|
||||
@@ -76,9 +102,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when first is scheduled and second is manually enabled forever within first's schedule then return second`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, second.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns second.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns Long.MAX_VALUE
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule), second)
|
||||
@@ -87,9 +113,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when first is scheduled and second is manually enabled forever before first's schedule start then return first`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, second.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns second.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns Long.MAX_VALUE
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 900, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule), second)
|
||||
@@ -108,9 +134,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when first and second have overlapping schedules and first is created before second and first is manually enabled within overlapping schedule then return first`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns first.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns Long.MAX_VALUE
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val firstSchedule = NotificationProfileSchedule(id = 3L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val secondSchedule = NotificationProfileSchedule(id = 4L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
@@ -121,9 +147,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when profile is manually enabled for set time after schedule end and now is after schedule end but before manual then return profile`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday930am.toMillis(ZoneOffset.UTC))
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns first.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns sunday930am.toMillis(ZoneOffset.UTC)
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, end = 845, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule))
|
||||
@@ -132,9 +158,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when profile is manually enabled for set time before schedule end and now is after manual but before schedule end then return null`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday9am.toMillis(ZoneOffset.UTC))
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns first.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns sunday9am.toMillis(ZoneOffset.UTC)
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, end = 1000, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule))
|
||||
@@ -143,9 +169,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when profile is manually enabled yesterday and is scheduled also for today then return profile`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday9am.toMillis(ZoneOffset.UTC))
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns first.id
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns sunday9am.toMillis(ZoneOffset.UTC)
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, enabled = true, start = 700, end = 900, daysEnabled = setOf(DayOfWeek.SUNDAY, DayOfWeek.MONDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule))
|
||||
@@ -154,9 +180,9 @@ class NotificationProfilesTest {
|
||||
|
||||
@Test
|
||||
fun `when profile is manually disabled and schedule is on but with start after end and now is before end then return null`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, 0)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, 0)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
every { notificationProfileValues.manuallyEnabledProfile } returns 0
|
||||
every { notificationProfileValues.manuallyEnabledUntil } returns 0
|
||||
every { notificationProfileValues.manuallyDisabledAt } returns sunday830am.toMillis(ZoneOffset.UTC)
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, enabled = true, start = 2200, end = 1000, daysEnabled = DayOfWeek.values().toSet())
|
||||
val profiles = listOf(first.copy(schedule = schedule))
|
||||
|
||||
@@ -3,6 +3,9 @@ package org.thoughtcrime.securesms.recipients
|
||||
import android.graphics.Color
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkAll
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -26,19 +29,23 @@ class Recipient_getChatColorsTest : BaseRecipientTest() {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
wallpaperValues = mockk<WallpaperValues>()
|
||||
chatColorsValues = mockk<ChatColorsValues>()
|
||||
wallpaperValues = mockk()
|
||||
chatColorsValues = mockk()
|
||||
|
||||
val globalWallpaper = createWallpaper(globalWallpaperChatColor)
|
||||
every { wallpaperValues.wallpaper } answers { globalWallpaper }
|
||||
every { chatColorsValues.chatColors } answers { globalChatColor }
|
||||
|
||||
val mockStore = mockk<SignalStore>()
|
||||
SignalStore.testInject(mockStore)
|
||||
mockkObject(SignalStore)
|
||||
every { SignalStore.wallpaper } returns wallpaperValues
|
||||
every { SignalStore.chatColors } returns chatColorsValues
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given recipient has custom chat color set, when I getChatColors, then I expect the custom chat color`() {
|
||||
// GIVEN
|
||||
|
||||
@@ -2,35 +2,26 @@ package org.thoughtcrime.securesms.storage
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkObject
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockedStatic
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.internal.configuration.plugins.Plugins
|
||||
import org.mockito.internal.junit.JUnitRule
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.mockito.quality.Strictness
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.keyvalue.AccountValues
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
|
||||
import org.thoughtcrime.securesms.keyvalue.MockKeyValuePersistentStorage
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.testutil.EmptyLogger
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord
|
||||
@@ -42,24 +33,23 @@ import java.util.UUID
|
||||
@Config(application = Application::class)
|
||||
class ContactRecordProcessorTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val mockitoRule: MockitoRule = JUnitRule(Plugins.getMockitoLogger(), Strictness.STRICT_STUBS)
|
||||
|
||||
@Mock
|
||||
lateinit var recipientTable: RecipientTable
|
||||
|
||||
@Mock
|
||||
lateinit var remoteConfig: MockedStatic<RemoteConfig>
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val mockAccountValues = mock(AccountValues::class.java)
|
||||
Mockito.lenient().`when`(mockAccountValues.isPrimaryDevice).thenReturn(true)
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
SignalStore.testInject(KeyValueStore(MockKeyValuePersistentStorage.withDataSet(KeyValueDataSet())))
|
||||
|
||||
mockkObject(SignalStore)
|
||||
every { SignalStore.account.isPrimaryDevice } returns true
|
||||
|
||||
recipientTable = mockk(relaxed = true)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkObject(SignalStore)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.thoughtcrime.securesms.SignalStoreRule;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.AccountValues;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
|
||||
@RunWith(ParameterizedRobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE, application = Application.class)
|
||||
public class SignalMeUtilText_parseE164FromLink {
|
||||
|
||||
private final String input;
|
||||
private final String output;
|
||||
|
||||
@ParameterizedRobolectricTestRunner.Parameters
|
||||
public static Collection<Object[]> data() {
|
||||
return Arrays.asList(new Object[][]{
|
||||
{ "https://signal.me/#p/+15555555555", "+15555555555" },
|
||||
{ "https://signal.me/#p/5555555555", null },
|
||||
{ "https://signal.me", null },
|
||||
{ "https://signal.me/#p/", null },
|
||||
{ "signal.me/#p/+15555555555", null },
|
||||
{ "sgnl://signal.me/#p/+15555555555", "+15555555555" },
|
||||
{ "sgnl://signal.me/#p/5555555555", null },
|
||||
{ "sgnl://signal.me", null },
|
||||
{ "sgnl://signal.me/#p/", null },
|
||||
{ "", null },
|
||||
{ null, null }
|
||||
});
|
||||
}
|
||||
|
||||
@Rule
|
||||
public SignalStoreRule signalStore = new SignalStoreRule(dataSet -> {
|
||||
dataSet.putString(AccountValues.KEY_E164, "+15555555555");
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
public SignalMeUtilText_parseE164FromLink(String input, String output) {
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse() {
|
||||
assertEquals(output, SignalMeUtil.parseE164FromLink(AppDependencies.getApplication(), input));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.thoughtcrime.securesms.util
|
||||
|
||||
import android.app.Application
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkAll
|
||||
import junit.framework.TestCase
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies.application
|
||||
import org.thoughtcrime.securesms.dependencies.MockApplicationDependencyProvider
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.SignalMeUtil.parseE164FromLink
|
||||
|
||||
@RunWith(ParameterizedRobolectricTestRunner::class)
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
class SignalMeUtilText_parseE164FromLink(private val input: String?, private val output: String?) {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
if (!AppDependencies.isInitialized) {
|
||||
AppDependencies.init(ApplicationProvider.getApplicationContext(), MockApplicationDependencyProvider())
|
||||
}
|
||||
|
||||
mockkObject(SignalStore)
|
||||
every { SignalStore.account.e164 } returns "+15555555555"
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parse() {
|
||||
TestCase.assertEquals(output, parseE164FromLink(application, input))
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@ParameterizedRobolectricTestRunner.Parameters
|
||||
fun data(): Collection<Array<Any?>> {
|
||||
return listOf(
|
||||
arrayOf("https://signal.me/#p/+15555555555", "+15555555555"),
|
||||
arrayOf("https://signal.me/#p/5555555555", null),
|
||||
arrayOf("https://signal.me", null),
|
||||
arrayOf("https://signal.me/#p/", null),
|
||||
arrayOf("signal.me/#p/+15555555555", null),
|
||||
arrayOf("sgnl://signal.me/#p/+15555555555", "+15555555555"),
|
||||
arrayOf("sgnl://signal.me/#p/5555555555", null),
|
||||
arrayOf("sgnl://signal.me", null),
|
||||
arrayOf("sgnl://signal.me/#p/", null),
|
||||
arrayOf("", null),
|
||||
arrayOf(null, null)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user