Package org.geoserver.gwc

Source Code of org.geoserver.gwc.GWCTest

/* (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.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.geoserver.gwc.GWC.tileLayerName;
import static org.geoserver.gwc.GWCTestHelpers.mockGroup;
import static org.geoserver.gwc.GWCTestHelpers.mockLayer;
import static org.geoserver.gwc.layer.TileLayerInfoUtil.updateAcceptAllFloatParameterFilter;
import static org.geoserver.gwc.layer.TileLayerInfoUtil.updateStringParameterFilter;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.event.CatalogListener;
import org.geoserver.gwc.config.GWCConfig;
import org.geoserver.gwc.config.GWCConfigPersister;
import org.geoserver.gwc.layer.CatalogLayerEventListener;
import org.geoserver.gwc.layer.CatalogStyleChangeListener;
import org.geoserver.gwc.layer.GeoServerTileLayer;
import org.geoserver.gwc.layer.GeoServerTileLayerInfo;
import org.geoserver.gwc.layer.TileLayerInfoUtil;
import org.geoserver.ows.Dispatcher;
import org.geoserver.ows.util.CaseInsensitiveMap;
import org.geoserver.security.GeoServerSecurityManager;
import org.geoserver.security.config.SecurityManagerConfig;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.kvp.PaletteManager;
import org.geotools.filter.identity.FeatureIdImpl;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geowebcache.GeoWebCacheException;
import org.geowebcache.config.Configuration;
import org.geowebcache.config.XMLConfiguration;
import org.geowebcache.config.XMLGridSet;
import org.geowebcache.config.XMLGridSubset;
import org.geowebcache.conveyor.ConveyorTile;
import org.geowebcache.diskquota.DiskQuotaMonitor;
import org.geowebcache.diskquota.QuotaStore;
import org.geowebcache.grid.BoundingBox;
import org.geowebcache.grid.GridSet;
import org.geowebcache.grid.GridSetBroker;
import org.geowebcache.grid.GridSubset;
import org.geowebcache.grid.SRS;
import org.geowebcache.layer.TileLayer;
import org.geowebcache.layer.TileLayerDispatcher;
import org.geowebcache.mime.MimeType;
import org.geowebcache.seed.GWCTask;
import org.geowebcache.seed.TileBreeder;
import org.geowebcache.service.Service;
import org.geowebcache.storage.DefaultStorageFinder;
import org.geowebcache.storage.StorageBroker;
import org.geowebcache.storage.StorageException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.vividsolutions.jts.geom.Envelope;

/**
* Unit test suite for the {@link GWC} mediator.
*
*/
/**
* @author groldan
*
*/
public class GWCTest {

    private GWC mediator;

    private GWCConfig defaults;

    private GWCConfigPersister gwcConfigPersister;

    private StorageBroker storageBroker;

    private GridSetBroker gridSetBroker;

    private Configuration config;

    private TileLayerDispatcher tld;

    private TileBreeder tileBreeder;

    private QuotaStore quotaStore;

    private DiskQuotaMonitor diskQuotaMonitor;

    private Dispatcher owsDispatcher;

    private Catalog catalog;

    LayerInfo layer;

    LayerGroupInfo layerGroup;

    GeoServerTileLayerInfo tileLayerInfo;

    GeoServerTileLayerInfo tileLayerGroupInfo;

    GeoServerTileLayer tileLayer;

    GeoServerTileLayer tileLayerGroup;

    private DefaultStorageFinder storageFinder;

    private JDBCConfigurationStorage jdbcStorage;

    @Before
    public void setUp() throws Exception {
        catalog = mock(Catalog.class);
        layer = mockLayer("testLayer", new String[]{"style1", "style2"}, LayerInfo.Type.RASTER);
        layerGroup = mockGroup("testGroup", layer);
        mockCatalog();

        defaults = GWCConfig.getOldDefaults();

        gwcConfigPersister = mock(GWCConfigPersister.class);
        when(gwcConfigPersister.getConfig()).thenReturn(defaults);

        storageBroker = mock(StorageBroker.class);
        gridSetBroker = new GridSetBroker(true, true);

        tileLayerInfo = TileLayerInfoUtil.loadOrCreate(layer, defaults);
        tileLayerGroupInfo = TileLayerInfoUtil.loadOrCreate(layerGroup, defaults);

        tileLayer = new GeoServerTileLayer(layer, gridSetBroker, tileLayerInfo);
        tileLayerGroup = new GeoServerTileLayer(layerGroup, gridSetBroker, tileLayerGroupInfo);

        tld = mock(TileLayerDispatcher.class);
        mockTileLayerDispatcher();

        config = mock(Configuration.class);
        tileBreeder = mock(TileBreeder.class);
        quotaStore = mock(QuotaStore.class);
        diskQuotaMonitor = mock(DiskQuotaMonitor.class);
        when(diskQuotaMonitor.getQuotaStore()).thenReturn(quotaStore);
        owsDispatcher = mock(Dispatcher.class);
       
        storageFinder = mock(DefaultStorageFinder.class);
        jdbcStorage = mock(JDBCConfigurationStorage.class);

        mediator = new GWC(gwcConfigPersister, storageBroker, tld, gridSetBroker, tileBreeder,
                diskQuotaMonitor, owsDispatcher, catalog, storageFinder, jdbcStorage);

        GWC.set(mediator);
    }

