Clean up and fixed some broken tests

This commit is contained in:
Morgan Pretty 2023-09-26 15:45:51 +10:00
parent 691acf2a42
commit 4f10277a48
29 changed files with 703 additions and 344 deletions

View File

@ -276,7 +276,7 @@
C328255225CA64470062D0A7 /* ContextMenuVC+ActionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C328255125CA64470062D0A7 /* ContextMenuVC+ActionView.swift */; };
C32C598A256D0664003C73A2 /* SNProtoEnvelope+Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38EEF09255B49A8007E1867 /* SNProtoEnvelope+Conversion.swift */; };
C32C599E256DB02B003C73A2 /* TypingIndicators.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA87255A57FC00E217F9 /* TypingIndicators.swift */; };
C32C5A24256DB7DB003C73A2 /* UserDefaultsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* UserDefaultsInfo.swift */; };
C32C5A24256DB7DB003C73A2 /* UserDefaultsConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* UserDefaultsConfig.swift */; };
C32C5A48256DB8F0003C73A2 /* BuildConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */; };
C32C5A88256DBCF9003C73A2 /* MessageReceiver+LegacyClosedGroups.swift in Sources */ = {isa = PBXBuildFile; fileRef = C32C5A87256DBCF9003C73A2 /* MessageReceiver+LegacyClosedGroups.swift */; };
C32C5C3D256DCBAF003C73A2 /* AppReadiness.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB75255A581000E217F9 /* AppReadiness.m */; };
@ -523,7 +523,7 @@
FD23CE282A67755C0000B97C /* MockCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE272A67755C0000B97C /* MockCrypto.swift */; };
FD23CE292A6775650000B97C /* MockCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE272A67755C0000B97C /* MockCrypto.swift */; };
FD23CE2A2A6775660000B97C /* MockCrypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE272A67755C0000B97C /* MockCrypto.swift */; };
FD23CE302A67B8820000B97C /* CacheInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE2F2A67B8820000B97C /* CacheInfo.swift */; };
FD23CE302A67B8820000B97C /* CacheConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE2F2A67B8820000B97C /* CacheConfig.swift */; };
FD23CE332A67C4D90000B97C /* MockNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE312A67C38D0000B97C /* MockNetwork.swift */; };
FD23CE342A67C4D90000B97C /* MockNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE312A67C38D0000B97C /* MockNetwork.swift */; };
FD23CE352A67C4DA0000B97C /* MockNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23CE312A67C38D0000B97C /* MockNetwork.swift */; };
@ -757,6 +757,8 @@
FDA8EAFE280E8B78002B68E5 /* FailedMessageSendsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */; };
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */; };
FDA8EB10280F8238002B68E5 /* Codable+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EB0F280F8238002B68E5 /* Codable+Utilities.swift */; };
FDAA16762AC28A3B00DDBF77 /* UserDefaultsType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDAA16752AC28A3B00DDBF77 /* UserDefaultsType.swift */; };
FDAA167B2AC28E2F00DDBF77 /* SnodeRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDAA167A2AC28E2F00DDBF77 /* SnodeRequestSpec.swift */; };
FDAED05C2A7C6CE600091B25 /* MigrationRequirement.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDAED05B2A7C6CE600091B25 /* MigrationRequirement.swift */; };
FDB4BBC72838B91E00B7C95D /* LinkPreviewError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB4BBC62838B91E00B7C95D /* LinkPreviewError.swift */; };
FDB4BBC92839BEF000B7C95D /* ProfileManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB4BBC82839BEF000B7C95D /* ProfileManagerError.swift */; };
@ -853,8 +855,8 @@
FDC438C927BB706500C60D73 /* SendDirectMessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438C827BB706500C60D73 /* SendDirectMessageRequest.swift */; };
FDC438CB27BB7DB100C60D73 /* UpdateMessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438CA27BB7DB100C60D73 /* UpdateMessageRequest.swift */; };
FDC438CD27BC641200C60D73 /* Set+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC438CC27BC641200C60D73 /* Set+Utilities.swift */; };
FDC498B32ABD82D000EDD897 /* MessageReceiverSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6ACADD2A32D3A9009AFB73 /* MessageReceiverSpec.swift */; };
FDC439632AC2492700A56963 /* MessageReceiverSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6ACADD2A32D3A9009AFB73 /* MessageReceiverSpec.swift */; };
FDC498B32ABD82D000EDD897 /* MessageReceiverSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6ACADD2A32D3A9009AFB73 /* MessageReceiverSpec.swift */; };
FDC498B72AC15F7D00EDD897 /* AppNotificationCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC498B62AC15F7D00EDD897 /* AppNotificationCategory.swift */; };
FDC498B92AC15FE300EDD897 /* AppNotificationAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC498B82AC15FE300EDD897 /* AppNotificationAction.swift */; };
FDC498BB2AC1606C00EDD897 /* AppNotificationUserInfoKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC498BA2AC1606C00EDD897 /* AppNotificationUserInfoKey.swift */; };
@ -890,7 +892,7 @@
FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */; };
FDED2E3C282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDED2E3B282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift */; };
FDF01FAB2A9EBAD500CAF969 /* MessageSenderGroupsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF01FAA2A9EBAD500CAF969 /* MessageSenderGroupsSpec.swift */; };
FDF01FAD2A9ECC4200CAF969 /* SingletonInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF01FAC2A9ECC4200CAF969 /* SingletonInfo.swift */; };
FDF01FAD2A9ECC4200CAF969 /* SingletonConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF01FAC2A9ECC4200CAF969 /* SingletonConfig.swift */; };
FDF0B73C27FFD3D6004C14C5 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */; };
FDF0B7422804EA4F004C14C5 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7412804EA4F004C14C5 /* _002_SetupStandardJobs.swift */; };
FDF0B7472804F0CE004C14C5 /* DisappearingMessagesJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7462804F0CE004C14C5 /* DisappearingMessagesJob.swift */; };
@ -1510,7 +1512,7 @@
C33FDB54255A580D00E217F9 /* DataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataSource.h; sourceTree = "<group>"; };
C33FDB68255A580F00E217F9 /* ContentProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentProxy.swift; sourceTree = "<group>"; };
C33FDB69255A580F00E217F9 /* FeatureFlags.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeatureFlags.swift; sourceTree = "<group>"; };
C33FDB6B255A580F00E217F9 /* UserDefaultsInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDefaultsInfo.swift; sourceTree = "<group>"; };
C33FDB6B255A580F00E217F9 /* UserDefaultsConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDefaultsConfig.swift; sourceTree = "<group>"; };
C33FDB75255A581000E217F9 /* AppReadiness.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppReadiness.m; sourceTree = "<group>"; };
C33FDB80255A581100E217F9 /* Notification+Loki.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Notification+Loki.swift"; sourceTree = "<group>"; };
C33FDB81255A581100E217F9 /* UIImage+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+OWS.m"; sourceTree = "<group>"; };
@ -1743,7 +1745,7 @@
FD23CE232A675C440000B97C /* Crypto+SessionMessagingKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Crypto+SessionMessagingKit.swift"; sourceTree = "<group>"; };
FD23CE252A676B5B0000B97C /* DependenciesSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependenciesSpec.swift; sourceTree = "<group>"; };
FD23CE272A67755C0000B97C /* MockCrypto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCrypto.swift; sourceTree = "<group>"; };
FD23CE2F2A67B8820000B97C /* CacheInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheInfo.swift; sourceTree = "<group>"; };
FD23CE2F2A67B8820000B97C /* CacheConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheConfig.swift; sourceTree = "<group>"; };
FD23CE312A67C38D0000B97C /* MockNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNetwork.swift; sourceTree = "<group>"; };
FD23EA6028ED0B260058676E /* CombineExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineExtensions.swift; sourceTree = "<group>"; };
FD245C612850664300B966DD /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
@ -1752,7 +1754,6 @@
FD29598C2A43BC0B00888A17 /* Version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = "<group>"; };
FD29598F2A43BE5F00888A17 /* VersionSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionSpec.swift; sourceTree = "<group>"; };
FD2AAAEF28ED57B500A49611 /* SynchronousStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SynchronousStorage.swift; sourceTree = "<group>"; };
FD2B4AFA29429D1000AB4848 /* ConfigContacts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigContacts.swift; sourceTree = "<group>"; };
FD2B4AFC294688D000AB4848 /* SessionUtil+Contacts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionUtil+Contacts.swift"; sourceTree = "<group>"; };
FD2B4AFE2946C93200AB4848 /* ConfigurationSyncJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationSyncJob.swift; sourceTree = "<group>"; };
FD2B4B032949887A00AB4848 /* QueryInterfaceRequest+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "QueryInterfaceRequest+Utilities.swift"; sourceTree = "<group>"; };
@ -1911,7 +1912,6 @@
FD8ECF7A29340FFD00C0D1BB /* SessionUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionUtil.swift; sourceTree = "<group>"; };
FD8ECF7C2934293A00C0D1BB /* _013_SessionUtilChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _013_SessionUtilChanges.swift; sourceTree = "<group>"; };
FD8ECF7E2934298100C0D1BB /* ConfigDump.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigDump.swift; sourceTree = "<group>"; };
FD8ECF812934387A00C0D1BB /* ConfigUserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigUserProfile.swift; sourceTree = "<group>"; };
FD8ECF882935AB7200C0D1BB /* SessionUtilError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionUtilError.swift; sourceTree = "<group>"; };
FD8ECF8F29381FC200C0D1BB /* SessionUtil+UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionUtil+UserProfile.swift"; sourceTree = "<group>"; };
FD8ECF912938552800C0D1BB /* Threading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Threading.swift; sourceTree = "<group>"; };
@ -1970,13 +1970,14 @@
FD9B30F2293EA0BF008DEE3E /* BatchResponseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchResponseSpec.swift; sourceTree = "<group>"; };
FD9BDDF82A5D2294005F1EBC /* libSessionUtil.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSessionUtil.a; sourceTree = BUILT_PRODUCTS_DIR; };
FD9DD2702A72516D00ECB68E /* TestExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestExtensions.swift; sourceTree = "<group>"; };
FDA1E83529A5748F00C5C3BD /* ConfigUserGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigUserGroups.swift; sourceTree = "<group>"; };
FDA1E83829A5771A00C5C3BD /* LibSessionSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibSessionSpec.swift; sourceTree = "<group>"; };
FDA1E83A29A5F2D500C5C3BD /* SessionUtil+Shared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionUtil+Shared.swift"; sourceTree = "<group>"; };
FDA1E83C29AC71A800C5C3BD /* SessionUtilSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionUtilSpec.swift; sourceTree = "<group>"; };
FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessageSendsJob.swift; sourceTree = "<group>"; };
FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedAttachmentDownloadsJob.swift; sourceTree = "<group>"; };
FDA8EB0F280F8238002B68E5 /* Codable+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Codable+Utilities.swift"; sourceTree = "<group>"; };
FDAA16752AC28A3B00DDBF77 /* UserDefaultsType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsType.swift; sourceTree = "<group>"; };
FDAA167A2AC28E2F00DDBF77 /* SnodeRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeRequestSpec.swift; sourceTree = "<group>"; };
FDAED05B2A7C6CE600091B25 /* MigrationRequirement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationRequirement.swift; sourceTree = "<group>"; };
FDB4BBC62838B91E00B7C95D /* LinkPreviewError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewError.swift; sourceTree = "<group>"; };
FDB4BBC82839BEF000B7C95D /* ProfileManagerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileManagerError.swift; sourceTree = "<group>"; };
@ -1986,8 +1987,6 @@
FDB5DAC62A9447E7002C8721 /* _018_GroupsRebuildChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _018_GroupsRebuildChanges.swift; sourceTree = "<group>"; };
FDB5DAC82A944E12002C8721 /* SessionUtil+GroupMembers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionUtil+GroupMembers.swift"; sourceTree = "<group>"; };
FDB5DACA2A944E72002C8721 /* SessionUtil+GroupKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionUtil+GroupKeys.swift"; sourceTree = "<group>"; };
FDB5DACC2A9452F0002C8721 /* ConfigGroupMembers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigGroupMembers.swift; sourceTree = "<group>"; };
FDB5DACE2A945307002C8721 /* ConfigGroupKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigGroupKeys.swift; sourceTree = "<group>"; };
FDB5DAD02A94838C002C8721 /* GroupInviteMemberJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInviteMemberJob.swift; sourceTree = "<group>"; };
FDB5DAD32A9483F3002C8721 /* GroupUpdateInviteMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupUpdateInviteMessage.swift; sourceTree = "<group>"; };
FDB5DAD72A95D830002C8721 /* GroupUpdateDeleteMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupUpdateDeleteMessage.swift; sourceTree = "<group>"; };
@ -2010,7 +2009,6 @@
FDB947142A9C23AF001F271A /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
FDB947162A9D69A8001F271A /* MockSessionUtilCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSessionUtilCache.swift; sourceTree = "<group>"; };
FDB9471A2A9D70A6001F271A /* CommonSMKMockExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonSMKMockExtensions.swift; sourceTree = "<group>"; };
FDBB25E02983909300F1508E /* ConfigConvoInfoVolatile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigConvoInfoVolatile.swift; sourceTree = "<group>"; };
FDBB25E22988B13800F1508E /* _004_AddJobPriority.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _004_AddJobPriority.swift; sourceTree = "<group>"; };
FDBB25E62988BBBD00F1508E /* UIContextualAction+Theming.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIContextualAction+Theming.swift"; sourceTree = "<group>"; };
FDC13D462A16E4CA007267C7 /* SubscribeRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscribeRequest.swift; sourceTree = "<group>"; };
@ -2035,7 +2033,6 @@
FDC2909D27D85751005DAE71 /* OpenGroupManagerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManagerSpec.swift; sourceTree = "<group>"; };
FDC290A527D860CE005DAE71 /* Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mock.swift; sourceTree = "<group>"; };
FDC290A727D9B46D005DAE71 /* NimbleExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NimbleExtensions.swift; sourceTree = "<group>"; };
FDC3833A2A9344C700FFD6A2 /* ConfigGroupInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigGroupInfo.swift; sourceTree = "<group>"; };
FDC4380827B31D4E00C60D73 /* OpenGroupAPIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupAPIError.swift; sourceTree = "<group>"; };
FDC4381627B32EC700C60D73 /* Personalization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Personalization.swift; sourceTree = "<group>"; };
FDC4381F27B36ADC00C60D73 /* SOGSEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSEndpoint.swift; sourceTree = "<group>"; };
@ -2098,7 +2095,7 @@
FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlMessageProcessRecord.swift; sourceTree = "<group>"; };
FDED2E3B282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+ReusableView.swift"; sourceTree = "<group>"; };
FDF01FAA2A9EBAD500CAF969 /* MessageSenderGroupsSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSenderGroupsSpec.swift; sourceTree = "<group>"; };
FDF01FAC2A9ECC4200CAF969 /* SingletonInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingletonInfo.swift; sourceTree = "<group>"; };
FDF01FAC2A9ECC4200CAF969 /* SingletonConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingletonConfig.swift; sourceTree = "<group>"; };
FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreview.swift; sourceTree = "<group>"; };
FDF0B73F280402C4004C14C5 /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Job.swift; sourceTree = "<group>"; };
FDF0B7412804EA4F004C14C5 /* _002_SetupStandardJobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_SetupStandardJobs.swift; sourceTree = "<group>"; };
@ -2509,13 +2506,6 @@
path = "Emoji Picker";
sourceTree = "<group>";
};
7B6ACADC2A32D38D009AFB73 /* MessagingKit */ = {
isa = PBXGroup;
children = (
);
path = MessagingKit;
sourceTree = "<group>";
};
7B7CB18C270D06350079FF93 /* Views & Modals */ = {
isa = PBXGroup;
children = (
@ -3628,7 +3618,6 @@
D221A08C169C9E5E00537ABF /* Frameworks */,
D221A08A169C9E5E00537ABF /* Products */,
2BADBA206E0B8D297E313FBA /* Pods */,
FDC498B22ABD6DC700EDD897 /* Recovered References */,
);
sourceTree = "<group>";
};
@ -3742,6 +3731,7 @@
FDE519F62AB7CDC700450C53 /* Result+Utilities.swift */,
C33FDB38255A580B00E217F9 /* OWSBackgroundTask.h */,
C33FDC1B255A581F00E217F9 /* OWSBackgroundTask.m */,
FDAA16752AC28A3B00DDBF77 /* UserDefaultsType.swift */,
FD29598C2A43BC0B00888A17 /* Version.swift */,
);
path = Utilities;
@ -4021,7 +4011,6 @@
isa = PBXGroup;
children = (
FDF01FAA2A9EBAD500CAF969 /* MessageSenderGroupsSpec.swift */,
7B6ACADD2A32D3A9009AFB73 /* MessageReceiverSpec.swift */,
FD3C907027E445E500CD579F /* MessageReceiverDecryptionSpec.swift */,
7B6ACADD2A32D3A9009AFB73 /* MessageReceiverSpec.swift */,
FD3C906C27E43C4B00CD579F /* MessageSenderEncryptionSpec.swift */,
@ -4325,6 +4314,14 @@
path = Networking;
sourceTree = "<group>";
};
FDAA16792AC28E2200DDBF77 /* Models */ = {
isa = PBXGroup;
children = (
FDAA167A2AC28E2F00DDBF77 /* SnodeRequestSpec.swift */,
);
path = Models;
sourceTree = "<group>";
};
FDB5DAD22A9483D4002C8721 /* Group Update Messages */ = {
isa = PBXGroup;
children = (
@ -4344,6 +4341,7 @@
FDB5DAFB2A981C43002C8721 /* SessionSnodeKitTests */ = {
isa = PBXGroup;
children = (
FDAA16792AC28E2200DDBF77 /* Models */,
FDB5DB042A981C55002C8721 /* Networking */,
);
path = SessionSnodeKitTests;
@ -4504,20 +4502,6 @@
path = _TestUtilities;
sourceTree = "<group>";
};
FDC498B22ABD6DC700EDD897 /* Recovered References */ = {
isa = PBXGroup;
children = (
FDBB25E02983909300F1508E /* ConfigConvoInfoVolatile.swift */,
FDB5DACE2A945307002C8721 /* ConfigGroupKeys.swift */,
FDA1E83529A5748F00C5C3BD /* ConfigUserGroups.swift */,
FD2B4AFA29429D1000AB4848 /* ConfigContacts.swift */,
FDC3833A2A9344C700FFD6A2 /* ConfigGroupInfo.swift */,
FDB5DACC2A9452F0002C8721 /* ConfigGroupMembers.swift */,
FD8ECF812934387A00C0D1BB /* ConfigUserProfile.swift */,
);
name = "Recovered References";
sourceTree = "<group>";
};
FDC498B52AC15F6D00EDD897 /* Types */ = {
isa = PBXGroup;
children = (
@ -4560,10 +4544,10 @@
FDF01FAE2A9ED0C800CAF969 /* Dependency Injection */ = {
isa = PBXGroup;
children = (
FD23CE2F2A67B8820000B97C /* CacheInfo.swift */,
FD23CE2F2A67B8820000B97C /* CacheConfig.swift */,
FDC6D75F2862B3F600B04575 /* Dependencies.swift */,
FDF01FAC2A9ECC4200CAF969 /* SingletonInfo.swift */,
C33FDB6B255A580F00E217F9 /* UserDefaultsInfo.swift */,
FDF01FAC2A9ECC4200CAF969 /* SingletonConfig.swift */,
C33FDB6B255A580F00E217F9 /* UserDefaultsConfig.swift */,
);
path = "Dependency Injection";
sourceTree = "<group>";
@ -6148,11 +6132,11 @@
FD23CE1F2A65269C0000B97C /* Crypto.swift in Sources */,
B8BC00C0257D90E30032E807 /* General.swift in Sources */,
FDF8488629405A61007DCAE5 /* Request.swift in Sources */,
FD23CE302A67B8820000B97C /* CacheInfo.swift in Sources */,
FD23CE302A67B8820000B97C /* CacheConfig.swift in Sources */,
FD17D7A127F40D2500122BE0 /* Storage.swift in Sources */,
FD1A94FB2900D1C2000D73D3 /* PersistableRecord+Utilities.swift in Sources */,
FD5D201E27B0D87C00FEA984 /* SessionId.swift in Sources */,
C32C5A24256DB7DB003C73A2 /* UserDefaultsInfo.swift in Sources */,
C32C5A24256DB7DB003C73A2 /* UserDefaultsConfig.swift in Sources */,
FD8ECF922938552800C0D1BB /* Threading.swift in Sources */,
B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */,
FDF22211281B5E0B000A4995 /* TableRecord+Utilities.swift in Sources */,
@ -6180,6 +6164,7 @@
FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */,
FD9004142818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift in Sources */,
FDF8487A29405906007DCAE5 /* HTTPError.swift in Sources */,
FDAA16762AC28A3B00DDBF77 /* UserDefaultsType.swift in Sources */,
FDDF074429C3E3D000E5E8B5 /* FetchRequest+Utilities.swift in Sources */,
B87EF18126377A1D00124B3C /* Features.swift in Sources */,
FD09797727FAB7A600936362 /* Data+Image.swift in Sources */,
@ -6190,7 +6175,7 @@
FDF8488929405B27007DCAE5 /* Data+Utilities.swift in Sources */,
FD09797227FAA2F500936362 /* Optional+Utilities.swift in Sources */,
FD7162DB281B6C440060647B /* TypedTableAlias.swift in Sources */,
FDF01FAD2A9ECC4200CAF969 /* SingletonInfo.swift in Sources */,
FDF01FAD2A9ECC4200CAF969 /* SingletonConfig.swift in Sources */,
FD7115F828C8151C00B47552 /* DisposableBarButtonItem.swift in Sources */,
FD17D7E727F6A16700122BE0 /* _003_YDBToGRDBMigration.swift in Sources */,
);
@ -6704,6 +6689,7 @@
FDB5DB162A9821DF002C8721 /* CommonMockedExtensions.swift in Sources */,
FDB5DB112A981FA6002C8721 /* TestExtensions.swift in Sources */,
FDB5DB092A981F8D002C8721 /* MockCrypto.swift in Sources */,
FDAA167B2AC28E2F00DDBF77 /* SnodeRequestSpec.swift in Sources */,
FD65318C2AA025C500DFEEAA /* TestDependencies.swift in Sources */,
FDB5DB102A981FA3002C8721 /* TestConstants.swift in Sources */,
FDB5DB0C2A981F96002C8721 /* MockNetwork.swift in Sources */,

View File

@ -175,7 +175,7 @@ public extension Profile {
profileEncryptionKey: profileKey,
lastProfilePictureUpdate: sentTimestamp,
blocksCommunityMessageRequests: (proto.hasBlocksCommunityMessageRequests ? proto.blocksCommunityMessageRequests : nil),
lastBlocksCommunityMessageRequests: (proto.hasBlocksCommunityMessageRequests ? sentTimestamp : 0)
lastBlocksCommunityMessageRequests: (proto.hasBlocksCommunityMessageRequests ? sentTimestamp : nil)
)
}

View File

@ -107,6 +107,7 @@ public enum MessageSendJob: JobExecutor {
/// If we got an error when trying to retrieve the attachment state then this job is actually invalid so it
/// should permanently fail
guard attachmentState.error == nil else {
SNLog("[MessageSendJob] Failed due to invalid attachment state")
return failure(job, (attachmentState.error ?? MessageSenderError.invalidMessage), true, dependencies)
}

View File

@ -1260,7 +1260,7 @@ public extension OpenGroupManager {
}
public extension Cache {
static let openGroupManager: CacheInfo.Config<OGMCacheType, OGMImmutableCacheType> = CacheInfo.create(
static let openGroupManager: CacheConfig<OGMCacheType, OGMImmutableCacheType> = Dependencies.create(
createInstance: { _ in OpenGroupManager.Cache() },
mutableInstance: { $0 },
immutableInstance: { $0 }

View File

@ -9,7 +9,7 @@ import SessionUtilitiesKit
// MARK: - Singleton
public extension Singleton {
static let closedGroupPoller: SingletonInfo.Config<ClosedGroupPoller> = SingletonInfo.create { _ in
static let closedGroupPoller: SingletonConfig<ClosedGroupPoller> = Dependencies.create { _ in
ClosedGroupPoller()
}
}

View File

@ -48,7 +48,7 @@ internal extension SessionUtil {
)
),
lastProfilePictureUpdate: (TimeInterval(serverTimestampMs) / 1000),
lastBlocksCommunityMessageRequests: 0
lastBlocksCommunityMessageRequests: nil
)
result.append(

View File

@ -608,7 +608,7 @@ public extension SessionUtil {
}
public extension Cache {
static let sessionUtil: CacheInfo.Config<SessionUtilCacheType, SessionUtilImmutableCacheType> = CacheInfo.create(
static let sessionUtil: CacheConfig<SessionUtilCacheType, SessionUtilImmutableCacheType> = Dependencies.create(
createInstance: { _ in SessionUtil.Cache() },
mutableInstance: { $0 },
immutableInstance: { $0 }

View File

@ -57,7 +57,13 @@ class SessionUtilSpec: QuickSpec {
)
@TestState(cache: .sessionUtil, in: dependencies) var mockSessionUtilCache: MockSessionUtilCache! = MockSessionUtilCache(
initialSetup: { cache in
var conf: UnsafeMutablePointer<config_object>!
var secretKey: [UInt8] = Array(Data(hex: TestConstants.edSecretKey))
_ = user_groups_init(&conf, &secretKey, nil, 0, nil)
cache.when { $0.setConfig(for: any(), publicKey: any(), to: any()) }.thenReturn(())
cache.when { $0.config(for: .userGroups, publicKey: any()) }
.thenReturn(Atomic(.object(conf)))
}
)
@TestState var createGroupOutput: SessionUtil.CreatedGroupInfo!
@ -355,10 +361,7 @@ class SessionUtilSpec: QuickSpec {
id: "123456",
profile: Profile(
id: "123456",
name: "",
lastNameUpdate: 0,
lastProfilePictureUpdate: 0,
lastBlocksCommunityMessageRequests: 0
name: ""
)
)],
admins: [],
@ -447,21 +450,15 @@ class SessionUtilSpec: QuickSpec {
profile: Profile(
id: "051111111111111111111111111111111111111111111111111111111111111111",
name: "TestName",
lastNameUpdate: 0,
profilePictureUrl: "testUrl",
profileEncryptionKey: Data([1, 2, 3]),
lastProfilePictureUpdate: 0,
lastBlocksCommunityMessageRequests: 0
profileEncryptionKey: Data([1, 2, 3])
)
)],
admins: [(
id: "05\(TestConstants.publicKey)",
profile: Profile(
id: "05\(TestConstants.publicKey)",
name: "TestName2",
lastNameUpdate: 0,
lastProfilePictureUpdate: 0,
lastBlocksCommunityMessageRequests: 0
name: "TestName2"
)
)],
using: dependencies
@ -504,10 +501,7 @@ class SessionUtilSpec: QuickSpec {
id: "051111111111111111111111111111111111111111111111111111111111111111",
profile: Profile(
id: "051111111111111111111111111111111111111111111111111111111111111111",
name: "TestName",
lastNameUpdate: 0,
lastProfilePictureUpdate: 0,
lastBlocksCommunityMessageRequests: 0
name: "TestName"
)
)],
admins: [],
@ -594,11 +588,14 @@ class SessionUtilSpec: QuickSpec {
)
})
}
}
// MARK: - when saving a created a group
context("when saving a created a group") {
// MARK: -- saves config dumps for the stored configs
it("saves config dumps for the stored configs") {
createGroupOutput = mockStorage.write(using: dependencies) { db in
try SessionUtil.createGroup(
mockStorage.write(using: dependencies) { db in
createGroupOutput = try SessionUtil.createGroup(
db,
name: "Testname",
displayPictureUrl: nil,
@ -611,6 +608,13 @@ class SessionUtilSpec: QuickSpec {
admins: [],
using: dependencies
)
try SessionUtil.saveCreatedGroup(
db,
group: createGroupOutput.group,
groupState: createGroupOutput.groupState,
using: dependencies
)
}
let result: [ConfigDump]? = mockStorage.read(using: dependencies) { db in
@ -618,11 +622,44 @@ class SessionUtilSpec: QuickSpec {
}
expect(result?.map { $0.variant }.asSet())
.to(equal([.groupInfo, .groupKeys, .groupMembers]))
.to(contain([.groupInfo, .groupKeys, .groupMembers]))
expect(result?.map { $0.publicKey }.asSet())
.to(equal(["03cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"]))
.to(contain(["03cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"]))
expect(result?.map { $0.timestampMs }.asSet())
.to(equal([1234567890000]))
.to(contain([1234567890000]))
}
// MARK: -- adds the group to the user groups config
it("adds the group to the user groups config") {
mockStorage.write(using: dependencies) { db in
createGroupOutput = try SessionUtil.createGroup(
db,
name: "Testname",
displayPictureUrl: nil,
displayPictureFilename: nil,
displayPictureEncryptionKey: nil,
members: [(
id: "051111111111111111111111111111111111111111111111111111111111111111",
profile: nil
)],
admins: [],
using: dependencies
)
try SessionUtil.saveCreatedGroup(
db,
group: createGroupOutput.group,
groupState: createGroupOutput.groupState,
using: dependencies
)
}
let result: [ConfigDump]? = mockStorage.read(using: dependencies) { db in
try ConfigDump.fetchAll(db)
}
expect(result?.map { $0.variant }.asSet()).to(contain([.userGroups]))
expect(result?.map { $0.timestampMs }.asSet()).to(contain([1234567890000]))
}
}
}

View File

@ -214,7 +214,7 @@ class OpenGroupManagerSpec: QuickSpec {
it("defaults the time since last open to greatestFiniteMagnitude") {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(nil)
@ -226,7 +226,7 @@ class OpenGroupManagerSpec: QuickSpec {
it("returns the time since the last open") {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(Date(timeIntervalSince1970: 1234567880))
dependencies.dateNow = Date(timeIntervalSince1970: 1234567890)
@ -239,7 +239,7 @@ class OpenGroupManagerSpec: QuickSpec {
it("caches the time since the last open") {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(Date(timeIntervalSince1970: 1234567770))
dependencies.dateNow = Date(timeIntervalSince1970: 1234567780)
@ -249,7 +249,7 @@ class OpenGroupManagerSpec: QuickSpec {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(Date(timeIntervalSince1970: 1234567890))
@ -289,7 +289,7 @@ class OpenGroupManagerSpec: QuickSpec {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(Date(timeIntervalSince1970: 1234567890))
}
@ -745,7 +745,7 @@ class OpenGroupManagerSpec: QuickSpec {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(Date(timeIntervalSince1970: 1234567890))
}
@ -890,7 +890,7 @@ class OpenGroupManagerSpec: QuickSpec {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(Date(timeIntervalSince1970: 1234567890))
}
@ -1171,7 +1171,7 @@ class OpenGroupManagerSpec: QuickSpec {
mockUserDefaults
.when { (defaults: inout any UserDefaultsType) -> Any? in
defaults.object(forKey: UserDefaultsInfo.DateKey.lastOpen.rawValue)
defaults.object(forKey: UserDefaults.DateKey.lastOpen.rawValue)
}
.thenReturn(nil)
}
@ -3207,7 +3207,7 @@ class OpenGroupManagerSpec: QuickSpec {
.to(call(matchingParameters: .all) {
$0.set(
testDate,
forKey: UserDefaultsInfo.DateKey.lastOpenGroupImageUpdate.rawValue
forKey: UserDefaults.DateKey.lastOpenGroupImageUpdate.rawValue
)
})
expect(
@ -3316,7 +3316,7 @@ class OpenGroupManagerSpec: QuickSpec {
.toNot(call(matchingParameters: .all) {
$0.set(
dependencies.dateNow,
forKey: UserDefaultsInfo.DateKey.lastOpenGroupImageUpdate.rawValue
forKey: UserDefaults.DateKey.lastOpenGroupImageUpdate.rawValue
)
})
}
@ -3398,7 +3398,7 @@ class OpenGroupManagerSpec: QuickSpec {
.to(call(matchingParameters: .all) {
$0.set(
dependencies.dateNow,
forKey: UserDefaultsInfo.DateKey.lastOpenGroupImageUpdate.rawValue
forKey: UserDefaults.DateKey.lastOpenGroupImageUpdate.rawValue
)
})
}

View File

@ -1,3 +1,188 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Combine
import GRDB
import SessionUtil
import SessionUtilitiesKit
import Quick
import Nimble
@testable import SessionMessagingKit
class MessageSenderGroupsSpec: QuickSpec {
override class func spec() {
// MARK: Configuration
@TestState var dependencies: TestDependencies! = TestDependencies { dependencies in
dependencies.dateNow = Date(timeIntervalSince1970: 1234567890)
dependencies.forceSynchronous = true
}
@TestState(singleton: .storage, in: dependencies) var mockStorage: Storage! = SynchronousStorage(
customWriter: try! DatabaseQueue(),
customMigrationTargets: [
SNUtilitiesKit.self,
SNMessagingKit.self
],
using: dependencies,
initialData: { db in
try Identity(variant: .x25519PublicKey, data: Data(hex: TestConstants.publicKey)).insert(db)
try Identity(variant: .x25519PrivateKey, data: Data(hex: TestConstants.privateKey)).insert(db)
try Identity(variant: .ed25519PublicKey, data: Data(hex: TestConstants.edPublicKey)).insert(db)
try Identity(variant: .ed25519SecretKey, data: Data(hex: TestConstants.edSecretKey)).insert(db)
}
)
@TestState(singleton: .network, in: dependencies) var mockNetwork: MockNetwork! = MockNetwork()
@TestState(singleton: .crypto, in: dependencies) var mockCrypto: MockCrypto! = MockCrypto(
initialSetup: { crypto in
crypto
.when { crypto in crypto.generate(.ed25519KeyPair(seed: any(), using: any())) }
.thenReturn(
KeyPair(
publicKey: Data.data(
fromHex: "cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"
)!.bytes,
secretKey: Data.data(
fromHex: "0123456789abcdef0123456789abcdeffedcba9876543210fedcba9876543210" +
"cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"
)!.bytes
)
)
}
)
@TestState(cache: .general, in: dependencies) var mockGeneralCache: MockGeneralCache! = MockGeneralCache(
initialSetup: { cache in
cache.when { $0.encodedPublicKey }.thenReturn("05\(TestConstants.publicKey)")
}
)
@TestState(cache: .sessionUtil, in: dependencies) var mockSessionUtilCache: MockSessionUtilCache! = MockSessionUtilCache(
initialSetup: { cache in
cache
.when { $0.setConfig(for: any(), publicKey: any(), to: any()) }
.thenReturn(())
}
)
@TestState var disposables: [AnyCancellable]! = []
@TestState var error: Error?
@TestState var thread: SessionThread?
// MARK: - a MessageSender dealing with Groups
describe("a MessageSender dealing with Groups") {
// MARK: -- when creating a group
context("when creating a group") {
beforeEach {
var userGroupsConf: UnsafeMutablePointer<config_object>!
var secretKey: [UInt8] = Array(Data(hex: TestConstants.edSecretKey))
_ = user_groups_init(&userGroupsConf, &secretKey, nil, 0, nil)
let userGroupsConfig: SessionUtil.Config = .object(userGroupsConf)
mockSessionUtilCache
.when { $0.config(for: .userGroups, publicKey: any()) }
.thenReturn(Atomic(userGroupsConfig))
}
// MARK: ---- stores the thread in the db
it("stores the thread in the db") {
MessageSender
.createGroup(
name: "Test",
displayPicture: nil,
members: [
("051111111111111111111111111111111111111111111111111111111111111111", nil)
],
using: dependencies
)
.handleEvents(receiveOutput: { result in thread = result })
.mapError { error.setting(to: $0) }
.sinkAndStore(in: &disposables)
expect(error).to(beNil())
expect(thread).toNot(beNil())
let dbValue: SessionThread? = mockStorage.read { db in try SessionThread.fetchOne(db) }
expect(dbValue).to(equal(thread))
expect(dbValue?.id)
.to(equal("03cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"))
expect(dbValue?.variant).to(equal(.group))
expect(dbValue?.creationDateTimestamp).to(equal(1234567890))
expect(dbValue?.shouldBeVisible).to(beTrue())
expect(dbValue?.notificationSound).to(beNil())
expect(dbValue?.mutedUntilTimestamp).to(beNil())
expect(dbValue?.onlyNotifyForMentions).to(beFalse())
expect(dbValue?.pinnedPriority).to(equal(0))
}
// MARK: ---- stores the group in the db
it("stores the group in the db") {
MessageSender
.createGroup(
name: "TestGroupName",
displayPicture: nil,
members: [
("051111111111111111111111111111111111111111111111111111111111111111", nil)
],
using: dependencies
)
.handleEvents(receiveOutput: { result in thread = result })
.mapError { error.setting(to: $0) }
.sinkAndStore(in: &disposables)
expect(error).to(beNil())
expect(thread).toNot(beNil())
let dbValue: ClosedGroup? = mockStorage.read { db in try ClosedGroup.fetchOne(db) }
expect(dbValue?.id)
.to(equal("03cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"))
expect(dbValue?.name).to(equal("TestGroupName"))
expect(dbValue?.formationTimestamp).to(equal(1234567890))
expect(dbValue?.displayPictureUrl).to(beNil())
expect(dbValue?.displayPictureFilename).to(beNil())
expect(dbValue?.displayPictureEncryptionKey).to(beNil())
expect(dbValue?.lastDisplayPictureUpdate).to(equal(1234567890))
expect(dbValue?.groupIdentityPrivateKey?.toHexString())
.to(equal(
"0123456789abcdef0123456789abcdeffedcba9876543210fedcba9876543210" +
"cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece"
))
expect(dbValue?.authData).to(beNil())
expect(dbValue?.invited).to(beFalse())
}
// MARK: ---- stores the group members in the db
it("stores the group members in the db") {
MessageSender
.createGroup(
name: "TestGroupName",
displayPicture: nil,
members: [
("051111111111111111111111111111111111111111111111111111111111111111", nil)
],
using: dependencies
)
.handleEvents(receiveOutput: { result in thread = result })
.mapError { error.setting(to: $0) }
.sinkAndStore(in: &disposables)
expect(error).to(beNil())
expect(thread).toNot(beNil())
expect(mockStorage.read { db in try GroupMember.fetchSet(db) })
.to(equal([
GroupMember(
groupId: "03cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece",
profileId: "051111111111111111111111111111111111111111111111111111111111111111",
role: .standard,
isHidden: false
),
GroupMember(
groupId: "03cbd569f56fb13ea95a3f0c05c331cc24139c0090feb412069dc49fab34406ece",
profileId: "05\(TestConstants.publicKey)",
role: .admin,
isHidden: false
)
]))
}
}
}
}
}

View File

@ -865,7 +865,7 @@ public extension OnionRequestAPI {
}
public extension Cache {
static let onionRequestAPI: CacheInfo.Config<ORAPICacheType, ORAPIImmutableCacheType> = CacheInfo.create(
static let onionRequestAPI: CacheConfig<ORAPICacheType, ORAPIImmutableCacheType> = Dependencies.create(
createInstance: { dependencies in OnionRequestAPI.Cache(using: dependencies) },
mutableInstance: { $0 },
immutableInstance: { $0 }

View File

@ -0,0 +1,74 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Combine
import SessionUtilitiesKit
import Quick
import Nimble
@testable import SessionSnodeKit
class SnodeRequestSpec: QuickSpec {
override class func spec() {
// MARK: Configuration
@TestState var dependencies: TestDependencies! = TestDependencies()
@TestState var batchRequest: HTTP.BatchRequest!
// MARK: - a SnodeRequest
describe("a SnodeRequest") {
// MARK: -- when encoding a HTTP.BatchRequest storage server type endpoint
context("when encoding a HTTP.BatchRequest storage server type endpoint") {
// MARK: ---- successfully encodes a SnodeRequest body
it("successfully encodes a SnodeRequest body") {
batchRequest = HTTP.BatchRequest(
requestsKey: .requests,
requests: [
HTTP.PreparedRequest<NoResponse>(
request: Request<SnodeRequest<TestType>, TestEndpoint>(
method: .post,
server: "testServer",
endpoint: .endpoint,
queryParameters: [:],
headers: [:],
x25519PublicKey: "05\(TestConstants.publicKey)",
body: SnodeRequest<TestType>(
endpoint: .sendMessage,
body: TestType(stringValue: "testValue")
)
),
urlRequest: URLRequest(url: URL(string: "https://www.oxen.io")!),
responseType: NoResponse.self,
timeout: 0
)
]
)
let requestData: Data? = try? JSONEncoder().encode(batchRequest)
let requestJson: [String: [[String: Any]]]? = requestData
.map { try? JSONSerialization.jsonObject(with: $0) as? [String: [[String: Any]]] }
let request: [String: Any]? = requestJson?["requests"]?.first
expect(request?["method"] as? String).to(equal("store"))
expect(request?["params"] as? [String: String]).to(equal(["stringValue": "testValue"]))
}
}
}
}
}
// MARK: - Test Types
fileprivate enum TestEndpoint: EndpointType {
case endpoint
static var name: String { "TestEndpoint" }
static var batchRequestVariant: HTTP.BatchRequest.Child.Variant { .storageServer }
static var excludedSubRequestHeaders: [HTTPHeader] { [] }
var path: String { return "endpoint" }
}
fileprivate struct TestType: Codable, Equatable {
let stringValue: String
}

View File

@ -9,9 +9,7 @@ import Curve25519Kit
// MARK: - Singleton
public extension Singleton {
static let crypto: SingletonInfo.Config<CryptoType> = SingletonInfo.create { _ in
Crypto()
}
static let crypto: SingletonConfig<CryptoType> = Dependencies.create { _ in Crypto() }
}
// MARK: - CryptoType

View File

@ -11,10 +11,10 @@ import SignalCoreKit
// MARK: - Singleton
public extension Singleton {
static let storage: SingletonInfo.Config<Storage> = SingletonInfo.create { dependencies in
static let storage: SingletonConfig<Storage> = Dependencies.create { dependencies in
Storage(using: dependencies)
}
static let scheduler: SingletonInfo.Config<ValueObservationScheduler> = SingletonInfo.create { _ in
static let scheduler: SingletonConfig<ValueObservationScheduler> = Dependencies.create { _ in
AsyncValueObservationScheduler.async(onQueue: .main)
}
}

View File

@ -0,0 +1,48 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - Cache
public class Cache {}
// MARK: - Cache Types
public protocol MutableCacheType {}
public protocol ImmutableCacheType {}
// MARK: - CacheInfo
public class CacheConfig<M, I>: Cache {
public let key: Int
public let createInstance: (Dependencies) -> M
public let mutableInstance: (M) -> MutableCacheType
public let immutableInstance: (M) -> I
fileprivate init(
createInstance: @escaping (Dependencies) -> M,
mutableInstance: @escaping (M) -> MutableCacheType,
immutableInstance: @escaping (M) -> I
) {
self.key = ObjectIdentifier(M.self).hashValue
self.createInstance = createInstance
self.mutableInstance = mutableInstance
self.immutableInstance = immutableInstance
}
}
// MARK: - Creation
public extension Dependencies {
static func create<M, I>(
createInstance: @escaping (Dependencies) -> M,
mutableInstance: @escaping (M) -> MutableCacheType,
immutableInstance: @escaping (M) -> I
) -> CacheConfig<M, I> {
return CacheConfig(
createInstance: createInstance,
mutableInstance: mutableInstance,
immutableInstance: immutableInstance
)
}
}

View File

@ -1,48 +0,0 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - Cache
public class Cache {}
// MARK: - Cache Types
public protocol MutableCacheType {}
public protocol ImmutableCacheType {}
// MARK: - CacheInfo
public enum CacheInfo {
public class Config<M, I>: Cache {
public let key: Int
public let createInstance: (Dependencies) -> M
public let mutableInstance: (M) -> MutableCacheType
public let immutableInstance: (M) -> I
fileprivate init(
createInstance: @escaping (Dependencies) -> M,
mutableInstance: @escaping (M) -> MutableCacheType,
immutableInstance: @escaping (M) -> I
) {
self.key = ObjectIdentifier(M.self).hashValue
self.createInstance = createInstance
self.mutableInstance = mutableInstance
self.immutableInstance = immutableInstance
}
}
}
public extension CacheInfo {
static func create<M, I>(
createInstance: @escaping (Dependencies) -> M,
mutableInstance: @escaping (M) -> MutableCacheType,
immutableInstance: @escaping (M) -> I
) -> CacheInfo.Config<M, I> {
return CacheInfo.Config(
createInstance: createInstance,
mutableInstance: mutableInstance,
immutableInstance: immutableInstance
)
}
}

View File

@ -12,15 +12,15 @@ public class Dependencies {
// MARK: - Subscript Access
public subscript<S>(singleton singleton: SingletonInfo.Config<S>) -> S {
public subscript<S>(singleton singleton: SingletonConfig<S>) -> S {
getValueSettingIfNull(singleton: singleton, &Dependencies.singletonInstances)
}
public subscript<M, I>(cache cache: CacheInfo.Config<M, I>) -> I {
public subscript<M, I>(cache cache: CacheConfig<M, I>) -> I {
getValueSettingIfNull(cache: cache, &Dependencies.cacheInstances)
}
public subscript(defaults defaults: UserDefaultsInfo.Config) -> UserDefaultsType {
public subscript(defaults defaults: UserDefaultsConfig) -> UserDefaultsType {
getValueSettingIfNull(defaults: defaults, &Dependencies.userDefaultsInstances)
}
@ -28,9 +28,7 @@ public class Dependencies {
public var dateNow: Date { Date() }
public var fixedTime: Int { 0 }
public var forceSynchronous: Bool = false
public var asyncExecutions: [Int: [() -> Void]] = [:]
public var forceSynchronous: Bool { false }
// MARK: - Initialization
@ -38,8 +36,14 @@ public class Dependencies {
// MARK: - Functions
public func async(at fixedTime: Int, closure: @escaping () -> Void) {
async(at: TimeInterval(fixedTime), closure: closure)
}
public func async(at timestamp: TimeInterval, closure: @escaping () -> Void) {}
@discardableResult public func mutate<M, I, R>(
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
_ mutation: (inout M) -> R
) -> R {
return Dependencies.cacheInstances.mutate { caches in
@ -49,7 +53,7 @@ public class Dependencies {
}
@discardableResult public func mutate<M, I, R>(
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
_ mutation: (inout M) throws -> R
) throws -> R {
return try Dependencies.cacheInstances.mutate { caches in
@ -61,7 +65,7 @@ public class Dependencies {
// MARK: - Instance upserting
@discardableResult private func getValueSettingIfNull<S>(
singleton: SingletonInfo.Config<S>,
singleton: SingletonConfig<S>,
_ store: inout Atomic<[Int: Any]>
) -> S {
guard let value: S = (store.wrappedValue[singleton.key] as? S) else {
@ -74,7 +78,7 @@ public class Dependencies {
}
@discardableResult private func getValueSettingIfNull<M, I>(
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
_ store: inout Atomic<[Int: MutableCacheType]>
) -> I {
guard let value: M = (store.wrappedValue[cache.key] as? M) else {
@ -88,7 +92,7 @@ public class Dependencies {
}
@discardableResult private func getValueSettingIfNull(
defaults: UserDefaultsInfo.Config,
defaults: UserDefaultsConfig,
_ store: inout Atomic<[Int: UserDefaultsType]>
) -> UserDefaultsType {
guard let value: UserDefaultsType = store.wrappedValue[defaults.key] else {
@ -104,33 +108,33 @@ public class Dependencies {
// MARK: - Storage Setting Convenience
public extension Dependencies {
subscript(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.BoolKey) -> Bool {
subscript(singleton singleton: SingletonConfig<Storage>, key key: Setting.BoolKey) -> Bool {
return self[singleton: singleton]
.read { db in db[key] }
.defaulting(to: false) // Default to false if it doesn't exist
}
subscript(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.DoubleKey) -> Double? {
subscript(singleton singleton: SingletonConfig<Storage>, key key: Setting.DoubleKey) -> Double? {
return self[singleton: singleton].read { db in db[key] }
}
subscript(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.IntKey) -> Int? {
subscript(singleton singleton: SingletonConfig<Storage>, key key: Setting.IntKey) -> Int? {
return self[singleton: singleton].read { db in db[key] }
}
subscript(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.StringKey) -> String? {
subscript(singleton singleton: SingletonConfig<Storage>, key key: Setting.StringKey) -> String? {
return self[singleton: singleton].read { db in db[key] }
}
subscript(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.DateKey) -> Date? {
subscript(singleton singleton: SingletonConfig<Storage>, key key: Setting.DateKey) -> Date? {
return self[singleton: singleton].read { db in db[key] }
}
subscript<T: EnumIntSetting>(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.EnumKey) -> T? {
subscript<T: EnumIntSetting>(singleton singleton: SingletonConfig<Storage>, key key: Setting.EnumKey) -> T? {
return self[singleton: singleton].read { db in db[key] }
}
subscript<T: EnumStringSetting>(singleton singleton: SingletonInfo.Config<Storage>, key key: Setting.EnumKey) -> T? {
subscript<T: EnumStringSetting>(singleton singleton: SingletonConfig<Storage>, key key: Setting.EnumKey) -> T? {
return self[singleton: singleton].read { db in db[key] }
}
}
@ -138,27 +142,27 @@ public extension Dependencies {
// MARK: - UserDefaults Convenience
public extension Dependencies {
subscript(defaults defaults: UserDefaultsInfo.Config, key key: UserDefaultsInfo.BoolKey) -> Bool {
subscript(defaults defaults: UserDefaultsConfig, key key: UserDefaults.BoolKey) -> Bool {
get { return self[defaults: defaults].bool(forKey: key.rawValue) }
set { self[defaults: defaults].set(newValue, forKey: key.rawValue) }
}
subscript(defaults defaults: UserDefaultsInfo.Config, key key: UserDefaultsInfo.DateKey) -> Date? {
subscript(defaults defaults: UserDefaultsConfig, key key: UserDefaults.DateKey) -> Date? {
get { return self[defaults: defaults].object(forKey: key.rawValue) as? Date }
set { self[defaults: defaults].set(newValue, forKey: key.rawValue) }
}
subscript(defaults defaults: UserDefaultsInfo.Config, key key: UserDefaultsInfo.DoubleKey) -> Double {
subscript(defaults defaults: UserDefaultsConfig, key key: UserDefaults.DoubleKey) -> Double {
get { return self[defaults: defaults].double(forKey: key.rawValue) }
set { self[defaults: defaults].set(newValue, forKey: key.rawValue) }
}
subscript(defaults defaults: UserDefaultsInfo.Config, key key: UserDefaultsInfo.IntKey) -> Int {
subscript(defaults defaults: UserDefaultsConfig, key key: UserDefaults.IntKey) -> Int {
get { return self[defaults: defaults].integer(forKey: key.rawValue) }
set { self[defaults: defaults].set(newValue, forKey: key.rawValue) }
}
subscript(defaults defaults: UserDefaultsInfo.Config, key key: UserDefaultsInfo.StringKey) -> String? {
subscript(defaults defaults: UserDefaultsConfig, key key: UserDefaults.StringKey) -> String? {
get { return self[defaults: defaults].string(forKey: key.rawValue) }
set { self[defaults: defaults].set(newValue, forKey: key.rawValue) }
}

View File

@ -0,0 +1,34 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - Singleton
public class Singleton {}
// MARK: - SingletonConfig<S>
public class SingletonConfig<S>: Singleton {
public let key: Int
public let createInstance: (Dependencies) -> S
/// `fileprivate` to hide when accessing via `dependencies[singleton: ]`
fileprivate init(
createInstance: @escaping (Dependencies) -> S
) {
self.key = ObjectIdentifier(S.self).hashValue
self.createInstance = createInstance
}
}
// MARK: - Creation
public extension Dependencies {
static func create<S>(
createInstance: @escaping (Dependencies) -> S
) -> SingletonConfig<S> {
return SingletonConfig(
createInstance: createInstance
)
}
}

View File

@ -1,33 +0,0 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - Singleton
public class Singleton {}
// MARK: - SingletonInfo
public enum SingletonInfo {
public class Config<S>: Singleton {
public let key: Int
public let createInstance: (Dependencies) -> S
fileprivate init(
createInstance: @escaping (Dependencies) -> S
) {
self.key = ObjectIdentifier(S.self).hashValue
self.createInstance = createInstance
}
}
}
public extension SingletonInfo {
static func create<S>(
createInstance: @escaping (Dependencies) -> S
) -> SingletonInfo.Config<S> {
return SingletonInfo.Config(
createInstance: createInstance
)
}
}

View File

@ -0,0 +1,37 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - UserDefaultsStorage
public class UserDefaultsStorage {}
// MARK: - UserDefaultsConfig
public class UserDefaultsConfig: UserDefaultsStorage {
public let key: Int
public let createInstance: (Dependencies) -> UserDefaultsType
/// `fileprivate` to hide when accessing via `dependencies[defaults: ]`
fileprivate init(
identifier: String,
createInstance: @escaping (Dependencies) -> UserDefaultsType
) {
self.key = identifier.hashValue
self.createInstance = createInstance
}
}
// MARK: - Creation
public extension Dependencies {
static func create(
identifier: String,
createInstance: @escaping (Dependencies) -> UserDefaultsType
) -> UserDefaultsConfig {
return UserDefaultsConfig(
identifier: identifier,
createInstance: createInstance
)
}
}

View File

@ -13,7 +13,7 @@ public enum General {
}
public extension Cache {
static let general: CacheInfo.Config<GeneralCacheType, ImmutableGeneralCacheType> = CacheInfo.create(
static let general: CacheConfig<GeneralCacheType, ImmutableGeneralCacheType> = Dependencies.create(
createInstance: { _ in General.Cache() },
mutableInstance: { $0 },
immutableInstance: { $0 }

View File

@ -15,7 +15,7 @@ extension Timer {
// timeInterval for execution and append it to the execution set so the test can
// trigger the logic in a synchronous way)
guard !dependencies.forceSynchronous else {
dependencies.asyncExecutions.appendTo(Int(ceil(dependencies.dateNow.timeIntervalSince1970 + timeInterval))) {
dependencies.async(at: dependencies.dateNow.timeIntervalSince1970 + timeInterval) {
block(timer)
}
return timer

View File

@ -8,7 +8,7 @@ import GRDB
// MARK: - Singleton
public extension Singleton {
static let jobRunner: SingletonInfo.Config<JobRunnerType> = SingletonInfo.create { _ in JobRunner() }
static let jobRunner: SingletonConfig<JobRunnerType> = Dependencies.create { _ in JobRunner() }
}
// MARK: - JobRunnerType

View File

@ -6,9 +6,7 @@ import Combine
// MARK: - Singleton
public extension Singleton {
static let network: SingletonInfo.Config<NetworkType> = SingletonInfo.create { _ in
Network()
}
static let network: SingletonConfig<NetworkType> = Dependencies.create { _ in Network() }
}
// MARK: - NetworkType

View File

@ -88,14 +88,14 @@ public class AppVersion {
// MARK: - UserDefaults Keys
private extension UserDefaultsInfo.StringKey {
private extension UserDefaults.StringKey {
/// The version of the app when it was first launched
static let firstAppVersion: UserDefaultsInfo.StringKey = "kNSUserDefaults_FirstAppVersion"
static let firstAppVersion: UserDefaults.StringKey = "kNSUserDefaults_FirstAppVersion"
/// The version of the app when it was last launched
static let lastAppVersion: UserDefaultsInfo.StringKey = "kNSUserDefaults_LastVersion"
static let lastAppVersion: UserDefaults.StringKey = "kNSUserDefaults_LastVersion"
static let lastCompletedLaunchAppVersion: UserDefaultsInfo.StringKey = "kNSUserDefaults_LastCompletedLaunchAppVersion"
static let lastCompletedLaunchMainAppVersion: UserDefaultsInfo.StringKey = "kNSUserDefaults_LastCompletedLaunchAppVersion_MainApp"
static let lastCompletedLaunchSAEAppVersion: UserDefaultsInfo.StringKey = "kNSUserDefaults_LastCompletedLaunchAppVersion_SAE"
static let lastCompletedLaunchAppVersion: UserDefaults.StringKey = "kNSUserDefaults_LastCompletedLaunchAppVersion"
static let lastCompletedLaunchMainAppVersion: UserDefaults.StringKey = "kNSUserDefaults_LastCompletedLaunchAppVersion_MainApp"
static let lastCompletedLaunchSAEAppVersion: UserDefaults.StringKey = "kNSUserDefaults_LastCompletedLaunchAppVersion_SAE"
}

View File

@ -1,48 +1,16 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - UserDefaultsStorage
public class UserDefaultsStorage {}
public extension UserDefaultsStorage {
static var standard: UserDefaultsInfo.Config = UserDefaultsInfo.create(identifier: "standard") { _ in
static var standard: UserDefaultsConfig = Dependencies.create(identifier: "standard") { _ in
UserDefaults.standard
}
static var appGroup: UserDefaultsInfo.Config = UserDefaultsInfo.create(identifier: UserDefaults.applicationGroup) { _ in
static var appGroup: UserDefaultsConfig = Dependencies.create(identifier: UserDefaults.applicationGroup) { _ in
UserDefaults(suiteName: UserDefaults.applicationGroup)!
}
}
// MARK: - UserDefaultsInfo
public enum UserDefaultsInfo {
public class Config: UserDefaultsStorage {
public let key: Int
public let createInstance: (Dependencies) -> UserDefaultsType
fileprivate init(
identifier: String,
createInstance: @escaping (Dependencies) -> UserDefaultsType
) {
self.key = identifier.hashValue
self.createInstance = createInstance
}
}
}
public extension UserDefaultsInfo {
static func create(
identifier: String,
createInstance: @escaping (Dependencies) -> UserDefaultsType
) -> UserDefaultsInfo.Config {
return UserDefaultsInfo.Config(
identifier: identifier,
createInstance: createInstance
)
}
}
// MARK: - UserDefaultsType
public protocol UserDefaultsType: AnyObject {
@ -85,8 +53,87 @@ public extension UserDefaults {
}
}
// MARK: - UserDefault Values
public extension UserDefaultsInfo {
public extension UserDefaults.BoolKey {
/// Indicates whether the user has synced an initial config message from this device
static let hasSyncedInitialConfiguration: UserDefaults.BoolKey = "hasSyncedConfiguration"
/// Indicates whether the user has seen the suggestion to enable link previews
static let hasSeenLinkPreviewSuggestion: UserDefaults.BoolKey = "hasSeenLinkPreviewSuggestion"
/// Indicates whether the user has seen the IP exposure warning when enabling calls
///
/// **Note:** This is currently not in use (it was decided that it's better to warn the user every time they enable calls instead
/// of just the first time)
static let hasSeenCallIPExposureWarning: UserDefaults.BoolKey = "hasSeenCallIPExposureWarning"
/// Indicates whether the user has seen the missed call tips modal
static let hasSeenCallMissedTips: UserDefaults.BoolKey = "hasSeenCallMissedTips"
/// Indicates whether the user is registered for APNS (ie. "Fast Mode" notifications)
static let isUsingFullAPNs: UserDefaults.BoolKey = "isUsingFullAPNs"
/// Indicates whether the device was unlinked from an account
///
/// **Note:** This doesn't seem to be properly used (we basically just maintain the existing value)
static let wasUnlinked: UserDefaults.BoolKey = "wasUnlinked"
/// Indicates whether the main app is active, this is set to `true` while the app is in the foreground and `false` when
/// the app is in the background
static let isMainAppActive: UserDefaults.BoolKey = "isMainAppActive"
/// Indicates whether there is an ongoing call
static let isCallOngoing: UserDefaults.BoolKey = "isCallOngoing"
}
public extension UserDefaults.DateKey {
/// The date/time when the users profile picture was last uploaded to the server (used to rate-limit re-uploading)
static let lastProfilePictureUpload: UserDefaults.DateKey = "lastProfilePictureUpload"
/// The date/time when the device last updated the default open group room images (used to rate-limit re-downloading)
static let lastOpenGroupImageUpdate: UserDefaults.DateKey = "lastOpenGroupImageUpdate"
/// The date/time when any open group last had a successful poll (used as a fallback date/time if the open group hasn't been polled
/// this session)
static let lastOpen: UserDefaults.DateKey = "lastOpen"
/// The date/time when the last garbage collection was performed (used to rate-limit garbage collection)
static let lastGarbageCollection: UserDefaults.DateKey = "lastGarbageCollection"
/// The date/time when we last subscribed for push notifications (used to rate-limit calling our subscription endpoint)
static let lastPushNotificationSync: UserDefaults.DateKey = "lastPushNotificationSync"
/// The date/time when we received a call pre-offer (used to suppress call notifications which are too old)
static let lastCallPreOffer: UserDefaults.DateKey = "lastCallPreOffer"
}
public extension UserDefaults.DoubleKey {
/// The timestamp when we last uploaded the users push token (used to rate-limit calling our subscription endpoint)
///
/// **Note:** Looks like this replicates the `lastPushNotificationSync` behaviour
static let lastDeviceTokenUpload: UserDefaults.DoubleKey = "lastDeviceTokenUploadTime"
}
public extension UserDefaults.IntKey {
/// The latest hardfork value returned when interacting with a service node
static let hardfork: UserDefaults.IntKey = "hardfork"
/// The latest softfork value returned when interacting with a service node
static let softfork: UserDefaults.IntKey = "softfork"
}
public extension UserDefaults.StringKey {
/// The most recently subscribed APNS token
static let deviceToken: UserDefaults.StringKey = "deviceToken"
/// The warning to show at the top of the app
static let topBannerWarningToShow: UserDefaults.StringKey = "topBannerWarningToShow"
}
// MARK: - Keys
public extension UserDefaults {
struct BoolKey: RawRepresentable, ExpressibleByStringLiteral, Hashable {
public let rawValue: String
@ -137,81 +184,3 @@ public extension UserDefaultsInfo {
public init(extendedGraphemeClusterLiteral value: String) { self.init(value) }
}
}
// MARK: - UserDefault Values
public extension UserDefaultsInfo.BoolKey {
/// Indicates whether the user has synced an initial config message from this device
static let hasSyncedInitialConfiguration: UserDefaultsInfo.BoolKey = "hasSyncedConfiguration"
/// Indicates whether the user has seen the suggestion to enable link previews
static let hasSeenLinkPreviewSuggestion: UserDefaultsInfo.BoolKey = "hasSeenLinkPreviewSuggestion"
/// Indicates whether the user has seen the IP exposure warning when enabling calls
///
/// **Note:** This is currently not in use (it was decided that it's better to warn the user every time they enable calls instead
/// of just the first time)
static let hasSeenCallIPExposureWarning: UserDefaultsInfo.BoolKey = "hasSeenCallIPExposureWarning"
/// Indicates whether the user has seen the missed call tips modal
static let hasSeenCallMissedTips: UserDefaultsInfo.BoolKey = "hasSeenCallMissedTips"
/// Indicates whether the user is registered for APNS (ie. "Fast Mode" notifications)
static let isUsingFullAPNs: UserDefaultsInfo.BoolKey = "isUsingFullAPNs"
/// Indicates whether the device was unlinked from an account
///
/// **Note:** This doesn't seem to be properly used (we basically just maintain the existing value)
static let wasUnlinked: UserDefaultsInfo.BoolKey = "wasUnlinked"
/// Indicates whether the main app is active, this is set to `true` while the app is in the foreground and `false` when
/// the app is in the background
static let isMainAppActive: UserDefaultsInfo.BoolKey = "isMainAppActive"
/// Indicates whether there is an ongoing call
static let isCallOngoing: UserDefaultsInfo.BoolKey = "isCallOngoing"
}
public extension UserDefaultsInfo.DateKey {
/// The date/time when the users profile picture was last uploaded to the server (used to rate-limit re-uploading)
static let lastProfilePictureUpload: UserDefaultsInfo.DateKey = "lastProfilePictureUpload"
/// The date/time when the device last updated the default open group room images (used to rate-limit re-downloading)
static let lastOpenGroupImageUpdate: UserDefaultsInfo.DateKey = "lastOpenGroupImageUpdate"
/// The date/time when any open group last had a successful poll (used as a fallback date/time if the open group hasn't been polled
/// this session)
static let lastOpen: UserDefaultsInfo.DateKey = "lastOpen"
/// The date/time when the last garbage collection was performed (used to rate-limit garbage collection)
static let lastGarbageCollection: UserDefaultsInfo.DateKey = "lastGarbageCollection"
/// The date/time when we last subscribed for push notifications (used to rate-limit calling our subscription endpoint)
static let lastPushNotificationSync: UserDefaultsInfo.DateKey = "lastPushNotificationSync"
/// The date/time when we received a call pre-offer (used to suppress call notifications which are too old)
static let lastCallPreOffer: UserDefaultsInfo.DateKey = "lastCallPreOffer"
}
public extension UserDefaultsInfo.DoubleKey {
/// The timestamp when we last uploaded the users push token (used to rate-limit calling our subscription endpoint)
///
/// **Note:** Looks like this replicates the `lastPushNotificationSync` behaviour
static let lastDeviceTokenUpload: UserDefaultsInfo.DoubleKey = "lastDeviceTokenUploadTime"
}
public extension UserDefaultsInfo.IntKey {
/// The latest hardfork value returned when interacting with a service node
static let hardfork: UserDefaultsInfo.IntKey = "hardfork"
/// The latest softfork value returned when interacting with a service node
static let softfork: UserDefaultsInfo.IntKey = "softfork"
}
public extension UserDefaultsInfo.StringKey {
/// The most recently subscribed APNS token
static let deviceToken: UserDefaultsInfo.StringKey = "deviceToken"
/// The warning to show at the top of the app
static let topBannerWarningToShow: UserDefaultsInfo.StringKey = "topBannerWarningToShow"
}

View File

@ -1737,7 +1737,7 @@ fileprivate enum TestJob: JobExecutor {
}
}
dependencies.asyncExecutions.appendTo(details.completeTime) {
dependencies.async(at: details.completeTime) {
queue.async(using: dependencies) {
completeJob()
}

View File

@ -2,7 +2,6 @@
import Foundation
import Combine
import SessionSnodeKit
import Quick
import Nimble
@ -179,23 +178,20 @@ class BatchRequestSpec: QuickSpec {
// MARK: -- when encoding a storage server type endpoint
context("when encoding a storage server type endpoint") {
// MARK: ---- successfully encodes a SnodeRequest body
it("successfully encodes a SnodeRequest body") {
// MARK: ---- ignores a string body
it("ignores a string body") {
request = HTTP.BatchRequest(
requestsKey: .requests,
requests: [
HTTP.PreparedRequest<NoResponse>(
request: Request<SnodeRequest<TestType>, TestEndpoint2>(
request: Request<String, TestEndpoint2>(
method: .get,
server: "testServer",
endpoint: .endpoint2,
queryParameters: [:],
headers: [:],
x25519PublicKey: "05\(TestConstants.publicKey)",
body: SnodeRequest<TestType>(
endpoint: .sendMessage,
body: TestType(stringValue: "testValue")
)
body: "testValue"
),
urlRequest: URLRequest(url: URL(string: "https://www.oxen.io")!),
responseType: NoResponse.self,
@ -207,9 +203,70 @@ class BatchRequestSpec: QuickSpec {
let requestData: Data? = try? JSONEncoder().encode(request)
let requestJson: [String: [[String: Any]]]? = requestData
.map { try? JSONSerialization.jsonObject(with: $0) as? [String: [[String: Any]]] }
let request: [String: Any]? = requestJson?["requests"]?.first
expect(request?["method"] as? String).to(equal("store"))
expect(request?["params"] as? [String: String]).to(equal(["stringValue": "testValue"]))
let requests: [[String: Any]]? = requestJson?["requests"]
expect(requests?.count).to(equal(1))
expect(requests?.first?.count).to(equal(0))
}
// MARK: ---- ignores a byte body
it("ignores a byte body") {
request = HTTP.BatchRequest(
requestsKey: .requests,
requests: [
HTTP.PreparedRequest<NoResponse>(
request: Request<[UInt8], TestEndpoint2>(
method: .get,
server: "testServer",
endpoint: .endpoint2,
queryParameters: [:],
headers: [:],
x25519PublicKey: "05\(TestConstants.publicKey)",
body: [1, 2, 3]
),
urlRequest: URLRequest(url: URL(string: "https://www.oxen.io")!),
responseType: NoResponse.self,
timeout: 0
)
]
)
let requestData: Data? = try? JSONEncoder().encode(request)
let requestJson: [String: [[String: Any]]]? = requestData
.map { try? JSONSerialization.jsonObject(with: $0) as? [String: [[String: Any]]] }
let requests: [[String: Any]]? = requestJson?["requests"]
expect(requests?.count).to(equal(1))
expect(requests?.first?.count).to(equal(0))
}
// MARK: ---- successfully encodes a JSON body
it("successfully encodes a JSON body") {
request = HTTP.BatchRequest(
requestsKey: .requests,
requests: [
HTTP.PreparedRequest<NoResponse>(
request: Request<TestType, TestEndpoint2>(
method: .get,
server: "testServer",
endpoint: .endpoint2,
queryParameters: [:],
headers: [:],
x25519PublicKey: "05\(TestConstants.publicKey)",
body: TestType(stringValue: "testValue")
),
urlRequest: URLRequest(url: URL(string: "https://www.oxen.io")!),
responseType: NoResponse.self,
timeout: 0
)
]
)
let requestData: Data? = try? JSONEncoder().encode(request)
let requestJson: [String: [[String: Any]]]? = requestData
.map { try? JSONSerialization.jsonObject(with: $0) as? [String: [[String: Any]]] }
let requests: [[String: Any]]? = requestJson?["requests"]
expect(requests?.count).to(equal(1))
expect(requests?.first as? [String: String])
.to(equal(["stringValue": "testValue"]))
}
}
}

View File

@ -12,29 +12,29 @@ public class TestDependencies: Dependencies {
// MARK: - Subscript Access
override public subscript<S>(singleton singleton: SingletonInfo.Config<S>) -> S {
override public subscript<S>(singleton singleton: SingletonConfig<S>) -> S {
return getValueSettingIfNull(singleton: singleton, &singletonInstances)
}
public subscript<S>(singleton singleton: SingletonInfo.Config<S>) -> S? {
public subscript<S>(singleton singleton: SingletonConfig<S>) -> S? {
get { return (singletonInstances[singleton.key] as? S) }
set { singletonInstances[singleton.key] = newValue }
}
override public subscript<M, I>(cache cache: CacheInfo.Config<M, I>) -> I {
override public subscript<M, I>(cache cache: CacheConfig<M, I>) -> I {
return getValueSettingIfNull(cache: cache, &cacheInstances)
}
public subscript<M, I>(cache cache: CacheInfo.Config<M, I>) -> M? {
public subscript<M, I>(cache cache: CacheConfig<M, I>) -> M? {
get { return (cacheInstances[cache.key] as? M) }
set { cacheInstances[cache.key] = newValue.map { cache.mutableInstance($0) } }
}
override public subscript(defaults defaults: UserDefaultsInfo.Config) -> UserDefaultsType {
override public subscript(defaults defaults: UserDefaultsConfig) -> UserDefaultsType {
return getValueSettingIfNull(defaults: defaults, &defaultsInstances)
}
public subscript(defaults defaults: UserDefaultsInfo.Config) -> UserDefaultsType? {
public subscript(defaults defaults: UserDefaultsConfig) -> UserDefaultsType? {
get { return defaultsInstances[defaults.key] }
set { defaultsInstances[defaults.key] = newValue }
}
@ -52,6 +52,14 @@ public class TestDependencies: Dependencies {
get { (_fixedTime.wrappedValue ?? 0) }
set { _fixedTime.mutate { $0 = newValue } }
}
public var _forceSynchronous: Bool = false
override public var forceSynchronous: Bool {
get { _forceSynchronous }
set { _forceSynchronous = newValue }
}
private var asyncExecutions: [Int: [() -> Void]] = [:]
// MARK: - Initialization
@ -63,8 +71,12 @@ public class TestDependencies: Dependencies {
// MARK: - Functions
override public func async(at timestamp: TimeInterval, closure: @escaping () -> Void) {
asyncExecutions.append(closure, toArrayOn: Int(ceil(timestamp)))
}
@discardableResult override public func mutate<M, I, R>(
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
_ mutation: (inout M) -> R
) -> R {
var value: M = ((cacheInstances[cache.key] as? M) ?? cache.createInstance(self))
@ -72,7 +84,7 @@ public class TestDependencies: Dependencies {
}
@discardableResult override public func mutate<M, I, R>(
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
_ mutation: (inout M) throws -> R
) throws -> R {
var value: M = ((cacheInstances[cache.key] as? M) ?? cache.createInstance(self))
@ -99,7 +111,7 @@ public class TestDependencies: Dependencies {
// MARK: - Instance upserting
@discardableResult private func getValueSettingIfNull<S>(
singleton: SingletonInfo.Config<S>,
singleton: SingletonConfig<S>,
_ store: inout [Int: Any]
) -> S {
guard let value: S = (store[singleton.key] as? S) else {
@ -112,7 +124,7 @@ public class TestDependencies: Dependencies {
}
@discardableResult private func getValueSettingIfNull<M, I>(
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
_ store: inout [Int: MutableCacheType]
) -> I {
guard let value: M = (store[cache.key] as? M) else {
@ -126,7 +138,7 @@ public class TestDependencies: Dependencies {
}
@discardableResult private func getValueSettingIfNull(
defaults: UserDefaultsInfo.Config,
defaults: UserDefaultsConfig,
_ store: inout [Int: (any UserDefaultsType)]
) -> UserDefaultsType {
guard let value: UserDefaultsType = store[defaults.key] else {
@ -144,7 +156,7 @@ public class TestDependencies: Dependencies {
internal extension TestState {
init<M, I>(
wrappedValue: @escaping @autoclosure () -> T?,
cache: CacheInfo.Config<M, I>,
cache: CacheConfig<M, I>,
in dependencies: @escaping @autoclosure () -> TestDependencies?
) where T: MutableCacheType {
self.init(wrappedValue: {
@ -157,7 +169,7 @@ internal extension TestState {
init<S>(
wrappedValue: @escaping @autoclosure () -> T?,
singleton: SingletonInfo.Config<S>,
singleton: SingletonConfig<S>,
in dependencies: @escaping @autoclosure () -> TestDependencies?
) {
self.init(wrappedValue: {
@ -170,7 +182,7 @@ internal extension TestState {
init(
wrappedValue: @escaping @autoclosure () -> T?,
defaults: UserDefaultsInfo.Config,
defaults: UserDefaultsConfig,
in dependencies: @escaping @autoclosure () -> TestDependencies?
) where T: UserDefaultsType {
self.init(wrappedValue: {