diff --git a/pom.xml b/pom.xml index 52859b3..50ee085 100644 --- a/pom.xml +++ b/pom.xml @@ -21,40 +21,39 @@ 1.8 - 3.1.1 - 3.8.0 - 3.1.1 - 3.0.0-M2 - 1.6 - 3.0.1 - 3.1.0 - 3.0.1 + 3.4.2 + 3.10.1 + 3.3.0 + 3.1.0 + 3.0.1 + 3.4.0 + 3.3.0 + 3.2.1 + 3.17.0 - 2.3.5 + 2.17.243 [4.1.59.Final,) 1.2 - 1.11.119 - 2.23.0 - 2.0.0 - 1.3 - 1.9.3 + 1.18.0 + 4.6.1 + 2.2 - 4.13.1 - 2.17.1 - 3.0.0-M3 - 3.0.0-M3 - 0.28.0 + 4.13.2 + 2.18.0 + 3.0.0-M7 + 3.0.0-M7 + 0.40.2 dev */BasicLockClientTests.java,*/GetAllLocksTests.java,*/GetLocksByPartitionKeyTest.java,*/ConsistentLockDataStressTest.java - 3.0.0 - 3.1.10 - 0.8.2 + 3.1.2 + 4.7.1.1 + 0.8.8 ${project.build.directory}/coverage-reports/jacoco-it.exec ${project.build.directory}/coverage-reports/jacoco-ut.exec ${project.build.directory}/coverage-reports/aggregate.exec @@ -133,11 +132,13 @@ software.amazon.awssdk auth ${aws.java.sdk.version} + test software.amazon.awssdk regions ${aws.java.sdk.version} + test software.amazon.awssdk @@ -155,31 +156,6 @@ ${junit.version} test - - org.powermock - powermock-core - ${powermock.version} - test - - - - org.objenesis - objenesis - - - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - org.mockito mockito-core @@ -219,7 +195,7 @@ org.hamcrest - hamcrest-core + hamcrest ${hamcrest.version} @@ -237,18 +213,6 @@ netty-handler ${netty.version} - - - net.bytebuddy - byte-buddy-agent - ${bytebuddy.version} - - - - net.bytebuddy - byte-buddy - ${bytebuddy.version} - @@ -394,7 +358,10 @@ org.apache.maven.plugins maven-pmd-plugin - 3.8 + ${maven.pmd.plugin.version} + + false + @@ -545,9 +512,6 @@ ${dynamodb-local.port}:${dynamodb-local.port} - - ${dynamodb-local.endpoint}/shell/ - diff --git a/src/main/java/com/amazonaws/services/dynamodbv2/AcquireLockOptions.java b/src/main/java/com/amazonaws/services/dynamodbv2/AcquireLockOptions.java index 852ce92..d64de83 100644 --- a/src/main/java/com/amazonaws/services/dynamodbv2/AcquireLockOptions.java +++ b/src/main/java/com/amazonaws/services/dynamodbv2/AcquireLockOptions.java @@ -192,7 +192,7 @@ public AcquireLockOptionsBuilder withTimeUnit(final TimeUnit timeUnit) { * @return a reference to this builder for fluent method chaining */ public AcquireLockOptionsBuilder withAdditionalAttributes(final Map additionalAttributes) { - this.additionalAttributes = additionalAttributes; + this.additionalAttributes = new HashMap<>(additionalAttributes); return this; } diff --git a/src/main/java/com/amazonaws/services/dynamodbv2/LockItem.java b/src/main/java/com/amazonaws/services/dynamodbv2/LockItem.java index 91108ba..8a5636b 100644 --- a/src/main/java/com/amazonaws/services/dynamodbv2/LockItem.java +++ b/src/main/java/com/amazonaws/services/dynamodbv2/LockItem.java @@ -20,10 +20,7 @@ import java.io.Closeable; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @@ -127,7 +124,7 @@ public Optional getData() { * @return The additional attributes that can optionally be stored alongside the lock. */ public Map getAdditionalAttributes() { - return this.additionalAttributes; + return Collections.unmodifiableMap(this.additionalAttributes); } diff --git a/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientOptionsTest.java b/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientOptionsTest.java index 99f9cbb..4e03ff7 100644 --- a/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientOptionsTest.java +++ b/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientOptionsTest.java @@ -15,8 +15,11 @@ package com.amazonaws.services.dynamodbv2; import static org.junit.Assert.assertEquals; -import static org.powermock.api.mockito.PowerMockito.when; +import static org.mockito.Mockito.when; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; @@ -25,10 +28,10 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Matchers; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.ArgumentMatchers; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @@ -40,30 +43,35 @@ * * @author Alexander Patrikalakis 2017-07-13 */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({AmazonDynamoDBLockClientTest.class, AmazonDynamoDBLockClientOptions.AmazonDynamoDBLockClientOptionsBuilder.class}) +@RunWith(MockitoJUnitRunner.class) public class AmazonDynamoDBLockClientOptionsTest { - DynamoDbClient dynamodb = PowerMockito.mock(DynamoDbClient.class); + DynamoDbClient dynamodb = Mockito.mock(DynamoDbClient.class); @Test - public void testBuilder_whenGetLocalHostThrowsUnknownHostException_uuidCreateRandomIsCalled() throws UnknownHostException, InterruptedException { - final UUID uuid = AmazonDynamoDBLockClientTest.setOwnerNameToUuid(); - AmazonDynamoDBLockClientOptions.AmazonDynamoDBLockClientOptionsBuilder builder = AmazonDynamoDBLockClientOptions.builder(dynamodb, "table") - .withLeaseDuration(2L) - .withHeartbeatPeriod(1L) - .withTimeUnit(TimeUnit.SECONDS) - .withPartitionKeyName("customer"); - System.out.println(builder.toString()); - //verifyStatic(); + public void testBuilder_whenGetLocalHostThrowsUnknownHostException_uuidCreateRandomIsCalled() throws InterruptedException, IOException { + final UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = AmazonDynamoDBLockClientTest.setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = AmazonDynamoDBLockClientTest.mockInet4Address()) { + AmazonDynamoDBLockClientOptions.AmazonDynamoDBLockClientOptionsBuilder builder = AmazonDynamoDBLockClientOptions.builder(dynamodb, "table") + .withLeaseDuration(2L) + .withHeartbeatPeriod(1L) + .withTimeUnit(TimeUnit.SECONDS) + .withPartitionKeyName("customer"); + System.out.println(builder.toString()); + //verifyStatic(); - AmazonDynamoDBLockClientOptions options = builder.build(); - AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(options); - Map previousLockItem = new HashMap<>(3); - previousLockItem.put("ownerName", AttributeValue.builder().s("foobar").build()); - previousLockItem.put("recordVersionNumber", AttributeValue.builder().s("oolala").build()); - previousLockItem.put("leaseDuration", AttributeValue.builder().s("1").build()); - when(dynamodb.getItem(Matchers.any())).thenReturn(GetItemResponse.builder().item(previousLockItem).build()); - LockItem lock = client.acquireLock(AcquireLockOptions.builder("asdf").build()); - assertEquals(uuid.toString(), lock.getOwnerName()); + AmazonDynamoDBLockClientOptions options = builder.build(); + LockItem lock; + try (AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(options)) { + Map previousLockItem = new HashMap<>(3); + previousLockItem.put("ownerName", AttributeValue.builder().s("foobar").build()); + previousLockItem.put("recordVersionNumber", AttributeValue.builder().s("oolala").build()); + previousLockItem.put("leaseDuration", AttributeValue.builder().s("1").build()); + when(dynamodb.getItem(ArgumentMatchers.any())).thenReturn(GetItemResponse.builder().item(previousLockItem).build()); + lock = client.acquireLock(AcquireLockOptions.builder("asdf").build()); + } + assertEquals(uuid.toString(), lock.getOwnerName()); + } + } } } diff --git a/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientTest.java b/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientTest.java index 0480d56..507d814 100644 --- a/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientTest.java +++ b/src/test/java/com/amazonaws/services/dynamodbv2/AmazonDynamoDBLockClientTest.java @@ -19,11 +19,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; -import static org.powermock.api.mockito.PowerMockito.doThrow; -import static org.powermock.api.mockito.PowerMockito.spy; -import static org.powermock.api.mockito.PowerMockito.when; import java.net.Inet4Address; +import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.HashMap; @@ -41,11 +39,9 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import com.amazonaws.services.dynamodbv2.util.LockClientUtils; @@ -55,12 +51,11 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.*; import com.amazonaws.services.dynamodbv2.model.LockNotGrantedException; import com.amazonaws.services.dynamodbv2.model.LockTableDoesNotExistException; +import org.mockito.junit.MockitoJUnitRunner; import software.amazon.awssdk.awscore.exception.AwsErrorDetails; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.core.exception.SdkServiceException; @@ -85,38 +80,41 @@ * * @author Alexander Patrikalakis 2017-07-13 */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({AmazonDynamoDBLockClient.class, AmazonDynamoDBLockClientOptions.AmazonDynamoDBLockClientOptionsBuilder.class, AmazonDynamoDBLockClientTest.class}) +@RunWith(MockitoJUnitRunner.class) public class AmazonDynamoDBLockClientTest { private static final String PARTITION_KEY = "pk"; private DynamoDbClient dynamodb; @Before public void setup() { - dynamodb = PowerMockito.mock(DynamoDbClient.class); + dynamodb = Mockito.mock(DynamoDbClient.class); } @Test public void releaseLock_whenRemoveKillSessionMonitorJoinInterrupted_swallowsInterruptedException() throws InterruptedException { - setOwnerNameToUuid(); - Thread thread = spy(new Thread(() -> System.out.println("Running spied thread"), "my-spy-thread")); - doThrow(new InterruptedException()).when(thread).join(); - //need this otherwise the background thread will start the thread in this frame - AmazonDynamoDBLockClient lockClient = spy( - new AmazonDynamoDBLockClient(getLockClientBuilder(threadName -> (runnable -> thread)) - .build())); - Map item = new HashMap<>(4); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s("oolala").build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - when(dynamodb.getItem(ArgumentMatchers.any())).thenReturn(GetItemResponse.builder().item(item).build()); - LockItem lockItem = lockClient.acquireLock(AcquireLockOptions.builder(PARTITION_KEY) - .withSessionMonitor(3001, - Optional.of(() -> System.out.println("monitored"))) - .withTimeUnit(TimeUnit.MILLISECONDS) - .build()); - lockClient.releaseLock(lockItem); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + Thread thread = spy(new Thread(() -> System.out.println("Running spied thread"), "my-spy-thread")); + doThrow(new InterruptedException()).when(thread).join(); + //need this otherwise the background thread will start the thread in this frame + AmazonDynamoDBLockClient lockClient = spy( + new AmazonDynamoDBLockClient(getLockClientBuilder(threadName -> (runnable -> thread)) + .build())); + Map item = new HashMap<>(4); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s("oolala").build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + when(dynamodb.getItem(ArgumentMatchers.any())).thenReturn(GetItemResponse.builder().item(item).build()); + LockItem lockItem = lockClient.acquireLock(AcquireLockOptions.builder(PARTITION_KEY) + .withSessionMonitor(3001, + Optional.of(() -> System.out.println("monitored"))) + .withTimeUnit(TimeUnit.MILLISECONDS) + .build()); + lockClient.releaseLock(lockItem); + } + } } @Test @@ -149,7 +147,7 @@ public void lockTableExists_whenTableIsCreating_returnFalse() { @Test(expected = LockTableDoesNotExistException.class) public void assertLockTableExists_whenTableIsUpdating_returnTrue() { - when(dynamodb.describeTable(any(DescribeTableRequest.class))).thenReturn(DescribeTableResponse.builder().table(TableDescription.builder().tableStatus(TableStatus.UPDATING).build()).build()); + //when(dynamodb.describeTable(any(DescribeTableRequest.class))).thenReturn(DescribeTableResponse.builder().table(TableDescription.builder().tableStatus(TableStatus.UPDATING).build()).build()); when(dynamodb.describeTable(any(DescribeTableRequest.class))).thenThrow(SdkServiceException.builder().message("Exception was not a ResourceNotFoundException").build()); AmazonDynamoDBLockClient lockClient = getLockClient(); lockClient.assertLockTableExists(); @@ -157,190 +155,230 @@ public void assertLockTableExists_whenTableIsUpdating_returnTrue() { @Test(expected = LockNotGrantedException.class) public void acquireLock_whenLockAlreadyExists_throwLockNotGrantedException() throws InterruptedException { - setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map lockItem = new HashMap<>(3); - lockItem.put("ownerName", AttributeValue.builder().s("owner").build()); - lockItem.put("leaseDuration", AttributeValue.builder().s("1").build()); - lockItem.put("recordVersionNumber", AttributeValue.builder().s("uuid").build()); - when(dynamodb.getItem(ArgumentMatchers.any())).thenReturn(GetItemResponse.builder().item(lockItem).build()); - when(dynamodb.putItem(ArgumentMatchers.any())).thenThrow(ConditionalCheckFailedException.builder().message("item existed").build()); - client.acquireLock(AcquireLockOptions.builder("asdf").build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map lockItem = new HashMap<>(3); + lockItem.put("ownerName", AttributeValue.builder().s("owner").build()); + lockItem.put("leaseDuration", AttributeValue.builder().s("1").build()); + lockItem.put("recordVersionNumber", AttributeValue.builder().s("uuid").build()); + when(dynamodb.getItem(ArgumentMatchers.any())).thenReturn(GetItemResponse.builder().item(lockItem).build()); + when(dynamodb.putItem(ArgumentMatchers.any())).thenThrow(ConditionalCheckFailedException.builder().message("item existed").build()); + client.acquireLock(AcquireLockOptions.builder("asdf").build()); + } + } } @Test(expected = LockNotGrantedException.class) public void acquireLock_whenProvisionedThroughputExceeds_throwLockNotGrantedException() throws InterruptedException { - setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - - Map item = new HashMap<>(4); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s("oolala").build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - when(dynamodb.getItem(Mockito.any())).thenReturn(GetItemResponse.builder().item(item).build()); - when(dynamodb.putItem(Mockito.any())).thenThrow(ProvisionedThroughputExceededException.builder() - .message("Provisioned Throughput for the table exceeded").build()); - client.acquireLock(AcquireLockOptions.builder("asdf").build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + + Map item = new HashMap<>(4); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s("oolala").build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + when(dynamodb.getItem(Mockito.any())).thenReturn(GetItemResponse.builder().item(item).build()); + when(dynamodb.putItem(Mockito.any())).thenThrow(ProvisionedThroughputExceededException.builder() + .message("Provisioned Throughput for the table exceeded").build()); + client.acquireLock(AcquireLockOptions.builder("asdf").build()); + } + } } @Test(expected = IllegalArgumentException.class) public void acquireLock_whenLockAlreadyExists_throwIllegalArgumentException() throws InterruptedException { - setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClientWithSortKey(); - Map additionalAttributes = new HashMap<>(); - additionalAttributes.put("sort", AttributeValue.builder().s("cool").build()); - client.acquireLock(AcquireLockOptions.builder("asdf") - .withSortKey("sort") - .withAdditionalAttributes(additionalAttributes).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClientWithSortKey(); + Map additionalAttributes = new HashMap<>(); + additionalAttributes.put("sort", AttributeValue.builder().s("cool").build()); + client.acquireLock(AcquireLockOptions.builder("asdf") + .withSortKey("sort") + .withAdditionalAttributes(additionalAttributes).build()); + } + } } @Test(expected = LockNotGrantedException.class) public void acquireLock_whenLockDoesNotExist_andWhenAcquireOnlyIfLockAlreadyExistsTrue_throwLockNotGrantedException() throws InterruptedException { - setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - when(dynamodb.getItem(Mockito.any())).thenReturn(GetItemResponse.builder().item(null).build()); - client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireOnlyIfLockAlreadyExists(true).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + when(dynamodb.getItem(Mockito.any())).thenReturn(GetItemResponse.builder().item(null).build()); + client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireOnlyIfLockAlreadyExists(true).build()); + } + } } @Test(expected = LockNotGrantedException.class) public void acquireLock_withAcquireOnlyIfLockAlreadyExistsTrue_releasedLockConditionalCheckFailure() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - item.put("isReleased", AttributeValue.builder().bool(true).build()); - - doAnswer((InvocationOnMock invocation) -> GetItemResponse.builder().item(item).build()) - .when(dynamodb).getItem(Mockito.any()); - when(dynamodb.putItem(Mockito.any())).thenThrow(ConditionalCheckFailedException.builder().message("item existed").build()); - client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireOnlyIfLockAlreadyExists(true).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + item.put("isReleased", AttributeValue.builder().bool(true).build()); + + doAnswer((InvocationOnMock invocation) -> GetItemResponse.builder().item(item).build()) + .when(dynamodb).getItem(Mockito.any()); + when(dynamodb.putItem(Mockito.any())).thenThrow(ConditionalCheckFailedException.builder().message("item existed").build()); + client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireOnlyIfLockAlreadyExists(true).build()); + } + } } @Test public void acquireLock_withAcquireOnlyIfLockAlreadyExists_releasedLockGetsCreated() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - item.put("isReleased", AttributeValue.builder().bool(true).build()); - when(dynamodb.getItem(Mockito.any())).thenReturn(GetItemResponse.builder().item(item).build()); - LockItem lockItem = client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireOnlyIfLockAlreadyExists(true).build()); - assertNotNull(lockItem); - assertEquals("asdf", lockItem.getPartitionKey()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + item.put("isReleased", AttributeValue.builder().bool(true).build()); + when(dynamodb.getItem(Mockito.any())).thenReturn(GetItemResponse.builder().item(item).build()); + LockItem lockItem = client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireOnlyIfLockAlreadyExists(true).build()); + assertNotNull(lockItem); + assertEquals("asdf", lockItem.getPartitionKey()); + } + } } @Test public void acquireLock_withReentrant_doesNotFailIfHoldingLock() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - Map differentRvn1 = new HashMap<>(item); - differentRvn1.put("recordVersionNumber", - AttributeValue.builder().s("uuid1").build()); - Map differentRvn2 = new HashMap<>(item); - differentRvn2.put("recordVersionNumber", - AttributeValue.builder().s("uuid2").build()); - when(dynamodb.getItem(Mockito.any())) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().item(differentRvn1).build()) - .thenReturn(GetItemResponse.builder().item(differentRvn2).build()); - String partitionKey = "asdf"; - LockItem lockItem1 = client.acquireLock(AcquireLockOptions.builder(partitionKey).build()); - assertNotNull(lockItem1); - assertEquals(partitionKey, lockItem1.getPartitionKey()); - - LockItem lockItem2 = client.acquireLock(AcquireLockOptions.builder(partitionKey) - .withReentrant(true).build()); - assertNotNull(lockItem2); - assertEquals(partitionKey, lockItem2.getPartitionKey()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + Map differentRvn1 = new HashMap<>(item); + differentRvn1.put("recordVersionNumber", + AttributeValue.builder().s("uuid1").build()); + Map differentRvn2 = new HashMap<>(item); + differentRvn2.put("recordVersionNumber", + AttributeValue.builder().s("uuid2").build()); + when(dynamodb.getItem(Mockito.any())) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().item(differentRvn1).build()) + .thenReturn(GetItemResponse.builder().item(differentRvn2).build()); + String partitionKey = "asdf"; + LockItem lockItem1 = client.acquireLock(AcquireLockOptions.builder(partitionKey).build()); + assertNotNull(lockItem1); + assertEquals(partitionKey, lockItem1.getPartitionKey()); + + LockItem lockItem2 = client.acquireLock(AcquireLockOptions.builder(partitionKey) + .withReentrant(true).build()); + assertNotNull(lockItem2); + assertEquals(partitionKey, lockItem2.getPartitionKey()); + } + } } @Test public void acquireLock_withReentrantFalse_failsIfHoldingLock() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - // Use different rvns to simulate heartbeat. - Map differentRvn1 = new HashMap<>(item); - differentRvn1.put("recordVersionNumber", - AttributeValue.builder().s("uuid1").build()); - Map differentRvn2 = new HashMap<>(item); - differentRvn2.put("recordVersionNumber", - AttributeValue.builder().s("uuid2").build()); - when(dynamodb.getItem(Mockito.any())) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().item(differentRvn1).build()) - .thenReturn(GetItemResponse.builder().item(differentRvn2).build()); - String partitionKey = "asdf"; - LockItem lockItem1 = client.acquireLock(AcquireLockOptions.builder(partitionKey).build()); - assertNotNull(lockItem1); - assertEquals(partitionKey, lockItem1.getPartitionKey()); - - try { - client.acquireLock(AcquireLockOptions.builder(partitionKey).build()); - fail("Expected acquireLock to throw."); - } catch (LockNotGrantedException e) { - assertTrue(e.getMessage().contains("Didn't acquire lock after sleeping for")); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + // Use different rvns to simulate heartbeat. + Map differentRvn1 = new HashMap<>(item); + differentRvn1.put("recordVersionNumber", + AttributeValue.builder().s("uuid1").build()); + Map differentRvn2 = new HashMap<>(item); + differentRvn2.put("recordVersionNumber", + AttributeValue.builder().s("uuid2").build()); + when(dynamodb.getItem(Mockito.any())) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().item(differentRvn1).build()) + .thenReturn(GetItemResponse.builder().item(differentRvn2).build()); + String partitionKey = "asdf"; + LockItem lockItem1 = client.acquireLock(AcquireLockOptions.builder(partitionKey).build()); + assertNotNull(lockItem1); + assertEquals(partitionKey, lockItem1.getPartitionKey()); + + try { + client.acquireLock(AcquireLockOptions.builder(partitionKey).build()); + fail("Expected acquireLock to throw."); + } catch (LockNotGrantedException e) { + assertTrue(e.getMessage().contains("Didn't acquire lock after sleeping for")); + } + } } } @Test public void acquireLock_whenLockAlreadyExistsAndIsNotReleased_andWhenHaveSleptForMinimumLeaseDurationTime_skipsAddingLeaseDuration() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(4); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - - Map differentItem = new HashMap<>(item); - differentItem.put("recordVersionNumber", AttributeValue.builder().s("a different uuid").build()); - - when(dynamodb.getItem(ArgumentMatchers.any())) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().item(differentItem).build()) - .thenReturn(GetItemResponse.builder().item(differentItem).build()); - LockItem lockItem = client.acquireLock(AcquireLockOptions.builder("customer1") - .withRefreshPeriod(800L) - .withAdditionalTimeToWaitForLock(100000L) - .withTimeUnit(TimeUnit.MILLISECONDS) - .withDeleteLockOnRelease(false).build()); - assertNotNull(lockItem); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(4); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + + Map differentItem = new HashMap<>(item); + differentItem.put("recordVersionNumber", AttributeValue.builder().s("a different uuid").build()); + + when(dynamodb.getItem(ArgumentMatchers.any())) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().item(differentItem).build()) + .thenReturn(GetItemResponse.builder().item(differentItem).build()); + LockItem lockItem = client.acquireLock(AcquireLockOptions.builder("customer1") + .withRefreshPeriod(800L) + .withAdditionalTimeToWaitForLock(100000L) + .withTimeUnit(TimeUnit.MILLISECONDS) + .withDeleteLockOnRelease(false).build()); + assertNotNull(lockItem); + } + } } @Test(expected = LockNotGrantedException.class) public void acquireLock_withConsistentLockDataTrue_releasedLockConditionalCheckFailure() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - item.put("isReleased", AttributeValue.builder().bool(true).build()); - doAnswer((InvocationOnMock invocation) -> GetItemResponse.builder().item(item).build()) - .when(dynamodb).getItem(Mockito.any()); - when(dynamodb.putItem(Mockito.any())).thenThrow(ConditionalCheckFailedException.builder().message("RVN constraint failed").build()); - client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireReleasedLocksConsistently(true).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + item.put("isReleased", AttributeValue.builder().bool(true).build()); + doAnswer((InvocationOnMock invocation) -> GetItemResponse.builder().item(item).build()) + .when(dynamodb).getItem(Mockito.any()); + when(dynamodb.putItem(Mockito.any())).thenThrow(ConditionalCheckFailedException.builder().message("RVN constraint failed").build()); + client.acquireLock(AcquireLockOptions.builder("asdf").withAcquireReleasedLocksConsistently(true).build()); + } + } } @Test @@ -410,20 +448,24 @@ public void acquireLock_whenLockNotExists_andSkipBlockingWaitIsTurnedOn() public void acquireLock_whenLockExistsAndIsExpired_andSkipBlockingWaitIsTurnedOn() throws InterruptedException { AmazonDynamoDBLockClient client = getLockClient(); - UUID uuid = setOwnerNameToUuid(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("1").build()); - item.put("isReleased", AttributeValue.builder().bool(true).build()); - when(dynamodb.getItem(Mockito.any())) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().build()); - LockItem lockItem = client.acquireLock(AcquireLockOptions.builder("customer1") - .withShouldSkipBlockingWait(true) - .withDeleteLockOnRelease(false).build()); - Assert.assertNotNull("Failed to get lock item, when the lock is not present in the db", lockItem); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("1").build()); + item.put("isReleased", AttributeValue.builder().bool(true).build()); + when(dynamodb.getItem(Mockito.any())) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().build()); + LockItem lockItem = client.acquireLock(AcquireLockOptions.builder("customer1") + .withShouldSkipBlockingWait(true) + .withDeleteLockOnRelease(false).build()); + Assert.assertNotNull("Failed to get lock item, when the lock is not present in the db", lockItem); + } + } } /* * Test case for the scenario, where the lock is being held by the first owner and the lock duration has not past @@ -432,96 +474,124 @@ public void acquireLock_whenLockExistsAndIsExpired_andSkipBlockingWaitIsTurnedOn @Test(expected = LockCurrentlyUnavailableException.class) public void acquireLock_whenLockAlreadyExistsAndIsNotReleased_andSkipBlockingWait_throwsAlreadyOwnedException() throws InterruptedException { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - Map item = new HashMap<>(5); - item.put("customer", AttributeValue.builder().s("customer1").build()); - item.put("ownerName", AttributeValue.builder().s("foobar").build()); - item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); - item.put("leaseDuration", AttributeValue.builder().s("100000").build()); - when(dynamodb.getItem(Mockito.any())) - .thenReturn(GetItemResponse.builder().item(item).build()) - .thenReturn(GetItemResponse.builder().build()); - AcquireLockOptions acquireLockOptions = AcquireLockOptions.builder("customer1") - .withShouldSkipBlockingWait(true) - .withDeleteLockOnRelease(false).build(); - client.acquireLock(acquireLockOptions); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + Map item = new HashMap<>(5); + item.put("customer", AttributeValue.builder().s("customer1").build()); + item.put("ownerName", AttributeValue.builder().s("foobar").build()); + item.put("recordVersionNumber", AttributeValue.builder().s(uuid.toString()).build()); + item.put("leaseDuration", AttributeValue.builder().s("100000").build()); + when(dynamodb.getItem(Mockito.any())) + .thenReturn(GetItemResponse.builder().item(item).build()) + .thenReturn(GetItemResponse.builder().build()); + AcquireLockOptions acquireLockOptions = AcquireLockOptions.builder("customer1") + .withShouldSkipBlockingWait(true) + .withDeleteLockOnRelease(false).build(); + client.acquireLock(acquireLockOptions); + } + } } @Test(expected = IllegalArgumentException.class) public void sendHeartbeat_whenDeleteDataTrueAndDataNotNull_throwsIllegalArgumentException() { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, uuid.toString(), 1L, 2L, "rvn", false, - Optional.empty(), null); - client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(true).withData(ByteBuffer.wrap("data".getBytes())).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, uuid.toString(), 1L, 2L, "rvn", false, + Optional.empty(), null); + client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(true).withData(ByteBuffer.wrap("data".getBytes())).build()); + } + } } @Test(expected = LockNotGrantedException.class) public void sendHeartbeat_whenExpired_throwsLockNotGrantedException() { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - long lastUpdatedTimeInMilliseconds = 2l; - LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, - "rvn", false, Optional.empty(), null); - client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(null).withData(ByteBuffer.wrap("data".getBytes())).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + long lastUpdatedTimeInMilliseconds = 2l; + LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, + "rvn", false, Optional.empty(), null); + client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(null).withData(ByteBuffer.wrap("data".getBytes())).build()); + } + } } @Test(expected = LockNotGrantedException.class) public void sendHeartbeat_whenNotExpiredAndDifferentOwner_throwsLockNotGrantedException() { - setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; - LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, "different owner", 1L, lastUpdatedTimeInMilliseconds, - "rvn", false, Optional.empty(), null); - client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(null).withData(ByteBuffer.wrap("data".getBytes())).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; + LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, "different owner", 1L, lastUpdatedTimeInMilliseconds, + "rvn", false, Optional.empty(), null); + client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(null).withData(ByteBuffer.wrap("data".getBytes())).build()); + } + } } @Test(expected = LockNotGrantedException.class) public void sendHeartbeat_whenNotExpired_andSameOwner_releasedTrue_throwsLockNotGrantedException() { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; - LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, - "rvn", true, Optional.empty(), null); - client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(null).withData(ByteBuffer.wrap("data".getBytes())).build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; + LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, + "rvn", true, Optional.empty(), null); + client.sendHeartbeat(SendHeartbeatOptions.builder(item).withDeleteData(null).withData(ByteBuffer.wrap("data".getBytes())).build()); + } + } } @Test public void sendHeartbeat_whenNotExpired_andSameOwner_releasedFalse_setsRequestMetricCollector() { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; - LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, - "rvn", false, Optional.empty(), null); - client.sendHeartbeat(SendHeartbeatOptions.builder(item) - .withDeleteData(null) - .withData(ByteBuffer.wrap("data".getBytes())) - .build()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; + LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, + "rvn", false, Optional.empty(), null); + client.sendHeartbeat(SendHeartbeatOptions.builder(item) + .withDeleteData(null) + .withData(ByteBuffer.wrap("data".getBytes())) + .build()); + } + } } @Test public void sendHeartbeat_whenNotExpired_andSameOwner_releasedFalse_deleteDataFalse_updatesData() { - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = getLockClient(); - long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; - String partitionKey = "partition_key"; - LockItem item = new LockItem(client, partitionKey, Optional.empty(), Optional.of(ByteBuffer.wrap("data1".getBytes())), - false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, - "rvn", false, Optional.empty(), null); - assertTrue(item.getData().isPresent()); - ByteBuffer updated = ByteBuffer.wrap("data2".getBytes()); - client.sendHeartbeat(SendHeartbeatOptions.builder(item) - .withDeleteData(null) - .withData(updated) - .build()); - assertTrue(item.getData().isPresent()); - assertEquals(updated, item.getData().get()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = getLockClient(); + long lastUpdatedTimeInMilliseconds = Long.MAX_VALUE; + String partitionKey = "partition_key"; + LockItem item = new LockItem(client, partitionKey, Optional.empty(), Optional.of(ByteBuffer.wrap("data1".getBytes())), + false, uuid.toString(), 1L, lastUpdatedTimeInMilliseconds, + "rvn", false, Optional.empty(), null); + assertTrue(item.getData().isPresent()); + ByteBuffer updated = ByteBuffer.wrap("data2".getBytes()); + client.sendHeartbeat(SendHeartbeatOptions.builder(item) + .withDeleteData(null) + .withData(updated) + .build()); + assertTrue(item.getData().isPresent()); + assertEquals(updated, item.getData().get()); + } + } } @Test @@ -530,23 +600,27 @@ public void sendHeartbeat_whenServiceUnavailable_andHoldLockOnServiceUnavailable .awsErrorDetails(AwsErrorDetails.builder().sdkHttpResponse(SdkHttpResponse.builder().statusCode(HttpStatusCode.SERVICE_UNAVAILABLE).build()).build()).build(); when(dynamodb.updateItem(Mockito.any())).thenThrow(serviceUnavailableException); - UUID uuid = setOwnerNameToUuid(); - AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(getLockClientBuilder(null).withHoldLockOnServiceUnavailable(false).build()); - - long lastUpdatedTimeInMilliseconds = LockClientUtils.INSTANCE.millisecondTime(); - LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, uuid.toString(), 10000L, lastUpdatedTimeInMilliseconds, - "rvn", false, Optional.empty(), null); - - AwsServiceException amazonServiceException = null; - try { - client.sendHeartbeat(SendHeartbeatOptions.builder(item).build()); - } catch (AwsServiceException e) { - amazonServiceException = e; + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(getLockClientBuilder(null).withHoldLockOnServiceUnavailable(false).build()); + + long lastUpdatedTimeInMilliseconds = LockClientUtils.INSTANCE.millisecondTime(); + LockItem item = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, uuid.toString(), 10000L, lastUpdatedTimeInMilliseconds, + "rvn", false, Optional.empty(), null); + + AwsServiceException amazonServiceException = null; + try { + client.sendHeartbeat(SendHeartbeatOptions.builder(item).build()); + } catch (AwsServiceException e) { + amazonServiceException = e; + } + + assertEquals(serviceUnavailableException, amazonServiceException); + assertEquals(lastUpdatedTimeInMilliseconds, item.getLookupTime()); + } } - - assertEquals(serviceUnavailableException, amazonServiceException); - assertEquals(lastUpdatedTimeInMilliseconds, item.getLookupTime()); } @Test @@ -555,26 +629,30 @@ public void sendHeartbeat_whenServiceUnavailable_andHoldLockOnServiceUnavailable .awsErrorDetails(AwsErrorDetails.builder().sdkHttpResponse(SdkHttpResponse.builder().statusCode(HttpStatusCode.SERVICE_UNAVAILABLE).build()).build()).build(); when(dynamodb.updateItem(Mockito.any())).thenThrow(serviceUnavailableException); - UUID uuid = setOwnerNameToUuid(); - long leaseDuration = 10000L; - AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(getLockClientBuilder(null) - .withLeaseDuration(leaseDuration).withHoldLockOnServiceUnavailable(true).build()); - - String recordVersionNumber = "rvn"; - long lastUpdatedTimeInMilliseconds = LockClientUtils.INSTANCE.millisecondTime(); - LockItem lockItem = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), - false, uuid.toString(), leaseDuration, lastUpdatedTimeInMilliseconds, - recordVersionNumber, false, Optional.empty(), null); - - // Setting up a spy mock to inspect the method on lockItem object created above - LockItem lockItemSpy = PowerMockito.spy(lockItem); - - Thread.sleep(1L); // This is to make sure that the lookup time has a higher value - client.sendHeartbeat(SendHeartbeatOptions.builder(lockItemSpy).build()); - - assertTrue(lockItemSpy.getLookupTime() > lastUpdatedTimeInMilliseconds); - verify(lockItemSpy, times(1)).updateLookUpTime(anyLong()); - verify(lockItemSpy, times(0)).updateRecordVersionNumber(anyString(), anyLong(), anyLong()); + UUID uuid = UUID.randomUUID(); + try (MockedStatic ignored = setOwnerNameToUuid(uuid)) { + try (MockedStatic ignored1 = mockInet4Address()) { + long leaseDuration = 10000L; + AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(getLockClientBuilder(null) + .withLeaseDuration(leaseDuration).withHoldLockOnServiceUnavailable(true).build()); + + String recordVersionNumber = "rvn"; + long lastUpdatedTimeInMilliseconds = LockClientUtils.INSTANCE.millisecondTime(); + LockItem lockItem = new LockItem(client, "a", Optional.empty(), Optional.of(ByteBuffer.wrap("data".getBytes())), + false, uuid.toString(), leaseDuration, lastUpdatedTimeInMilliseconds, + recordVersionNumber, false, Optional.empty(), null); + + // Setting up a spy mock to inspect the method on lockItem object created above + LockItem lockItemSpy = Mockito.spy(lockItem); + + Thread.sleep(1L); // This is to make sure that the lookup time has a higher value + client.sendHeartbeat(SendHeartbeatOptions.builder(lockItemSpy).build()); + + assertTrue(lockItemSpy.getLookupTime() > lastUpdatedTimeInMilliseconds); + verify(lockItemSpy, times(1)).updateLookUpTime(anyLong()); + verify(lockItemSpy, times(0)).updateRecordVersionNumber(anyString(), anyLong(), anyLong()); + } + } } private AmazonDynamoDBLockClient getLockClient() { @@ -600,20 +678,19 @@ private AmazonDynamoDBLockClientOptions.AmazonDynamoDBLockClientOptionsBuilder g .withCreateHeartbeatBackgroundThread(false); } - /** - * Requires power mockito to mock the system and static calls. - * @return - */ - public static UUID setOwnerNameToUuid() { - final UUID uuid = UUID.randomUUID(); //get UUID for use in test - PowerMockito.mockStatic(UUID.class); //, invocation -> uuid); //mock UUID + public static MockedStatic setOwnerNameToUuid(final UUID uuid) { + MockedStatic uuidMockedStatic = mockStatic(UUID.class);//, invocation -> uuid); //mock UUID when(UUID.randomUUID()).thenReturn(uuid); //return pregenerated uuid - PowerMockito.mockStatic(Inet4Address.class); + return uuidMockedStatic; + } + + public static MockedStatic mockInet4Address() { + MockedStatic inet4AddressMockedStatic = mockStatic(InetAddress.class); try { - when(Inet4Address.getLocalHost()).thenThrow(new UnknownHostException()); + when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException()); } catch(UnknownHostException willNotHappenBecauseItsMocked) { throw new Error("mock not configured correctly"); } - return uuid; + return inet4AddressMockedStatic; } } diff --git a/src/test/java/com/amazonaws/services/dynamodbv2/SessionMonitorTest.java b/src/test/java/com/amazonaws/services/dynamodbv2/SessionMonitorTest.java index 53dab75..f475b74 100644 --- a/src/test/java/com/amazonaws/services/dynamodbv2/SessionMonitorTest.java +++ b/src/test/java/com/amazonaws/services/dynamodbv2/SessionMonitorTest.java @@ -16,34 +16,32 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.powermock.api.mockito.PowerMockito.when; +import static org.mockito.Mockito.when; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /** * SendHeartbeatOptions unit tests. * * @author Alexander Patrikalakis 2017-07-13 */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({SessionMonitor.class}) +@RunWith(MockitoJUnitRunner.class) public class SessionMonitorTest { @Test public void isLeaseEnteringDangerZone_whenThereAreZeroOrLessMillisUntilEnterDangerZone_returnTrue() { - SessionMonitor sut = PowerMockito.spy(new SessionMonitor(1000, Optional.empty())); + SessionMonitor sut = Mockito.spy(new SessionMonitor(1000, Optional.empty())); when(sut.millisecondsUntilLeaseEntersDangerZone(25L)).thenReturn(0L); assertTrue(sut.isLeaseEnteringDangerZone(25L)); } @Test public void isLeaseEnteringDangerZone_whenThereAreMoreThanZeroMillisUntilEnterDangerZone_returnFalse() { - SessionMonitor sut = PowerMockito.spy(new SessionMonitor(1000, Optional.empty())); + SessionMonitor sut = Mockito.spy(new SessionMonitor(1000, Optional.empty())); when(sut.millisecondsUntilLeaseEntersDangerZone(25L)).thenReturn(1L); assertFalse(sut.isLeaseEnteringDangerZone(25L)); } diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000..ca6ee9c --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file