    @After
    public void tearDown() {
        GWC.set(null);
    }

    private void mockCatalog() {
        when(catalog.getLayers()).thenReturn(Arrays.asList(layer));
        when(catalog.getLayerGroups()).thenReturn(Arrays.asList(layerGroup));
        when(catalog.getLayer(eq(layer.getId()))).thenReturn(layer);
        when(catalog.getLayerGroup(layerGroup.getId())).thenReturn(layerGroup);
        when(catalog.getLayerByName(eq(layer.getResource().prefixedName()))).thenReturn(layer);
        when(catalog.getLayerGroupByName(tileLayerName(layerGroup))).thenReturn(layerGroup);
    }

    private void mockTileLayerDispatcher() throws Exception {
        when(tld.getConfiguration(same(tileLayer))).thenReturn(config);
        when(tld.getConfiguration(same(tileLayerGroup))).thenReturn(config);
        when(tld.getConfiguration(eq(tileLayer.getName()))).thenReturn(config);
        when(tld.getConfiguration(eq(tileLayerGroup.getName()))).thenReturn(config);

        when(tld.getTileLayer(eq(tileLayer.getName()))).thenReturn(tileLayer);
        when(tld.getTileLayer(eq(tileLayerGroup.getName()))).thenReturn(tileLayerGroup);

        when(tld.getLayerNames()).thenReturn(
                ImmutableSet.of(tileLayer.getName(), tileLayerGroup.getName()));
        Iterable<TileLayer> tileLayers = ImmutableList.of((TileLayer) tileLayer,
                (TileLayer) tileLayerGroup);
        when(tld.getLayerList()).thenReturn(tileLayers);

        when(tld.layerExists(eq(tileLayer.getName()))).thenReturn(true);
        when(tld.layerExists(eq(tileLayerGroup.getName()))).thenReturn(true);
    }

    public void testAddTileLayer() throws Exception {

        when(tld.addLayer(same(tileLayer))).thenThrow(new IllegalArgumentException("fake"));
        when(tld.addLayer(same(tileLayerGroup))).thenReturn(config);

        try {
            mediator.add(tileLayer);
            fail("Expected IAE");
        } catch (IllegalArgumentException e) {
            assertTrue(true);
        }

        mediator.add(tileLayerGroup);
        verify(config, times(1)).save();
    }

    @Test
    public void testModifyTileLayer() throws Exception {
        try {
            mediator.save(null);
            fail();
        } catch (NullPointerException e) {
            assertTrue(true);
        }

        when(tld.modify(same(tileLayer))).thenThrow(new IllegalArgumentException());
        try {
            mediator.save(tileLayer);
            fail();
        } catch (IllegalArgumentException e) {
            assertTrue(true);
        }

        when(tld.modify(same(tileLayerGroup))).thenReturn(config);
        mediator.save(tileLayerGroup);
        verify(config, times(1)).save();

        when(tld.modify(same(tileLayer))).thenReturn(config);
        doThrow(new IOException()).when(config).save();
        try {
            mediator.save(tileLayer);
        } catch (RuntimeException e) {
            assertTrue(true);
        }
    }

    @Test
    public void testRemoveTileLayers() throws Exception {
        try {
            mediator.removeTileLayers(null);
        } catch (NullPointerException e) {
            assertTrue(true);
        }

        when(tld.removeLayer(eq(tileLayer.getName()))).thenReturn(config);
        when(tld.removeLayer(eq(tileLayerGroup.getName()))).thenReturn(config);

        List<String> layerNames = Arrays.asList(tileLayer.getName(), tileLayerGroup.getName());
        mediator.removeTileLayers(layerNames);
        verify(tld, times(1)).removeLayer(eq(tileLayer.getName()));
        verify(tld, times(1)).removeLayer(eq(tileLayerGroup.getName()));
        verify(config, times(1)).save();
    }

    @Test
    public void testAddGridset() throws Exception {
        try {
            mediator.addGridSet(null);
            fail();
        } catch (NullPointerException e) {
            assertTrue(true);
        }
        GridSet gset = mock(GridSet.class);
        GridSet gset2 = mock(GridSet.class);
        doThrow(new IOException("fake")).when(tld).addGridSet(same(gset));
        try {
            mediator.addGridSet(gset);
            fail();
        } catch (IOException e) {
            assertEquals("fake", e.getMessage());
        }
        mediator.addGridSet(gset2);
        verify(tld, times(1)).addGridSet(same(gset2));
    }

    @Test
    public void testModifyGridsetPreconditions() throws Exception {
        GridSet oldGridset = gridSetBroker.get("EPSG:4326");
        try {
            mediator.modifyGridSet(null, oldGridset);
            fail();
        } catch (NullPointerException e) {
            assertTrue(true);
        }
        try {
            mediator.modifyGridSet("oldname", null);
            fail();
        } catch (NullPointerException e) {
            assertTrue(true);
        }
        try {
            mediator.modifyGridSet("wrongOldName", oldGridset);
            fail();
        } catch (IllegalArgumentException e) {
            assertTrue(e.getMessage().contains("does not exist"));
        }
    }

