/* (c) 2014 - 2016 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 com.google.common.collect.Iterators.forEnumeration;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.union;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createMockBuilder;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
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.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
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.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.PublishedType;
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.platform.GeoServerEnvironment;
import org.geoserver.platform.resource.Files;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
import org.geoserver.security.AccessLimits;
import org.geoserver.security.CoverageAccessLimits;
import org.geoserver.security.WrapperPolicy;
import org.geoserver.security.decorators.SecuredLayerInfo;
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.GeoWebCacheEnvironment;
import org.geowebcache.GeoWebCacheException;
import org.geowebcache.GeoWebCacheExtensions;
import org.geowebcache.config.BlobStoreConfig;
import org.geowebcache.config.Configuration;
import org.geowebcache.config.ConfigurationException;
import org.geowebcache.config.FileBlobStoreConfig;
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.diskquota.jdbc.JDBCConfiguration;
import org.geowebcache.filter.parameters.StringParameterFilter;
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.SeedRequest;
import org.geowebcache.seed.TileBreeder;
import org.geowebcache.service.Service;
import org.geowebcache.storage.CompositeBlobStore;
import org.geowebcache.storage.DefaultStorageFinder;
import org.geowebcache.storage.StorageBroker;
import org.geowebcache.storage.StorageException;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opengis.filter.Filter;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
import org.springframework.context.ApplicationContext;
import com.google.common.base.Throwables;
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.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.MultiPolygon;
/**
* Unit test suite for the {@link GWC} mediator.
*
*/
/**
* @author groldan
*
*/
public class GWCTest {
private GWC mediator;
private GWCConfig defaults;
private GWCConfigPersister gwcConfigPersister;
private XMLConfiguration xmlConfig;
private StorageBroker storageBroker;
private GridSetBroker gridSetBroker;
private Configuration config;
private TileLayerDispatcher tld;
private TileBreeder tileBreeder;
private QuotaStore quotaStore;
private DiskQuotaMonitor diskQuotaMonitor;
private ConfigurableQuotaStoreProvider diskQuotaStoreProvider;
private Dispatcher owsDispatcher;
private Catalog catalog;
LayerInfo layer;
LayerGroupInfo layerGroup;
GeoServerTileLayerInfo tileLayerInfo;
GeoServerTileLayerInfo tileLayerGroupInfo;
GeoServerTileLayer tileLayer;
GeoServerTileLayer tileLayerGroup;
private DefaultStorageFinder storageFinder;
private JDBCConfigurationStorage jdbcStorage;
static Resource tmpDir() throws IOException {
Resource root = Files.asResource(new File(System.getProperty("java.io.tmpdir", ".")));
Resource directory = Resources.createRandom("tmp", "", root);
do {
FileUtils.forceDelete(directory.dir());
} while (Resources.exists(directory));
FileUtils.forceMkdir(directory.dir());
return Files.asResource(directory.dir());
}
@Rule
public ExpectedException expected = ExpectedException.none();
@Before
public void setUp() throws Exception {
System.setProperty("ALLOW_ENV_PARAMETRIZATION", "true");
System.setProperty("TEST_ENV_PROPERTY", "H2");
catalog = mock(Catalog.class);
layer = mockLayer("testLayer", new String[] { "style1", "style2" }, PublishedType.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);
diskQuotaStoreProvider = mock(ConfigurableQuotaStoreProvider.class);
when(diskQuotaMonitor.getQuotaStoreProvider()).thenReturn(diskQuotaStoreProvider);
storageFinder = mock(DefaultStorageFinder.class);
jdbcStorage = createMock(JDBCConfigurationStorage.class);
xmlConfig = mock(XMLConfiguration.class);
GeoWebCacheEnvironment genv = createMockBuilder(GeoWebCacheEnvironment.class)
.withConstructor()
.createMock();
ApplicationContext appContext = createMock(ApplicationContext.class);
expect(appContext.getBeanNamesForType(GeoWebCacheEnvironment.class))
.andReturn(new String[] { "geoWebCacheEnvironment" }).anyTimes();
Map<String, GeoWebCacheEnvironment> genvMap = new HashMap<>();
genvMap.put("geoWebCacheEnvironment", genv);
expect(appContext.getBeansOfType(GeoWebCacheEnvironment.class))
.andReturn(genvMap).anyTimes();
expect(appContext.getBean("geoWebCacheEnvironment")).andReturn(genv).anyTimes();
expect(appContext.getBeanNamesForType(XMLConfiguration.class))
.andReturn(new String[] { "geoWebCacheXMLConfiguration" }).anyTimes();
Map<String, XMLConfiguration> xmlConfMap = new HashMap();
xmlConfMap.put("geoWebCacheXMLConfiguration", xmlConfig);
expect(appContext.getBeansOfType(XMLConfiguration.class))
.andReturn(xmlConfMap).anyTimes();
expect(appContext.getBean("geoWebCacheXMLConfiguration")).andReturn(xmlConfig).anyTimes();
replay(appContext);
GeoWebCacheExtensions gse = createMockBuilder(GeoWebCacheExtensions.class).createMock();
gse.setApplicationContext(appContext);
replay(gse);
List<GeoWebCacheEnvironment> extensions = GeoWebCacheExtensions
.extensions(GeoWebCacheEnvironment.class);
assertNotNull(extensions);
assertEquals(1, extensions.size());
assertTrue(extensions.contains(genv));
JDBCConfiguration jdbcConfiguration = new JDBCConfiguration();
if (GeoWebCacheEnvironment.ALLOW_ENV_PARAMETRIZATION) {
jdbcConfiguration.setDialect("${TEST_ENV_PROPERTY}");
} else {
jdbcConfiguration.setDialect("H2");
}
File jdbcConfigurationFile = File.createTempFile("jdbcConfigurationFile", ".tmp",
tmpDir().dir());
jdbcConfiguration.store(jdbcConfiguration, jdbcConfigurationFile);
JDBCConfiguration loadedConf = jdbcConfiguration.load(jdbcConfigurationFile);
jdbcStorage.setApplicationContext(appContext);
expect(jdbcStorage.getJDBCDiskQuotaConfig()).andReturn(loadedConf).anyTimes();
replay(jdbcStorage);
mediator = new GWC(gwcConfigPersister, storageBroker, tld, gridSetBroker, tileBreeder,
diskQuotaMonitor, owsDispatcher, catalog, catalog, storageFinder, jdbcStorage);
mediator.setApplicationContext(appContext);
mediator = spy(mediator);
when(mediator.getXmlConfiguration()).thenReturn(xmlConfig);
GWC.set(mediator);
}
@After
public void tearDown() {
System.clearProperty("ALLOW_ENV_PARAMETRIZATION");
System.clearProperty("TEST_ENV_PROPERTY");
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();
}
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();
}
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[] {}, PublishedType.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().prefixedName();
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();
when(tileBreeder.findTileLayer(layerName))
.thenReturn(tileLayer);
final Set<Map<String, String>> cachedParameters = tileLayer.getInfo().cachedStyles().stream()
.map(style->Collections.singletonMap("STYLES",style))
.collect(Collectors.toSet());
when(storageBroker.getCachedParameters(layerName))
.thenReturn(cachedParameters);
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)).seed(eq(layerName), any(SeedRequest.class));
reset(tileBreeder);
when(tileBreeder.findTileLayer(layerName))
.thenReturn(tileLayer);
bounds = bounds.transform(CRS.decode("EPSG:900913"), true);
mediator.truncate(layerName, bounds);
verify(tileBreeder, times(expected)).seed(eq(layerName), any(SeedRequest.class));
reset(tileBreeder);
when(tileBreeder.findTileLayer(layerName))
.thenReturn(tileLayer);
bounds = mediator.getAreaOfValidity(CRS.decode("EPSG:2083"));// Terra del Fuego Does not intersect subset
mediator.truncate(layerName, bounds);
verify(tileBreeder, times(0)).seed(eq(layerName), any(SeedRequest.class));
reset(tileBreeder);
when(tileBreeder.findTileLayer(layerName))
.thenReturn(tileLayer);
bounds = mediator.getAreaOfValidity(CRS.decode("EPSG:26986"));// Massachussets
mediator.truncate(layerName, bounds);
verify(tileBreeder, times(expected)).seed(eq(layerName), any(SeedRequest.class));
}
@Test
public void testTruncateByBoundsWithDimension() throws Exception {
TileLayerInfoUtil.updateAcceptAllRegExParameterFilter(tileLayerInfo, "TIME", true);
Collection <String> cachedTimes = Arrays.asList("time1", "time2");
String layerName = tileLayer.getName();
when(tileBreeder.findTileLayer(layerName))
.thenReturn(tileLayer);
final Set<Map<String, String>> cachedParameters = tileLayer.getInfo().cachedStyles().stream()
.flatMap(style->cachedTimes.stream()
.map(time->{
Map<String, String> map = new HashMap();
map.put("STYLE", style);
map.put("TIME", time);
return map;
}))
.collect(Collectors.toSet());
when(storageBroker.getCachedParameters(layerName))
.thenReturn(cachedParameters);
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 = tileLayer.getInfo().cachedStyles().size();
int numTimes = cachedTimes.size();
int numParameters = numStyles * numTimes +1;
final int expected = numGridsets * numFormats * numParameters;
verify(tileBreeder, times(expected)).seed(eq(layerName), any(SeedRequest.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();
verify(diskQuotaStoreProvider, times(1)).reloadQuotaStore();
RuntimeException expected = new RuntimeException("expected");
doThrow(expected).when(tld).reInit();
try {
mediator.reload();
fail("Expected RTE");
} catch (RuntimeException e) {
assertSame(expected, e);
}
}
@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);
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("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());
}
/**
* Since GeoServer sets a new FILTER parameter equal to an input CQL_FILTER parameter (if present) for each WMS requests (using direct WMS
* integration), this may result in a caching error. This test ensures that no error is thrown and caching is allowed.
*/
@Test
public void testCQLFILTERParameters() throws Exception {
// Define a CQL_FILTER
TileLayerInfoUtil.updateAcceptAllRegExParameterFilter(tileLayerInfo, "CQL_FILTER", true);
tileLayer = new GeoServerTileLayer(layer, gridSetBroker, tileLayerInfo);
// Create the new GetMapRequest
GetMapRequest request = new GetMapRequest();
@SuppressWarnings("unchecked")
Map<String, String> rawKvp = new CaseInsensitiveMap(new HashMap<String, String>());
rawKvp.put("CQL_FILTER", "include");
request.setRawKvp(rawKvp);
StringBuilder target = new StringBuilder();
// Setting CQL FILTER
List<Filter> cqlFilters = Arrays.asList(CQL.toFilter("include"));
request.setCQLFilter(cqlFilters);
// Checking if caching is possible
assertTrue(mediator.isCachingPossible(tileLayer, request, target));
// Ensure No error is logged
assertEquals(0, target.length());
// Setting FILTER parameter equal to CQL FILTER (GeoServer does it internally)
request.setFilter(cqlFilters);
// Checking if caching is possible
assertTrue(mediator.isCachingPossible(tileLayer, request, target));
// Ensure No error is logged
assertEquals(0, target.length());
// Ensure that if another filter is set an error is thrown
List filters = new ArrayList(cqlFilters);
filters.add(Filter.INCLUDE);
request.setFilter(filters);
// Ensuring caching is not possible
assertFalse(mediator.isCachingPossible(tileLayer, request, target));
// Ensure No error is logged
assertFalse(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()));
}
@Test
public void testGetDefaultAdvertisedCachedFormats() {
// from src/main/resources/org/geoserver/gwc/advertised_formats.properties
Set<String> defaultFormats = ImmutableSet.of("image/png", "image/png8", "image/jpeg",
"image/gif", "image/vnd.jpeg-png");
SetView<String> formatsWithUtfGrid = union(defaultFormats,
Collections.singleton("application/json;type=utfgrid"));
assertEquals(formatsWithUtfGrid, GWC.getAdvertisedCachedFormats(PublishedType.VECTOR));
assertEquals(formatsWithUtfGrid, GWC.getAdvertisedCachedFormats(PublishedType.REMOTE));
assertEquals(defaultFormats, GWC.getAdvertisedCachedFormats(PublishedType.RASTER));
assertEquals(defaultFormats, GWC.getAdvertisedCachedFormats(PublishedType.WMS));
assertEquals(formatsWithUtfGrid, GWC.getAdvertisedCachedFormats(PublishedType.GROUP));
}
@Test
public void testGetPluggabledAdvertisedCachedFormats() throws IOException {
List<URL> urls;
try {
// load the default and test resources separately so they are named differently and we
// don't get the ones for testing listed in the UI when running from eclipse
String defaultResource = "org/geoserver/gwc/advertised_formats.properties";
String testResource = "org/geoserver/gwc/advertised_formats_unittesting.properties";
ClassLoader classLoader = GWC.class.getClassLoader();
urls = newArrayList(forEnumeration(classLoader.getResources(defaultResource)));
urls.addAll(newArrayList(forEnumeration(classLoader.getResources(testResource))));
} catch (IOException e) {
throw Throwables.propagate(e);
}
// from src/main/resources/org/geoserver/gwc/advertised_formats.properties
Set<String> defaultFormats = ImmutableSet.of("image/png", "image/png8", "image/jpeg", "image/gif", "image/vnd.jpeg-png");
// see src/test/resources/org/geoserver/gwc/advertised_formats.properties
Set<String> expectedVector = union(defaultFormats,
ImmutableSet.of("test/vector1", "test/vector2", "application/json;type=utfgrid"));
Set<String> expectedRaster = union(defaultFormats,
ImmutableSet.of("test/raster1", "test/raster2;type=test"));
Set<String> expectedGroup = union(defaultFormats,
ImmutableSet.of("test/group1", "test/group2", "application/json;type=utfgrid"));
assertEquals(expectedVector, GWC.getAdvertisedCachedFormats(PublishedType.VECTOR, urls));
assertEquals(expectedVector, GWC.getAdvertisedCachedFormats(PublishedType.REMOTE, urls));
assertEquals(expectedRaster, GWC.getAdvertisedCachedFormats(PublishedType.RASTER, urls));
assertEquals(expectedRaster, GWC.getAdvertisedCachedFormats(PublishedType.WMS, urls));
assertEquals(expectedGroup, GWC.getAdvertisedCachedFormats(PublishedType.GROUP, urls));
}
@Test
public void testSetBlobStoresNull() throws ConfigurationException {
expected.expect(NullPointerException.class);
expected.expectMessage("stores is null");
mediator.setBlobStores(null);
}
@Test
public void testSetBlobStoresWrapsStorageException() throws Exception {
when(xmlConfig.getBlobStores()).thenReturn(ImmutableList.<BlobStoreConfig> of());
CompositeBlobStore composite = mock(CompositeBlobStore.class);
doReturn(composite).when(mediator).getCompositeBlobStore();
StorageException se = new StorageException("expected");
doThrow(se).when(composite).setBlobStores(any(Iterable.class));
expected.expect(ConfigurationException.class);
expected.expectMessage("Error connecting to BlobStore");
mediator.setBlobStores(ImmutableList.<BlobStoreConfig> of());
}
@Test
public void testSetBlobStoresSavesConfig() throws Exception {
when(xmlConfig.getBlobStores()).thenReturn(ImmutableList.<BlobStoreConfig> of());
CompositeBlobStore composite = mock(CompositeBlobStore.class);
doReturn(composite).when(mediator).getCompositeBlobStore();
List<BlobStoreConfig> configList = Lists.newArrayList(mock(BlobStoreConfig.class),
mock(BlobStoreConfig.class));
when(xmlConfig.getBlobStores()).thenReturn(configList);
BlobStoreConfig config = new FileBlobStoreConfig();
List<BlobStoreConfig> newStores = ImmutableList.<BlobStoreConfig> of(config);
mediator.setBlobStores(newStores);
verify(composite, times(1)).setBlobStores(same(newStores));
verify(xmlConfig, times(1)).save();
assertEquals(newStores, configList);
}
@Test
public void testSetBlobStoresRestoresRuntimeStoresOnSaveFailure() throws Exception {
when(xmlConfig.getBlobStores()).thenReturn(ImmutableList.<BlobStoreConfig> of());
CompositeBlobStore composite = mock(CompositeBlobStore.class);
doReturn(composite).when(mediator).getCompositeBlobStore();
doThrow(new IOException("expected")).when(xmlConfig).save();
List<BlobStoreConfig> oldStores = Lists.newArrayList(mock(BlobStoreConfig.class),
mock(BlobStoreConfig.class));
when(xmlConfig.getBlobStores()).thenReturn(oldStores);
BlobStoreConfig config = new FileBlobStoreConfig();
List<BlobStoreConfig> newStores = ImmutableList.<BlobStoreConfig> of(config);
try {
mediator.setBlobStores(newStores);
fail("Expected ConfigurationException");
} catch (ConfigurationException e) {
assertTrue(e.getMessage().contains("Error saving config"));
}
verify(xmlConfig, times(1)).save();
verify(composite, times(1)).setBlobStores(same(newStores));
verify(composite, times(1)).setBlobStores(eq(oldStores));
}
@Test
public void testGeoServerEnvParametrization() throws Exception {
if (GeoServerEnvironment.ALLOW_ENV_PARAMETRIZATION) {
assertTrue("H2".equals(jdbcStorage.getJDBCDiskQuotaConfig().clone(true).getDialect()));
}
}
@Test
public void testVerifyAccessTiledLayerOutside() throws Exception {
Envelope filterBox = new Envelope(10, 11, 20, 21);
BoundingBox bounds = new BoundingBox(42.0, 33.0, 84.0, 66.0);
final String layerName = "testLayer";
final String gridName = "testGridSet";
final int zoom=0;
final long col=0;
final long row=0;
mockCachedSecureLayer(filterBox, bounds, layerName, gridName, zoom, col,
row);
expected.expect(org.geotools.ows.ServiceException.class);
expected.expect(hasProperty("code", equalTo("AccessDenied")));
mediator.verifyAccessTiledLayer(layerName, gridName, zoom, col, row);
}
@Test
public void testVerifyAccessTiledLayerInside() throws Exception {
Envelope filterBox = new Envelope(10, 11, 20, 21);
BoundingBox bounds = new BoundingBox(10.1, 20.1, 10.2, 20.2);
final String layerName = "testLayer";
final String gridName = "testGridSet";
final int zoom=0;
final long col=0;
final long row=0;
mockCachedSecureLayer(filterBox, bounds, layerName, gridName, zoom, col,
row);
mediator.verifyAccessTiledLayer(layerName, gridName, zoom, col, row);
}
private void mockCachedSecureLayer(Envelope filterBox, BoundingBox bounds,
final String layerName, final String gridName, final long zoom,
final long col, final long row) throws GeoWebCacheException, NoSuchAuthorityCodeException, FactoryException {
GeoServerTileLayer tileLayer = mock(GeoServerTileLayer.class);
GridSubset subset = mock(GridSubset.class);
SRS srs = mock(SRS.class);
SecuredLayerInfo layer = mock(SecuredLayerInfo.class);
FeatureTypeInfo featureType = mock(FeatureTypeInfo.class);
CoordinateReferenceSystem crs = mock(CoordinateReferenceSystem.class);
CoordinateSystem cs = mock(CoordinateSystem.class);
WrapperPolicy policy = mock(WrapperPolicy.class);
CoverageAccessLimits limits = mock(CoverageAccessLimits.class);
MultiPolygon filter = mock(MultiPolygon.class);
when(tld.getTileLayer(eq(layerName))).thenReturn(tileLayer);
when(tileLayer.getGridSubset(eq(gridName))).thenReturn(subset);
when(subset.boundsFromIndex(eq(new long[]{col,row,zoom}))).thenReturn(bounds);
when(subset.getSRS()).thenReturn(srs);
doReturn(crs).when(mediator).getCRSForGridset(eq(subset));
when(tileLayer.getLayerInfo()).thenReturn(layer);
when(layer.getResource()).thenReturn(featureType);
when(featureType.getCRS()).thenReturn(crs);
when(crs.getCoordinateSystem()).thenReturn(cs);
when(cs.getDimension()).thenReturn(2);
when(catalog.getLayerByName(layerName)).thenReturn(layer);
when(layer.getWrapperPolicy()).thenReturn(policy);
when(policy.getLimits()).thenReturn(limits);
when(limits.getRasterFilter()).thenReturn(filter);
when(filter.getEnvelopeInternal()).thenReturn(filterBox);
}
}