// Path: xvfb-manager/src/main/java/com/github/mike10004/xvfbmanager/Poller.java
// public static class PollOutcome<E> {
// 
//     /**
//      * Reason polling stopped.
//      */
//     public final StopReason reason;
// 
//     /**
//      * An object that represents the resolved state of the poll.
//      */
//     public final @Nullable E content;
// 
//     /**
//      * Gets the polling duration. This may not be exact.
//      */
//     public final Duration duration;
// 
//     private final int numAttempts;
// 
//     private PollOutcome(StopReason reason, @Nullable E content, Duration duration, int numAttempts) {
//         this.reason = checkNotNull(reason);
//         this.content = content;
//         this.duration = checkNotNull(duration);
//         this.numAttempts = numAttempts;
//     }
// 
//     @Override
//     public String toString() {
//         return "PollOutcome{" +
//                 "reason=" + reason +
//                 ", content=" + content +
//                 ", duration=" + duration +
//                 ", attempts=" + numAttempts +
//                 '}';
//     }
// 
//     /**
//      * Gets the number of times the poll was attempted. This is the numbef of
//      * times the {@link #check(int) check()} function is invoked.
//      * @return count of attempts
//      */
//     public int getNumAttempts() {
//         return numAttempts;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         PollOutcome<?> that = (PollOutcome<?>) o;
// 
//         if (numAttempts != that.numAttempts) return false;
//         if (reason != that.reason) return false;
//         if (content != null ? !content.equals(that.content) : that.content != null) return false;
//         return duration.equals(that.duration);
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = reason.hashCode();
//         result = 31 * result + (content != null ? content.hashCode() : 0);
//         result = 31 * result + duration.hashCode();
//         result = 31 * result + numAttempts;
//         return result;
//     }
// }
// 
// Path: xvfb-manager/src/main/java/com/github/mike10004/xvfbmanager/Poller.java
// protected static class SimplePoller extends Poller<Void> {
// 
//     private final Supplier<Boolean> condition;
// 
//     public SimplePoller(Sleeper sleeper, Supplier<Boolean> condition) {
//         super(sleeper);
//         this.condition = checkNotNull(condition);
//     }
// 
//     public SimplePoller(Supplier<Boolean> condition) {
//         super();
//         this.condition = checkNotNull(condition);
//     }
// 
//     @Override
//     protected PollAnswer<Void> check(int pollAttemptsSoFar) {
//         boolean state = condition.get();
//         if (state) {
//             return resolve(null);
//         } else {
//             return continuePolling();
//         }
//     }
// }
// 
// Path: xvfb-manager/src/main/java/com/github/mike10004/xvfbmanager/Poller.java
// public enum StopReason {
// 
//     /**
//      * State was resolved to the poller's satisfaction.
//      */
//     RESOLVED,
// 
//     /**
//      * State was not resolved to the poller's satisfaction,
//      * but polling must cease anyway.
//      */
//     ABORTED,
// 
//     /**
//      * The poller's iterator of intervals was exhausted
//      * prior to resolution or abortion of polling.
//      */
//     TIMEOUT
// }


