Skip to content

Commit

Permalink
chore(unit-test): Add missing unit tests in modules with low coverage (
Browse files Browse the repository at this point in the history
…#1264)

* chore(unit-tests): add unit tests to powertools-core
* chore(unit-tests): add unit tests to powertools-parameters
* chore(unit-tests): add unit tests to powertools-serialization
* chore(unit-tests): add unit tests to powertools-validation
* chore(unit-tests): add unit tests to powertools-logging

* chore(unit-tests): minor formatting fixes

* chore(unit-tests): add missing return statement

* chore(unit-test): rename, reformat, fix typos as suggested from code review

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>

* chore(unit-tests): address review comments

* chore(unit-tests): revert refactoring of EventDeserializer

* chore(unit-tests): expand and optimize imports

* chore(unit-tests): change response of base64gzip when decompressing empty string

* chore(unit-tests): add unit test and fix config for wrong arg type in base64gzip function invocation

* chore(unit-tests): fix base64gzip function invocation for argument value argument

---------

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
  • Loading branch information
eldimi and jeromevdl authored Jul 10, 2023
1 parent 2c282a9 commit c7aedc4
Show file tree
Hide file tree
Showing 79 changed files with 1,728 additions and 316 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@
<version>3.1.2</version>
<configuration>
<argLine>
@{argLine}
--add-opens java.base/java.util=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
</argLine>
Expand Down
5 changes: 5 additions & 0 deletions powertools-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ public class LambdaConstants {
public static final String AWS_REGION_ENV = "AWS_REGION";
public static final String AWS_LAMBDA_INITIALIZATION_TYPE = "AWS_LAMBDA_INITIALIZATION_TYPE";
public static final String ON_DEMAND = "on-demand";
public static final String X_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID";
public static final String AWS_SAM_LOCAL = "AWS_SAM_LOCAL";
public static final String ROOT_EQUALS = "Root=";
public static final String POWERTOOLS_SERVICE_NAME = "POWERTOOLS_SERVICE_NAME";
public static final String SERVICE_UNDEFINED = "service_undefined";
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,21 @@
import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;

public final class LambdaHandlerProcessor {

// SERVICE_NAME cannot be final for testing purposes
private static String SERVICE_NAME = null != System.getenv("POWERTOOLS_SERVICE_NAME")
? System.getenv("POWERTOOLS_SERVICE_NAME") : "service_undefined";
private static String SERVICE_NAME = calculateServiceName();

private static Boolean IS_COLD_START = null;

private LambdaHandlerProcessor() {
// Hide default constructor
}

private static String calculateServiceName() {
return null != getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME)
? getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME) : LambdaConstants.SERVICE_UNDEFINED;
}

public static boolean isHandlerMethod(final ProceedingJoinPoint pjp) {
return placedOnRequestHandler(pjp) || placedOnStreamHandler(pjp);
}
Expand All @@ -56,23 +62,24 @@ public static boolean placedOnStreamHandler(final ProceedingJoinPoint pjp) {

public static Context extractContext(final ProceedingJoinPoint pjp) {

if (isHandlerMethod(pjp)) {
if (placedOnRequestHandler(pjp)) {
return (Context) pjp.getArgs()[1];
}

if (placedOnStreamHandler(pjp)) {
return (Context) pjp.getArgs()[2];
}
if (placedOnRequestHandler(pjp)) {
return (Context) pjp.getArgs()[1];
} else if (placedOnStreamHandler(pjp)) {
return (Context) pjp.getArgs()[2];
} else {
return null;
}

return null;
}

public static String serviceName() {
return SERVICE_NAME;
}

// Method used for testing purposes
protected static void resetServiceName() {
SERVICE_NAME = calculateServiceName();
}

public static boolean isColdStart() {
return IS_COLD_START == null;
}
Expand All @@ -82,13 +89,13 @@ public static void coldStartDone() {
}

public static boolean isSamLocal() {
return "true".equals(System.getenv("AWS_SAM_LOCAL"));
return "true".equals(getenv(LambdaConstants.AWS_SAM_LOCAL));
}

public static Optional<String> getXrayTraceId() {
final String X_AMZN_TRACE_ID = getenv("_X_AMZN_TRACE_ID");
if(X_AMZN_TRACE_ID != null) {
return of(X_AMZN_TRACE_ID.split(";")[0].replace("Root=", ""));
final String X_AMZN_TRACE_ID = getenv(LambdaConstants.X_AMZN_TRACE_ID);
if (X_AMZN_TRACE_ID != null) {
return of(X_AMZN_TRACE_ID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, ""));
}
return empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,231 @@
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;

class LambdaHandlerProcessorTest {

private Signature signature = mock(Signature.class);
private ProceedingJoinPoint pjpMock = mock(ProceedingJoinPoint.class);

@Test
void isHandlerMethod_shouldRecognizeRequestHandler() {
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp();
Object[] args = {new Object(), mock(Context.class)};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args);

assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue();
}

@Test
void isHandlerMethod_shouldRecognizeRequestStreamHandler() {
ProceedingJoinPoint pjpMock = mockRequestStreamHandlerPjp();
Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue();
}

@Test
void isHandlerMethod_shouldReturnFalse() {
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(Object.class, new Object[]{});

boolean isHandlerMethod = LambdaHandlerProcessor.isHandlerMethod(pjpMock);

assertThat(isHandlerMethod).isFalse();
}

@Test
void placedOnRequestHandler_shouldRecognizeRequestHandler() {
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp();
Object[] args = {new Object(), mock(Context.class)};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args);

assertThat(LambdaHandlerProcessor.placedOnRequestHandler(pjpMock)).isTrue();
}

@Test
void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() {
ProceedingJoinPoint pjpMock = mockRequestStreamHandlerPjp();
Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue();
}

private static ProceedingJoinPoint mockRequestHandlerPjp() {
Signature signature = mock(Signature.class);
when(signature.getDeclaringType()).thenReturn(RequestHandler.class);
ProceedingJoinPoint pjpMock = mock(ProceedingJoinPoint.class);
@Test
void placedOnRequestHandler_shouldInvalidateOnWrongNoOfArgs() {
Object[] args = {new Object()};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args);

boolean isPlacedOnRequestHandler = LambdaHandlerProcessor.placedOnRequestHandler(pjpMock);

assertThat(isPlacedOnRequestHandler).isFalse();
}

@Test
void placedOnRequestHandler_shouldInvalidateOnWrongTypeOfArgs() {
Object[] args = {new Object(), new Object()};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args);

boolean isPlacedOnRequestHandler = LambdaHandlerProcessor.placedOnRequestHandler(pjpMock);

assertThat(isPlacedOnRequestHandler).isFalse();
}

@Test
void placedOnStreamHandler_shouldInvalidateOnWrongNoOfArgs() {
Object[] args = {new Object()};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock);

assertThat(isPlacedOnStreamHandler).isFalse();
}

@Test
void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() {
Object[] args = {new Object(), new Object(), new Object()};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock);

assertThat(isPlacedOnStreamHandler).isFalse();
}