    @Test
    public void testModifyGridsetNoNeedToTruncate() throws Exception {
        final String oldName = "EPSG:4326";
        final String newName = "MyEPSG:4326";

        final GridSet oldGridset = gridSetBroker.get(oldName);
        final GridSet newGridset;
        {
            XMLGridSet xmlGridSet = new XMLGridSet(oldGridset);
            xmlGridSet.setName(newName);
            newGridset = xmlGridSet.makeGridSet();
        }

        XMLConfiguration xmlConfig = mock(XMLConfiguration.class);
        mediator = spy(mediator);
        when(mediator.getXmlConfiguration()).thenReturn(xmlConfig);

        assertNotNull(tileLayer.getGridSubset(oldName));
        assertNotNull(tileLayerGroup.getGridSubset(oldName));

        when(tld.getConfiguration(same(tileLayer))).thenReturn(config);
        when(tld.getConfiguration(same(tileLayerGroup))).thenReturn(config);
        mediator.modifyGridSet(oldName, newGridset);

        assertNull(tileLayer.getGridSubset(oldName));
        assertNull(tileLayerGroup.getGridSubset(oldName));
        assertNotNull(tileLayer.getGridSubset(newName));
        assertNotNull(tileLayerGroup.getGridSubset(newName));

        verify(xmlConfig, times(1)).removeGridset(eq(oldName));
        verify(xmlConfig, times(1)).addOrReplaceGridSet(eq(new XMLGridSet(newGridset)));
        verify(xmlConfig, times(1)).save();

        assertNull(gridSetBroker.get(oldName));
        assertEquals(newGridset, gridSetBroker.get(newName));

        verify(config, times(1)).save();
    }

