7
7
8
8
import XCTest
9
9
import AWSPinpoint
10
+ import AwsCommonRuntimeKit
10
11
@testable import Amplify
12
+ import ClientRuntime
11
13
@_spi ( InternalAWSPinpoint) @testable import InternalAWSPinpoint
12
14
13
15
class EventRecorderTests : XCTestCase {
@@ -26,6 +28,13 @@ class EventRecorderTests: XCTestCase {
26
28
XCTFail ( " Failed to setup EventRecorderTests " )
27
29
}
28
30
}
31
+
32
+ override func tearDown( ) {
33
+ pinpointClient = nil
34
+ endpointClient = nil
35
+ storage = nil
36
+ recorder = nil
37
+ }
29
38
30
39
/// - Given: a event recorder
31
40
/// - When: instance is constructed
@@ -56,4 +65,129 @@ class EventRecorderTests: XCTestCase {
56
65
XCTAssertEqual ( event, storage. events [ 0 ] )
57
66
XCTAssertEqual ( storage. checkDiskSizeCallCount, 2 )
58
67
}
68
+
69
+ /// - Given: a event recorder with events saved in the local storage
70
+ /// - When: submitAllEvents is invoked and successful
71
+ /// - Then: the events are removed from the local storage
72
+ func testSubmitAllEvents_withSuccess_shouldRemoveEventsFromStorage( ) async throws {
73
+ Amplify . Logging. logLevel = . verbose
74
+ let session = PinpointSession ( sessionId: " 1 " , startTime: Date ( ) , stopTime: nil )
75
+ storage. events = [
76
+ . init( id: " 1 " , eventType: " eventType1 " , eventDate: Date ( ) , session: session) ,
77
+ . init( id: " 2 " , eventType: " eventType2 " , eventDate: Date ( ) , session: session)
78
+ ]
79
+
80
+ pinpointClient. putEventsResult = . success( . init( eventsResponse: . init( results: [
81
+ " endpointId " : PinpointClientTypes . ItemResponse (
82
+ endpointItemResponse: . init( message: " Accepted " , statusCode: 202 ) ,
83
+ eventsItemResponse: [
84
+ " 1 " : . init( message: " Accepted " , statusCode: 202 ) ,
85
+ " 2 " : . init( message: " Accepted " , statusCode: 202 )
86
+ ]
87
+ )
88
+ ] ) ) )
89
+ let events = try await recorder. submitAllEvents ( )
90
+
91
+ XCTAssertEqual ( events. count, 2 )
92
+ XCTAssertEqual ( pinpointClient. putEventsCount, 1 )
93
+ XCTAssertTrue ( storage. events. isEmpty)
94
+ XCTAssertEqual ( storage. deleteEventCallCount, 2 )
95
+ }
96
+
97
+ /// - Given: a event recorder with events saved in the local storage
98
+ /// - When: submitAllEvents is invoked and fails with a non-retryable error
99
+ /// - Then: the events are marked as dirty
100
+ func testSubmitAllEvents_withRetryableError_shouldSetEventsAsDirty( ) async throws {
101
+ Amplify . Logging. logLevel = . verbose
102
+ let session = PinpointSession ( sessionId: " 1 " , startTime: Date ( ) , stopTime: nil )
103
+ let event1 = PinpointEvent ( id: " 1 " , eventType: " eventType1 " , eventDate: Date ( ) , session: session)
104
+ let event2 = PinpointEvent ( id: " 2 " , eventType: " eventType2 " , eventDate: Date ( ) , session: session)
105
+ storage. events = [ event1, event2 ]
106
+ pinpointClient. putEventsResult = . failure( NonRetryableError ( ) )
107
+ do {
108
+ let events = try await recorder. submitAllEvents ( )
109
+ XCTFail ( " Expected error " )
110
+ } catch {
111
+ XCTAssertEqual ( pinpointClient. putEventsCount, 1 )
112
+ XCTAssertEqual ( storage. events. count, 2 )
113
+ XCTAssertEqual ( storage. deleteEventCallCount, 0 )
114
+ XCTAssertEqual ( storage. eventRetryDictionary. count, 0 )
115
+ XCTAssertEqual ( storage. dirtyEventDictionary. count, 2 )
116
+ XCTAssertEqual ( storage. dirtyEventDictionary [ " 1 " ] , 1 )
117
+ XCTAssertEqual ( storage. dirtyEventDictionary [ " 2 " ] , 1 )
118
+ }
119
+ }
120
+
121
+ /// - Given: a event recorder with events saved in the local storage
122
+ /// - When: submitAllEvents is invoked and fails with a retryable error
123
+ /// - Then: the events' retry count is increased
124
+ func testSubmitAllEvents_withRetryableError_shouldIncreaseRetryCount( ) async throws {
125
+ Amplify . Logging. logLevel = . verbose
126
+ let session = PinpointSession ( sessionId: " 1 " , startTime: Date ( ) , stopTime: nil )
127
+ let event1 = PinpointEvent ( id: " 1 " , eventType: " eventType1 " , eventDate: Date ( ) , session: session)
128
+ let event2 = PinpointEvent ( id: " 2 " , eventType: " eventType2 " , eventDate: Date ( ) , session: session)
129
+ storage. events = [ event1, event2 ]
130
+ pinpointClient. putEventsResult = . failure( RetryableError ( ) )
131
+ do {
132
+ let events = try await recorder. submitAllEvents ( )
133
+ XCTFail ( " Expected error " )
134
+ } catch {
135
+ XCTAssertEqual ( pinpointClient. putEventsCount, 1 )
136
+ XCTAssertEqual ( storage. events. count, 2 )
137
+ XCTAssertEqual ( storage. deleteEventCallCount, 0 )
138
+ XCTAssertEqual ( storage. eventRetryDictionary. count, 2 )
139
+ XCTAssertEqual ( storage. eventRetryDictionary [ " 1 " ] , 1 )
140
+ XCTAssertEqual ( storage. eventRetryDictionary [ " 2 " ] , 1 )
141
+ XCTAssertEqual ( storage. dirtyEventDictionary. count, 0 )
142
+ }
143
+ }
144
+
145
+ /// - Given: a event recorder with events saved in the local storage
146
+ /// - When: submitAllEvents is invoked and fails with a connectivity error
147
+ /// - Then: the events are not removed from the local storage
148
+ func testSubmitAllEvents_withConnectivityError_shouldNotIncreaseRetryCount_andNotSetEventsAsDirty( ) async throws {
149
+ Amplify . Logging. logLevel = . verbose
150
+ let session = PinpointSession ( sessionId: " 1 " , startTime: Date ( ) , stopTime: nil )
151
+ let event1 = PinpointEvent ( id: " 1 " , eventType: " eventType1 " , eventDate: Date ( ) , session: session)
152
+ let event2 = PinpointEvent ( id: " 2 " , eventType: " eventType2 " , eventDate: Date ( ) , session: session)
153
+ storage. events = [ event1, event2 ]
154
+ pinpointClient. putEventsResult = . failure( ConnectivityError ( ) )
155
+ do {
156
+ let events = try await recorder. submitAllEvents ( )
157
+ XCTFail ( " Expected error " )
158
+ } catch {
159
+ XCTAssertEqual ( pinpointClient. putEventsCount, 1 )
160
+ XCTAssertEqual ( storage. events. count, 2 )
161
+ XCTAssertEqual ( storage. deleteEventCallCount, 0 )
162
+ XCTAssertEqual ( storage. eventRetryDictionary. count, 0 )
163
+ XCTAssertEqual ( storage. dirtyEventDictionary. count, 0 )
164
+ }
165
+ }
166
+ }
167
+
168
+ private struct RetryableError : Error , ModeledError {
169
+ static var typeName = " RetriableError "
170
+ static var fault = ErrorFault . client
171
+ static var isRetryable = true
172
+ static var isThrottling = false
173
+ }
174
+
175
+ private struct NonRetryableError : Error , ModeledError {
176
+ static var typeName = " RetriableError "
177
+ static var fault = ErrorFault . client
178
+ static var isRetryable = false
179
+ static var isThrottling = false
180
+ }
181
+
182
+ private class ConnectivityError : NSError {
183
+ init ( ) {
184
+ super. init (
185
+ domain: " ConnectivityError " ,
186
+ code: NSURLErrorNotConnectedToInternet
187
+ )
188
+ }
189
+
190
+ required init ? ( coder: NSCoder ) {
191
+ super. init ( coder: coder)
192
+ }
59
193
}
0 commit comments