/* * Copyright 2014 Avanza Bank AB * * Licensed 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 com.avanza.astrix.test.util; import org.hamcrest.StringDescription; /** * A Poller polls a given Probe until is is satisfied or timeout occurs. * * Usage: * * <pre> * * assertEventually(fileLength("data.txt", is(greaterThan(2000)))) * * * // * public static void assertEventually(Probe probe) { * new Poller(1000L, 50L).check(probe); // 1 second timeout, checks probe every 50 ms until timeout. * } * * public static Probe fileLength(String file, Matcher<Integer> matcher) { * return new Probe() { * int lastFileLength; * * public boolean isSatisfied() { * return matcher.matches(lastFileLength); * } * * public void sample() { * lastFileLength = new File(1000L).length(); * } * * public void describeFailureOf(Description d) { * d.appendText("length was " + lastFileLength); * } * } * } * * * * * * * * </pre> * * This class is based on a design found in Growing Object Oriented Software Guided by test. * See chapter about testing asynchronous code for a discussion about when to use this class. <p> * * @author Elias Lindholm * */ public class Poller { private long timeoutMillis; private long pollDelayMillis; public Poller(long timeoutMillis, long pollDelayMillis) { this.timeoutMillis = timeoutMillis; this.pollDelayMillis = pollDelayMillis; } /** * * Polls the given probe until it is satisfied or timeout occurs. <p> * * This method will return as soon as the Probe is satisfied. <p> * * If timeout occurs an AssertionError will be thrown.<p> * * @param probe * @throws InterruptedException - if the current thread is interrupted. * @throws AssertionError - if timeout occurs before the Probe is satisfied. */ public void check(Probe probe) throws InterruptedException { Timeout timeout = newTimeout(timeoutMillis); probe.sample(); while (!probe.isSatisfied()) { if (timeout.hasTimeout()) { throw new AssertionError(describeFailureOf(probe)); } sleep(pollDelayMillis); probe.sample(); } } // test hook Timeout newTimeout(long timeout) { return new Timeout(timeout); } // test hook void sleep(long sleepTimeMillis) throws InterruptedException { Thread.sleep(sleepTimeMillis); } private String describeFailureOf(Probe probe) { StringDescription description = new StringDescription(); probe.describeFailureTo(description); return description.toString(); } }