package com.limegroup.gnutella.uploader;
import org.limewire.core.settings.UploadSettings;
import junit.framework.Test;
import com.limegroup.gnutella.BandwidthTrackerImpl;
import com.limegroup.gnutella.util.LimeTestCase;
public class UploadSlotManagerTest extends LimeTestCase {
public UploadSlotManagerTest(String name){
super(name);
}
public static Test suite() {
return buildTestSuite(UploadSlotManagerTest.class);
}
private UploadSlotManager manager;
@Override
public void setUp() {
UploadSettings.SOFT_MAX_UPLOADS.revertToDefault();
UploadSettings.HARD_MAX_UPLOADS.revertToDefault();
UploadSettings.UPLOAD_QUEUE_SIZE.revertToDefault();
manager = new UploadSlotManagerImpl();
}
/**
* Tests case where poll requests with equal priority
* are processed in a fifo manner until the queue fills up,
* after that are rejected.
* Also tests cancelling of poll requests.
*/
public void testEqualPriorityPolling() throws Exception {
UploadSettings.SOFT_MAX_UPLOADS.setValue(1);
UploadSettings.HARD_MAX_UPLOADS.setValue(2);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(1);
UploadSlotUser queued = new UploadSlotUserAdapter();
UploadSlotUser granted = new UploadSlotUserAdapter();
// free slot
assertEquals(0, manager.pollForSlot(granted, true, false));
assertEquals(-1, manager.positionInQueue(granted));
// queued
assertEquals(1, manager.pollForSlot(queued, true, false));
assertEquals(1, manager.getNumQueued());
assertEquals(0, manager.positionInQueue(queued)); // queue starts at pos 0
// reject
assertEquals(-1, manager.pollForSlot(new UploadSlotUserAdapter(), true, false));
// another reject
assertEquals(-1, manager.pollForSlot(new UploadSlotUserAdapter(), true, false));
// was already in queue, stays there.
assertEquals(1, manager.pollForSlot(queued, true, false));
assertEquals(1, manager.getNumQueued());
assertEquals(0, manager.positionInQueue(queued));
// the one that used the slot is done, the queued one is granted.
manager.requestDone(granted);
assertEquals(0, manager.pollForSlot(queued, true, false));
assertEquals(0, manager.getNumQueued());
// there are no slots - try a non-queuable poll which gets rejected
assertEquals(-1, manager.pollForSlot(new UploadSlotUserAdapter(), false, false));
assertEquals(0, manager.getNumQueued());
// there is room in the queue - try to queue someone else - they get queued
UploadSlotUser queued2 = new UploadSlotUserAdapter();
assertEquals(1, manager.pollForSlot(queued2, true, false));
assertEquals(1, manager.getNumQueued());
// cancel the queued one, try to queue another one - queued
manager.cancelRequest(queued2);
assertEquals(0, manager.getNumQueued());
assertEquals(1, manager.pollForSlot(new UploadSlotUserAdapter(), true, false));
assertEquals(1, manager.getNumQueued());
}
/**
* Tests that listeners with equal priority get processed/queued/rejected in
* fifo manner and notified when a slot becomes available.
*/
public void testEqualPriorityListeners() throws Exception {
UploadSettings.SOFT_MAX_UPLOADS.setValue(1);
UploadSettings.HARD_MAX_UPLOADS.setValue(2);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(2);
UploadSlotListenerAdapter granted = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter queued = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter queued2 = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter rejected = new UploadSlotListenerAdapter();
// first is granted
assertEquals(0, manager.requestSlot(granted, false));
assertFalse(granted.notified);
// second and third are queued
assertEquals(1, manager.requestSlot(queued, false));
assertEquals(2, manager.requestSlot(queued2, false));
// last one rejected
assertEquals(-1, manager.requestSlot(rejected, false));
assertEquals(2, manager.getNumQueuedResumable());
// when the one using the slot is done, the first queued one gets notified
// and becomes active
manager.requestDone(granted);
assertEquals(1, manager.getNumQueuedResumable());
assertTrue(queued.notified);
assertFalse(queued2.notified);
granted = queued;
// queue a third one - there is room in the queue now
UploadSlotListenerAdapter queued3 = new UploadSlotListenerAdapter();
assertEquals(2, manager.requestSlot(queued3, false));
// if the first queued one gives up their spot, the one behind
// him will not get notified
manager.cancelRequest(queued2);
assertEquals(1, manager.getNumQueuedResumable());
assertFalse(queued3.notified);
// but if the one that was using the slot finishes,
// the next in the queue gets notification.
manager.cancelRequest(granted);
assertEquals(0, manager.getNumQueuedResumable());
assertTrue(queued3.notified);
}
/**
* tests that listeners with low priority get preempted should
* there be pollers with high priority.
*/
public void testPollerPreemptsLowPriorityListeners() throws Exception {
UploadSettings.SOFT_MAX_UPLOADS.setValue(2);
UploadSettings.HARD_MAX_UPLOADS.setValue(3);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(1);
UploadSlotUserAdapter poller = new UploadSlotUserAdapter();
UploadSlotListenerAdapter lowPriority = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter lowPriority2 = new UploadSlotListenerAdapter();
// start off with two active low priority listeners
assertEquals(0, manager.requestSlot(lowPriority, false));
assertEquals(0, manager.requestSlot(lowPriority2, false));
// add a poller
assertEquals(0, manager.pollForSlot(poller, true, false));
// the listeners should have been preempted
assertTrue(lowPriority.releaseSlot);
assertTrue(lowPriority2.releaseSlot);
// nothing on the queue
assertEquals(0,manager.getNumQueuedResumable());
}
/**
* tests that listeners with low priority get preempted should
* there be a listener with high priority.
*/
public void testListenerPreemptsLowPriorityListeners() throws Exception {
UploadSettings.SOFT_MAX_UPLOADS.setValue(2);
UploadSettings.HARD_MAX_UPLOADS.setValue(3);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(1);
UploadSlotListenerAdapter lowPriority = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter lowPriority2 = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter highPriority = new UploadSlotListenerAdapter();
// start off with two active low priority listeners
assertEquals(0, manager.requestSlot(lowPriority, false));
assertEquals(0, manager.requestSlot(lowPriority2, false));
// add a high-priority listener
assertEquals(0, manager.requestSlot(highPriority, true));
// the other listeners should have been preempted
assertTrue(lowPriority.releaseSlot);
assertTrue(lowPriority2.releaseSlot);
// nothing on the queue
assertEquals(0,manager.getNumQueuedResumable());
}
/**
* Tests that requests with low priority get queued if there are
* active requests with higher priority
*/
public void testLowerPriorityQueuableQueued() throws Exception {
UploadSettings.SOFT_MAX_UPLOADS.setValue(3);
UploadSettings.HARD_MAX_UPLOADS.setValue(4);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(20);
UploadSlotListenerAdapter lowListener = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter highListener = new UploadSlotListenerAdapter();
UploadSlotUserAdapter lowPoller = new UploadSlotUserAdapter();
UploadSlotUserAdapter highPoller = new UploadSlotUserAdapter();
// if there is a high priority poller, everyone else gets queued
// except the high priority listener
assertEquals(0, manager.pollForSlot(highPoller, true, true));
assertGreaterThan(0, manager.pollForSlot(lowPoller, true, false));
assertEquals(0, manager.requestSlot(highListener, true));
assertGreaterThan(0, manager.requestSlot(lowListener, false));
manager = new UploadSlotManagerImpl();
// if there is a high priority listener, everyone but the high
// priority poller gets queued. The latter gets in but does not
// preempt the listener
assertEquals(0, manager.requestSlot(highListener, true));
assertGreaterThan(0, manager.requestSlot(lowListener, false));
assertGreaterThan(0, manager.pollForSlot(lowPoller, true, false));
assertEquals(0, manager.pollForSlot(highPoller, false, true));
manager = new UploadSlotManagerImpl();
// low priority pollers force low priority listeners to get queued
// the rest go through and do not preempt it
assertEquals(0, manager.pollForSlot(lowPoller, true, false));
assertGreaterThan(0, manager.requestSlot(lowListener, false));
assertEquals(0, manager.requestSlot(highListener, true));
assertEquals(0, manager.pollForSlot(highPoller, true, true));
assertFalse(lowPoller.releaseSlot);
}
/**
* tests that listeners get notified for available slot
* if there are no other users with high priority
*/
public void testListenersNotified() throws Exception {
final int SLOTS = 3;
UploadSettings.SOFT_MAX_UPLOADS.setValue(SLOTS);
UploadSettings.HARD_MAX_UPLOADS.setValue(4);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(20);
UploadSlotListenerAdapter[] lowListener = new UploadSlotListenerAdapter[5];
for (int i = 0; i < 5; i++)
lowListener[i] = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter highListener = new UploadSlotListenerAdapter();
UploadSlotListenerAdapter highListener2 = new UploadSlotListenerAdapter();
// add two high listeners, all low listeners should get queued
assertEquals(0, manager.requestSlot(highListener, true));
assertEquals(0, manager.requestSlot(highListener2, true));
for (int i = 0; i < lowListener.length; i++) {
assertEquals(i+1, manager.requestSlot(lowListener[i], false));
assertEquals(i, manager.positionInQueue(lowListener[i]));
}
assertEquals(lowListener.length, manager.getNumQueuedResumable());
// kill one of the high listeners - none of the lower should not be notified
manager.cancelRequest(highListener);
for (UploadSlotListenerAdapter l : lowListener)
assertFalse(l.notified);
// kill the second high listeners - enough low listeners should be notified
// to fill the slots.
manager.cancelRequest(highListener2);
assertTrue(lowListener[0].notified);
assertTrue(lowListener[1].notified);
assertTrue(lowListener[2].notified);
// the rest should not be notified, but should move forward in the queue.
for (int i = SLOTS; i < lowListener.length; i++) {
assertFalse(lowListener[i].notified);
assertEquals(i - SLOTS, manager.positionInQueue(lowListener[i]));
}
assertEquals(lowListener.length - SLOTS, manager.getNumQueuedResumable());
}
public void testMeasureBandwidth() throws Exception {
UploadSettings.SOFT_MAX_UPLOADS.setValue(2);
UploadSettings.HARD_MAX_UPLOADS.setValue(2);
UploadSettings.UPLOAD_QUEUE_SIZE.setValue(2);
// add two high listeners, all low listeners should get queued
UploadSlotUserAdapter user1 = new UploadSlotUserAdapter(100);
assertEquals(0, manager.pollForSlot(user1, false, false));
for (int i = 0; i < 40; i++) {
manager.measureBandwidth();
Thread.sleep(90);
}
float bw = manager.getMeasuredBandwidth();
assertGreaterThan(0.9f, bw);
assertLessThan(1.1f, bw);
bw = manager.getAverageBandwidth();
assertGreaterThan(0.9f, bw);
assertLessThan(1.1f, bw);
}
private static class UploadSlotUserAdapter extends BandwidthTrackerImpl implements UploadSlotUser {
private int bandwidth;
private int transfered;
public UploadSlotUserAdapter(int bandwidth) {
this.bandwidth = bandwidth;
}
public UploadSlotUserAdapter() {
}
boolean releaseSlot;
public String getHost() {
return null;
}
public void releaseSlot() {
releaseSlot = true;
}
public void measureBandwidth() {
transfered += bandwidth;
measureBandwidth(transfered);
}
}
private static class UploadSlotListenerAdapter
extends UploadSlotUserAdapter implements UploadSlotListener {
boolean notified;
public void slotAvailable() {notified = true;}
}
}