/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.gwc; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; import static org.geotools.referencing.crs.DefaultGeographicCRS.WGS84; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import net.opengis.wfs.InsertElementType; import net.opengis.wfs.TransactionResponseType; import net.opengis.wfs.TransactionType; import org.geoserver.wfs.TransactionEvent; import org.geoserver.wfs.TransactionEventType; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.geometry.jts.ReferencedEnvelope3D; import org.geotools.referencing.CRS; import org.junit.Before; import org.junit.Test; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.google.common.collect.ImmutableSet; public class GWCTransactionListenerTest { private GWC mediator; private GWCTransactionListener listener; @Before public void setUp() throws Exception { mediator = mock(GWC.class); listener = new GWCTransactionListener(mediator); } @Test public void testNoInteractionsInUnusedMethods() { TransactionType request = mock(TransactionType.class); TransactionType returned = listener.beforeTransaction(request); assertSame(request, returned); verifyNoMoreInteractions(request, mediator); listener.beforeCommit(request); verifyNoMoreInteractions(request, mediator); } @Test public void testAfterTransactionUncommitted() { TransactionType request = mock(TransactionType.class); TransactionResponseType result = mock(TransactionResponseType.class); boolean committed = false; listener.afterTransaction(request, result, committed); verifyNoMoreInteractions(request, result, mediator); } @Test public void testDataStoreChangeDoesNotPropagateExceptions() { TransactionEvent event = mock(TransactionEvent.class); when(event.getSource()).thenThrow(new RuntimeException("fake")); try { listener.dataStoreChange(event); } catch (RuntimeException e) { fail("Exception should have been eaten to prevent the transaction from failing due to a gwc integration error"); } } @Test public void testDataStoreChangeOfNoInterest() { TransactionEvent event = mock(TransactionEvent.class); when(event.getSource()).thenReturn(new Object()); listener.dataStoreChange(event); verify(event, times(1)).getLayerName(); verify(event, times(1)).getType(); verify(event, times(1)).getSource(); verifyNoMoreInteractions(event, mediator); } @Test public void testDataStoreChangePostInsert() { InsertElementType insert = mock(InsertElementType.class); TransactionEvent event = mock(TransactionEvent.class); QName layerName = new QName("testType"); when(event.getLayerName()).thenReturn(layerName); when(event.getSource()).thenReturn(insert); when(event.getType()).thenReturn(TransactionEventType.POST_INSERT); listener.dataStoreChange(event); // no need to do anything at post insert, bounds computed at pre_insert verifyNoMoreInteractions(mediator); } @Test public void testDataStoreChangeDoesNotAffectTileLayer() { InsertElementType insert = mock(InsertElementType.class); TransactionEvent event = mock(TransactionEvent.class); QName layerName = new QName("testType"); when(event.getLayerName()).thenReturn(layerName); when(event.getSource()).thenReturn(insert); when(event.getType()).thenReturn(TransactionEventType.PRE_INSERT); when( mediator.getTileLayersByFeatureType(eq(layerName.getNamespaceURI()), eq(layerName.getLocalPart()))).thenReturn(Collections.EMPTY_SET); listener.dataStoreChange(event); // nothing else to do verify(mediator, times(1)).getTileLayersByFeatureType(eq(layerName.getNamespaceURI()), eq(layerName.getLocalPart())); verifyNoMoreInteractions(mediator); } @Test public void testDataStoreChangeInsert() { Map<Object, Object> extendedProperties = new HashMap<Object, Object>(); ReferencedEnvelope affectedBounds = new ReferencedEnvelope(-180, 0, 0, 90, WGS84); issueInsert(extendedProperties, affectedBounds); assertTrue(extendedProperties .containsKey(GWCTransactionListener.GWC_TRANSACTION_INFO_PLACEHOLDER)); @SuppressWarnings("unchecked") Map<String, List<ReferencedEnvelope>> placeHolder = (Map<String, List<ReferencedEnvelope>>) extendedProperties .get(GWCTransactionListener.GWC_TRANSACTION_INFO_PLACEHOLDER); assertNotNull(placeHolder.get("theLayer")); assertSame(affectedBounds, placeHolder.get("theLayer").get(0)); assertSame(affectedBounds, placeHolder.get("theGroup").get(0)); } @Test public void testAfterTransactionCompoundCRS() throws Exception { Map<Object, Object> extendedProperties = new HashMap<Object, Object>(); final CoordinateReferenceSystem compoundCrs = CRS.decode("EPSG:7415"); ReferencedEnvelope3D transactionBounds = new ReferencedEnvelope3D(142892, 470783, 142900, 470790, 16, 20, compoundCrs); issueInsert(extendedProperties, transactionBounds); TransactionType request = mock(TransactionType.class); TransactionResponseType result = mock(TransactionResponseType.class); when(request.getExtendedProperties()).thenReturn(extendedProperties); when(mediator.getDeclaredCrs(anyString())).thenReturn(compoundCrs); listener.afterTransaction(request, result, true); ReferencedEnvelope expectedBounds = new ReferencedEnvelope(transactionBounds, CRS.getHorizontalCRS(compoundCrs)); verify(mediator, times(1)).truncate(eq("theLayer"), eq(expectedBounds)); verify(mediator, times(1)).truncate(eq("theGroup"), eq(expectedBounds)); } @Test public void testAfterTransaction() throws Exception { Map<Object, Object> extendedProperties = new HashMap<Object, Object>(); ReferencedEnvelope affectedBounds1 = new ReferencedEnvelope(-180, 0, 0, 90, WGS84); ReferencedEnvelope affectedBounds2 = new ReferencedEnvelope(0, 180, 0, 90, WGS84); issueInsert(extendedProperties, affectedBounds1); issueInsert(extendedProperties, affectedBounds2); TransactionType request = mock(TransactionType.class); TransactionResponseType result = mock(TransactionResponseType.class); when(request.getExtendedProperties()).thenReturn(extendedProperties); when(mediator.getDeclaredCrs(anyString())).thenReturn(WGS84); listener.afterTransaction(request, result, true); ReferencedEnvelope expectedEnv = new ReferencedEnvelope(affectedBounds1); expectedEnv.expandToInclude(affectedBounds2); verify(mediator, times(1)).truncate(eq("theLayer"), eq(expectedEnv)); verify(mediator, times(1)).truncate(eq("theGroup"), eq(expectedEnv)); } /** * Issues a fake dataStoreChange insert event that affects two tile layers: "theLayer" and * "theGroup" */ private void issueInsert(Map<Object, Object> extendedProperties, ReferencedEnvelope affectedBounds) { TransactionType transaction = mock(TransactionType.class); when(transaction.getExtendedProperties()).thenReturn(extendedProperties); TransactionEvent event = mock(TransactionEvent.class); when(event.getRequest()).thenReturn(transaction); QName layerName = new QName("testType"); when(event.getLayerName()).thenReturn(layerName); InsertElementType insert = mock(InsertElementType.class); when(event.getSource()).thenReturn(insert); when(event.getType()).thenReturn(TransactionEventType.PRE_INSERT); when( mediator.getTileLayersByFeatureType(eq(layerName.getNamespaceURI()), eq(layerName.getLocalPart()))).thenReturn( ImmutableSet.of("theLayer", "theGroup")); SimpleFeatureCollection affectedFeatures = mock(SimpleFeatureCollection.class); when(affectedFeatures.getBounds()).thenReturn(affectedBounds); when(event.getAffectedFeatures()).thenReturn(affectedFeatures); listener.dataStoreChange(event); } }