Merge "Fix OperationScheduler moratorium calculation for clock rollback case." into froyo
This commit is contained in:
@@ -124,7 +124,8 @@ public class OperationScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the time of the next operation. Does not modify any state.
|
* Compute the time of the next operation. Does not modify any state
|
||||||
|
* (unless the clock rolls backwards, in which case timers are reset).
|
||||||
*
|
*
|
||||||
* @param options to use for this computation.
|
* @param options to use for this computation.
|
||||||
* @return the wall clock time ({@link System#currentTimeMillis()}) when the
|
* @return the wall clock time ({@link System#currentTimeMillis()}) when the
|
||||||
@@ -143,11 +144,11 @@ public class OperationScheduler {
|
|||||||
// clipped to the current time so we don't languish forever.
|
// clipped to the current time so we don't languish forever.
|
||||||
|
|
||||||
int errorCount = mStorage.getInt(PREFIX + "errorCount", 0);
|
int errorCount = mStorage.getInt(PREFIX + "errorCount", 0);
|
||||||
long now = System.currentTimeMillis();
|
long now = currentTimeMillis();
|
||||||
long lastSuccessTimeMillis = getTimeBefore(PREFIX + "lastSuccessTimeMillis", now);
|
long lastSuccessTimeMillis = getTimeBefore(PREFIX + "lastSuccessTimeMillis", now);
|
||||||
long lastErrorTimeMillis = getTimeBefore(PREFIX + "lastErrorTimeMillis", now);
|
long lastErrorTimeMillis = getTimeBefore(PREFIX + "lastErrorTimeMillis", now);
|
||||||
long triggerTimeMillis = mStorage.getLong(PREFIX + "triggerTimeMillis", Long.MAX_VALUE);
|
long triggerTimeMillis = mStorage.getLong(PREFIX + "triggerTimeMillis", Long.MAX_VALUE);
|
||||||
long moratoriumSetMillis = mStorage.getLong(PREFIX + "moratoriumSetTimeMillis", 0);
|
long moratoriumSetMillis = getTimeBefore(PREFIX + "moratoriumSetTimeMillis", now);
|
||||||
long moratoriumTimeMillis = getTimeBefore(PREFIX + "moratoriumTimeMillis",
|
long moratoriumTimeMillis = getTimeBefore(PREFIX + "moratoriumTimeMillis",
|
||||||
moratoriumSetMillis + options.maxMoratoriumMillis);
|
moratoriumSetMillis + options.maxMoratoriumMillis);
|
||||||
|
|
||||||
@@ -155,9 +156,8 @@ public class OperationScheduler {
|
|||||||
if (options.periodicIntervalMillis > 0) {
|
if (options.periodicIntervalMillis > 0) {
|
||||||
time = Math.min(time, lastSuccessTimeMillis + options.periodicIntervalMillis);
|
time = Math.min(time, lastSuccessTimeMillis + options.periodicIntervalMillis);
|
||||||
}
|
}
|
||||||
if (time >= moratoriumTimeMillis - options.maxMoratoriumMillis) {
|
|
||||||
time = Math.max(time, moratoriumTimeMillis);
|
time = Math.max(time, moratoriumTimeMillis);
|
||||||
}
|
|
||||||
time = Math.max(time, lastSuccessTimeMillis + options.minTriggerMillis);
|
time = Math.max(time, lastSuccessTimeMillis + options.minTriggerMillis);
|
||||||
if (errorCount > 0) {
|
if (errorCount > 0) {
|
||||||
time = Math.max(time, lastErrorTimeMillis + options.backoffFixedMillis +
|
time = Math.max(time, lastErrorTimeMillis + options.backoffFixedMillis +
|
||||||
@@ -205,7 +205,7 @@ public class OperationScheduler {
|
|||||||
/**
|
/**
|
||||||
* Request an operation to be performed at a certain time. The actual
|
* Request an operation to be performed at a certain time. The actual
|
||||||
* scheduled time may be affected by error backoff logic and defined
|
* scheduled time may be affected by error backoff logic and defined
|
||||||
* minimum intervals.
|
* minimum intervals. Use {@link Long#MAX_VALUE} to disable triggering.
|
||||||
*
|
*
|
||||||
* @param millis wall clock time ({@link System#currentTimeMillis()}) to
|
* @param millis wall clock time ({@link System#currentTimeMillis()}) to
|
||||||
* trigger another operation; 0 to trigger immediately
|
* trigger another operation; 0 to trigger immediately
|
||||||
@@ -218,13 +218,13 @@ public class OperationScheduler {
|
|||||||
* Forbid any operations until after a certain (absolute) time.
|
* Forbid any operations until after a certain (absolute) time.
|
||||||
* Limited by {@link #Options.maxMoratoriumMillis}.
|
* Limited by {@link #Options.maxMoratoriumMillis}.
|
||||||
*
|
*
|
||||||
* @param millis wall clock time ({@link System#currentTimeMillis()}) to
|
* @param millis wall clock time ({@link System#currentTimeMillis()})
|
||||||
* wait before attempting any more operations; 0 to remove moratorium
|
* when operations should be allowed again; 0 to remove moratorium
|
||||||
*/
|
*/
|
||||||
public void setMoratoriumTimeMillis(long millis) {
|
public void setMoratoriumTimeMillis(long millis) {
|
||||||
mStorage.edit()
|
mStorage.edit()
|
||||||
.putLong(PREFIX + "moratoriumTimeMillis", millis)
|
.putLong(PREFIX + "moratoriumTimeMillis", millis)
|
||||||
.putLong(PREFIX + "moratoriumSetTimeMillis", System.currentTimeMillis())
|
.putLong(PREFIX + "moratoriumSetTimeMillis", currentTimeMillis())
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ public class OperationScheduler {
|
|||||||
public boolean setMoratoriumTimeHttp(String retryAfter) {
|
public boolean setMoratoriumTimeHttp(String retryAfter) {
|
||||||
try {
|
try {
|
||||||
long ms = Long.valueOf(retryAfter) * 1000;
|
long ms = Long.valueOf(retryAfter) * 1000;
|
||||||
setMoratoriumTimeMillis(ms + System.currentTimeMillis());
|
setMoratoriumTimeMillis(ms + currentTimeMillis());
|
||||||
return true;
|
return true;
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
try {
|
try {
|
||||||
@@ -269,13 +269,12 @@ public class OperationScheduler {
|
|||||||
public void onSuccess() {
|
public void onSuccess() {
|
||||||
resetTransientError();
|
resetTransientError();
|
||||||
resetPermanentError();
|
resetPermanentError();
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
mStorage.edit()
|
mStorage.edit()
|
||||||
.remove(PREFIX + "errorCount")
|
.remove(PREFIX + "errorCount")
|
||||||
.remove(PREFIX + "lastErrorTimeMillis")
|
.remove(PREFIX + "lastErrorTimeMillis")
|
||||||
.remove(PREFIX + "permanentError")
|
.remove(PREFIX + "permanentError")
|
||||||
.remove(PREFIX + "triggerTimeMillis")
|
.remove(PREFIX + "triggerTimeMillis")
|
||||||
.putLong(PREFIX + "lastSuccessTimeMillis", now).commit();
|
.putLong(PREFIX + "lastSuccessTimeMillis", currentTimeMillis()).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,8 +283,7 @@ public class OperationScheduler {
|
|||||||
* purposes.
|
* purposes.
|
||||||
*/
|
*/
|
||||||
public void onTransientError() {
|
public void onTransientError() {
|
||||||
long now = System.currentTimeMillis();
|
mStorage.edit().putLong(PREFIX + "lastErrorTimeMillis", currentTimeMillis()).commit();
|
||||||
mStorage.edit().putLong(PREFIX + "lastErrorTimeMillis", now).commit();
|
|
||||||
mStorage.edit().putInt(PREFIX + "errorCount",
|
mStorage.edit().putInt(PREFIX + "errorCount",
|
||||||
mStorage.getInt(PREFIX + "errorCount", 0) + 1).commit();
|
mStorage.getInt(PREFIX + "errorCount", 0) + 1).commit();
|
||||||
}
|
}
|
||||||
@@ -338,4 +336,13 @@ public class OperationScheduler {
|
|||||||
}
|
}
|
||||||
return out.append("]").toString();
|
return out.append("]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current time. Can be overridden for unit testing.
|
||||||
|
*
|
||||||
|
* @return {@link System#currentTimeMillis()}
|
||||||
|
*/
|
||||||
|
protected long currentTimeMillis() {
|
||||||
|
return System.currentTimeMillis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,19 +22,34 @@ import android.test.suitebuilder.annotation.MediumTest;
|
|||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
|
||||||
public class OperationSchedulerTest extends AndroidTestCase {
|
public class OperationSchedulerTest extends AndroidTestCase {
|
||||||
|
/**
|
||||||
|
* OperationScheduler subclass which uses an artificial time.
|
||||||
|
* Set {@link #timeMillis} to whatever value you like.
|
||||||
|
*/
|
||||||
|
private class TimeTravelScheduler extends OperationScheduler {
|
||||||
|
static final long DEFAULT_TIME = 1250146800000L; // 13-Aug-2009, 12:00:00 am
|
||||||
|
public long timeMillis = DEFAULT_TIME;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long currentTimeMillis() { return timeMillis; }
|
||||||
|
public TimeTravelScheduler() { super(getFreshStorage()); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private SharedPreferences getFreshStorage() {
|
||||||
|
SharedPreferences sp = getContext().getSharedPreferences("OperationSchedulerTest", 0);
|
||||||
|
sp.edit().clear().commit();
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
@MediumTest
|
@MediumTest
|
||||||
public void testScheduler() throws Exception {
|
public void testScheduler() throws Exception {
|
||||||
String name = "OperationSchedulerTest.testScheduler";
|
TimeTravelScheduler scheduler = new TimeTravelScheduler();
|
||||||
SharedPreferences storage = getContext().getSharedPreferences(name, 0);
|
|
||||||
storage.edit().clear().commit();
|
|
||||||
|
|
||||||
OperationScheduler scheduler = new OperationScheduler(storage);
|
|
||||||
OperationScheduler.Options options = new OperationScheduler.Options();
|
OperationScheduler.Options options = new OperationScheduler.Options();
|
||||||
assertEquals(Long.MAX_VALUE, scheduler.getNextTimeMillis(options));
|
assertEquals(Long.MAX_VALUE, scheduler.getNextTimeMillis(options));
|
||||||
assertEquals(0, scheduler.getLastSuccessTimeMillis());
|
assertEquals(0, scheduler.getLastSuccessTimeMillis());
|
||||||
assertEquals(0, scheduler.getLastAttemptTimeMillis());
|
assertEquals(0, scheduler.getLastAttemptTimeMillis());
|
||||||
|
|
||||||
long beforeTrigger = System.currentTimeMillis();
|
long beforeTrigger = scheduler.timeMillis;
|
||||||
scheduler.setTriggerTimeMillis(beforeTrigger + 1000000);
|
scheduler.setTriggerTimeMillis(beforeTrigger + 1000000);
|
||||||
assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
@@ -51,33 +66,26 @@ public class OperationSchedulerTest extends AndroidTestCase {
|
|||||||
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
// Backoff interval after an error
|
// Backoff interval after an error
|
||||||
long beforeError = System.currentTimeMillis();
|
long beforeError = (scheduler.timeMillis += 100);
|
||||||
scheduler.onTransientError();
|
scheduler.onTransientError();
|
||||||
long afterError = System.currentTimeMillis();
|
|
||||||
assertEquals(0, scheduler.getLastSuccessTimeMillis());
|
assertEquals(0, scheduler.getLastSuccessTimeMillis());
|
||||||
assertTrue(beforeError <= scheduler.getLastAttemptTimeMillis());
|
assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
|
||||||
assertTrue(afterError >= scheduler.getLastAttemptTimeMillis());
|
|
||||||
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
||||||
options.backoffFixedMillis = 1000000;
|
options.backoffFixedMillis = 1000000;
|
||||||
options.backoffIncrementalMillis = 500000;
|
options.backoffIncrementalMillis = 500000;
|
||||||
assertTrue(beforeError + 1500000 <= scheduler.getNextTimeMillis(options));
|
assertEquals(beforeError + 1500000, scheduler.getNextTimeMillis(options));
|
||||||
assertTrue(afterError + 1500000 >= scheduler.getNextTimeMillis(options));
|
|
||||||
|
|
||||||
// Two errors: backoff interval increases
|
// Two errors: backoff interval increases
|
||||||
beforeError = System.currentTimeMillis();
|
beforeError = (scheduler.timeMillis += 100);
|
||||||
scheduler.onTransientError();
|
scheduler.onTransientError();
|
||||||
afterError = System.currentTimeMillis();
|
assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
|
||||||
assertTrue(beforeError <= scheduler.getLastAttemptTimeMillis());
|
assertEquals(beforeError + 2000000, scheduler.getNextTimeMillis(options));
|
||||||
assertTrue(afterError >= scheduler.getLastAttemptTimeMillis());
|
|
||||||
assertTrue(beforeError + 2000000 <= scheduler.getNextTimeMillis(options));
|
|
||||||
assertTrue(afterError + 2000000 >= scheduler.getNextTimeMillis(options));
|
|
||||||
|
|
||||||
// Reset transient error: no backoff interval
|
// Reset transient error: no backoff interval
|
||||||
scheduler.resetTransientError();
|
scheduler.resetTransientError();
|
||||||
assertEquals(0, scheduler.getLastSuccessTimeMillis());
|
assertEquals(0, scheduler.getLastSuccessTimeMillis());
|
||||||
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
||||||
assertTrue(beforeError <= scheduler.getLastAttemptTimeMillis());
|
assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
|
||||||
assertTrue(afterError >= scheduler.getLastAttemptTimeMillis());
|
|
||||||
|
|
||||||
// Permanent error holds true even if transient errors are reset
|
// Permanent error holds true even if transient errors are reset
|
||||||
// However, we remember that the transient error was reset...
|
// However, we remember that the transient error was reset...
|
||||||
@@ -89,30 +97,26 @@ public class OperationSchedulerTest extends AndroidTestCase {
|
|||||||
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
// Success resets the trigger
|
// Success resets the trigger
|
||||||
long beforeSuccess = System.currentTimeMillis();
|
long beforeSuccess = (scheduler.timeMillis += 100);
|
||||||
scheduler.onSuccess();
|
scheduler.onSuccess();
|
||||||
long afterSuccess = System.currentTimeMillis();
|
assertEquals(beforeSuccess, scheduler.getLastAttemptTimeMillis());
|
||||||
assertTrue(beforeSuccess <= scheduler.getLastAttemptTimeMillis());
|
assertEquals(beforeSuccess, scheduler.getLastSuccessTimeMillis());
|
||||||
assertTrue(afterSuccess >= scheduler.getLastAttemptTimeMillis());
|
|
||||||
assertTrue(beforeSuccess <= scheduler.getLastSuccessTimeMillis());
|
|
||||||
assertTrue(afterSuccess >= scheduler.getLastSuccessTimeMillis());
|
|
||||||
assertEquals(Long.MAX_VALUE, scheduler.getNextTimeMillis(options));
|
assertEquals(Long.MAX_VALUE, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
// The moratorium is not reset by success!
|
// The moratorium is not reset by success!
|
||||||
scheduler.setTriggerTimeMillis(beforeSuccess + 500000);
|
scheduler.setTriggerTimeMillis(0);
|
||||||
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
|
||||||
scheduler.setMoratoriumTimeMillis(0);
|
scheduler.setMoratoriumTimeMillis(0);
|
||||||
assertEquals(beforeSuccess + 500000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeSuccess, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
// Periodic interval after success
|
// Periodic interval after success
|
||||||
options.periodicIntervalMillis = 250000;
|
options.periodicIntervalMillis = 250000;
|
||||||
assertTrue(beforeSuccess + 250000 <= scheduler.getNextTimeMillis(options));
|
scheduler.setTriggerTimeMillis(Long.MAX_VALUE);
|
||||||
assertTrue(afterSuccess + 250000 >= scheduler.getNextTimeMillis(options));
|
assertEquals(beforeSuccess + 250000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
// Trigger minimum is also since the last success
|
// Trigger minimum is also since the last success
|
||||||
options.minTriggerMillis = 1000000;
|
options.minTriggerMillis = 1000000;
|
||||||
assertTrue(beforeSuccess + 1000000 <= scheduler.getNextTimeMillis(options));
|
assertEquals(beforeSuccess + 1000000, scheduler.getNextTimeMillis(options));
|
||||||
assertTrue(afterSuccess + 1000000 >= scheduler.getNextTimeMillis(options));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -138,23 +142,19 @@ public class OperationSchedulerTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testMoratoriumWithHttpDate() throws Exception {
|
public void testMoratoriumWithHttpDate() throws Exception {
|
||||||
String name = "OperationSchedulerTest.testMoratoriumWithHttpDate";
|
TimeTravelScheduler scheduler = new TimeTravelScheduler();
|
||||||
SharedPreferences storage = getContext().getSharedPreferences(name, 0);
|
|
||||||
storage.edit().clear().commit();
|
|
||||||
|
|
||||||
OperationScheduler scheduler = new OperationScheduler(storage);
|
|
||||||
OperationScheduler.Options options = new OperationScheduler.Options();
|
OperationScheduler.Options options = new OperationScheduler.Options();
|
||||||
|
|
||||||
long beforeTrigger = System.currentTimeMillis();
|
long beforeTrigger = scheduler.timeMillis;
|
||||||
scheduler.setTriggerTimeMillis(beforeTrigger + 1000000);
|
scheduler.setTriggerTimeMillis(beforeTrigger + 1000000);
|
||||||
assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
scheduler.setMoratoriumTimeMillis(beforeTrigger + 2000000);
|
scheduler.setMoratoriumTimeMillis(beforeTrigger + 2000000);
|
||||||
assertEquals(beforeTrigger + 2000000, scheduler.getNextTimeMillis(options));
|
assertEquals(beforeTrigger + 2000000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
long beforeMoratorium = System.currentTimeMillis();
|
long beforeMoratorium = scheduler.timeMillis;
|
||||||
assertTrue(scheduler.setMoratoriumTimeHttp("3000"));
|
assertTrue(scheduler.setMoratoriumTimeHttp("3000"));
|
||||||
long afterMoratorium = System.currentTimeMillis();
|
long afterMoratorium = scheduler.timeMillis;
|
||||||
assertTrue(beforeMoratorium + 3000000 <= scheduler.getNextTimeMillis(options));
|
assertTrue(beforeMoratorium + 3000000 <= scheduler.getNextTimeMillis(options));
|
||||||
assertTrue(afterMoratorium + 3000000 >= scheduler.getNextTimeMillis(options));
|
assertTrue(afterMoratorium + 3000000 >= scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
@@ -164,4 +164,56 @@ public class OperationSchedulerTest extends AndroidTestCase {
|
|||||||
|
|
||||||
assertFalse(scheduler.setMoratoriumTimeHttp("not actually a date"));
|
assertFalse(scheduler.setMoratoriumTimeHttp("not actually a date"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public void testClockRollbackScenario() throws Exception {
|
||||||
|
TimeTravelScheduler scheduler = new TimeTravelScheduler();
|
||||||
|
OperationScheduler.Options options = new OperationScheduler.Options();
|
||||||
|
options.minTriggerMillis = 2000;
|
||||||
|
|
||||||
|
// First, set up a scheduler with reasons to wait: a transient
|
||||||
|
// error with backoff and a moratorium for a few minutes.
|
||||||
|
|
||||||
|
long beforeTrigger = scheduler.timeMillis;
|
||||||
|
long triggerTime = beforeTrigger - 10000000;
|
||||||
|
scheduler.setTriggerTimeMillis(triggerTime);
|
||||||
|
assertEquals(triggerTime, scheduler.getNextTimeMillis(options));
|
||||||
|
assertEquals(0, scheduler.getLastAttemptTimeMillis());
|
||||||
|
|
||||||
|
long beforeSuccess = (scheduler.timeMillis += 100);
|
||||||
|
scheduler.onSuccess();
|
||||||
|
scheduler.setTriggerTimeMillis(triggerTime);
|
||||||
|
assertEquals(beforeSuccess, scheduler.getLastAttemptTimeMillis());
|
||||||
|
assertEquals(beforeSuccess + 2000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
|
long beforeError = (scheduler.timeMillis += 100);
|
||||||
|
scheduler.onTransientError();
|
||||||
|
assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
|
||||||
|
assertEquals(beforeError + 5000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
|
long beforeMoratorium = (scheduler.timeMillis += 100);
|
||||||
|
scheduler.setMoratoriumTimeMillis(beforeTrigger + 1000000);
|
||||||
|
assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
|
// Now set the time back a few seconds.
|
||||||
|
// The moratorium time should still be honored.
|
||||||
|
long beforeRollback = (scheduler.timeMillis = beforeTrigger - 10000);
|
||||||
|
assertEquals(beforeTrigger + 1000000, scheduler.getNextTimeMillis(options));
|
||||||
|
|
||||||
|
// The rollback also moved the last-attempt clock back to the rollback time.
|
||||||
|
assertEquals(scheduler.timeMillis, scheduler.getLastAttemptTimeMillis());
|
||||||
|
|
||||||
|
// But if we set the time back more than a day, the moratorium
|
||||||
|
// resets to the maximum moratorium (a day, by default), exposing
|
||||||
|
// the original trigger time.
|
||||||
|
beforeRollback = (scheduler.timeMillis = beforeTrigger - 100000000);
|
||||||
|
assertEquals(triggerTime, scheduler.getNextTimeMillis(options));
|
||||||
|
assertEquals(beforeRollback, scheduler.getLastAttemptTimeMillis());
|
||||||
|
|
||||||
|
// If we roll forward until after the re-set moratorium, then it expires.
|
||||||
|
scheduler.timeMillis = triggerTime + 5000000;
|
||||||
|
assertEquals(triggerTime, scheduler.getNextTimeMillis(options));
|
||||||
|
assertEquals(beforeRollback, scheduler.getLastAttemptTimeMillis());
|
||||||
|
assertEquals(beforeRollback, scheduler.getLastSuccessTimeMillis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user