16
16
package software .amazon .awssdk .services .sqs .batchmanager ;
17
17
18
18
19
+ import static org .assertj .core .api .Assertions .assertThat ;
19
20
import static org .junit .jupiter .api .Assertions .assertEquals ;
20
- import static org .junit .jupiter .api .Assertions .assertNotEquals ;
21
21
import static org .mockito .ArgumentCaptor .forClass ;
22
+ import static org .mockito .ArgumentMatchers .any ;
23
+ import static org .mockito .Mockito .atLeast ;
24
+ import static org .mockito .Mockito .times ;
25
+ import static org .mockito .Mockito .verify ;
26
+ import static org .mockito .Mockito .when ;
22
27
28
+ import java .time .Duration ;
23
29
import java .util .Collections ;
24
30
import java .util .HashMap ;
25
31
import java .util .Map ;
32
+ import java .util .concurrent .CompletableFuture ;
26
33
import java .util .concurrent .Executors ;
34
+ import java .util .concurrent .ScheduledExecutorService ;
27
35
import java .util .concurrent .TimeUnit ;
28
36
import java .util .stream .Stream ;
37
+
38
+ import org .apache .logging .log4j .Level ;
29
39
import org .junit .jupiter .api .DisplayName ;
30
40
import org .junit .jupiter .api .extension .ExtendWith ;
31
41
import org .junit .jupiter .params .ParameterizedTest ;
43
53
import software .amazon .awssdk .services .sqs .model .QueueAttributeName ;
44
54
import software .amazon .awssdk .services .sqs .model .ReceiveMessageRequest ;
45
55
import software .amazon .awssdk .services .sqs .model .ReceiveMessageResponse ;
46
-
47
- import java .util .concurrent .CompletableFuture ;
48
- import java .util .concurrent .ScheduledExecutorService ;
49
-
50
- import static org .mockito .ArgumentMatchers .any ;
51
- import static org .mockito .Mockito .*;
52
-
56
+ import software .amazon .awssdk .testutils .LogCaptor ;
53
57
54
58
@ ExtendWith (MockitoExtension .class )
55
59
class ReceiveMessageBatchManagerTest {
56
60
61
+ private static final ScheduledExecutorService EXECUTOR = Executors .newScheduledThreadPool (4 );
62
+
57
63
@ Mock
58
64
private SqsAsyncClient sqsClient ;
59
65
60
- private final ScheduledExecutorService executor = Executors .newScheduledThreadPool (4 );
61
-
62
66
private ReceiveMessageBatchManager receiveMessageBatchManager ;
63
67
64
-
65
68
@ ParameterizedTest (name = "{index} => {0}" )
66
69
@ MethodSource ("provideBatchOverrideConfigurations" )
67
70
@ DisplayName ("Test BatchRequest with various configurations" )
68
- void testBatchRequest_WhenBufferingDisabledAndInCompatible_ShouldNotUseBatchManager (String testCaseName ,
69
- ResponseBatchConfiguration overrideConfig ,
70
- ReceiveMessageRequest request ,
71
- boolean useBatchManager ) throws Exception {
72
-
73
- // Initialize the ResponseBatchConfiguration and ReceiveMessageBatchManager
74
- ResponseBatchConfiguration config = ResponseBatchConfiguration .builder ()
75
- .messageSystemAttributeNames (overrideConfig .messageSystemAttributeNames ())
76
- .receiveMessageAttributeNames (overrideConfig .receiveMessageAttributeNames ())
77
- .visibilityTimeout (overrideConfig .visibilityTimeout ())
78
- .messageMinWaitDuration (overrideConfig .messageMinWaitDuration ()).build ();
79
-
80
- receiveMessageBatchManager = new ReceiveMessageBatchManager (sqsClient , executor , overrideConfig );
81
-
82
- CompletableFuture <ReceiveMessageResponse > mockResponse =
83
- CompletableFuture .completedFuture (ReceiveMessageResponse .builder ().build ());
84
- String visibilityTimeout = "1" ;
85
- when (sqsClient .receiveMessage (any (ReceiveMessageRequest .class ))).thenReturn (mockResponse );
86
- if (useBatchManager ) {
87
- mockGetQueueAttributesResponse ("0" , visibilityTimeout );
88
- }
71
+ void testBatchRequest (String testCaseName ,
72
+ ResponseBatchConfiguration overrideConfig ,
73
+ ReceiveMessageRequest request ,
74
+ boolean useBatchManager ,
75
+ String inEligibleReason ) throws Exception {
89
76
77
+ setupBatchManager (overrideConfig );
90
78
91
- CompletableFuture <ReceiveMessageResponse > result = receiveMessageBatchManager .batchRequest (request );
92
- result .get (2 , TimeUnit .SECONDS );
79
+ CompletableFuture <ReceiveMessageResponse > mockResponse = CompletableFuture .completedFuture (
80
+ ReceiveMessageResponse .builder ().build ());
81
+ when (sqsClient .receiveMessage (any (ReceiveMessageRequest .class ))).thenReturn (mockResponse );
93
82
94
- // Enough time to make sure any spawned task after receiving response is completed
95
- Thread .sleep (500 );
83
+ try (LogCaptor logCaptor = LogCaptor .create (Level .DEBUG )) {
96
84
97
- // Capture the argument passed to receiveMessage
98
- ArgumentCaptor <ReceiveMessageRequest > requestCaptor = forClass (ReceiveMessageRequest .class );
85
+ if (useBatchManager ) {
86
+ mockQueueAttributes ("0" , "1" );
87
+ }
99
88
100
- if (useBatchManager ) {
101
- verify (sqsClient , atLeast (1 )).receiveMessage (requestCaptor .capture ());
89
+ CompletableFuture <ReceiveMessageResponse > result = receiveMessageBatchManager .batchRequest (request );
90
+ result .get (2 , TimeUnit .SECONDS );
91
+ Thread .sleep (500 );
102
92
103
- // Assertions to verify the behavior when batch manager is used
104
- assertEquals (config .maxBatchItems (), requestCaptor .getValue ().maxNumberOfMessages ());
105
- assertEquals (Integer .parseInt (visibilityTimeout ), requestCaptor .getValue ().visibilityTimeout ());
106
- } else {
107
- verify (sqsClient , times (1 )).receiveMessage (requestCaptor .capture ());
93
+ ArgumentCaptor <ReceiveMessageRequest > requestCaptor = forClass (ReceiveMessageRequest .class );
108
94
109
- // Assertions to verify the behavior when batch manager is not used
110
- assertEquals ( request . maxNumberOfMessages (), requestCaptor . getValue (). maxNumberOfMessages () );
111
- assertEquals ( request . visibilityTimeout (), requestCaptor . getValue (). visibilityTimeout ());
112
- assertNotEquals ( config . maxBatchItems (),
113
- requestCaptor . getValue (). maxNumberOfMessages ());
95
+ if ( useBatchManager ) {
96
+ verifyBatchManagerUsed ( requestCaptor );
97
+ } else {
98
+ verifyBatchManagerNotUsed ( request , requestCaptor , logCaptor , inEligibleReason );
99
+ }
114
100
}
115
101
}
116
102
103
+ private void setupBatchManager (ResponseBatchConfiguration overrideConfig ) {
104
+ receiveMessageBatchManager = new ReceiveMessageBatchManager (sqsClient , EXECUTOR , overrideConfig );
105
+ }
117
106
107
+ private void verifyBatchManagerUsed (ArgumentCaptor <ReceiveMessageRequest > requestCaptor ) {
108
+ verify (sqsClient , atLeast (1 )).receiveMessage (requestCaptor .capture ());
109
+ assertEquals (ResponseBatchConfiguration .MAX_DONE_RECEIVE_BATCHES_DEFAULT ,
110
+ requestCaptor .getValue ().maxNumberOfMessages ());
111
+ }
112
+
113
+ private void verifyBatchManagerNotUsed (ReceiveMessageRequest request ,
114
+ ArgumentCaptor <ReceiveMessageRequest > requestCaptor ,
115
+ LogCaptor logCaptor ,
116
+ String inEligibleReason ) {
117
+ verify (sqsClient , times (1 )).receiveMessage (requestCaptor .capture ());
118
+ assertEquals (request .maxNumberOfMessages (), requestCaptor .getValue ().maxNumberOfMessages ());
119
+ assertEquals (request .visibilityTimeout (), requestCaptor .getValue ().visibilityTimeout ());
120
+ assertThat (logCaptor .loggedEvents ())
121
+ .anySatisfy (logEvent -> assertThat (logEvent .getMessage ().getFormattedMessage ())
122
+ .contains (inEligibleReason ));
123
+ }
124
+
125
+ private void mockQueueAttributes (String receiveMessageWaitTimeSeconds , String visibilityTimeout ) {
126
+ Map <QueueAttributeName , String > attributes = new HashMap <>();
127
+ attributes .put (QueueAttributeName .RECEIVE_MESSAGE_WAIT_TIME_SECONDS , receiveMessageWaitTimeSeconds );
128
+ attributes .put (QueueAttributeName .VISIBILITY_TIMEOUT , visibilityTimeout );
129
+
130
+ GetQueueAttributesResponse response = GetQueueAttributesResponse .builder ()
131
+ .attributes (attributes )
132
+ .build ();
133
+
134
+ when (sqsClient .getQueueAttributes (any (GetQueueAttributesRequest .class )))
135
+ .thenReturn (CompletableFuture .completedFuture (response ));
136
+ }
118
137
119
138
private static Stream <Arguments > provideBatchOverrideConfigurations () {
120
139
return Stream .of (
121
140
Arguments .of (
122
- "Buffering enabled, compatible system and message attributes, and no visibility timeout" ,
141
+ "Buffering enabled, compatible system and message attributes, no visibility timeout" ,
123
142
ResponseBatchConfiguration .builder ()
124
143
.receiveMessageAttributeNames (Collections .singletonList ("attr1" ))
125
144
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
@@ -129,10 +148,11 @@ private static Stream<Arguments> provideBatchOverrideConfigurations() {
129
148
.messageAttributeNames (Collections .singletonList ("attr1" ))
130
149
.messageSystemAttributeNames (MessageSystemAttributeName .SENDER_ID )
131
150
.build (),
132
- true
151
+ true ,
152
+ ""
133
153
),
134
154
Arguments .of (
135
- "Buffering , compatible attributes, and no visibility timeout" ,
155
+ "Buffering enabled , compatible attributes, no visibility timeout but deprecated attributeNames " ,
136
156
ResponseBatchConfiguration .builder ()
137
157
.receiveMessageAttributeNames (Collections .singletonList ("attr1" ))
138
158
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
@@ -141,27 +161,27 @@ private static Stream<Arguments> provideBatchOverrideConfigurations() {
141
161
.queueUrl ("testQueueUrl" )
142
162
.messageAttributeNames (Collections .singletonList ("attr1" ))
143
163
.messageSystemAttributeNamesWithStrings (Collections .singletonList ("SenderId" ))
144
- // attributeNames which is Deprecated api not supported for Batching
145
- .attributeNames (QueueAttributeName .ALL )
164
+ .attributeNames (QueueAttributeName .ALL ) // Deprecated api not supported for Batching
146
165
.build (),
147
- false
166
+ false ,
167
+ "Incompatible attributes."
148
168
),
149
169
Arguments .of (
150
- "Buffering disabled, incompatible system attributes, and no visibility timeout" ,
170
+ "Buffering disabled, incompatible system attributes, no visibility timeout" ,
151
171
ResponseBatchConfiguration .builder ()
152
172
.receiveMessageAttributeNames (Collections .singletonList ("attr1" ))
153
173
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENT_TIMESTAMP ))
154
174
.build (),
155
175
ReceiveMessageRequest .builder ()
156
176
.queueUrl ("testQueueUrl" )
157
177
.messageAttributeNames (Collections .singletonList ("attr1" ))
158
- .messageSystemAttributeNamesWithStrings (Collections .singletonList ("SenderId" )) //
159
- // Incompatible system attribute
178
+ .messageSystemAttributeNamesWithStrings (Collections .singletonList ("SenderId" ))
160
179
.build (),
161
- false
180
+ false ,
181
+ "Incompatible attributes."
162
182
),
163
183
Arguments .of (
164
- "Buffering disabled, compatible attributes, but visibility timeout is set" ,
184
+ "Buffering disabled, compatible attributes, visibility timeout is set" ,
165
185
ResponseBatchConfiguration .builder ()
166
186
.receiveMessageAttributeNames (Collections .singletonList ("attr1" ))
167
187
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
@@ -170,12 +190,13 @@ private static Stream<Arguments> provideBatchOverrideConfigurations() {
170
190
.queueUrl ("testQueueUrl" )
171
191
.messageAttributeNames (Collections .singletonList ("attr1" ))
172
192
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
173
- .visibilityTimeout (30 ) // Visibility timeout is set
193
+ .visibilityTimeout (30 )
174
194
.build (),
175
- false
195
+ false ,
196
+ "Visibility timeout is set."
176
197
),
177
198
Arguments .of (
178
- "Buffering disabled, compatible attributes, no visibility timeout, but request has attribute names" ,
199
+ "Buffering disabled, compatible attributes, no visibility timeout but has attribute names" ,
179
200
ResponseBatchConfiguration .builder ()
180
201
.receiveMessageAttributeNames (Collections .singletonList ("attr1" ))
181
202
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
@@ -184,36 +205,49 @@ private static Stream<Arguments> provideBatchOverrideConfigurations() {
184
205
.queueUrl ("testQueueUrl" )
185
206
.messageAttributeNames (Collections .singletonList ("attr1" ))
186
207
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
187
- .attributeNamesWithStrings ("All" ) // Request has attribute names
208
+ .attributeNamesWithStrings ("All" )
188
209
.build (),
189
- false
210
+ false ,
211
+ "Incompatible attributes."
190
212
),
191
213
Arguments .of (
192
- "Buffering enabled, with messageSystemAttributeName in Config and simple ReceiveMessageRequest " ,
214
+ "Buffering enabled, simple ReceiveMessageRequest, no visibility timeout " ,
193
215
ResponseBatchConfiguration .builder ()
194
216
.messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
195
217
.build (),
196
218
ReceiveMessageRequest .builder ()
197
219
.queueUrl ("testQueueUrl" )
198
220
.maxNumberOfMessages (3 )
199
221
.build (),
200
- true
222
+ true ,
223
+ ""
224
+ ),
225
+ Arguments .of (
226
+ "Buffering disabled, request has override config" ,
227
+ ResponseBatchConfiguration .builder ()
228
+ .messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
229
+ .build (),
230
+ ReceiveMessageRequest .builder ()
231
+ .queueUrl ("testQueueUrl" )
232
+ .maxNumberOfMessages (3 )
233
+ .overrideConfiguration (o -> o .apiCallTimeout (Duration .ofSeconds (2 )))
234
+ .build (),
235
+ false ,
236
+ "Request has override configurations."
237
+ ),
238
+ Arguments .of (
239
+ "Buffering disabled, with waitTimeSeconds in ReceiveMessageRequest" ,
240
+ ResponseBatchConfiguration .builder ()
241
+ .messageSystemAttributeNames (Collections .singletonList (MessageSystemAttributeName .SENDER_ID ))
242
+ .build (),
243
+ ReceiveMessageRequest .builder ()
244
+ .queueUrl ("testQueueUrl" )
245
+ .maxNumberOfMessages (3 )
246
+ .waitTimeSeconds (3 )
247
+ .build (),
248
+ false ,
249
+ "Request has long polling enabled."
201
250
)
202
251
);
203
252
}
204
-
205
- private void mockGetQueueAttributesResponse (String receiveMessageWaitTimeSeconds , String visibilityTimeout ) {
206
- Map <QueueAttributeName , String > attributes = new HashMap <>();
207
- attributes .put (QueueAttributeName .RECEIVE_MESSAGE_WAIT_TIME_SECONDS , receiveMessageWaitTimeSeconds );
208
- attributes .put (QueueAttributeName .VISIBILITY_TIMEOUT , visibilityTimeout );
209
-
210
- GetQueueAttributesResponse response = GetQueueAttributesResponse .builder ()
211
- .attributes (attributes )
212
- .build ();
213
-
214
- when (sqsClient .getQueueAttributes (any (GetQueueAttributesRequest .class )))
215
- .thenReturn (CompletableFuture .completedFuture (response ));
216
- }
217
-
218
-
219
253
}
0 commit comments