package com.ldbc.driver.runtime.coordination; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.ldbc.driver.generator.GeneratorFactory; import com.ldbc.driver.generator.RandomDataGeneratorFactory; import com.ldbc.driver.runtime.ConcurrentErrorReporter; import com.ldbc.driver.runtime.scheduling.Spinner; import com.ldbc.driver.temporal.SystemTimeSource; import com.ldbc.driver.temporal.TimeSource; import com.ldbc.driver.util.Tuple; import com.ldbc.driver.util.Tuple2; import org.junit.Test; import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; public class MultiWriterLocalCompletionTimeConcurrentStateManagerTest { /* **************************************************** * **************************************************** * **************************************************** * Tests that are known to work with LocalCompletionTimeStateManager * **************************************************** * **************************************************** * **************************************************** */ @Test public void shouldReturnNullWhenNoEventsHaveBeenInitiatedOrCompletedWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When // no events have been initiated or completed // Then assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenNoOperationsHaveCompletedWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); // Then assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenEarliestInitiatedOperationHasNotCompletedWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); writer.submitLocalCompletedTime(2); writer.submitLocalCompletedTime(3); // Then assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldAdvanceToNextUncompletedEventAsInitiatedEventsAreCompletedWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); writer.submitLocalCompletedTime(3); writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); } @Test public void shouldAdvanceToNextUncompletedEventAsInitiatedEventsAreCompletedButOnlyIfNoUncompletedTimesExistAtSameTimeWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,1,2,3] // CT [] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,1,2, ] // CT [1, , ,3] writer.submitLocalCompletedTime(3); writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ , ,2, ] // CT [1,1, ,3] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , , , ] // CT [1,1,2,3] writer.submitLocalCompletedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); // because we do not know if more Initiated Time == 3 will arrive assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , , ,3] // CT [1,1,2,3, ] writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); // another Initiated Time == 3 arrived assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , , , ] // CT [1,1,2,3,3] writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); // because we do not know if more Initiated Time == 3 will arrive assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , , , ,4] // CT [1,1,2,3,3, ] writer.submitLocalInitiatedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(4l)); assertThat(reader.localCompletionTimeAsMilli(), is(3l)); } @Test public void shouldAllowForSubmittedInitiatedTimeToEqualCurrentCompletionTimeButNotBeLowerWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,2,3] // CT [ , , ] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,2,3] // CT [1, , ] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); //apply initiated time equal to highest submitted initiated time AND equal to LCT <- should be ok // IT [ ,2,3,3] // CT [1, , , ] writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ ,2, ,3] // CT [1, ,3, ] writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ ,2, ,3] // CT [1, ,3, ] boolean exceptionThrown = false; try { writer.submitLocalInitiatedTime(1); } catch (CompletionTimeException e) { exceptionThrown = true; } assertThat(exceptionThrown, is(true)); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); } @Test public void shouldAdvanceToNextUncompletedEventUntilAllInitiatedEventsAreCompletedWhenCompletedTimesComeInOutOfOrder1WithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,2,3,4] // CT [ , , , ] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); writer.submitLocalInitiatedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [1,2, , ] // CT [ , ,3,4] writer.submitLocalCompletedTime(4); writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,2, , ] // CT [1, ,3,4] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , , , ] // CT [1,2,3,4] writer.submitLocalCompletedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(4l)); assertThat(reader.localCompletionTimeAsMilli(), is(3l)); } @Test public void shouldAdvanceToNextUncompletedEventUntilAllInitiatedEventsAreCompletedWhenCompletedTimesComeInOutOfOrder2WithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,2,3,4] // CT [ , , , ] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); writer.submitLocalInitiatedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [1,2, , ] // CT [ , ,3,4] writer.submitLocalCompletedTime(3); writer.submitLocalCompletedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,2, , ] // CT [1, ,3,4] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , , , ] // CT [1,2,3,4] writer.submitLocalCompletedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(4l)); assertThat(reader.localCompletionTimeAsMilli(), is(3l)); } @Test public void shouldAdvanceToNextUncompletedEventUntilAllInitiatedEventsAreCompletedWhenCompletedTimesComeInOutOfOrder3WithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,2,3,4] // CT [ , , , ] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); writer.submitLocalInitiatedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [1,2, , ] // CT [ , ,3,4] writer.submitLocalCompletedTime(4); writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [1, , , ] // CT [ ,2,3,4] writer.submitLocalCompletedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ , , , ] // CT [1,2,3,4] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(4l)); assertThat(reader.localCompletionTimeAsMilli(), is(3l)); } @Test public void shouldReturnLatestInitiatedEventTimeWhenAllEventsHaveCompletedWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,2,3] // CT [ , , ] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ , , ] // CT [1,2,3] writer.submitLocalCompletedTime(1); writer.submitLocalCompletedTime(2); writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); } @Test public void shouldThrowExceptionWhenEventCompletesThatHasNoMatchingInitiatedEntryWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1,2,3] // CT [ , , ] writer.submitLocalInitiatedTime(1); writer.submitLocalInitiatedTime(2); writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,2,3] // CT [1, , ] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); boolean exceptionThrown = false; try { // only one entry with DueTime=1 exists, this should throw exception writer.submitLocalCompletedTime(1); } catch (CompletionTimeException e) { exceptionThrown = true; } assertThat(exceptionThrown, is(true)); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); } @Test public void shouldReturnLatestTimeBehindWhichThereAreNoUncompletedITEventsWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1] // CT [ ] writer.submitLocalInitiatedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ] // CT [1] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,2] // CT [1, ] writer.submitLocalInitiatedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , ] // CT [1,2] writer.submitLocalCompletedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , ,3] // CT [1,2, ] writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4] // CT [1,2, , ] writer.submitLocalInitiatedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4,5] // CT [1,2, , , ] writer.submitLocalInitiatedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4, ] // CT [1,2, , ,5] writer.submitLocalCompletedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4, ,5] // CT [1,2, , ,5, ] writer.submitLocalInitiatedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4, , ] // CT [1,2, , ,5,5] writer.submitLocalCompletedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4, , ,5] // CT [1,2, , ,5,5, ] writer.submitLocalInitiatedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,4, , , ] // CT [1,2, , ,5,5,5] writer.submitLocalCompletedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , ,4, , , ] // CT [1,2,3, ,5,5,5] writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(4l)); assertThat(reader.localCompletionTimeAsMilli(), is(3l)); // IT [ , , , , , , ] // CT [1,2,3,4,5,5,5] writer.submitLocalCompletedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(5l)); assertThat(reader.localCompletionTimeAsMilli(), is(4l)); // IT [ , , , , , , ,6] // CT [1,2,3,4,5,5,5, ] writer.submitLocalInitiatedTime(6); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(6l)); assertThat(reader.localCompletionTimeAsMilli(), is(5l)); } @Test public void shouldReturnTimeOfEarliestITThatHasHadNotMatchingCTEvenWhenMultipleEventsHaveSameInitiatedTimeWithOneWriter() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT [1] // CT [ ] writer.submitLocalInitiatedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ] // CT [1] writer.submitLocalCompletedTime(1); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); // IT [ ,2] // CT [1, ] writer.submitLocalInitiatedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , ] // CT [1,2] writer.submitLocalCompletedTime(2); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); // IT [ , ,3] // CT [1,2, ] writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,3] // CT [1,2, , ] writer.submitLocalInitiatedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , ,3,3,4] // CT [1,2, , , ] writer.submitLocalInitiatedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , ,3,4] // CT [1,2,3, , ] writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , ,3, ] // CT [1,2,3, ,4] writer.submitLocalCompletedTime(4); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(reader.localCompletionTimeAsMilli(), is(2l)); // IT [ , , , , ] // CT [1,2,3,3,4] writer.submitLocalCompletedTime(3); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(4l)); assertThat(reader.localCompletionTimeAsMilli(), is(3l)); // IT [ , , , , ,5] // CT [1,2,3,3,4, ] writer.submitLocalInitiatedTime(5); assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(5l)); assertThat(reader.localCompletionTimeAsMilli(), is(4l)); } /** * ************************************************** * **************************************************** * **************************************************** * Tests with multiple writers, but no concurrency * **************************************************** * **************************************************** * **************************************************** */ @Test public void shouldReturnNullWhenNoWriters() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); // When LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; // Then assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenOneWriterAndNoInitiatedTimesAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); // When LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // Then // IT(1) [] // CT(1) [] assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenMultipleWritersAndNoInitiatedTimesAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); // When LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter3 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // Then // IT(1) [] // CT(1) [] // IT(2) [] // CT(2) [] // IT(3) [] // CT(3) [] assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenOneWriterAndOneInitiatedTimeAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When localCompletionTimeWriter.submitLocalInitiatedTime(1); // Then // IT(1) [] // CT(1) [] assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenOneWriterAndMultipleInitiatedTimeAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT(1) [1,2,3] // CT(1) [ , , ] localCompletionTimeWriter.submitLocalInitiatedTime(1); localCompletionTimeWriter.submitLocalInitiatedTime(2); localCompletionTimeWriter.submitLocalInitiatedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenMultipleWritersAndOneInitiatedTimeAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT(1) [1] // CT(1) [ ] // IT(2) [] // CT(2) [] localCompletionTimeWriter1.submitLocalInitiatedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenMultipleWritersAndMultipleInitiatedTimeAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT(1) [1] // CT(1) [ ] // IT(2) [1] // CT(2) [ ] localCompletionTimeWriter1.submitLocalInitiatedTime(1); localCompletionTimeWriter2.submitLocalInitiatedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenMultipleWritersAndMultipleInitiatedTimesPerWriterAndNoCompletedTimes() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT(1) [1,2,3] // CT(1) [ , , ] // IT(2) [] // CT(2) [] localCompletionTimeWriter1.submitLocalInitiatedTime(1); localCompletionTimeWriter1.submitLocalInitiatedTime(2); localCompletionTimeWriter1.submitLocalInitiatedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [1,2,3] // CT(1) [ , , ] // IT(2) [1,2,3] // CT(2) [ , , ] localCompletionTimeWriter2.submitLocalInitiatedTime(1); localCompletionTimeWriter2.submitLocalInitiatedTime(2); localCompletionTimeWriter2.submitLocalInitiatedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnSubmittedTimeWhenOneWriterAndOneInitiatedTimeAndOneCompletedTime() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When // IT(1) [ ] // CT(1) [1] localCompletionTimeWriter1.submitLocalInitiatedTime(1); localCompletionTimeWriter1.submitLocalCompletedTime(1); // Then assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnNullWhenMultipleWritersAndOneWriterHasInitiatedTimeAndCompletedTimeButOtherHasNeither() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [] localCompletionTimeWriter1.submitLocalInitiatedTime(1); localCompletionTimeWriter1.submitLocalCompletedTime(1); // Then assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnSubmittedTimeWhenMultipleWritersAndOneInitiatedTimeEachAndOneCompletedTimeEach() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [] localCompletionTimeWriter1.submitLocalInitiatedTime(1); localCompletionTimeWriter1.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [1] localCompletionTimeWriter2.submitLocalInitiatedTime(1); localCompletionTimeWriter2.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldReturnMinTimeWhenMultipleWritersAndOneInitiatedTimeEachAndOneCompletedTimeEach() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter localCompletionTimeWriter1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter localCompletionTimeWriter2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When/Then // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [] localCompletionTimeWriter1.submitLocalInitiatedTime(1); localCompletionTimeWriter1.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [2] localCompletionTimeWriter2.submitLocalInitiatedTime(2); localCompletionTimeWriter2.submitLocalCompletedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void shouldPassComplexTwoWriterScenario1() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When / Then // IT(1) [] // CT(1) [] // IT(2) [] // CT(2) [] assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [] writer1.submitLocalInitiatedTime(1); writer1.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ,2] // CT(1) [1, ] // IT(2) [] // CT(2) [] writer1.submitLocalInitiatedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ,2] // CT(1) [1, ] // IT(2) [ , ] // CT(2) [ ,2] writer2.submitLocalInitiatedTime(2); writer2.submitLocalCompletedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ ,2] // CT(1) [1, ] // IT(2) [ , , ] // CT(2) [ ,2,3] writer2.submitLocalInitiatedTime(3); writer2.submitLocalCompletedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ ,2] // CT(1) [1, ] // IT(2) [ , , ,3,3,3] // CT(2) [ ,2,3, , , ] writer2.submitLocalInitiatedTime(3); writer2.submitLocalInitiatedTime(3); writer2.submitLocalInitiatedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ , ] // CT(1) [1,2] // IT(2) [ , , ,3,3,3] // CT(2) [ ,2,3, , , ] writer1.submitLocalCompletedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ , ,3] // CT(1) [1,2, ] // IT(2) [ , , ,3,3,3] // CT(2) [ ,2,3, , , ] writer1.submitLocalInitiatedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3,4] // CT(1) [1,2, , ] // IT(2) [ , , ,3,3,3] // CT(2) [ ,2,3, , , ] writer1.submitLocalInitiatedTime(4); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3,4] // CT(1) [1,2, , ] // IT(2) [ , , , , , ] // CT(2) [ ,2,3,3,3,3] writer2.submitLocalCompletedTime(3); writer2.submitLocalCompletedTime(3); writer2.submitLocalCompletedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3,4] // CT(1) [1,2, , ] // IT(2) [ , , , , , , ] // CT(2) [ ,2,3,3,3,3,4] writer2.submitLocalInitiatedTime(4); writer2.submitLocalCompletedTime(4); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3, ] // CT(1) [1,2, ,4] // IT(2) [ , , , , , , ] // CT(2) [ ,2,3,3,3,3,4] writer1.submitLocalCompletedTime(4); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3, ,5] // CT(1) [1,2, ,4, ] // IT(2) [ , , , , , , ] // CT(2) [ ,2,3,3,3,3,4] writer1.submitLocalInitiatedTime(5); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3, , ] // CT(1) [1,2, ,4,5] // IT(2) [ , , , , , , ] // CT(2) [ ,2,3,3,3,3,4] writer1.submitLocalCompletedTime(5); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,3, , ] // CT(1) [1,2, ,4,5] // IT(2) [ , , , , , , , ] // CT(2) [ ,2,3,3,3,3,4,5] writer2.submitLocalInitiatedTime(5); writer2.submitLocalCompletedTime(5); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , , , , ] // CT(1) [1,2,3,4,5] // IT(2) [ , , , , , , , ] // CT(2) [ ,2,3,3,3,3,4,5] writer1.submitLocalCompletedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(5l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(4l)); // IT(1) [ , , , , ] // CT(1) [1,2,3,4,5] // IT(2) [ , , , , , , , ] // CT(2) [ ,2,3,3,3,3,4,5] boolean exceptionThrown = false; try { writer2.submitLocalInitiatedTime(4); } catch (CompletionTimeException e) { exceptionThrown = true; } assertThat(exceptionThrown, is(true)); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(5l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(4l)); } @Test public void shouldPassComplexTwoWriterScenario2() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When / Then // IT(1) [] // CT(1) [] // IT(2) [] // CT(2) [] assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [] writer1.submitLocalInitiatedTime(1); writer1.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [1] // IT(2) [] // CT(2) [1] writer2.submitLocalInitiatedTime(1); writer2.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [1] // IT(2) [ , ] // CT(2) [1,2] writer2.submitLocalInitiatedTime(2); writer2.submitLocalCompletedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ , ] // CT(1) [1,2] // IT(2) [ , ] // CT(2) [1,2] writer1.submitLocalInitiatedTime(2); writer1.submitLocalCompletedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ , ,10] // CT(1) [1,2, ] // IT(2) [ , ] // CT(2) [1,2] writer1.submitLocalInitiatedTime(10); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ , ,10] // CT(1) [1,2, ] // IT(2) [ , , ] // CT(2) [1,2,3] writer2.submitLocalInitiatedTime(3); writer2.submitLocalCompletedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ , ,10] // CT(1) [1,2, ] // IT(2) [ , , , ] // CT(2) [1,2,3,10] writer2.submitLocalInitiatedTime(10); writer2.submitLocalCompletedTime(10); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(10l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(3l)); } @Test public void shouldPassComplexTwoWriterScenario3() throws CompletionTimeException { // Given MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader localCompletionTimeReader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); // When / Then // IT(1) [] // CT(1) [] // IT(2) [] // CT(2) [] assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [10] // IT(2) [] // CT(2) [] writer1.submitLocalInitiatedTime(10); writer1.submitLocalCompletedTime(10); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [10] // IT(2) [1] // CT(2) [ ] writer2.submitLocalInitiatedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [10] // IT(2) [1,2] // CT(2) [ , ] writer2.submitLocalInitiatedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [10] // IT(2) [1,2,3] // CT(2) [ , ] writer2.submitLocalInitiatedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(1l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(-1l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ ,2,3] // CT(2) [1, , ] writer2.submitLocalCompletedTime(1); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(1l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , ,3] // CT(2) [1,2, ] writer2.submitLocalCompletedTime(2); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , ,3,5] // CT(2) [1,2, , ] writer2.submitLocalInitiatedTime(5); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , ,3,5,9] // CT(2) [1,2, , , ] writer2.submitLocalInitiatedTime(9); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , ,3,5,9,20] // CT(2) [1,2, , , , ] writer2.submitLocalInitiatedTime(20); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(3l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(2l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , , ,5,9,20] // CT(2) [1,2,3, , , ] writer2.submitLocalCompletedTime(3); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(5l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(3l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , , ,5, ,20] // CT(2) [1,2,3, ,9, ] writer2.submitLocalCompletedTime(9); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(5l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(3l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , , , , ,20] // CT(2) [1,2,3,5,9, ] writer2.submitLocalCompletedTime(5); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(10l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(9l)); // IT(1) [ ] // CT(1) [10] // IT(2) [ , , , , , ] // CT(2) [1,2,3,5,9,20] writer2.submitLocalCompletedTime(20); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(10l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(9l)); // IT(1) [ ,11] // CT(1) [10, ] // IT(2) [ , , , , , ] // CT(2) [1,2,3,5,9,20] writer1.submitLocalInitiatedTime(11); assertThat(localCompletionTimeReader.lastKnownLowestInitiatedTimeAsMilli(), is(11l)); assertThat(localCompletionTimeReader.localCompletionTimeAsMilli(), is(10l)); } /* **************************************************** * **************************************************** * **************************************************** * Tests with multiple writers, AND concurrency * **************************************************** * **************************************************** * **************************************************** */ @Test public void concurrentScenario1() throws CompletionTimeException { ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); // IT(1) [ , , , , ,6,7] // CT(1) [1,2,3,4,5, , ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream1 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 3l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 5l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 3l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 5l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 6l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 7l) ); // IT(2) [ , , , , ,100] // CT(2) [2,2,2,2,4, ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream2 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 100l) ); MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriterThread thread1 = new LocalCompletionTimeWriterThread(writer1, writeStream1.iterator(), errorReporter); LocalCompletionTimeWriterThread thread2 = new LocalCompletionTimeWriterThread(writer2, writeStream2.iterator(), errorReporter); thread1.start(); thread2.start(); boolean thread1CompletedOnTime = waitForLocalCompletionTimeWriterThread(1000, thread1); boolean thread2CompletedOnTime = waitForLocalCompletionTimeWriterThread(500, thread2); assertThat(errorReporter.toString(), errorReporter.errorEncountered(), is(false)); // clean up threads if (false == thread1CompletedOnTime || false == thread2CompletedOnTime) { thread1.interrupt(); thread2.interrupt(); } assertThat(thread1CompletedOnTime, is(true)); assertThat(thread2CompletedOnTime, is(true)); // IT(1) [ , , , , ,6,7] // CT(1) [1,2,3,4,5, , ] // IT(2) [ , , , , ,100] // CT(2) [2,2,2,2,4, ] assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(6l)); assertThat(reader.localCompletionTimeAsMilli(), is(5l)); } @Test public void concurrentScenario2() throws CompletionTimeException { ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); // IT(1) [ , , , , ,6,7] // CT(1) [1,2,3,4,5, , ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream1 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 3l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 5l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 3l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 5l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 6l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 7l) ); // IT(2) [ , , , , ,100] // CT(2) [2,2,2,2,4, ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream2 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 4l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 100l) ); // IT(3) [] // CT(3) [] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream3 = Lists.newArrayList( ); MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer3 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriterThread thread1 = new LocalCompletionTimeWriterThread(writer1, writeStream1.iterator(), errorReporter); LocalCompletionTimeWriterThread thread2 = new LocalCompletionTimeWriterThread(writer2, writeStream2.iterator(), errorReporter); LocalCompletionTimeWriterThread thread3 = new LocalCompletionTimeWriterThread(writer3, writeStream3.iterator(), errorReporter); thread1.start(); thread2.start(); thread3.start(); boolean thread1CompletedOnTime = waitForLocalCompletionTimeWriterThread(1000, thread1); boolean thread2CompletedOnTime = waitForLocalCompletionTimeWriterThread(500, thread2); boolean thread3CompletedOnTime = waitForLocalCompletionTimeWriterThread(500, thread3); assertThat(errorReporter.toString(), errorReporter.errorEncountered(), is(false)); // clean up threads if (false == thread1CompletedOnTime || false == thread2CompletedOnTime) { thread1.interrupt(); thread2.interrupt(); thread3.interrupt(); } assertThat(thread1CompletedOnTime, is(true)); assertThat(thread2CompletedOnTime, is(true)); assertThat(thread3CompletedOnTime, is(true)); // IT(1) [ , , , , ,6,7] // CT(1) [1,2,3,4,5, , ] // IT(2) [ , , , , ,100] // CT(2) [2,2,2,2,4, ] // IT(3) [] // CT(3) [] assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(-1l)); assertThat(reader.localCompletionTimeAsMilli(), is(-1l)); } @Test public void concurrentScenario3() throws CompletionTimeException { ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); // IT(1) [ , , , , , , , , , , , , , , , , , , , ,2] // CT(1) [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream1 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l) ); // IT(2) [ , , , , , , , , , , , , , , , , , , , ,2] // CT(2) [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream2 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l) ); // IT(3) [ , , , , , , , , , , , , , , , , , , , ,2] // CT(3) [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ] List<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream3 = Lists.newArrayList( Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l), Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l) ); MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer3 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriterThread thread1 = new LocalCompletionTimeWriterThread(writer1, writeStream1.iterator(), errorReporter); LocalCompletionTimeWriterThread thread2 = new LocalCompletionTimeWriterThread(writer2, writeStream2.iterator(), errorReporter); LocalCompletionTimeWriterThread thread3 = new LocalCompletionTimeWriterThread(writer3, writeStream3.iterator(), errorReporter); thread1.start(); thread2.start(); thread3.start(); boolean thread1CompletedOnTime = waitForLocalCompletionTimeWriterThread(1000, thread1); boolean thread2CompletedOnTime = waitForLocalCompletionTimeWriterThread(500, thread2); boolean thread3CompletedOnTime = waitForLocalCompletionTimeWriterThread(500, thread3); assertThat(errorReporter.toString(), errorReporter.errorEncountered(), is(false)); // clean up threads if (false == thread1CompletedOnTime || false == thread2CompletedOnTime) { thread1.interrupt(); thread2.interrupt(); thread3.interrupt(); } assertThat(thread1CompletedOnTime, is(true)); assertThat(thread2CompletedOnTime, is(true)); assertThat(thread3CompletedOnTime, is(true)); // IT(1) [ , , , , , , , , , , , , , , , , , , , ,2] // CT(1) [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ] // IT(2) [ , , , , , , , , , , , , , , , , , , , ,2] // CT(2) [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ] // IT(3) [ , , , , , , , , , , , , , , , , , , , ,2] // CT(3) [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ] assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(2l)); assertThat(reader.localCompletionTimeAsMilli(), is(1l)); } @Test public void concurrentScenario4() throws CompletionTimeException { ConcurrentErrorReporter errorReporter = new ConcurrentErrorReporter(); GeneratorFactory gf = new GeneratorFactory(new RandomDataGeneratorFactory(42L)); Iterator<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream1 = Iterators.concat( gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 1l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 100l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 100l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 1000l)), 1) ); Iterator<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream2 = Iterators.concat( gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 10l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 10l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 90l)), 1000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 90l)), 1000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 900l)), 1), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 900l)), 1), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 9000l)), 1000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 9000l)), 1000) ); Iterator<Tuple2<LocalCompletionTimeWriterThread.WriteType, Long>> writeStream3 = Iterators.concat( gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 2l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LCT, 2l)), 10000), gf.limit( gf.constant(Tuple.tuple2(LocalCompletionTimeWriterThread.WriteType.WRITE_LIT, 901l)), 1) ); MultiWriterLocalCompletionTimeConcurrentStateManager multiWriterLocalCompletionTimeConcurrentStateManager = new MultiWriterLocalCompletionTimeConcurrentStateManager(); LocalCompletionTimeReader reader = multiWriterLocalCompletionTimeConcurrentStateManager; LocalCompletionTimeWriter writer1 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer2 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriter writer3 = multiWriterLocalCompletionTimeConcurrentStateManager.newLocalCompletionTimeWriter(); LocalCompletionTimeWriterThread thread1 = new LocalCompletionTimeWriterThread(writer1, writeStream1, errorReporter); LocalCompletionTimeWriterThread thread2 = new LocalCompletionTimeWriterThread(writer2, writeStream2, errorReporter); LocalCompletionTimeWriterThread thread3 = new LocalCompletionTimeWriterThread(writer3, writeStream3, errorReporter); thread1.start(); thread2.start(); thread3.start(); boolean thread1CompletedOnTime = waitForLocalCompletionTimeWriterThread(5000, thread1); boolean thread2CompletedOnTime = waitForLocalCompletionTimeWriterThread(5000, thread2); boolean thread3CompletedOnTime = waitForLocalCompletionTimeWriterThread(5000, thread3); assertThat(errorReporter.toString(), errorReporter.errorEncountered(), is(false)); // clean up threads if (false == thread1CompletedOnTime || false == thread2CompletedOnTime) { thread1.interrupt(); thread2.interrupt(); thread3.interrupt(); } assertThat(thread1CompletedOnTime, is(true)); assertThat(thread2CompletedOnTime, is(true)); assertThat(thread3CompletedOnTime, is(true)); // IT(1) [ , ,1000] // CT(1) [1...,100..., ] // IT(2) [ , , , ] // CT(2) [10...,90...,900,9000...] // IT(3) [ ,901] // CT(3) [2..., ] assertThat(reader.lastKnownLowestInitiatedTimeAsMilli(), is(901l)); assertThat(reader.localCompletionTimeAsMilli(), is(900l)); } boolean waitForLocalCompletionTimeWriterThread(long timeoutDurationAsMilli, LocalCompletionTimeWriterThread thread) throws CompletionTimeException { TimeSource timeSource = new SystemTimeSource(); long endTimeAsMilli = timeSource.nowAsMilli() + timeoutDurationAsMilli; while (timeSource.nowAsMilli() < endTimeAsMilli) { if (thread.hasCompletedExecution()) break; Spinner.powerNap(100); } return thread.hasCompletedExecution(); } static class LocalCompletionTimeWriterThread extends Thread { static enum WriteType { WRITE_LIT, WRITE_LCT } private final LocalCompletionTimeWriter writer; private final AtomicBoolean continueExecuting = new AtomicBoolean(true); private final AtomicBoolean hasCompletedExecution = new AtomicBoolean(false); private final Iterator<Tuple2<WriteType, Long>> writeStream; private final ConcurrentErrorReporter errorReporter; LocalCompletionTimeWriterThread(LocalCompletionTimeWriter writer, Iterator<Tuple2<WriteType, Long>> writeStream, ConcurrentErrorReporter errorReporter) { this.writer = writer; this.writeStream = writeStream; this.errorReporter = errorReporter; } void shutdown() { continueExecuting.set(false); } boolean hasCompletedExecution() { return hasCompletedExecution.get(); } @Override public void run() { try { while (continueExecuting.get()) { if (writeStream.hasNext()) { Tuple2<WriteType, Long> write = writeStream.next(); WriteType writeType = write._1(); long writeTimeAsMilli = write._2(); switch (writeType) { case WRITE_LIT: writer.submitLocalInitiatedTime(writeTimeAsMilli); break; case WRITE_LCT: writer.submitLocalCompletedTime(writeTimeAsMilli); break; } } else { break; } } } catch (CompletionTimeException e) { errorReporter.reportError(this, ConcurrentErrorReporter.stackTraceToString(e)); } hasCompletedExecution.set(true); } } }