That fuck shit the fascists are using
1package org.tm.archive.testing
2
3import android.app.Activity
4import android.app.Application
5import android.content.Context
6import android.content.Intent
7import android.content.SharedPreferences
8import android.preference.PreferenceManager
9import androidx.test.core.app.ActivityScenario
10import androidx.test.platform.app.InstrumentationRegistry
11import okhttp3.mockwebserver.MockResponse
12import org.junit.rules.ExternalResource
13import org.signal.libsignal.protocol.IdentityKey
14import org.signal.libsignal.protocol.IdentityKeyPair
15import org.signal.libsignal.protocol.SignalProtocolAddress
16import org.tm.archive.SignalInstrumentationApplicationContext
17import org.tm.archive.crypto.IdentityKeyUtil
18import org.tm.archive.crypto.MasterSecretUtil
19import org.tm.archive.crypto.ProfileKeyUtil
20import org.tm.archive.database.IdentityTable
21import org.tm.archive.database.SignalDatabase
22import org.tm.archive.dependencies.ApplicationDependencies
23import org.tm.archive.dependencies.InstrumentationApplicationDependencyProvider
24import org.tm.archive.keyvalue.SignalStore
25import org.tm.archive.profiles.ProfileName
26import org.tm.archive.recipients.Recipient
27import org.tm.archive.recipients.RecipientId
28import org.tm.archive.registration.RegistrationData
29import org.tm.archive.registration.RegistrationRepository
30import org.tm.archive.registration.RegistrationUtil
31import org.tm.archive.registration.VerifyResponse
32import org.tm.archive.testing.GroupTestingUtils.asMember
33import org.tm.archive.util.Util
34import org.whispersystems.signalservice.api.profiles.SignalServiceProfile
35import org.whispersystems.signalservice.api.push.ServiceId.ACI
36import org.whispersystems.signalservice.api.push.SignalServiceAddress
37import org.whispersystems.signalservice.internal.ServiceResponse
38import org.whispersystems.signalservice.internal.ServiceResponseProcessor
39import org.whispersystems.signalservice.internal.push.VerifyAccountResponse
40import java.util.UUID
41
42/**
43 * Test rule to use that sets up the application in a mostly registered state. Enough so that most
44 * activities should be launchable directly.
45 *
46 * To use: `@get:Rule val harness = SignalActivityRule()`
47 */
48class SignalActivityRule(private val othersCount: Int = 4, private val createGroup: Boolean = false) : ExternalResource() {
49
50 val application: Application = ApplicationDependencies.getApplication()
51
52 lateinit var context: Context
53 private set
54 lateinit var self: Recipient
55 private set
56 lateinit var others: List<RecipientId>
57 private set
58 lateinit var othersKeys: List<IdentityKeyPair>
59
60 var group: GroupTestingUtils.TestGroupInfo? = null
61 private set
62
63 val inMemoryLogger: InMemoryLogger
64 get() = (application as SignalInstrumentationApplicationContext).inMemoryLogger
65
66 override fun before() {
67 context = InstrumentationRegistry.getInstrumentation().targetContext
68 self = setupSelf()
69
70 val setupOthers = setupOthers()
71 others = setupOthers.first
72 othersKeys = setupOthers.second
73
74 if (createGroup && others.size >= 2) {
75 group = GroupTestingUtils.insertGroup(
76 revision = 0,
77 self.asMember(),
78 others[0].asMember(),
79 others[1].asMember()
80 )
81 }
82
83 InstrumentationApplicationDependencyProvider.clearHandlers()
84 }
85
86 private fun setupSelf(): Recipient {
87 PreferenceManager.getDefaultSharedPreferences(application).edit().putBoolean("pref_prompted_push_registration", true).commit()
88 val masterSecret = MasterSecretUtil.generateMasterSecret(application, MasterSecretUtil.UNENCRYPTED_PASSPHRASE)
89 MasterSecretUtil.generateAsymmetricMasterSecret(application, masterSecret)
90 val preferences: SharedPreferences = application.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0)
91 preferences.edit().putBoolean("passphrase_initialized", true).commit()
92
93 SignalStore.account().generateAciIdentityKeyIfNecessary()
94 SignalStore.account().generatePniIdentityKeyIfNecessary()
95
96 val registrationRepository = RegistrationRepository(application)
97
98 InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(Put("/v2/keys") { MockResponse().success() })
99 val response: ServiceResponse<VerifyResponse> = registrationRepository.registerAccount(
100 RegistrationData(
101 code = "123123",
102 e164 = "+15555550101",
103 password = Util.getSecret(18),
104 registrationId = registrationRepository.registrationId,
105 profileKey = registrationRepository.getProfileKey("+15555550101"),
106 fcmToken = null,
107 pniRegistrationId = registrationRepository.pniRegistrationId,
108 recoveryPassword = "asdfasdfasdfasdf"
109 ),
110 VerifyResponse(
111 verifyAccountResponse = VerifyAccountResponse(UUID.randomUUID().toString(), UUID.randomUUID().toString(), false),
112 masterKey = null,
113 pin = null,
114 aciPreKeyCollection = RegistrationRepository.generateSignedAndLastResortPreKeys(SignalStore.account().aciIdentityKey, SignalStore.account().aciPreKeys),
115 pniPreKeyCollection = RegistrationRepository.generateSignedAndLastResortPreKeys(SignalStore.account().aciIdentityKey, SignalStore.account().pniPreKeys)
116 ),
117 false
118 ).blockingGet()
119
120 ServiceResponseProcessor.DefaultProcessor(response).resultOrThrow
121
122 SignalStore.svr().optOut()
123 RegistrationUtil.maybeMarkRegistrationComplete()
124 SignalDatabase.recipients.setProfileName(Recipient.self().id, ProfileName.fromParts("Tester", "McTesterson"))
125
126 SignalStore.settings().isMessageNotificationsEnabled = false
127
128 return Recipient.self()
129 }
130
131 private fun setupOthers(): Pair<List<RecipientId>, List<IdentityKeyPair>> {
132 val others = mutableListOf<RecipientId>()
133 val othersKeys = mutableListOf<IdentityKeyPair>()
134
135 if (othersCount !in 0 until 1000) {
136 throw IllegalArgumentException("$othersCount must be between 0 and 1000")
137 }
138
139 for (i in 0 until othersCount) {
140 val aci = ACI.from(UUID.randomUUID())
141 val recipientId = RecipientId.from(SignalServiceAddress(aci, "+15555551%03d".format(i)))
142 SignalDatabase.recipients.setProfileName(recipientId, ProfileName.fromParts("Buddy", "#$i"))
143 SignalDatabase.recipients.setProfileKeyIfAbsent(recipientId, ProfileKeyUtil.createNew())
144 SignalDatabase.recipients.setCapabilities(recipientId, SignalServiceProfile.Capabilities(true, true, true))
145 SignalDatabase.recipients.setProfileSharing(recipientId, true)
146 SignalDatabase.recipients.markRegistered(recipientId, aci)
147 val otherIdentity = IdentityKeyUtil.generateIdentityKeyPair()
148 ApplicationDependencies.getProtocolStore().aci().saveIdentity(SignalProtocolAddress(aci.toString(), 0), otherIdentity.publicKey)
149 others += recipientId
150 othersKeys += otherIdentity
151 }
152
153 return others to othersKeys
154 }
155
156 inline fun <reified T : Activity> launchActivity(initIntent: Intent.() -> Unit = {}): ActivityScenario<T> {
157 return androidx.test.core.app.launchActivity(Intent(context, T::class.java).apply(initIntent))
158 }
159
160 fun changeIdentityKey(recipient: Recipient, identityKey: IdentityKey = IdentityKeyUtil.generateIdentityKeyPair().publicKey) {
161 ApplicationDependencies.getProtocolStore().aci().saveIdentity(SignalProtocolAddress(recipient.requireServiceId().toString(), 0), identityKey)
162 }
163
164 fun getIdentity(recipient: Recipient): IdentityKey {
165 return ApplicationDependencies.getProtocolStore().aci().identities().getIdentity(SignalProtocolAddress(recipient.requireServiceId().toString(), 0))
166 }
167
168 fun setVerified(recipient: Recipient, status: IdentityTable.VerifiedStatus) {
169 ApplicationDependencies.getProtocolStore().aci().identities().setVerified(recipient.id, getIdentity(recipient), IdentityTable.VerifiedStatus.VERIFIED)
170 }
171}