From afa32431d242d60471e5431d654784ee64b63bbf Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 27 Dec 2019 11:28:46 +0100 Subject: Begin Stanik impelementation * Get cloned hierarchy * Test on empty hierarchy --- .../agent/messages/GetHierarchyMessage.java | 22 ++++++++++ .../agent/messages/HierarchyMessage.java | 17 ++++++++ .../cloudatlas/agent/messages/ResponseMessage.java | 31 ++++++++++++++ .../cloudatlas/agent/messages/StanikMessage.java | 25 +++++++++++ .../edu/mimuw/cloudatlas/agent/modules/Module.java | 10 +++++ .../mimuw/cloudatlas/agent/modules/ModuleType.java | 4 +- .../edu/mimuw/cloudatlas/agent/modules/Stanik.java | 31 ++++++++++++++ .../edu/mimuw/cloudatlas/agent/MockExecutor.java | 24 +++++++++++ .../mimuw/cloudatlas/agent/modules/StanikTest.java | 49 ++++++++++++++++++++++ 9 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/GetHierarchyMessage.java create mode 100644 src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/HierarchyMessage.java create mode 100644 src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/ResponseMessage.java create mode 100644 src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java create mode 100644 src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java create mode 100644 src/test/java/pl/edu/mimuw/cloudatlas/agent/MockExecutor.java create mode 100644 src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/GetHierarchyMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/GetHierarchyMessage.java new file mode 100644 index 0000000..d3c749d --- /dev/null +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/GetHierarchyMessage.java @@ -0,0 +1,22 @@ +package pl.edu.mimuw.cloudatlas.agent.messages; + +import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType; + +public class GetHierarchyMessage extends StanikMessage { + private ModuleType requestingModule; + private long requestId; + + public GetHierarchyMessage(String messageId, long timestamp, ModuleType requestingModule, long requestId) { + super(messageId, timestamp, Type.GET_HIERARCHY); + this.requestingModule = requestingModule; + this.requestId = requestId; + } + + public ModuleType getRequestingModule() { + return requestingModule; + } + + public long getRequestId() { + return requestId; + } +} diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/HierarchyMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/HierarchyMessage.java new file mode 100644 index 0000000..9f7ca70 --- /dev/null +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/HierarchyMessage.java @@ -0,0 +1,17 @@ +package pl.edu.mimuw.cloudatlas.agent.messages; + +import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType; +import pl.edu.mimuw.cloudatlas.model.ZMI; + +public class HierarchyMessage extends ResponseMessage { + private ZMI zmi; + + public HierarchyMessage(String messageId, ModuleType destinationModule, long timestamp, long requestId, ZMI zmi) { + super(messageId, destinationModule, timestamp, Type.HIERARCHY, requestId); + this.zmi = zmi; + } + + public ZMI getZMI() { + return zmi; + } +} diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/ResponseMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/ResponseMessage.java new file mode 100644 index 0000000..171cf07 --- /dev/null +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/ResponseMessage.java @@ -0,0 +1,31 @@ +package pl.edu.mimuw.cloudatlas.agent.messages; + +import pl.edu.mimuw.cloudatlas.agent.modules.Module; +import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType; + +public abstract class ResponseMessage extends AgentMessage { + public enum Type { + HIERARCHY + } + + Type type; + long requestId; + + public ResponseMessage(String messageId, ModuleType destinationModule, long timestamp, Type type, long requestId) { + super(messageId, destinationModule, timestamp); + this.type = type; + this.requestId = requestId; + } + + public void callMe(Module module) throws InterruptedException, Module.InvalidMessageType { + module.handleTyped(this); + } + + public long getRequestId() { + return requestId; + } + + public Type getType() { + return type; + } +} diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java new file mode 100644 index 0000000..d2b3064 --- /dev/null +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java @@ -0,0 +1,25 @@ +package pl.edu.mimuw.cloudatlas.agent.messages; + +import pl.edu.mimuw.cloudatlas.agent.modules.Module; +import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType; + +public abstract class StanikMessage extends AgentMessage { + public enum Type { + GET_HIERARCHY + } + + private Type type; + + public StanikMessage(String messageId, long timestamp, Type type) { + super(messageId, ModuleType.STATE, timestamp); + this.type = type; + } + + public Type getType() { + return type; + } + + public void callMe(Module module) throws InterruptedException, Module.InvalidMessageType { + module.handleTyped(this); + } +} diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Module.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Module.java index a50a95f..d0bf083 100644 --- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Module.java +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Module.java @@ -3,7 +3,9 @@ package pl.edu.mimuw.cloudatlas.agent.modules; import pl.edu.mimuw.cloudatlas.agent.Executor; import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage; import pl.edu.mimuw.cloudatlas.agent.messages.TimerSchedulerMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.ResponseMessage; import pl.edu.mimuw.cloudatlas.agent.messages.RMIMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.StanikMessage; /* * A Module is a (potentially stateful) event handler. @@ -34,6 +36,14 @@ public abstract class Module { throw new InvalidMessageType("Got an RMIMessage in module " + moduleType.toString()); } + public void handleTyped(StanikMessage message) throws InterruptedException, InvalidMessageType { + throw new InvalidMessageType("Got a StanikMessage in module " + moduleType.toString()); + } + + public void handleTyped(ResponseMessage message) throws InterruptedException, InvalidMessageType { + throw new InvalidMessageType("Got a ResponseMessage in module " + moduleType.toString()); + } + public void setExecutor(Executor executor) { this.executor = executor; } diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/ModuleType.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/ModuleType.java index ff4a92e..d221f06 100644 --- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/ModuleType.java +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/ModuleType.java @@ -8,5 +8,7 @@ public enum ModuleType { GOSSIP_IN, GOSSIP_OUT, STATE, - QUERY + QUERY, + // for testing + TEST } diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java new file mode 100644 index 0000000..b8db08a --- /dev/null +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java @@ -0,0 +1,31 @@ +package pl.edu.mimuw.cloudatlas.agent.modules; + +import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.GetHierarchyMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.HierarchyMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.StanikMessage; +import pl.edu.mimuw.cloudatlas.model.ZMI; + +public class Stanik extends Module { + private ZMI hierarchy; + + public Stanik() { + super(ModuleType.STATE); + hierarchy = new ZMI(); + } + + public void handleTyped(StanikMessage message) throws InterruptedException, InvalidMessageType { + switch(message.getType()) { + case GET_HIERARCHY: + handleGetHierarchy((GetHierarchyMessage) message); + break; + default: + throw new InvalidMessageType("This type of message cannot be handled by Stanik"); + } + } + + public void handleGetHierarchy(GetHierarchyMessage message) throws InterruptedException { + HierarchyMessage response = new HierarchyMessage("", message.getRequestingModule(), 0, message.getRequestId(), hierarchy.clone()); + sendMessage(response); + } +} diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/MockExecutor.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/MockExecutor.java new file mode 100644 index 0000000..1da50ad --- /dev/null +++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/MockExecutor.java @@ -0,0 +1,24 @@ +package pl.edu.mimuw.cloudatlas.agent; + +import java.util.concurrent.LinkedBlockingQueue; + +import pl.edu.mimuw.cloudatlas.agent.modules.Module; +import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage; + +/* + * Instead of passing messages to an EventBus, this one just collects them + * locally for inspection in unit tests. + */ +public class MockExecutor extends Executor { + public LinkedBlockingQueue messagesToPass; + + public MockExecutor(Module module) { + super(module); + messagesToPass = new LinkedBlockingQueue(); + } + + @Override + public void passMessage(AgentMessage message) throws InterruptedException { + messagesToPass.put(message); + } +} diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java new file mode 100644 index 0000000..7c869e7 --- /dev/null +++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java @@ -0,0 +1,49 @@ +package pl.edu.mimuw.cloudatlas.agent.modules; + +import java.util.List; +import java.util.Map.Entry; + +import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.GetHierarchyMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.HierarchyMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.ResponseMessage; +import pl.edu.mimuw.cloudatlas.agent.MockExecutor; +import pl.edu.mimuw.cloudatlas.model.Attribute; +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ZMI; + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +public class StanikTest { + private Stanik stanik; + private MockExecutor executor; + + @Before + public void setupEventBus() { + stanik = new Stanik(); + executor = new MockExecutor(stanik); + } + + @Test + public void getEmptyHierarchy() throws Exception { + GetHierarchyMessage message = new GetHierarchyMessage("test_msg", 0, ModuleType.TEST, 42); + stanik.handleTyped(message); + assertEquals(1, executor.messagesToPass.size()); + ResponseMessage receivedMessage = (ResponseMessage) executor.messagesToPass.take(); + assertEquals(ModuleType.TEST, receivedMessage.getDestinationModule()); + assertEquals(ResponseMessage.Type.HIERARCHY, receivedMessage.getType()); + assertEquals(42, receivedMessage.getRequestId()); + HierarchyMessage hierarchyMessage = (HierarchyMessage) receivedMessage; + ZMI zmi = hierarchyMessage.getZMI(); + assertNull(zmi.getFather()); + assertTrue(zmi.getSons().isEmpty()); + boolean empty = true; + for (Entry entry : zmi.getAttributes()) { + empty = false; + break; + } + assertTrue(empty); + } +} -- cgit v1.2.3