@Test
void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() {
Object[] args = {mock(InputStream.class), new Object(), mock(Context.class)};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock);

assertThat(isPlacedOnStreamHandler).isFalse();
}

@Test
void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() {
Object[] args = {mock(InputStream.class), mock(OutputStream.class), new Object()};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock);

assertThat(isPlacedOnStreamHandler).isFalse();
}

@Test
void getXrayTraceId_present() {
String traceID = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"";
try (MockedStatic<SystemWrapper> mockedSystemWrapper = mockStatic(SystemWrapper.class)) {
mockedSystemWrapper.when(() -> getenv(LambdaConstants.X_AMZN_TRACE_ID)).thenReturn(traceID);

Optional xRayTraceId = LambdaHandlerProcessor.getXrayTraceId();

assertThat(xRayTraceId.isPresent()).isTrue();
assertThat(traceID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")).isEqualTo(xRayTraceId.get());
}
}

@Test
void getXrayTraceId_notPresent() {
try (MockedStatic<SystemWrapper> mockedSystemWrapper = mockStatic(SystemWrapper.class)) {
mockedSystemWrapper.when(() -> getenv(LambdaConstants.X_AMZN_TRACE_ID)).thenReturn(null);

boolean isXRayTraceIdPresent = LambdaHandlerProcessor.getXrayTraceId().isPresent();

assertThat(isXRayTraceIdPresent).isFalse();
}
}

@Test
void extractContext_fromRequestHandler() {
Object[] args = {new Object(), mock(Context.class)};
when(pjpMock.getArgs()).thenReturn(args);
when(pjpMock.getSignature()).thenReturn(signature);
return pjpMock;
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args);

Context context = LambdaHandlerProcessor.extractContext(pjpMock);

assertThat(context).isNotNull();
}

