Skip to content

Commit 0fc8be6

Browse files
authored
misc: add unit test for runtime API (#503)
1 parent 8af7655 commit 0fc8be6

File tree

2 files changed

+388
-0
lines changed

2 files changed

+388
-0
lines changed

Diff for: aws-lambda-java-runtime-interface-client/pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@
8787
<version>4.11.0</version>
8888
<scope>test</scope>
8989
</dependency>
90+
<dependency>
91+
<groupId>com.squareup.okhttp3</groupId>
92+
<artifactId>mockwebserver</artifactId>
93+
<version>4.12.0</version>
94+
<scope>test</scope>
95+
</dependency>
9096
</dependencies>
9197

9298
<build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
7+
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.Test;
10+
import org.junit.jupiter.api.condition.DisabledOnOs;
11+
import org.junit.jupiter.api.condition.OS;
12+
13+
import static org.junit.jupiter.api.Assertions.assertTrue;
14+
import static org.junit.jupiter.api.Assertions.assertNull;
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertThrows;
17+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.ErrorRequest;
18+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.StackElement;
19+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayErrorCause;
20+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayException;
21+
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
25+
import static org.junit.jupiter.api.Assertions.fail;
26+
import okhttp3.HttpUrl;
27+
import static java.net.HttpURLConnection.HTTP_ACCEPTED;
28+
import static java.net.HttpURLConnection.HTTP_OK;
29+
import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
30+
import okhttp3.mockwebserver.MockWebServer;
31+
32+
import okhttp3.mockwebserver.MockResponse;
33+
import okhttp3.mockwebserver.RecordedRequest;
34+
35+
@DisabledOnOs(OS.MAC)
36+
public class LambdaRuntimeApiClientImplTest {
37+
38+
MockWebServer mockWebServer;
39+
LambdaRuntimeApiClientImpl lambdaRuntimeApiClientImpl;
40+
41+
String[] errorStackStrace = { "item0", "item1", "item2" };
42+
ErrorRequest errorRequest = new ErrorRequest("testErrorMessage", "testErrorType", errorStackStrace);
43+
44+
String requestId = "1234";
45+
46+
@BeforeEach
47+
void setUp() {
48+
mockWebServer = new MockWebServer();
49+
String hostnamePort = getHostnamePort();
50+
lambdaRuntimeApiClientImpl = new LambdaRuntimeApiClientImpl(hostnamePort);
51+
}
52+
53+
@Test
54+
public void reportInitErrorTest() {
55+
try {
56+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
57+
58+
MockResponse mockResponse = new MockResponse();
59+
mockResponse.setResponseCode(HTTP_ACCEPTED);
60+
mockWebServer.enqueue(mockResponse);
61+
62+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
63+
lambdaRuntimeApiClientImpl.reportInitError(lambdaError);
64+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
65+
HttpUrl actualUrl = recordedRequest.getRequestUrl();
66+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/init/error";
67+
assertEquals(expectedUrl, actualUrl.toString());
68+
69+
String userAgentHeader = recordedRequest.getHeader("User-Agent");
70+
assertTrue(userAgentHeader.startsWith("aws-lambda-java/"));
71+
72+
String lambdaRuntimeErrorTypeHeader = recordedRequest.getHeader("Lambda-Runtime-Function-Error-Type");
73+
assertEquals("Runtime.AfterRestoreError", lambdaRuntimeErrorTypeHeader);
74+
75+
String actualBody = recordedRequest.getBody().readUtf8();
76+
assertEquals("{\"errorMessage\":\"testErrorMessage\",\"errorType\":\"testErrorType\",\"stackTrace\":[\"item0\",\"item1\",\"item2\"]}", actualBody);
77+
} catch(Exception e) {
78+
fail();
79+
}
80+
}
81+
82+
@Test
83+
public void reportInitErrorTestWrongStatusCode() {
84+
int errorStatusCode = HTTP_INTERNAL_ERROR;
85+
try {
86+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
87+
88+
MockResponse mockResponse = new MockResponse();
89+
mockResponse.setResponseCode(errorStatusCode);
90+
mockWebServer.enqueue(mockResponse);
91+
92+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
93+
lambdaRuntimeApiClientImpl.reportInitError(lambdaError);
94+
fail();
95+
} catch(LambdaRuntimeClientException e) {
96+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/init/error";
97+
String expectedMessage = expectedUrl + " Response code: '" + errorStatusCode + "'.";
98+
assertEquals(expectedMessage, e.getLocalizedMessage());
99+
} catch(Exception e) {
100+
fail();
101+
}
102+
}
103+
104+
@Test
105+
public void reportRestoreErrorTest() {
106+
try {
107+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
108+
109+
MockResponse mockResponse = new MockResponse();
110+
mockResponse.setResponseCode(HTTP_ACCEPTED);
111+
mockWebServer.enqueue(mockResponse);
112+
113+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
114+
lambdaRuntimeApiClientImpl.reportRestoreError(lambdaError);
115+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
116+
HttpUrl actualUrl = recordedRequest.getRequestUrl();
117+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/restore/error";
118+
assertEquals(expectedUrl, actualUrl.toString());
119+
120+
String userAgentHeader = recordedRequest.getHeader("User-Agent");
121+
assertTrue(userAgentHeader.startsWith("aws-lambda-java/"));
122+
123+
String lambdaRuntimeErrorTypeHeader = recordedRequest.getHeader("Lambda-Runtime-Function-Error-Type");
124+
assertEquals("Runtime.AfterRestoreError", lambdaRuntimeErrorTypeHeader);
125+
126+
String actualBody = recordedRequest.getBody().readUtf8();
127+
assertEquals("{\"errorMessage\":\"testErrorMessage\",\"errorType\":\"testErrorType\",\"stackTrace\":[\"item0\",\"item1\",\"item2\"]}", actualBody);
128+
} catch(Exception e) {
129+
fail();
130+
}
131+
}
132+
133+
@Test
134+
public void reportRestoreErrorTestWrongStatusCode() {
135+
int errorStatusCode = HTTP_INTERNAL_ERROR;
136+
try {
137+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
138+
139+
MockResponse mockResponse = new MockResponse();
140+
mockResponse.setResponseCode(errorStatusCode);
141+
mockWebServer.enqueue(mockResponse);
142+
143+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
144+
lambdaRuntimeApiClientImpl.reportRestoreError(lambdaError);
145+
fail();
146+
} catch(LambdaRuntimeClientException e) {
147+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/restore/error";
148+
String expectedMessage = expectedUrl + " Response code: '" + errorStatusCode + "'.";
149+
assertEquals(expectedMessage, e.getLocalizedMessage());
150+
} catch(Exception e) {
151+
fail();
152+
}
153+
}
154+
155+
@Test
156+
public void reportInvocationErrorTest() {
157+
try {
158+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
159+
160+
MockResponse mockResponse = new MockResponse();
161+
mockResponse.setResponseCode(HTTP_ACCEPTED);
162+
mockWebServer.enqueue(mockResponse);
163+
164+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
165+
lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
166+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
167+
HttpUrl actualUrl = recordedRequest.getRequestUrl();
168+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/error";
169+
assertEquals(expectedUrl, actualUrl.toString());
170+
171+
String userAgentHeader = recordedRequest.getHeader("User-Agent");
172+
assertTrue(userAgentHeader.startsWith("aws-lambda-java/"));
173+
174+
String lambdaRuntimeErrorTypeHeader = recordedRequest.getHeader("Lambda-Runtime-Function-Error-Type");
175+
assertEquals("Runtime.AfterRestoreError", lambdaRuntimeErrorTypeHeader);
176+
177+
String actualBody = recordedRequest.getBody().readUtf8();
178+
assertEquals("{\"errorMessage\":\"testErrorMessage\",\"errorType\":\"testErrorType\",\"stackTrace\":[\"item0\",\"item1\",\"item2\"]}", actualBody);
179+
} catch(Exception e) {
180+
fail();
181+
}
182+
}
183+
184+
@Test
185+
public void reportInvocationErrorTestWrongStatusCode() {
186+
int errorStatusCode = HTTP_INTERNAL_ERROR;
187+
try {
188+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
189+
190+
MockResponse mockResponse = new MockResponse();
191+
mockResponse.setResponseCode(errorStatusCode);
192+
mockWebServer.enqueue(mockResponse);
193+
194+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
195+
lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
196+
fail();
197+
} catch(LambdaRuntimeClientException e) {
198+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/error";
199+
String expectedMessage = expectedUrl + " Response code: '" + errorStatusCode + "'.";
200+
assertEquals(expectedMessage, e.getLocalizedMessage());
201+
} catch(Exception e) {
202+
fail();
203+
}
204+
}
205+
206+
@Test
207+
public void reportLambdaErrorWithXRayTest() {
208+
try {
209+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
210+
211+
MockResponse mockResponse = new MockResponse();
212+
mockResponse.setResponseCode(HTTP_ACCEPTED);
213+
mockWebServer.enqueue(mockResponse);
214+
215+
String workingDirectory = "my-test-directory";
216+
List<String> paths = new ArrayList<String>();
217+
paths.add("path-0");
218+
paths.add("path-1");
219+
paths.add("path-2");
220+
221+
List<StackElement> stackElements0 = new ArrayList<>();
222+
stackElements0.add(new StackElement("label0", "path0", 0));
223+
stackElements0.add(new StackElement("label1", "path1", 1));
224+
stackElements0.add(new StackElement("label2", "path2", 2));
225+
XRayException xRayException0 = new XRayException("my-test-message0", "my-test-type0", stackElements0);
226+
227+
List<StackElement> stackElements1 = new ArrayList<>();
228+
stackElements1.add(new StackElement("label10", "path10", 0));
229+
stackElements1.add(new StackElement("label11", "path11", 11));
230+
stackElements1.add(new StackElement("label12", "path12", 12));
231+
XRayException xRayException1 = new XRayException("my-test-message1", "my-test-type0", stackElements1);
232+
233+
List<XRayException> exceptions = new ArrayList<>();
234+
exceptions.add(xRayException0);
235+
exceptions.add(xRayException1);
236+
237+
XRayErrorCause xRayErrorCause = new XRayErrorCause(workingDirectory, exceptions, paths);
238+
LambdaError lambdaError = new LambdaError(errorRequest, xRayErrorCause, rapidErrorType);
239+
lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
240+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
241+
242+
String xrayErrorCauseHeader = recordedRequest.getHeader("Lambda-Runtime-Function-XRay-Error-Cause");
243+
assertEquals("{\"working_directory\":\"my-test-directory\",\"exceptions\":[{\"message\":\"my-test-message0\",\"type\":\"my-test-type0\",\"stack\":[{\"label\":\"label0\"," +
244+
"\"path\":\"path0\",\"line\":0},{\"label\":\"label1\",\"path\":\"path1\",\"line\":1},{\"label\":\"label2\",\"path\":\"path2\",\"line\":2}]},{\"message\":\"my-test-message1\"," +
245+
"\"type\":\"my-test-type0\",\"stack\":[{\"label\":\"label10\",\"path\":\"path10\",\"line\":0},{\"label\":\"label11\",\"path\":\"path11\",\"line\":11},{\"label\":\"label12\"," +
246+
"\"path\":\"path12\",\"line\":12}]}],\"paths\":[\"path-0\",\"path-1\",\"path-2\"]}", xrayErrorCauseHeader);
247+
} catch(Exception e) {
248+
fail();
249+
}
250+
}
251+
252+
@Test
253+
public void reportInvocationSuccessTest() {
254+
try {
255+
MockResponse mockResponse = new MockResponse();
256+
mockResponse.setResponseCode(HTTP_ACCEPTED);
257+
mockWebServer.enqueue(mockResponse);
258+
259+
String response = "{\"msg\":\"test\"}";
260+
lambdaRuntimeApiClientImpl.reportInvocationSuccess(requestId, response.getBytes());
261+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
262+
HttpUrl actualUrl = recordedRequest.getRequestUrl();
263+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/response";
264+
assertEquals(expectedUrl, actualUrl.toString());
265+
266+
String actualBody = recordedRequest.getBody().readUtf8();
267+
assertEquals("{\"msg\":\"test\"}", actualBody);
268+
} catch(Exception e) {
269+
e.printStackTrace();
270+
fail();
271+
}
272+
}
273+
274+
@Test
275+
public void restoreNextTest() {
276+
try {
277+
MockResponse mockResponse = new MockResponse();
278+
mockResponse.setResponseCode(HTTP_OK);
279+
mockWebServer.enqueue(mockResponse);
280+
281+
lambdaRuntimeApiClientImpl.restoreNext();
282+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
283+
HttpUrl actualUrl = recordedRequest.getRequestUrl();
284+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/restore/next";
285+
assertEquals(expectedUrl, actualUrl.toString());
286+
287+
String actualBody = recordedRequest.getBody().readUtf8();
288+
assertEquals("", actualBody);
289+
} catch(Exception e) {
290+
e.printStackTrace();
291+
fail();
292+
}
293+
}
294+
295+
@Test
296+
public void restoreNextWrongStatusCodeTest() {
297+
int errorStatusCode = HTTP_INTERNAL_ERROR;
298+
try {
299+
MockResponse mockResponse = new MockResponse();
300+
mockResponse.setResponseCode(errorStatusCode);
301+
mockWebServer.enqueue(mockResponse);
302+
303+
lambdaRuntimeApiClientImpl.restoreNext();
304+
fail();
305+
} catch(LambdaRuntimeClientException e) {
306+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/restore/next";
307+
String expectedMessage = expectedUrl + " Response code: '" + errorStatusCode + "'.";
308+
assertEquals(expectedMessage, e.getLocalizedMessage());
309+
} catch(Exception e) {
310+
fail();
311+
}
312+
}
313+
314+
@Test
315+
public void nextTest() {
316+
try {
317+
MockResponse mockResponse = new MockResponse();
318+
mockResponse.setResponseCode(HTTP_ACCEPTED);
319+
mockResponse.setHeader("lambda-runtime-aws-request-id", "1234567890");
320+
mockResponse.setHeader("Content-Type", "application/json");
321+
mockWebServer.enqueue(mockResponse);
322+
323+
lambdaRuntimeApiClientImpl.nextInvocation();
324+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
325+
HttpUrl actualUrl = recordedRequest.getRequestUrl();
326+
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/next";
327+
assertEquals(expectedUrl, actualUrl.toString());
328+
329+
String actualBody = recordedRequest.getBody().readUtf8();
330+
assertEquals("", actualBody);
331+
} catch(Exception e) {
332+
fail();
333+
}
334+
}
335+
336+
337+
@Test
338+
public void createUrlMalformedTest() {
339+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
340+
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
341+
RuntimeException thrown = assertThrows(RuntimeException.class, ()->{
342+
lambdaRuntimeApiClientImpl.reportLambdaError("invalidurl", lambdaError, 100);
343+
});
344+
assertTrue(thrown.getLocalizedMessage().contains("java.net.MalformedURLException"));
345+
}
346+
347+
@Test
348+
public void lambdaReportErrorXRayHeaderTooLongTest() {
349+
try {
350+
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
351+
352+
MockResponse mockResponse = new MockResponse();
353+
mockResponse.setResponseCode(HTTP_ACCEPTED);
354+
mockWebServer.enqueue(mockResponse);
355+
356+
String workingDirectory = "my-test-directory";
357+
List<String> paths = new ArrayList<String>();
358+
paths.add("path-0");
359+
360+
List<StackElement> stackElements = new ArrayList<>();
361+
stackElements.add(new StackElement("label0", "path0", 0));
362+
XRayException xRayException = new XRayException("my-test-message0", "my-test-type0", stackElements);
363+
364+
List<XRayException> exceptions = new ArrayList<>();
365+
exceptions.add(xRayException);
366+
367+
XRayErrorCause xRayErrorCause = new XRayErrorCause(workingDirectory, exceptions, paths);
368+
LambdaError lambdaError = new LambdaError(errorRequest, xRayErrorCause, rapidErrorType);
369+
lambdaRuntimeApiClientImpl.reportLambdaError("http://" + getHostnamePort(), lambdaError, 10);
370+
RecordedRequest recordedRequest = mockWebServer.takeRequest();
371+
372+
String xrayErrorCauseHeader = recordedRequest.getHeader("Lambda-Runtime-Function-XRay-Error-Cause");
373+
assertNull(xrayErrorCauseHeader);
374+
} catch(Exception e) {
375+
fail();
376+
}
377+
}
378+
379+
private String getHostnamePort() {
380+
return mockWebServer.getHostName() + ":" + mockWebServer.getPort();
381+
}
382+
}

0 commit comments

Comments
 (0)