Anticipate { public static long next(long now, final long last, final long period, final long grace) { final long since = now - last; if (since <= (grace * 2)) { return last + period - grace; } final long modulus = (last - now) % period; long nextMin; if (modulus < -grace) { nextMin = (now + modulus) + period - grace; } else { nextMin = (now + modulus); } while (nextMin <= now) { nextMin += grace; } return nextMin; }  static long next(long now, final long last, final long period, final long grace);  }
@Test public void next_simpleMode() { long now = 10_000; int period = 1_000; long last = now - 1_000; int grace = 5; long next = Anticipate.next(now, last, period, grace); assertThat(next).isEqualTo(now + 5); }
@Test public void next_lateCall() { long now = 10_000; long last = now - 5_000; int period = 1_000; int grace = 5; long next = Anticipate.next(now, last, period, grace); assertThat(next).isEqualTo(now + 5); }
@Test public void next_waitPeriod() { long now = 10_000; long last = now - 5; int period = 1_000; int grace = 5; long next = Anticipate.next(now, last, period, grace); assertThat(next).isEqualTo(last + period - grace); }
@Test public void next_waitPeriod2() { long now = 10_000; long last = now - 15; int period = 1_000; int grace = 5; long next = Anticipate.next(now, last, period, grace); assertThat(next).isEqualTo(last + period - grace); }
@Test public void next_betweenGraceAndAPeriodSinceLastReading() { long now = 10_000; long period = 1_000; int grace = 5; int testCount = 0; for (long last = now - 3 * grace; last >= now - period; last -= grace) { long next = Anticipate.next(now, last, period, grace); assertWithMessage("last: " + last) .that(next) .isEqualTo(Math.max(last + period - grace, now + grace)); testCount++; } assertThat(testCount).isEqualTo(198); }
@Test public void next_moreThanTwoPeriodsSinceLastReading() { long now = 10_000; long period = 1_000; long grace = 5; int testCount = 0; for (long last = now - 3 * grace; last >= now - 5 * period; last -= (grace * 3)) { long next = Anticipate.next(now, last, period, grace); assertWithMessage("last: " + last + " next is at least") .that(next) .isAtLeast(now + grace); assertWithMessage("last: " + last + " next is at most") .that(next) .isAtMost(now + period); long restOfWholePeriod = Math.abs((next - last) % period); if (restOfWholePeriod > period / 2) { restOfWholePeriod -= period; } assertWithMessage("last: " + last + " is around modulus grace") .that(restOfWholePeriod) .isAtMost(2 * grace); testCount++; } assertThat(testCount).isEqualTo(333); }
@Test public void next_realWorld1() { long now = 1_561_893_529_622L; long last = 1_561_893_209_000L; long period = 300_000L; long grace = 10_000; long next = Anticipate.next(now, last, period, grace); assertThat(next).isEqualTo(1_561_893_799_000L); }