That fuck shit the fascists are using
at master 341 lines 11 kB view raw
1package org.tm.archive.database 2 3import org.junit.Assert.assertEquals 4import org.junit.Assert.assertFalse 5import org.junit.Assert.assertNotEquals 6import org.junit.Assert.assertTrue 7import org.junit.Before 8import org.junit.Rule 9import org.junit.Test 10import org.signal.core.util.deleteAll 11import org.signal.core.util.readToList 12import org.signal.core.util.requireLong 13import org.signal.core.util.withinTransaction 14import org.signal.libsignal.zkgroup.groups.GroupMasterKey 15import org.signal.storageservice.protos.groups.Member 16import org.signal.storageservice.protos.groups.local.DecryptedGroup 17import org.signal.storageservice.protos.groups.local.DecryptedMember 18import org.tm.archive.groups.GroupId 19import org.tm.archive.recipients.Recipient 20import org.tm.archive.recipients.RecipientId 21import org.tm.archive.testing.SignalActivityRule 22import java.security.SecureRandom 23import kotlin.random.Random 24 25class GroupTableTest { 26 27 @get:Rule 28 val harness = SignalActivityRule() 29 30 private lateinit var groupTable: GroupTable 31 32 @Before 33 fun setUp() { 34 groupTable = SignalDatabase.groups 35 36 groupTable.writableDatabase.deleteAll(GroupTable.TABLE_NAME) 37 groupTable.writableDatabase.deleteAll(GroupTable.MembershipTable.TABLE_NAME) 38 } 39 40 @Test 41 fun whenICreateGroupV2_thenIExpectMemberRowsPopulated() { 42 val groupId = insertPushGroup() 43 44 //language=sql 45 val members: List<RecipientId> = groupTable.writableDatabase.query( 46 """ 47 SELECT ${GroupTable.MembershipTable.RECIPIENT_ID} 48 FROM ${GroupTable.MembershipTable.TABLE_NAME} 49 WHERE ${GroupTable.MembershipTable.GROUP_ID} = "${groupId.serialize()}" 50 """.trimIndent() 51 ).readToList { 52 RecipientId.from(it.requireLong(GroupTable.RECIPIENT_ID)) 53 } 54 55 assertEquals(2, members.size) 56 } 57 58 @Test 59 fun givenAGroupV2_whenIGetGroupsContainingMember_thenIExpectGroup() { 60 val groupId = insertPushGroup() 61 insertThread(groupId) 62 63 val groups = groupTable.getGroupsContainingMember(harness.others[0], false) 64 65 assertEquals(1, groups.size) 66 assertEquals(groupId, groups[0].id) 67 } 68 69 @Test 70 fun givenAnMmsGroup_whenIGetMembers_thenIExpectAllMembers() { 71 val groupId = insertMmsGroup() 72 73 val groups = groupTable.getGroupMemberIds(groupId, GroupTable.MemberSet.FULL_MEMBERS_INCLUDING_SELF) 74 75 assertEquals(2, groups.size) 76 } 77 78 @Test 79 fun givenGroups_whenIQueryGroupsByMembership_thenIExpectBothGroups() { 80 insertPushGroup() 81 insertMmsGroup(members = listOf(harness.others[1])) 82 83 val groups = groupTable.queryGroupsByMembership( 84 setOf(harness.self.id, harness.others[1]), 85 includeInactive = false, 86 excludeV1 = false, 87 excludeMms = false 88 ) 89 90 assertEquals(2, groups.cursor?.count) 91 } 92 93 @Test 94 fun givenGroups_whenIGetGroups_thenIExpectBothGroups() { 95 insertPushGroup() 96 insertMmsGroup(members = listOf(harness.others[1])) 97 98 val groups = groupTable.getGroups() 99 100 assertEquals(2, groups.cursor?.count) 101 } 102 103 @Test 104 fun givenAGroup_whenIGetGroup_thenIExpectGroup() { 105 val v2Group = insertPushGroup() 106 insertThread(v2Group) 107 108 val groupRecord = groupTable.getGroup(v2Group).get() 109 assertEquals(setOf(harness.self.id, harness.others[0]), groupRecord.members.toSet()) 110 } 111 112 @Test 113 fun givenAGroupAndARemap_whenIGetGroup_thenIExpectRemap() { 114 val v2Group = insertPushGroup() 115 insertThread(v2Group) 116 117 groupTable.writableDatabase.withinTransaction { 118 RemappedRecords.getInstance().addRecipient(harness.others[0], harness.others[1]) 119 } 120 121 val groupRecord = groupTable.getGroup(v2Group).get() 122 assertEquals(setOf(harness.self.id, harness.others[1]), groupRecord.members.toSet()) 123 } 124 125 @Test 126 fun givenAGroup_whenIRemapRecipientsThatHaveAConflict_thenIExpectDeletion() { 127 val v2Group = insertPushGroupWithSelfAndOthers( 128 listOf( 129 harness.others[0], 130 harness.others[1] 131 ) 132 ) 133 134 insertThread(v2Group) 135 136 groupTable.remapRecipient(harness.others[0], harness.others[1]) 137 138 val groupRecord = groupTable.getGroup(v2Group).get() 139 140 assertEquals(setOf(harness.self.id, harness.others[1]), groupRecord.members.toSet()) 141 } 142 143 @Test 144 fun givenAGroup_whenIRemapRecipients_thenIExpectRemap() { 145 val v2Group = insertPushGroup() 146 insertThread(v2Group) 147 148 val newId = harness.others[1] 149 groupTable.remapRecipient(harness.others[0], newId) 150 151 val groupRecord = groupTable.getGroup(v2Group).get() 152 153 assertEquals(setOf(harness.self.id, newId), groupRecord.members.toSet()) 154 } 155 156 @Test 157 fun givenAGroupAndMember_whenIIsCurrentMember_thenIExpectTrue() { 158 val v2Group = insertPushGroup() 159 160 val actual = groupTable.isCurrentMember(v2Group.requirePush(), harness.others[0]) 161 162 assertTrue(actual) 163 } 164 165 @Test 166 fun givenAGroupAndMember_whenIRemove_thenIExpectNotAMember() { 167 val v2Group = insertPushGroup() 168 169 groupTable.remove(v2Group, harness.others[0]) 170 val actual = groupTable.isCurrentMember(v2Group.requirePush(), harness.others[0]) 171 172 assertFalse(actual) 173 } 174 175 @Test 176 fun givenAGroupAndNonMember_whenIIsCurrentMember_thenIExpectFalse() { 177 val v2Group = insertPushGroup() 178 179 val actual = groupTable.isCurrentMember(v2Group.requirePush(), harness.others[1]) 180 181 assertFalse(actual) 182 } 183 184 @Test 185 fun givenAGroup_whenIUpdateMembers_thenIExpectUpdatedMembers() { 186 val v2Group = insertPushGroup() 187 groupTable.updateMembers(v2Group, listOf(harness.self.id, harness.others[1])) 188 val groupRecord = groupTable.getGroup(v2Group) 189 190 assertEquals(setOf(harness.self.id, harness.others[1]), groupRecord.get().members.toSet()) 191 } 192 193 @Test 194 fun givenAnMmsGroup_whenIGetOrCreateMmsGroup_thenIExpectMyMmsGroup() { 195 val members: List<RecipientId> = listOf(harness.self.id, harness.others[0]) 196 val other = insertMmsGroup(members + listOf(harness.others[1])) 197 val mmsGroup = insertMmsGroup(members) 198 val actual = groupTable.getOrCreateMmsGroupForMembers(members.toSet()) 199 200 assertNotEquals(other, actual) 201 assertEquals(mmsGroup, actual) 202 } 203 204 @Test 205 fun givenMultipleMmsGroups_whenIGetOrCreateMmsGroup_thenIExpectMyMmsGroup() { 206 val group1Members: List<RecipientId> = listOf(harness.self.id, harness.others[0], harness.others[1]) 207 val group2Members: List<RecipientId> = listOf(harness.self.id, harness.others[0], harness.others[2]) 208 209 val group1: GroupId = insertMmsGroup(group1Members) 210 val group2: GroupId = insertMmsGroup(group2Members) 211 212 val group1Result: GroupId = groupTable.getOrCreateMmsGroupForMembers(group1Members.toSet()) 213 val group2Result: GroupId = groupTable.getOrCreateMmsGroupForMembers(group2Members.toSet()) 214 215 assertEquals(group1, group1Result) 216 assertEquals(group2, group2Result) 217 assertNotEquals(group1Result, group2Result) 218 } 219 220 @Test 221 fun givenMultipleMmsGroupsWithDifferentMemberOrders_whenIGetOrCreateMmsGroup_thenIExpectMyMmsGroup() { 222 val group1Members: List<RecipientId> = listOf(harness.self.id, harness.others[0], harness.others[1], harness.others[2]).shuffled() 223 val group2Members: List<RecipientId> = listOf(harness.self.id, harness.others[0], harness.others[2], harness.others[3]).shuffled() 224 225 val group1: GroupId = insertMmsGroup(group1Members) 226 val group2: GroupId = insertMmsGroup(group2Members) 227 228 val group1Result: GroupId = groupTable.getOrCreateMmsGroupForMembers(group1Members.shuffled().toSet()) 229 val group2Result: GroupId = groupTable.getOrCreateMmsGroupForMembers(group2Members.shuffled().toSet()) 230 231 assertEquals(group1, group1Result) 232 assertEquals(group2, group2Result) 233 assertNotEquals(group1Result, group2Result) 234 } 235 236 @Test 237 fun givenMmsGroupWithOneMember_whenIGetOrCreateMmsGroup_thenIExpectMyMmsGroup() { 238 val groupMembers: List<RecipientId> = listOf(harness.self.id) 239 val group: GroupId = insertMmsGroup(groupMembers) 240 241 val groupResult: GroupId = groupTable.getOrCreateMmsGroupForMembers(groupMembers.toSet()) 242 243 assertEquals(group, groupResult) 244 } 245 246 @Test 247 fun givenTwoGroupsWithoutMembers_whenIQueryThem_thenIExpectEach() { 248 val g1 = insertPushGroup(listOf()) 249 val g2 = insertPushGroup(listOf()) 250 251 val gr1 = groupTable.getGroup(g1) 252 val gr2 = groupTable.getGroup(g2) 253 254 assertEquals(g1, gr1.get().id) 255 assertEquals(g2, gr2.get().id) 256 } 257 258 @Test 259 fun givenASharedActiveGroupWithoutAThread_whenISearchForRecipientsWithGroupsInCommon_thenIExpectThatGroup() { 260 val groupInCommon = insertPushGroup() 261 val expected = Recipient.resolved(harness.others[0]) 262 263 SignalDatabase.recipients.setProfileSharing(expected.id, false) 264 265 SignalDatabase.recipients.queryGroupMemberContacts("Buddy")!!.use { 266 assertTrue(it.moveToFirst()) 267 assertEquals(1, it.count) 268 assertEquals(expected.id.toLong(), it.requireLong(RecipientTable.ID)) 269 } 270 271 val groups = groupTable.getPushGroupsContainingMember(expected.id) 272 assertEquals(1, groups.size) 273 assertEquals(groups[0].id, groupInCommon) 274 } 275 276 private fun insertThread(groupId: GroupId): Long { 277 val groupRecipient = SignalDatabase.recipients.getByGroupId(groupId).get() 278 return SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(groupRecipient)) 279 } 280 281 private fun insertMmsGroup(members: List<RecipientId> = listOf(harness.self.id, harness.others[0])): GroupId { 282 val id = GroupId.createMms(SecureRandom()) 283 groupTable.create( 284 id, 285 null, 286 members.apply { 287 println("Creating a group with ${members.size} members") 288 } 289 ) 290 291 return id 292 } 293 294 private fun insertPushGroup( 295 members: List<DecryptedMember> = listOf( 296 DecryptedMember.Builder() 297 .aciBytes(harness.self.requireAci().toByteString()) 298 .joinedAtRevision(0) 299 .role(Member.Role.DEFAULT) 300 .build(), 301 DecryptedMember.Builder() 302 .aciBytes(Recipient.resolved(harness.others[0]).requireAci().toByteString()) 303 .joinedAtRevision(0) 304 .role(Member.Role.DEFAULT) 305 .build() 306 ) 307 ): GroupId { 308 val groupMasterKey = GroupMasterKey(Random.nextBytes(GroupMasterKey.SIZE)) 309 val decryptedGroupState = DecryptedGroup.Builder() 310 .members(members) 311 .revision(0) 312 .build() 313 314 return groupTable.create(groupMasterKey, decryptedGroupState)!! 315 } 316 317 private fun insertPushGroupWithSelfAndOthers(others: List<RecipientId>): GroupId { 318 val groupMasterKey = GroupMasterKey(Random.nextBytes(GroupMasterKey.SIZE)) 319 320 val selfMember: DecryptedMember = DecryptedMember.Builder() 321 .aciBytes(harness.self.requireAci().toByteString()) 322 .joinedAtRevision(0) 323 .role(Member.Role.DEFAULT) 324 .build() 325 326 val otherMembers: List<DecryptedMember> = others.map { id -> 327 DecryptedMember.Builder() 328 .aciBytes(Recipient.resolved(id).requireAci().toByteString()) 329 .joinedAtRevision(0) 330 .role(Member.Role.DEFAULT) 331 .build() 332 } 333 334 val decryptedGroupState = DecryptedGroup.Builder() 335 .members(listOf(selfMember) + otherMembers) 336 .revision(0) 337 .build() 338 339 return groupTable.create(groupMasterKey, decryptedGroupState)!! 340 } 341}