private static ProceedingJoinPoint mockRequestStreamHandlerPjp() {
Signature signature = mock(Signature.class);
when(signature.getDeclaringType()).thenReturn(RequestStreamHandler.class);
ProceedingJoinPoint pjpMock = mock(ProceedingJoinPoint.class);
@Test
void extractContext_fromStreamRequestHandler() {
Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)};
when(pjpMock.getArgs()).thenReturn(args);
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args);

Context context = LambdaHandlerProcessor.extractContext(pjpMock);

assertNotNull(context);
}

@Test
void extractContext_notKnownHandler() {
Object[] args = {new Object()};
ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(Object.class, args);

Context context = LambdaHandlerProcessor.extractContext(pjpMock);

assertThat(context).isNull();
}

@Test
void isColdStart() {
boolean isColdStart = LambdaHandlerProcessor.isColdStart();

assertThat(isColdStart).isTrue();
}

@Test
void isColdStart_coldStartDone() {
LambdaHandlerProcessor.coldStartDone();

boolean isColdStart = LambdaHandlerProcessor.isColdStart();

assertThat(isColdStart).isFalse();
}

@Test
void isSamLocal() {
try (MockedStatic<SystemWrapper> mockedSystemWrapper = mockStatic(SystemWrapper.class)) {
mockedSystemWrapper.when(() -> getenv(LambdaConstants.AWS_SAM_LOCAL)).thenReturn("true");

boolean isSamLocal = LambdaHandlerProcessor.isSamLocal();

assertThat(isSamLocal).isTrue();
}
}

@Test
void serviceName() {
try (MockedStatic<SystemWrapper> mockedSystemWrapper = mockStatic(SystemWrapper.class)) {
String expectedServiceName = "MyService";
mockedSystemWrapper.when(() -> getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME)).thenReturn(expectedServiceName);

String actualServiceName = LambdaHandlerProcessor.serviceName();

assertThat(actualServiceName).isEqualTo(expectedServiceName);
}
}

@Test
void serviceName_Undefined() {
LambdaHandlerProcessor.resetServiceName();
try (MockedStatic<SystemWrapper> mockedSystemWrapper = mockStatic(SystemWrapper.class)) {
mockedSystemWrapper.when(() -> getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME)).thenReturn(null);

assertThat(LambdaHandlerProcessor.serviceName()).isEqualTo(LambdaConstants.SERVICE_UNDEFINED);
}
}

private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) {
when(signature.getDeclaringType()).thenReturn(handlerClass);
when(pjpMock.getArgs()).thenReturn(handlerArgs);
when(pjpMock.getSignature()).thenReturn(signature);
return pjpMock;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
*/
package software.amazon.lambda.powertools.logging;

import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.ThreadContext;

import java.util.Map;

import static java.util.Arrays.asList;

/**
Expand Down
Loading

0 comments on commit c7aedc4

Please sign in to comment.