/*
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/
package com.google.common.util.concurrent;
import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.google.common.util.concurrent.RateLimiter.SleepingTicker;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Provides a fake {@link RateLimiter} to facilitate testing. Note that in Guava 14.0 the
* {@link RateLimiter.SleepingTicker} class is package private, so this fake rate limiter has to
* be in the same package to be able to extend it. Later versions of Guava makes it public, so this
* can be moved to a package belongs to alluxio when updating to a newer version of Guava.
*/
public final class MockRateLimiter {
private final RateLimiter mRateLimiter;
private final FakeSleepingTicker mTicker;
/**
* Constructs {@link MockRateLimiter}.
*
* @param permitsPerSecond the rate of the returned {@code RateLimiter}, measured in
* how many permits become available per second
*/
public MockRateLimiter(double permitsPerSecond) {
mTicker = new FakeSleepingTicker();
mRateLimiter = RateLimiter.create(mTicker, permitsPerSecond);
}
/**
* Gets Guava RateLimiter.
*
* @return Guava RateLimiter
*/
public RateLimiter getGuavaRateLimiter() {
return mRateLimiter;
}
/**
* Sleeps in milliseconds.
*
* @param millis the number of milliseconds
*/
public void sleepMillis(int millis) {
mTicker.sleepMillis(millis);
}
/**
* Reads events and clears.
* @return the list of events
*/
public List<String> readEventsAndClear() {
return mTicker.readEventsAndClear();
}
/**
* The sleeping ticker gathers events and presents them as strings.
* R0.6 means a delay of 0.6 seconds caused by the (R)ateLimiter
* U1.0 means the (U)ser caused the ticker to sleep for a second.
*/
private static class FakeSleepingTicker extends SleepingTicker {
private long mInstant = 0L;
private final List<String> mEvents = new ArrayList<>();
@Override
public long read() {
return mInstant;
}
private void sleepMillis(int millis) {
sleepMicros("U", MILLISECONDS.toMicros(millis));
}
private void sleepMicros(String caption, long micros) {
mInstant += MICROSECONDS.toNanos(micros);
mEvents.add(caption + String.format(Locale.ROOT, "%3.2f", (micros / 1000000.0)));
}
@Override
public void sleepMicrosUninterruptibly(long micros) {
sleepMicros("R", micros);
}
private List<String> readEventsAndClear() {
try {
return new ArrayList<>(mEvents);
} finally {
mEvents.clear();
}
}
@Override
public String toString() {
return mEvents.toString();
}
}
}