m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2019-12-30 22:16:46 +0100
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2019-12-30 22:16:46 +0100
commitca2f1ab4a37f0d590d5c116cd1fa7c341c77fad3 (patch)
treefb3b8ff1629e5480086f43065156625985a2e034
parentfda20e7aa496926d4f4d78921925025040414d9b (diff)
Implement modular getZoneSet
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/Agent.java31
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/EventBus.java4
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java178
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RemikMessage.java (renamed from src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RMIMessage.java)15
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RequestStateMessage.java16
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Module.java6
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/RMI.java37
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Remik.java54
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java8
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/Container.java5
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementationTests.java1
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/agent/MockEventBus.java17
-rw-r--r--src/test/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementationTests.java171
13 files changed, 495 insertions, 48 deletions
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/Agent.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/Agent.java
index 392e0a1..52bd395 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/Agent.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/Agent.java
@@ -1,22 +1,45 @@
package pl.edu.mimuw.cloudatlas.agent;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+import pl.edu.mimuw.cloudatlas.agent.ApiImplementation;
import pl.edu.mimuw.cloudatlas.agent.modules.Module;
import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType;
import pl.edu.mimuw.cloudatlas.agent.modules.Qurnik;
-import pl.edu.mimuw.cloudatlas.agent.modules.RMI;
+import pl.edu.mimuw.cloudatlas.agent.modules.Remik;
import pl.edu.mimuw.cloudatlas.agent.modules.Stanik;
import pl.edu.mimuw.cloudatlas.agent.modules.TimerScheduler;
+import pl.edu.mimuw.cloudatlas.api.Api;
+import pl.edu.mimuw.cloudatlas.interpreter.Main;
+import pl.edu.mimuw.cloudatlas.model.ZMI;
public class Agent {
+ private static EventBus eventBus;
+
+ public static void runRegistry() {
+ try {
+ ZMI root = Main.createTestHierarchy2();
+ ApiImplementation api = new ApiImplementation(root);
+ Api apiStub =
+ (Api) UnicastRemoteObject.exportObject(api, 0);
+ Registry registry = LocateRegistry.getRegistry();
+ registry.rebind("Api", apiStub);
+ System.out.println("Agent: api bound");
+ } catch (Exception e) {
+ System.err.println("Agent registry initialization exception:");
+ e.printStackTrace();
+ }
+ }
public static HashMap<ModuleType, Module> initializeModules() {
HashMap<ModuleType, Module> modules = new HashMap<ModuleType, Module>();
modules.put(ModuleType.TIMER_SCHEDULER, new TimerScheduler(ModuleType.TIMER_SCHEDULER));
- modules.put(ModuleType.RMI, new RMI(ModuleType.RMI));
+ modules.put(ModuleType.RMI, new Remik());
modules.put(ModuleType.STATE, new Stanik());
modules.put(ModuleType.QUERY, new Qurnik());
// TODO add modules as we implement them
@@ -61,7 +84,8 @@ public class Agent {
HashMap<ModuleType, Executor> executors = initializeExecutors(modules);
ArrayList<Thread> executorThreads = initializeExecutorThreads(executors);
- Thread eventBusThread = new Thread(new EventBus(executors));
+ eventBus = new EventBus(executors);
+ Thread eventBusThread = new Thread(eventBus);
System.out.println("Initializing event bus");
eventBusThread.start();
@@ -71,5 +95,6 @@ public class Agent {
public static void main(String[] args) {
runModulesAsThreads();
+ runRegistry();
}
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/EventBus.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/EventBus.java
index 5b09253..a6d3b2d 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/EventBus.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/EventBus.java
@@ -20,6 +20,10 @@ public class EventBus implements Runnable {
}
}
+ // Allows for testing with a mock EventBus
+ protected EventBus() {
+ }
+
EventBus(HashMap<ModuleType, Executor> executors) {
this.executors = executors;
setEventBusReference();
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java
new file mode 100644
index 0000000..4aa5148
--- /dev/null
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java
@@ -0,0 +1,178 @@
+package pl.edu.mimuw.cloudatlas.agent;
+
+import java.io.PrintStream;
+
+import java.rmi.RemoteException;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+
+import pl.edu.mimuw.cloudatlas.agent.messages.RequestStateMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.ResponseMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.StateMessage;
+import pl.edu.mimuw.cloudatlas.interpreter.Interpreter;
+import pl.edu.mimuw.cloudatlas.interpreter.InterpreterException;
+import pl.edu.mimuw.cloudatlas.interpreter.Main;
+import pl.edu.mimuw.cloudatlas.interpreter.QueryResult;
+import pl.edu.mimuw.cloudatlas.model.Attribute;
+import pl.edu.mimuw.cloudatlas.model.AttributesMap;
+import pl.edu.mimuw.cloudatlas.model.PathName;
+import pl.edu.mimuw.cloudatlas.model.ValueContact;
+import pl.edu.mimuw.cloudatlas.model.Value;
+import pl.edu.mimuw.cloudatlas.model.ValueQuery;
+import pl.edu.mimuw.cloudatlas.model.ValueSet;
+import pl.edu.mimuw.cloudatlas.model.ValueNull;
+import pl.edu.mimuw.cloudatlas.model.Type;
+import pl.edu.mimuw.cloudatlas.model.TypePrimitive;
+import pl.edu.mimuw.cloudatlas.model.ZMI;
+import pl.edu.mimuw.cloudatlas.api.Api;
+
+public class NewApiImplementation implements Api {
+ private EventBus eventBus;
+
+ public NewApiImplementation(EventBus eventBus) {
+ this.eventBus = eventBus;
+ }
+
+ public Set<String> getZoneSet() throws RemoteException {
+ CompletableFuture<ResponseMessage> responseFuture = new CompletableFuture();
+ RequestStateMessage message = new RequestStateMessage("", 0, responseFuture);
+ try {
+ eventBus.addMessage(message);
+ ResponseMessage response = responseFuture.get();
+
+ if (response.getType() == ResponseMessage.Type.STATE) {
+ StateMessage stateMessage = (StateMessage) response;
+ Set<String> zones = new HashSet<String>();
+ collectZoneNames(stateMessage.getZMI(), zones);
+ return zones;
+ } else {
+ System.out.println("ERROR: getZoneSet didn't receive a StateMessage");
+ throw new Exception("Failed to retrieve zone set");
+ }
+ } catch (Exception e) {
+ System.out.println("ERROR: exception caught in getZoneSet");
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private void collectZoneNames(ZMI zone, Set<String> names) {
+ names.add(zone.getPathName().toString());
+ for (ZMI son : zone.getSons()) {
+ collectZoneNames(son, names);
+ }
+ }
+
+ public AttributesMap getZoneAttributeValues(String zoneName) throws RemoteException {
+ /*
+ try {
+ ZMI zmi = root.findDescendant(new PathName(zoneName));
+ return zmi.getAttributes();
+ } catch (ZMI.NoSuchZoneException e) {
+ throw new RemoteException("Zone not found", e);
+ }
+ */
+
+ // placeholder
+ return new AttributesMap();
+ }
+
+ public void installQuery(String name, String queryCode) throws RemoteException {
+ /*
+ Pattern queryNamePattern = Pattern.compile("&[a-zA-Z][\\w_]*");
+ Matcher matcher = queryNamePattern.matcher(name);
+ if (!matcher.matches()) {
+ throw new RemoteException("Invalid query identifier");
+ }
+ try {
+ ValueQuery query = new ValueQuery(queryCode);
+ Attribute attributeName = new Attribute(name);
+ installQueryInHierarchy(root, attributeName, query);
+ executeAllQueries(root);
+ } catch (Exception e) {
+ throw new RemoteException("Failed to install query", e);
+ }
+ */
+ }
+
+ private void installQueryInHierarchy(ZMI zmi, Attribute queryName, ValueQuery query) {
+ /*
+ if (!zmi.getSons().isEmpty()) {
+ zmi.getAttributes().addOrChange(queryName, query);
+ for (ZMI son : zmi.getSons()) {
+ installQueryInHierarchy(son, queryName, query);
+ }
+ }
+ */
+ }
+
+ public void uninstallQuery(String queryName) throws RemoteException {
+ // uninstallQueryInHierarchy(root, new Attribute(queryName));
+ }
+
+ private void uninstallQueryInHierarchy(ZMI zmi, Attribute queryName) {
+ /*
+ if (!zmi.getSons().isEmpty()) {
+ zmi.getAttributes().remove(queryName);
+ for (ZMI son : zmi.getSons()) {
+ uninstallQueryInHierarchy(son, queryName);
+ }
+ }
+ */
+ }
+
+ public void setAttributeValue(String zoneName, String attributeName, Value value) throws RemoteException {
+ /*
+ try {
+ ZMI zmi = root.findDescendant(new PathName(zoneName));
+ zmi.getAttributes().addOrChange(new Attribute(attributeName), value);
+ executeAllQueries(root);
+ } catch (ZMI.NoSuchZoneException e) {
+ throw new RemoteException("Zone not found", e);
+ }
+ */
+ }
+
+ private void executeAllQueries(ZMI zmi) {
+ /*
+ if(!zmi.getSons().isEmpty()) {
+ for(ZMI son : zmi.getSons()) {
+ executeAllQueries(son);
+ }
+
+ Interpreter interpreter = new Interpreter(zmi);
+ for (ValueQuery query : getQueries(zmi)) {
+ try {
+ List<QueryResult> result = interpreter.interpretProgram(query.getQuery());
+ for(QueryResult r : result) {
+ zmi.getAttributes().addOrChange(r.getName(), r.getValue());
+ }
+ } catch(InterpreterException exception) {}
+ }
+ }
+ */
+ }
+
+ private Set<ValueQuery> getQueries(ZMI zmi) {
+ Set<ValueQuery> querySet = new HashSet<ValueQuery>();
+ /*
+ for (Map.Entry<Attribute, Value> attribute : zmi.getAttributes()) {
+ if (attribute.getValue().getType().getPrimaryType() == Type.PrimaryType.QUERY) {
+ querySet.add((ValueQuery) attribute.getValue());
+ }
+ }
+ */
+
+ return querySet;
+ }
+
+ public void setFallbackContacts(Set<ValueContact> contacts) throws RemoteException {
+ // this.contacts = contacts;
+ }
+}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RMIMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RemikMessage.java
index a8e3afb..b0300cb 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RMIMessage.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RemikMessage.java
@@ -3,9 +3,20 @@ package pl.edu.mimuw.cloudatlas.agent.messages;
import pl.edu.mimuw.cloudatlas.agent.modules.Module;
import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType;
-public class RMIMessage extends AgentMessage {
- public RMIMessage(String messageId, long timestamp) {
+public abstract class RemikMessage extends AgentMessage {
+ public enum Type {
+ REQUEST_STATE
+ }
+
+ private Type type;
+
+ public RemikMessage(String messageId, long timestamp, Type type) {
super(messageId, ModuleType.RMI, timestamp);
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
}
public void callMe(Module module) throws InterruptedException, Module.InvalidMessageType {
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RequestStateMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RequestStateMessage.java
new file mode 100644
index 0000000..698aac7
--- /dev/null
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/RequestStateMessage.java
@@ -0,0 +1,16 @@
+package pl.edu.mimuw.cloudatlas.agent.messages;
+
+import java.util.concurrent.CompletableFuture;
+
+public class RequestStateMessage extends RemikMessage {
+ CompletableFuture<ResponseMessage> responseFuture;
+
+ public RequestStateMessage(String messageId, long timestamp, CompletableFuture<ResponseMessage> responseFuture) {
+ super(messageId, timestamp, Type.REQUEST_STATE);
+ this.responseFuture = responseFuture;
+ }
+
+ public CompletableFuture<ResponseMessage> getFuture() {
+ return responseFuture;
+ }
+}
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 ba5e1d1..0a934cb 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
@@ -4,8 +4,8 @@ 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.QurnikMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.RemikMessage;
import pl.edu.mimuw.cloudatlas.agent.messages.ResponseMessage;
-import pl.edu.mimuw.cloudatlas.agent.messages.RMIMessage;
import pl.edu.mimuw.cloudatlas.agent.messages.StanikMessage;
/*
@@ -37,8 +37,8 @@ public abstract class Module {
throw new InvalidMessageType("Got a QurnikMessage in module " + moduleType.toString());
}
- public void handleTyped(RMIMessage message) throws InterruptedException, InvalidMessageType {
- throw new InvalidMessageType("Got an RMIMessage in module " + moduleType.toString());
+ public void handleTyped(RemikMessage message) throws InterruptedException, InvalidMessageType {
+ throw new InvalidMessageType("Got a RemikMessage in module " + moduleType.toString());
}
public void handleTyped(StanikMessage message) throws InterruptedException, InvalidMessageType {
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/RMI.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/RMI.java
deleted file mode 100644
index 1a86fc7..0000000
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/RMI.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package pl.edu.mimuw.cloudatlas.agent.modules;
-
-import pl.edu.mimuw.cloudatlas.agent.ApiImplementation;
-import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage;
-import pl.edu.mimuw.cloudatlas.agent.messages.RMIMessage;
-import pl.edu.mimuw.cloudatlas.api.Api;
-import pl.edu.mimuw.cloudatlas.interpreter.Main;
-import pl.edu.mimuw.cloudatlas.model.ZMI;
-
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-
-public class RMI extends Module {
- public RMI(ModuleType moduleType) {
- super(moduleType);
- runRegistry();
- }
-
- public void runRegistry() {
- try {
- ZMI root = Main.createTestHierarchy2();
- ApiImplementation api = new ApiImplementation(root);
- Api apiStub =
- (Api) UnicastRemoteObject.exportObject(api, 0);
- Registry registry = LocateRegistry.getRegistry();
- registry.rebind("Api", apiStub);
- System.out.println("Agent: api bound");
- } catch (Exception e) {
- System.err.println("Agent registry initialization exception:");
- e.printStackTrace();
- }
- }
-
- public void handleTyped(RMIMessage event) throws InterruptedException {
- }
-}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Remik.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Remik.java
new file mode 100644
index 0000000..9645d71
--- /dev/null
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Remik.java
@@ -0,0 +1,54 @@
+package pl.edu.mimuw.cloudatlas.agent.modules;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.HashMap;
+import java.util.Map;
+
+
+import pl.edu.mimuw.cloudatlas.agent.messages.GetStateMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.RemikMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.RequestStateMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.ResponseMessage;
+
+/*
+ * Remik is a cute little module that allows RMI functions to interface with
+ * agent's asynchronous modules.
+ */
+public class Remik extends Module {
+ private Map<Long, CompletableFuture<ResponseMessage>> awaitingRequests;
+ private long nextRequestId = 0;
+
+ public Remik() {
+ super(ModuleType.RMI);
+ awaitingRequests = new HashMap();
+ }
+
+ public void handleTyped(RemikMessage message) throws InvalidMessageType, InterruptedException {
+ switch (message.getType()) {
+ case REQUEST_STATE:
+ handleRequestState((RequestStateMessage) message);
+ break;
+ default:
+ throw new InvalidMessageType("This type of message cannot be handled by Remik");
+ }
+ }
+
+ public void handleTyped(ResponseMessage message) {
+ CompletableFuture<ResponseMessage> responseFuture = awaitingRequests.get(message.getRequestId());
+
+ if (responseFuture == null) {
+ System.out.println("ERROR: Remik got response for nonexistent/finished request");
+ } else {
+ responseFuture.complete(message);
+ }
+ }
+
+ private void handleRequestState(RequestStateMessage message) throws InterruptedException {
+ awaitingRequests.put(nextRequestId, message.getFuture());
+
+ GetStateMessage getStateMessage = new GetStateMessage("", 0, ModuleType.RMI, nextRequestId);
+ nextRequestId++;
+
+ sendMessage(getStateMessage);
+ }
+}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java b/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java
index 54fbf43..cda0296 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java
@@ -219,8 +219,12 @@ public class ZMI implements Cloneable, Serializable {
* @return a <code>PathName</code> object representing this zone
*/
public PathName getPathName() {
- String name = ((ValueString)getAttributes().get("name")).getValue();
- return getFather() == null? PathName.ROOT : getFather().getPathName().levelDown(name);
+ if (getFather() == null) {
+ return PathName.ROOT;
+ } else {
+ String name = ((ValueString)getAttributes().get("name")).getValue();
+ return getFather().getPathName().levelDown(name);
+ }
}
public static ZMI deserialize(InputStream in) {
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/Container.java b/src/test/java/pl/edu/mimuw/cloudatlas/Container.java
new file mode 100644
index 0000000..db5a156
--- /dev/null
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/Container.java
@@ -0,0 +1,5 @@
+package pl.edu.mimuw.cloudatlas;
+
+public class Container<T> {
+ public T thing;
+}
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementationTests.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementationTests.java
index c964ed9..0a7a8df 100644
--- a/src/test/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementationTests.java
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementationTests.java
@@ -3,7 +3,6 @@ package pl.edu.mimuw.cloudatlas.agent;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
-import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.hasItems;
import java.util.ArrayList;
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/MockEventBus.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/MockEventBus.java
new file mode 100644
index 0000000..e8f8bfa
--- /dev/null
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/MockEventBus.java
@@ -0,0 +1,17 @@
+package pl.edu.mimuw.cloudatlas.agent;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage;
+
+public class MockEventBus extends EventBus {
+ public LinkedBlockingQueue<AgentMessage> events;
+
+ public MockEventBus() {
+ events = new LinkedBlockingQueue<AgentMessage>();
+ }
+
+ public void addMessage(AgentMessage msg) throws InterruptedException {
+ events.put(msg);
+ }
+}
diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementationTests.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementationTests.java
new file mode 100644
index 0000000..a3b57a9
--- /dev/null
+++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementationTests.java
@@ -0,0 +1,171 @@
+package pl.edu.mimuw.cloudatlas.agent;
+
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.hasItems;
+
+import java.util.concurrent.TimeUnit;
+import java.util.HashSet;
+import java.util.Set;
+
+import pl.edu.mimuw.cloudatlas.Container;
+import pl.edu.mimuw.cloudatlas.model.ZMI;
+import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType;
+import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.RequestStateMessage;
+import pl.edu.mimuw.cloudatlas.agent.messages.StateMessage;
+
+public class NewApiImplementationTests {
+ private NewApiImplementation api;
+ private MockEventBus eventBus;
+
+ @Before
+ public void initializeApi() throws Exception {
+ eventBus = new MockEventBus();
+ api = new NewApiImplementation(eventBus);
+ }
+
+ @Test
+ public void testGetZoneSet() throws Exception {
+ final Set<String> zoneSet = new HashSet();
+ final Container<Exception> exceptionContainer = new Container();
+ Thread apiThread = new Thread(() -> {
+ try {
+ zoneSet.addAll(api.getZoneSet());
+ } catch (Exception e) {
+ exceptionContainer.thing = e;
+ }
+ });
+ apiThread.start();
+
+ AgentMessage message = eventBus.events.poll(100, TimeUnit.MILLISECONDS);
+ assertNotNull(message);
+ assertEquals(ModuleType.RMI, message.getDestinationModule());
+ RequestStateMessage requestMessage = (RequestStateMessage) message;
+
+ ZMI root = new ZMI();
+ StateMessage responseMessage = new StateMessage("", ModuleType.RMI, 0, 0, root, null);
+
+ requestMessage.getFuture().complete(responseMessage);
+
+ apiThread.join(100);
+ assertFalse(apiThread.isAlive());
+ assertNull(exceptionContainer.thing);
+
+ assertThat(zoneSet, hasItems("/"));
+ }
+
+ /*
+ @Test
+ public void testRootGetZoneAttributeValue() throws Exception {
+ AttributesMap rootAttributes = api.getZoneAttributeValues("/");
+ assertEquals(new ValueInt(0l), rootAttributes.get("level"));
+ assertEquals(ValueNull.getInstance(), rootAttributes.get("name"));
+ }
+
+ @Test
+ public void testIntermediateGetZoneAttributeValue() throws Exception {
+ AttributesMap attributes = api.getZoneAttributeValues("/uw");
+ assertEquals(new ValueInt(1l), attributes.get("level"));
+ assertEquals(new ValueString("uw"), attributes.get("name"));
+ }
+
+ @Test
+ public void testLeafGetZoneAttributeValue() throws Exception {
+ AttributesMap attributes = api.getZoneAttributeValues("/pjwstk/whatever01");
+ assertEquals(new ValueInt(2l), attributes.get("level"));
+ assertEquals(new ValueString("whatever01"), attributes.get("name"));
+ assertEquals(new ValueString("/pjwstk/whatever01"), attributes.get("owner"));
+ assertEquals(new ValueTime("2012/11/09 21:12:00.000"), attributes.get("timestamp"));
+ assertEquals(new ValueInt(1l), attributes.get("cardinality"));
+ assertEquals(new ValueTime("2012/10/18 07:03:00.000"), attributes.get("creation"));
+ assertEquals(new ValueDouble(0.1), attributes.get("cpu_usage"));
+ assertEquals(new ValueInt(7l), attributes.get("num_cores"));
+ assertEquals(new ValueInt(215l), attributes.get("num_processes"));
+
+ List<Value> phpModules = new ArrayList<Value>();
+ phpModules.add(new ValueString("rewrite"));
+ assertEquals(new ValueList(phpModules, TypePrimitive.STRING), attributes.get("php_modules"));
+ }
+
+ @Test
+ public void testInstallQuery() throws Exception {
+ String name = "&query";
+ String queryCode = "SELECT 1 AS one";
+ api.installQuery(name, queryCode);
+ assertAttributeInZmiEquals(name, new ValueQuery(queryCode), "/");
+ assertAttributeInZmiEquals(name, new ValueQuery(queryCode), "/uw");
+ assertAttributeInZmiEquals(name, new ValueQuery(queryCode), "/pjwstk");
+ }
+
+ @Test
+ public void testInstallQueryRuns() throws Exception {
+ api.installQuery("&query", "SELECT 1 AS one");
+ assertAttributeInZmiEquals("one", new ValueInt(1l), "/");
+ assertAttributeInZmiEquals("one", new ValueInt(1l), "/uw");
+ assertAttributeInZmiEquals("one", new ValueInt(1l), "/pjwstk");
+ }
+
+ @Test
+ public void testInstallQueryRuns2() throws Exception {
+ api.installQuery("&query", "SELECT sum(num_processes) AS num_processes");
+ assertAttributeInZmiEquals("num_processes", new ValueInt(362l), "/uw");
+ assertAttributeInZmiEquals("num_processes", new ValueInt(437l), "/pjwstk");
+ assertAttributeInZmiEquals("num_processes", new ValueInt(799l), "/");
+ }
+
+ @Test
+ public void testInstallQueryWithInvalidNameFails() throws Exception {
+ String name = "query";
+ String queryCode = "SELECT 1 AS one";
+ try {
+ api.installQuery(name, queryCode);
+ assertTrue("should have thrown", false);
+ } catch (Exception e) {
+ assertEquals("Invalid query identifier", e.getMessage());
+ }
+ }
+
+ public void assertAttributeInZmiEquals(String attribute, Value expected, String zmiPath) throws Exception {
+ AttributesMap attributes = api.getZoneAttributeValues(zmiPath);
+ assertEquals(expected, attributes.get(attribute));
+ }
+
+ @Test
+ public void testUninstallQuery() throws Exception {
+ String name = "&query";
+ String queryCode = "SELECT 1 AS one";
+ api.installQuery(name, queryCode);
+ api.uninstallQuery(name);
+ AttributesMap attributes = api.getZoneAttributeValues("/pjwstk");
+ assertNull(attributes.getOrNull(name));
+ }
+
+ @Test
+ public void testSetAttributeValueChange() throws Exception {
+ Value numProcesses = new ValueInt(42l);
+ api.setAttributeValue("/uw/khaki13", "num_processes", numProcesses);
+ AttributesMap attributes = api.getZoneAttributeValues("/uw/khaki13");
+ assertEquals(numProcesses, attributes.get("num_processes"));
+ }
+
+ @Test
+ public void testSetAttributeValueAdd() throws Exception {
+ Value numProcesses = new ValueInt(42l);
+ api.setAttributeValue("/uw/khaki13", "an_attribute", numProcesses);
+ AttributesMap attributes = api.getZoneAttributeValues("/uw/khaki13");
+ assertEquals(numProcesses, attributes.get("an_attribute"));
+ }
+
+ @Test
+ public void testSetAttributeValueRunsQueries() throws Exception {
+ api.installQuery("&query", "SELECT sum(num_processes) AS num_processes");
+ Value numProcesses = new ValueInt(42l);
+ api.setAttributeValue("/uw/khaki13", "num_processes", numProcesses);
+ assertAttributeInZmiEquals("num_processes", new ValueInt(297l), "/uw");
+ assertAttributeInZmiEquals("num_processes", new ValueInt(437l), "/pjwstk");
+ assertAttributeInZmiEquals("num_processes", new ValueInt(734l), "/");
+ }
+ */
+}