Skip to content
Snippets Groups Projects
Commit 5d978b03 authored by Robin Oppermann's avatar Robin Oppermann
Browse files

Merge branch 'feature-#464-adapt-prophet' into 'master'

Adapt PRoPHET

See merge request !145
parents 43212622 5291b106
No related branches found
No related tags found
1 merge request!145Adapt PRoPHET
Pipeline #
Showing
with 452 additions and 57 deletions
# Add this file as argument if you want to use ProphetRouter
Group.router = ProphetRouter
ProphetRouter.secondsInTimeUnit = 30
\ No newline at end of file
......@@ -12,6 +12,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import core.DataMessage;
import core.MulticastMessage;
import routing.util.DatabaseApplicationUtil;
import routing.util.RoutingInfo;
import util.Tuple;
......@@ -55,7 +58,7 @@ public class ProphetRouter extends ActiveRouter {
private double beta;
/** delivery predictabilities */
private Map<DTNHost, Double> preds;
private Map<Integer, Double> preds;
/** last delivery predictability update (sim)time */
private double lastAgeUpdate;
......@@ -93,7 +96,7 @@ public class ProphetRouter extends ActiveRouter {
* Initializes predictability hash
*/
private void initPreds() {
this.preds = new HashMap<DTNHost, Double>();
this.preds = new HashMap<>();
}
@Override
......@@ -115,7 +118,43 @@ public class ProphetRouter extends ActiveRouter {
private void updateDeliveryPredFor(DTNHost host) {
double oldValue = getPredFor(host);
double newValue = oldValue + (1 - oldValue) * P_INIT;
preds.put(host, newValue);
preds.put(host.getAddress(), newValue);
}
/**
* Returns the current prediction (P) value for a message or 0 if no entry for any recipient exists.
* @param message Message to find P for. Either a one-to-one message or a multicast.
* @return The current P value. In case of multicast, the maximum P value of remaining recipients.
*/
private double getPredFor(Message message) {
switch (message.getType()) {
case ONE_TO_ONE:
return this.getPredFor(message.getTo());
case MULTICAST:
MulticastMessage multicast = (MulticastMessage)message;
return this.getMaxPredFor(multicast.getRemainingRecipients());
default:
throw new IllegalArgumentException(
"No delivery predictability for messages of type " + message.getType() + " defined!");
}
}
/**
* Returns the maximum prediction (P) value for all hosts matching the provided addresses. If no such P values
* exist, returns 0.
* @param addresses The addresses to check.
* @return The maximum P value.
*/
private double getMaxPredFor(Collection<Integer> addresses) {
// Make sure preds are updated once before getting.
this.ageDeliveryPreds();
double maxPred = 0;
for (int address : addresses) {
double predForAddress = this.preds.getOrDefault(address, 0D);
maxPred = Math.max(maxPred, predForAddress);
}
return maxPred;
}
/**
......@@ -125,13 +164,19 @@ public class ProphetRouter extends ActiveRouter {
* @return the current P value
*/
public double getPredFor(DTNHost host) {
ageDeliveryPreds(); // make sure preds are updated before getting
if (preds.containsKey(host)) {
return preds.get(host);
}
else {
return 0;
return this.getPredFor(host.getAddress());
}
/**
* Returns the current prediction (P) value for a host address or 0 if entry for
* the host doesn't exist.
* @param address The host address to look the P for
* @return the current P value
*/
private double getPredFor(Integer address) {
// make sure preds are updated before getting
this.ageDeliveryPreds();
return preds.getOrDefault(address, 0D);
}
/**
......@@ -146,11 +191,11 @@ public class ProphetRouter extends ActiveRouter {
" with other routers of same type";
double pForHost = getPredFor(host); // P(a,b)
Map<DTNHost, Double> othersPreds =
Map<Integer, Double> othersPreds =
((ProphetRouter)otherRouter).getDeliveryPreds();
for (Map.Entry<DTNHost, Double> e : othersPreds.entrySet()) {
if (e.getKey() == getHost()) {
for (Map.Entry<Integer, Double> e : othersPreds.entrySet()) {
if (e.getKey().equals(getHost().getAddress())) {
continue; // don't add yourself
}
......@@ -175,7 +220,7 @@ public class ProphetRouter extends ActiveRouter {
}
double mult = Math.pow(GAMMA, timeDiff);
for (Map.Entry<DTNHost, Double> e : preds.entrySet()) {
for (Map.Entry<Integer, Double> e : preds.entrySet()) {
e.setValue(e.getValue()*mult);
}
......@@ -186,7 +231,7 @@ public class ProphetRouter extends ActiveRouter {
* Returns a map of this router's delivery predictions
* @return a map of this router's delivery predictions
*/
private Map<DTNHost, Double> getDeliveryPreds() {
private Map<Integer, Double> getDeliveryPreds() {
ageDeliveryPreds(); // make sure the aging is done
return this.preds;
}
......@@ -206,6 +251,16 @@ public class ProphetRouter extends ActiveRouter {
tryOtherMessages();
}
/**
* Checks whether this router has anything to send out.
*
* @return Whether or not the router has anything to send out.
*/
@Override
protected boolean hasNothingToSend() {
return DatabaseApplicationUtil.hasNoMessagesToSend(this);
}
/**
* Tries to send all other messages to all connected hosts ordered by
* their delivery probability
......@@ -219,6 +274,7 @@ public class ProphetRouter extends ActiveRouter {
/* for all connected hosts collect all messages that have a higher
probability of delivery by the other host */
List<Connection> availableConnections = new ArrayList<>();
for (Connection con : getConnections()) {
DTNHost other = con.getOtherNode(getHost());
ProphetRouter othRouter = (ProphetRouter)other.getRouter();
......@@ -226,18 +282,23 @@ public class ProphetRouter extends ActiveRouter {
if (othRouter.isTransferring()) {
continue; // skip hosts that are transferring
}
availableConnections.add(con);
for (Message m : msgCollection) {
if (othRouter.hasMessage(m.getId())) {
continue; // skip messages that the other one has
}
if (othRouter.getPredFor(m.getTo()) > getPredFor(m.getTo())) {
if (othRouter.getPredFor(m) > getPredFor(m)) {
// the other node has higher probability of delivery
messages.add(new Tuple<Message, Connection>(m,con));
}
}
}
/* For all available connections, add useful data messages. */
messages.addAll(DatabaseApplicationUtil.wrapUsefulDataIntoMessages(
this, this.getHost(), availableConnections));
if (messages.size() == 0) {
return null;
}
......@@ -248,35 +309,42 @@ public class ProphetRouter extends ActiveRouter {
}
/**
* Comparator for Message-Connection-Tuples that orders the tuples by
* their delivery probability by the host on the other side of the
* connection (GRTRMax)
* Comparator for Message-Connection-Tuples that orders the tuples by the utility computed by
* {@link #computeUtility(Tuple)}, higher utilities first.
*/
private class TupleComparator implements Comparator
<Tuple<Message, Connection>> {
public int compare(Tuple<Message, Connection> tuple1,
Tuple<Message, Connection> tuple2) {
// delivery probability of tuple1's message with tuple1's connection
double p1 = ((ProphetRouter)tuple1.getValue().
getOtherNode(getHost()).getRouter()).getPredFor(
tuple1.getKey().getTo());
// -"- tuple2...
double p2 = ((ProphetRouter)tuple2.getValue().
getOtherNode(getHost()).getRouter()).getPredFor(
tuple2.getKey().getTo());
// bigger probability should come first
if (p2-p1 == 0) {
/* equal probabilities -> let queue mode decide */
double utility1 = this.computeUtility(tuple1);
double utility2 = this.computeUtility(tuple2);
// bigger utility should come first
int utilityComparison = (-1) * Double.compare(utility1, utility2);
if (utilityComparison == 0) {
/* equal utilities -> let queue mode decide */
return compareByQueueMode(tuple1.getKey(), tuple2.getKey());
}
else if (p2-p1 < 0) {
return -1;
return utilityComparison;
}
else {
return 1;
/**
* Computes a utility value for a Message-Connection tuple. This is
* - either the delivery probability by the host on the other side of the connection (GRTRMax) if the message is
* not a data message, or
* - the data message's utility.
* @param tuple Tuple to compute utility for.
* @return The tuple's utility.
*/
private double computeUtility(Tuple<Message, Connection> tuple) {
Message message = tuple.getKey();
if (message instanceof DataMessage) {
return ((DataMessage) message).getUtility();
}
DTNHost neighbor = tuple.getValue().getOtherNode(getHost());
return ((ProphetRouter)neighbor.getRouter()).getPredFor(message);
}
}
......@@ -287,12 +355,12 @@ public class ProphetRouter extends ActiveRouter {
RoutingInfo ri = new RoutingInfo(preds.size() +
" delivery prediction(s)");
for (Map.Entry<DTNHost, Double> e : preds.entrySet()) {
DTNHost host = e.getKey();
for (Map.Entry<Integer, Double> e : preds.entrySet()) {
Integer hostAddress = e.getKey();
Double value = e.getValue();
ri.addMoreInfo(new RoutingInfo(String.format("%s : %.6f",
host, value)));
hostAddress, value)));
}
top.addMoreInfo(ri);
......
package test;
import core.Group;
import core.SimClock;
import org.junit.After;
import org.junit.Before;
......@@ -53,6 +54,16 @@ public abstract class AbstractReportTest {
this.outputFile.delete();
}
@After
public void resetGroups() {
Group.clearGroups();
}
@After
public void resetSimClock() {
SimClock.reset();
}
/**
* Checks that the report correctly handles the warm up time as set by the {@link Report#WARMUP_S} setting.
*/
......
......@@ -84,6 +84,7 @@ public abstract class AbstractRouterTest extends TestCase {
protected void tearDown() throws Exception {
super.tearDown();
Settings.init(null);
SimClock.reset();
}
protected void setRouterProto(MessageRouter r) {
......
......@@ -24,6 +24,11 @@ public class ActivenessHandlerTest extends TestCase {
moreTimes);
ah = new ActivenessHandler(ts);
clock = SimClock.getInstance();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
SimClock.reset();
}
......
......@@ -32,7 +32,6 @@ public class ConnectionTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
SimClock.reset();
clock.setTime(START_TIME);
TestSettings testSettings = new TestSettings();
testSettings.setNameSpace(TestUtils.IFACE_NS);
......@@ -65,6 +64,12 @@ public class ConnectionTest extends TestCase {
conCount = 3;
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
SimClock.reset();
}
private void con(DTNHost from, DTNHost to) {
c[index] = new CBRConnection(from, from.getInterfaces().get(0), to, to.getInterfaces().get(0), speed[index]);
index++;
......
......@@ -72,6 +72,12 @@ public class ContactTimesReportTest extends TestCase {
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
SimClock.reset();
}
private void generateConnections(TestUtils utils) {
Coord c1 = new Coord(0,0);
Coord c2 = new Coord(1,0);
......
......@@ -44,6 +44,12 @@ public class DistanceDelayReportTest extends TestCase {
this.utils = new TestUtils(null, ml, ts);
}
@Override
protected void tearDown() throws Exception{
super.tearDown();
SimClock.reset();
}
@Test
public void testMessageTransferred() throws IOException {
DTNHost h1 = utils.createHost(new Coord(0,0));
......
......@@ -79,6 +79,12 @@ public class ExternalMovementTest extends TestCase {
clock.setTime(0);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
SimClock.reset();
}
public void testMovement() throws Exception {
setUpUsing(INPUT);
......
......@@ -5,7 +5,7 @@ import core.DTNHost;
import core.Group;
import core.MessageListener;
import junit.framework.TestCase;
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import java.util.ArrayList;
......@@ -21,8 +21,8 @@ public class GroupTest {
private TestUtils utils = new TestUtils(new ArrayList<ConnectionListener>(),
new ArrayList<MessageListener>(), new TestSettings());
@Before
public void setUp(){
@After
public void tearDown(){
Group.clearGroups();
DTNHost.reset();
}
......
......@@ -86,11 +86,12 @@ public class ImmediateMessageDelayReportTest extends AbstractReportTest {
}
/**
* Resets the clock to 0.
* Resets the clock to 0 and clears all groups.
*/
@After
public void resetClock() {
public void tearDown() {
this.clock.setTime(0);
Group.clearGroups();
}
/***
......
......@@ -8,6 +8,7 @@ import core.Group;
import core.Message;
import core.MessageListener;
import core.MulticastMessage;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
......@@ -47,7 +48,6 @@ public class MessageRouterTest {
@Before
public void setUp() {
Group.clearGroups();
TestSettings ts = new TestSettings();
ts.putSetting(MessageRouter.B_SIZE_S, ""+BUFFER_SIZE);
List<MessageListener> mListener = new ArrayList<>(1);
......@@ -69,6 +69,11 @@ public class MessageRouterTest {
this.multicast = new MulticastMessage(sender, g,"G",DEFAULT_MESSAGE_SIZE);
}
@After
public void tearDown() {
Group.clearGroups();
}
@Test
public void testMessageTransferredForNonRecipientPutsMessageIntoBufferButNotIntoDelivered() {
DTNHost nonRecipient = this.utils.createHost();
......
......@@ -41,7 +41,6 @@ public class MessageStatsReportTest {
public void init() throws IOException{
SimScenario.reset();
DTNHost.reset();
Group.clearGroups();
Settings.init(null);
java.util.Locale.setDefault(java.util.Locale.US);
......@@ -68,6 +67,7 @@ public class MessageStatsReportTest {
// Cleanup to make further tests with other settings possible.
SimScenario.reset();
DTNHost.reset();
Group.clearGroups();
}
private void playScenario() {
......
......@@ -48,6 +48,12 @@ public class MessageTest extends TestCase {
msg.setTtl(10);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
SimClock.reset();
}
@Test
public void testGetTtl() {
assertEquals(10, msg.getTtl());
......
......@@ -8,6 +8,7 @@ import core.DisasterData;
import core.Group;
import core.Message;
import core.MulticastMessage;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import routing.util.MessageTransferAcceptPolicy;
......@@ -53,7 +54,6 @@ public class MessageTransferAcceptPolicyTest {
@Before
public void init() {
Group.clearGroups();
DTNHost.reset();
this.settings = new TestSettings();
TestUtils utils = new TestUtils(
......@@ -83,6 +83,11 @@ public class MessageTransferAcceptPolicyTest {
this.setAcceptableRecipientAddress(this.recipient.getAddress());
}
@After
public void tearDown() {
Group.clearGroups();
}
@Test
public void testAcceptSendingReturnsTrueForMessageAdheringToSimplePolicies() {
MessageTransferAcceptPolicy policy = new MessageTransferAcceptPolicy(this.settings);
......
......@@ -6,6 +6,7 @@ import core.Message;
import core.MulticastMessage;
import input.ExternalEvent;
import input.MulticastCreateEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -20,11 +21,15 @@ public class MulticastCreateEventTest extends AbstractMessageCreateEventTest {
@Before
public void createGroup(){
Group.clearGroups();
Group g = Group.createGroup(0);
g.addHost(creator);
}
@After
public void tearDown() {
Group.clearGroups();
}
@Test
public void testProcessEventCreatesMulticastMessageWithCorrectGroupAddress() {
int groupAddress = 0;
......
......@@ -68,8 +68,6 @@ public class MulticastDeliveryReportTest extends AbstractReportTest {
// Let base do the basic report setup.
super.setUp();
Group.clearGroups();
// Set clock to 0.
this.clock.setTime(0);
......@@ -84,8 +82,9 @@ public class MulticastDeliveryReportTest extends AbstractReportTest {
}
@After
public void resetClock(){
public void tearDown(){
clock.setTime(0);
Group.clearGroups();
}
@Test
......
......@@ -8,6 +8,7 @@ import core.SimScenario;
import input.AbstractMessageEventGenerator;
import input.MulticastCreateEvent;
import input.MulticastEventGenerator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -34,7 +35,6 @@ public class MulticastEventGeneratorTest extends AbstractMessageEventGeneratorTe
public void init(){
super.init();
SimScenario.reset();
Group.clearGroups();
DTNHost.reset();
TestSettings.addSettingsToEnableSimScenario(this.settings);
......@@ -52,6 +52,11 @@ public class MulticastEventGeneratorTest extends AbstractMessageEventGeneratorTe
settings.putSetting(MulticastEventGenerator.GROUP_SIZE_RANGE_S,MIN_GROUP_SIZE+", "+MAX_GROUP_SIZE);
}
@After
public void tearDown() {
Group.clearGroups();
}
@Test
public void testNextEventCreatesMulticastMessages() {
AbstractMessageEventGenerator generator = new MulticastEventGenerator(this.settings);
......
......@@ -7,6 +7,7 @@ import core.Message;
import core.MessageListener;
import core.MulticastMessage;
import core.SimError;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
......@@ -48,13 +49,17 @@ public class MulticastMessageTest {
@Before
public void setUp() {
Group.clearGroups();
this.group1 = Group.createGroup(GROUP_ADDRESS_1);
this.group1.addHost(from);
msg = new MulticastMessage(from, this.group1, "M", MESSAGE_SIZE);
msgPrio = new MulticastMessage(from, this.group1, "N", MESSAGE_SIZE, PRIORITY);
}
@After
public void tearDown() {
Group.clearGroups();
}
@Test(expected = java.lang.UnsupportedOperationException.class)
public void testGetToThrowsException() {
this.msg.getTo();
......
......@@ -4,11 +4,23 @@
*/
package test;
import applications.DatabaseApplication;
import core.BroadcastMessage;
import core.Coord;
import core.DTNHost;
import core.DisasterData;
import core.Group;
import core.MulticastMessage;
import core.SimClock;
import org.junit.Assert;
import org.junit.Test;
import routing.MessageRouter;
import routing.ProphetRouter;
import core.Message;
import java.util.Arrays;
import java.util.HashSet;
/**
* Tests for PRoPHET router
*/
......@@ -16,15 +28,32 @@ public class ProphetRouterTest extends AbstractRouterTest {
private static int SECONDS_IN_TIME_UNIT = 60;
private static final double ONE_HOUR = 60 * 60D;
private static final double ONE_DAY = 24 * ONE_HOUR;
private static final double ONE_WEEK = 7 * ONE_DAY;
private static final Coord FAR_AWAY_LOCATION = new Coord(30_000, 40_000);
@Override
public void setUp() throws Exception {
ts.putSetting(MessageRouter.B_SIZE_S, ""+BUFFER_SIZE);
ts.putSetting(ProphetRouter.PROPHET_NS + "." +
ProphetRouter.SECONDS_IN_UNIT_S , SECONDS_IN_TIME_UNIT+"");
setRouterProto(new ProphetRouter(ts));
DatabaseApplicationTest.addDatabaseApplicationSettings(ts);
super.setUp();
}
/**
* Tears down the fixture, for example, close a network connection.
* This method is called after a test is executed.
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
Group.clearGroups();
}
/**
* Tests normal routing
*/
......@@ -122,6 +151,173 @@ public class ProphetRouterTest extends AbstractRouterTest {
}
/**
* Checks that {@link ProphetRouter} correctly sorts direct messages, broadcasts, non-direct one-to-one messages,
* direct and non-direct multicasts, and data messages.
*/
public void testPrioritization() {
// Create groups for multicasts.
Group directGroup = ProphetRouterTest.createGroup(0, this.h1, this.h2);
Group indirectGroup = ProphetRouterTest.createGroup(1, this.h1, this.h3, this.h4);
// Create all kinds of messages.
Message broadcast = new BroadcastMessage(this.h1, "B1", 0);
Message directMessage = new Message(this.h1, this.h2, "M1", 0);
Message nonDirectMessage = new Message(this.h1, this.h3, "M2", 0);
Message nonDirectMessage2 = new Message(this.h1, this.h5, "M3", 0);
Message directMulticast = new MulticastMessage(this.h1, directGroup, "m1", 0);
Message indirectMulticast = new MulticastMessage(this.h1, indirectGroup, "m2", 0);
this.h1.createNewMessage(broadcast);
this.h1.createNewMessage(directMessage);
this.h1.createNewMessage(nonDirectMessage);
this.h1.createNewMessage(nonDirectMessage2);
this.h1.createNewMessage(directMulticast);
this.h1.createNewMessage(indirectMulticast);
// Add data for data message.
this.clock.advance(ONE_DAY);
DisasterData data =
new DisasterData(DisasterData.DataType.MARKER, 0, 0, this.h1.getLocation());
DatabaseApplication app = this.createDatabaseApplicationFor(this.h1);
app.disasterDataCreated(h1, data);
// Modify utilities for testing:
// First, increase delivery predictability H2 --> H5, then advance clock to lower it again.
this.h2.connect(this.h5);
this.clock.advance(ONE_HOUR);
// Then, do the same for delivery predictability H2 --> H4.
this.h2.connect(this.h4);
this.clock.advance(ONE_HOUR);
// Finally, make sure the delivery predictability H2 --> H3 is high
this.h2.connect(this.h3);
disconnect(this.h2);
// And ensure that the multicast message was already delivered to H3.
ProphetRouterTest.addNodeOnPath(this.h1, indirectMulticast.getId(), this.h3);
// Connect h1 to h2.
this.h1.connect(this.h2);
// Check order of messages: First direct messages, then sorted by predictability / data utility
// Direct messages are pseudo-randomly sorted, so you might have to change the order if changing the clock.
String dataMessageId = "D" + Arrays.asList(data).hashCode();
String[] idsInExpectedOrder = {
broadcast.getId(), directMessage.getId(), directMulticast.getId(),
nonDirectMessage.getId(), dataMessageId, indirectMulticast.getId(), nonDirectMessage2.getId()
};
this.checkMessagesAreSentInOrder(idsInExpectedOrder);
}
/**
* Checks that {@link ProphetRouter} sends {@link core.DataMessage}s wrapping useful data, but data with too low
* utility is not sent.
*/
public void testUsefulDataGetsExchanged() {
// Add data.
DatabaseApplication app = this.createDatabaseApplicationFor(this.h1);
this.clock.advance(ONE_WEEK);
this.h1.setLocation(FAR_AWAY_LOCATION);
DisasterData uselessData = new DisasterData(DisasterData.DataType.MARKER, 0, 0, new Coord(0, 0));
DisasterData usefulData =
new DisasterData(DisasterData.DataType.MARKER, 0, SimClock.getTime(), this.h1.getLocation());
app.disasterDataCreated(this.h1, uselessData);
app.disasterDataCreated(this.h1, usefulData);
// Check that H1 only sends the useful data item to H2.
this.h1.connect(this.h2);
this.mc.reset();
h1.update(false);
do {
this.mc.next();
} while (!this.mc.TYPE_START.equals(this.mc.getLastType()));
Assert.assertEquals(
"Expected the useful data item to be sent.",
"D" + Arrays.asList(usefulData).hashCode(), mc.getLastMsg().getId());
Assert.assertFalse("Did not expect any additional message.", this.mc.next());
}
/**
* Checks that both one-to-one messages and multicast messages are only transferred to a neighbor if those messages
* have higher delivery predictability at the neighbor than at the current host.
*/
public void testMessagesAreOnlyTransferredToHostsWithHigherPredictability() {
// Make sure H1 has higher delivery predictability for H3, while H2 has higher delivery predictability for H4.
// First, increase delivery predictability H1 --> H4, then advance clock to lower it again.
this.h1.connect(this.h4);
this.clock.advance(ONE_HOUR);
// Then set high delivery predictabilities for H1 --> H3 and H2 --> H4.
this.h1.connect(this.h3);
this.h2.connect(this.h4);
disconnect(this.h1);
disconnect(this.h2);
// Create group including both H3 and H4.
Group group = ProphetRouterTest.createGroup(0, this.h1, this.h3, this.h4);
// Create multicasts and one to one messages to H3 and H4.
Message messageToH3 = new Message(this.h1, this.h3, "M1", 0);
Message messageToH4 = new Message(this.h1, this.h4, "M2", 0);
Message receivedMulticast = new MulticastMessage(this.h1, group, "m1", 0);
Message newMulticast = new MulticastMessage(this.h1, group, "m2", 0);
this.h1.createNewMessage(messageToH3);
this.h1.createNewMessage(messageToH4);
this.h1.createNewMessage(receivedMulticast);
this.h1.createNewMessage(newMulticast);
// Ensure that one of the multicast messages was already delivered to H4.
ProphetRouterTest.addNodeOnPath(this.h1, receivedMulticast.getId(), this.h4);
// Connect h1 to h2.
this.h1.connect(this.h2);
// Check that only half of the messages are transferred
HashSet<String> sentIds = new HashSet<>();
this.mc.reset();
this.h1.update(true);
while (this.mc.next()) {
sentIds.add(this.mc.getLastMsg().getId());
this.h1.update(true);
}
HashSet<String> expectedIds = new HashSet<>(2);
expectedIds.add(messageToH4.getId());
expectedIds.add(newMulticast.getId());
assertEquals("Expected different message set to be sent.", sentIds, expectedIds);
}
/**
* Checks that a host does not send out new messages to hosts which are already transferring.
*/
public void testNoMessagesAreReceivedWhenAlreadyTransferring() {
// Let h2 be transferring.
this.h2.connect(this.h3);
Message m1 = new Message(this.h2, this.h3, "M1", 1);
this.h2.createNewMessage(m1);
this.updateAllNodes();
// Check the transfer started.
this.mc.next();
this.checkTransferStart(this.h2, this.h3, m1.getId());
// Let h1 try to send a message to h2 now.
Message m2 = new Message(this.h1, this.h2, "M2", 0);
this.h1.createNewMessage(m2);
this.h1.connect(this.h2);
this.updateAllNodes();
// Check that the new message was not sent.
while(this.mc.next()) {
Assert.assertNotEquals("Did not expect another transfer.", this.mc.TYPE_START, this.mc.getLastType());
}
// Finally, check that the original message will still be transferred.
this.clock.advance(1);
this.updateAllNodes();
this.mc.next();
Assert.assertEquals(
"Original message should have been processed next.", m1.getId(), this.mc.getLastMsg().getId());
Assert.assertEquals(
"Original message should have been transferred.", this.mc.TYPE_RELAY, this.mc.getLastType());
}
private void doRelay() {
clock.advance(10);
updateAllNodes();
......@@ -153,4 +349,60 @@ public class ProphetRouterTest extends AbstractRouterTest {
assertEquals(newPred, r5.getPredFor(h4));
}
/**
* Observes which messages are sent by {@link #h1} and checks they match the provided IDs.
* @param idsInExpectedOrder The expected message IDs in expected order.
*/
private void checkMessagesAreSentInOrder(String[] idsInExpectedOrder) {
this.mc.reset();
for (String expectedId : idsInExpectedOrder) {
this.h1.update(true);
do {
this.mc.next();
} while (!this.mc.TYPE_START.equals(this.mc.getLastType()));
Assert.assertEquals("Expected different message.", expectedId, mc.getLastMsg().getId());
}
}
/**
* Creates a group using the provided number as address.
* All provided hosts will be part of the group.
* @param address The new group's address.
* @param hosts The hosts in the new group.
* @return The created group.
*/
private static Group createGroup(int address, DTNHost... hosts) {
Group group = Group.createGroup(address);
for (DTNHost host : hosts) {
group.addHost(host);
}
return group;
}
/**
* Creates and initializes a {@link DatabaseApplication} for the provided {@link DTNHost}.
* @param host Host to create the application for.
* @return The created application.
*/
private DatabaseApplication createDatabaseApplicationFor(DTNHost host) {
DatabaseApplication app = new DatabaseApplication(this.ts);
host.getRouter().addApplication(app);
app.update(host);
return app;
}
/**
* Changes the meta data of the message with provided ID in the buffer of the provided host by adding the provided
* node to path.
* @param bufferToChange The host in which buffer the message should be changed.
* @param messageId The message's ID.
* @param node The host to add to path.
*/
private static void addNodeOnPath(DTNHost bufferToChange, String messageId, DTNHost node) {
for (Message m : bufferToChange.getMessageCollection()) {
if (m.getId().equals(messageId)) {
m.addNodeOnPath(node);
}
}
}
}
  • Contributor

    SonarQube analysis reported 1 issue

    • 1 major
    1. Remove this unused private "getMaxPredFor" method. 📘
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment