package com.ldbc.driver.runtime.coordination;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class LocalCompletionTimeTest {
@Test
public void shouldReturnNullWhenNoEventsHaveBeenInitiatedOrCompleted() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When / Then
// no events have been initiated or completed
// IT []
// CT []
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(-1l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
}
@Test
public void shouldReturnNullWhenNoOperationsHaveCompleted() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When / Then
// IT [1,2,3]
// CT [ , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
}
@Test
public void shouldReturnNullWhenEarliestInitiatedOperationHasNotCompleted() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When / Then
// IT [1,2,3]
// CT [ , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [1, , ]
// CT [ ,2,3]
lct.submitLocalCompletedTime(2000l);
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
}
@Test
public void shouldAdvanceToNextUncompletedEventAsInitiatedEventsAreCompleted() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When / Then
// IT [1,2,3]
// CT [ , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2, ]
// CT [1, ,3]
lct.submitLocalCompletedTime(3000l);
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
}
@Test
public void shouldAdvanceToNextUncompletedEventAsInitiatedEventsAreCompletedButOnlyIfNoUncompletedTimesExistAtSameTime() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,1,2,3]
// CT [ , , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,1,2, ]
// CT [1, , ,3]
lct.submitLocalCompletedTime(3000l);
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ , ,2, ]
// CT [1,1, ,3]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , , , ]
// CT [1,1,2,3]
lct.submitLocalCompletedTime(2000l);
// because we do not know if more Initiated Time == 3 will arrive
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , , ,3]
// CT [1,1,2,3, ]
lct.submitLocalInitiatedTime(3000l);
// another Initiated Time == 3 arrived
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , , , ]
// CT [1,1,2,3,3]
lct.submitLocalCompletedTime(3000l);
// because we do not know if more Initiated Time == 3 will arrive
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , , , ,4]
// CT [1,1,2,3,3, ]
lct.submitLocalInitiatedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(4000l));
assertThat(lct.localCompletionTimeAsMilli(), is(3000l));
}
@Test
public void shouldAllowForSubmittedInitiatedTimeToEqualCurrentCompletionTimeButNotBeLower() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,2,3]
// CT [ , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2,3]
// CT [1, , ]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
//apply initiated time equal to highest submitted initiated time AND equal to GCT <- should be ok
// IT [ ,2,3,3]
// CT [1, , , ]
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ ,2, ,3]
// CT [1, ,3, ]
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ ,2, ,3]
// CT [1, ,3, ]
boolean exceptionThrown = false;
try {
lct.submitLocalInitiatedTime(1000l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
assertThat(exceptionThrown, is(true));
}
@Test
public void shouldAdvanceToNextUncompletedEventUntilAllInitiatedEventsAreCompletedWhenCompletedTimesComeInOutOfOrder1() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,2,3,4]
// CT [ , , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
lct.submitLocalInitiatedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [1,2, , ]
// CT [ , ,3,4]
lct.submitLocalCompletedTime(4000l);
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2, , ]
// CT [1, ,3,4]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , , , ]
// CT [1,2,3,4]
lct.submitLocalCompletedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(4000l));
assertThat(lct.localCompletionTimeAsMilli(), is(3000l));
}
@Test
public void shouldAdvanceToNextUncompletedEventUntilAllInitiatedEventsAreCompletedWhenCompletedTimesComeInOutOfOrder2() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,2,3,4]
// CT [ , , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
lct.submitLocalInitiatedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [1,2, , ]
// CT [ , ,3,4]
lct.submitLocalCompletedTime(3000l);
lct.submitLocalCompletedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2, , ]
// CT [1, ,3,4]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , , , ]
// CT [1,2,3,4]
lct.submitLocalCompletedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(4000l));
assertThat(lct.localCompletionTimeAsMilli(), is(3000l));
}
@Test
public void shouldAdvanceToNextUncompletedEventUntilAllInitiatedEventsAreCompletedWhenCompletedTimesComeInOutOfOrder3() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,2,3,4]
// CT [ , , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
lct.submitLocalInitiatedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [1,2, , ]
// CT [ , ,3,4]
lct.submitLocalCompletedTime(4000l);
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [1, , , ]
// CT [ ,2,3,4]
lct.submitLocalCompletedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ , , , ]
// CT [1,2,3,4]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(4000l));
assertThat(lct.localCompletionTimeAsMilli(), is(3000l));
}
@Test
public void shouldReturnLatestInitiatedEventTimeWhenAllEventsHaveCompleted() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,2,3]
// CT [ , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ , , ]
// CT [1,2,3]
lct.submitLocalCompletedTime(1000l);
lct.submitLocalCompletedTime(2000l);
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
}
@Test
public void shouldThrowExceptionWhenEventCompletesThatHasNoMatchingInitiatedEntry() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1,2,3]
// CT [ , , ]
lct.submitLocalInitiatedTime(1000l);
lct.submitLocalInitiatedTime(2000l);
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2,3]
// CT [1, , ]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
boolean exceptionThrown = false;
try {
// only one entry with DueTime=1 exists, this should throw exception
lct.submitLocalCompletedTime(1000l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
}
@Test
public void shouldReturnLatestTimeBehindWhichThereAreNoUncompletedITEvents() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1]
// CT []
lct.submitLocalInitiatedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ]
// CT [1]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2]
// CT [1, ]
lct.submitLocalInitiatedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , ]
// CT [1,2]
lct.submitLocalCompletedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , ,3]
// CT [1,2, ]
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4]
// CT [1,2, , ]
lct.submitLocalInitiatedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4,5]
// CT [1,2, , , ]
lct.submitLocalInitiatedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4, ]
// CT [1,2, , ,5]
lct.submitLocalCompletedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4, ,5]
// CT [1,2, , ,5, ]
lct.submitLocalInitiatedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4, , ]
// CT [1,2, , ,5,5]
lct.submitLocalCompletedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4, , ,5]
// CT [1,2, , ,5,5, ]
lct.submitLocalInitiatedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,4, , , ]
// CT [1,2, , ,5,5,5]
lct.submitLocalCompletedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , ,4, , , ]
// CT [1,2,3, ,5,5,5]
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(4000l));
assertThat(lct.localCompletionTimeAsMilli(), is(3000l));
// IT [ , , , , , , ]
// CT [1,2,3,4,5,5,5]
lct.submitLocalCompletedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(5000l));
assertThat(lct.localCompletionTimeAsMilli(), is(4000l));
// IT [ , , , , , , ,6]
// CT [1,2,3,4,5,5,5, ]
lct.submitLocalInitiatedTime(6000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(6000l));
assertThat(lct.localCompletionTimeAsMilli(), is(5000l));
}
@Test
public void shouldReturnTimeOfEarliestITThatHasHadNotMatchingCTEvenWhenMultipleEventsHaveSameInitiatedTime() throws CompletionTimeException {
// Given
LocalCompletionTimeStateManager lct = new LocalCompletionTimeStateManager();
// When/Then
// IT [1]
// CT [ ]
lct.submitLocalInitiatedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ]
// CT [1]
lct.submitLocalCompletedTime(1000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(1000l));
assertThat(lct.localCompletionTimeAsMilli(), is(-1l));
// IT [ ,2]
// CT [1, ]
lct.submitLocalInitiatedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , ]
// CT [1,2]
lct.submitLocalCompletedTime(2000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(2000l));
assertThat(lct.localCompletionTimeAsMilli(), is(1000l));
// IT [ , ,3]
// CT [1,2, ]
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,3]
// CT [1,2, , ]
lct.submitLocalInitiatedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , ,3,3,4]
// CT [1,2, , , ]
lct.submitLocalInitiatedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , ,3,4]
// CT [1,2,3, , ]
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , ,3, ]
// CT [1,2,3, ,4]
lct.submitLocalCompletedTime(4000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(3000l));
assertThat(lct.localCompletionTimeAsMilli(), is(2000l));
// IT [ , , , , ]
// CT [1,2,3,3,4]
lct.submitLocalCompletedTime(3000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(4000l));
assertThat(lct.localCompletionTimeAsMilli(), is(3000l));
// IT [ , , , , ,5]
// CT [1,2,3,3,4, ]
lct.submitLocalInitiatedTime(5000l);
assertThat(lct.lastKnownLowestInitiatedTimeAsMilli(), is(5000l));
assertThat(lct.localCompletionTimeAsMilli(), is(4000l));
}
}