    @Test
    public void testModifyGridsetTruncates() throws Exception {
        final String oldName = "EPSG:4326";
        final String newName = "MyEPSG:4326";

        final GridSet oldGridset = gridSetBroker.get(oldName);
        final GridSet newGridset;
        {
            XMLGridSet xmlGridSet = new XMLGridSet(oldGridset);
            xmlGridSet.setName(newName);

            // make it so the gridset forces truncation
            xmlGridSet.setAlignTopLeft(!xmlGridSet.getAlignTopLeft());
            newGridset = xmlGridSet.makeGridSet();
        }

        XMLConfiguration xmlConfig = mock(XMLConfiguration.class);
        mediator = spy(mediator);
        when(mediator.getXmlConfiguration()).thenReturn(xmlConfig);
        when(tld.getConfiguration(same(tileLayer))).thenReturn(config);
        when(tld.getConfiguration(same(tileLayerGroup))).thenReturn(config);

        mediator.modifyGridSet(oldName, newGridset);

        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayer.getName()), eq(oldName));
        verify(storageBroker, times(1))
                .deleteByGridSetId(eq(tileLayerGroup.getName()), eq(oldName));
    }

    @Test
    public void testRemoveGridsets() throws Exception {
        try {
            mediator.removeGridSets(null);
            fail();
        } catch (NullPointerException e) {
            assertTrue(true);
        }

        {
            final GridSet oldGridset = gridSetBroker.get("EPSG:4326");
            final GridSet newGridset;
            XMLGridSet xmlGridSet = new XMLGridSet(oldGridset);
            xmlGridSet.setName("My4326");
            // make it a bit different
            xmlGridSet.setAlignTopLeft(!xmlGridSet.getAlignTopLeft());
            newGridset = xmlGridSet.makeGridSet();
            gridSetBroker.put(newGridset);
        }

        when(tld.getConfiguration(same(tileLayer))).thenReturn(config);
        when(tld.getConfiguration(same(tileLayerGroup))).thenReturn(config);
        when(tld.modify(same(tileLayer))).thenReturn(config);
        when(tld.modify(same(tileLayerGroup))).thenReturn(config);
        when(tld.removeGridset(eq("EPSG:4326"))).thenReturn(config);
        when(tld.removeGridset(eq("My4326"))).thenReturn(config);

        mediator.removeGridSets(ImmutableSet.of("My4326", "EPSG:4326"));

        assertEquals(ImmutableSet.of("EPSG:900913"), tileLayer.getGridSubsets());
        assertEquals(ImmutableSet.of("EPSG:900913"), tileLayerGroup.getGridSubsets());

        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayer.getName()), eq("EPSG:4326"));
        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayerGroup.getName()),
                eq("EPSG:4326"));

        verify(storageBroker, never())
                .deleteByGridSetId(eq(tileLayer.getName()), eq("EPSG:900913"));
        verify(storageBroker, never()).deleteByGridSetId(eq(tileLayer.getName()), eq("My4326"));
        verify(storageBroker, never()).deleteByGridSetId(eq(tileLayerGroup.getName()),
                eq("EPSG:900913"));
        verify(storageBroker, never())
                .deleteByGridSetId(eq(tileLayerGroup.getName()), eq("My4326"));

        verify(tld, times(1)).modify(same(tileLayer));
        verify(tld, times(1)).modify(same(tileLayerGroup));
        verify(tld, times(1)).removeGridset(eq("EPSG:4326"));
        verify(tld, times(1)).removeGridset(eq("My4326"));
        // all these modifications, and a single save()
        verify(config, times(1)).save();
    }

    @Test
    public void testRemoveAllLayerGridsetsDisablesLayer() throws Exception {

        when(tld.getConfiguration(same(tileLayer))).thenReturn(config);
        when(tld.getConfiguration(same(tileLayerGroup))).thenReturn(config);
        when(tld.modify(same(tileLayer))).thenReturn(config);
        when(tld.modify(same(tileLayerGroup))).thenReturn(config);
        when(tld.removeGridset(eq("EPSG:4326"))).thenReturn(config);
        when(tld.removeGridset(eq("EPSG:900913"))).thenReturn(config);

        // sanity check before modification
        assertTrue(tileLayer.getInfo().isEnabled());
        assertTrue(tileLayer.getInfo().isEnabled());

        mediator.removeGridSets(ImmutableSet.of("EPSG:900913", "EPSG:4326"));

        verify(config, times(1)).save();// all other checks are in testRemoveGridsets
        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayer.getName()), eq("EPSG:4326"));
        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayerGroup.getName()),
                eq("EPSG:900913"));
        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayer.getName()), eq("EPSG:4326"));
        verify(storageBroker, times(1)).deleteByGridSetId(eq(tileLayerGroup.getName()),
                eq("EPSG:900913"));

        assertTrue(tileLayer.getGridSubsets().isEmpty());
        assertTrue(tileLayerGroup.getGridSubsets().isEmpty());

        // layers ended up with no gridsubsets, shall have been disabled
        assertFalse(tileLayer.getInfo().isEnabled());
        assertFalse(tileLayerGroup.getInfo().isEnabled());
    }

    @Test
    public void testAutoConfigureLayers() throws Exception {
        {
            GWCConfig insaneDefaults = new GWCConfig();
            insaneDefaults.setMetaTilingX(-1);
            assertFalse(insaneDefaults.isSane());
            try {
                mediator.autoConfigureLayers(Arrays.asList(tileLayer.getName()), insaneDefaults);
            } catch (IllegalArgumentException e) {
                assertTrue(true);
            }
        }

        try {
            mediator.autoConfigureLayers(Arrays.asList(tileLayer.getName()), defaults);
            fail("expected IAE, layer exists");
        } catch (IllegalArgumentException e) {
            assertTrue(true);
        }

        LayerInfo layer2 = mockLayer("layer2", new String[]{}, LayerInfo.Type.RASTER);
        LayerGroupInfo group2 = mockGroup("group2", layer, layer2);

        when(catalog.getLayerByName(eq(tileLayerName(layer2)))).thenReturn(layer2);
        when(catalog.getLayerGroupByName(eq(tileLayerName(group2)))).thenReturn(group2);

        List<String> layerNames = Arrays.asList(tileLayerName(layer2), tileLayerName(group2));

        when(tld.addLayer(any(GeoServerTileLayer.class))).thenReturn(config);
        mediator.autoConfigureLayers(layerNames, defaults);

        GeoServerTileLayerInfo expected1 = new GeoServerTileLayer(layer2, defaults, gridSetBroker)
                .getInfo();
        GeoServerTileLayerInfo expected2 = new GeoServerTileLayer(group2, defaults, gridSetBroker)
                .getInfo();

        ArgumentCaptor<GeoServerTileLayer> addCaptor = ArgumentCaptor
                .forClass(GeoServerTileLayer.class);

        verify(tld, times(2)).addLayer(addCaptor.capture());
        verify(config, times(2)).save();

        GeoServerTileLayerInfo actual1 = addCaptor.getAllValues().get(0).getInfo();
        GeoServerTileLayerInfo actual2 = addCaptor.getAllValues().get(1).getInfo();

        assertEquals(expected1, actual1);
        assertEquals(expected2, actual2);
    }

    @Test
    public void testIsInternalGridset() {

        Set<String> embeddedNames = gridSetBroker.getEmbeddedNames();
        for (String name : embeddedNames) {
            assertTrue(mediator.isInternalGridSet(name));
        }

        assertFalse(mediator.isInternalGridSet("somethingelse"));
    }

    @Test
    public void testDeleteCacheByGridSetId() throws Exception {

        when(storageBroker.deleteByGridSetId(eq("layer"), eq("gset1"))).thenThrow(
                new StorageException("fake"));

        try {
            mediator.deleteCacheByGridSetId("layer", "gset1");
            fail();
        } catch (RuntimeException e) {
            assertTrue(true);
        }
        mediator.deleteCacheByGridSetId("layer", "gset2");
        verify(storageBroker, times(1)).deleteByGridSetId(eq("layer"), eq("gset2"));

    }

    @Test
    public void testDestroy() throws Exception {

        mediator.destroy();

        ArgumentCaptor<CatalogListener> captor = ArgumentCaptor.forClass(CatalogListener.class);
        verify(catalog, times(2)).removeListener(captor.capture());
        for (CatalogListener captured : captor.getAllValues()) {
            assertTrue(captured instanceof CatalogLayerEventListener
                    || captured instanceof CatalogStyleChangeListener);
        }
    }

    @Test
    public void testTruncateLayerFully() throws Exception {

        when(tld.getTileLayer(eq(tileLayerGroup.getName()))).thenThrow(
                new GeoWebCacheException("fake"));

        mediator.truncate(tileLayerGroup.getName());
        verify(storageBroker, never()).deleteByGridSetId(anyString(), anyString());

        mediator.truncate(tileLayer.getName());
        verify(storageBroker, times(tileLayer.getGridSubsets().size())).deleteByGridSetId(
                anyString(), anyString());

    }

    @Test
    public void testTruncateByLayerAndStyle() throws Exception {

        String layerName = tileLayer.getName();
        String styleName = "notACachedStyle";

        mediator.truncateByLayerAndStyle(layerName, styleName);
        verify(tileBreeder, never()).dispatchTasks(any(GWCTask[].class));

        styleName = layer.getDefaultStyle().getName();
        mediator.truncateByLayerAndStyle(layerName, styleName);

        int expected = tileLayer.getGridSubsets().size() * tileLayer.getMimeTypes().size();
        verify(tileBreeder, times(expected)).dispatchTasks(any(GWCTask[].class));
    }

    @Test
    public void testTruncateByBounds() throws Exception {

        String layerName = tileLayer.getName();
        ReferencedEnvelope bounds;
        // bounds outside layer bounds (which are -180,0,0,90)
        bounds = new ReferencedEnvelope(10, 20, 10, 20, DefaultGeographicCRS.WGS84);
        BoundingBox layerBounds = tileLayer.getGridSubset("EPSG:4326").getGridSet()
                .getOriginalExtent();

        assertFalse(bounds.intersects(layerBounds.getMinX(), layerBounds.getMinY()));
        assertFalse(bounds.intersects(layerBounds.getMaxX(), layerBounds.getMaxY()));

        mediator.truncate(layerName, bounds);

        verify(tileBreeder, never()).dispatchTasks(any(GWCTask[].class));

        // bounds intersecting layer bounds
        bounds = new ReferencedEnvelope(-10, -10, 10, 10, DefaultGeographicCRS.WGS84);

        mediator.truncate(layerName, bounds);

        int numGridsets = tileLayer.getGridSubsets().size();
        int numFormats = tileLayer.getMimeTypes().size();
        int numStyles = 1/* default */+ tileLayer.getInfo().cachedStyles().size();
        final int expected = numGridsets * numFormats * numStyles;
        verify(tileBreeder, times(expected)).dispatchTasks(any(GWCTask[].class));

        reset(tileBreeder);
        bounds = bounds.transform(CRS.decode("EPSG:900913"), true);
        mediator.truncate(layerName, bounds);
        verify(tileBreeder, times(expected)).dispatchTasks(any(GWCTask[].class));

        reset(tileBreeder);
        bounds = mediator.getAreaOfValidity(CRS.decode("EPSG:2083"));// Terra del Fuego
        mediator.truncate(layerName, bounds);
        verify(tileBreeder, never()).dispatchTasks(any(GWCTask[].class));

        reset(tileBreeder);
        bounds = mediator.getAreaOfValidity(CRS.decode("EPSG:26986"));// Massachussets
        mediator.truncate(layerName, bounds);
        verify(tileBreeder, times(expected)).dispatchTasks(any(GWCTask[].class));
    }

    @Test
    public void testLayerRemoved() throws Exception {
        mediator.layerRemoved("someLayer");
        verify(storageBroker, times(1)).delete(eq("someLayer"));

        doThrow(new StorageException("fake")).when(storageBroker).delete(eq("anotherLayer"));
        try {
            mediator.layerRemoved("anotherLayer");
            fail("Expected RTE");
        } catch (RuntimeException e) {
            assertTrue(e.getCause() instanceof StorageException);
        }
    }

    @Test
    public void testLayerAdded() throws Exception {

        when(diskQuotaMonitor.isEnabled()).thenReturn(false);
        mediator.layerAdded("someLayer");
        verify(quotaStore, never()).createLayer(anyString());

        when(diskQuotaMonitor.isEnabled()).thenReturn(true);

        mediator.layerAdded("someLayer");
        verify(quotaStore, times(1)).createLayer(eq("someLayer"));

        doThrow(new InterruptedException("fake")).when(quotaStore).createLayer(eq("someLayer"));
        try {
            mediator.layerAdded("someLayer");
            fail("Expected RTE");
        } catch (RuntimeException e) {
            assertTrue(e.getCause() instanceof InterruptedException);
        }
    }

    @Test
    public void testLayerRenamed() throws Exception {

        mediator.layerRenamed("old", "new");
        verify(storageBroker, times(1)).rename(eq("old"), eq("new"));

        doThrow(new StorageException("target directory already exists")).when(storageBroker)
                .rename(eq("old"), eq("new"));
        try {
            mediator.layerRenamed("old", "new");
            fail("Expected RTE");
        } catch (RuntimeException e) {
            assertTrue(e.getCause() instanceof StorageException);
        }
    }

    @Test
    public void testReload() throws Exception {
        mediator.reload();
        verify(tld, times(1)).reInit();
        doThrow(new RuntimeException("fake")).when(tld).reInit();
        try {
            mediator.reload();
            fail("Expected RTE");
        } catch (RuntimeException e) {
            assertTrue(true);
        }
    }

    @Test
    public void testReloadAndLayerRemovedExternally() throws Exception {

        final String removedLayer = tileLayer.getName();
        final String remainingLayer = tileLayerGroup.getName();

        final Set<String> layerNames = Sets.newHashSet(removedLayer, remainingLayer);

        when(tld.getLayerNames()).thenReturn(layerNames);
        doAnswer(new Answer<Void>() {

            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                layerNames.remove(removedLayer);
                return null;
            }
        }).when(tld).reInit();

        ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class);

        mediator = spy(mediator);
        doReturn(true).when(mediator).layerRemoved(argCaptor.capture());

        mediator.reload();

        verify(tld, times(1)).reInit();
        assertEquals(1, argCaptor.getAllValues().size());
        assertEquals(removedLayer, argCaptor.getValue());
    }

    @Test
    public void testIsServiceEnabled() {
        Service service = mock(Service.class);

        when(service.getPathName()).thenReturn("wms");
        defaults.setWMSCEnabled(true);
        assertTrue(mediator.isServiceEnabled(service));
        defaults.setWMSCEnabled(false);
        assertFalse(mediator.isServiceEnabled(service));

        when(service.getPathName()).thenReturn("tms");
        defaults.setTMSEnabled(true);
        assertTrue(mediator.isServiceEnabled(service));
        defaults.setTMSEnabled(false);
        assertFalse(mediator.isServiceEnabled(service));

        when(service.getPathName()).thenReturn("wmts");
        defaults.setWMTSEnabled(true);
        assertTrue(mediator.isServiceEnabled(service));
        defaults.setWMTSEnabled(false);
        assertFalse(mediator.isServiceEnabled(service));

        when(service.getPathName()).thenReturn("somethingElse");
        assertTrue(mediator.isServiceEnabled(service));
    }

    @Test
    public void testDispatchGetMapDoesntMatchTileCache() throws Exception {
        GetMapRequest request = new GetMapRequest();

        @SuppressWarnings("unchecked")
        Map<String, String> rawKvp = new CaseInsensitiveMap(new HashMap<String, String>());
        request.setRawKvp(rawKvp);

        rawKvp.put("layers", "more,than,one,layer");
        assertDispatchMismatch(request, "more than one layer requested");

        rawKvp.put("layers", "SomeNonCachedLayer");
        when(tld.getTileLayer(eq("SomeNonCachedLayer"))).thenThrow(
                new GeoWebCacheException("layer not found"));
        assertDispatchMismatch(request, "not a tile layer");

        rawKvp.put("layers", tileLayer.getName());

        request.setFormat("badFormat");
        assertDispatchMismatch(request, "not a GWC supported format");

        request.setFormat("image/gif");
        assertDispatchMismatch(request, "no tile cache for requested format");
        request.setFormat(tileLayer.getMimeTypes().get(0).getMimeType());

        request.setSRS("EPSG:4326");
        request.setBbox(new Envelope(10, 10, 20, 20));
        assertDispatchMismatch(request, "request does not align to grid");

        request.setSRS("EPSG:23036");
        assertDispatchMismatch(request, "no cache exists for requested CRS");

        request.setSRS("badCRS");
        assertDispatchMismatch(request, "exception occurred");
        request.setSRS("EPSG:4326");

        request.setWidth(128);
        request.setHeight(256);
        assertDispatchMismatch(request, "request does not align to grid");

        request.setWidth(256);
        request.setHeight(128);
        assertDispatchMismatch(request, "request does not align to grid");

        request.setSRS("EPSG:4326");
        request.setWidth(256);
        request.setHeight(256);
        assertDispatchMismatch(request, "request does not align to grid");
    }

    @Test
    public void testDispatchGetMapNonMatchingParameterFilter() throws Exception {
        GetMapRequest request = new GetMapRequest();

        @SuppressWarnings("unchecked")
        Map<String, String> rawKvp = new CaseInsensitiveMap(new HashMap<String, String>());
        request.setRawKvp(rawKvp);

        rawKvp.put("layers", tileLayer.getName());
        tileLayer.setEnabled(false);
        assertDispatchMismatch(request, "tile layer disabled");

        tileLayer.setEnabled(true);
        assertTrue(layer.enabled());

        request.setRemoteOwsURL(new URL("http://example.com"));
        assertDispatchMismatch(request, "remote OWS");
        request.setRemoteOwsURL(null);

        request.setRemoteOwsType("WFS");
        assertDispatchMismatch(request, "remote OWS");
        request.setRemoteOwsType(null);

        request.setEnv(ImmutableMap.of("envVar", "envValue"));
        assertDispatchMismatch(request, "no parameter filter exists for ENV");
        request.setEnv(null);

        request.setFormatOptions(ImmutableMap.of("optKey", "optVal"));
        assertDispatchMismatch(request, "no parameter filter exists for FORMAT_OPTIONS");
        request.setFormatOptions(null);

        request.setAngle(45);
        assertDispatchMismatch(request, "no parameter filter exists for ANGLE");
        request.setAngle(0);

        rawKvp.put("BGCOLOR", "0xAA0000");
        assertDispatchMismatch(request, "no parameter filter exists for BGCOLOR");
        rawKvp.remove("BGCOLOR");

        request.setBuffer(10);
        assertDispatchMismatch(request, "no parameter filter exists for BUFFER");
        request.setBuffer(0);

        request.setCQLFilter(Arrays.asList(CQL.toFilter("ATT = 1")));
        assertDispatchMismatch(request, "no parameter filter exists for CQL_FILTER");
        request.setCQLFilter(null);

        request.setElevation(10D);
        assertDispatchMismatch(request, "no parameter filter exists for ELEVATION");
        request.setElevation(Collections.emptyList());

        request.setFeatureId(Arrays.asList(new FeatureIdImpl("someid")));
        assertDispatchMismatch(request, "no parameter filter exists for FEATUREID");
        request.setFeatureId(null);

        request.setFilter(Arrays.asList(CQL.toFilter("ATT = 1")));
        assertDispatchMismatch(request, "no parameter filter exists for FILTER");
        request.setFilter(null);

        request.setPalette(PaletteManager.getPalette("SAFE"));
        assertDispatchMismatch(request, "no parameter filter exists for PALETTE");
        request.setPalette(null);

        request.setStartIndex(10);
        assertDispatchMismatch(request, "no parameter filter exists for STARTINDEX");
        request.setStartIndex(null);

        request.setMaxFeatures(1);
        assertDispatchMismatch(request, "no parameter filter exists for MAXFEATURES");
        request.setMaxFeatures(null);

        request.setTime(Arrays.asList((Object) 1, (Object) 2));
        assertDispatchMismatch(request, "no parameter filter exists for TIME");
        request.setTime(Collections.emptyList());

        List<Map<String, String>> viewParams = ImmutableList.of((Map<String, String>) ImmutableMap
                .of("paramKey", "paramVal"));
        request.setViewParams(viewParams);
        assertDispatchMismatch(request, "no parameter filter exists for VIEWPARAMS");
        request.setViewParams(null);

        request.setFeatureVersion("@version");
        assertDispatchMismatch(request, "no parameter filter exists for FEATUREVERSION");
        request.setFeatureVersion(null);
    }

    /**
     * See GEOS-5003
     */
    @Test
    public void testNullsInDimensionAndTimeParameters() throws Exception {
        TileLayerInfoUtil.updateAcceptAllFloatParameterFilter(tileLayerInfo, "ELEVATION", true);
        TileLayerInfoUtil.updateAcceptAllRegExParameterFilter(tileLayerInfo, "TIME", true);
        tileLayer = new GeoServerTileLayer(layer, gridSetBroker, tileLayerInfo);

        GetMapRequest request = new GetMapRequest();
        @SuppressWarnings("unchecked")
        Map<String, String> rawKvp = new CaseInsensitiveMap(new HashMap<String, String>());
        request.setRawKvp(rawKvp);

        StringBuilder target = new StringBuilder();

        boolean cachingPossible;

        request.setElevation(Arrays.asList((Object) null));
        cachingPossible = mediator.isCachingPossible(tileLayer, request, target);
        assertTrue(cachingPossible);
        assertEquals(0, target.length());
        request.setElevation(Collections.emptyList());

        request.setTime(Arrays.asList((Object) null));
        cachingPossible = mediator.isCachingPossible(tileLayer, request, target);
        assertTrue(cachingPossible);
        assertEquals(0, target.length());
    }

    private void assertDispatchMismatch(GetMapRequest request, String expectedReason) {

        StringBuilder target = new StringBuilder();
        assertNull(mediator.dispatch(request, target));
        assertTrue("mismatch reason '" + target + "' does not contain '" + expectedReason + "'",
                target.toString().contains(expectedReason));
    }

    @Test
    public void testDispatchGetMapMultipleCrsMatchingGridSubsets() throws Exception {

        testMultipleCrsMatchingGridSubsets("EPSG:4326", "EPSG:4326", new long[] { 1, 1, 1 });
        testMultipleCrsMatchingGridSubsets("EPSG:4326", "EPSG:4326", new long[] { 10, 10, 10 });

        testMultipleCrsMatchingGridSubsets("EPSG:4326", "GlobalCRS84Scale", new long[] { 1, 1, 1 });
        testMultipleCrsMatchingGridSubsets("EPSG:4326", "GlobalCRS84Scale",
                new long[] { 10, 10, 10 });

        testMultipleCrsMatchingGridSubsets("EPSG:4326", "GlobalCRS84Scale", new long[] { 1, 1, 1 });
        testMultipleCrsMatchingGridSubsets("EPSG:4326", "GlobalCRS84Scale",
                new long[] { 10, 10, 10 });

    }

    private void testMultipleCrsMatchingGridSubsets(final String srs, final String expectedGridset,
            long[] tileIndex) throws Exception {
        GetMapRequest request = new GetMapRequest();

        @SuppressWarnings("unchecked")
        Map<String, String> rawKvp = new CaseInsensitiveMap(new HashMap<String, String>());
        request.setRawKvp(rawKvp);
        request.setFormat("image/png");

        request.setSRS(srs);

        request.setWidth(256);
        request.setHeight(256);
        rawKvp.put("layers", "mockLayer");
        List<String> gridSetNames = Arrays.asList("GlobalCRS84Pixel", "GlobalCRS84Scale",
                "EPSG:4326");
        tileLayer = mockTileLayer("mockLayer", gridSetNames);

        // make the request match a tile in the expected gridset
        BoundingBox bounds;
        bounds = tileLayer.getGridSubset(expectedGridset).boundsFromIndex(tileIndex);

        Envelope reqBbox = new Envelope(bounds.getMinX(), bounds.getMaxX(), bounds.getMinY(),
                bounds.getMaxY());
        request.setBbox(reqBbox);

        ArgumentCaptor<ConveyorTile> captor = ArgumentCaptor.forClass(ConveyorTile.class);
        StringBuilder errors = new StringBuilder();

        mediator.dispatch(request, errors);

        assertTrue(errors.toString(), errors.length() == 0);

        verify(tileLayer, times(1)).getTile(captor.capture());

        ConveyorTile tileRequest = captor.getValue();

        assertEquals(expectedGridset, tileRequest.getGridSetId());
        assertEquals("image/png", tileRequest.getMimeType().getMimeType());
        assertTrue(
                "Expected " + Arrays.toString(tileIndex) + " got "
                        + Arrays.toString(tileRequest.getTileIndex()),

                Arrays.equals(tileIndex, tileRequest.getTileIndex()));
    }

    private GeoServerTileLayer mockTileLayer(String layerName, List<String> gridSetNames)
            throws Exception {

        GeoServerTileLayer tileLayer = mock(GeoServerTileLayer.class);
        when(tld.layerExists(eq(layerName))).thenReturn(true);
        when(tld.getTileLayer(eq(layerName))).thenReturn(tileLayer);
        when(tileLayer.getName()).thenReturn(layerName);
        when(tileLayer.isEnabled()).thenReturn(true);

        final MimeType mimeType1 = MimeType.createFromFormat("image/png");
        final MimeType mimeType2 = MimeType.createFromFormat("image/jpeg");
        when(tileLayer.getMimeTypes()).thenReturn(ImmutableList.of(mimeType1, mimeType2));

        Map<String, GridSubset> subsets = Maps.newHashMap();
        Multimap<SRS, GridSubset> bySrs = LinkedHashMultimap.create();

        GridSetBroker broker = gridSetBroker;

        for (String gsetName : gridSetNames) {
            GridSet gridSet = broker.get(gsetName);
            XMLGridSubset xmlGridSubset = new XMLGridSubset();
            String gridSetName = gridSet.getName();
            xmlGridSubset.setGridSetName(gridSetName);
            GridSubset gridSubSet = xmlGridSubset.getGridSubSet(broker);
            subsets.put(gsetName, gridSubSet);
            bySrs.put(gridSet.getSrs(), gridSubSet);

            when(tileLayer.getGridSubset(eq(gsetName))).thenReturn(gridSubSet);

        }
        for (SRS srs : bySrs.keySet()) {
            List<GridSubset> list = ImmutableList.copyOf(bySrs.get(srs));
            when(tileLayer.getGridSubsetsForSRS(eq(srs))).thenReturn(list);

        }
        when(tileLayer.getGridSubsets()).thenReturn(subsets.keySet());

        // sanity check
        for (String gsetName : gridSetNames) {
            assertTrue(tileLayer.getGridSubsets().contains(gsetName));
            assertNotNull(tileLayer.getGridSubset(gsetName));
        }

        return tileLayer;
    }

    @Test
    public void testDispatchGetMapWithMatchingParameterFilters() throws Exception {
        GetMapRequest request = new GetMapRequest();

        @SuppressWarnings("unchecked")
        Map<String, String> rawKvp = new CaseInsensitiveMap(new HashMap<String, String>());
        request.setRawKvp(rawKvp);
        request.setFormat("image/png");
        request.setSRS("EPSG:900913");
        request.setWidth(256);
        request.setHeight(256);
        rawKvp.put("layers", tileLayer.getName());

        // tileLayer = mockTileLayer("mockLayer", ImmutableList.of("EPSG:900913", "EPSG:4326"));

        // make the request match a tile in the expected gridset
        BoundingBox bounds;
        bounds = tileLayer.getGridSubset("EPSG:900913").boundsFromIndex(new long[] { 0, 0, 1 });

        Envelope reqBbox = new Envelope(bounds.getMinX(), bounds.getMaxX(), bounds.getMinY(),
                bounds.getMaxY());
        request.setBbox(reqBbox);

        assertTrue(tileLayer.getInfo().cachedStyles().size() > 0);

        for (String style : tileLayer.getInfo().cachedStyles()) {

            String rawKvpParamName = "styles";
            String rawKvpParamValue = style;

            testParameterFilter(request, rawKvp, rawKvpParamName, rawKvpParamValue);
        }

        request.setEnv(ImmutableMap.of("envKey", "envValue"));
        updateStringParameterFilter(tileLayerInfo, "ENV", true, "def:devVal", "envKey:envValue",
                "envKey2:envValue2");
        testParameterFilter(request, rawKvp, "env", "envKey:envValue");

        updateAcceptAllFloatParameterFilter(tileLayerInfo, "ANGLE", true);
        request.setAngle(60);
        testParameterFilter(request, rawKvp, "angle", "60.0");

        request.setAngle(61.1);
        testParameterFilter(request, rawKvp, "angle", "61.1");

    }

    private void testParameterFilter(GetMapRequest request, Map<String, String> rawKvp,
            String rawKvpParamName, String rawKvpParamValue) {

        // set up raw kvp
        rawKvp.put(rawKvpParamName, rawKvpParamValue);

        StringBuilder errors = new StringBuilder();
        ConveyorTile tileRequest = mediator.prepareRequest(tileLayer, request, errors);
        assertTrue(errors.toString(), errors.length() == 0);

        Map<String, String> fullParameters = tileRequest.getFullParameters();
        assertEquals(fullParameters.toString(), rawKvpParamValue,
                fullParameters.get(rawKvpParamName.toUpperCase()));
    }
}
TOP

Related Classes of org.geoserver.gwc.GWCTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.