/*
* Copyright 2015-2017 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. 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.handlers;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import org.apache.http.client.methods.HttpGet;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.AmazonWebServiceRequest;
import com.amazonaws.Request;
import com.amazonaws.Response;
import com.amazonaws.http.HttpResponse;
@RunWith(Enclosed.class)
public class StackedRequestHandlerTest {
/**
* Tests a {@link StackedRequestHandler} with no {@link RequestHandler2}'s added. Mainly tests
* that things don't blow up as nothing should happen when no request handlers are added
*/
public static class NoRequestHandlers {
private StackedRequestHandler stackedRequestHandler;
@Mock
private Request<?> request;
private Response<?> response;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
stackedRequestHandler = new StackedRequestHandler(new ArrayList<RequestHandler2>());
response = new Response<String>("Dummy response", new HttpResponse(request, new HttpGet()));
}
@Test
public void beforeMarshalling() {
final AmazonWebServiceRequest inputRequest = mock(AmazonWebServiceRequest.class);
stackedRequestHandler.beforeMarshalling(inputRequest);
}
@Test
public void beforeRequest() {
stackedRequestHandler.beforeRequest(request);
}
@Test
public void beforeUnmarshalling() {
stackedRequestHandler.beforeUnmarshalling(request, new HttpResponse(request, null));
}
@Test
public void afterResponse() {
stackedRequestHandler.afterResponse(request, response);
}
@Test
public void afterError() {
final Exception exception = new AmazonServiceException("Some service failure");
stackedRequestHandler.afterError(request, response, exception);
}
}
/**
* Tests a {@link StackedRequestHandler} with a single {@link RequestHandler2} added. Tests that
* only that request handler is delegated to.
*/
public static class SingleRequestHandler {
private StackedRequestHandler stackedRequestHandler;
@Mock
private RequestHandler2 only;
@Mock
private Request<?> request;
private Response<?> response;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
stackedRequestHandler = new StackedRequestHandler(only);
response = new Response<String>("Dummy response", new HttpResponse(request, new HttpGet()));
}
@Test
public void beforeMarshalling() {
final AmazonWebServiceRequest inputRequest = mock(AmazonWebServiceRequest.class);
stackedRequestHandler.beforeMarshalling(inputRequest);
assertNull(verify(only).beforeMarshalling(inputRequest));
}
@Test
public void beforeRequest() {
stackedRequestHandler.beforeRequest(request);
verify(only).beforeRequest(request);
}
@Test
public void beforeUnmarshalling() {
HttpResponse httpResponse = new HttpResponse(request, null);
stackedRequestHandler.beforeUnmarshalling(request, httpResponse);
verify(only).beforeUnmarshalling(request, httpResponse);
}
@Test
public void afterResponse() {
stackedRequestHandler.afterResponse(request, response);
verify(only).afterResponse(request, response);
}
@Test
public void afterError() {
final Exception exception = new AmazonServiceException("Some service failure");
stackedRequestHandler.afterError(request, response, exception);
verify(only).afterError(request, response, exception);
}
}
/**
* Tests a {@link StackedRequestHandler} with multiple {@link RequestHandler2} added. Before
* hooks should be executed in normal order (i.e. first, second, then third in respect to what
* order they were added to the {@link StackedRequestHandler}) and after hooks should be
* executed in reverse order (i.e. third, second, first)
*/
public static class MultipleRequestHandlers {
private StackedRequestHandler stackedRequestHandler;
@Mock
private RequestHandler2 first;
@Mock
private RequestHandler2 second;
@Mock
private RequestHandler2 third;
@Mock
private Request<?> request;
private Response<?> response;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
stackedRequestHandler = new StackedRequestHandler(first, second, third);
response = new Response<String>("Dummy response", new HttpResponse(request, new HttpGet()));
}
@Test
public void beforeMarshalling_CalledInOrder() {
stackedRequestHandler.beforeMarshalling(null);
InOrder inOrder = inOrder(first, second, third);
inOrder.verify(first).beforeMarshalling(null);
inOrder.verify(second).beforeMarshalling(null);
inOrder.verify(third).beforeMarshalling(null);
}
/**
* The beforeMarshalling step is a bit different. It's expected to take the potentially
* modified {@link AmazonWebServiceRequest} returned by
* {@link RequestHandler2#beforeMarshalling(AmazonWebServiceRequest)} and forward that
* result as input to the next request handler in the chain. This tests makes sure that each
* request handler forwards the appropriate the result to the next in the chain and that the
* end result is what's returned by the last request handler in the chain
*/
@Test
public void beforeMarshalling_ModifiedRequestForwardedToNextInChain() {
final AmazonWebServiceRequest origAwsRequest = mock(AmazonWebServiceRequest.class);
final AmazonWebServiceRequest afterFirstAwsRequest = mock(AmazonWebServiceRequest.class);
final AmazonWebServiceRequest afterSecondAwsRequest = mock(AmazonWebServiceRequest.class);
final AmazonWebServiceRequest afterThirdAwsRequest = mock(AmazonWebServiceRequest.class);
doReturn(afterFirstAwsRequest).when(first).beforeMarshalling(origAwsRequest);
doReturn(afterSecondAwsRequest).when(second).beforeMarshalling(afterFirstAwsRequest);
doReturn(afterThirdAwsRequest).when(third).beforeMarshalling(afterSecondAwsRequest);
assertEquals(afterThirdAwsRequest, stackedRequestHandler.beforeMarshalling(origAwsRequest));
InOrder inOrder = inOrder(first, second, third);
inOrder.verify(first).beforeMarshalling(origAwsRequest);
inOrder.verify(second).beforeMarshalling(afterFirstAwsRequest);
inOrder.verify(third).beforeMarshalling(afterSecondAwsRequest);
}
@Test
public void beforeRequest_CalledInOrder() {
stackedRequestHandler.beforeRequest(request);
InOrder inOrder = inOrder(first, second, third);
inOrder.verify(first).beforeRequest(request);
inOrder.verify(second).beforeRequest(request);
inOrder.verify(third).beforeRequest(request);
}
@Test
public void beforeUnmarshalling_CalledInOrder() {
stackedRequestHandler.beforeUnmarshalling(request, null);
InOrder inOrder = inOrder(third, second, first);
inOrder.verify(third).beforeUnmarshalling(request, null);
inOrder.verify(second).beforeUnmarshalling(request, null);
inOrder.verify(first).beforeUnmarshalling(request, null);
}
@Test
public void beforeUnmarshalling_ModifiedResponseForwardedToNextInChain() {
final HttpResponse origHttpResponse = mock(HttpResponse.class);
final HttpResponse afterFirstHttpResponse = mock(HttpResponse.class);
final HttpResponse afterSecondHttpResponse = mock(HttpResponse.class);
final HttpResponse afterThirdHttpResponse = mock(HttpResponse.class);
doReturn(afterThirdHttpResponse).when(third).beforeUnmarshalling(request, origHttpResponse);
doReturn(afterSecondHttpResponse).when(second).beforeUnmarshalling(request, afterThirdHttpResponse);
doReturn(afterFirstHttpResponse).when(first).beforeUnmarshalling(request, afterSecondHttpResponse);
assertEquals(afterFirstHttpResponse, stackedRequestHandler.beforeUnmarshalling(request, origHttpResponse));
InOrder inOrder = inOrder(third, second, first);
inOrder.verify(third).beforeUnmarshalling(request, origHttpResponse);
inOrder.verify(second).beforeUnmarshalling(request, afterThirdHttpResponse);
inOrder.verify(first).beforeUnmarshalling(request, afterSecondHttpResponse);
}
@Test
public void afterResponse_CalledInOrder() {
stackedRequestHandler.afterResponse(request, response);
InOrder inOrder = inOrder(third, second, first);
inOrder.verify(third).afterResponse(request, response);
inOrder.verify(second).afterResponse(request, response);
inOrder.verify(first).afterResponse(request, response);
}
@Test
public void afterError_CalledInOrder() {
final Exception exception = new AmazonServiceException("Some service failure");
stackedRequestHandler.afterError(request, response, exception);
InOrder inOrder = inOrder(third, second, first);
inOrder.verify(third).afterError(request, response, exception);
inOrder.verify(second).afterError(request, response, exception);
inOrder.verify(first).afterError(request, response, exception);
}
}
}