Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.lordofthejars.nosqlunit.dynamodb.DynamoDbAssertion Maven / Gradle / Ivy
package com.lordofthejars.nosqlunit.dynamodb;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.lordofthejars.nosqlunit.core.FailureHandler;
public class DynamoDbAssertion {
private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbAssertion.class);
private DynamoDbAssertion() {
super();
}
public static final void strictAssertEquals(final ExpectedDataSet expectedData, final AmazonDynamoDB dynamoDb) {
final Set tableaNames = expectedData.getTables();
final List tableNames = DynamoDBOperation.getAllTables(dynamoDb);
checkTablesName(tableaNames, tableNames);
for (final String tableName : tableaNames) {
checkTableObjects(expectedData, dynamoDb, tableName);
}
}
private static void checkTablesName(final Set expectedTableNames, final List dynamodbTableNames) {
final Set allTables = new HashSet<>(dynamodbTableNames);
allTables.addAll(expectedTableNames);
if (allTables.size() != expectedTableNames.size() || allTables.size() != dynamodbTableNames.size()) {
throw FailureHandler.createFailure("Expected table names are %s but insert table names are %s",
expectedTableNames, dynamodbTableNames);
}
}
private static void checkTableObjects(final ExpectedDataSet expectedData, final AmazonDynamoDB dynamoDb,
final String tableName) {
final List> dataObjects = expectedData.getDataFor(tableName);
final List> dbTable = DynamoDBOperation.getAllItems(dynamoDb, tableName);
final int expectedDataObjectsCount = dataObjects.size();
final long insertedDataObjectsCount = dbTable.size();
if (expectedDataObjectsCount != insertedDataObjectsCount) {
throw FailureHandler.createFailure("Expected table has %s elements but insert table has %s",
expectedDataObjectsCount, insertedDataObjectsCount);
}
for (final Map expectedDataObject : dataObjects) {
dbTable.stream() //
.filter(map -> map.equals(expectedDataObject)) //
.findFirst() //
.orElseThrow(() -> FailureHandler.createFailure("Object # %s # is not found into table [%s]",
expectedDataObject.toString(), tableName));
}
}
//
/**
* Checks that all the expected data is present in DynamoDB.
*
* @param expectedData Expected data.
* @param dynamoDb Dynamo Database.
*/
public static void flexibleAssertEquals(final ExpectedDataSet expectedData, final String[] ignorePropertyValues,
final AmazonDynamoDB dynamoDb) {
// Get the expected tables
final Set tableNames = expectedData.getTables();
// Get the current tables in dynamoDB
final List listTableNames = DynamoDBOperation.getAllTables(dynamoDb);
// Get the concrete property names that should be ignored
// Map>
final Map> propertiesToIgnore = parseIgnorePropertyValues(tableNames, ignorePropertyValues);
// Check expected data
flexibleCheckTablesName(tableNames, listTableNames);
for (final String tableName : tableNames) {
flexibleCheckTableObjects(expectedData, dynamoDb, tableName, propertiesToIgnore);
}
}
/**
* Resolve the properties that will be ignored for each expected table.
*
*
* @param ignorePropertyValues Input values defined with @IgnorePropertyValue.
* @return Map with the properties that will be ignored for each document.
*/
private static Map> parseIgnorePropertyValues(final Set tableNames,
final String[] ignorePropertyValues) {
final Map> propertiesToIgnore = new HashMap<>();
final Pattern tableAndPropertyPattern = Pattern.compile(
"^(?!system\\.)([a-z,A-Z,_][^$\0]*)([.])([^$][^.\0]*)$");
final Pattern propertyPattern = Pattern.compile("^([^$][^.0]*)$");
for (final String ignorePropertyValue : ignorePropertyValues) {
final Matcher tableAndPropertyMatcher = tableAndPropertyPattern.matcher(ignorePropertyValue);
final Matcher propertyMatcher = propertyPattern.matcher(ignorePropertyValue);
// If the property to ignore includes the table, add it to only exclude
// the property in the indicated table
if (tableAndPropertyMatcher.matches()) {
// Add the property to ignore to the proper table
final String tableName = tableAndPropertyMatcher.group(1);
final String propertyName = tableAndPropertyMatcher.group(3);
if (tableNames.contains(tableName)) {
Set properties = propertiesToIgnore.get(tableName);
if (properties == null) {
properties = new HashSet<>();
}
properties.add(propertyName);
propertiesToIgnore.put(tableName, properties);
} else {
LOGGER.warn("Table {} for {} is not defined as expected. It won't be used for ignoring properties",
tableName, ignorePropertyValue);
}
// If the property to ignore doesn't include the table, add it to
// all the expected tables
} else if (propertyMatcher.matches()) {
final String propertyName = propertyMatcher.group(0);
// Add the property to ignore to all the expected tables
for (final String tableName : tableNames) {
Set properties = propertiesToIgnore.get(tableName);
if (properties == null) {
properties = new HashSet<>();
}
properties.add(propertyName);
propertiesToIgnore.put(tableName, properties);
}
// If doesn't match any pattern
} else {
LOGGER.warn("Property {} has an invalid table.property value. It won't be used for ignoring properties",
ignorePropertyValue);
}
}
return propertiesToIgnore;
}
/**
* Checks that all the expected table names are present in DynamoDB. Does not check
* that all the table names present in Dynamo are in the expected dataset table names.
*
* If any expected table isn't found in the database table, the returned error
* indicates only the missing expected tables.
*
* @param expectedTableNames Expected table names.
* @param dynamodbTableNames Current DynamoDB table names.
*/
private static void flexibleCheckTablesName(final Set expectedTableNames,
final List dynamodbTableNames) {
boolean ok = true;
final HashSet notFoundTableNames = new HashSet<>();
for (final String expectedTableName : expectedTableNames) {
if (!dynamodbTableNames.contains(expectedTableName)) {
ok = false;
notFoundTableNames.add(expectedTableName);
}
}
if (!ok) {
throw FailureHandler.createFailure(
"The following table names %s were not found in the inserted table names", notFoundTableNames);
}
}
/**
* Checks that each expected object in the table exists in the database.
*
* @param expectedData Expected data.
* @param dynamoDb dynamo database.
* @param tableName Table name.
*/
private static void flexibleCheckTableObjects(final ExpectedDataSet expectedData, final AmazonDynamoDB dynamoDb,
final String tableName, final Map> propertiesToIgnore) {
final List> dataObjects = expectedData.getDataFor(tableName);
final List> dbTable = DynamoDBOperation.getAllItems(dynamoDb, tableName);
for (final Map expectedDataObject : dataObjects) {
final Map filteredExpectedDataObject = filterProperties(expectedDataObject,
propertiesToIgnore.get(tableName));
final List> foundObjects = dbTable.stream() //
.map(foundDataObject -> filterProperties(foundDataObject, propertiesToIgnore.get(tableName))) //
.filter(map -> map.equals(filteredExpectedDataObject)) //
.collect(Collectors.toList());
if (foundObjects.size() > 1) {
LOGGER.warn(
"There were found {} possible matches for this object # {} #. That could have been caused by ignoring too many properties.",
foundObjects.size(), expectedDataObject);
}
if (foundObjects.isEmpty()) {
throw FailureHandler.createFailure("Object # %s # is not found into table [%s]",
filteredExpectedDataObject.toString(), tableName);
}
}
}
/**
* Removes the properties defined with @IgnorePropertyValue annotation.
*
* @param dataObject Object to filter.
* @param propertiesToIgnore Properties to filter
* @return Data object without the properties to be ignored.
*/
private static Map filterProperties(final Map dataObject,
final Set propertiesToIgnore) {
final Map filteredDataObject = new HashMap<>();
for (final Map.Entry entry : dataObject.entrySet()) {
if (propertiesToIgnore == null || !propertiesToIgnore.contains(entry.getKey())) {
filteredDataObject.put(entry.getKey(), entry.getValue());
}
}
return filteredDataObject;
}
//
}