import se.chalmers.gdcn.control.PeerOwner;
import se.chalmers.gdcn.communicationToUI.CommandWord;
import se.chalmers.gdcn.communicationToUI.OperationFinishedEvent;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.storage.Data;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.testng.Assert;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Semaphore;
/**
* Created by HalfLeif on 2014-02-25
*/
public class ClientTest {
/**
* Variables used by the tests
*/
//Semaphore used to make sure that everything is finished when doing things over
//the network before proceeding.
private Semaphore sem;
//Key used when getting and putting to the DHT
private String dhtKey = "Key";
//The standard value used when putting to the DHT
private Data putValue;
//The standard value which is saved to in getResultListener
private Data getValue;
//The standard node used to rendezvous to.
private PeerOwner bootstrapNode;
//The standard peer used by the tests
private PeerOwner peer;
//The boolean used to see if the tests are successful.
private Boolean success;
//Information about the bootstrapping node to make it easier to bootstrap
private String bootstrapAddress = "localhost";
private int bootstrapPort = 4002;
/**
* Listeners used by the tests so that new ones do not have to be made for each test.
* Each command got its own listener. So if a test is doing multiple commands, multiple listeners is needed.
*/
//only listens to the bootstrap command. releases the semaphore and sets success to true. Vital that
//the semaphore is acquired after this and if the test is not about bootstrapping that the
//success of the test if checked some other way
private PropertyChangeListener bootstrapListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
OperationFinishedEvent event = (OperationFinishedEvent) evt;
if(event.getCommandWord() == CommandWord.BOOTSTRAP) {
success = event.getOperation().isSuccess();
sem.release();
}
}
};
//See bootstrapListener
private PropertyChangeListener startListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
OperationFinishedEvent event = (OperationFinishedEvent) evt;
if(event.getCommandWord() == CommandWord.START) {
success = event.getOperation().isSuccess();
sem.release();
}
}
};
//See bootstrapListener
private PropertyChangeListener putListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
OperationFinishedEvent event = (OperationFinishedEvent) evt;
if(event.getCommandWord() == CommandWord.PUT) {
success = event.getOperation().isSuccess();
sem.release();
}
}
};
//Sets the success and the getValue so it can be confirmed in the test.
//It also releases the semaphore
private PropertyChangeListener getListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
OperationFinishedEvent event = (OperationFinishedEvent) evt;
if(event.getCommandWord() == CommandWord.GET) {
success = event.getOperation().isSuccess();
getValue = (Data) event.getOperation().getResult();
sem.release();
}
}
};
//See bootstrapListener
private PropertyChangeListener stopListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
OperationFinishedEvent event = (OperationFinishedEvent) evt;
if(event.getCommandWord() == CommandWord.STOP) {
success = event.getOperation().isSuccess();
sem.release();
}
}
};
/**
* Is run before each test.
* resets the semaphore variable, the success variable and the standard nodes.
* also sets the getValue to null and the putValue to the correct value.
* @throws IOException
*/
@BeforeMethod
public void setUp() throws IOException {
sem = new Semaphore(0);
success = true;
peer = new PeerOwner();
bootstrapNode = new PeerOwner();
peer.testStart(4001);
bootstrapNode.testStart(bootstrapPort);
putValue = new Data("value");
}
/**
* Is run after each test and makes sure that the standard nodes is stopped.
*/
@AfterMethod
public void tearDown() {
stopPeer(peer);
stopPeer(bootstrapNode);
}
@AfterTest
public void deleteTestDir() {
peer.deleteTestDir();
}
/**
* Tests if the bootstrap commands works by checking that the number of neighbours is equal to 1
* and that the operation is a success.
*
*/
@Test
public void bootStrapTest1() throws InterruptedException {
peer.addListener(bootstrapListener);
peer.bootstrap(bootstrapAddress, bootstrapPort);
sem.acquire();
Assert.assertEquals(peer.getNeighbours().size(), 1);
Assert.assertTrue(success);
}
/**
* Tests to make sure that the bootstrap command is not a success when the bootstrapNode is offline
* and that the number of neighbours is zero.
*/
@Test
public void bootStrapTest2() throws InterruptedException {
bootstrapNode.stop();
peer.addListener(bootstrapListener);
peer.bootstrap(bootstrapAddress, bootstrapPort);
sem.acquire();
Assert.assertFalse (success);
Assert.assertEquals(peer.getNeighbours().size(), 0);
}
//Makes sure that a peer can bootstrap to a node twice without crashing
//also makes sure that the number of neighbours is one.
@Test
public void bootStrapTest3() throws InterruptedException {
peer.addListener(bootstrapListener);
peer.bootstrap(bootstrapAddress, bootstrapPort);
sem.acquire();
Assert.assertTrue(success);
peer.bootstrap(bootstrapAddress, bootstrapPort);
sem.acquire();
Assert.assertTrue(success);
Assert.assertEquals(peer.getNeighbours().size(), 1);
}
//Makes sure that the number of neighbours is in the getNeighbours method.
@Test
public void getNeighbourTest1() throws InterruptedException {
int numberOfPeers = 5;
PeerOwner[] peers = new PeerOwner[numberOfPeers];
for(int i = 0; i < numberOfPeers; i++) {
peers[i] = new PeerOwner();
peers[i].addListener(bootstrapListener);
peers[i].testStart(4003 + i);
}
for (int i = 0; i < numberOfPeers; i++) {
peers[i].bootstrap(bootstrapAddress, bootstrapPort);
sem.acquire();
success = success && bootstrapNode.getNeighbours().size() == i+1;
Assert.assertTrue(success);
}
List<PeerAddress> peerAddresses = bootstrapNode.getNeighbours();
for(int i = 0; i < numberOfPeers; i++) {
stopPeer(peers[i]);
}
Assert.assertTrue(success);
Assert.assertEquals(numberOfPeers, peerAddresses.size());
}
/**
* Makes sure that the put method works by putting a value and making sure that the operation is a success
*
*/
@Test
public void putTest1() throws IOException, InterruptedException {
peer.addListener(putListener);
putValue = new Data("Value");
peer.put(dhtKey, putValue);
sem.acquire();
Assert.assertTrue(success);
}
/**
* Makes sure that the put overwrites a earlier value when the same key is used.
*
*/
@Test
public void putTest2() throws IOException, InterruptedException, ClassNotFoundException {
final Data putValue2 = new Data("secondValue");
peer.addListener(getListener);
peer.addListener(putListener);
peer.put(dhtKey, putValue2);
sem.acquire();
Assert.assertTrue(success);
peer.put(dhtKey, putValue);
sem.acquire();
Assert.assertTrue(success);
peer.get(dhtKey);
sem.acquire();
Assert.assertEquals(getValue.getObject(), putValue.getObject());
Assert.assertTrue(success);
}
/**
* Tests get by bootstrapping to peers to a bootstrap node, then one peer puts a value and the other one gets it
* Is successful if the correct value is found.
*/
@Test
public void getTest1() throws IOException, InterruptedException, ClassNotFoundException {
PeerOwner peer2 = new PeerOwner();
putValue = new Data("Value");
peer2.testStart(4003);
peer2.addListener(putListener);
peer.addListener(getListener);
peer2.bootstrap(bootstrapAddress, bootstrapPort);
peer.bootstrap(bootstrapAddress, bootstrapPort);
peer2.put(dhtKey, putValue);
sem.acquire();
Assert.assertTrue(success);
peer.get(dhtKey);
sem.acquire();
stopPeer(peer2);
Assert.assertEquals(getValue.getObject(), putValue.getObject());
Assert.assertTrue(success);
}
//Makes sure that the getValue is null when trying to get a non-existing value.
//Also makes sure that the success from the get method is false.
@Test
public void getTest2() throws InterruptedException {
peer.addListener(getListener);
peer.addListener(bootstrapListener);
peer.bootstrap(bootstrapAddress, bootstrapPort);
sem.acquire();
Assert.assertTrue(success);
peer.get("none-existing");
sem.acquire();
Assert.assertTrue(getValue == null);
Assert.assertFalse(success);
}
//Makes sure that the start method works.
@Test
public void startTest1() throws InterruptedException {
PeerOwner peer2 = new PeerOwner();
peer2.addListener(startListener);
peer2.testStart(4003);
sem.acquire();
stopPeer(peer2);
Assert.assertTrue(success);
}
//Makes sure that the start method can be called when already running.
@Test
public void startTest2() throws InterruptedException {
peer.addListener(startListener);
peer.testStart(4003);
sem.acquire();
peer.deleteNeighbourFile();
peer.deleteKeyFile();
peer.deleteReplicaManager();
Assert.assertTrue(success);
peer.testStart(4001);
sem.acquire();
Assert.assertTrue(success);
}
//Makes sure that the stop method works.
@Test
public void stopTest1 () throws InterruptedException {
peer.addListener(stopListener);
peer.stop();
sem.acquire();
Assert.assertTrue(success);
}
//Makes sure that the stop method doesn't crash when called twice.
@Test
public void stopTest2 () throws InterruptedException {
peer.addListener(stopListener);
peer.stop();
sem.acquire();
Assert.assertTrue(success);
peer.stop();
sem.acquire();
Assert.assertFalse(success);
}
//Makes sure that a non-running node can be stopped without crashing and that the success returned is false.
@Test
public void stopTest3 () throws InterruptedException {
PeerOwner peer2 = new PeerOwner();
peer2.addListener(stopListener);
stopPeer(peer2);
sem.acquire();
Assert.assertFalse(success);
}
//Checks the rebootstrap method so that the number of reconnected nodes is correct and that
//it is the same nodes.
@Test
public void rebootstrapTest1() throws InterruptedException {
int numberOfPeers = 5;
PeerOwner[] peers = new PeerOwner[numberOfPeers];
bootstrapNode.addListener(stopListener);
bootstrapNode.addListener(startListener);
bootstrapNode.addListener(bootstrapListener);
for(int i = 0; i < numberOfPeers; i++) {
peers[i] = new PeerOwner();
peers[i].addListener(bootstrapListener);
peers[i].testStart(4003 + i);
}
for (int i = 0; i < numberOfPeers; i++) {
peers[i].bootstrap(bootstrapAddress, bootstrapPort);
}
sem.acquire(numberOfPeers);
List<PeerAddress> peerAddressesBefore = bootstrapNode.getNeighbours();
bootstrapNode.stop();
sem.acquire();
bootstrapNode.testStart(bootstrapPort);
sem.acquire();
bootstrapNode.reBootstrap();
sem.acquire(numberOfPeers);
List<PeerAddress> peerAddressesAfter = bootstrapNode.getNeighbours();
for(int i = 0; i < numberOfPeers; i++) {
stopPeer(peers[i]);
}
Assert.assertEquals(peerAddressesAfter.size(), numberOfPeers);
Assert.assertEquals(peerAddressesAfter.size(), peerAddressesBefore.size());
for(PeerAddress p : peerAddressesBefore) {
Assert.assertTrue(peerAddressesAfter.contains(p));
}
}
//Checks the rebootstrap method so that a node can reconnect to nodes even
//if not everyone is online.
@Test
public void rebootstrapTest2() throws InterruptedException {
int numberOfPeers = 5;
int numberOfPeersToStop = 2;
PeerOwner[] peers = new PeerOwner[numberOfPeers];
bootstrapNode.addListener(stopListener);
bootstrapNode.addListener(startListener);
bootstrapNode.addListener(bootstrapListener);
for(int i = 0; i < numberOfPeers; i++) {
peers[i] = new PeerOwner();
peers[i].addListener(bootstrapListener);
peers[i].testStart(4003 + i);
}
for (int i = 0; i < numberOfPeers; i++) {
peers[i].bootstrap(bootstrapAddress, bootstrapPort);
}
for (int i = 0; i < numberOfPeersToStop; i++) {
peers[i].addListener(stopListener);
}
sem.acquire(numberOfPeers);
bootstrapNode.stop();
for(int i = 0; i < numberOfPeersToStop; i++) {
stopPeer(peers[i]);
}
sem.acquire(numberOfPeersToStop+1);
bootstrapNode.testStart(bootstrapPort);
sem.acquire();
bootstrapNode.reBootstrap();
sem.acquire(numberOfPeers);
int numNeighbours = bootstrapNode.getNeighbours().size();
for(int i = 0; i < numberOfPeers; i++) {
stopPeer(peers[i]);
}
Assert.assertEquals(numNeighbours, numberOfPeers-numberOfPeersToStop);
}
public void stopPeer(PeerOwner p) {
p.stop();
p.deleteKeyFile();
p.deleteNeighbourFile();
p.deleteReplicaManager();
}
// Makes sure that the oldNeighbour list is updated
// @Test
// public void getOldNeighboursTest() throws InterruptedException {
// int numberOfPeers = 5;
//
// PeerOwner[] peers = new PeerOwner[numberOfPeers];
//
// for(int i = 0; i < numberOfPeers; i++) {
// peers[i] = new PeerOwner();
// peers[i].start(4003+i);
// peers[i].bootstrap(bootstrapAddress, bootstrapPort);
// }
//
// while(bootstrapNode.getNeighbours().size() < 5) {
// Thread.sleep(1000);
// }
//
// for(int i = 0; i < numberOfPeers; i++) {
// peers[i].stop();
// }
//
// while (bootstrapNode.getOldNeighbours().size() < 5) {
// Thread.sleep(1000);
// }
// }
}