/* (c) 2017 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.notification; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.List; import net.sf.json.JSONObject; import org.geoserver.catalog.CatalogBuilder; import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.CoverageStoreInfo; import org.geoserver.catalog.LayerGroupInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.NamespaceInfo; import org.geoserver.catalog.ProjectionPolicy; import org.geoserver.catalog.StyleInfo; import org.geoserver.catalog.WMSLayerInfo; import org.geoserver.catalog.WMSStoreInfo; import org.geoserver.catalog.WorkspaceInfo; import org.geoserver.data.test.SystemTestData; import org.geoserver.notification.common.Bounds; import org.geoserver.notification.common.Notification; import org.geoserver.notification.geonode.kombu.KombuCoverageInfo; import org.geoserver.notification.geonode.kombu.KombuLayerGroupInfo; import org.geoserver.notification.geonode.kombu.KombuLayerInfo; import org.geoserver.notification.geonode.kombu.KombuLayerSimpleInfo; import org.geoserver.notification.geonode.kombu.KombuMessage; import org.geoserver.notification.geonode.kombu.KombuStoreInfo; import org.geoserver.notification.geonode.kombu.KombuWMSLayerInfo; import org.geoserver.notification.support.BrokerManager; import org.geoserver.notification.support.Receiver; import org.geoserver.notification.support.ReceiverService; import org.geoserver.notification.support.Utils; import org.geoserver.rest.catalog.CatalogRESTTestSupport; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.fasterxml.jackson.databind.ObjectMapper; public class IntegrationTest extends CatalogRESTTestSupport { private static BrokerManager brokerStarter; private static Receiver rc; @BeforeClass public static void startup() throws Exception { brokerStarter = new BrokerManager(); brokerStarter.startBroker(false); rc = new Receiver("guest", "guest"); } @AfterClass public static void tearDown() throws Exception { brokerStarter.stopBroker(); } @After public void before() throws Exception { if (rc != null) { rc.close(); } } public void addStatesWmsLayer() throws Exception { WMSLayerInfo wml = catalog.getResourceByName("sf", "states", WMSLayerInfo.class); if (wml == null) { wml = catalog.getFactory().createWMSLayer(); wml.setName("states"); wml.setNativeName("topp:states"); wml.setStore(catalog.getStoreByName("demo", WMSStoreInfo.class)); wml.setCatalog(catalog); wml.setNamespace(catalog.getNamespaceByPrefix("sf")); wml.setSRS("EPSG:4326"); CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326"); wml.setNativeCRS(wgs84); wml.setLatLonBoundingBox(new ReferencedEnvelope(-110, 0, -60, 50, wgs84)); wml.setProjectionPolicy(ProjectionPolicy.FORCE_DECLARED); catalog.add(wml); } } @Override protected void setUpTestData(SystemTestData testData) throws Exception { super.setUpTestData(testData); new File(testData.getDataDirectoryRoot(), "notifier").mkdir(); testData.copyTo( getClass().getClassLoader().getResourceAsStream( NotifierInitializer.PROPERTYFILENAME), "notifier/" + NotifierInitializer.PROPERTYFILENAME); } /* * @Override protected void onSetUp(SystemTestData testData) throws Exception { super.onSetUp(testData); * * } */ @Test public void catalogAddNamespaces() throws Exception { ReceiverService service = new ReceiverService(2); rc.receive(service); String json = "{'namespace':{ 'prefix':'foo', 'uri':'http://foo.com' }}"; postAsServletResponse("/rest/namespaces", json, "text/json"); List<byte[]> ret = service.getMessages(); assertEquals(2, ret.size()); KombuMessage nsMsg = Utils.toKombu(ret.get(0)); assertEquals(Notification.Action.Add.name(), nsMsg.getAction()); assertEquals("Catalog", nsMsg.getType()); assertEquals("NamespaceInfo", nsMsg.getSource().getType()); KombuMessage wsMsg = Utils.toKombu(ret.get(1)); assertEquals("Catalog", wsMsg.getType()); assertEquals("WorkspaceInfo", wsMsg.getSource().getType()); } @Test public void catalogChangeLayerStyle() throws Exception { ReceiverService service = new ReceiverService(1); rc.receive(service); LayerInfo l = catalog.getLayerByName("cite:Buildings"); assertEquals("Buildings", l.getDefaultStyle().getName()); JSONObject json = (JSONObject) getAsJSON("/rest/layers/cite:Buildings.json"); JSONObject layer = (JSONObject) json.get("layer"); JSONObject style = (JSONObject) layer.get("defaultStyle"); style.put("name", "polygon"); style.put("href", "http://localhost:8080/geoserver/rest/styles/polygon.json"); String updatedJson = json.toString(); putAsServletResponse("/rest/layers/cite:Buildings", updatedJson, "application/json"); List<byte[]> ret = service.getMessages(); assertEquals(1, ret.size()); KombuMessage nsMsg = Utils.toKombu(ret.get(0)); assertEquals(Notification.Action.Update.name(), nsMsg.getAction()); assertEquals("Catalog", nsMsg.getType()); KombuLayerInfo source = (KombuLayerInfo) nsMsg.getSource(); assertEquals("LayerInfo", source.getType()); assertEquals("polygon", source.getDefaultStyle()); } @Test public void catalogChangeLayerStyles() throws Exception { ReceiverService service = new ReceiverService(1); rc.receive(service); String xml = "<style>" + "<name>foo</name>" + "<filename>foo.sld</filename>" + "</style>"; postAsServletResponse("/rest/workspaces/cite/styles", xml); xml = "<layer>" + "<styles>" + "<style>" + "<name>foo</name>" + "<workspace>cite</workspace>" + "</style>" + "</styles>" + "<enabled>true</enabled>" + "</layer>"; putAsServletResponse("/rest/layers/cite:Buildings", xml, "application/xml"); List<byte[]> ret = service.getMessages(); assertEquals(1, ret.size()); KombuMessage updateMsg = Utils.toKombu(ret.get(0)); assertEquals("Catalog", updateMsg.getType()); assertEquals(Notification.Action.Update.name(), updateMsg.getAction()); KombuLayerInfo source = (KombuLayerInfo) updateMsg.getSource(); assertEquals("LayerInfo", source.getType()); assertEquals("foo", source.getStyles()); } @Test public void catalogAddAndDeleteWMSLayer() throws Exception { ReceiverService service = new ReceiverService(3); rc.receive(service); CatalogBuilder cb = new CatalogBuilder(catalog); cb.setWorkspace(catalog.getWorkspaceByName("sf")); WMSStoreInfo wms = cb.buildWMSStore("demo"); wms.setCapabilitiesURL("http://demo.opengeo.org/geoserver/wms?"); catalog.add(wms); addStatesWmsLayer(); assertNotNull(catalog.getResourceByName("sf", "states", WMSLayerInfo.class)); deleteAsServletResponse("/rest/workspaces/sf/wmsstores/demo/wmslayers/states"); List<byte[]> ret = service.getMessages(); assertEquals(3, ret.size()); KombuMessage addStrMsg = Utils.toKombu(ret.get(0)); assertEquals(Notification.Action.Add.name(), addStrMsg.getAction()); KombuStoreInfo source1 = (KombuStoreInfo) addStrMsg.getSource(); assertEquals("StoreInfo", source1.getType()); KombuMessage addLayerMsg = Utils.toKombu(ret.get(1)); assertEquals(Notification.Action.Add.name(), addLayerMsg.getAction()); KombuWMSLayerInfo source2 = (KombuWMSLayerInfo) addLayerMsg.getSource(); assertEquals("WMSLayerInfo", source2.getType()); KombuMessage deleteMsg = Utils.toKombu(ret.get(2)); assertEquals("Catalog", deleteMsg.getType()); assertEquals(Notification.Action.Remove.name(), deleteMsg.getAction()); KombuWMSLayerInfo source3 = (KombuWMSLayerInfo) deleteMsg.getSource(); assertEquals("WMSLayerInfo", source3.getType()); assertEquals("states", source3.getName()); catalog.remove(wms); } @Test public void cpuLoadTest() throws Exception { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); threadMXBean.setThreadContentionMonitoringEnabled(true); threadMXBean.setThreadCpuTimeEnabled(true); ReceiverService service = new ReceiverService(3); rc.receive(service); CatalogBuilder cb = new CatalogBuilder(catalog); cb.setWorkspace(catalog.getWorkspaceByName("sf")); WMSStoreInfo wms = cb.buildWMSStore("demo"); wms.setCapabilitiesURL("http://demo.opengeo.org/geoserver/wms?"); try { catalog.add(wms); } catch (Exception e) { } addStatesWmsLayer(); assertNotNull(catalog.getResourceByName("sf", "states", WMSLayerInfo.class)); deleteAsServletResponse("/rest/workspaces/sf/wmsstores/demo/wmslayers/states"); List<byte[]> ret = service.getMessages(); assertEquals(3, ret.size()); Thread.sleep(1000); ThreadInfo[] threadInfo = threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds()); for (ThreadInfo threadInfo2 : threadInfo) { if (threadInfo2.getThreadName().equals(NotifierInitializer.THREAD_NAME)) { long blockedTime = threadInfo2.getBlockedTime(); long waitedTime = threadInfo2.getWaitedTime(); long cpuTime = threadMXBean.getThreadCpuTime(threadInfo2.getThreadId()); long userTime = threadMXBean.getThreadUserTime(threadInfo2.getThreadId()); String msg = String.format( "%s: %d ms cpu time, %d ms user time, blocked for %d ms, waited %d ms", threadInfo2.getThreadName(), cpuTime / 1000000, userTime / 1000000, blockedTime, waitedTime); System.out.println(msg); assertTrue(waitedTime > 0); break; } } catalog.remove(wms); } @Test public void catalogAddCoverage() throws Exception { ReceiverService service = new ReceiverService(4); rc.receive(service); addCoverageStore(); NamespaceInfo ns = catalog.getFactory().createNamespace(); ns.setPrefix("bar"); ns.setURI("http://bar"); catalog.add(ns); CoverageInfo ft = catalog.getFactory().createCoverage(); ft.setName("foo"); ft.setNamespace(ns); ft.setStore(catalog.getCoverageStoreByName("acme", "foostore")); catalog.add(ft); List<byte[]> ret = service.getMessages(); assertEquals(4, ret.size()); KombuMessage coverageMsg = Utils.toKombu(ret.get(3)); assertEquals("Catalog", coverageMsg.getType()); assertEquals(Notification.Action.Add.name(), coverageMsg.getAction()); KombuCoverageInfo source = (KombuCoverageInfo) coverageMsg.getSource(); assertEquals("CoverageInfo", source.getType()); assertEquals(ft.getName(), source.getName()); } @Test public void catalogAddLayerGroup() throws Exception { ReceiverService service = new ReceiverService(1); rc.receive(service); LayerGroupInfo lg = catalog.getFactory().createLayerGroup(); lg.setName("sfLayerGroup"); LayerInfo l = catalog.getLayerByName("cite:Buildings"); lg.getLayers().add(l); lg.getStyles().add(catalog.getStyleByName(StyleInfo.DEFAULT_POLYGON)); lg.setBounds(new ReferencedEnvelope(-180, -90, 180, 90, CRS.decode("EPSG:4326"))); catalog.add(lg); List<byte[]> ret = service.getMessages(); assertEquals(1, ret.size()); KombuMessage groupMsg = Utils.toKombu(ret.get(0)); assertEquals("Catalog", groupMsg.getType()); assertEquals(Notification.Action.Add.name(), groupMsg.getAction()); KombuLayerGroupInfo source = (KombuLayerGroupInfo) groupMsg.getSource(); assertEquals("LayerGroupInfo", source.getType()); assertEquals(1, source.getLayers().size()); KombuLayerSimpleInfo kl = source.getLayers().get(0); assertEquals(l.getName(), kl.getName()); assertEquals(l.getDefaultStyle().getName(), kl.getStyle()); } @Test public void transactionDoubleAdd() throws Exception { ReceiverService service = new ReceiverService(1); rc.receive(service); String xml = "<wfs:Transaction service=\"WFS\" version=\"1.0.0\" " + "xmlns:cgf=\"http://www.opengis.net/cite/geometry\" " + "xmlns:ogc=\"http://www.opengis.net/ogc\" " + "xmlns:wfs=\"http://www.opengis.net/wfs\" " + "xmlns:gml=\"http://www.opengis.net/gml\"> " + "<wfs:Insert handle='insert-1'> " + "<cgf:Lines>" + "<cgf:lineStringProperty>" + "<gml:LineString>" + "<gml:coordinates decimal=\".\" cs=\",\" ts=\" \">" + "5,5 6,6" + "</gml:coordinates>" + "</gml:LineString>" + "</cgf:lineStringProperty>" + "<cgf:id>t0001</cgf:id>" + "</cgf:Lines>" + "</wfs:Insert>" + "<wfs:Insert handle='insert-2'> " + "<cgf:Lines>" + "<cgf:lineStringProperty>" + "<gml:LineString>" + "<gml:coordinates decimal=\".\" cs=\",\" ts=\" \">" + "7,7 8,8" + "</gml:coordinates>" + "</gml:LineString>" + "</cgf:lineStringProperty>" + "<cgf:id>t0002</cgf:id>" + "</cgf:Lines>" + "</wfs:Insert>" + "</wfs:Transaction>"; postAsDOM("wfs", xml); List<byte[]> ret = service.getMessages(); assertEquals(1, ret.size()); KombuMessage tMsg = Utils.toKombu(ret.get(0)); assertEquals("Data", tMsg.getType()); assertEquals(2, tMsg.getProperties().get(NotificationTransactionListener.INSERTED)); assertNotNull(tMsg.getProperties().get(NotificationTransactionListener.BOUNDS)); ObjectMapper mapper = new ObjectMapper(); mapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); Bounds b = mapper.convertValue( tMsg.getProperties().get(NotificationTransactionListener.BOUNDS), Bounds.class); assertEquals(5d, b.getMinx().doubleValue(), 0); assertEquals(5d, b.getMiny().doubleValue(), 0); assertEquals(8d, b.getMaxx().doubleValue(), 0); assertEquals(8d, b.getMaxy().doubleValue(), 0); } public void addWorkspace() throws Exception { WorkspaceInfo acme = catalog.getFactory().createWorkspace(); acme.setName("acme"); catalog.add(acme); } public void addCoverageStore() throws Exception { addWorkspace(); CoverageStoreInfo cs = catalog.getFactory().createCoverageStore(); cs.setName("foostore"); cs.setWorkspace(catalog.getWorkspaceByName("acme")); catalog.add(cs); } }