package com.ldbc.driver.runtime.coordination; import com.google.common.collect.Sets; import com.ldbc.driver.runtime.ConcurrentErrorReporter; import com.ldbc.driver.temporal.SystemTimeSource; import com.ldbc.driver.temporal.TimeSource; import org.junit.Test; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class CompletionTimeServiceBasicTest { @Test public void shouldBehavePredictablyAfterInstantiationWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { shouldBehavePredictablyAfterInstantiation(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldBehavePredictablyAfterInstantiationWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { shouldBehavePredictablyAfterInstantiation(completionTimeService); } finally { completionTimeService.shutdown(); } } public void shouldBehavePredictablyAfterInstantiation(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given // instantiated completion time service // When // nothing // Then assertThat(completionTimeService.globalCompletionTimeAsMilli(), is(-1l)); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); } @Test public void shouldAdvanceGctWhenWriterSubmitInitiatedAndCompletedTimesWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { shouldAdvanceGctWhenWriterSubmitInitiatedAndCompletedTimes(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldAdvanceGctWhenWriterSubmitInitiatedAndCompletedTimesWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { shouldAdvanceGctWhenWriterSubmitInitiatedAndCompletedTimes(completionTimeService); } finally { completionTimeService.shutdown(); } } public void shouldAdvanceGctWhenWriterSubmitInitiatedAndCompletedTimes(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter writer1 = completionTimeService.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = completionTimeService.newLocalCompletionTimeWriter(); // When writer1.submitLocalInitiatedTime(0l); writer1.submitLocalCompletedTime(0l); writer2.submitLocalInitiatedTime(0l); writer2.submitLocalCompletedTime(0l); writer1.submitLocalInitiatedTime(1l); writer2.submitLocalInitiatedTime(1l); // Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(0l)); assertThat(completionTimeService.globalCompletionTimeAsMilli(), is(0l)); } @Test public void shouldReturnAllWritersWithSynchronizedImplementation() throws CompletionTimeException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { shouldReturnAllWriters(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnAllWritersWithThreadedImplementation() throws CompletionTimeException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { shouldReturnAllWriters(completionTimeService); } finally { completionTimeService.shutdown(); } } public void shouldReturnAllWriters(CompletionTimeService completionTimeService) throws CompletionTimeException { // Given // instantiated completion time service // When/Then assertThat(completionTimeService.getAllWriters().size(), is(0)); LocalCompletionTimeWriter writer1 = completionTimeService.newLocalCompletionTimeWriter(); assertThat(completionTimeService.getAllWriters().size(), is(1)); assertThat(completionTimeService.getAllWriters().contains(writer1), is(true)); LocalCompletionTimeWriter writer2 = completionTimeService.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer3 = completionTimeService.newLocalCompletionTimeWriter(); assertThat(completionTimeService.getAllWriters().size(), is(3)); assertThat(completionTimeService.getAllWriters().contains(writer1), is(true)); assertThat(completionTimeService.getAllWriters().contains(writer2), is(true)); assertThat(completionTimeService.getAllWriters().contains(writer3), is(true)); } @Test public void shouldReturnNullWhenNoLocalITNoLocalCTNoExternalCTWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnNullWhenNoLocalITNoLocalCTNoExternalCT(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnNullWhenNoLocalITNoLocalCTNoExternalCTWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnNullWhenNoLocalITNoLocalCTNoExternalCT(completionTimeService); } finally { completionTimeService.shutdown(); } } // LocalIT = none, LocalCT = none, ExternalCT = none --> null public void doShouldReturnNullWhenNoLocalITNoLocalCTNoExternalCT(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); // When // no events have been initiated or completed // Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); } @Test public void shouldReturnNullWhenSomeITAndNoCTAndNoExternalCTWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnNullWhenSomeITAndNoCTAndNoExternalCT(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnNullWhenSomeITAndNoCTAndNoExternalCTWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = new HashSet<>(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnNullWhenSomeITAndNoCTAndNoExternalCT(completionTimeService); } finally { completionTimeService.shutdown(); } } // LocalIT = some, LocalCT = none, ExternalCT = none --> null public void doShouldReturnNullWhenSomeITAndNoCTAndNoExternalCT(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); // When localCompletionTimeWriter.submitLocalInitiatedTime(1000l); // Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); } @Test public void shouldReturnNullWhenNoLocalITAndNoLocalCTAndSomeExternalCTWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnNullWhenNoLocalITAndNoLocalCTAndSomeExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnNullWhenNoLocalITAndNoLocalCTAndSomeExternalCTWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnNullWhenNoLocalITAndNoLocalCTAndSomeExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } // LocalIT = none, LocalCT = none, ExternalCT = some --> null public void doShouldReturnNullWhenNoLocalITAndNoLocalCTAndSomeExternalCT(CompletionTimeService completionTimeService, String otherPeerId) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given ExternalCompletionTimeWriter externalCompletionTimeWriter = completionTimeService; // When externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 1000l); // Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); } @Test public void shouldReturnNullWhenSomeLocalITAndSomeLocalCTAndNoExternalCTWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnNullWhenSomeLocalITAndSomeLocalCTAndNoExternalCT(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnNullWhenSomeLocalITAndSomeLocalCTAndNoExternalCTWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnNullWhenSomeLocalITAndSomeLocalCTAndNoExternalCT(completionTimeService); } finally { completionTimeService.shutdown(); } } // LocalIT = some, LocalCT = some, ExternalCT = none --> null public void doShouldReturnNullWhenSomeLocalITAndSomeLocalCTAndNoExternalCT(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); // When localCompletionTimeWriter.submitLocalInitiatedTime(1000l); localCompletionTimeWriter.submitLocalCompletedTime(1000l); // Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); } @Test public void shouldReturnNullWhenSomeLocalITAndNoLocalCTAndSomeExternalCTWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnNullWhenSomeLocalITAndNoLocalCTAndSomeExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnNullWhenSomeLocalITAndNoLocalCTAndSomeExternalCTWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnNullWhenSomeLocalITAndNoLocalCTAndSomeExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } // LocalIT = 1, LocalCT = none, ExternalCT = 2 --> null public void doShouldReturnNullWhenSomeLocalITAndNoLocalCTAndSomeExternalCT(CompletionTimeService completionTimeService, String otherPeerId) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); ExternalCompletionTimeWriter externalCompletionTimeWriter = completionTimeService; // When localCompletionTimeWriter.submitLocalInitiatedTime(1000l); externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 2000l); // Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); } @Test public void shouldReturnGCTWhenLowerLCTThanExternalCTWithSynchronizedImplementation() throws CompletionTimeException, ExecutionException, InterruptedException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnLCTWhenLowerLCTThanExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnGCTWhenLowerLCTThanExternalCTWithThreadedImplementation() throws CompletionTimeException, ExecutionException, InterruptedException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnLCTWhenLowerLCTThanExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } // LocalIT = 1, LocalCT = 1, ExternalCT = 2 --> 1 public void doShouldReturnLCTWhenLowerLCTThanExternalCT(CompletionTimeService completionTimeService, String otherPeerId) throws CompletionTimeException, ExecutionException, InterruptedException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); ExternalCompletionTimeWriter externalCompletionTimeWriter = completionTimeService; // When/Then localCompletionTimeWriter.submitLocalInitiatedTime(1000l); localCompletionTimeWriter.submitLocalCompletedTime(1000l); externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(), is(-1l)); localCompletionTimeWriter.submitLocalInitiatedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); } @Test public void shouldReturnExternalCTWhenLowerLCTThanExternalCTWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnExternalCTWhenLowerLCTThanExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnExternalCTWhenLowerLCTThanExternalCTWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnExternalCTWhenLowerLCTThanExternalCT(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } // LocalIT = 2, LocalCT = 2, ExternalCT = --> 1 public void doShouldReturnExternalCTWhenLowerLCTThanExternalCT(CompletionTimeService completionTimeService, String otherPeerId) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); ExternalCompletionTimeWriter externalCompletionTimeWriter = completionTimeService; // When/Then localCompletionTimeWriter.submitLocalInitiatedTime(2000l); localCompletionTimeWriter.submitLocalCompletedTime(2000l); externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); localCompletionTimeWriter.submitLocalInitiatedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); } @Test public void shouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeers(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeers(completionTimeService); } finally { completionTimeService.shutdown(); } } public void doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeers(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); // When/Then // initiated [1] // completed [] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1] // completed [1] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1,2] // completed [1] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2] // completed [1,2] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2,3] // completed [1,2] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4] // completed [1,2] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5] // completed [1,2] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5] // completed [1,2, , ,5] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2, , ,5, , , , , ] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(6000l); localCompletionTimeWriter.submitLocalInitiatedTime(7000l); localCompletionTimeWriter.submitLocalInitiatedTime(8000l); localCompletionTimeWriter.submitLocalInitiatedTime(9000l); localCompletionTimeWriter.submitLocalInitiatedTime(10000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2, , ,5, , ,8, , ] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(8000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2, , ,5, ,7,8, , ] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(7000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2, , ,5, ,7,8,9, ] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(9000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2, ,4,5, ,7,8,9, ] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2,3,4,5, ,7,8,9, ] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(5000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2,3,4,5,6,7,8,9, ] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(6000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(9000l)); // initiated [1,2,3,4,5,6,7,8,9,10] // completed [1,2,3,4,5,6,7,8,9,10] // external (-) localCompletionTimeWriter.submitLocalCompletedTime(10000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(9000l)); // initiated [1,2,3,4,5,6,7,8,9,10,11] // completed [1,2,3,4,5,6,7,8,9,10, ] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(11000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(10000l)); } @Test public void shouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithDuplicateTimesWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet(); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithDuplicateTimes(completionTimeService); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithDuplicateTimesWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet(); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithDuplicateTimes(completionTimeService); } finally { completionTimeService.shutdown(); } } public void doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWhenNoPeersWithDuplicateTimes(CompletionTimeService completionTimeService) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); // When/Then // initiated [1] // completed [1] localCompletionTimeWriter.submitLocalInitiatedTime(1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); localCompletionTimeWriter.submitLocalCompletedTime(1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1,2] // completed [1,2] localCompletionTimeWriter.submitLocalInitiatedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); localCompletionTimeWriter.submitLocalCompletedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2,3] // completed [1,2, ] localCompletionTimeWriter.submitLocalInitiatedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3] // completed [1,2, , ] localCompletionTimeWriter.submitLocalInitiatedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3] // completed [1,2, , , ] localCompletionTimeWriter.submitLocalInitiatedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4] // completed [1,2, , , , ] localCompletionTimeWriter.submitLocalInitiatedTime(4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4,5] // completed [1,2, , , , , ] localCompletionTimeWriter.submitLocalInitiatedTime(5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2, , , , , , ] localCompletionTimeWriter.submitLocalInitiatedTime(6000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2, , , , ,5, ] localCompletionTimeWriter.submitLocalCompletedTime(5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2, , ,3, ,5, ] localCompletionTimeWriter.submitLocalCompletedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2, ,3,3, ,5, ] localCompletionTimeWriter.submitLocalCompletedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2,3,3,3, ,5, ] localCompletionTimeWriter.submitLocalCompletedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(3000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2,3,3,3,4,5, ] localCompletionTimeWriter.submitLocalCompletedTime(4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(5000l)); // initiated [1,2,3,3,3,4,5,6] // completed [1,2,3,3,3,4,5,6] localCompletionTimeWriter.submitLocalCompletedTime(6000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(5000l)); } @Test public void shouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWithDuplicateTimesWithSynchronizedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newSynchronizedConcurrentCompletionTimeServiceFromPeerIds(peerIds); // Then try { doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWithDuplicateTimes(completionTimeService, "other"); } finally { completionTimeService.shutdown(); } } @Test public void shouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWithDuplicateTimesWithThreadedImplementation() throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given TimeSource timeSource = new SystemTimeSource(); ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); CompletionTimeServiceAssistant assistant = new CompletionTimeServiceAssistant(); Set<String> peerIds = Sets.newHashSet("other"); CompletionTimeService completionTimeService = assistant.newThreadedQueuedConcurrentCompletionTimeServiceFromPeerIds(timeSource, peerIds, errorReporter); // Then try { doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWithDuplicateTimes(completionTimeService, "other"); } finally { try { completionTimeService.shutdown(); } catch (Throwable e) { // do nothing, exception is expected because test was trying to force an error } } } public void doShouldReturnTimeOfEarliestITThatHasHadNoMatchingCTWithDuplicateTimes(CompletionTimeService completionTimeService, String otherPeerId) throws CompletionTimeException, InterruptedException, ExecutionException, TimeoutException { // Given LocalCompletionTimeWriter localCompletionTimeWriter = completionTimeService.newLocalCompletionTimeWriter(); ExternalCompletionTimeWriter externalCompletionTimeWriter = completionTimeService; // When/Then assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1] // completed [1] // external (-) localCompletionTimeWriter.submitLocalInitiatedTime(1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); localCompletionTimeWriter.submitLocalCompletedTime(1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1] // completed [1] // external (1) externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 1000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1] // completed [1] // external (3) externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(-1l)); // initiated [1,2] // completed [1] // external (3) localCompletionTimeWriter.submitLocalInitiatedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2,3] // completed [1] // external (3) localCompletionTimeWriter.submitLocalInitiatedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2,3,4] // completed [1] // external (3) localCompletionTimeWriter.submitLocalInitiatedTime(4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2,3,4] // completed [1, , ,4] // external (3) localCompletionTimeWriter.submitLocalCompletedTime(4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(1000l)); // initiated [1,2,3,4] // completed [1,2, ,4] // external (3) localCompletionTimeWriter.submitLocalCompletedTime(2000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5] // completed [1,2, ,4, ] // external (3) localCompletionTimeWriter.submitLocalInitiatedTime(5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5] // completed [1,2, ,4, ] // external (4) externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 4000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(2000l)); // initiated [1,2,3,4,5] // completed [1,2,3,4, ] // external (4) localCompletionTimeWriter.submitLocalCompletedTime(3000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(4000l)); // initiated [1,2,3,4,5] // completed [1,2,3,4,5] // external (4) localCompletionTimeWriter.submitLocalCompletedTime(5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(4000l)); // initiated [1,2,3,4,5] // completed [1,2,3,4,5] // external (5) externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 5000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(4000l)); // initiated [1,2,3,4,5,6] // completed [1,2,3,4,5] // external (5) localCompletionTimeWriter.submitLocalInitiatedTime(6000l); assertThat(completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS), is(5000l)); // initiated [1,2,3,4,5,6] // completed [1,2,3,4,5] // external (4) <-- SHOULD NEVER DECREASE boolean exceptionThrown = false; try { externalCompletionTimeWriter.submitPeerCompletionTime(otherPeerId, 4000l); completionTimeService.globalCompletionTimeAsMilliFuture().get(1, TimeUnit.SECONDS); } catch (Throwable e) { exceptionThrown = true; } assertThat(exceptionThrown, is(true)); } }