package net.pterodactylus.sone.core;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.concurrent.atomic.AtomicInteger;
import net.pterodactylus.sone.core.SoneModificationDetector.LockableFingerprintProvider;
import com.google.common.base.Ticker;
import org.junit.Before;
import org.junit.Test;
/**
* Unit test for {@link SoneModificationDetector}.
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
public class SoneModificationDetectorTest {
private final Ticker ticker = mock(Ticker.class);
private final AtomicInteger insertionDelay = new AtomicInteger(60);
private final SoneModificationDetector soneModificationDetector;
private final LockableFingerprintProvider lockableFingerprintProvider = mock(LockableFingerprintProvider.class);
public SoneModificationDetectorTest() {
when(lockableFingerprintProvider.getFingerprint()).thenReturn("original");
when(lockableFingerprintProvider.isLocked()).thenReturn(false);
soneModificationDetector = new SoneModificationDetector(ticker, lockableFingerprintProvider, insertionDelay);
}
private void modifySone() {
modifySone("");
}
private void modifySone(String uniqueValue) {
when(lockableFingerprintProvider.getFingerprint()).thenReturn("modified" + uniqueValue);
}
private void passTime(int seconds) {
when(ticker.read()).thenReturn(SECONDS.toNanos(seconds));
}
private void lockSone() {
when(lockableFingerprintProvider.isLocked()).thenReturn(true);
}
private void unlockSone() {
when(lockableFingerprintProvider.isLocked()).thenReturn(false);
}
@Before
public void setupOriginalFingerprint() {
soneModificationDetector.setFingerprint("original");
}
@Test
public void normalConstructorCanBeCalled() {
new SoneModificationDetector(lockableFingerprintProvider, insertionDelay);
}
@Test
public void sonesStartOutAsNotEligible() {
assertThat(soneModificationDetector.isModified(), is(false));
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
}
@Test
public void originalFingerprintIsRetained() {
assertThat(soneModificationDetector.getLastInsertFingerprint(), is("original"));
}
@Test
public void modifiedSoneIsEligibleAfter60Seconds() {
modifySone();
assertThat(soneModificationDetector.isModified(), is(true));
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(100);
assertThat(soneModificationDetector.isModified(), is(true));
assertThat(soneModificationDetector.isEligibleForInsert(), is(true));
}
@Test
public void modifiedAndRemodifiedSoneIsEligibleAfter90Seconds() {
modifySone();
assertThat(soneModificationDetector.isModified(), is(true));
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(30);
modifySone("2");
assertThat(soneModificationDetector.isModified(), is(true));
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(61);
assertThat(soneModificationDetector.isModified(), is(true));
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(91);
assertThat(soneModificationDetector.isModified(), is(true));
assertThat(soneModificationDetector.isEligibleForInsert(), is(true));
}
@Test
public void modifiedSoneIsNotEligibleAfter30Seconds() {
modifySone();
passTime(30);
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
}
@Test
public void lockedAndModifiedSoneIsNotEligibleAfter60Seconds() {
lockSone();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
modifySone();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(100);
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
}
@Test
public void lockingAndUnlockingASoneRestartsTheWaitPeriod() {
modifySone();
lockSone();
passTime(30);
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
unlockSone();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(60);
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(90);
assertThat(soneModificationDetector.isEligibleForInsert(), is(true));
}
@Test
public void settingFingerprintWillResetTheEligibility() {
modifySone();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(100);
assertThat(soneModificationDetector.isEligibleForInsert(), is(true));
soneModificationDetector.setFingerprint("modified");
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
}
@Test
public void changingInsertionDelayWillInfluenceEligibility() {
modifySone();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(100);
assertThat(soneModificationDetector.isEligibleForInsert(), is(true));
insertionDelay.set(120);
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
}
@Test
public void soneWithoutOriginalFingerprintIsNotEligibleAfter59Seconds() {
SoneModificationDetector soneModificationDetector = createDetectorWithoutOriginalFingerprint();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(59);
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
}
private SoneModificationDetector createDetectorWithoutOriginalFingerprint() {
return new SoneModificationDetector(ticker, new LockableFingerprintProvider() {
@Override
public boolean isLocked() {
return false;
}
@Override
public String getFingerprint() {
return "changed";
}
}, insertionDelay);
}
@Test
public void soneWithoutOriginalFingerprintIsEligibleAfter60Seconds() {
SoneModificationDetector soneModificationDetector = createDetectorWithoutOriginalFingerprint();
assertThat(soneModificationDetector.isEligibleForInsert(), is(false));
passTime(60);
assertThat(soneModificationDetector.isEligibleForInsert(), is(true));
}
}