/*
* Copyright 2016 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package com.github.ambry.store;
import com.github.ambry.utils.MockTime;
import com.github.ambry.utils.Throttler;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.Test;
import static org.junit.Assert.*;
public class DiskIOSchedulerTest {
/**
* Test that the correct throttlers are used for different job types.
* @throws Exception
*/
@Test
public void basicTest() throws Exception {
final int numJobTypes = 5;
Map<String, Throttler> throttlers = new HashMap<>();
for (int i = 0; i < numJobTypes; i++) {
String jobType = Integer.toString(i);
throttlers.put(jobType, new MockThrottler());
}
DiskIOScheduler scheduler = new DiskIOScheduler(throttlers);
// recognized job types
for (int i = 0; i < numJobTypes; i++) {
String jobType = Integer.toString(i);
Long usedSinceLastCall = ThreadLocalRandom.current().nextLong(Long.MAX_VALUE);
assertEquals("Unexpected i/o slice availability returned", Long.MAX_VALUE,
scheduler.getSlice(jobType, "job", usedSinceLastCall));
MockThrottler throttler = (MockThrottler) throttlers.get(jobType);
assertTrue("maybeThrottle should have been called for this jobType", throttler.called);
assertEquals("observed units passed to throttler not as expected", usedSinceLastCall, throttler.observedUnits,
0.0);
}
for (Throttler throttler : throttlers.values()) {
((MockThrottler) throttler).reset();
}
// unrecognized job type
String jobType = Integer.toString(numJobTypes);
assertEquals("Unexpected i/o slice availability returned", Long.MAX_VALUE, scheduler.getSlice(jobType, "job", 0));
for (Throttler throttler : throttlers.values()) {
assertFalse("maybeThrottle should not have been called for this jobType", ((MockThrottler) throttler).called);
}
// closing scheduler
scheduler.close();
for (Throttler throttler : throttlers.values()) {
assertTrue("Throttler should be closed.", ((MockThrottler) throttler).closed);
}
}
/**
* Test for correct behavior when a null throttler map is passed in.
* @throws Exception
*/
@Test
public void nullThrottlersTest() throws Exception {
DiskIOScheduler scheduler = new DiskIOScheduler(null);
assertEquals("Unexpected i/o slice availability returned", Long.MAX_VALUE, scheduler.getSlice("jobType", "job", 0));
scheduler.close();
}
/**
* A mock of {@link Throttler} for testing purposes.
*/
private static class MockThrottler extends Throttler {
boolean called;
boolean closed;
double observedUnits;
/**
* Build a {@link MockThrottler}.
*/
private MockThrottler() {
super(0, 0, false, new MockTime());
reset();
}
@Override
public void maybeThrottle(double observed) {
called = true;
observedUnits = observed;
}
@Override
public void close() {
closed = true;
}
/**
* Reset the testing related variables to their default values.
*/
private void reset() {
called = false;
observedUnits = Double.MIN_VALUE;
closed = false;
}
}
}