GH-64: Add DynamoDbMetaDataStore implementation
Fixes spring-projects/spring-integration-aws#64 * Add `DynamoDbRunning` for testing against locally ran DynamoDB * Upgrade to Gradle 4.0.1, SI-4.3.11 * Switch on some Checkstyle rules for tests
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* 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.springframework.integration.aws;
|
||||
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.rules.TestWatcher;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import com.amazonaws.ClientConfiguration;
|
||||
import com.amazonaws.SdkClientException;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsync;
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsyncClientBuilder;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public final class DynamoDbRunning extends TestWatcher {
|
||||
|
||||
private static Log logger = LogFactory.getLog(DynamoDbRunning.class);
|
||||
|
||||
// Static so that we only test once on failure: speeds up test suite
|
||||
private static Map<Integer, Boolean> dynamoDbOnline = new HashMap<>();
|
||||
|
||||
private final int port;
|
||||
|
||||
private AmazonDynamoDBAsync amazonDynamoDB;
|
||||
|
||||
private DynamoDbRunning(int port) {
|
||||
this.port = port;
|
||||
dynamoDbOnline.put(port, true);
|
||||
}
|
||||
|
||||
public AmazonDynamoDBAsync getDynamoDB() {
|
||||
return this.amazonDynamoDB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, Description description) {
|
||||
assumeTrue(dynamoDbOnline.get(this.port));
|
||||
|
||||
String url = "http://localhost:" + this.port;
|
||||
|
||||
this.amazonDynamoDB = AmazonDynamoDBAsyncClientBuilder.standard()
|
||||
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("", "")))
|
||||
.withClientConfiguration(
|
||||
new ClientConfiguration()
|
||||
.withMaxErrorRetry(0)
|
||||
.withConnectionTimeout(1000))
|
||||
.withEndpointConfiguration(
|
||||
new AwsClientBuilder.EndpointConfiguration(url, Regions.DEFAULT_REGION.getName()))
|
||||
.build();
|
||||
|
||||
try {
|
||||
this.amazonDynamoDB.listTables();
|
||||
}
|
||||
catch (SdkClientException e) {
|
||||
logger.warn("Tests not running because no DynamoDb on " + url, e);
|
||||
assumeNoException(e);
|
||||
}
|
||||
return super.apply(base, description);
|
||||
}
|
||||
|
||||
|
||||
public static DynamoDbRunning isRunning(int port) {
|
||||
return new DynamoDbRunning(port);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* 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.springframework.integration.aws.metadata;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.aws.DynamoDbRunning;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsync;
|
||||
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
|
||||
import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest;
|
||||
import com.amazonaws.waiters.FixedDelayStrategy;
|
||||
import com.amazonaws.waiters.MaxAttemptsRetryStrategy;
|
||||
import com.amazonaws.waiters.PollingStrategy;
|
||||
import com.amazonaws.waiters.Waiter;
|
||||
import com.amazonaws.waiters.WaiterParameters;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 1.1
|
||||
*
|
||||
*/
|
||||
public class DynamoDbMetadataStoreTests {
|
||||
|
||||
@ClassRule
|
||||
public static final DynamoDbRunning DYNAMO_DB_RUNNING = DynamoDbRunning.isRunning(4567);
|
||||
|
||||
private static final String TEST_TABLE = "testMetadataStore";
|
||||
|
||||
private static DynamoDbMetaDataStore store;
|
||||
|
||||
private final String file1 = "/remotepath/filesTodownload/file-1.txt";
|
||||
|
||||
private final String file1Id = "12345";
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
AmazonDynamoDBAsync dynamoDB = DYNAMO_DB_RUNNING.getDynamoDB();
|
||||
|
||||
try {
|
||||
dynamoDB.deleteTableAsync(TEST_TABLE);
|
||||
|
||||
Waiter<DescribeTableRequest> waiter =
|
||||
dynamoDB.waiters()
|
||||
.tableNotExists();
|
||||
|
||||
waiter.run(new WaiterParameters<>(new DescribeTableRequest(TEST_TABLE))
|
||||
.withPollingStrategy(new PollingStrategy(new MaxAttemptsRetryStrategy(25),
|
||||
new FixedDelayStrategy(1))));
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
store = new DynamoDbMetaDataStore(dynamoDB, TEST_TABLE);
|
||||
store.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void clear() throws InterruptedException {
|
||||
CountDownLatch createTableLatch = TestUtils.getPropertyValue(store, "createTableLatch", CountDownLatch.class);
|
||||
|
||||
createTableLatch.await();
|
||||
|
||||
DYNAMO_DB_RUNNING.getDynamoDB()
|
||||
.deleteItem(TEST_TABLE,
|
||||
Collections.singletonMap("KEY",
|
||||
new AttributeValue()
|
||||
.withS(this.file1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFromStore() {
|
||||
String fileID = store.get(this.file1);
|
||||
assertThat(fileID).isNull();
|
||||
|
||||
store.put(this.file1, this.file1Id);
|
||||
|
||||
fileID = store.get(this.file1);
|
||||
assertThat(fileID).isNotNull();
|
||||
assertThat(fileID).isEqualTo(this.file1Id);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutIfAbsent() throws Exception {
|
||||
String fileID = store.get(file1);
|
||||
assertThat(fileID).describedAs("Get First time, Value must not exist").isNull();
|
||||
|
||||
fileID = store.putIfAbsent(file1, file1Id);
|
||||
assertThat(fileID).describedAs("Insert First time, Value must return null").isNull();
|
||||
|
||||
fileID = store.putIfAbsent(file1, "56789");
|
||||
assertThat(fileID).describedAs("Key Already Exists - Insertion Failed, ol value must be returned").isNotNull();
|
||||
assertThat(fileID).describedAs("The Old Value must be equal to returned").isEqualTo(this.file1Id);
|
||||
|
||||
assertThat(store.get(this.file1)).describedAs("The Old Value must return").isEqualTo(this.file1Id);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() throws Exception {
|
||||
String fileID = store.remove(this.file1);
|
||||
assertThat(fileID).isNull();
|
||||
|
||||
fileID = store.putIfAbsent(this.file1, this.file1Id);
|
||||
assertThat(fileID).isNull();
|
||||
|
||||
fileID = store.remove(this.file1);
|
||||
assertThat(fileID).isNotNull();
|
||||
assertThat(fileID).isEqualTo(this.file1Id);
|
||||
|
||||
fileID = store.get(this.file1);
|
||||
assertThat(fileID).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplace() throws Exception {
|
||||
boolean removedValue = store.replace(file1, file1Id, "4567");
|
||||
assertThat(removedValue).isFalse();
|
||||
|
||||
String fileID = store.get(this.file1);
|
||||
assertThat(fileID).isNull();
|
||||
|
||||
fileID = store.putIfAbsent(this.file1, file1Id);
|
||||
assertThat(fileID).isNull();
|
||||
|
||||
removedValue = store.replace(this.file1, file1Id, "4567");
|
||||
assertThat(removedValue).isTrue();
|
||||
|
||||
fileID = store.get(this.file1);
|
||||
assertThat(fileID).isNotNull();
|
||||
assertThat(fileID).isEqualTo("4567");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user