/*
* Copyright 2015 herd contributors
*
* 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.finra.herd.service.helper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.finra.herd.dao.helper.HerdDaoSecurityHelper;
import org.finra.herd.model.api.xml.BusinessObjectDataKey;
import org.finra.herd.model.dto.ConfigurationValue;
import org.finra.herd.model.jpa.BusinessObjectDataEntity;
import org.finra.herd.service.AbstractServiceTest;
/**
* Tests the functionality within the default SQS message builder.
*/
public class DefaultSqsMessageBuilderTest extends AbstractServiceTest
{
@Autowired
private SqsMessageBuilder defaultSqsMessageBuilder;
/**
* Test message building using 4 sub-partitions and default user.
*/
@Test
public void testBuildBusinessObjectDataStatusChangeMessage()
{
List<String> subPartitionValues = Arrays.asList("testSubPartitionValueA", "testSubPartitionValueB", "testSubPartitionValueC", "testSubPartitionValueD");
testBuildBusinessObjectDataStatusChangeMessage(subPartitionValues, HerdDaoSecurityHelper.SYSTEM_USER);
}
/**
* Test message building using null sub-partitions and default user.
*/
@Test
public void testBuildBusinessObjectDataStatusChangeMessageNullSubpartitions()
{
List<String> subPartitionValues = null;
testBuildBusinessObjectDataStatusChangeMessage(subPartitionValues, HerdDaoSecurityHelper.SYSTEM_USER);
}
/**
* Test message building using 4 sub-partitions and a non-default user.
*/
@SuppressWarnings("serial")
@Test
public void testBuildBusinessObjectDataStatusChangeMessageUserInContext()
{
Authentication originalAuthentication = SecurityContextHolder.getContext().getAuthentication();
try
{
SecurityContextHolder.getContext().setAuthentication(new Authentication()
{
@Override
public String getName()
{
return null;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException
{
}
@Override
public boolean isAuthenticated()
{
return false;
}
@Override
public Object getPrincipal()
{
List<GrantedAuthority> authorities = Collections.emptyList();
return new User("testUsername", "", authorities);
}
@Override
public Object getDetails()
{
return null;
}
@Override
public Object getCredentials()
{
return null;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
{
return null;
}
});
List<String> subPartitionValues =
Arrays.asList("testSubPartitionValueA", "testSubPartitionValueB", "testSubPartitionValueC", "testSubPartitionValueD");
testBuildBusinessObjectDataStatusChangeMessage(subPartitionValues, "testUsername");
}
finally
{
// Restore the original authentication.
SecurityContextHolder.getContext().setAuthentication(originalAuthentication);
}
}
/**
* Test BuildSystemMonitorResponse. Builds the response based on a test request, then asserts the correct system monitor transformations occur.
*/
@Test
public void testBuildSystemMonitorResponse() throws Exception
{
validateSystemMonitorResponse(defaultSqsMessageBuilder.buildSystemMonitorResponse(getTestSystemMonitorIncomingMessage()));
}
/**
* Test that no response is built when a velocity template is not configured.
*/
@Test
public void testBuildSystemMonitorResponseNoVelocityTemplate() throws Exception
{
// Override the configuration to remove the velocity template for building the system monitor response.
Map<String, Object> overrideMap = new HashMap<>();
overrideMap.put(ConfigurationValue.HERD_NOTIFICATION_SQS_SYS_MONITOR_RESPONSE_VELOCITY_TEMPLATE.getKey(), null);
modifyPropertySourceInEnvironment(overrideMap);
try
{
// When no velocity template is present, the response message should be null.
assertNull(defaultSqsMessageBuilder.buildSystemMonitorResponse(getTestSystemMonitorIncomingMessage()));
}
finally
{
// Restore the property sources so we don't affect other tests.
restorePropertySourceInEnvironment();
}
}
/**
* Test that a parsing exception is thrown when an invalid velocity template is configured.
*/
@Test(expected = ParseErrorException.class)
public void testBuildSystemMonitorResponseInvalidVelocityTemplate() throws Exception
{
// Override the configuration to use an invalid velocity template for building the system monitor response.
Map<String, Object> overrideMap = new HashMap<>();
overrideMap.put(ConfigurationValue.HERD_NOTIFICATION_SQS_SYS_MONITOR_RESPONSE_VELOCITY_TEMPLATE.getKey(), "#if($missingEndOfIfStatement");
modifyPropertySourceInEnvironment(overrideMap);
try
{
// When the velocity template is invalid, a ParseErrorException should be thrown.
defaultSqsMessageBuilder.buildSystemMonitorResponse(getTestSystemMonitorIncomingMessage());
}
finally
{
// Restore the property sources so we don't affect other tests.
restorePropertySourceInEnvironment();
}
}
/**
* Test that the resultant system monitor response message works when no XPath expressions are configured.
*/
@Test
public void testBuildSystemMonitorResponseNoXPathExpressions() throws Exception
{
// Override the configuration to remove the XPath expressions when building the system monitor response.
Map<String, Object> overrideMap = new HashMap<>();
overrideMap.put(ConfigurationValue.HERD_NOTIFICATION_SQS_SYS_MONITOR_REQUEST_XPATH_PROPERTIES.getKey(), null);
modifyPropertySourceInEnvironment(overrideMap);
try
{
// Try to get a system monitor response when XPath expressions are removed.
defaultSqsMessageBuilder.buildSystemMonitorResponse(getTestSystemMonitorIncomingMessage());
fail("Should throw an MethodInvocationException when the velocity template contains an undefined variable.");
}
catch (MethodInvocationException e)
{
assertEquals(String.format("Variable $incoming_message_correlation_id has not been set at systemMonitorResponse[line 11, column 29]"),
e.getMessage());
}
finally
{
// Restore the property sources so we don't affect other tests.
restorePropertySourceInEnvironment();
}
}
/**
* Test that an IllegalStateException is thrown when an invalid XPath expression is encountered.
*/
@Test(expected = IllegalStateException.class)
public void testBuildSystemMonitorResponseInvalidXpathExpression() throws Exception
{
// Override the configuration to use an invalid XPath expression.
Map<String, Object> overrideMap = new HashMap<>();
overrideMap.put(ConfigurationValue.HERD_NOTIFICATION_SQS_SYS_MONITOR_REQUEST_XPATH_PROPERTIES.getKey(), "key=///");
modifyPropertySourceInEnvironment(overrideMap);
try
{
// When the XPath expression is invalid, an IllegalStateException should be thrown.
defaultSqsMessageBuilder.buildSystemMonitorResponse(getTestSystemMonitorIncomingMessage());
}
finally
{
// Restore the property sources so we don't affect other tests.
restorePropertySourceInEnvironment();
}
}
/**
* Test that an IllegalStateException is thrown when the XPath properties format is invalid.
*/
@Test(expected = IllegalStateException.class)
public void testBuildSystemMonitorResponseInvalidXpathProperties() throws Exception
{
// Override the configuration to use an invalid XPath properties format. This happens when an invalid unicode character is found.
Map<String, Object> overrideMap = new HashMap<>();
overrideMap.put(ConfigurationValue.HERD_NOTIFICATION_SQS_SYS_MONITOR_REQUEST_XPATH_PROPERTIES.getKey(), "key=\\uxxxx");
modifyPropertySourceInEnvironment(overrideMap);
try
{
// When the XPath properties are not a valid format, an IllegalStateException should be thrown.
defaultSqsMessageBuilder.buildSystemMonitorResponse(getTestSystemMonitorIncomingMessage());
}
finally
{
// Restore the property sources so we don't affect other tests.
restorePropertySourceInEnvironment();
}
}
/**
* Builds a message and validates that: - No exceptions are thrown. - Returned message XML is valid and de-serializable. - Returned correlation ID equals
* expected. - Returned triggered by username equals expected. - Returned business object data key equals expected. - Returned old and new statuses equal
* expected.
*
* @param subPartitionValues customizable expected sub-partition values
* @param triggeredByUsername customizable expected user name
*/
private void testBuildBusinessObjectDataStatusChangeMessage(List<String> subPartitionValues, String triggeredByUsername)
{
// Create a business object data entity.
BusinessObjectDataEntity businessObjectDataEntity =
businessObjectDataServiceTestHelper.createTestValidBusinessObjectData(subPartitionValues, NO_ATTRIBUTE_DEFINITIONS, NO_ATTRIBUTES);
BusinessObjectDataKey businessObjectDataKey = businessObjectDataHelper.getBusinessObjectDataKey(businessObjectDataEntity);
String newBusinessObjectDataStatus = "testNewBusinessObjectDataStatus";
String oldBusinessObjectDataStatus = "testOldBusinessObjectDataStatus";
// Construct the ESB message
String message = defaultSqsMessageBuilder
.buildBusinessObjectDataStatusChangeMessage(businessObjectDataKey, newBusinessObjectDataStatus, oldBusinessObjectDataStatus);
// Validate the message.
businessObjectDataServiceTestHelper
.validateBusinessObjectDataStatusChangeMessage(message, businessObjectDataKey, businessObjectDataEntity.getId(), triggeredByUsername,
newBusinessObjectDataStatus, oldBusinessObjectDataStatus, NO_ATTRIBUTES);
}
}