package org.ovirt.engine.core.bll.network.macpool;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.math.LongRange;
import org.junit.Before;
import org.junit.Test;
import org.ovirt.engine.core.utils.MacAddressRangeUtils;
public class RangeTest {
private static final int MAC_FROM_RANGE = 15;
private static final int MAC_OUTSIDE_OF_RANGE = 25;
private static final int RANGE_FROM = 10;
private static final int RANGE_TO = 19;
private static final int NUMBER_OF_MACS = 10;
private Range rangeOf10Macs;
@Before
public void before() {
rangeOf10Macs = new Range(RANGE_FROM, RANGE_TO);
}
@Test
public void testMacIsContainedInRange() throws Exception {
assertThat(rangeOf10Macs.contains(MAC_FROM_RANGE), is(true));
}
@Test
public void testMacIsNotContainedInRange() throws Exception {
assertThat(rangeOf10Macs.contains(MAC_OUTSIDE_OF_RANGE), is(false));
}
@Test(expected = IllegalArgumentException.class)
public void testFailWhenUsingMacOutsideOfRange() throws Exception {
rangeOf10Macs.use(MAC_OUTSIDE_OF_RANGE, false);
}
@Test(expected = IllegalArgumentException.class)
public void testFailWhenAskingForMacOutsideOfRange() throws Exception {
rangeOf10Macs.isAllocated(MAC_OUTSIDE_OF_RANGE);
}
@Test(expected = IllegalArgumentException.class)
public void testFailWhenReturningMacOutsideOfRange() throws Exception {
rangeOf10Macs.freeMac(MAC_OUTSIDE_OF_RANGE);
}
@Test
public void testAllMacsAreAvailableAfterCreation() {
assertThat(rangeOf10Macs.getAvailableCount(), is(NUMBER_OF_MACS));
}
@Test
public void testAssigningMacWithDisallowedDuplicates() throws Exception {
assertThat(rangeOf10Macs.use(MAC_FROM_RANGE, false), is(true));
assertThat(rangeOf10Macs.getAvailableCount(), is(NUMBER_OF_MACS - 1));
assertThat(rangeOf10Macs.use(MAC_FROM_RANGE, false), is(false));
assertThat(rangeOf10Macs.getAvailableCount(), is(NUMBER_OF_MACS - 1));
assertThat(rangeOf10Macs.isAllocated(MAC_FROM_RANGE), is(true));
}
@Test
public void testAssigningMacWithAllowedDuplicates() throws Exception {
assertThat(rangeOf10Macs.use(MAC_FROM_RANGE, true), is(true));
assertThat(rangeOf10Macs.getAvailableCount(), is(NUMBER_OF_MACS - 1));
assertThat(rangeOf10Macs.use(MAC_FROM_RANGE, true), is(true));
assertThat(rangeOf10Macs.getAvailableCount(), is(NUMBER_OF_MACS - 1));
assertThat(rangeOf10Macs.isAllocated(MAC_FROM_RANGE), is(true));
}
@Test
public void testFreeMac() throws Exception {
final List<Long> allocatedMacs = rangeOf10Macs.allocateMacs(NUMBER_OF_MACS);
assertThat(allocatedMacs.size(), is(NUMBER_OF_MACS));
assertThat(rangeOf10Macs.getAvailableCount(), is(0));
for(int i = 1; i <= NUMBER_OF_MACS; i++) {
rangeOf10Macs.freeMac(allocatedMacs.remove(0));
assertThat(rangeOf10Macs.getAvailableCount(), is(i));
}
}
@Test
public void testFreeMacDuplicityAllowed() throws Exception {
// Allocate one mac twice.
assertThat(rangeOf10Macs.use(MAC_FROM_RANGE, true), is(true));
assertThat(rangeOf10Macs.isAllocated(MAC_FROM_RANGE), is(true));
assertThat(rangeOf10Macs.use(MAC_FROM_RANGE, true), is(true));
assertThat(rangeOf10Macs.isAllocated(MAC_FROM_RANGE), is(true));
// Check decreasing of duplicity usage.
rangeOf10Macs.freeMac(MAC_FROM_RANGE);
assertThat(rangeOf10Macs.isAllocated(MAC_FROM_RANGE), is(true));
rangeOf10Macs.freeMac(MAC_FROM_RANGE);
assertThat(rangeOf10Macs.isAllocated(MAC_FROM_RANGE), is(false));
}
@Test
public void testAllocateMac() throws Exception {
assertThat(rangeOf10Macs.allocateMacs(5).size(), is(5));
assertThat(rangeOf10Macs.getAvailableCount(), is(5));
assertThat(rangeOf10Macs.allocateMacs(5).size(), is(5));
assertThat(rangeOf10Macs.getAvailableCount(), is(0));
}
@Test(expected = IllegalStateException.class)
public void testAllocateMacNoEnoughMacs() throws Exception {
rangeOf10Macs.allocateMacs(NUMBER_OF_MACS + 1);
}
@Test
public void testRangeStartAndRangeStopAreInclusive() throws Exception {
assertThat(new Range(MAC_FROM_RANGE, MAC_FROM_RANGE).getAvailableCount(), is(1));
}
@Test
public void testRangeCanContainOnlyIntSizeNumberOfElements() throws Exception {
LongRange longRange = MacAddressRangeUtils.clipRange(new LongRange(0, Long.MAX_VALUE));
Range range = new Range(longRange.getMinimumLong(), longRange.getMaximumLong());
assertThat(range.getAvailableCount(), is(Integer.MAX_VALUE));
}
@Test(expected = IllegalArgumentException.class)
public void testTooBigRange() throws Exception {
new Range(0, Integer.MAX_VALUE);
}
@Test
public void testMaxSizeRange() throws Exception {
new Range(0, Integer.MAX_VALUE - 1);
}
/**
* test that MACs arent returned in leftmost-available order. Instead, we're returning macs from left to right,
* noting last scan position. That means that if we obtain and return mac from/to pool, we'll obtain this MAC again
* only after all other free macs were used.
*/
@Test
public void testOrderOrAcquiredMACs() {
Range range = new Range(0, 5);
List<Integer> usedMacs = Arrays.asList(0, 2, 4);
for(int i = 0; i < 5; i++) {
boolean usedMac = usedMacs.contains(i);
if (usedMac) {
boolean allowDuplicates = false;
range.use(i, allowDuplicates);
}
}
for (Integer expectedUnallocatedMac : Arrays.asList(1, 3, 5, 1, 3, 5, 1)) {
allocateAndFreeMacAndExpectGivenMac(range, expectedUnallocatedMac);
}
}
/***
*
* method obtains mac from pool, assert expectation, and return it back.
*
* @param range range of macs
* @param expectedMac mac, which we expect to be returned from {@code range.allocateMacs(1)}
*/
private void allocateAndFreeMacAndExpectGivenMac(Range range, long expectedMac) {
Long mac = range.allocateMacs(1).get(0);
assertThat(mac, is(expectedMac));
range.freeMac(mac);
}
}