/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.verification;
import org.mockito.exceptions.base.
MockitoAssertionError;
import org.mockito.internal.util.
Timer;
import org.mockito.internal.verification.api.
VerificationData;
import org.mockito.verification.
VerificationMode;
/**
* Verifies that another verification mode (the delegate) is satisfied within a certain timeframe
* (before timeoutMillis has passed, measured from the call to verify()), and either returns immediately
* once it does, or waits until it is definitely satisfied once the full time has passed.
*/
public class
VerificationOverTimeImpl implements
VerificationMode {
private final long
pollingPeriodMillis;
private final
VerificationMode delegate;
private final boolean
returnOnSuccess;
private final
Timer timer;
/**
* Create this verification mode, to be used to verify invocation ongoing data later.
*
* @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied
* @param durationMillis The max time to wait (in millis) for the delegate verification mode to be satisfied
* @param delegate The verification mode to delegate overall success or failure to
* @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in
* {@link org.mockito.verification.VerificationWithTimeout}, or to only return once
* the delegate is satisfied and the full duration has passed (as in
* {@link org.mockito.verification.VerificationAfterDelay}).
*/
public
VerificationOverTimeImpl(long
pollingPeriodMillis, long
durationMillis,
VerificationMode delegate, boolean
returnOnSuccess) {
this(
pollingPeriodMillis,
delegate,
returnOnSuccess, new
Timer(
durationMillis));
}
/**
* Create this verification mode, to be used to verify invocation ongoing data later.
*
* @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied
* @param delegate The verification mode to delegate overall success or failure to
* @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in
* {@link org.mockito.verification.VerificationWithTimeout}, or to only return once
* the delegate is satisfied and the full duration has passed (as in
* {@link org.mockito.verification.VerificationAfterDelay}).
* @param timer Checker of whether the duration of the verification is still acceptable
*/
public
VerificationOverTimeImpl(long
pollingPeriodMillis,
VerificationMode delegate, boolean
returnOnSuccess,
Timer timer) {
this.
pollingPeriodMillis =
pollingPeriodMillis;
this.
delegate =
delegate;
this.
returnOnSuccess =
returnOnSuccess;
this.
timer =
timer;
}
/**
* Verify the given ongoing verification data, and confirm that it satisfies the delegate verification mode
* before the full duration has passed.
*
* In practice, this polls the delegate verification mode until it is satisfied. If it is not satisfied once
* the full duration has passed, the last error returned by the delegate verification mode will be thrown
* here in turn. This may be thrown early if the delegate is unsatisfied and the verification mode is known
* to never recover from this situation (e.g. {@link AtMost}).
*
* If it is satisfied before the full duration has passed, behaviour is dependent on the returnOnSuccess parameter
* given in the constructor. If true, this verification mode is immediately satisfied once the delegate is. If
* false, this verification mode is not satisfied until the delegate is satisfied and the full time has passed.
*
* @throws MockitoAssertionError if the delegate verification mode does not succeed before the timeout
*/
public void
verify(
VerificationData data) {
AssertionError error = null;
timer.
start();
while (
timer.
isCounting()) {
try {
delegate.
verify(
data);
if (
returnOnSuccess) {
return;
} else {
error = null;
}
} catch (
MockitoAssertionError e) {
error =
handleVerifyException(
e);
}
catch (
AssertionError e) {
error =
handleVerifyException(
e);
}
}
if (
error != null) {
throw
error;
}
}
private
AssertionError handleVerifyException(
AssertionError e) {
if (
canRecoverFromFailure(
delegate)) {
sleep(
pollingPeriodMillis);
return
e;
} else {
throw
e;
}
}
protected boolean
canRecoverFromFailure(
VerificationMode verificationMode) {
return !(
verificationMode instanceof
AtMost ||
verificationMode instanceof
NoMoreInteractions);
}
public
VerificationOverTimeImpl copyWithVerificationMode(
VerificationMode verificationMode) {
return new
VerificationOverTimeImpl(
pollingPeriodMillis,
timer.
duration(),
verificationMode,
returnOnSuccess);
}
private void
sleep(long
sleep) {
try {
Thread.
sleep(
sleep);
} catch (
InterruptedException ie) {
throw new
RuntimeException("Thread sleep has been interrupted",
ie);
}
}
@
Override
public
VerificationMode description(
String description) {
return
VerificationModeFactory.
description(this,
description);
}
public boolean
isReturnOnSuccess() {
return
returnOnSuccess;
}
public long
getPollingPeriodMillis() {
return
pollingPeriodMillis;
}
public
Timer getTimer() {
return
timer;
}
public
VerificationMode getDelegate() {
return
delegate;
}
}