import com.github.mike10004.xvfbmanager.Poller.PollOutcome;
import com.github.mike10004.xvfbmanager.Poller.SimplePoller;
import com.github.mike10004.xvfbmanager.Poller.StopReason;
import com.google.common.base.Suppliers;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
    public void poll_timeoutOverridesAbort(final int attempts) throws Exception {
        TestSleeper sleeper = new TestSleeper();
        PollOutcome<?> outcome = new Poller<Void>(sleeper) {
            @Override
            protected PollAnswer<Void> check(int pollAttemptsSoFar) {
                return pollAttemptsSoFar >= attempts ? abortPolling() : continuePolling();
            }
        }.poll(1000, attempts); // poll forever
        assertEquals("reason", StopReason.TIMEOUT, outcome.reason);
        assertEquals("duration", attempts * 1000, sleeper.getDuration());
        assertEquals("sleep count", attempts, sleeper.getCount());
    }

    @Test(expected = IllegalArgumentException.class)
    public void poll_badArgs() throws Exception {
        testPoller(5, 4, -1000, null, 0);
    }

    @Test
    public void testDoNotSleepIfAboutToTimeOut_1() throws Exception {
        testDoNotSleepIfAboutToTimeOut(1000, 1, StopReason.TIMEOUT, 1000, 1);
    }

    @Test
    public void testDoNotSleepIfAboutToTimeOut_2() throws Exception {
        testDoNotSleepIfAboutToTimeOut(1000, 2, StopReason.TIMEOUT, 2000, 2);
    }

    public void testDoNotSleepIfAboutToTimeOut(long intervalMs, int maxPolls, StopReason stopReason, long expectedDuration, int expectedSleeps) throws Exception {
        TestSleeper sleeper = new TestSleeper();
// Path: xvfb-manager/src/main/java/com/github/mike10004/xvfbmanager/Poller.java
// public static class PollOutcome<E> {
// 
//     /**
//      * Reason polling stopped.
//      */
//     public final StopReason reason;
// 
//     /**
//      * An object that represents the resolved state of the poll.
//      */
//     public final @Nullable E content;
// 
//     /**
//      * Gets the polling duration. This may not be exact.
//      */
//     public final Duration duration;
// 
//     private final int numAttempts;
// 
//     private PollOutcome(StopReason reason, @Nullable E content, Duration duration, int numAttempts) {
//         this.reason = checkNotNull(reason);
//         this.content = content;
//         this.duration = checkNotNull(duration);
//         this.numAttempts = numAttempts;
//     }
// 
//     @Override
//     public String toString() {
//         return "PollOutcome{" +
//                 "reason=" + reason +
//                 ", content=" + content +
//                 ", duration=" + duration +
//                 ", attempts=" + numAttempts +
//                 '}';
//     }
// 
//     /**
//      * Gets the number of times the poll was attempted. This is the numbef of
//      * times the {@link #check(int) check()} function is invoked.
//      * @return count of attempts
//      */
//     public int getNumAttempts() {
//         return numAttempts;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         PollOutcome<?> that = (PollOutcome<?>) o;
// 
//         if (numAttempts != that.numAttempts) return false;
//         if (reason != that.reason) return false;
//         if (content != null ? !content.equals(that.content) : that.content != null) return false;
//         return duration.equals(that.duration);
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = reason.hashCode();
//         result = 31 * result + (content != null ? content.hashCode() : 0);
//         result = 31 * result + duration.hashCode();
//         result = 31 * result + numAttempts;
//         return result;
//     }
// }
// 
// Path: xvfb-manager/src/main/java/com/github/mike10004/xvfbmanager/Poller.java
// protected static class SimplePoller extends Poller<Void> {
// 
//     private final Supplier<Boolean> condition;
// 
//     public SimplePoller(Sleeper sleeper, Supplier<Boolean> condition) {
//         super(sleeper);
//         this.condition = checkNotNull(condition);
//     }
// 
//     public SimplePoller(Supplier<Boolean> condition) {
//         super();
//         this.condition = checkNotNull(condition);
//     }
// 
//     @Override
//     protected PollAnswer<Void> check(int pollAttemptsSoFar) {
//         boolean state = condition.get();
//         if (state) {
//             return resolve(null);
//         } else {
//             return continuePolling();
//         }
//     }
// }
// 
// Path: xvfb-manager/src/main/java/com/github/mike10004/xvfbmanager/Poller.java
// public enum StopReason {
// 
//     /**
//      * State was resolved to the poller's satisfaction.
//      */
//     RESOLVED,
// 
//     /**
//      * State was not resolved to the poller's satisfaction,
//      * but polling must cease anyway.
//      */
//     ABORTED,
// 
//     /**
//      * The poller's iterator of intervals was exhausted
//      * prior to resolution or abortion of polling.
//      */
//     TIMEOUT
// }


// Path: xvfb-manager/src/test/java/com/github/mike10004/xvfbmanager/PollerTest.java
import com.github.mike10004.xvfbmanager.Poller.PollOutcome;
import com.github.mike10004.xvfbmanager.Poller.SimplePoller;
import com.github.mike10004.xvfbmanager.Poller.StopReason;
import com.google.common.base.Suppliers;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;

    public void poll_timeoutOverridesAbort(final int attempts) throws Exception {
        TestSleeper sleeper = new TestSleeper();
        PollOutcome<?> outcome = new Poller<Void>(sleeper) {
            @Override
            protected PollAnswer<Void> check(int pollAttemptsSoFar) {
                return pollAttemptsSoFar >= attempts ? abortPolling() : continuePolling();
            }
        }.poll(1000, attempts); // poll forever
        assertEquals("reason", StopReason.TIMEOUT, outcome.reason);
        assertEquals("duration", attempts * 1000, sleeper.getDuration());
        assertEquals("sleep count", attempts, sleeper.getCount());
    }

    @Test(expected = IllegalArgumentException.class)
    public void poll_badArgs() throws Exception {
        testPoller(5, 4, -1000, null, 0);
    }

    @Test
    public void testDoNotSleepIfAboutToTimeOut_1() throws Exception {
        testDoNotSleepIfAboutToTimeOut(1000, 1, StopReason.TIMEOUT, 1000, 1);
    }

    @Test
    public void testDoNotSleepIfAboutToTimeOut_2() throws Exception {
        testDoNotSleepIfAboutToTimeOut(1000, 2, StopReason.TIMEOUT, 2000, 2);
    }

    public void testDoNotSleepIfAboutToTimeOut(long intervalMs, int maxPolls, StopReason stopReason, long expectedDuration, int expectedSleeps) throws Exception {
        TestSleeper sleeper = new TestSleeper();
        PollOutcome<Void> outcome = new SimplePoller(sleeper, Suppliers.ofInstance(false)).poll(intervalMs, maxPolls);