Skip to content

Commit 97e2860

Browse files
author
Pankaj Agrawal
committed
Initial Test cases setup and some refactorings
1 parent 0752389 commit 97e2860

File tree

8 files changed

+185
-9
lines changed

8 files changed

+185
-9
lines changed

powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/PowertoolsSqs.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*/
1414
package software.amazon.lambda.powertools.sqs;
1515

16+
import java.lang.reflect.Constructor;
17+
import java.lang.reflect.InvocationTargetException;
1618
import java.util.ArrayList;
1719
import java.util.List;
1820
import java.util.function.Function;
@@ -100,8 +102,16 @@ public static <R> List<R> partialBatchProcessor(final SQSEvent event,
100102
final Class<? extends SqsMessageHandler<R>> handler) {
101103

102104
try {
103-
return partialBatchProcessor(event, suppressException, handler.newInstance());
104-
} catch (IllegalAccessException | InstantiationException e) {
105+
SqsMessageHandler<R> handlerInstance;
106+
if (null == handler.getDeclaringClass()) {
107+
handlerInstance = handler.newInstance();
108+
} else {
109+
Constructor<? extends SqsMessageHandler<R>> constructor = handler.getDeclaredConstructor(handler.getDeclaringClass());
110+
constructor.setAccessible(true);
111+
handlerInstance = constructor.newInstance(handler.getDeclaringClass().newInstance());
112+
}
113+
return partialBatchProcessor(event, suppressException, handlerInstance);
114+
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
105115
LOG.error("Failed invoking process method on handler", e);
106116
throw new RuntimeException("Unexpected error occurred. Please raise issue at " +
107117
"https://github.com/awslabs/aws-lambda-powertools-java/issues", e);
@@ -124,7 +134,12 @@ public static <R> List<R> partialBatchProcessor(final SQSEvent event,
124134
}
125135
}
126136

127-
batchContext.processSuccessAndReset(suppressException);
137+
try {
138+
batchContext.processSuccessAndReset(suppressException);
139+
} catch (SQSBatchProcessingException e) {
140+
e.addSuccessMessageReturnValues(handlerReturn);
141+
throw e;
142+
}
128143

129144
return handlerReturn;
130145
}

powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,56 @@
33
import java.util.ArrayList;
44
import java.util.List;
55

6+
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
7+
68
import static java.util.stream.Collectors.joining;
79

