1
+ package software .amazon .lambda .powertools .sqs ;
2
+
3
+ import java .io .ByteArrayInputStream ;
4
+ import java .io .IOException ;
5
+ import java .util .HashMap ;
6
+ import java .util .Map ;
7
+ import java .util .stream .Stream ;
8
+
9
+ import com .amazonaws .AmazonServiceException ;
10
+ import com .amazonaws .SdkClientException ;
11
+ import com .amazonaws .services .lambda .runtime .events .SQSEvent ;
12
+ import com .amazonaws .services .s3 .AmazonS3 ;
13
+ import com .amazonaws .services .s3 .model .S3Object ;
14
+ import com .amazonaws .services .s3 .model .S3ObjectInputStream ;
15
+ import com .amazonaws .util .StringInputStream ;
16
+ import org .apache .http .client .methods .HttpRequestBase ;
17
+ import org .junit .jupiter .api .BeforeEach ;
18
+ import org .junit .jupiter .api .Test ;
19
+ import org .junit .jupiter .params .ParameterizedTest ;
20
+ import org .junit .jupiter .params .provider .Arguments ;
21
+ import org .junit .jupiter .params .provider .MethodSource ;
22
+ import org .mockito .Mock ;
23
+ import software .amazon .lambda .powertools .sqs .internal .SqsMessageAspect ;
24
+
25
+ import static com .amazonaws .services .lambda .runtime .events .SQSEvent .SQSMessage ;
26
+ import static java .util .Collections .singletonList ;
27
+ import static org .apache .commons .lang3 .reflect .FieldUtils .writeStaticField ;
28
+ import static org .assertj .core .api .Assertions .assertThat ;
29
+ import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
30
+ import static org .mockito .Mockito .mock ;
31
+ import static org .mockito .Mockito .never ;
32
+ import static org .mockito .Mockito .verify ;
33
+ import static org .mockito .Mockito .verifyNoInteractions ;
34
+ import static org .mockito .Mockito .when ;
35
+ import static org .mockito .MockitoAnnotations .initMocks ;
36
+
37
+ class PowertoolsSqsTest {
38
+
39
+ @ Mock
40
+ private AmazonS3 amazonS3 ;
41
+ private static final String BUCKET_NAME = "ms-extended-sqs-client" ;
42
+ private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf" ;
43
+
44
+ @ BeforeEach
45
+ void setUp () throws IllegalAccessException {
46
+ initMocks (this );
47
+ writeStaticField (SqsMessageAspect .class , "amazonS3" , amazonS3 , true );
48
+ }
49
+
50
+ @ Test
51
+ public void testLargeMessage () {
52
+ S3Object s3Response = new S3Object ();
53
+ s3Response .setObjectContent (new ByteArrayInputStream ("A big message" .getBytes ()));
54
+
55
+ when (amazonS3 .getObject (BUCKET_NAME , BUCKET_KEY )).thenReturn (s3Response );
56
+ SQSEvent sqsEvent = messageWithBody ("[\" software.amazon.payloadoffloading.PayloadS3Pointer\" ,{\" s3BucketName\" :\" " + BUCKET_NAME + "\" ,\" s3Key\" :\" " + BUCKET_KEY + "\" }]" );
57
+
58
+ Map <String , String > sqsMessage = PowertoolsSqs .enrichedMessageFromS3 (sqsEvent , sqsMessages -> {
59
+ Map <String , String > someBusinessLogic = new HashMap <>();
60
+ someBusinessLogic .put ("Message" , sqsMessages .get (0 ).getBody ());
61
+ return someBusinessLogic ;
62
+ });
63
+
64
+ assertThat (sqsMessage )
65
+ .hasSize (1 )
66
+ .containsEntry ("Message" , "A big message" );
67
+
68
+ verify (amazonS3 ).deleteObject (BUCKET_NAME , BUCKET_KEY );
69
+ }
70
+
71
+ @ Test
72
+ public void shouldNotProcessSmallMessageBody () {
73
+ S3Object s3Response = new S3Object ();
74
+ s3Response .setObjectContent (new ByteArrayInputStream ("A big message" .getBytes ()));
75
+
76
+ when (amazonS3 .getObject (BUCKET_NAME , BUCKET_KEY )).thenReturn (s3Response );
77
+ SQSEvent sqsEvent = messageWithBody ("This is small message" );
78
+
79
+ Map <String , String > sqsMessage = PowertoolsSqs .enrichedMessageFromS3 (sqsEvent , sqsMessages -> {
80
+ Map <String , String > someBusinessLogic = new HashMap <>();
81
+ someBusinessLogic .put ("Message" , sqsMessages .get (0 ).getBody ());
82
+ return someBusinessLogic ;
83
+ });
84
+
85
+ assertThat (sqsMessage )
86
+ .containsEntry ("Message" , "This is small message" );
87
+
88
+ verifyNoInteractions (amazonS3 );
89
+ }
90
+
91
+ @ ParameterizedTest
92
+ @ MethodSource ("exception" )
93
+ public void shouldFailEntireBatchIfFailedDownloadingFromS3 (RuntimeException exception ) {
94
+ when (amazonS3 .getObject (BUCKET_NAME , BUCKET_KEY )).thenThrow (exception );
95
+
96
+ String messageBody = "[\" software.amazon.payloadoffloading.PayloadS3Pointer\" ,{\" s3BucketName\" :\" " + BUCKET_NAME + "\" ,\" s3Key\" :\" " + BUCKET_KEY + "\" }]" ;
97
+ SQSEvent sqsEvent = messageWithBody (messageBody );
98
+
99
+ assertThatExceptionOfType (SqsMessageAspect .FailedProcessingLargePayloadException .class )
100
+ .isThrownBy (() -> PowertoolsSqs .enrichedMessageFromS3 (sqsEvent , sqsMessages -> sqsMessages .get (0 ).getBody ()))
101
+ .withCause (exception );
102
+
103
+ verify (amazonS3 , never ()).deleteObject (BUCKET_NAME , BUCKET_KEY );
104
+ }
105
+
106
+ @ Test
107
+ public void shouldFailEntireBatchIfFailedProcessingDownloadMessageFromS3 () throws IOException {
108
+ S3Object s3Response = new S3Object ();
109
+
110
+ s3Response .setObjectContent (new S3ObjectInputStream (new StringInputStream ("test" ) {
111
+ @ Override
112
+ public void close () throws IOException {
113
+ throw new IOException ("Failed" );
114
+ }
115
+ }, mock (HttpRequestBase .class )));
116
+
117
+ when (amazonS3 .getObject (BUCKET_NAME , BUCKET_KEY )).thenReturn (s3Response );
118
+
119
+ String messageBody = "[\" software.amazon.payloadoffloading.PayloadS3Pointer\" ,{\" s3BucketName\" :\" " + BUCKET_NAME + "\" ,\" s3Key\" :\" " + BUCKET_KEY + "\" }]" ;
120
+ SQSEvent sqsEvent = messageWithBody (messageBody );
121
+
122
+ assertThatExceptionOfType (SqsMessageAspect .FailedProcessingLargePayloadException .class )
123
+ .isThrownBy (() -> PowertoolsSqs .enrichedMessageFromS3 (sqsEvent , sqsMessages -> sqsMessages .get (0 ).getBody ()))
124
+ .withCauseInstanceOf (IOException .class );
125
+
126
+ verify (amazonS3 , never ()).deleteObject (BUCKET_NAME , BUCKET_KEY );
127
+ }
128
+
129
+ private static Stream <Arguments > exception () {
130
+ return Stream .of (Arguments .of (new AmazonServiceException ("Service Exception" )),
131
+ Arguments .of (new SdkClientException ("Client Exception" )));
132
+ }
133
+
134
+ private SQSEvent messageWithBody (String messageBody ) {
135
+ SQSMessage sqsMessage = new SQSMessage ();
136
+ sqsMessage .setBody (messageBody );
137
+ SQSEvent sqsEvent = new SQSEvent ();
138
+ sqsEvent .setRecords (singletonList (sqsMessage ));
139
+ return sqsEvent ;
140
+ }
141
+ }
0 commit comments