/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.test.dunit; import static org.apache.geode.test.dunit.Jitter.*; import static org.junit.Assert.*; import org.apache.logging.log4j.Logger; import org.apache.geode.internal.cache.LocalRegion; import org.apache.geode.internal.logging.LogService; /** * <code>Wait</code> provides static utility methods to wait for some asynchronous action with * intermittent polling. * * These methods can be used directly: <code>Wait.waitForCriterion(...)</code>, however, they are * intended to be referenced through static import: * * <pre> * import static org.apache.geode.test.dunit.Wait.*; * ... * waitForCriterion(...); * </pre> * * Extracted from DistributedTestCase. * * <p> * Deprecated in favor of using {@link com.jayway.awaitility.Awaitility}. * * <p> * Examples of using Awaitility: * * <pre> * * import static com.jayway.awaitility.Awaitility.*; * import static com.jayway.awaitility.Duration.*; // optional * import static java.util.concurrent.TimeUnit.*; // optional * * await().atMost(2, SECONDS).until(() -> isDone()); * * Host.getHost(0).getVM(0).invoke(() -> await().atMost(1, MINUTES).until(() -> isDone())); * * Host.getHost(0).getVM(0).invoke(() -> await("waiting for 4 members").atMost(5, SECONDS).until(() -> getMemberCount(), is(4))); * * await().atMost(5, SECONDS).untilCall(getValue(), equalTo(5)); * * volatile boolean done = false; * await().atMost(2, SECONDS).untilCall(Boolean.class, equalTo(this.done)); * * AtomicBoolean closed = new AtomicBoolean(); * await().atMost(5, SECONDS).untilTrue(closed); * * AtomicBoolean running = new AtomicBoolean(); * await().atMost(30, SECONDS).untilFalse(running); * * List members = new ArrayList(); * await().untilCall(to(members).size(), greaterThan(2)); * </pre> * * <p> * NOTE: By default, the pollDelay is equal to the pollInterval which defaults to * ONE_HUNDRED_MILLISECONDS. You may want to add pollDelay(ZERO) to force Awaitility to check your * condition before waiting the pollInterval. * * <p> * Example of detailed conversion to Awaitility: * * <pre> * From: * * public boolean waitForClose() { * WaitCriterion ev = new WaitCriterion() { * public boolean done() { * return isClosed(); * } * public String description() { * return "resource never closed"; * } * }; * Wait.waitForCriterion(ev, 2000, 200, true); * return true; * } * * To: * * import static com.jayway.awaitility.Awaitility.*; * import static com.jayway.awaitility.Duration.*; * import static java.util.concurrent.TimeUnit.*; * * await("resource never closed").atMost(2, SECONDS).untilCall(() -> isClosed()); * * Or: * * await("resource never closed").atMost(2, SECONDS).pollDelay(ZERO).pollInterval(200, MILLISECONDS).untilCall(() -> isClosed()); * </pre> * * @deprecated Use {@link com.jayway.awaitility.Awaitility} instead. * * @see com.jayway.awaitility.Awaitility * @see com.jayway.awaitility.Duration * @see com.jayway.awaitility.core.ConditionFactory */ @Deprecated public class Wait { private static final Logger logger = LogService.getLogger(); protected Wait() {} /** * Pause for a default interval (250 milliseconds). * * @deprecated Please use {@link com.jayway.awaitility.Awaitility} instead. */ public static void pause() { pause(250); } /** * Pause for the specified milliseconds. Make sure system clock has advanced by the specified * number of millis before returning. * * @deprecated Please use {@link com.jayway.awaitility.Awaitility} instead. */ public static final void pause(final int milliseconds) { if (milliseconds >= 1000 || logger.isDebugEnabled()) { // check for debug but log at info logger.info("Pausing for {} ms...", milliseconds); } final long target = System.currentTimeMillis() + milliseconds; try { for (;;) { long msLeft = target - System.currentTimeMillis(); if (msLeft <= 0) { break; } Thread.sleep(msLeft); } } catch (InterruptedException e) { Assert.fail("interrupted", e); } } /** * Wait until given criterion is met * * @param waitCriterion criterion to wait on * @param timeoutMillis total time to wait, in milliseconds * @param pollingInterval pause interval between waits * @param throwOnTimeout if false, don't generate an error * @deprecated Please use {@link com.jayway.awaitility.Awaitility} instead. */ @Deprecated public static void waitForCriterion(final WaitCriterion waitCriterion, final long timeoutMillis, final long pollingInterval, final boolean throwOnTimeout) { long waitThisTime = jitterInterval(pollingInterval); final long tilt = System.currentTimeMillis() + timeoutMillis; for (;;) { if (waitCriterion.done()) { return; // success } if (waitCriterion instanceof StoppableWaitCriterion) { StoppableWaitCriterion ev2 = (StoppableWaitCriterion) waitCriterion; if (ev2.stopWaiting()) { if (throwOnTimeout) { fail("stopWaiting returned true: " + waitCriterion.description()); } return; } } // Calculate time left long timeLeft = tilt - System.currentTimeMillis(); if (timeLeft <= 0) { if (!throwOnTimeout) { return; // not an error, but we're done } fail("Event never occurred after " + timeoutMillis + " ms: " + waitCriterion.description()); } if (waitThisTime > timeLeft) { waitThisTime = timeLeft; } // Wait a little bit Thread.yield(); try { Thread.sleep(waitThisTime); } catch (InterruptedException e) { fail("interrupted"); } } } /** * Blocks until the clock used for expiration moves forward. * * @param cacheTimeMillisSource region that provides cacheTimeMillis * @return the last time stamp observed * @deprecated Please use {@link com.jayway.awaitility.Awaitility} instead. */ public static final long waitForExpiryClockToChange(final LocalRegion cacheTimeMillisSource) { return waitForExpiryClockToChange(cacheTimeMillisSource, cacheTimeMillisSource.cacheTimeMillis()); } /** * Blocks until the clock used for expiration moves forward. * * @param cacheTimeMillisSource region that provides cacheTimeMillis * @param baseTime the timestamp that the clock must exceed * @return the last time stamp observed * @deprecated Please use {@link com.jayway.awaitility.Awaitility} instead. */ public static final long waitForExpiryClockToChange(final LocalRegion cacheTimeMillisSource, final long baseTime) { long nowTime; do { Thread.yield(); nowTime = cacheTimeMillisSource.cacheTimeMillis(); } while ((nowTime - baseTime) <= 0L); return nowTime; } /** * Wait on a mutex. This is done in a loop in order to address the "spurious wakeup" "feature" in * Java. * * @param waitCriterion condition to test * @param mutex object to lock and wait on * @param milliseconds total amount of time to wait * @param pollingInterval interval to pause for the wait * @param throwOnTimeout if false, no error is thrown. * @deprecated Please use {@link com.jayway.awaitility.Awaitility} instead. */ public static void waitMutex(final WaitCriterion waitCriterion, final Object mutex, final long milliseconds, final long pollingInterval, final boolean throwOnTimeout) { final long tilt = System.currentTimeMillis() + milliseconds; long waitThisTime = jitterInterval(pollingInterval); synchronized (mutex) { for (;;) { if (waitCriterion.done()) { break; } long timeLeft = tilt - System.currentTimeMillis(); if (timeLeft <= 0) { if (!throwOnTimeout) { return; // not an error, but we're done } fail( "Event never occurred after " + milliseconds + " ms: " + waitCriterion.description()); } if (waitThisTime > timeLeft) { waitThisTime = timeLeft; } try { mutex.wait(waitThisTime); } catch (InterruptedException e) { fail("interrupted"); } } // for } // synchronized } }