1 /* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.internal.verification; 6 7 import org.mockito.exceptions.base.MockitoAssertionError; 8 import org.mockito.internal.util.Timer; 9 import org.mockito.internal.verification.api.VerificationData; 10 import org.mockito.verification.VerificationMode; 11 12 /** 13 * Verifies that another verification mode (the delegate) is satisfied within a certain timeframe 14 * (before timeoutMillis has passed, measured from the call to verify()), and either returns immediately 15 * once it does, or waits until it is definitely satisfied once the full time has passed. 16 */ 17 public class VerificationOverTimeImpl implements VerificationMode { 18 19 private final long pollingPeriodMillis; 20 private final VerificationMode delegate; 21 private final boolean returnOnSuccess; 22 private final Timer timer; 23 24 /** 25 * Create this verification mode, to be used to verify invocation ongoing data later. 26 * 27 * @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied 28 * @param durationMillis The max time to wait (in millis) for the delegate verification mode to be satisfied 29 * @param delegate The verification mode to delegate overall success or failure to 30 * @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in 31 * {@link org.mockito.verification.VerificationWithTimeout}, or to only return once 32 * the delegate is satisfied and the full duration has passed (as in 33 * {@link org.mockito.verification.VerificationAfterDelay}). 34 */ VerificationOverTimeImpl( long pollingPeriodMillis, long durationMillis, VerificationMode delegate, boolean returnOnSuccess)35 public VerificationOverTimeImpl( 36 long pollingPeriodMillis, 37 long durationMillis, 38 VerificationMode delegate, 39 boolean returnOnSuccess) { 40 this(pollingPeriodMillis, delegate, returnOnSuccess, new Timer(durationMillis)); 41 } 42 43 /** 44 * Create this verification mode, to be used to verify invocation ongoing data later. 45 * 46 * @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied 47 * @param delegate The verification mode to delegate overall success or failure to 48 * @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in 49 * {@link org.mockito.verification.VerificationWithTimeout}, or to only return once 50 * the delegate is satisfied and the full duration has passed (as in 51 * {@link org.mockito.verification.VerificationAfterDelay}). 52 * @param timer Checker of whether the duration of the verification is still acceptable 53 */ VerificationOverTimeImpl( long pollingPeriodMillis, VerificationMode delegate, boolean returnOnSuccess, Timer timer)54 public VerificationOverTimeImpl( 55 long pollingPeriodMillis, 56 VerificationMode delegate, 57 boolean returnOnSuccess, 58 Timer timer) { 59 this.pollingPeriodMillis = pollingPeriodMillis; 60 this.delegate = delegate; 61 this.returnOnSuccess = returnOnSuccess; 62 this.timer = timer; 63 } 64 65 /** 66 * Verify the given ongoing verification data, and confirm that it satisfies the delegate verification mode 67 * before the full duration has passed. 68 * 69 * In practice, this polls the delegate verification mode until it is satisfied. If it is not satisfied once 70 * the full duration has passed, the last error returned by the delegate verification mode will be thrown 71 * here in turn. This may be thrown early if the delegate is unsatisfied and the verification mode is known 72 * to never recover from this situation (e.g. {@link AtMost}). 73 * 74 * If it is satisfied before the full duration has passed, behaviour is dependent on the returnOnSuccess parameter 75 * given in the constructor. If true, this verification mode is immediately satisfied once the delegate is. If 76 * false, this verification mode is not satisfied until the delegate is satisfied and the full time has passed. 77 * 78 * @throws MockitoAssertionError if the delegate verification mode does not succeed before the timeout 79 */ 80 @Override verify(VerificationData data)81 public void verify(VerificationData data) { 82 AssertionError error = null; 83 84 timer.start(); 85 while (timer.isCounting()) { 86 try { 87 delegate.verify(data); 88 89 if (returnOnSuccess) { 90 return; 91 } else { 92 error = null; 93 } 94 } catch (AssertionError e) { 95 error = handleVerifyException(e); 96 } 97 } 98 99 if (error != null) { 100 throw error; 101 } 102 } 103 handleVerifyException(AssertionError e)104 private AssertionError handleVerifyException(AssertionError e) { 105 if (canRecoverFromFailure(delegate)) { 106 sleep(pollingPeriodMillis); 107 return e; 108 } else { 109 throw e; 110 } 111 } 112 canRecoverFromFailure(VerificationMode verificationMode)113 protected boolean canRecoverFromFailure(VerificationMode verificationMode) { 114 return !(verificationMode instanceof AtMost 115 || verificationMode instanceof NoMoreInteractions); 116 } 117 copyWithVerificationMode(VerificationMode verificationMode)118 public VerificationOverTimeImpl copyWithVerificationMode(VerificationMode verificationMode) { 119 return new VerificationOverTimeImpl( 120 pollingPeriodMillis, timer.duration(), verificationMode, returnOnSuccess); 121 } 122 sleep(long sleep)123 private void sleep(long sleep) { 124 try { 125 Thread.sleep(sleep); 126 } catch (InterruptedException ie) { 127 throw new RuntimeException("Thread sleep has been interrupted", ie); 128 } 129 } 130 isReturnOnSuccess()131 public boolean isReturnOnSuccess() { 132 return returnOnSuccess; 133 } 134 getPollingPeriodMillis()135 public long getPollingPeriodMillis() { 136 return pollingPeriodMillis; 137 } 138 getTimer()139 public Timer getTimer() { 140 return timer; 141 } 142 getDelegate()143 public VerificationMode getDelegate() { 144 return delegate; 145 } 146 } 147