/*
* Copyright (c) 2010 Lockheed Martin Corporation
*
* 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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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 org.eurekastreams.commons.server.async;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.eurekastreams.commons.actions.ExecutionStrategy;
import org.eurekastreams.commons.actions.TaskHandlerAction;
import org.eurekastreams.commons.actions.TaskHandlerExecutionStrategy;
import org.eurekastreams.commons.actions.ValidationStrategy;
import org.eurekastreams.commons.actions.async.AsyncAction;
import org.eurekastreams.commons.actions.context.ActionContext;
import org.eurekastreams.commons.actions.context.TaskHandlerActionContext;
import org.eurekastreams.commons.actions.context.async.AsyncActionContext;
import org.eurekastreams.commons.exceptions.ExecutionException;
import org.eurekastreams.commons.exceptions.GeneralException;
import org.eurekastreams.commons.exceptions.ValidationException;
import org.eurekastreams.commons.server.TransactionManagerFake;
import org.eurekastreams.commons.server.UserActionRequest;
import org.eurekastreams.commons.task.TaskHandler;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Before;
import org.junit.Test;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
/**
* Test suite for the AsyncActionController.
*
*/
@SuppressWarnings("unchecked")
public class AsyncActionControllerTest
{
/**
* Instance of {@link AsyncActionController} System Under Test.
*/
private AsyncActionController sut;
/**
* Context for building mock objects.
*/
private final Mockery context = new JUnit4Mockery()
{
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
/**
* Mock of the TransactionManagerFake for testing.
*/
private final TransactionManagerFake transMgrMock = context.mock(TransactionManagerFake.class);
/**
* instance of a TransactionDefinition.
*/
private DefaultTransactionDefinition transDef = null;
/**
* Mocked instance of a TransactionStatus.
*/
private TransactionStatus transStatus = context.mock(TransactionStatus.class);
/**
* Mocked instance of the ValidationStrategy for testing.
*/
private ValidationStrategy<ActionContext> validationStrategy = context.mock(ValidationStrategy.class);
/**
* Mocked instance of the {@link ExecutionStrategy} for testing.
*/
private ExecutionStrategy<ActionContext> executionStrategy = context.mock(ExecutionStrategy.class);
/**
* Mocked instance of the {@link TaskHandlerExecutionStrategy} for testing.
*/
private TaskHandlerExecutionStrategy<ActionContext> taskHandlerExecutionStrategy = context
.mock(TaskHandlerExecutionStrategy.class);
/**
* Mocked instance of the {@link AsyncAction} class for testing.
*/
private AsyncAction asyncActionMock = context.mock(AsyncAction.class);
/**
* Mocked instance of the {@link AsyncActionContext}.
*/
private AsyncActionContext asyncActionContextMock = context.mock(AsyncActionContext.class);
/**
* Mocked instance of the {@link TaskHandlerAction} class for testing.
*/
private TaskHandlerAction queueSubmitterActionMock = context.mock(TaskHandlerAction.class);
/**
* Mocked instance of the {@link TaskHandler} class.
*/
private TaskHandler taskHandlerMock = context.mock(TaskHandler.class);
/**
* Mocked instance of the {@link UserActionRequest} class for testing.
*/
private UserActionRequest userActionRequest = context.mock(UserActionRequest.class);
/**
* Prepare the system under test.
*/
@Before
public void setup()
{
sut = new AsyncActionController(transMgrMock);
transDef = new DefaultTransactionDefinition();
}
/**
* Test the execution of the AsyncActionController with just an AsyncAction.
*
* @throws Throwable
* - on error.
*/
@Test
public void testExecuteWithAsycAction() throws Throwable
{
Serializable params = null;
final AsyncActionContext asyncActionContext = new AsyncActionContext(params);
transDef.setReadOnly(true);
setupTransactionContext(true, asyncActionContext, false);
sut.execute(asyncActionContext, asyncActionMock);
context.assertIsSatisfied();
}
/**
* Test the execution of the AsyncActionController with just an AsyncAction.
*
* @throws Throwable
* - on error.
*/
@Test(expected = GeneralException.class)
public void testExecuteWithAsyncActionFailure() throws Throwable
{
Serializable params = null;
final AsyncActionContext asyncActionContext = new AsyncActionContext(params);
transDef.setReadOnly(true);
setupTransactionContext(true, asyncActionContext, true);
context.checking(new Expectations()
{
{
oneOf(transStatus).isCompleted();
will(returnValue(false));
oneOf(transMgrMock).rollback(transStatus);
}
});
sut.execute(asyncActionContext, asyncActionMock);
context.assertIsSatisfied();
}
/**
* Test the execution of the AsyncActionController with just an async Action and fail on validation.
*
* @throws Throwable
* - on error.
*/
@Test(expected = ValidationException.class)
public void testExecuteWithAsyncActionValidationFailure() throws Throwable
{
Serializable params = null;
final AsyncActionContext asyncActionContext = new AsyncActionContext(params);
transDef.setReadOnly(true);
context.checking(new Expectations()
{
{
oneOf(asyncActionMock).isReadOnly();
will(returnValue(true));
oneOf(transMgrMock).getTransaction(transDef);
will(returnValue(transStatus));
oneOf(asyncActionMock).getValidationStrategy();
will(returnValue(validationStrategy));
oneOf(validationStrategy).validate(asyncActionContext);
will(throwException(new ValidationException()));
oneOf(transStatus).isCompleted();
will(returnValue(false));
oneOf(transMgrMock).rollback(transStatus);
}
});
sut.execute(asyncActionContext, asyncActionMock);
context.assertIsSatisfied();
}
/**
* Test the execution of the AsyncActionController with just an async Action and fail on execution.
*
* @throws Throwable
* - on error.
*/
@Test(expected = ExecutionException.class)
public void testExecuteWithAsyncActionExecutionFailure() throws Throwable
{
Serializable params = null;
final AsyncActionContext asyncActionContext = new AsyncActionContext(params);
transDef.setReadOnly(true);
context.checking(new Expectations()
{
{
oneOf(asyncActionMock).isReadOnly();
will(returnValue(true));
oneOf(transMgrMock).getTransaction(transDef);
will(returnValue(transStatus));
oneOf(asyncActionMock).getValidationStrategy();
will(returnValue(validationStrategy));
oneOf(validationStrategy).validate(asyncActionContext);
oneOf(asyncActionMock).getExecutionStrategy();
will(returnValue(executionStrategy));
oneOf(executionStrategy).execute(asyncActionContext);
will(throwException(new ExecutionException()));
oneOf(transStatus).isCompleted();
will(returnValue(false));
oneOf(transMgrMock).rollback(transStatus);
}
});
sut.execute(asyncActionContext, asyncActionMock);
context.assertIsSatisfied();
}
/**
* Test the sucessful path of the {@link TaskHandlerAction}.
*
* @throws Throwable
* - on error.
*/
@Test
public void testExecuteWithQueueAsyncAction() throws Throwable
{
transDef.setReadOnly(false);
final List<UserActionRequest> requests = new ArrayList<UserActionRequest>();
requests.add(userActionRequest);
final TaskHandlerActionContext<ActionContext> taskHandlerActionContextMock = context
.mock(TaskHandlerActionContext.class);
setupTaskHandlerTransactionContext(false, taskHandlerActionContextMock, false);
sut.execute(asyncActionContextMock, queueSubmitterActionMock);
context.assertIsSatisfied();
}
/**
* Test the failure path of the {@link TaskHandlerAction}.
*
* @throws Throwable
* - on error.
*/
@Test(expected = GeneralException.class)
public void testExecuteWithQueueAsyncActionFailure() throws Throwable
{
transDef.setReadOnly(false);
final List<UserActionRequest> requests = new ArrayList<UserActionRequest>();
requests.add(userActionRequest);
final TaskHandlerActionContext<ActionContext> taskHandlerActionContextMock = context
.mock(TaskHandlerActionContext.class);
setupTaskHandlerTransactionContext(false, taskHandlerActionContextMock, true);
context.checking(new Expectations()
{
{
oneOf(transStatus).isCompleted();
will(returnValue(false));
oneOf(transMgrMock).rollback(transStatus);
}
});
sut.execute(asyncActionContextMock, queueSubmitterActionMock);
context.assertIsSatisfied();
}
/**
* Test the failure path of the {@link TaskHandlerAction}.
*
* @throws Throwable
* - on error.
*/
@Test(expected = ValidationException.class)
public void testExecuteWithQueueAsyncActionValidationFailure() throws Throwable
{
transDef.setReadOnly(false);
final List<UserActionRequest> requests = new ArrayList<UserActionRequest>();
requests.add(userActionRequest);
context.checking(new Expectations()
{
{
oneOf(queueSubmitterActionMock).isReadOnly();
will(returnValue(false));
oneOf(transMgrMock).getTransaction(transDef);
will(returnValue(transStatus));
oneOf(queueSubmitterActionMock).getValidationStrategy();
will(returnValue(validationStrategy));
oneOf(validationStrategy).validate(asyncActionContextMock);
will(throwException(new ValidationException()));
oneOf(transStatus).isCompleted();
will(returnValue(false));
oneOf(transMgrMock).rollback(transStatus);
}
});
sut.execute(asyncActionContextMock, queueSubmitterActionMock);
context.assertIsSatisfied();
}
/**
* Test the failure path of the {@link TaskHandlerAction}.
*
* @throws Throwable
* - on error.
*/
@Test(expected = ExecutionException.class)
public void testExecuteWithQueueAsyncActionExecutionFailure() throws Throwable
{
transDef.setReadOnly(false);
final List<UserActionRequest> requests = new ArrayList<UserActionRequest>();
requests.add(userActionRequest);
context.checking(new Expectations()
{
{
oneOf(queueSubmitterActionMock).isReadOnly();
will(returnValue(false));
oneOf(transMgrMock).getTransaction(transDef);
will(returnValue(transStatus));
oneOf(queueSubmitterActionMock).getValidationStrategy();
will(returnValue(validationStrategy));
oneOf(validationStrategy).validate(asyncActionContextMock);
oneOf(queueSubmitterActionMock).getExecutionStrategy();
will(returnValue(taskHandlerExecutionStrategy));
oneOf(taskHandlerExecutionStrategy).execute(with(any(TaskHandlerActionContext.class)));
will(throwException(new ExecutionException()));
oneOf(transStatus).isCompleted();
will(returnValue(false));
oneOf(transMgrMock).rollback(transStatus);
}
});
sut.execute(asyncActionContextMock, queueSubmitterActionMock);
context.assertIsSatisfied();
}
/**
* Helper method.
*
* @param isReadOnlyTransaction
* - flag for setting the readonly transaction
* @param inContext
* - {@link AsyncActionContext} for the current test.
* @param throwsException
* - flag for whether or not to throw an exception within the trans.
* @throws Throwable
* on error.
*/
private void setupTaskHandlerTransactionContext(final boolean isReadOnlyTransaction,
final TaskHandlerActionContext inContext, final boolean throwsException) throws Throwable
{
context.checking(new Expectations()
{
{
oneOf(queueSubmitterActionMock).isReadOnly();
will(returnValue(isReadOnlyTransaction));
oneOf(transMgrMock).getTransaction(transDef);
will(returnValue(transStatus));
oneOf(queueSubmitterActionMock).getValidationStrategy();
will(returnValue(validationStrategy));
oneOf(validationStrategy).validate(asyncActionContextMock);
oneOf(queueSubmitterActionMock).getExecutionStrategy();
will(returnValue(taskHandlerExecutionStrategy));
oneOf(taskHandlerExecutionStrategy).execute(with(any(TaskHandlerActionContext.class)));
if (throwsException)
{
oneOf(transMgrMock).commit(transStatus);
will(throwException(new GeneralException()));
}
else
{
oneOf(transMgrMock).commit(transStatus);
oneOf(queueSubmitterActionMock).getTaskHandler();
will(returnValue(taskHandlerMock));
}
}
});
}
/**
* Helper method.
*
* @param isReadOnlyTransaction
* - flag for setting the readonly transaction
* @param inContext
* - {@link AsyncActionContext} for the current test.
* @param throwsException
* - flag for whether or not to throw an exception within the trans.
* @throws Throwable
* on error.
*/
private void setupTransactionContext(final boolean isReadOnlyTransaction, final AsyncActionContext inContext,
final boolean throwsException) throws Throwable
{
context.checking(new Expectations()
{
{
oneOf(asyncActionMock).isReadOnly();
will(returnValue(isReadOnlyTransaction));
oneOf(transMgrMock).getTransaction(transDef);
will(returnValue(transStatus));
oneOf(asyncActionMock).getValidationStrategy();
will(returnValue(validationStrategy));
oneOf(validationStrategy).validate(inContext);
oneOf(asyncActionMock).getExecutionStrategy();
will(returnValue(executionStrategy));
oneOf(executionStrategy).execute(inContext);
if (throwsException)
{
oneOf(transMgrMock).commit(transStatus);
will(throwException(new GeneralException()));
}
else
{
oneOf(transMgrMock).commit(transStatus);
}
}
});
}
}