/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://aws.amazon.com/apache2.0
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and
* limitations under the License.
*/
package com.amazonaws.mobileconnectors.lambdainvoker;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.util.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.nio.ByteBuffer;
public class LambdaInvocationHandlerTest {
private LambdaInvocationHandler handler;
private AWSLambda lambda;
private LambdaInvokerFactory factory;
private MockInterface invoker;
@Before
public void setup() {
lambda = Mockito.mock(AWSLambda.class);
factory = new LambdaInvokerFactory(lambda, null);
invoker = factory.build(MockInterface.class);
handler = (LambdaInvocationHandler) Proxy.getInvocationHandler(invoker);
}
static interface MockInterface {
void noAnnotation();
@LambdaFunction
void oneArgument(String a);
@LambdaFunction
void twoArguments(String a, String b);
@LambdaFunction
void variableArguments(String... a);
@LambdaFunction
String echo(String a);
@LambdaFunction(functionName = "echo", invocationType = "Event")
String echoAlias(String a);
@LambdaFunction(qualifier = "version")
String echoVersion(String a);
@LambdaFunction
String echoNoArgument();
}
@Test(expected = UnsupportedOperationException.class)
public void testNoAnnotation() throws Exception {
Method noAnnotation = getMethod("noAnnotation");
handler.validateInterfaceMethod(noAnnotation, null);
}
@Test(expected = UnsupportedOperationException.class)
public void testTwoArguments() throws Exception {
Method twoArguments = getMethod("twoArguments", String.class, String.class);
handler.validateInterfaceMethod(twoArguments, new Object[] {
"a", "b"
});
}
@Test(expected = UnsupportedOperationException.class)
public void testVariableArguments() throws Exception {
Method variableArguments = getMethod("variableArguments", String[].class);
handler.validateInterfaceMethod(variableArguments, new Object[] {
"a", "b"
});
}
@Test
public void testOneArgument() throws Exception {
Method oneArgument = getMethod("oneArgument", String.class);
handler.validateInterfaceMethod(oneArgument, new Object[] {
"a"
});
}
@Test
public void testBuildInvokeRequest() throws Exception {
Method echo = getMethod("echo", String.class);
String input = "hello world";
InvokeRequest request = handler.buildInvokeRequest(echo, input);
assertEquals("function name", "echo", request.getFunctionName());
assertEquals("invocation type", "RequestResponse", request.getInvocationType());
assertNull("default qualifier", request.getQualifier());
// Json encoding puts double quotes around a string
String json = "\"" + input + "\"";
ByteBuffer payload = stringToByteBuffer(json);
assertArrayEquals("payload", payload.array(), request.getPayload().array());
}
@Test
public void testBuildInvokeRequestOverride() throws Exception {
Method echoAlias = getMethod("echoAlias", String.class);
InvokeRequest request = handler.buildInvokeRequest(echoAlias, "hello world");
assertEquals("function name", "echo", request.getFunctionName());
// invocation type is forced as RequestResponse because log type is
// empty/None
assertEquals("invocation type", "RequestResponse", request.getInvocationType());
}
@Test
public void testBuildInvokeRequestVersion() throws Exception {
Method echoVersion = getMethod("echoVersion", String.class);
InvokeRequest request = handler.buildInvokeRequest(echoVersion, "hello world");
assertEquals("function name", "echoVersion", request.getFunctionName());
assertEquals("qualifier", "version", request.getQualifier());
}
@Test
public void testProcessInvokeResult() throws Exception {
Method echo = getMethod("echo", String.class);
InvokeResult invokeResult = createInvokeResult(200, null, "\"hello world\"");
String result = (String) handler.processInvokeResult(echo, invokeResult);
assertEquals("same result", "hello world", result);
}
@Test
public void testProcessInvokeResult204() throws Exception {
Method echo = getMethod("echo", String.class);
InvokeResult invokeResult = createInvokeResult(204, null, null);
invokeResult.setStatusCode(204);
invokeResult.setFunctionError(null);
invokeResult.setPayload(null);
String result = (String) handler.processInvokeResult(echo, invokeResult);
assertNull("no content", result);
}
@Test(expected = LambdaFunctionException.class)
public void testException() throws Exception {
Method echo = getMethod("echo", String.class);
String error = "Panic!";
String payload = "Bulls eye";
InvokeResult invokeResult = createInvokeResult(200, error, payload);
try {
handler.processInvokeResult(echo, invokeResult);
} catch (LambdaFunctionException lfe) {
assertEquals("error message", error, lfe.getMessage());
assertEquals("payload", payload, lfe.getDetails());
throw lfe;
}
}
@Test
public void testInvoke() {
String input = "Hello world!";
InvokeResult invokeResult = createInvokeResult(200, null, "\"" + input + "\"");
Mockito.when(lambda.invoke(Matchers.any(InvokeRequest.class))).thenReturn(invokeResult);
String result = invoker.echo(input);
assertEquals("echo", input, result);
}
@Test
public void testInvokeNoArgument() throws Exception {
String echoResult = "No argument";
InvokeResult invokeResult = createInvokeResult(200, null, "\"" + echoResult + "\"");
Mockito.when(lambda.invoke(Matchers.any(InvokeRequest.class))).thenReturn(invokeResult);
String result = invoker.echoNoArgument();
assertEquals("echoNoArgument", echoResult, result);
}
@Test(expected = LambdaFunctionException.class)
public void testInvokeException() {
String input = "Hello world!";
String error = "Panic!";
String payload = "Bulls eye";
InvokeResult invokeResult = createInvokeResult(200, error, payload);
Mockito.when(lambda.invoke(Matchers.any(InvokeRequest.class))).thenReturn(invokeResult);
try {
invoker.echo(input);
} catch (LambdaFunctionException lfe) {
assertEquals("error message", error, lfe.getMessage());
assertEquals("payload", payload, lfe.getDetails());
throw lfe;
}
}
private Method getMethod(String name, Class<?>... classes)
throws NoSuchMethodException, SecurityException {
return MockInterface.class.getMethod(name, classes);
}
private ByteBuffer stringToByteBuffer(String s) {
if (s == null) {
return null;
}
return ByteBuffer.wrap(s.getBytes(StringUtils.UTF8));
}
private InvokeResult createInvokeResult(int statusCode, String error, String payload) {
InvokeResult invokeResult = new InvokeResult();
invokeResult.setStatusCode(statusCode);
invokeResult.setFunctionError(error);
invokeResult.setPayload(stringToByteBuffer(payload));
return invokeResult;
}
}