blob: c5219648a1e219816e8390f6ce9125636b77d0df [file] [log] [blame]
/*
********************************************************************************
* Copyright (c) 9th November 2018 Cloudreach Limited Europe
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is
* available at https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
package org.eclipse.jemo.sys;
import org.eclipse.jemo.Jemo;
import org.eclipse.jemo.JemoGSMTest;
import org.eclipse.jemo.api.KeyValue;
import org.eclipse.jemo.api.Module;
import org.eclipse.jemo.internal.model.JemoMessage;
import org.eclipse.jemo.internal.model.CloudProvider;
import org.eclipse.jemo.internal.model.CloudRuntime;
import org.eclipse.jemo.internal.model.SystemDBObject;
import org.eclipse.jemo.internal.model.JemoApplicationMetaData;
import org.eclipse.jemo.runtime.MemoryRuntime;
import org.eclipse.jemo.sys.internal.Util;
import org.eclipse.jemo.HttpServletRequestAdapter;
import org.eclipse.jemo.HttpServletResponseAdapter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Holder;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author Christopher Stura "christopher.stura@cloudreach.com"
*/
public class TestPluginManager extends JemoGSMTest {
public TestPluginManager() throws Throwable { super(); }
@Test
public void testGetInstances() throws Throwable {
Class pluginManagerClass = Class.forName("org.eclipse.jemo.sys.JemoPluginManager");
Object pluginManager = pluginManagerClass.getMethod("getInstance").invoke(pluginManagerClass);
List<String> instances = (List)pluginManagerClass.getMethod("listInstances", String.class).invoke(pluginManager, "AWS");
Logger.getAnonymousLogger().info(String.format("instances: %s", instances));
CloudRuntime runtime = CloudProvider.getInstance().getRuntime();
JemoPluginManager jemoPluginManager = (JemoPluginManager)pluginManager;
jemoPluginManager.runWithModuleContext(Void.class, x -> {
Map<String,String> payload = new HashMap<>();
JemoMessage msg = new JemoMessage();
msg.setSourcePluginId(20);
msg.setPluginId(20);
msg.setModuleClass("org.eclipse.jemo.connect.ConnectModule");
/*msg.getAttributes().put("queue", getName()); //name of connect queue
msg.getAttributes().put("class", m.getClass().getName()); //the connect class which recieves the queue (EventProcessor implementation)
msg.getAttributes().put("pluginId", pluginId); //the id of the connect plugin.*/
instances.forEach(i -> {
try {
Long whenWasILaunched = runtime.retrieve("metoffice_instance_run_"+i, Long.class);
if(whenWasILaunched == null || System.currentTimeMillis()-whenWasILaunched > TimeUnit.HOURS.toMillis(2)) {
runtime.store("metoffice_instance_run_"+i, System.currentTimeMillis());
msg.getAttributes().put("payload", Jemo.toJSONString(payload)); //the data to send to connect.
msg.send(runtime.getQueueId("JEMO-AWS-"+i));
}
}catch(Throwable ex) {
throw new RuntimeException(ex);
}
});
return null;
});
}
@Test
public void test_getLocationList() throws Throwable {
//so for this test to pass we must have a queue id value for all of the locations in the list.
Set<String> locations = jemoServer.getPluginManager().getLocationList();
Set<String> queueIdList = locations.stream()
.map(l -> CloudProvider.getInstance().getRuntime().getQueueId("JEMO-"+l+"-WORK-QUEUE"))
.filter(qId -> qId != null)
.collect(Collectors.toSet());
assertEquals(locations.size(),queueIdList.size());
}
@Test
public void test_getActiveLocationList() throws Throwable {
Set<String> activeLocations = jemoServer.getPluginManager().getActiveLocationList();
Set<String> queueIdList = activeLocations.stream()
.map(l -> CloudProvider.getInstance().getRuntime().getQueueId("JEMO-"+l+"-WORK-QUEUE"))
.filter(qId -> qId != null)
.collect(Collectors.toSet());
assertEquals(activeLocations.size(),queueIdList.size());
//also each location must have at least 1 active instance.
Set<String> activeInstances = activeLocations.stream()
.filter(l -> !jemoServer.getPluginManager().listInstances(l).isEmpty())
.collect(Collectors.toSet());
assertEquals(activeLocations.size(),activeInstances.size());
}
@Test
public void test_getInstanceLocations() throws Throwable {
Set<String> instanceList = jemoServer.getPluginManager().getActiveInstanceList();
assertArrayEquals(jemoServer.getPluginManager().getActiveLocationList().toArray(), jemoServer.getPluginManager().getInstanceLocations(instanceList.toArray(new String[] {})).toArray());
}
@Test
public void test_getInstanceLocationMap() throws Throwable {
assertEquals(locationList().stream()
.flatMap(l -> instanceList(l).stream().map(i -> new KeyValue<>(i,l)))
.collect(Collectors.toMap(KeyValue::getKey, KeyValue::getValue)), jemoServer.getPluginManager().getInstanceLocationMap(jemoServer.getPluginManager().getActiveInstanceList().toArray(new String[] {})));
}
@Test
public void test_MonitoringInterval_httpRequest() {
JemoPluginManager.MonitoringInterval interval = new JemoPluginManager.MonitoringInterval("1M", 1, TimeUnit.MINUTES);
interval.httpRequest(1000);
assertEquals(1,interval.getHttpRequests());
assertEquals(1000,interval.getTotalHttpTime());
}
@Test
public void test_MonitoringInterval_checkInterval() {
JemoPluginManager.MonitoringInterval interval = new JemoPluginManager.MonitoringInterval("1M", 1, TimeUnit.MINUTES);
interval.httpRequest(1000);
assertEquals(1,interval.getHttpRequests());
assertEquals(1000,interval.getTotalHttpTime());
interval.eventRequest(100);
assertEquals(1,interval.getEventRequests());
assertEquals(100,interval.getTotalEventTime());
assertEquals("1M",interval.getKey());
assertEquals(TimeUnit.MINUTES.toMillis(1), interval.getDuration());
Util.setFieldValue(interval, "intervalStart", System.currentTimeMillis() - (interval.getDuration()+100));
interval.eventRequest(100);
assertEquals(1,interval.getEventRequests());
assertEquals(100,interval.getTotalEventTime());
}
@Test
public void test_ModuleInfoCache() {
JemoPluginManager.ModuleInfoCache cache = new JemoPluginManager.ModuleInfoCache("TEST1",new HashSet<>());
assertEquals("TEST1",cache.getLocation());
long cachedOn = System.currentTimeMillis();
Util.setFieldValue(cache, "cachedOn", cachedOn);
assertEquals(cachedOn, cache.getCachedOn());
}
@Test
public void test_listApplications() {
//we need to set a mock cloud runtime up first
List<JemoApplicationMetaData> origKnownApplications = new ArrayList<>();
List<JemoApplicationMetaData> knownApplications = Util.getFieldValue(jemoServer.getPluginManager(),"KNOWN_APPLICATIONS",List.class);
try {
origKnownApplications.addAll(knownApplications);
knownApplications.clear();
CloudProvider.defineCustomeRuntime(new MemoryRuntime() {
List<SystemDBObject> objList = new ArrayList<>();
@Override
public <T> List<T> listNoSQL(String tableName, Class<T> objectType) {
return objList.stream().map(obj -> objectType.cast(obj)).collect(Collectors.toList());
}
@Override
public Set<String> listPlugins() {
return Arrays.asList("10_Test-1-1.0.jar").stream().collect(Collectors.toSet());
}
@Override
public boolean hasNoSQLTable(String tableName) {
return true;
}
@Override
public Long getModuleInstallDate(String moduleJar) throws IOException {
return System.currentTimeMillis();
}
@Override
public void saveNoSQL(String tableName, SystemDBObject... data) {
objList.addAll(Arrays.asList(data));
}
});
jemoServer.getPluginManager().listApplications();
assertEquals(1,knownApplications.size());
JemoApplicationMetaData resultMetadata = knownApplications.iterator().next();
assertNotNull(resultMetadata);
JemoApplicationMetaData targetMetadata = new JemoApplicationMetaData();
targetMetadata.setId("10_Test-1-1.0.jar");
assertEquals(targetMetadata.getId(),resultMetadata.getId());
}finally {
CloudProvider.defineCustomeRuntime(null);
knownApplications.clear();
knownApplications.addAll(origKnownApplications);
}
}
@Test
public void test_getVirtualHostMap() {
try {
CloudProvider.defineCustomeRuntime(new MemoryRuntime() {
@Override
public <T> T retrieve(String key, Class<T> objType) {
Map<String,String> currentDefinitions = new HashMap<>();
currentDefinitions.put("www.google.com","/3/v1.0/google");
return objType.cast(currentDefinitions);
}
});
assertNotNull(jemoServer.getPluginManager().getVirtualHostMap());
jemoServer.getPluginManager().loadVirtualHostDefinitions();
assertFalse(jemoServer.getPluginManager().getVirtualHostMap().isEmpty());
assertTrue(jemoServer.getPluginManager().getVirtualHostMap().containsKey("www.google.com"));
}finally {
CloudProvider.defineCustomeRuntime(null);
}
}
@Test
public void test_getMonitoringInterval() {
assertNotNull(jemoServer.getPluginManager().getMonitoringInterval("5M"));
}
@Test
public void test_listMonitoringIntervals() {
jemoServer.getPluginManager().listMonitoringIntervals().forEach(interval -> assertNotNull(jemoServer.getPluginManager().getMonitoringInterval(interval)));
}
@Test
public void test_PLUGIN_INSTALLED_ON() {
try {
CloudProvider.defineCustomeRuntime(new MemoryRuntime() {
@Override
public Long getModuleInstallDate(String moduleJar) throws IOException {
throw new IOException(moduleJar);
}
});
long now = System.currentTimeMillis();
long installedOn = JemoPluginManager.PLUGIN_INSTALLED_ON("10_test-1-1.0.jar");
assertTrue(installedOn >= now);
}finally {
CloudProvider.defineCustomeRuntime(null);
}
}
@Test
public void test_MEMORY_CHECK() {
assertTrue(JemoPluginManager.MEMORY_CHECK() > 0);
assertTrue(JemoPluginManager.garbageCollectIfNecessary(0));
assertFalse(JemoPluginManager.garbageCollectIfNecessary(150000));
}
public static class TestModule implements Module {
@Override
public void construct(Logger logger, String name, int id, double version) {}
}
@Test
public void test_MODULE_LIST() throws Throwable {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
Util.createJar(byteOut, TestModule.class, TestPluginManager.class);
byte[] jarBytes = byteOut.toByteArray();
try(JemoClassLoader clsLoader = new JemoClassLoader(UUID.randomUUID().toString(), jarBytes)) {
List<String> moduleList = jemoServer.getPluginManager().MODULE_LIST("10_Test-1-1.0.jar", jarBytes, clsLoader);
assertTrue(moduleList.contains(TestModule.class.getName()));
}
assertTrue(jemoServer.getPluginManager().MODULE_LIST("100_Test-1-1.0.jar", null, null).isEmpty());
CloudProvider.getInstance().getRuntime().uploadModule("101_Test-1-1.0.jar", jarBytes);
List<String> moduleList = jemoServer.getPluginManager().MODULE_LIST("101_Test-1-1.0.jar");
assertTrue(moduleList.contains(TestModule.class.getName()));
try {
CloudProvider.defineCustomeRuntime(new MemoryRuntime() {});
assertTrue(jemoServer.getPluginManager().MODULE_LIST("102_Test-1-1.0.jar").isEmpty());
}finally {
CloudProvider.defineCustomeRuntime(null);
}
}
@Test
public void test_listPlugins() {
List<JemoApplicationMetaData> appList = Util.getFieldValue(jemoServer.getPluginManager(), "APPLICATION_LIST", List.class);
assertEquals(appList.size(), jemoServer.getPluginManager().listPluginIds().size());
}
public static class TestWebModule implements Module {
@Override
public void construct(Logger logger, String name, int id, double version) {}
@Override
public String getBasePath() {
return "/test";
}
@Override
public void process(HttpServletRequest request, HttpServletResponse response) throws Throwable {}
}
@Test
public void test_process() throws Throwable {
try {
JemoMessage msg = new JemoMessage();
msg.setPluginId(100);
msg.setModuleClass("org.test.com.Test");
jemoServer.getPluginManager().process(msg);
}catch(Throwable rtEx) {
assertEquals("Module: 100 - org.test.com.Test could not be found", rtEx.getMessage());
}
Holder<String> errorStr = new Holder<>();
jemoServer.getPluginManager().process(new HttpServletRequestAdapter() {
@Override
public String getServletPath() {
return "/1/v1.0/test";
}
@Override
public StringBuffer getRequestURL() {
return new StringBuffer("https://localhost:8080/1/v1.0/test");
}
}, new HttpServletResponseAdapter() {
@Override
public void sendError(int i, String string) throws IOException {
errorStr.value = string;
}
});
assertEquals("no module mapping defined for: /1/v1.0/test supported mappings are: "+Util.getFieldValue(jemoServer.getPluginManager(), "moduleEndpointMap", Map.class).toString(), errorStr.value);
//ok now lets test the virtual host scenario
Map<String,String> vhostMap = Util.getFieldValue(jemoServer.getPluginManager(), "virtualHostMap", Map.class);
vhostMap.put("//www.google.com", "/1/v1.0/test");
jemoServer.getPluginManager().process(new HttpServletRequestAdapter() {
@Override
public String getServletPath() {
return "";
}
@Override
public StringBuffer getRequestURL() {
return new StringBuffer("https://www.google.com/");
}
}, new HttpServletResponseAdapter() {
@Override
public void sendError(int i, String string) throws IOException {
errorStr.value = string;
}
});
assertEquals("the path: /1/v1.0/test does not currespond to any mappings. supported mappings are: "+Util.getFieldValue(jemoServer.getPluginManager(), "moduleEndpointMap", Map.class).toString(), errorStr.value);
//ok now lets add a module map for our test module.
uploadPlugin(1, 1.0, TestWebModule.class.getSimpleName(), TestWebModule.class, TestPluginManager.class);
//we now need to wait until the upload has completed.
do {
TimeUnit.SECONDS.sleep(1);
}while(!((List<JemoApplicationMetaData>)Util.getFieldValue(jemoServer.getPluginManager(),"APPLICATION_LIST", List.class)).stream().anyMatch(app -> JemoPluginManager.PLUGIN_ID(app.getId()) == 1));
assertNotNull(Util.getFieldValue(jemoServer.getPluginManager(), "moduleEndpointMap", Map.class).get("/1/v1.0/test"));
errorStr.value = null;
jemoServer.getPluginManager().process(new HttpServletRequestAdapter() {
@Override
public String getServletPath() {
return "";
}
@Override
public StringBuffer getRequestURL() {
return new StringBuffer("https://www.google.com/");
}
}, new HttpServletResponseAdapter() {
@Override
public void sendError(int i, String string) throws IOException {
errorStr.value = string;
}
});
assertNull(errorStr.value);
//we need to call a url on the plugin manager
jemoServer.getPluginManager().process(new HttpServletRequestAdapter() {
@Override
public String getServletPath() {
return "/jemo/check";
}
@Override
public StringBuffer getRequestURL() {
return new StringBuffer("https://localhost:8080/jemo/check");
}
@Override
public String getRequestURI() {
return "https://localhost:8080/jemo/check";
}
@Override
public String getHeader(String string) {
return null;
}
@Override
public String getMethod() {
return "GET";
}
}, new HttpServletResponseAdapter() {
@Override
public void sendError(int i, String string) throws IOException {
errorStr.value = string;
}
});
assertNull(errorStr.value);
}
@Test
public void test_process_http_pluginmanager_module() throws Throwable {
Holder<String> contentType = new Holder<>();
jemoServer.getPluginManager().process(new HttpServletRequestAdapter() {
@Override
public String getServletPath() {
return "/jemo/check";
}
@Override
public String getRequestURI() {
return getServletPath();
}
@Override
public StringBuffer getRequestURL() {
return new StringBuffer("https://localhost:8080/jemo/check");
}
@Override
public String getHeader(String string) {
return "Basic "+Base64.getEncoder().encodeToString("test:test".getBytes(Util.UTF8_CHARSET));
}
@Override
public String getParameter(String string) {
return null;
}
@Override
public String getMethod() {
return "GET";
}
}, new HttpServletResponseAdapter() {
@Override
public void setContentType(String string) {
contentType.value = string;
}
@Override
public void setContentLength(int i) {
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
private ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener wl) {}
@Override
public void write(int b) throws IOException {
byteOut.write(b);
}
};
}
@Override
public void sendError(int i, String string) throws IOException {}
});
assertNotNull(contentType.value);
assertEquals("text/html",contentType.value);
}
}