m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2020-01-09 18:16:28 +0100
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2020-01-09 18:16:28 +0100
commit4ba7fa9be088650dc32dbabaa1ef2ea47681ec81 (patch)
treeb503340909c3202bd1ee11ff05cd199082547bd7 /src
parentce76dbc406da1a8fe839b1e311ed699f9d5c7498 (diff)
Test gossip initialization
Diffstat (limited to 'src')
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirl.java13
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlState.java55
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlTest.java114
3 files changed, 168 insertions, 14 deletions
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirl.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirl.java
index 01119bf..ccc7ee5 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirl.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirl.java
@@ -69,8 +69,8 @@ public class GossipGirl extends Module {
"",
0,
state.gossipId,
- getZoneTimestamps(message.getZMI()),
- getQueryTimestamps(message.getQueries())
+ state.getZoneTimestampsToSend(),
+ state.getQueryTimestampsToSend()
);
UDUPMessage udupMessage = new UDUPMessage("", 0, state.theirContact, hejka);
sendMessage(udupMessage);
@@ -96,13 +96,4 @@ public class GossipGirl extends Module {
System.out.println("ERROR: GossipGirl got state for a nonexistent gossip");
}
}
-
- public Map<PathName, ValueTime> getZoneTimestamps(ZMI root) {
- return new HashMap();
- }
-
- public Map<Attribute, ValueTime> getQueryTimestamps(Map<Attribute, Entry<ValueQuery, ValueTime>> queries) {
- return new HashMap();
- }
-
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlState.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlState.java
index 726a9b2..8ec8ed2 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlState.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlState.java
@@ -1,5 +1,7 @@
package pl.edu.mimuw.cloudatlas.agent.modules;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -95,10 +97,63 @@ public class GossipGirlState {
}
}
+ public Map<PathName, ValueTime> getZoneTimestampsToSend() {
+ Map<PathName, ValueTime> timestamps = new HashMap();
+ collectZoneTimestamps(timestamps, hierarchy, theirContact.getName());
+ return timestamps;
+ }
+
+ public Map<Attribute, ValueTime> getQueryTimestampsToSend() {
+ Map<Attribute, ValueTime> queryTimestamps= new HashMap();
+ for (Entry<Attribute, Entry<ValueQuery, ValueTime>> query : queries.entrySet()) {
+ queryTimestamps.put(query.getKey(), query.getValue().getValue());
+ }
+
+ return queryTimestamps;
+ }
+
public List<ZMI> getZMIsToSend() {
return new LinkedList();
}
+ public void collectZoneTimestamps(Map<PathName, ValueTime> timestamps, ZMI currentZMI, PathName recipientPath) {
+ for (ZMI zmi : currentZMI.getSons()) {
+ if (interestedIn(recipientPath, zmi.getPathName())) {
+ ValueTime timestamp = (ValueTime) zmi.getAttributes().getOrNull("timestamp");
+ if (timestamp != null) {
+ timestamps.put(zmi.getPathName(), timestamp);
+ } else {
+ System.out.println("ERROR: collectZoneTimestamps encountered a zone with no timestamp");
+ }
+ } else {
+ collectZoneTimestamps(timestamps, zmi, recipientPath);
+ }
+ }
+ }
+
+ public boolean interestedIn(PathName recipientPath, PathName zmiPath) {
+ return isPrefix(zmiPath.levelUp(), recipientPath) && !isPrefix(zmiPath, recipientPath);
+ }
+
+ public boolean isPrefix(PathName prefix, PathName path) {
+ List<String> prefixComponents = prefix.getComponents();
+ List<String> pathComponents = path.getComponents();
+
+ if (prefixComponents.size() > pathComponents.size()) {
+ return false;
+ }
+
+ Iterator<String> prefixIterator = prefixComponents.iterator();
+ Iterator<String> pathIterator = pathComponents.iterator();
+
+ while (prefixIterator.hasNext()) {
+ if (!prefixIterator.next().equals(pathIterator.next())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public void sentInfo() {
switch (state) {
case SEND_INFO:
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlTest.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlTest.java
index 0658b65..1d6496c 100644
--- a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlTest.java
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/GossipGirlTest.java
@@ -3,28 +3,109 @@ package pl.edu.mimuw.cloudatlas.agent.modules;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.hasItems;
+
+import java.net.InetAddress;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
import pl.edu.mimuw.cloudatlas.agent.MockExecutor;
import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.HejkaMessage;
import pl.edu.mimuw.cloudatlas.agent.messages.GetStateMessage;
import pl.edu.mimuw.cloudatlas.agent.messages.GossipGirlMessage;
import pl.edu.mimuw.cloudatlas.agent.messages.InitiateGossipMessage;
import pl.edu.mimuw.cloudatlas.agent.messages.StanikMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.StateMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.UDUPMessage;
+import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType;
+import pl.edu.mimuw.cloudatlas.model.AttributesMap;
+import pl.edu.mimuw.cloudatlas.model.Attribute;
+import pl.edu.mimuw.cloudatlas.model.PathName;
+import pl.edu.mimuw.cloudatlas.model.TestUtil;
+import pl.edu.mimuw.cloudatlas.model.ValueContact;
+import pl.edu.mimuw.cloudatlas.model.ValueInt;
+import pl.edu.mimuw.cloudatlas.model.ValueQuery;
+import pl.edu.mimuw.cloudatlas.model.ValueString;
+import pl.edu.mimuw.cloudatlas.model.ValueTime;
+import pl.edu.mimuw.cloudatlas.model.ValueUtils;
+import pl.edu.mimuw.cloudatlas.model.ZMI;
public class GossipGirlTest {
private GossipGirl gossipGirl;
private MockExecutor executor;
+ private final PathName ourPath = new PathName("/son/grand");
+ private final PathName theirPath = new PathName("/son/bro");
+ private ValueContact theirContact;
+ private InitiateGossipMessage initiateGossipMessage;
+ private ZMI initiatorHierarchy;
+ private ValueTime testTime;
+ private Map<Attribute, Entry<ValueQuery, ValueTime>> initiatorQueries;
+ private StateMessage initiatorStateMessage;
@Before
- public void setupLocals() {
+ public void setupLocals() throws Exception {
gossipGirl = new GossipGirl();
executor = new MockExecutor(gossipGirl);
+
+ theirContact = new ValueContact(
+ theirPath,
+ InetAddress.getByAddress("localhost", new byte[] { 127, 0, 0, 1 })
+ );
+ initiateGossipMessage = new InitiateGossipMessage(
+ "test_msg",
+ 0,
+ ourPath,
+ theirContact
+ );
+
+ testTime = ValueUtils.currentTime();
+ setupHierarchy();
+ setupQueries();
+ initiatorStateMessage = new StateMessage("", ModuleType.GOSSIP, 0, 0, initiatorHierarchy, initiatorQueries);
+ }
+
+ public void setupHierarchy() {
+ initiatorHierarchy = makeZMI(null, null, 13l, "hello", testTime);
+ ZMI son = makeZMI(initiatorHierarchy, "son", 42l, "world", testTime);
+ ZMI daughter = makeZMI(initiatorHierarchy, "daughter", 24l, "kebab", testTime);
+ ZMI grand = makeZMI(son, "grand", 1337l, "ok", testTime);
+ ZMI bro = makeZMI(son, "bro", 3451434l, "whazzup", testTime);
+ ZMI sis = makeZMI(son, "sis", 420l, "hey", testTime);
+ }
+
+ public void setupQueries() throws Exception {
+ initiatorQueries = new HashMap();
+ addQuery(initiatorQueries, "&one", "SELECT 1 AS one", testTime);
+ addQuery(initiatorQueries, "&query", "SELECT sum(foo) AS foo", testTime);
+ }
+
+ public void addQuery(Map<Attribute, Entry<ValueQuery, ValueTime>> queries, String name, String query, ValueTime timestamp) throws Exception {
+ queries.put(
+ new Attribute(name),
+ new SimpleImmutableEntry(new ValueQuery(query), timestamp)
+ );
+ }
+
+ private ZMI makeZMI(ZMI parent, String name, Long foo, String bar, ValueTime timestamp) {
+ ZMI zmi = new ZMI(parent);
+ if (parent != null) {
+ parent.addSon(zmi);
+ }
+ AttributesMap attributes = zmi.getAttributes();
+ attributes.add("name", new ValueString(name));
+ attributes.add("foo", new ValueInt(foo));
+ attributes.add("bar", new ValueString(bar));
+ attributes.add("timestamp", timestamp);
+ return zmi;
}
@Test
public void initiateGossipRequestsState() throws Exception {
- InitiateGossipMessage message = new InitiateGossipMessage("test_msg", 0);
- gossipGirl.handleTyped(message);
+ gossipGirl.handleTyped(initiateGossipMessage);
AgentMessage receivedMessage = executor.messagesToPass.poll();
assertNotNull(receivedMessage);
@@ -34,4 +115,31 @@ public class GossipGirlTest {
GetStateMessage getStateMessage = (GetStateMessage) stanikMessage;
assertEquals(ModuleType.GOSSIP, getStateMessage.getRequestingModule());
}
+
+ @Test
+ public void initiatorSendsHejkaOnState() throws Exception {
+ gossipGirl.handleTyped(initiateGossipMessage);
+ executor.messagesToPass.take();
+ gossipGirl.handleTyped(initiatorStateMessage);
+
+ AgentMessage receivedMessage = executor.messagesToPass.poll();
+ assertNotNull(receivedMessage);
+ assertEquals(ModuleType.UDP, receivedMessage.getDestinationModule());
+ UDUPMessage udupMessage = (UDUPMessage) receivedMessage;
+ assertEquals(new PathName("/son/bro"), udupMessage.getContact().getName());
+ assertEquals(ModuleType.GOSSIP, udupMessage.getContent().getDestinationModule());
+ GossipGirlMessage gossipMessage = (GossipGirlMessage) udupMessage.getContent();
+
+ assertEquals(GossipGirlMessage.Type.HEJKA, gossipMessage.getType());
+ HejkaMessage hejkaMessage = (HejkaMessage) gossipMessage;
+ assertEquals(0, hejkaMessage.getSenderGossipId());
+ System.out.println(hejkaMessage.getZoneTimestamps().keySet());
+ assertEquals(3, TestUtil.iterableSize(hejkaMessage.getZoneTimestamps().keySet()));
+ Set<PathName> zoneSet = hejkaMessage.getZoneTimestamps().keySet();
+ assertThat(zoneSet, hasItems(new PathName("/daughter")));
+ assertThat(zoneSet, hasItems(new PathName("/son/sis")));
+ assertThat(zoneSet, hasItems(new PathName("/son/grand")));
+
+ assertEquals(2, TestUtil.iterableSize(hejkaMessage.getQueryTimestamps().keySet()));
+ }
}