/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.ow2.choreos.ee.nodes;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.stubbing.OngoingStubbing;
import org.ow2.choreos.ee.config.CloudConfiguration;
import org.ow2.choreos.ee.nodes.IdlePool;
import org.ow2.choreos.ee.nodes.IdlePoolFactory;
import org.ow2.choreos.ee.nodes.NodeCreator;
import org.ow2.choreos.ee.nodes.NodeCreatorFactory;
import org.ow2.choreos.nodes.NodeNotCreatedException;
import org.ow2.choreos.nodes.datamodel.CloudNode;
import org.ow2.choreos.nodes.datamodel.NodeSpec;
import org.ow2.choreos.utils.LogConfigurator;
public class IdlePoolTest {
private static final int POOL_THRESHOLD = -1;
private NodeCreator nodeCreator;
@BeforeClass
public static void setUpClass() {
LogConfigurator.configLog();
}
@Before
public void setUp() throws NodeNotCreatedException {
int N = 10;
nodeCreator = mock(NodeCreator.class);
OngoingStubbing<CloudNode> ongoingStubbing = when(nodeCreator.createBootstrappedNode(any(NodeSpec.class)));
for (int i = 0; i < N; i++) {
CloudNode node = new CloudNode();
node.setId("node" + i);
ongoingStubbing = ongoingStubbing.thenReturn(node);
}
NodeCreatorFactory.nodeCreatorForTesting = nodeCreator;
NodeCreatorFactory.testing = true;
}
@Test
public void shouldCreateExtraVMs() throws InterruptedException {
int N = 3;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
int howManyVMs = N;
pool.createExtraVMs(howManyVMs);
Thread.sleep(300);
Set<CloudNode> idlePool = pool.getIdleNodes();
assertEquals(howManyVMs, idlePool.size());
}
@Test(timeout = 2000)
public void shouldFillThePool() throws InterruptedException {
int N = 3;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
pool.createExtraVMs(1);
pool.fillPool();
while (true) {
if (pool.isFull())
break; // pass the test
Thread.sleep(50);
}
}
@Test(timeout = 2000)
public void shouldFillThePoolConcurrently() throws InterruptedException {
int N = 5;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
pool.createExtraVMs(1);
Thread.sleep(100);
for (int i = 0; i < 3; i++) {
PoolFiller filler = new PoolFiller(pool);
Thread thrd = new Thread(filler);
thrd.start();
}
while (true) {
if (pool.isFull())
break; // pas the test
Thread.sleep(50);
}
}
@Test
public void multipleClientsShouldNotRetrieveTheSameNode() throws InterruptedException {
int N = 5;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
pool.fillPool();
Thread.sleep(100);
List<PoolClient> clients = new ArrayList<PoolClient>();
for (int i = 0; i < 3; i++) {
PoolClient client = new PoolClient(pool);
clients.add(client);
Thread thrd = new Thread(client);
thrd.start();
}
Thread.sleep(200);
Iterator<PoolClient> it = clients.iterator();
CloudNode previousNode = it.next().retrievedNode;
assertNotNull(previousNode);
while (it.hasNext()) {
CloudNode node = it.next().retrievedNode;
assertNotNull(node);
assertNotSame(previousNode, node);
previousNode = node;
}
}
@Test(timeout = 3000)
public void multipleRequestsShouldLeaveThePoolFull() throws InterruptedException {
int N = 5;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
pool.fillPool();
Thread.sleep(100);
for (int i = 0; i < 3; i++) {
PoolConsumerAndFiller client = new PoolConsumerAndFiller(pool);
Thread thrd = new Thread(client);
thrd.start();
}
while (true) {
if (pool.isFull())
break; // pas the test
Thread.sleep(50);
}
}
@Test
public void shouldRetrieveANodeEvenWithAnEmptyPool() throws NodeNotCreatedException {
int N = 5;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
CloudNode node = pool.retriveNode();
assertNotNull(node);
assertNotNull(node.getId());
assertFalse(node.getId().isEmpty());
}
@Test
public void shouldRetrieveANodeThatWasAlreadyInThePool() throws NodeNotCreatedException, InterruptedException {
int N = 5;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
pool.fillPool();
Thread.sleep(200);
List<String> nodes = new ArrayList<String>();
for (CloudNode n : pool.getIdleNodes()) {
nodes.add(n.getId());
}
CloudNode node = pool.retriveNode();
assertNotNull(node);
assertNotNull(node.getId());
assertFalse(node.getId().isEmpty());
assertTrue(nodes.contains(node.getId()));
}
@Test
public void multipleClientsShouldRetrieveNodesEvenWithAnEmptyPool() throws InterruptedException {
int N = 5;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
POOL_THRESHOLD);
List<PoolClient> clients = new ArrayList<PoolClient>();
for (int i = 0; i < 3; i++) {
PoolClient client = new PoolClient(pool);
clients.add(client);
Thread thrd = new Thread(client);
thrd.start();
}
Thread.sleep(200);
Iterator<PoolClient> it = clients.iterator();
CloudNode previousNode = it.next().retrievedNode;
assertNotNull(previousNode);
while (it.hasNext()) {
CloudNode node = it.next().retrievedNode;
assertNotNull(node);
assertNotSame(previousNode, node);
previousNode = node;
}
}
@Test
public void shouldIncreasePoolSize() throws InterruptedException, NodeNotCreatedException {
int N = 5;
int threshold = 2;
IdlePool pool = IdlePoolFactory.getCleanInstance(CloudConfiguration.getCloudConfigurationInstance(), N,
threshold);
int howManyVMs = N;
pool.createExtraVMs(howManyVMs);
Thread.sleep(300);
assertEquals(N, pool.getSize());
for (int i = 0; i < N - threshold - 1; i++) {
pool.retriveNode();
}
assertEquals(N, pool.getSize());
pool.retriveNode();
assertEquals(N + 1, pool.getSize());
}
private class PoolFiller implements Runnable {
IdlePool pool;
public PoolFiller(IdlePool pool) {
this.pool = pool;
}
@Override
public void run() {
this.pool.fillPool();
}
}
private class PoolClient implements Runnable {
IdlePool pool;
CloudNode retrievedNode;
public PoolClient(IdlePool pool) {
this.pool = pool;
}
@Override
public void run() {
try {
this.retrievedNode = pool.retriveNode();
} catch (NodeNotCreatedException e) {
System.out.println("=(");
}
}
}
private class PoolConsumerAndFiller implements Runnable {
IdlePool pool;
public PoolConsumerAndFiller(IdlePool pool) {
this.pool = pool;
}
@Override
public void run() {
try {
pool.retriveNode();
} catch (NodeNotCreatedException e) {
System.out.println("=(");
}
pool.fillPool();
}
}
@After
public void tearDown() {
NodeCreatorFactory.testing = false;
}
}