Skip to content

Commit af68c9a

Browse files
authored
[doc]: add javadoc for sdk/sdk-testing package (#200)
* add javadoc for sdk/sdk-testing package * fix some javadoc * add some more javadoc * add some more javadoc
1 parent 3e574d0 commit af68c9a

48 files changed

Lines changed: 341 additions & 26 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/src/main/java/software/amazon/lambda/durable/examples/GenericInputOutputExample.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
/**
1717
* Example demonstrating a durable Lambda function that uses generic types in input and output.
1818
*
19-
* <p>This example shows how to use TypeToken to work with generic types like List<String>, Map<String, List<String,
20-
* String>, and nested generics that cannot be represented by simple Class objects.
19+
* <p>This example shows how to use TypeToken to work with generic types like {@code List<String>}, {@code Map<String,
20+
* List<String>>}, and nested generics that cannot be represented by simple Class objects.
2121
*/
2222
public class GenericInputOutputExample
2323
extends DurableHandler<Map<String, String>, Map<String, Map<String, List<String>>>> {

examples/src/main/java/software/amazon/lambda/durable/examples/GenericTypesExample.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
/**
1717
* Example demonstrating TypeToken support for complex generic types.
1818
*
19-
* <p>This example shows how to use TypeToken to work with generic types like List<String>, Map<String, Object>, and
20-
* nested generics that cannot be represented by simple Class objects.
19+
* <p>This example shows how to use TypeToken to work with generic types like {@code List<String>}, {@code Map<String,
20+
* Object>}, and nested generics that cannot be represented by simple Class objects.
2121
*/
2222
public class GenericTypesExample extends DurableHandler<GenericTypesExample.Input, GenericTypesExample.Output> {
2323

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<version>0.7.0-SNAPSHOT</version>
1010
<packaging>pom</packaging>
1111

12-
<name>AWS Lambda Durable Execution SDK Parent</name>
12+
<name>AWS Lambda Durable Execution SDK</name>
1313
<description>Parent POM for AWS Lambda Durable Execution SDK and Examples</description>
1414
<url>https://github.com/aws/aws-durable-execution-sdk-java</url>
1515

sdk-testing/src/main/java/software/amazon/lambda/durable/testing/CloudDurableTestRunner.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
import software.amazon.lambda.durable.TypeToken;
1212
import software.amazon.lambda.durable.serde.JacksonSerDes;
1313

14+
/**
15+
* Test runner for durable Lambda functions deployed to AWS. Invokes a real Lambda function, polls execution history,
16+
* and returns structured test results.
17+
*
18+
* @param <I> the handler input type
19+
* @param <O> the handler output type
20+
*/
1421
public class CloudDurableTestRunner<I, O> {
1522
private final String functionArn;
1623
private final TypeToken<I> inputType;
@@ -39,11 +46,13 @@ private CloudDurableTestRunner(
3946
this.invocationType = invocationType;
4047
}
4148

49+
/** Creates a runner for the given function ARN with Class-based input/output types. */
4250
public static <I, O> CloudDurableTestRunner<I, O> create(
4351
String functionArn, Class<I> inputType, Class<O> outputType) {
4452
return create(functionArn, TypeToken.get(inputType), TypeToken.get(outputType));
4553
}
4654

55+
/** Creates a runner for the given function ARN with TypeToken-based input/output types. */
4756
public static <I, O> CloudDurableTestRunner<I, O> create(
4857
String functionArn, TypeToken<I> inputType, TypeToken<O> outputType) {
4958
return new CloudDurableTestRunner<>(
@@ -59,11 +68,13 @@ public static <I, O> CloudDurableTestRunner<I, O> create(
5968
InvocationType.REQUEST_RESPONSE);
6069
}
6170

71+
/** Creates a runner with a custom {@link LambdaClient} and Class-based input/output types. */
6272
public static <I, O> CloudDurableTestRunner<I, O> create(
6373
String functionArn, Class<I> inputType, Class<O> outputType, LambdaClient lambdaClient) {
6474
return create(functionArn, TypeToken.get(inputType), TypeToken.get(outputType), lambdaClient);
6575
}
6676

77+
/** Creates a runner with a custom {@link LambdaClient} and TypeToken-based input/output types. */
6778
public static <I, O> CloudDurableTestRunner<I, O> create(
6879
String functionArn, TypeToken<I> inputType, TypeToken<O> outputType, LambdaClient lambdaClient) {
6980
return new CloudDurableTestRunner<>(
@@ -76,21 +87,25 @@ public static <I, O> CloudDurableTestRunner<I, O> create(
7687
InvocationType.REQUEST_RESPONSE);
7788
}
7889

90+
/** Returns a new runner with the specified poll interval between history checks. */
7991
public CloudDurableTestRunner<I, O> withPollInterval(Duration interval) {
8092
return new CloudDurableTestRunner<>(
8193
functionArn, inputType, outputType, lambdaClient, interval, timeout, invocationType);
8294
}
8395

96+
/** Returns a new runner with the specified maximum wait time for execution completion. */
8497
public CloudDurableTestRunner<I, O> withTimeout(Duration timeout) {
8598
return new CloudDurableTestRunner<>(
8699
functionArn, inputType, outputType, lambdaClient, pollInterval, timeout, invocationType);
87100
}
88101

102+
/** Returns a new runner with the specified Lambda invocation type. */
89103
public CloudDurableTestRunner<I, O> withInvocationType(InvocationType type) {
90104
return new CloudDurableTestRunner<>(
91105
functionArn, inputType, outputType, lambdaClient, pollInterval, timeout, type);
92106
}
93107

108+
/** Invokes the Lambda function, polls execution history until completion, and returns the result. */
94109
public TestResult<O> run(I input) {
95110
try {
96111
// Serialize input
@@ -167,6 +182,7 @@ public AsyncExecution<O> startAsync(I input) {
167182
}
168183
}
169184

185+
/** Returns the {@link TestOperation} for the given name from the last execution result. */
170186
public TestOperation getOperation(String name) {
171187
if (lastResult == null) {
172188
throw new IllegalStateException("No execution has been run yet");

sdk-testing/src/main/java/software/amazon/lambda/durable/testing/HistoryEventProcessor.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,21 @@
1919
import software.amazon.lambda.durable.model.ExecutionStatus;
2020
import software.amazon.lambda.durable.serde.JacksonSerDes;
2121

22+
/**
23+
* Processes execution history events from the GetDurableExecutionHistory API into {@link TestResult} objects. Used by
24+
* {@link CloudDurableTestRunner} and {@link AsyncExecution} to convert cloud execution history into testable results.
25+
*/
2226
public class HistoryEventProcessor {
2327
private final JacksonSerDes serDes = new JacksonSerDes();
2428

29+
/**
30+
* Processes a list of execution history events into a structured {@link TestResult}.
31+
*
32+
* @param events the raw history events from the GetDurableExecutionHistory API
33+
* @param outputType the expected output type for deserialization
34+
* @param <O> the handler output type
35+
* @return a TestResult containing the execution status, output, and operation details
36+
*/
2537
public <O> TestResult<O> processEvents(List<Event> events, TypeToken<O> outputType) {
2638
var operations = new HashMap<String, Operation>();
2739
var operationEvents = new HashMap<String, List<Event>>();

sdk-testing/src/main/java/software/amazon/lambda/durable/testing/HistoryPoller.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,27 @@
1111
import software.amazon.awssdk.services.lambda.model.EventType;
1212
import software.amazon.awssdk.services.lambda.model.GetDurableExecutionHistoryRequest;
1313

14+
/**
15+
* Polls the GetDurableExecutionHistory API until execution completes or a timeout is reached. Used by
16+
* {@link CloudDurableTestRunner} for synchronous test execution.
17+
*/
1418
public class HistoryPoller {
1519
private final LambdaClient lambdaClient;
1620

21+
/** Creates a poller backed by the given Lambda client. */
1722
public HistoryPoller(LambdaClient lambdaClient) {
1823
this.lambdaClient = lambdaClient;
1924
}
2025

26+
/**
27+
* Polls execution history until a terminal event is found or the timeout is exceeded.
28+
*
29+
* @param executionArn the durable execution ARN to poll
30+
* @param pollInterval the interval between poll requests
31+
* @param timeout the maximum time to wait for completion
32+
* @return all history events collected during polling
33+
* @throws RuntimeException if the timeout is exceeded or polling is interrupted
34+
*/
2135
public List<Event> pollUntilComplete(String executionArn, Duration pollInterval, Duration timeout) {
2236
var allEvents = new ArrayList<Event>();
2337
var startTime = Instant.now();

sdk-testing/src/main/java/software/amazon/lambda/durable/testing/LocalDurableTestRunner.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
import software.amazon.lambda.durable.serde.JacksonSerDes;
2323
import software.amazon.lambda.durable.serde.SerDes;
2424

25+
/**
26+
* In-memory test runner for durable Lambda functions. Simulates the Lambda re-invocation loop locally without requiring
27+
* AWS infrastructure, enabling fast unit and integration tests.
28+
*
29+
* @param <I> the handler input type
30+
* @param <O> the handler output type
31+
*/
2532
public class LocalDurableTestRunner<I, O> {
2633
private static final int MAX_INVOCATIONS = 100;
2734

@@ -51,6 +58,12 @@ private LocalDurableTestRunner(
5158
/**
5259
* Creates a LocalDurableTestRunner with default configuration. Use this method when your handler uses the default
5360
* DurableConfig.
61+
*
62+
* @param inputType The input type class
63+
* @param handlerFn The handler function
64+
* @param <I> Input type
65+
* @param <O> Output type
66+
* @return LocalDurableTestRunner with default configuration
5467
*/
5568
public static <I, O> LocalDurableTestRunner<I, O> create(
5669
Class<I> inputType, BiFunction<I, DurableContext, O> handlerFn) {
@@ -81,6 +94,13 @@ public static <I, O> LocalDurableTestRunner<I, O> create(
8194
/**
8295
* Creates a LocalDurableTestRunner that uses a custom configuration. This allows the test runner to use custom
8396
* SerDes and other configuration, while overriding the DurableExecutionClient with the in-memory implementation.
97+
*
98+
* @param inputType The input type class
99+
* @param handlerFn The handler function
100+
* @param config The DurableConfig to use (DurableExecutionClient will be overridden with in-memory implementation)
101+
* @param <I> Input type
102+
* @param <O> Output type
103+
* @return LocalDurableTestRunner configured with the provided settings
84104
*/
85105
public static <I, O> LocalDurableTestRunner<I, O> create(
86106
Class<I> inputType, BiFunction<I, DurableContext, O> handlerFn, DurableConfig config) {
@@ -129,6 +149,12 @@ public static <I, O> LocalDurableTestRunner<I, O> create(
129149
* Creates a LocalDurableTestRunner from a DurableHandler instance, automatically extracting the configuration. This
130150
* is a convenient method when you have a handler instance and want to test it with the same configuration it uses
131151
* in production.
152+
*
153+
* @param inputType The input type class
154+
* @param handler The DurableHandler instance to test
155+
* @param <I> Input type
156+
* @param <O> Output type
157+
* @return LocalDurableTestRunner configured with the handler's settings
132158
*/
133159
public static <I, O> LocalDurableTestRunner<I, O> create(Class<I> inputType, DurableHandler<I, O> handler) {
134160
return new LocalDurableTestRunner<>(
@@ -220,14 +246,17 @@ public TestResult<O> runUntilComplete(I input) {
220246
return result;
221247
}
222248

249+
/** Resets a named step operation to STARTED status, simulating a checkpoint failure. */
223250
public void resetCheckpointToStarted(String stepName) {
224251
storage.resetCheckpointToStarted(stepName);
225252
}
226253

254+
/** Removes a named step operation entirely, simulating loss of a fire-and-forget checkpoint. */
227255
public void simulateFireAndForgetCheckpointLoss(String stepName) {
228256
storage.simulateFireAndForgetCheckpointLoss(stepName);
229257
}
230258

259+
/** Returns the {@link TestOperation} for the given operation name, or null if not found. */
231260
public TestOperation getOperation(String name) {
232261
var op = storage.getOperationByName(name);
233262
return op != null ? new TestOperation(op, serDes) : null;
@@ -253,27 +282,27 @@ public void timeoutCallback(String callbackId) {
253282
storage.timeoutCallback(callbackId);
254283
}
255284

256-
// Manual time advancement for skipTime=false scenarios
285+
/** Advances all pending operations, simulating time passing for retries and waits. */
257286
public void advanceTime() {
258287
storage.advanceReadyOperations();
259288
}
260289

261-
// Manual complete a chained invoke call
290+
/** Completes a chained invoke operation with a successful result. */
262291
public void completeChainedInvoke(String name, String result) {
263292
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.SUCCEEDED, result, null));
264293
}
265294

266-
// Manual mark a chained invoke call TIMEOUT
295+
/** Marks a chained invoke operation as timed out. */
267296
public void timeoutChainedInvoke(String name) {
268297
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.TIMED_OUT, null, null));
269298
}
270299

271-
// Manual fail a chained invoke call
300+
/** Fails a chained invoke operation with the given error. */
272301
public void failChainedInvoke(String name, ErrorObject error) {
273302
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.FAILED, null, error));
274303
}
275304

276-
// Manual stop a chained invoke call
305+
/** Stops a chained invoke operation with the given error. */
277306
public void stopChainedInvoke(String name, ErrorObject error) {
278307
storage.completeChainedInvoke(name, new OperationResult(OperationStatus.STOPPED, null, error));
279308
}

sdk-testing/src/main/java/software/amazon/lambda/durable/testing/LocalMemoryExecutionClient.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
import software.amazon.lambda.durable.serde.JacksonSerDes;
1818
import software.amazon.lambda.durable.serde.SerDes;
1919

20+
/**
21+
* In-memory implementation of {@link DurableExecutionClient} for local testing. Stores operations and checkpoint state
22+
* in memory, simulating the durable execution backend without AWS infrastructure.
23+
*/
2024
public class LocalMemoryExecutionClient implements DurableExecutionClient {
2125
private final Map<String, Operation> operations = new ConcurrentHashMap<>();
2226
private final List<Event> allEvents = new CopyOnWriteArrayList<>();
@@ -96,6 +100,7 @@ public boolean advanceReadyOperations() {
96100
return replaced.get();
97101
}
98102

103+
/** Completes a chained invoke operation with the given result, simulating a child Lambda response. */
99104
public void completeChainedInvoke(String name, OperationResult result) {
100105
var op = getOperationByName(name);
101106
if (op == null) {
@@ -126,17 +131,20 @@ public void completeChainedInvoke(String name, OperationResult result) {
126131
}
127132
}
128133

134+
/** Returns the operation with the given name, or null if not found. */
129135
public Operation getOperationByName(String name) {
130136
return operations.values().stream()
131137
.filter(op -> name.equals(op.name()))
132138
.findFirst()
133139
.orElse(null);
134140
}
135141

142+
/** Returns all operations currently stored. */
136143
public List<Operation> getAllOperations() {
137144
return operations.values().stream().toList();
138145
}
139146

147+
/** Clears all operations and events, resetting the client to its initial state. */
140148
public void reset() {
141149
operations.clear();
142150
allEvents.clear();

sdk-testing/src/main/java/software/amazon/lambda/durable/testing/TestOperation.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,47 @@ public class TestOperation {
3030
this.serDes = serDes;
3131
}
3232

33+
/** Returns the raw history events associated with this operation. */
3334
public List<Event> getEvents() {
3435
return List.copyOf(events);
3536
}
3637

38+
/** Returns the operation name. */
3739
public String getName() {
3840
return operation.name();
3941
}
4042

43+
/** Returns the current status of this operation (e.g. STARTED, SUCCEEDED, FAILED). */
4144
public OperationStatus getStatus() {
4245
return operation.status();
4346
}
4447

48+
/** Returns the operation type (STEP, WAIT, CALLBACK, etc.). */
4549
public OperationType getType() {
4650
return operation.type();
4751
}
4852

53+
/** Returns the step details, or null if this is not a step operation. */
4954
public StepDetails getStepDetails() {
5055
return operation.stepDetails();
5156
}
5257

58+
/** Returns the wait details, or null if this is not a wait operation. */
5359
public WaitDetails getWaitDetails() {
5460
return operation.waitDetails();
5561
}
5662

63+
/** Returns the callback details, or null if this is not a callback operation. */
5764
public CallbackDetails getCallbackDetails() {
5865
return operation.callbackDetails();
5966
}
6067

68+
/** Deserializes and returns the step result as the given type. */
6169
public <T> T getStepResult(Class<T> type) {
6270
return getStepResult(TypeToken.get(type));
6371
}
6472

65-
/** Type-safe result extraction from step details. */
73+
/** Deserializes and returns the step result using a TypeToken for generic types. */
6674
public <T> T getStepResult(TypeToken<T> type) {
6775
var details = operation.stepDetails();
6876
if (details == null || details.result() == null) {
@@ -71,11 +79,13 @@ public <T> T getStepResult(TypeToken<T> type) {
7179
return serDes.deserialize(details.result(), type);
7280
}
7381

82+
/** Returns the step error, or null if the step succeeded or this is not a step operation. */
7483
public ErrorObject getError() {
7584
var details = operation.stepDetails();
7685
return details != null ? details.error() : null;
7786
}
7887

88+
/** Returns the current retry attempt number (1-based), defaulting to 1 if not available. */
7989
public int getAttempt() {
8090
var details = operation.stepDetails();
8191
return details != null && details.attempt() != null ? details.attempt() : 1;

0 commit comments

Comments
 (0)