810
public class SQSBatchProcessingException extends RuntimeException {
911

1012
private final List<Exception> exceptions;
13+
private final List<SQSEvent.SQSMessage> failures;
14+
private final List<Object> returnValues;
1115

12-
public SQSBatchProcessingException(List<Exception> exceptions) {
16+
public <T> SQSBatchProcessingException(final List<Exception> exceptions,
17+
final List<SQSEvent.SQSMessage> failures,
18+
final List<T> successReturns) {
1319
this.exceptions = new ArrayList<>(exceptions);
20+
this.failures = new ArrayList<>(failures);
21+
this.returnValues = new ArrayList<>(successReturns);
22+
}
23+
24+
public List<Exception> getExceptions() {
25+
return exceptions;
26+
}
27+
28+
public List<Object> successMessageReturnValues() {
29+
return returnValues;
30+
}
31+
32+
public List<SQSEvent.SQSMessage> getFailures() {
33+
return failures;
1434
}
1535

1636
@Override
1737
public String getMessage() {
1838
return exceptions.stream()
19-
.map(Throwable::getMessage)
39+
.map(Throwable::toString)
2040
.collect(joining("\n"));
2141
}
42+
43+
@Override
44+
public void printStackTrace() {
45+
for (Exception exception : exceptions) {
46+
exception.printStackTrace();
47+
}
48+
}
49+
50+
@Override
51+
public String toString() {
52+
return getMessage();
53+
}
54+
55+
<T> void addSuccessMessageReturnValues(final List<T> returnValues) {
56+
this.returnValues.addAll(returnValues);
57+
}
2258
}

powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package software.amazon.lambda.powertools.sqs.internal;
22

3+
import java.awt.geom.Area;
34
import java.util.ArrayList;
45
import java.util.List;
56

@@ -36,7 +37,7 @@ public void addFailure(SQSMessage event, Exception e) {
3637
exceptions.add(e);
3738
}
3839

39-
public void processSuccessAndReset(final boolean suppressException) {
40+
public <T> void processSuccessAndReset(final boolean suppressException) {
4041
try {
4142
if (hasFailures()) {
4243

@@ -46,7 +47,7 @@ public void processSuccessAndReset(final boolean suppressException) {
4647
List<String> messageIds = failures.stream().map(SQSMessage::getMessageId).collect(toList());
4748
LOG.debug(format("[%s] records failed processing, but exceptions are suppressed. Failed messages %s", failures.size(), messageIds));
4849
} else {
49-
throw new SQSBatchProcessingException(exceptions);
50+
throw new SQSBatchProcessingException(exceptions, failures, new ArrayList<T>());
5051
}
5152
}
5253
} finally {

powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ && placedOnSqsEventRequestHandler(pjp)) {
2929

3030
SQSEvent sqsEvent = (SQSEvent) proceedArgs[0];
3131

32-
partialBatchProcessor(sqsEvent, sqsBatchProcessor.suppressException(), sqsBatchProcessor.value().newInstance());
32+
partialBatchProcessor(sqsEvent, sqsBatchProcessor.suppressException(), sqsBatchProcessor.value());
3333
}
3434

3535
return pjp.proceed(proceedArgs);
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package software.amazon.lambda.powertools.sqs;
2+
3+
import java.io.IOException;
4+
import java.util.List;
5+
import java.util.stream.Stream;
6+
7+
import com.amazonaws.AmazonServiceException;
8+
import com.amazonaws.SdkClientException;
9+
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
10+
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import org.junit.jupiter.api.BeforeEach;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.params.ParameterizedTest;
14+
import org.junit.jupiter.params.provider.Arguments;
15+
import org.junit.jupiter.params.provider.ValueSource;
16+
import software.amazon.awssdk.services.sqs.SqsClient;
17+
18+
import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.mockito.Mockito.mock;
21+
import static org.mockito.Mockito.times;
22+
import static org.mockito.Mockito.verify;
23+
import static org.mockito.Mockito.verifyNoInteractions;
24+
25+
class PowertoolsSqsBatchProcessorTest {
26+
27+
private final SqsClient sqsClient = mock(SqsClient.class);
28+
private final SqsClient interactionClient = mock(SqsClient.class);
29+
private static final ObjectMapper MAPPER = new ObjectMapper();
30+
private SQSEvent event;
31+
32+
@BeforeEach
33+
void setUp() throws IOException {
34+
event = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEvent.json"), SQSEvent.class);
35+
PowertoolsSqs.defaultSqsClient(sqsClient);
36+
}
37+
38+
@Test
39+
void shouldBatchProcessAndNotDeleteMessagesWhenAllSuccess() {
40+
List<String> returnValues = PowertoolsSqs.partialBatchProcessor(event, false, (message) -> {
41+
interactionClient.listQueues();
42+
return "Success";
43+
});
44+
45+
assertThat(returnValues)
46+
.hasSize(2)
47+
.containsExactly("Success", "Success");
48+
49+
verify(interactionClient, times(2)).listQueues();
50+
verifyNoInteractions(sqsClient);
51+
}
52+
53+
@ParameterizedTest
54+
@ValueSource(classes = {SampleInnerSqsHandler.class, SampleSqsHandler.class})
55+
void shouldBatchProcessViaClassAndNotDeleteMessagesWhenAllSuccess(Class<? extends SqsMessageHandler<String>> handler) {
56+
List<String> returnValues = PowertoolsSqs.partialBatchProcessor(event, false, handler);
57+
58+
assertThat(returnValues)
59+
.hasSize(2)
60+
.containsExactly("0", "1");
61+
}
62+
63+
private static Stream<Arguments> exception() {
64+
return Stream.of(Arguments.of(new AmazonServiceException("Service Exception")),
65+
Arguments.of(new SdkClientException("Client Exception")));
66+
}
67+
68+
public class SampleInnerSqsHandler implements SqsMessageHandler<String> {
69+
private int counter;
70+
71+
@Override
72+
public String process(SQSMessage message) {
73+
return String.valueOf(counter++);
74+
}
75+
}
76+
}

powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/PowertoolsSqsTest.java renamed to powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/PowertoolsSqsLargeMessageTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import static org.mockito.Mockito.when;
3636
import static org.mockito.MockitoAnnotations.openMocks;
3737

38-
class PowertoolsSqsTest {
38+
class PowertoolsSqsLargeMessageTest {
3939

4040
@Mock
4141
private AmazonS3 amazonS3;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package software.amazon.lambda.powertools.sqs;
2+
3+
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
4+
5+
public class SampleSqsHandler implements SqsMessageHandler<String> {
6+
private int counter;
7+
8+
@Override
9+
public String process(SQSEvent.SQSMessage message) {
10+
return String.valueOf(counter++);
11+
}
12+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"records": [
3+
{
4+
"messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
5+
"receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
6+
"body": "Test message.",
7+
"attributes": {
8+
"ApproximateReceiveCount": "1",
9+
"SentTimestamp": "1545082649183",
10+
"SenderId": "AIDAIENQZJOLO23YVJ4VO",
11+
"ApproximateFirstReceiveTimestamp": "1545082649185"
12+
},
13+
"messageAttributes": {},
14+
"md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
15+
"eventSource": "aws:sqs",
16+
"eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue",
17+
"awsRegion": "us-east-2"
18+
},
19+
{
20+
"messageId": "2e1424d4-f796-459a-8184-9c92662be6da",
21+
"receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...",
22+
"body": "Test message.",
23+
"attributes": {
24+
"ApproximateReceiveCount": "1",
25+
"SentTimestamp": "1545082650636",
26+
"SenderId": "AIDAIENQZJOLO23YVJ4VO",
27+
"ApproximateFirstReceiveTimestamp": "1545082650649"
28+
},
29+
"messageAttributes": {},
30+
"md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
31+
"eventSource": "aws:sqs",
32+
"eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue",
33+
"awsRegion": "us-east-2"
34+
}
35+
]
36+
}

0 commit comments

Comments
 (0)