From d24c0f69d7a4958303ae6ccaed2e4b6b91a55a0c Mon Sep 17 00:00:00 2001 From: jguz-pubnub Date: Mon, 8 Apr 2024 15:44:23 +0200 Subject: [PATCH] feat(retry): moving retry logic away from EventEngine --- PubNub.xcodeproj/project.pbxproj | 72 ++- .../Effects/DelayedHeartbeatEffect.swift | 52 -- .../Effects/PresenceEffectFactory.swift | 13 - .../Helpers/PresenceHeartbeatRequest.swift | 27 +- .../EventEngine/Presence/Presence.swift | 13 - .../Presence/PresenceTransition.swift | 34 +- .../Effects/SubscribeEffectFactory.swift | 29 -- .../Subscribe/Effects/SubscribeEffects.swift | 99 ---- .../Subscribe/Helpers/SubscribeRequest.swift | 26 +- .../EventEngine/Subscribe/Subscribe.swift | 34 -- .../Subscribe/SubscribeTransition.swift | 99 +--- .../PubNub/Networking/Request/Request.swift | 1 + .../Subscription/SubscriptionSession.swift | 18 +- ...ubNubPresenceEngineContractTestSteps.swift | 7 - ...NubSubscribeEngineContractTestsSteps.swift | 25 +- .../DelayedHeartbeatEffectTests.swift | 132 ----- .../Presence/PresenceTransitionTests.swift | 197 +------- .../Subscribe/SubscribeEffectsTests.swift | 285 ----------- .../Subscribe/SubscribeRequestTests.swift | 64 --- .../Subscribe/SubscribeTransitionTests.swift | 470 +----------------- .../Routers/SubscribeRouterTests.swift | 2 +- .../SubscribeSessionFactoryTests.swift | 2 +- 22 files changed, 85 insertions(+), 1616 deletions(-) delete mode 100644 Sources/PubNub/EventEngine/Presence/Effects/DelayedHeartbeatEffect.swift delete mode 100644 Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift delete mode 100644 Tests/PubNubTests/EventEngine/Subscribe/SubscribeRequestTests.swift diff --git a/PubNub.xcodeproj/project.pbxproj b/PubNub.xcodeproj/project.pbxproj index 3c42f42f..c46b280b 100644 --- a/PubNub.xcodeproj/project.pbxproj +++ b/PubNub.xcodeproj/project.pbxproj @@ -384,14 +384,12 @@ 3D389FF22B35AF4A006928E7 /* LeaveEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FD92B35AF4A006928E7 /* LeaveEffect.swift */; }; 3D389FF32B35AF4A006928E7 /* WaitEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FDA2B35AF4A006928E7 /* WaitEffect.swift */; }; 3D389FF42B35AF4A006928E7 /* PresenceEffectFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FDB2B35AF4A006928E7 /* PresenceEffectFactory.swift */; }; - 3D389FF52B35AF4A006928E7 /* DelayedHeartbeatEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FDC2B35AF4A006928E7 /* DelayedHeartbeatEffect.swift */; }; 3D389FF62B35AF4A006928E7 /* PresenceLeaveRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FDE2B35AF4A006928E7 /* PresenceLeaveRequest.swift */; }; 3D389FF72B35AF4A006928E7 /* PresenceHeartbeatRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FDF2B35AF4A006928E7 /* PresenceHeartbeatRequest.swift */; }; 3D389FF82B35AF4A006928E7 /* PresenceInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FE02B35AF4A006928E7 /* PresenceInput.swift */; }; 3D38A00B2B35AF6A006928E7 /* DispatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FFA2B35AF6A006928E7 /* DispatcherTests.swift */; }; 3D38A00C2B35AF6A006928E7 /* SubscribeInputTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FFC2B35AF6A006928E7 /* SubscribeInputTests.swift */; }; 3D38A00D2B35AF6A006928E7 /* EmitMessagesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FFD2B35AF6A006928E7 /* EmitMessagesTests.swift */; }; - 3D38A00E2B35AF6A006928E7 /* SubscribeRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FFE2B35AF6A006928E7 /* SubscribeRequestTests.swift */; }; 3D38A00F2B35AF6A006928E7 /* EmitStatusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D389FFF2B35AF6A006928E7 /* EmitStatusTests.swift */; }; 3D38A0102B35AF6B006928E7 /* SubscribeEffectsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0002B35AF6A006928E7 /* SubscribeEffectsTests.swift */; }; 3D38A0112B35AF6B006928E7 /* SubscribeTransitionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0012B35AF6A006928E7 /* SubscribeTransitionTests.swift */; }; @@ -399,7 +397,6 @@ 3D38A0132B35AF6B006928E7 /* HeartbeatEffectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0042B35AF6A006928E7 /* HeartbeatEffectTests.swift */; }; 3D38A0142B35AF6B006928E7 /* PresenceTransitionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0052B35AF6A006928E7 /* PresenceTransitionTests.swift */; }; 3D38A0152B35AF6B006928E7 /* LeaveEffectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0062B35AF6A006928E7 /* LeaveEffectTests.swift */; }; - 3D38A0162B35AF6B006928E7 /* DelayedHeartbeatEffectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0072B35AF6A006928E7 /* DelayedHeartbeatEffectTests.swift */; }; 3D38A0172B35AF6B006928E7 /* EffectInvocation+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A0092B35AF6A006928E7 /* EffectInvocation+Equatable.swift */; }; 3D38A0182B35AF6B006928E7 /* EventEngineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A00A2B35AF6A006928E7 /* EventEngineTests.swift */; }; 3D38A01D2B35AFBE006928E7 /* PubNubSubscribeEngineContractTestsSteps.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D38A01A2B35AFBE006928E7 /* PubNubSubscribeEngineContractTestsSteps.swift */; }; @@ -980,14 +977,12 @@ 3D389FD92B35AF4A006928E7 /* LeaveEffect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaveEffect.swift; sourceTree = ""; }; 3D389FDA2B35AF4A006928E7 /* WaitEffect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WaitEffect.swift; sourceTree = ""; }; 3D389FDB2B35AF4A006928E7 /* PresenceEffectFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceEffectFactory.swift; sourceTree = ""; }; - 3D389FDC2B35AF4A006928E7 /* DelayedHeartbeatEffect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DelayedHeartbeatEffect.swift; sourceTree = ""; }; 3D389FDE2B35AF4A006928E7 /* PresenceLeaveRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceLeaveRequest.swift; sourceTree = ""; }; 3D389FDF2B35AF4A006928E7 /* PresenceHeartbeatRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceHeartbeatRequest.swift; sourceTree = ""; }; 3D389FE02B35AF4A006928E7 /* PresenceInput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceInput.swift; sourceTree = ""; }; 3D389FFA2B35AF6A006928E7 /* DispatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatcherTests.swift; sourceTree = ""; }; 3D389FFC2B35AF6A006928E7 /* SubscribeInputTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscribeInputTests.swift; sourceTree = ""; }; 3D389FFD2B35AF6A006928E7 /* EmitMessagesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmitMessagesTests.swift; sourceTree = ""; }; - 3D389FFE2B35AF6A006928E7 /* SubscribeRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscribeRequestTests.swift; sourceTree = ""; }; 3D389FFF2B35AF6A006928E7 /* EmitStatusTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmitStatusTests.swift; sourceTree = ""; }; 3D38A0002B35AF6A006928E7 /* SubscribeEffectsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscribeEffectsTests.swift; sourceTree = ""; }; 3D38A0012B35AF6A006928E7 /* SubscribeTransitionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscribeTransitionTests.swift; sourceTree = ""; }; @@ -995,7 +990,6 @@ 3D38A0042B35AF6A006928E7 /* HeartbeatEffectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeartbeatEffectTests.swift; sourceTree = ""; }; 3D38A0052B35AF6A006928E7 /* PresenceTransitionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceTransitionTests.swift; sourceTree = ""; }; 3D38A0062B35AF6A006928E7 /* LeaveEffectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaveEffectTests.swift; sourceTree = ""; }; - 3D38A0072B35AF6A006928E7 /* DelayedHeartbeatEffectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DelayedHeartbeatEffectTests.swift; sourceTree = ""; }; 3D38A0092B35AF6A006928E7 /* EffectInvocation+Equatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EffectInvocation+Equatable.swift"; sourceTree = ""; }; 3D38A00A2B35AF6A006928E7 /* EventEngineTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventEngineTests.swift; sourceTree = ""; }; 3D38A01A2B35AFBE006928E7 /* PubNubSubscribeEngineContractTestsSteps.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PubNubSubscribeEngineContractTestsSteps.swift; sourceTree = ""; }; @@ -2074,7 +2068,6 @@ 3D389FD92B35AF4A006928E7 /* LeaveEffect.swift */, 3D389FDA2B35AF4A006928E7 /* WaitEffect.swift */, 3D389FDB2B35AF4A006928E7 /* PresenceEffectFactory.swift */, - 3D389FDC2B35AF4A006928E7 /* DelayedHeartbeatEffect.swift */, ); path = Effects; sourceTree = ""; @@ -2106,7 +2099,6 @@ children = ( 3D389FFC2B35AF6A006928E7 /* SubscribeInputTests.swift */, 3D389FFD2B35AF6A006928E7 /* EmitMessagesTests.swift */, - 3D389FFE2B35AF6A006928E7 /* SubscribeRequestTests.swift */, 3D389FFF2B35AF6A006928E7 /* EmitStatusTests.swift */, 3D38A0002B35AF6A006928E7 /* SubscribeEffectsTests.swift */, 3D38A0012B35AF6A006928E7 /* SubscribeTransitionTests.swift */, @@ -2121,7 +2113,6 @@ 3D38A0042B35AF6A006928E7 /* HeartbeatEffectTests.swift */, 3D38A0052B35AF6A006928E7 /* PresenceTransitionTests.swift */, 3D38A0062B35AF6A006928E7 /* LeaveEffectTests.swift */, - 3D38A0072B35AF6A006928E7 /* DelayedHeartbeatEffectTests.swift */, ); path = Presence; sourceTree = ""; @@ -2827,7 +2818,7 @@ attributes = { LastSwiftMigration = 9999; LastSwiftUpdateCheck = 1340; - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1530; ORGANIZATIONNAME = PubNub; TargetAttributes = { 358B890A284D206B00DB0F3D = { @@ -3493,7 +3484,6 @@ 35E71C3C2490678E0032A991 /* PubNubPresence.swift in Sources */, 35D8D4CD22EB90F1001B07D9 /* Int+PubNub.swift in Sources */, 35B3824A233AAB8C0028803F /* JSONCodable.swift in Sources */, - 3D389FF52B35AF4A006928E7 /* DelayedHeartbeatEffect.swift in Sources */, 35599792230A3F11000BCFD1 /* Thread+PubNub.swift in Sources */, 3D389FEF2B35AF4A006928E7 /* Presence.swift in Sources */, 3DB925862B7AA75F001B7E90 /* EntitySubscribable.swift in Sources */, @@ -3580,7 +3570,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( - 3D38A0162B35AF6B006928E7 /* DelayedHeartbeatEffectTests.swift in Sources */, 3558069C231303D9005CDD92 /* AutomaticRetryTests.swift in Sources */, 35D973542857BBFE001A44DC /* FlatJSONCodable+Test.swift in Sources */, 35FE93B922EE44F70051C455 /* MockURLSession.swift in Sources */, @@ -3633,7 +3622,6 @@ 35D8D4CB22EB84B4001B07D9 /* AtomicTests.swift in Sources */, 3D38A0172B35AF6B006928E7 /* EffectInvocation+Equatable.swift in Sources */, 3D38A0102B35AF6B006928E7 /* SubscribeEffectsTests.swift in Sources */, - 3D38A00E2B35AF6A006928E7 /* SubscribeRequestTests.swift in Sources */, 3D38A0142B35AF6B006928E7 /* PresenceTransitionTests.swift in Sources */, OBJ_49 /* PubNubTests.swift in Sources */, 35CF549E248D913A0099FE81 /* ObjectsUUIDRouterTests.swift in Sources */, @@ -3748,6 +3736,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PLATFORM_DIR)/Developer/Library/Frameworks", @@ -3783,6 +3772,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PLATFORM_DIR)/Developer/Library/Frameworks", @@ -3825,10 +3815,12 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -3848,6 +3840,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.pubnub.swift.PubNubUser; @@ -3878,10 +3871,12 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -3897,6 +3892,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17"; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.pubnub.swift.PubNubUser; @@ -3921,6 +3917,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GCC_DYNAMIC_NO_PIC = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -3948,6 +3945,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -3980,10 +3978,12 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -4003,6 +4003,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.pubnub.swift.PubNubSpace; @@ -4035,10 +4036,12 @@ CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -4054,6 +4057,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17"; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.pubnub.swift.PubNubSpace; @@ -4079,6 +4083,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GCC_DYNAMIC_NO_PIC = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4113,6 +4118,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4150,10 +4156,12 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -4173,6 +4181,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.pubnub.swift.PubNubMembership; @@ -4204,10 +4213,12 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -4223,6 +4234,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17"; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.pubnub.swift.PubNubMembership; @@ -4247,6 +4259,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GCC_DYNAMIC_NO_PIC = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4282,6 +4295,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4310,6 +4324,7 @@ 359152A622BA9F380048842D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4321,6 +4336,7 @@ 359152A722BA9F380048842D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4338,6 +4354,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GCC_DYNAMIC_NO_PIC = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4365,6 +4382,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4391,6 +4409,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GCC_DYNAMIC_NO_PIC = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4425,6 +4444,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4457,6 +4477,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GCC_DYNAMIC_NO_PIC = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4492,6 +4513,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; @@ -4539,6 +4561,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4581,6 +4604,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4623,6 +4647,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4666,6 +4691,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4692,8 +4718,10 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PLATFORM_DIR)/Developer/Library/Frameworks", @@ -4707,6 +4735,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14"; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4733,8 +4762,10 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; + ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PLATFORM_DIR)/Developer/Library/Frameworks", @@ -4748,6 +4779,7 @@ ); MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 7.1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14"; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4792,6 +4824,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = YES; @@ -4810,8 +4843,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MACOSX_DEPLOYMENT_TARGET = 10.11; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; ONLY_ACTIVE_ARCH = YES; OTHER_SWIFT_FLAGS = "-DXcode"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4819,7 +4851,7 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE DEBUG"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 12.0; USE_HEADERMAP = NO; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -4850,6 +4882,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -4865,8 +4898,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MACOSX_DEPLOYMENT_TARGET = 10.11; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; OTHER_SWIFT_FLAGS = "-DXcode"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; @@ -4874,7 +4906,7 @@ SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 12.0; USE_HEADERMAP = NO; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -4887,6 +4919,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -4923,6 +4956,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/Sources/PubNub/EventEngine/Presence/Effects/DelayedHeartbeatEffect.swift b/Sources/PubNub/EventEngine/Presence/Effects/DelayedHeartbeatEffect.swift deleted file mode 100644 index c9c266e2..00000000 --- a/Sources/PubNub/EventEngine/Presence/Effects/DelayedHeartbeatEffect.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// DelayedHeartbeatEffect.swift -// -// Copyright (c) PubNub Inc. -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. -// - -import Foundation - -class DelayedHeartbeatEffect: EffectHandler { - private let request: PresenceHeartbeatRequest - private let reason: PubNubError - private let timerEffect: TimerEffect? - - init( - request: PresenceHeartbeatRequest, - retryAttempt: Int, - reason: PubNubError - ) { - self.request = request - self.reason = reason - self.timerEffect = TimerEffect(interval: request.reconnectionDelay(dueTo: reason, retryAttempt: retryAttempt)) - } - - func performTask(completionBlock: @escaping ([Presence.Event]) -> Void) { - guard let timerEffect = timerEffect else { - completionBlock([.heartbeatGiveUp(error: reason)]); return - } - timerEffect.performTask { [weak self] _ in - self?.request.execute { result in - switch result { - case .success: - completionBlock([.heartbeatSuccess]) - case .failure(let error): - completionBlock([.heartbeatFailed(error: error)]) - } - } - } - } - - func cancelTask() { - timerEffect?.cancelTask() - request.cancel() - } - - deinit { - cancelTask() - } -} diff --git a/Sources/PubNub/EventEngine/Presence/Effects/PresenceEffectFactory.swift b/Sources/PubNub/EventEngine/Presence/Effects/PresenceEffectFactory.swift index f3ff97c8..fc3ebbcc 100644 --- a/Sources/PubNub/EventEngine/Presence/Effects/PresenceEffectFactory.swift +++ b/Sources/PubNub/EventEngine/Presence/Effects/PresenceEffectFactory.swift @@ -41,19 +41,6 @@ class PresenceEffectFactory: EffectHandlerFactory { sessionResponseQueue: sessionResponseQueue ) ) - case let .delayedHeartbeat(channels, groups, retryAttempt, reason): - return DelayedHeartbeatEffect( - request: PresenceHeartbeatRequest( - channels: channels, - groups: groups, - channelStates: presenceStateContainer.getStates(forChannels: channels), - configuration: dependencies.value.configuration, - session: session, - sessionResponseQueue: sessionResponseQueue - ), - retryAttempt: retryAttempt, - reason: reason - ) case let .leave(channels, groups): return LeaveEffect( request: PresenceLeaveRequest( diff --git a/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift b/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift index 0ced846c..3e68be06 100644 --- a/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift +++ b/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift @@ -45,7 +45,7 @@ class PresenceHeartbeatRequest { ) request = session.request( with: PresenceRouter(endpoint, configuration: configuration), - requestOperator: nil + requestOperator: configuration.automaticRetry?.retryOperator(for: .presence) ) request?.validate().response(on: sessionResponseQueue, decoder: GenericServiceResponseDecoder()) { result in switch result { @@ -60,29 +60,4 @@ class PresenceHeartbeatRequest { func cancel() { request?.cancel(PubNubError(.clientCancelled)) } - - func reconnectionDelay(dueTo error: PubNubError, retryAttempt: Int) -> TimeInterval? { - guard let automaticRetry = configuration.automaticRetry else { - return nil - } - guard automaticRetry.retryOperator(for: .presence) != nil else { - return nil - } - guard automaticRetry.retryLimit > retryAttempt else { - return nil - } - guard let underlyingError = error.underlying else { - return automaticRetry.policy.delay(for: retryAttempt) - } - guard let urlResponse = error.affected.findFirst(by: PubNubError.AffectedValue.response) else { - return nil - } - - let shouldRetry = automaticRetry.shouldRetry( - response: urlResponse, - error: underlyingError - ) - - return shouldRetry ? automaticRetry.policy.delay(for: retryAttempt) : nil - } } diff --git a/Sources/PubNub/EventEngine/Presence/Presence.swift b/Sources/PubNub/EventEngine/Presence/Presence.swift index 2edc2efa..c74be773 100644 --- a/Sources/PubNub/EventEngine/Presence/Presence.swift +++ b/Sources/PubNub/EventEngine/Presence/Presence.swift @@ -42,12 +42,6 @@ extension Presence { let input: PresenceInput } - struct HeartbeatReconnecting: PresenceState { - let input: PresenceInput - let retryAttempt: Int - let error: PubNubError - } - struct HeartbeatFailed: PresenceState { let input: PresenceInput let error: PubNubError @@ -74,7 +68,6 @@ extension Presence { case timesUp case heartbeatSuccess case heartbeatFailed(error: PubNubError) - case heartbeatGiveUp(error: PubNubError) } } @@ -90,20 +83,16 @@ extension Presence { enum Invocation: AnyEffectInvocation { case heartbeat(channels: [String], groups: [String]) case leave(channels: [String], groups: [String]) - case delayedHeartbeat(channels: [String], groups: [String], retryAttempt: Int, error: PubNubError) case wait // swiftlint:disable:next nesting enum Cancellable: AnyCancellableInvocation { case wait - case delayedHeartbeat var id: String { switch self { case .wait: return "Presence.ScheduleNextHeartbeat" - case .delayedHeartbeat: - return "Presence.HeartbeatReconnect" } } } @@ -114,8 +103,6 @@ extension Presence { return "Presence.Heartbeat" case .wait: return Cancellable.wait.id - case .delayedHeartbeat: - return Cancellable.delayedHeartbeat.id case .leave: return "Presence.Leave" } diff --git a/Sources/PubNub/EventEngine/Presence/PresenceTransition.swift b/Sources/PubNub/EventEngine/Presence/PresenceTransition.swift index fc8f7516..a5fc2a0e 100644 --- a/Sources/PubNub/EventEngine/Presence/PresenceTransition.swift +++ b/Sources/PubNub/EventEngine/Presence/PresenceTransition.swift @@ -28,11 +28,9 @@ class PresenceTransition: TransitionProtocol { case .left: return !(state is Presence.HeartbeatInactive) case .heartbeatSuccess: - return state is Presence.Heartbeating || state is Presence.HeartbeatReconnecting + return state is Presence.Heartbeating case .heartbeatFailed: - return state is Presence.Heartbeating || state is Presence.HeartbeatReconnecting - case .heartbeatGiveUp: - return state is Presence.HeartbeatReconnecting + return state is Presence.Heartbeating case .timesUp: return state is Presence.HeartbeatCooldown case .leftAll: @@ -51,11 +49,6 @@ class PresenceTransition: TransitionProtocol { channels: state.channels, groups: state.input.groups ))] - case let state as Presence.HeartbeatReconnecting: - return [.managed(.delayedHeartbeat( - channels: state.channels, groups: state.groups, - retryAttempt: state.retryAttempt, error: state.error - ))] case is Presence.HeartbeatCooldown: return [.managed(.wait)] default: @@ -67,8 +60,6 @@ class PresenceTransition: TransitionProtocol { switch state { case is Presence.HeartbeatCooldown: return [.cancel(.wait)] - case is Presence.HeartbeatReconnecting: - return [.cancel(.delayedHeartbeat)] default: return [] } @@ -85,9 +76,7 @@ class PresenceTransition: TransitionProtocol { case .heartbeatSuccess: results = heartbeatSuccessTransition(from: state) case let .heartbeatFailed(error): - results = heartbeatReconnectingTransition(from: state, dueTo: error) - case let .heartbeatGiveUp(error): - results = heartbeatReconnectingGiveUpTransition(from: state, dueTo: error) + results = heartbeatFailedTransition(from: state, dueTo: error) case .timesUp: results = heartbeatingTransition(from: state) case .leftAll: @@ -156,22 +145,7 @@ fileprivate extension PresenceTransition { } fileprivate extension PresenceTransition { - func heartbeatReconnectingTransition( - from state: State, - dueTo error: PubNubError - ) -> TransitionResult { - return TransitionResult( - state: Presence.HeartbeatReconnecting( - input: state.input, - retryAttempt: ((state as? Presence.HeartbeatReconnecting)?.retryAttempt ?? -1) + 1, - error: error - ) - ) - } -} - -fileprivate extension PresenceTransition { - func heartbeatReconnectingGiveUpTransition( + func heartbeatFailedTransition( from state: State, dueTo error: PubNubError ) -> TransitionResult { diff --git a/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffectFactory.swift b/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffectFactory.swift index 26085ab6..76e07b80 100644 --- a/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffectFactory.swift +++ b/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffectFactory.swift @@ -45,20 +45,6 @@ class SubscribeEffectFactory: EffectHandlerFactory { sessionResponseQueue: sessionResponseQueue ), listeners: dependencies.value.listeners ) - case let .handshakeReconnect(channels, groups, retryAttempt, reason): - return HandshakeReconnectEffect( - request: SubscribeRequest( - configuration: dependencies.value.configuration, - channels: channels, - groups: groups, - channelStates: presenceStateContainer.getStates(forChannels: channels), - timetoken: 0, - session: session, - sessionResponseQueue: sessionResponseQueue - ), listeners: dependencies.value.listeners, - error: reason, - retryAttempt: retryAttempt - ) case let .receiveMessages(channels, groups, cursor): return ReceivingEffect( request: SubscribeRequest( @@ -72,21 +58,6 @@ class SubscribeEffectFactory: EffectHandlerFactory { sessionResponseQueue: sessionResponseQueue ), listeners: dependencies.value.listeners ) - case let .receiveReconnect(channels, groups, cursor, retryAttempt, reason): - return ReceiveReconnectEffect( - request: SubscribeRequest( - configuration: dependencies.value.configuration, - channels: channels, - groups: groups, - channelStates: [:], - timetoken: cursor.timetoken, - region: cursor.region, - session: session, - sessionResponseQueue: sessionResponseQueue - ), listeners: dependencies.value.listeners, - error: reason, - retryAttempt: retryAttempt - ) case let .emitMessages(messages, cursor): return EmitMessagesEffect( messages: messages, diff --git a/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffects.swift b/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffects.swift index 3df7a8ca..02035957 100644 --- a/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffects.swift +++ b/Sources/PubNub/EventEngine/Subscribe/Effects/SubscribeEffects.swift @@ -65,105 +65,6 @@ class ReceivingEffect: EffectHandler { } } -// MARK: - HandshakeReconnectEffect - -class HandshakeReconnectEffect: EffectHandler { - private let subscribeEffect: SubscribeEffect - private let timerEffect: TimerEffect? - private let error: PubNubError - - init( - request: SubscribeRequest, - listeners: [BaseSubscriptionListener], - error: PubNubError, - retryAttempt: Int - ) { - self.timerEffect = TimerEffect(interval: request.reconnectionDelay( - dueTo: error, - retryAttempt: retryAttempt - )) - self.subscribeEffect = SubscribeEffect( - request: request, - listeners: listeners, - onResponseReceived: { .handshakeReconnectSuccess(cursor: $0.cursor) }, - onErrorReceived: { .handshakeReconnectFailure(error: $0) } - ) - self.error = error - } - - func performTask(completionBlock: @escaping ([Subscribe.Event]) -> Void) { - guard let timerEffect = timerEffect else { - completionBlock([.handshakeReconnectGiveUp(error: error)]); return - } - timerEffect.performTask { [weak self] _ in - self?.subscribeEffect.performTask(completionBlock: completionBlock) - } - } - - func cancelTask() { - timerEffect?.cancelTask() - subscribeEffect.cancelTask() - } - - deinit { - cancelTask() - } -} - -// MARK: - ReceiveReconnectEffect - -class ReceiveReconnectEffect: EffectHandler { - private let subscribeEffect: SubscribeEffect - private let timerEffect: TimerEffect? - private let error: PubNubError - - init( - request: SubscribeRequest, - listeners: [BaseSubscriptionListener], - error: PubNubError, - retryAttempt: Int - ) { - self.timerEffect = TimerEffect(interval: request.reconnectionDelay( - dueTo: error, - retryAttempt: retryAttempt - )) - self.subscribeEffect = SubscribeEffect( - request: request, - listeners: listeners, - onResponseReceived: { .receiveReconnectSuccess(cursor: $0.cursor, messages: $0.messages) }, - onErrorReceived: { .receiveReconnectFailure(error: $0) } - ) - self.error = error - } - - func performTask(completionBlock: @escaping ([Subscribe.Event]) -> Void) { - subscribeEffect.listeners.forEach { - $0.emit(subscribe: .connectionChanged(.reconnecting)) - } - guard let timerEffect = timerEffect else { - completionBlock([.receiveReconnectGiveUp(error: error)]); return - } - subscribeEffect.request.onAuthChallengeReceived = { [weak self] in - // Delay time for server to process connection after TLS handshake - DispatchQueue.global(qos: .default).asyncAfter(deadline: DispatchTime.now() + 0.05) { - self?.subscribeEffect.listeners.forEach { $0.emit(subscribe: .connectionChanged(.connected)) } - } - } - timerEffect.performTask { [weak self] _ in - self?.subscribeEffect.performTask(completionBlock: completionBlock) - } - } - - func cancelTask() { - timerEffect?.cancelTask() - subscribeEffect.cancelTask() - } - - deinit { - cancelTask() - } -} - // MARK: - SubscribeEffect private class SubscribeEffect: EffectHandler { diff --git a/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift b/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift index 2693d66b..b18399d9 100644 --- a/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift +++ b/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift @@ -20,7 +20,6 @@ class SubscribeRequest { private let session: SessionReplaceable private let sessionResponseQueue: DispatchQueue private let channelStates: [String: JSONCodable] - private var request: RequestReplaceable? var retryLimit: UInt { configuration.automaticRetry?.retryLimit ?? 0 } @@ -52,29 +51,6 @@ class SubscribeRequest { } } - func reconnectionDelay(dueTo error: PubNubError, retryAttempt: Int) -> TimeInterval? { - guard let automaticRetry = configuration.automaticRetry else { - return nil - } - guard automaticRetry.retryOperator(for: .subscribe) != nil else { - return nil - } - guard automaticRetry.retryLimit > retryAttempt else { - return nil - } - guard let underlyingError = error.underlying else { - return automaticRetry.policy.delay(for: retryAttempt) - } - guard let urlResponse = error.affected.findFirst(by: PubNubError.AffectedValue.response) else { - return nil - } - let shouldRetry = automaticRetry.shouldRetry( - response: urlResponse, - error: underlyingError - ) - return shouldRetry ? automaticRetry.policy.delay(for: retryAttempt) : nil - } - func execute(onCompletion: @escaping (Result) -> Void) { let router = SubscribeRouter( .subscribe( @@ -90,7 +66,7 @@ class SubscribeRequest { ) request = session.request( with: router, - requestOperator: nil + requestOperator: configuration.automaticRetry?.retryOperator(for: .subscribe) ) request?.validate().response( on: sessionResponseQueue, diff --git a/Sources/PubNub/EventEngine/Subscribe/Subscribe.swift b/Sources/PubNub/EventEngine/Subscribe/Subscribe.swift index c5a8ba8a..e3063dd5 100644 --- a/Sources/PubNub/EventEngine/Subscribe/Subscribe.swift +++ b/Sources/PubNub/EventEngine/Subscribe/Subscribe.swift @@ -44,14 +44,6 @@ extension Subscribe { let connectionStatus = ConnectionStatus.disconnected } - struct HandshakeReconnectingState: SubscribeState { - let input: SubscribeInput - let cursor: SubscribeCursor - let retryAttempt: Int - let reason: PubNubError - let connectionStatus = ConnectionStatus.connecting - } - struct HandshakeFailedState: SubscribeState { let input: SubscribeInput let cursor: SubscribeCursor @@ -72,14 +64,6 @@ extension Subscribe { let connectionStatus = ConnectionStatus.connected } - struct ReceiveReconnectingState: SubscribeState { - let input: SubscribeInput - let cursor: SubscribeCursor - let retryAttempt: Int - let reason: PubNubError - let connectionStatus = ConnectionStatus.connected - } - struct ReceiveStoppedState: SubscribeState { let input: SubscribeInput let cursor: SubscribeCursor @@ -116,14 +100,8 @@ extension Subscribe { case subscriptionRestored(channels: [String], groups: [String], cursor: SubscribeCursor) case handshakeSuccess(cursor: SubscribeCursor) case handshakeFailure(error: PubNubError) - case handshakeReconnectSuccess(cursor: SubscribeCursor) - case handshakeReconnectFailure(error: PubNubError) - case handshakeReconnectGiveUp(error: PubNubError) case receiveSuccess(cursor: SubscribeCursor, messages: [SubscribeMessagePayload]) case receiveFailure(error: PubNubError) - case receiveReconnectSuccess(cursor: SubscribeCursor, messages: [SubscribeMessagePayload]) - case receiveReconnectFailure(error: PubNubError) - case receiveReconnectGiveUp(error: PubNubError) case disconnect case reconnect(cursor: SubscribeCursor?) case unsubscribeAll @@ -155,29 +133,21 @@ extension Subscribe { extension Subscribe { enum Invocation: AnyEffectInvocation { case handshakeRequest(channels: [String], groups: [String]) - case handshakeReconnect(channels: [String], groups: [String], retryAttempt: Int, reason: PubNubError) case receiveMessages(channels: [String], groups: [String], cursor: SubscribeCursor) - case receiveReconnect(channels: [String], groups: [String], cursor: SubscribeCursor, retryAttempt: Int, reason: PubNubError) case emitStatus(change: Subscribe.ConnectionStatusChange) case emitMessages(events: [SubscribeMessagePayload], forCursor: SubscribeCursor) // swiftlint:disable:next nesting enum Cancellable: AnyCancellableInvocation { case handshakeRequest - case handshakeReconnect case receiveMessages - case receiveReconnect var id: String { switch self { case .handshakeRequest: return "Subscribe.HandshakeRequest" - case .handshakeReconnect: - return "Subscribe.HandshakeReconnect" case .receiveMessages: return "Subscribe.ReceiveMessages" - case .receiveReconnect: - return "Subscribe.ReceiveReconnect" } } } @@ -186,12 +156,8 @@ extension Subscribe { switch self { case .handshakeRequest: return Cancellable.handshakeRequest.id - case .handshakeReconnect: - return Cancellable.handshakeReconnect.id case .receiveMessages: return Cancellable.receiveMessages.id - case .receiveReconnect: - return Cancellable.receiveReconnect.id case .emitMessages: return "Subscribe.EmitMessages" case .emitStatus: diff --git a/Sources/PubNub/EventEngine/Subscribe/SubscribeTransition.swift b/Sources/PubNub/EventEngine/Subscribe/SubscribeTransition.swift index 31a2bd53..ef076916 100644 --- a/Sources/PubNub/EventEngine/Subscribe/SubscribeTransition.swift +++ b/Sources/PubNub/EventEngine/Subscribe/SubscribeTransition.swift @@ -15,29 +15,16 @@ class SubscribeTransition: TransitionProtocol { typealias Event = Subscribe.Event typealias Invocation = Subscribe.Invocation - // swiftlint:disable:next cyclomatic_complexity func canTransition(from state: State, dueTo event: Event) -> Bool { switch event { case .handshakeSuccess: return state is Subscribe.HandshakingState case .handshakeFailure: return state is Subscribe.HandshakingState - case .handshakeReconnectSuccess: - return state is Subscribe.HandshakeReconnectingState - case .handshakeReconnectFailure: - return state is Subscribe.HandshakeReconnectingState - case .handshakeReconnectGiveUp: - return state is Subscribe.HandshakeReconnectingState case .receiveSuccess: return state is Subscribe.ReceivingState case .receiveFailure: return state is Subscribe.ReceivingState - case .receiveReconnectSuccess: - return state is Subscribe.ReceiveReconnectingState - case .receiveReconnectFailure: - return state is Subscribe.ReceiveReconnectingState - case .receiveReconnectGiveUp: - return state is Subscribe.ReceiveReconnectingState case .subscriptionChanged: return true case .subscriptionRestored: @@ -62,12 +49,8 @@ class SubscribeTransition: TransitionProtocol { switch state { case is Subscribe.HandshakingState: return [.cancel(.handshakeRequest)] - case is Subscribe.HandshakeReconnectingState: - return [.cancel(.handshakeReconnect)] case is Subscribe.ReceivingState: return [.cancel(.receiveMessages)] - case is Subscribe.ReceiveReconnectingState: - return [.cancel(.receiveReconnect)] default: return [] } @@ -84,17 +67,6 @@ class SubscribeTransition: TransitionProtocol { ) ) ] - case let state as Subscribe.HandshakeReconnectingState: - return [ - .managed( - .handshakeReconnect( - channels: state.input.allSubscribedChannelNames, - groups: state.input.allSubscribedGroupNames, - retryAttempt: state.retryAttempt, - reason: state.reason - ) - ) - ] case let state as Subscribe.ReceivingState: return [ .managed( @@ -105,24 +77,11 @@ class SubscribeTransition: TransitionProtocol { ) ) ] - case let state as Subscribe.ReceiveReconnectingState: - return [ - .managed( - .receiveReconnect( - channels: state.input.allSubscribedChannelNames, - groups: state.input.allSubscribedGroupNames, - cursor: state.cursor, - retryAttempt: state.retryAttempt, - reason: state.reason - ) - ) - ] default: return [] } } - // swiftlint:disable:next cyclomatic_complexity func transition(from state: State, event: Event) -> TransitionResult { var results: TransitionResult @@ -130,22 +89,10 @@ class SubscribeTransition: TransitionProtocol { case let .handshakeSuccess(cursor): results = setReceivingState(from: state, cursor: resolveCursor(for: state, new: cursor)) case let .handshakeFailure(error): - results = setHandshakeReconnectingState(from: state, error: error) - case let .handshakeReconnectSuccess(cursor): - results = setReceivingState(from: state, cursor: resolveCursor(for: state, new: cursor)) - case let .handshakeReconnectFailure(error): - results = setHandshakeReconnectingState(from: state, error: error) - case let .handshakeReconnectGiveUp(error): results = setHandshakeFailedState(from: state, error: error) case let .receiveSuccess(cursor, messages): results = setReceivingState(from: state, cursor: cursor, messages: messages) case .receiveFailure(let error): - results = setReceiveReconnectingState(from: state, error: error) - case let .receiveReconnectSuccess(cursor, messages): - results = setReceivingState(from: state, cursor: cursor, messages: messages) - case let .receiveReconnectFailure(error): - results = setReceiveReconnectingState(from: state, error: error) - case let .receiveReconnectGiveUp(error): results = setReceiveFailedState(from: state, error: error) case let .subscriptionChanged(channels, groups): results = onSubscriptionAltered(from: state, channels: channels, groups: groups, cursor: state.cursor) @@ -180,7 +127,6 @@ class SubscribeTransition: TransitionProtocol { } fileprivate extension SubscribeTransition { - // swiftlint:disable:next cyclomatic_complexity func onSubscriptionAltered( from state: State, channels: [String], @@ -198,16 +144,12 @@ fileprivate extension SubscribeTransition { switch state { case is Subscribe.HandshakingState: return TransitionResult(state: Subscribe.HandshakingState(input: newInput, cursor: cursor)) - case is Subscribe.HandshakeReconnectingState: - return TransitionResult(state: Subscribe.HandshakingState(input: newInput, cursor: cursor)) case is Subscribe.HandshakeStoppedState: return TransitionResult(state: Subscribe.HandshakeStoppedState(input: newInput, cursor: cursor)) case is Subscribe.HandshakeFailedState: return TransitionResult(state: Subscribe.HandshakingState(input: newInput, cursor: cursor)) case is Subscribe.ReceivingState: return TransitionResult(state: Subscribe.ReceivingState(input: newInput, cursor: cursor)) - case is Subscribe.ReceiveReconnectingState: - return TransitionResult(state: Subscribe.ReceivingState(input: newInput, cursor: cursor)) case is Subscribe.ReceiveStoppedState: return TransitionResult(state: Subscribe.ReceiveStoppedState(input: newInput, cursor: cursor)) case is Subscribe.ReceiveFailedState: @@ -232,22 +174,6 @@ fileprivate extension SubscribeTransition { } } -fileprivate extension SubscribeTransition { - func setHandshakeReconnectingState( - from state: State, - error: PubNubError - ) -> TransitionResult { - return TransitionResult( - state: Subscribe.HandshakeReconnectingState( - input: state.input, - cursor: state.cursor, - retryAttempt: ((state as? Subscribe.HandshakeReconnectingState)?.retryAttempt ?? -1) + 1, - reason: error - ) - ) - } -} - fileprivate extension SubscribeTransition { func setHandshakeFailedState( from state: State, @@ -286,7 +212,7 @@ fileprivate extension SubscribeTransition { )) ) - if state is Subscribe.HandshakingState || state is Subscribe.HandshakeReconnectingState { + if state is Subscribe.HandshakingState { return TransitionResult( state: Subscribe.ReceivingState(input: state.input, cursor: cursor), invocations: [messages.isEmpty ? nil : emitMessagesInvocation, emitStatusInvocation].compactMap { $0 } @@ -300,30 +226,11 @@ fileprivate extension SubscribeTransition { } } -fileprivate extension SubscribeTransition { - func setReceiveReconnectingState( - from state: State, - error: PubNubError - ) -> TransitionResult { - return TransitionResult( - state: Subscribe.ReceiveReconnectingState( - input: state.input, - cursor: state.cursor, - retryAttempt: ((state as? Subscribe.ReceiveReconnectingState)?.retryAttempt ?? -1) + 1, - reason: error - ) - ) - } -} - fileprivate extension SubscribeTransition { func setReceiveFailedState( from state: State, error: PubNubError ) -> TransitionResult { - guard let state = state as? Subscribe.ReceiveReconnectingState else { - return TransitionResult(state: state) - } return TransitionResult( state: Subscribe.ReceiveFailedState( input: state.input, @@ -361,12 +268,8 @@ fileprivate extension SubscribeTransition { switch state { case is Subscribe.HandshakingState: return handshakeStoppedTransition - case is Subscribe.HandshakeReconnectingState: - return handshakeStoppedTransition case is Subscribe.ReceivingState: return receiveStoppedTransition - case is Subscribe.ReceiveReconnectingState: - return receiveStoppedTransition default: return TransitionResult(state: state) } diff --git a/Sources/PubNub/Networking/Request/Request.swift b/Sources/PubNub/Networking/Request/Request.swift index 276890b8..bcd9cd74 100644 --- a/Sources/PubNub/Networking/Request/Request.swift +++ b/Sources/PubNub/Networking/Request/Request.swift @@ -289,6 +289,7 @@ final class Request { delegate.retryResult(for: self, dueTo: error, andPrevious: previousError) { retryResult in switch retryResult { case let .success(retryAfter): + self.atomicState.lockedWrite { $0.responesData = nil } delegate.retryRequest(self, withDelay: retryAfter) case let .failure(error): self.finish(error: PubNubError.retry(error, router: self.router)) diff --git a/Sources/PubNub/Subscription/SubscriptionSession.swift b/Sources/PubNub/Subscription/SubscriptionSession.swift index ebcd8aca..0b3fe32a 100644 --- a/Sources/PubNub/Subscription/SubscriptionSession.swift +++ b/Sources/PubNub/Subscription/SubscriptionSession.swift @@ -156,19 +156,21 @@ class SubscriptionSession: EventEmitter, StatusEmitter { and groups: [String] = [], presenceOnly: Bool = false ) { + let channelNamesToUnsubscribe = channels.flatMap { + presenceOnly ? [$0.presenceChannelName] : [$0, $0.presenceChannelName] + } + let groupNamesToUnsubscribe = groups.flatMap { + presenceOnly ? [$0.presenceChannelName] : [$0, $0.presenceChannelName] + } internalUnsubscribe( - from: channels.map { Subscription(queue: queue, entity: channel($0)) }, - and: groups.map { Subscription(queue: queue, entity: channelGroup($0)) }, + from: globalChannelSubscriptions.compactMap { channelNamesToUnsubscribe.contains($0.key) ? $0.value : nil }, + and: globalGroupSubscriptions.compactMap { groupNamesToUnsubscribe.contains($0.key) ? $0.value : nil }, presenceOnly: presenceOnly ) - channels.flatMap { - presenceOnly ? [$0.presenceChannelName] : [$0, $0.presenceChannelName] - }.forEach { + channelNamesToUnsubscribe.forEach { globalChannelSubscriptions.removeValue(forKey: $0) } - groups.flatMap { - presenceOnly ? [$0.presenceChannelName] : [$0, $0.presenceChannelName] - }.forEach { + groupNamesToUnsubscribe.forEach { globalGroupSubscriptions.removeValue(forKey: $0) } } diff --git a/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift b/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift index 5bc4c671..490ef513 100644 --- a/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift +++ b/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift @@ -20,8 +20,6 @@ extension Presence.Invocation: ContractTestIdentifiable { return "HEARTBEAT" case .leave: return "LEAVE" - case .delayedHeartbeat: - return "DELAYED_HEARTBEAT" case .wait: return "WAIT" } @@ -33,8 +31,6 @@ extension Presence.Invocation.Cancellable: ContractTestIdentifiable { switch self { case .wait: return "CANCEL_WAIT" - case .delayedHeartbeat: - return "CANCEL_DELAYED_HEARTBEAT" } } } @@ -58,8 +54,6 @@ extension Presence.Event: ContractTestIdentifiable { return "HEARTBEAT_SUCCESS" case .heartbeatFailed: return "HEARTBEAT_FAILURE" - case .heartbeatGiveUp: - return "HEARTBEAT_GIVEUP" } } } @@ -86,7 +80,6 @@ class PubNubPresenceEngineContractTestsSteps: PubNubEventEngineContractTestsStep override func createPubNubClient() -> PubNub { let container = DependencyContainer(configuration: self.configuration) - let key = PresenceEventEngineDependencyKey.self self.dispatcherDecorator = DispatcherDecorator(wrappedInstance: EffectDispatcher( factory: PresenceEffectFactory( diff --git a/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift b/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift index 75dfb278..8e219622 100644 --- a/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift +++ b/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift @@ -18,12 +18,8 @@ extension Subscribe.Invocation: ContractTestIdentifiable { switch self { case .handshakeRequest: return "HANDSHAKE" - case .handshakeReconnect: - return "HANDSHAKE_RECONNECT" case .receiveMessages: return "RECEIVE_MESSAGES" - case .receiveReconnect: - return "RECEIVE_RECONNECT" case .emitMessages: return "EMIT_MESSAGES" case .emitStatus: @@ -37,12 +33,8 @@ extension Subscribe.Invocation.Cancellable: ContractTestIdentifiable { switch self { case .handshakeRequest: return "CANCEL_HANDSHAKE" - case .handshakeReconnect: - return "CANCEL_HANDSHAKE_RECONNECT" case .receiveMessages: return "CANCEL_RECEIVE_MESSAGES" - case .receiveReconnect: - return "CANCEL_RECEIVE_RECONNECT" } } } @@ -54,22 +46,10 @@ extension Subscribe.Event: ContractTestIdentifiable { return "HANDSHAKE_SUCCESS" case .handshakeFailure: return "HANDSHAKE_FAILURE" - case .handshakeReconnectSuccess: - return "HANDSHAKE_RECONNECT_SUCCESS" - case .handshakeReconnectFailure: - return "HANDSHAKE_RECONNECT_FAILURE" - case .handshakeReconnectGiveUp: - return "HANDSHAKE_RECONNECT_GIVEUP" case .receiveSuccess: return "RECEIVE_SUCCESS" case .receiveFailure: return "RECEIVE_FAILURE" - case .receiveReconnectSuccess: - return "RECEIVE_RECONNECT_SUCCESS" - case .receiveReconnectFailure: - return "RECEIVE_RECONNECT_FAILURE" - case .receiveReconnectGiveUp: - return "RECEIVE_RECONNECT_GIVEUP" case .subscriptionChanged: return "SUBSCRIPTION_CHANGED" case .subscriptionRestored: @@ -115,7 +95,6 @@ class PubNubSubscribeEngineContractTestsSteps: PubNubEventEngineContractTestsSte override func createPubNubClient() -> PubNub { let container = DependencyContainer(configuration: self.configuration) - let key = SubscribeEventEngineDependencyKey.self self.dispatcherDecorator = DispatcherDecorator(wrappedInstance: EffectDispatcher( factory: SubscribeEffectFactory( @@ -174,8 +153,8 @@ class PubNubSubscribeEngineContractTestsSteps: PubNubEventEngineContractTestsSte self.subscribeSynchronously(self.client, to: ["test"]) } - When("I subscribe with timetoken 42") { _, _ in - self.subscribeSynchronously(self.client, to: ["test"], timetoken: 42) + When("I subscribe with timetoken 12345678901234567") { _, _ in + self.subscribeSynchronously(self.client, to: ["test"], timetoken: 12345678901234567) } Then("I receive an error in my subscribe response") { _, _ in diff --git a/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift b/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift deleted file mode 100644 index 6ddabf03..00000000 --- a/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// DelayedHeartbeatEffectTests.swift -// -// Copyright (c) PubNub Inc. -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. -// - -import Foundation -import XCTest - -@testable import PubNub - -class DelayedHeartbeatEffectTests: XCTestCase { - private var mockUrlSession: MockURLSession! - private var httpSession: HTTPSession! - private var delegate: HTTPSessionDelegate! - private var factory: PresenceEffectFactory! - - override func setUp() { - delegate = HTTPSessionDelegate() - mockUrlSession = MockURLSession(delegate: delegate) - httpSession = HTTPSession(session: mockUrlSession, delegate: delegate, sessionQueue: .main) - factory = PresenceEffectFactory(session: httpSession, presenceStateContainer: .shared) - super.setUp() - } - - override func tearDown() { - delegate = nil - mockUrlSession = nil - httpSession = nil - factory = nil - super.tearDown() - } - - func test_DelayedHeartbeatEffect() { - let expectation = XCTestExpectation() - expectation.expectationDescription = "Effect Completion Expectation" - expectation.assertForOverFulfill = true - - mockResponse(GenericServicePayloadResponse(status: 200)) - - let delayRange = 2.0...3.0 - let automaticRetry = AutomaticRetry(retryLimit: 3, policy: .linear(delay: delayRange.lowerBound), excluded: []) - let effect = configureEffectToTest(retryAttempt: 0, automaticRetry: automaticRetry, dueTo: PubNubError(.unknown)) - let startDate = Date() - - effect.performTask { returnedEvents in - XCTAssertTrue(returnedEvents.elementsEqual([.heartbeatSuccess])) - XCTAssertTrue(Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound)) - expectation.fulfill() - } - - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } - - func test_DelayedHeartbeatEffectFailure() { - let expectation = XCTestExpectation() - expectation.expectationDescription = "Effect Completion Expectation" - expectation.assertForOverFulfill = true - - mockResponse(GenericServicePayloadResponse(status: 500)) - - let delayRange = 2.0...3.0 - let automaticRetry = AutomaticRetry(retryLimit: 3, policy: .linear(delay: delayRange.lowerBound), excluded: []) - let error = PubNubError(.unknown) - let effect = configureEffectToTest(retryAttempt: 0, automaticRetry: automaticRetry, dueTo: error) - - effect.performTask { returnedEvents in - let expectedError = PubNubError(.internalServiceError) - let expectedRes = Presence.Event.heartbeatFailed(error: expectedError) - XCTAssertTrue(returnedEvents.elementsEqual([expectedRes])) - expectation.fulfill() - } - - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } - - func test_DelayedHeartbeatEffectGiveUp() { - let expectation = XCTestExpectation() - expectation.expectationDescription = "Effect Completion Expectation" - expectation.assertForOverFulfill = true - - let automaticRetry = AutomaticRetry(retryLimit: 3, policy: .linear(delay: 2.0), excluded: []) - let error = PubNubError(.unknown) - let effect = configureEffectToTest(retryAttempt: 3, automaticRetry: automaticRetry, dueTo: error) - - mockResponse(GenericServicePayloadResponse(status: 200)) - - effect.performTask { returnedEvents in - let expectedRes = Presence.Event.heartbeatGiveUp(error: PubNubError(.unknown)) - XCTAssertTrue(returnedEvents.elementsEqual([expectedRes])) - expectation.fulfill() - } - - wait(for: [expectation], timeout: 0.5) - } -} - -private extension DelayedHeartbeatEffectTests { - func mockResponse(_ response: GenericServicePayloadResponse) { - mockUrlSession.responseForDataTask = { task, _ in - task.mockError = nil - task.mockData = try? Constant.jsonEncoder.encode(response) - task.mockResponse = HTTPURLResponse(statusCode: response.status) - return task - } - } - - func configureEffectToTest( - retryAttempt attempt: Int, - automaticRetry: AutomaticRetry?, - dueTo error: PubNubError - ) -> any EffectHandler { - factory.effect( - for: .delayedHeartbeat( - channels: ["channel-1", "channel-2"], groups: ["group-1", "group-2"], - retryAttempt: attempt, error: error - ), - with: EventEngineDependencies(value: Presence.Dependencies( - configuration: PubNubConfiguration( - publishKey: "pubKey", - subscribeKey: "subKey", - userId: "userId", - automaticRetry: automaticRetry - )) - ) - ) - } -} diff --git a/Tests/PubNubTests/EventEngine/Presence/PresenceTransitionTests.swift b/Tests/PubNubTests/EventEngine/Presence/PresenceTransitionTests.swift index 148023b3..5efc9944 100644 --- a/Tests/PubNubTests/EventEngine/Presence/PresenceTransitionTests.swift +++ b/Tests/PubNubTests/EventEngine/Presence/PresenceTransitionTests.swift @@ -20,8 +20,6 @@ extension Presence.Invocation: Equatable { return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) case let (.leave(lC, lG), .leave(rC, rG)): return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) - case let (.delayedHeartbeat(lC, lG, lAtt, lErr),.delayedHeartbeat(rC, rG, rAtt, rErr)): - return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) && lAtt == rAtt && lErr == rErr case (.wait, .wait): return true default: @@ -39,8 +37,6 @@ extension Presence.Event: Equatable { return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) case let (.heartbeatFailed(lError), .heartbeatFailed(rError)): return lError == rError - case let (.heartbeatGiveUp(lError), .heartbeatGiveUp(rError)): - return lError == rError case (.leftAll, .leftAll): return true case (.reconnect, .reconnect): @@ -148,27 +144,6 @@ class PresenceTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.isEmpty) } - func testPresence_JoinedEventForReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting(input: input, retryAttempt: 1, error: PubNubError(.unknown)), - event: .joined(channels: ["c3"], groups: ["g3"]) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - .regular(.heartbeat(channels: ["c1", "c2", "c3"], groups: ["g1", "g2", "g3"])) - ] - let expectedState = Presence.Heartbeating( - input: PresenceInput(channels: ["c1", "c2", "c3"], groups: ["g1", "g2", "g3"]) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func testPresence_JoinedEventForCooldownState() { let input = PresenceInput( channels: ["c1", "c2"], @@ -230,28 +205,6 @@ class PresenceTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.isEmpty) } - func testPresence_LeftEventForReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2", "c3"], - groups: ["g1", "g2", "g3"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting(input: input, retryAttempt: 1, error: PubNubError(.unknown)), - event: .left(channels: ["c3"], groups: ["g3"]) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - .regular(.leave(channels: ["c3"], groups: ["g3"])), - .regular(.heartbeat(channels: ["c1", "c2"], groups: ["g1", "g2"])) - ] - let expectedState = Presence.Heartbeating( - input: PresenceInput(channels: ["c1", "c2"], groups: ["g1", "g2"]) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func testPresence_LeftEventForCooldownState() { let input = PresenceInput( channels: ["c1", "c2", "c3"], @@ -360,29 +313,6 @@ class PresenceTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func testPresence_LeftAllForReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting( - input: input, - retryAttempt: 1, - error: PubNubError(.unknown) - ), - event: .leftAll - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - .regular(.leave(channels: ["c1", "c2"], groups: ["g1", "g2"])) - ] - let expectedState = Presence.HeartbeatInactive() - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func testPresence_LeftAllWithSuppressLeaveEventsSetInConfig() { let input = PresenceInput( channels: ["c1", "c2", "c3"], @@ -444,31 +374,6 @@ class PresenceTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func testPresence_ReconnectForHeartbeatingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - - let results = transition.transition( - from: Presence.Heartbeating(input: input), - event: .heartbeatFailed(error: PubNubError(.unknown)) - ) - let expectedInvocations: [EffectInvocation] = [ - .managed(.delayedHeartbeat( - channels: ["c1", "c2"], groups: ["g1", "g2"], - retryAttempt: 0, error: PubNubError(.unknown) - )) - ] - let expectedState = Presence.HeartbeatReconnecting( - input: input, - retryAttempt: 0, error: PubNubError(.unknown) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Disconnect func testPresence_DisconnectForHeartbeatingState() { @@ -508,25 +413,6 @@ class PresenceTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func testPresence_DisconnectForHeartbeatReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting(input: input, retryAttempt: 1, error: PubNubError(.unknown)), - event: .disconnect - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - .regular(.leave(channels: ["c1", "c2"], groups: ["g1", "g2"])) - ] - let expectedState = Presence.HeartbeatStopped(input: input) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Heartbeat Success func testPresence_HeartbeatSuccessForHeartbeatingState() { @@ -547,29 +433,6 @@ class PresenceTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func testPresence_HeartbeatSuccessForReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting( - input: input, - retryAttempt: 1, - error: PubNubError(.unknown) - ), - event: .heartbeatSuccess - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - .managed(.wait) - ] - let expectedState = Presence.HeartbeatCooldown(input: input) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Heartbeat Failed func testPresence_HeartbeatFailedForHeartbeatingState() { @@ -581,69 +444,13 @@ class PresenceTransitionTests: XCTestCase { from: Presence.Heartbeating(input: input), event: .heartbeatFailed(error: PubNubError(.unknown)) ) - let expectedInvocations: [EffectInvocation] = [ - .managed(.delayedHeartbeat( - channels: ["c1", "c2"], groups: ["g1", "g2"], - retryAttempt: 0, error: PubNubError(.unknown) - )) - ] - let expectedState = Presence.HeartbeatReconnecting( - input: input, - retryAttempt: 0, - error: PubNubError(.unknown) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - - func testPresence_HeartbeatFailedForReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting(input: input, retryAttempt: 1, error: PubNubError(.unknown)), - event: .heartbeatFailed(error: PubNubError(.badServerResponse)) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - .managed(.delayedHeartbeat( - channels: ["c1", "c2"], groups: ["g1", "g2"], - retryAttempt: 2, error: PubNubError(.badServerResponse) - )) - ] - let expectedState = Presence.HeartbeatReconnecting( - input: input, - retryAttempt: 2, - error: PubNubError(.badServerResponse) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - - // MARK: - Heartbeat Give Up - - func testPresence_HeartbeatGiveUpForReconnectingState() { - let input = PresenceInput( - channels: ["c1", "c2"], - groups: ["g1", "g2"] - ) - let results = transition.transition( - from: Presence.HeartbeatReconnecting(input: input, retryAttempt: 1, error: PubNubError(.unknown)), - event: .heartbeatGiveUp(error: PubNubError(.badServerResponse)) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.delayedHeartbeat), - ] let expectedState = Presence.HeartbeatFailed( input: input, - error: PubNubError(.badServerResponse) + error: PubNubError(.unknown) ) XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) + XCTAssertTrue(results.invocations.isEmpty) } // MARK: - Times Up diff --git a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift index 461cf21a..18a7edea 100644 --- a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift +++ b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift @@ -179,291 +179,6 @@ extension SubscribeEffectsTests { } } -// MARK: - HandshakeReconnecting - -extension SubscribeEffectsTests { - func test_HandshakeReconnectingSuccess() { - mockResponse(subscribeResponse: SubscribeResponse( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [] - )) - - let delayRange = 2.0...3.0 - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - let testedInvocation: Subscribe.Invocation = .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 1, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse), - affected: [.response(HTTPURLResponse(statusCode: 500)!)] - ) - ) - let expectedOutput: Subscribe.Event = .handshakeReconnectSuccess( - cursor: SubscribeCursor(timetoken: 12345, region: 1) - ) - let effect = factory.effect( - for: testedInvocation, - with: EventEngineDependencies(value: Subscribe.Dependencies( - configuration: configWithLinearPolicy(delayRange.lowerBound) - )) - ) - - effect.performTask { - XCTAssertEqual([expectedOutput], $0) - expectation.fulfill() - } - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } - - func test_HandshakeReconnectingFailed() { - mockResponse( - errorIfAny: URLError(.cannotFindHost), - httpResponse: HTTPURLResponse(statusCode: 404)! - ) - - let delayRange = 2.0...3.0 - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - let testedInvocation: Subscribe.Invocation = .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 1, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse), - affected: [.response(HTTPURLResponse(statusCode: 500)!)] - ) - ) - let expectedOutput: Subscribe.Event = .handshakeReconnectFailure( - error: PubNubError(.nameResolutionFailure, underlying: URLError(.cannotFindHost)) - ) - let effect = factory.effect( - for: testedInvocation, - with: EventEngineDependencies(value: Subscribe.Dependencies( - configuration: configWithLinearPolicy(delayRange.lowerBound) - )) - ) - - effect.performTask { - XCTAssertEqual([expectedOutput], $0) - expectation.fulfill() - } - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } - - func test_HandshakeReconnectGiveUp() { - let delayRange = 2.0...3.0 - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - let testedInvocation: Subscribe.Invocation = .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 3, - reason: PubNubError(URLError(.badServerResponse).pubnubReason!, underlying: URLError(.badServerResponse)) - ) - let expectedOutput: Subscribe.Event = .handshakeReconnectGiveUp( - error: PubNubError(.badServerResponse) - ) - let effect = factory.effect( - for: testedInvocation, - with: EventEngineDependencies(value: Subscribe.Dependencies( - configuration: configWithLinearPolicy(delayRange.lowerBound) - )) - ) - - effect.performTask { - XCTAssertEqual([expectedOutput], $0) - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - } - - func test_HandshakeReconnectIsDelayed() { - mockResponse(subscribeResponse: SubscribeResponse( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [] - )) - - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - let testedInvocation: Subscribe.Invocation = .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 3, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse), - affected: [.response(HTTPURLResponse(statusCode: 500)!)] - ) - ) - - let delayRange = 2.0...3.0 - let startDate = Date() - let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) - let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) - - effect.performTask { _ in - XCTAssertTrue(Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound)) - expectation.fulfill() - } - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } -} - -// MARK: - ReceiveReconnecting - -extension SubscribeEffectsTests { - func test_ReceiveReconnectingSuccess() { - mockResponse(subscribeResponse: SubscribeResponse( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [firstMessage, secondMessage] - )) - - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - let testedInvocation: Subscribe.Invocation = .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 1, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse), - affected: [.response(HTTPURLResponse(statusCode: 500)!)] - ) - ) - let expectedOutput: Subscribe.Event = .receiveReconnectSuccess( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [firstMessage, secondMessage] - ) - - let delayRange = 2.0...3.0 - let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) - let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) - - effect.performTask { - XCTAssertEqual([expectedOutput], $0) - expectation.fulfill() - } - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } - - func test_ReceiveReconnectingFailure() { - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - mockResponse( - errorIfAny: URLError(.cannotFindHost), - httpResponse: HTTPURLResponse(statusCode: 404)! - ) - let testedInvocation: Subscribe.Invocation = .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 1, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse), - affected: [.response(HTTPURLResponse(statusCode: 500)!)] - ) - ) - - let expectedOutput: Subscribe.Event = .receiveReconnectFailure(error: PubNubError(.nameResolutionFailure)) - let delayRange = 2.0...3.0 - let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) - let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) - - effect.performTask { - XCTAssertEqual([expectedOutput], $0) - expectation.fulfill() - } - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } - - func test_ReceiveReconnectGiveUp() { - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - mockResponse( - errorIfAny: URLError(.cannotFindHost), - httpResponse: HTTPURLResponse(statusCode: 404)! - ) - - let testedInvocation: Subscribe.Invocation = .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 3, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse) - ) - ) - let expectedOutput: Subscribe.Event = .receiveReconnectGiveUp( - error: PubNubError(.badServerResponse) - ) - - let delayRange = 2.0...3.0 - let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) - let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) - - effect.performTask { - XCTAssertEqual([expectedOutput], $0) - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - } - - func test_ReceiveReconnectingIsDelayed() { - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - mockResponse(subscribeResponse: SubscribeResponse( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [firstMessage, secondMessage] - )) - - let testedInvocation: Subscribe.Invocation = .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 1, - reason: PubNubError( - URLError(.badServerResponse).pubnubReason!, - underlying: URLError(.badServerResponse), - affected: [.response(HTTPURLResponse(statusCode: 500)!)] - ) - ) - - let delayRange = 2.0...3.0 - let startDate = Date() - let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) - let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) - - effect.performTask { _ in - XCTAssertTrue(Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound)) - expectation.fulfill() - } - wait(for: [expectation], timeout: 2 * delayRange.upperBound) - } -} - // MARK: - Helpers private extension SubscribeEffectsTests { diff --git a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeRequestTests.swift b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeRequestTests.swift deleted file mode 100644 index a65cd15e..00000000 --- a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeRequestTests.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// SubscribeRequestTests.swift -// -// Copyright (c) PubNub Inc. -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. -// - -import Foundation -import XCTest - -@testable import PubNub - -class SubscribeRequestTests: XCTestCase { - func test_SubscribeRequestWithoutRetryPolicy() { - let config = PubNubConfiguration( - publishKey: "publishKey", - subscribeKey: "subscribeKey", - userId: "userId" - ) - let request = SubscribeRequest( - configuration: config, - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - channelStates: [:], - session: HTTPSession(configuration: .subscription), - sessionResponseQueue: .main - ) - - let urlResponse = HTTPURLResponse(statusCode: 500)! - let error = PubNubError(.connectionFailure, affected: [.response(urlResponse)]) - - XCTAssertNil(request.reconnectionDelay(dueTo: error, retryAttempt: 0)) - } - - func test_SubscribeRequestDoesNotRetryForNonSupportedCode() { - let automaticRetry = AutomaticRetry( - retryLimit: 2, - policy: .linear(delay: 3.0), - retryableURLErrorCodes: [.badURL] - ) - let config = PubNubConfiguration( - publishKey: "publishKey", - subscribeKey: "subscribeKey", - userId: "userId", - automaticRetry: automaticRetry - ) - let request = SubscribeRequest( - configuration: config, - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - channelStates: [:], - session: HTTPSession(configuration: .subscription), - sessionResponseQueue: .main - ) - - let urlError = URLError(.cannotFindHost) - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError) - - XCTAssertNil(request.reconnectionDelay(dueTo: pubNubError, retryAttempt: 0)) - } -} diff --git a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift index 29462cd4..86b5e664 100644 --- a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift +++ b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift @@ -24,12 +24,8 @@ extension Subscribe.Invocation : Equatable { switch (lhs, rhs) { case let (.handshakeRequest(lC, lG), .handshakeRequest(rC, rG)): return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) - case let (.handshakeReconnect(lC, lG, lAtt, lErr),.handshakeReconnect(rC, rG, rAtt, rErr)): - return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) && lAtt == rAtt && lErr == rErr case let (.receiveMessages(lC, lG, lCrsr),.receiveMessages(rC, rG, rCrsr)): return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) && lCrsr == rCrsr - case let (.receiveReconnect(lC, lG, lCrsr, lAtt, lErr), .receiveReconnect(rC, rG, rCrsr, rAtt, rErr)): - return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) && lCrsr == rCrsr && lAtt == rAtt && lErr == rErr case let (.emitStatus(lhsChange), .emitStatus(rhsChange)): return lhsChange == rhsChange case let (.emitMessages(lhsMssgs, lhsCrsr), .emitMessages(rhsMssgs, rhsCrsr)): @@ -49,24 +45,12 @@ extension Subscribe.Event: Equatable { return lC.sorted(by: <) == rC.sorted(by: <) && lG.sorted(by: <) == rG.sorted(by: <) && lCursor == rCursor case let (.handshakeSuccess(lCursor), .handshakeSuccess(rCursor)): return lCursor == rCursor - case let (.handshakeReconnectSuccess(lCursor), .handshakeReconnectSuccess(rCursor)): - return lCursor == rCursor case let (.handshakeFailure(lError), .handshakeFailure(rError)): return lError == rError - case let (.handshakeReconnectFailure(lError), .handshakeReconnectFailure(rError)): - return lError == rError - case let (.handshakeReconnectGiveUp(lError), .handshakeReconnectGiveUp(rError)): - return lError == rError case let (.receiveSuccess(lCursor, lMssgs), .receiveSuccess(rCursor, rMssgs)): return lCursor == rCursor && lMssgs == rMssgs case let (.receiveFailure(lError), .receiveFailure(rError)): return lError == rError - case let (.receiveReconnectSuccess(lCursor, lMssgs), .receiveReconnectSuccess(rCursor, rMssgs)): - return lCursor == rCursor && lMssgs == rMssgs - case let (.receiveReconnectFailure(lError), .receiveReconnectFailure(rError)): - return lError == rError - case let (.receiveReconnectGiveUp(lError), .receiveReconnectGiveUp(rError)): - return lError == rError case (.disconnect, .disconnect): return true case (.reconnect, .reconnect): @@ -179,44 +163,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.isEmpty) } - func test_SubscriptionChangedForHandshakeReconnectingState() throws { - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .subscriptionChanged( - channels: ["c1", "c1", "c1-pnpres", "c2"], - groups: ["g1", "g1-pnpres", "g2", "g2", "g2-pnpres", "g3"] - ) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), - .managed(.handshakeRequest( - channels: ["c1", "c1-pnpres", "c2"], - groups: ["g1", "g1-pnpres", "g2", "g2-pnpres", "g3"] - )) - ] - let expectedChannels = [ - PubNubChannel(id: "c1", withPresence: true), - PubNubChannel(id: "c2", withPresence: false) - ] - let expectedGroups = [ - PubNubChannel(id: "g1", withPresence: true), - PubNubChannel(id: "g2", withPresence: true), - PubNubChannel(id: "g3", withPresence: false) - ] - let expectedState = Subscribe.HandshakingState(input: SubscribeInput( - channels: expectedChannels, - groups: expectedGroups - ), cursor: SubscribeCursor(timetoken: 0, region: 0)) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func test_SubscriptionChangedForHandshakingState() throws { let results = transition.transition( from: Subscribe.HandshakingState(input: input, cursor: SubscribeCursor(timetoken: 0, region: 0)), @@ -359,50 +305,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.isEmpty) } - func test_SubscriptionChangedForReceiveReconnectingState() throws { - let results = transition.transition( - from: Subscribe.ReceiveReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 500100900, region: 11), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .subscriptionChanged( - channels: ["c1", "c1", "c1-pnpres", "c2"], - groups: ["g1", "g1-pnpres", "g2", "g2", "g2-pnpres", "g3"] - ) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.receiveReconnect), - .managed(.receiveMessages( - channels: ["c1", "c1-pnpres", "c2"], - groups: ["g1", "g1-pnpres", "g2", "g2-pnpres", "g3"], - cursor: SubscribeCursor(timetoken: 500100900, region: 11) - )) - ] - let expectedChannels = [ - PubNubChannel(id: "c1", withPresence: true), - PubNubChannel(id: "c2", withPresence: false) - ] - let expectedGroups = [ - PubNubChannel(id: "g1", withPresence: true), - PubNubChannel(id: "g2", withPresence: true), - PubNubChannel(id: "g3", withPresence: false) - ] - let expectedState = Subscribe.ReceivingState( - input: SubscribeInput( - channels: expectedChannels, - groups: expectedGroups - ), cursor: SubscribeCursor( - timetoken: 500100900, - region: 11 - ) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Subscription Restored func test_SubscriptionRestoredForReceivingState() throws { @@ -446,52 +348,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func test_SubscriptionRestoredForReceiveReconnectingState() { - let results = transition.transition( - from: Subscribe.ReceiveReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 1500100900, region: 41), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .subscriptionRestored( - channels: ["c1", "c1-pnpres", "c2", "c2", "c2-pnpres", "c3", "c3-pnpres", "c4"], - groups: ["g1", "g1-pnpres", "g2", "g2-pnpres", "g3", "g3-pnpres", "g4", "g4"], - cursor: SubscribeCursor(timetoken: 100, region: 55) - ) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.receiveReconnect), - .managed(.receiveMessages( - channels: ["c1", "c1-pnpres", "c2", "c2-pnpres", "c3", "c3-pnpres", "c4"], - groups: ["g1", "g1-pnpres", "g2", "g2-pnpres", "g3", "g3-pnpres", "g4"], - cursor: SubscribeCursor(timetoken: 100, region: 55) - )) - ] - let expectedChannels = [ - PubNubChannel(id: "c1", withPresence: true), - PubNubChannel(id: "c2", withPresence: true), - PubNubChannel(id: "c3", withPresence: true), - PubNubChannel(id: "c4", withPresence: false) - ] - let expectedGroups = [ - PubNubChannel(id: "g1", withPresence: true), - PubNubChannel(id: "g2", withPresence: true), - PubNubChannel(id: "g3", withPresence: true), - PubNubChannel(id: "g4", withPresence: false) - ] - let expectedState = Subscribe.ReceivingState( - input: SubscribeInput( - channels: expectedChannels, - groups: expectedGroups - ), - cursor: SubscribeCursor(timetoken: 100, region: 55) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func test_SubscriptionRestoredForReceiveFailedState() { let results = transition.transition( from: Subscribe.ReceiveFailedState( @@ -610,51 +466,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func test_SubscriptionRestoredForHandshakeReconnectingState() { - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .subscriptionRestored( - channels: ["c1", "c1-pnpres", "c2", "c2", "c2-pnpres", "c3", "c3-pnpres", "c4"], - groups: ["g1", "g1-pnpres", "g2", "g2-pnpres", "g3", "g3-pnpres", "g4", "g4"], - cursor: SubscribeCursor(timetoken: 100, region: 55) - ) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), - .managed(.handshakeRequest( - channels: ["c1", "c1-pnpres", "c2", "c2-pnpres", "c3", "c3-pnpres", "c4"], - groups: ["g1", "g1-pnpres", "g2", "g2-pnpres", "g3", "g3-pnpres", "g4"] - )) - ] - let expectedChannels = [ - PubNubChannel(id: "c1", withPresence: true), - PubNubChannel(id: "c2", withPresence: true), - PubNubChannel(id: "c3", withPresence: true), - PubNubChannel(id: "c4", withPresence: false) - ] - let expectedGroups = [ - PubNubChannel(id: "g1", withPresence: true), - PubNubChannel(id: "g2", withPresence: true), - PubNubChannel(id: "g3", withPresence: true), - PubNubChannel(id: "g4", withPresence: false) - ] - let expectedState = Subscribe.HandshakingState( - input: SubscribeInput( - channels: expectedChannels, - groups: expectedGroups - ), - cursor: SubscribeCursor(timetoken: 100, region: 55) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func test_SubscriptionRestoredForHandshakeFailedState() { let results = transition.transition( from: Subscribe.HandshakeFailedState( @@ -771,111 +582,11 @@ class SubscribeTransitionTests: XCTestCase { ) let expectedInvocations: [EffectInvocation] = [ .cancel(.handshakeRequest), - .managed(.handshakeReconnect( - channels: input.allSubscribedChannelNames, - groups: input.allSubscribedGroupNames, - retryAttempt: 0, - reason: PubNubError(.unknown) - )) - ] - let expectedState = Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 0, - reason: PubNubError(.unknown) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - - // MARK: - Handshake Reconnect Success - - func test_HandshakeReconnectSuccessForReconnectingState() { - let cursor = SubscribeCursor( - timetoken: 200400600, - region: 45 - ) - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .handshakeReconnectSuccess(cursor: cursor) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), - .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( - oldStatus: .connecting, - newStatus: .connected, - error: nil - ))), - .managed(.receiveMessages( - channels: input.allSubscribedChannelNames, - groups: input.allSubscribedGroupNames, - cursor: SubscribeCursor(timetoken: 200400600, region: 45) - )) - ] - let expectedState = Subscribe.ReceivingState( - input: input, - cursor: SubscribeCursor(timetoken: 200400600, region: 45) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - - // MARK: - Handshake Reconnect Failure - - func test_HandshakeReconnectFailedForReconnectingState() { - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 0, - reason: PubNubError(.unknown) - ), - event: .handshakeReconnectFailure(error: PubNubError(.unknown)) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), - .managed(.handshakeReconnect( - channels: input.allSubscribedChannelNames, groups: input.allSubscribedGroupNames, - retryAttempt: 1, reason: PubNubError(.unknown) - )) - ] - let expectedState = Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 1, - reason: PubNubError(.unknown) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - - // MARK: - Handshake Give Up - - func test_HandshakeGiveUpForReconnectingState() { - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 3, - reason: PubNubError(.unknown) - ), - event: .handshakeReconnectGiveUp(error: PubNubError(.unknown)) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( oldStatus: .connecting, newStatus: .connectionError(PubNubError(.unknown)), - error: PubNubError(.unknown) - ))) + error: PubNubError(.unknown)) + )) ] let expectedState = Subscribe.HandshakeFailedState( input: input, @@ -887,35 +598,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - // MARK: - Receive Give Up - - func test_ReceiveGiveUpForReconnectingState() { - let results = transition.transition( - from: Subscribe.ReceiveReconnectingState( - input: input, cursor: SubscribeCursor(timetoken: 18001000, region: 123), - retryAttempt: 3, - reason: PubNubError(.unknown) - ), - event: .receiveReconnectGiveUp(error: PubNubError(.unknown)) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.receiveReconnect), - .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( - oldStatus: .connected, - newStatus: .disconnectedUnexpectedly(PubNubError(.unknown)), - error: PubNubError(.unknown) - ))) - ] - let expectedState = Subscribe.ReceiveFailedState( - input: input, - cursor: SubscribeCursor(timetoken: 18001000, region: 123), - error: PubNubError(.unknown) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Receiving With Messages func test_ReceivingStateWithMessages() { @@ -962,56 +644,22 @@ class SubscribeTransitionTests: XCTestCase { ) let expectedInvocations: [EffectInvocation] = [ .cancel(.receiveMessages), - .managed(.receiveReconnect( - channels: input.allSubscribedChannelNames, - groups: input.allSubscribedGroupNames, - cursor: SubscribeCursor(timetoken: 100500900, region: 11), - retryAttempt: 0, - reason: PubNubError(.unknown) + .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( + oldStatus: .connected, + newStatus: .disconnectedUnexpectedly(PubNubError(.unknown)), + error: PubNubError(.unknown)) )) ] - let expectedState = Subscribe.ReceiveReconnectingState( + let expectedState = Subscribe.ReceiveFailedState( input: input, cursor: SubscribeCursor(timetoken: 100500900, region: 11), - retryAttempt: 0, - reason: PubNubError(.unknown) + error: PubNubError(.unknown) ) XCTAssertTrue(results.state.isEqual(to: expectedState)) XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func test_ReceiveReconnectFailedForReconnectingState() { - let results = transition.transition( - from: Subscribe.ReceiveReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 100500900, region: 11), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .receiveReconnectFailure(error: PubNubError(.unknown)) - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.receiveReconnect), - .managed(.receiveReconnect( - channels: input.allSubscribedChannelNames, - groups: input.allSubscribedGroupNames, - cursor: SubscribeCursor(timetoken: 100500900, region: 11), - retryAttempt: 2, - reason: PubNubError(.unknown) - )) - ] - let expectedState = Subscribe.ReceiveReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 100500900, region: 11), - retryAttempt: 2, - reason: PubNubError(.unknown) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Reconnect func test_ReconnectForHandshakeStoppedState() throws { @@ -1128,33 +776,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func test_DisconnectForHandshakeReconnectingState() { - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .disconnect - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), - .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( - oldStatus: .connecting, - newStatus: .disconnected, - error: nil - ))) - ] - let expectedState = Subscribe.HandshakeStoppedState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func test_DisconnectForReceivingState() { let results = transition.transition( from: Subscribe.ReceivingState( @@ -1180,33 +801,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func test_DisconnectForReceiveReconnectingState() { - let results = transition.transition( - from: Subscribe.ReceiveReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 123, region: 456), - retryAttempt: 1, - reason: PubNubError(.unknown) - ), - event: .disconnect - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.receiveReconnect), - .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( - oldStatus: .connected, - newStatus: .disconnected, - error: nil - ))) - ] - let expectedState = Subscribe.ReceiveStoppedState( - input: input, - cursor: SubscribeCursor(timetoken: 123, region: 456) - ) - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - // MARK: - Unsubscribe All func testUnsubscribeAll_ForHandshakingState() throws { @@ -1228,30 +822,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func testUnsubscribeAll_ForHandshakeReconnectingState() throws { - let results = transition.transition( - from: Subscribe.HandshakeReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 0, region: 0), - retryAttempt: 1, - reason: PubNubError(.badRequest) - ), - event: .unsubscribeAll - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.handshakeReconnect), - .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( - oldStatus: .connecting, - newStatus: .disconnected, - error: nil - ))) - ] - let expectedState = Subscribe.UnsubscribedState() - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func testUnsubscribeAll_ForHandshakeFailedState() throws { let results = transition.transition( from: Subscribe.HandshakeFailedState( @@ -1313,30 +883,6 @@ class SubscribeTransitionTests: XCTestCase { XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) } - func test_UnsubscribeAllForReceiveReconnectingState() throws { - let results = transition.transition( - from: Subscribe.ReceiveReconnectingState( - input: input, - cursor: SubscribeCursor(timetoken: 123, region: 456), - retryAttempt: 1, - reason: PubNubError(.badRequest) - ), - event: .unsubscribeAll - ) - let expectedInvocations: [EffectInvocation] = [ - .cancel(.receiveReconnect), - .regular(.emitStatus(change: Subscribe.ConnectionStatusChange( - oldStatus: .connected, - newStatus: .disconnected, - error: nil - ))) - ] - let expectedState = Subscribe.UnsubscribedState() - - XCTAssertTrue(results.state.isEqual(to: expectedState)) - XCTAssertTrue(results.invocations.elementsEqual(expectedInvocations)) - } - func test_UnsubscribeAllForReceiveFailedState() throws { let results = transition.transition( from: Subscribe.ReceiveFailedState( diff --git a/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift b/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift index b045285b..1d03f8d0 100644 --- a/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift +++ b/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift @@ -469,7 +469,7 @@ extension SubscribeRouterTests { case let .channelMetadataSet(changeset): XCTAssertEqual(try? changeset.apply(to: baseChannel).transcode(), patchedChannel) objectExpect.fulfill() - case let .subscriptionChanged(change): + case .subscriptionChanged: break default: XCTFail("Incorrect Event Received") diff --git a/Tests/PubNubTests/Subscription/SubscribeSessionFactoryTests.swift b/Tests/PubNubTests/Subscription/SubscribeSessionFactoryTests.swift index 6d9cb92d..fa30d95c 100644 --- a/Tests/PubNubTests/Subscription/SubscribeSessionFactoryTests.swift +++ b/Tests/PubNubTests/Subscription/SubscribeSessionFactoryTests.swift @@ -35,7 +35,7 @@ class SubscribeSessionFactoryTests: XCTestCase { ) let dependencyContainer = DependencyContainer(configuration: config) - let nextDependencyContainer = DependencyContainer(configuration: config) + let nextDependencyContainer = DependencyContainer(configuration: newConfig) let first = dependencyContainer.subscriptionSession let third = nextDependencyContainer.subscriptionSession