package org.geoserver.gwc.layer;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.Keyword;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.LayerInfo.Type;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.impl.DataStoreInfoImpl;
import org.geoserver.catalog.impl.FeatureTypeInfoImpl;
import org.geoserver.catalog.impl.LayerGroupInfoImpl;
import org.geoserver.catalog.impl.LayerInfoImpl;
import org.geoserver.catalog.impl.NamespaceInfoImpl;
import org.geoserver.catalog.impl.StyleInfoImpl;
import org.geoserver.gwc.config.GWCConfig;
import org.geoserver.wms.WMSMapContent;
import org.geoserver.wms.WebMap;
import org.geoserver.wms.map.RenderedImageMap;
import org.geoserver.wms.map.RenderedImageMapResponse;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geowebcache.GeoWebCacheException;
import org.geowebcache.conveyor.Conveyor.CacheResult;
import org.geowebcache.conveyor.ConveyorTile;
import org.geowebcache.filter.parameters.ParameterFilter;
import org.geowebcache.filter.parameters.StringParameterFilter;
import org.geowebcache.grid.BoundingBox;
import org.geowebcache.grid.GridSetBroker;
import org.geowebcache.grid.GridSubset;
import org.geowebcache.grid.OutsideCoverageException;
import org.geowebcache.io.Resource;
import org.geowebcache.layer.meta.LayerMetaInformation;
import org.geowebcache.mime.MimeType;
import org.geowebcache.storage.StorageBroker;
import org.geowebcache.storage.TileObject;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import com.mockrunner.mock.web.MockHttpServletRequest;
import com.mockrunner.mock.web.MockHttpServletResponse;
public class GeoServerTileLayerTest extends TestCase {
private LayerInfoImpl layerInfo;
private GeoServerTileLayer layerInfoTileLayer;
private LayerGroupInfoImpl layerGroup;
private GeoServerTileLayer layerGroupInfoTileLayer;
private CatalogConfiguration catalogConfig;
private GWCConfig defaultSettings;
@Override
public void setUp() throws Exception {
final String layerInfoId = "mock-layer-info";
NamespaceInfo ns = new NamespaceInfoImpl();
ns.setPrefix("test");
ns.setURI("http://goserver.org/test");
DataStoreInfoImpl storeInfo = new DataStoreInfoImpl(null);
storeInfo.setId("mock-store-info");
storeInfo.setEnabled(true);
FeatureTypeInfoImpl resource = new FeatureTypeInfoImpl((Catalog) null);
resource.setStore(storeInfo);
resource.setId("mock-resource-info");
resource.setName("MockLayerInfoName");
resource.setNamespace(ns);
resource.setTitle("Test resource title");
resource.setAbstract("Test resource abstract");
resource.setEnabled(true);
resource.setDescription("Test resource description");
resource.setLatLonBoundingBox(new ReferencedEnvelope(-180, -90, 0, 0,
DefaultGeographicCRS.WGS84));
resource.setNativeBoundingBox(new ReferencedEnvelope(-180, -90, 0, 0,
DefaultGeographicCRS.WGS84));
resource.setSRS("EPSG:4326");
resource.setKeywords((List)Arrays.asList(new Keyword("kwd1"), new Keyword("kwd2")));
layerInfo = new LayerInfoImpl();
layerInfo.setId(layerInfoId);
layerInfo.setEnabled(true);
layerInfo.setResource(resource);
layerInfo.setName("MockLayerInfoName");
layerInfo.setType(Type.VECTOR);
StyleInfo defaultStyle = new StyleInfoImpl(null);
defaultStyle.setName("default_style");
layerInfo.setDefaultStyle(defaultStyle);
StyleInfo alternateStyle1 = new StyleInfoImpl(null);
alternateStyle1.setName("alternateStyle-1");
StyleInfo alternateStyle2 = new StyleInfoImpl(null);
alternateStyle2.setName("alternateStyle-2");
Set<StyleInfo> alternateStyles = new HashSet<StyleInfo>(Arrays.asList(alternateStyle1,
alternateStyle2));
layerInfo.setStyles(alternateStyles);
layerGroup = new LayerGroupInfoImpl();
final String layerGroupId = "mock-layergroup-id";
layerGroup.setId(layerGroupId);
layerGroup.setName("MockLayerGroup");
layerGroup.setLayers(Collections.singletonList((LayerInfo) layerInfo));
defaultSettings = GWCConfig.getOldDefaults();
catalogConfig = mock(CatalogConfiguration.class);
when(catalogConfig.getConfig()).thenReturn(defaultSettings);
when(catalogConfig.getLayerInfoById(eq(layerInfoId))).thenReturn(layerInfo);
when(catalogConfig.getLayerGroupById(eq(layerGroupId))).thenReturn(layerGroup);
GridSetBroker gridSetBroker = new GridSetBroker(true, true);
gridSetBroker.put(gridSetBroker.WORLD_EPSG4326);
gridSetBroker.put(gridSetBroker.WORLD_EPSG3857);
when(catalogConfig.getGridSetBroker()).thenReturn(gridSetBroker);
}
public void testEnabled() {
layerInfo.setEnabled(true);
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
assertTrue(layerInfoTileLayer.isEnabled());
layerInfo.setEnabled(false);
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
assertFalse(layerInfoTileLayer.isEnabled());
layerInfo.setEnabled(true);
layerInfoTileLayer.setEnabled(true);
assertTrue(layerInfoTileLayer.isEnabled());
assertTrue(layerInfoTileLayer.getInfo().isEnabled());
layerInfoTileLayer.setConfigErrorMessage("fake error message");
assertFalse(layerInfoTileLayer.isEnabled());
layerInfoTileLayer.setConfigErrorMessage(null);
// this is the only call to layerInfoTileLayer that will call catalogConfig.save
layerInfoTileLayer.setEnabled(false);
assertFalse(layerInfoTileLayer.isEnabled());
assertFalse(layerInfoTileLayer.getInfo().isEnabled());
verify(catalogConfig, times(1)).save(same(layerInfoTileLayer));
layerGroupInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerGroup);
assertTrue(layerGroupInfoTileLayer.isEnabled());
}
public void testGetMetaTilingFactors() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
int[] metaTilingFactors = layerInfoTileLayer.getMetaTilingFactors();
assertEquals(defaultSettings.getMetaTilingX(), metaTilingFactors[0]);
assertEquals(defaultSettings.getMetaTilingY(), metaTilingFactors[1]);
GeoServerTileLayerInfo info = layerInfoTileLayer.getInfo();
info.setMetaTilingX(1 + defaultSettings.getMetaTilingX());
info.setMetaTilingY(2 + defaultSettings.getMetaTilingY());
info.saveTo(layerInfo.getMetadata());
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
metaTilingFactors = layerInfoTileLayer.getMetaTilingFactors();
assertEquals(1 + defaultSettings.getMetaTilingX(), metaTilingFactors[0]);
assertEquals(2 + defaultSettings.getMetaTilingY(), metaTilingFactors[1]);
}
public void testIsQueryable() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
when(catalogConfig.isQueryable(same(layerInfoTileLayer))).thenReturn(true);
assertTrue(layerInfoTileLayer.isQueryable());
when(catalogConfig.isQueryable(same(layerInfoTileLayer))).thenReturn(false);
assertFalse(layerInfoTileLayer.isQueryable());
verify(catalogConfig, times(2)).isQueryable(same(layerInfoTileLayer));
}
public void testGetName() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
assertEquals(layerInfo.getResource().getPrefixedName(), layerInfoTileLayer.getName());
layerGroupInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerGroup);
assertEquals(layerGroup.getName(), layerGroupInfoTileLayer.getName());
}
public void testGetParameterFilters() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
List<ParameterFilter> parameterFilters = layerInfoTileLayer.getParameterFilters();
assertNotNull(parameterFilters);
assertEquals(1, parameterFilters.size());
assertTrue(parameterFilters.get(0) instanceof StringParameterFilter);
StringParameterFilter styleFilter = (StringParameterFilter) parameterFilters.get(0);
assertEquals("STYLES", styleFilter.getKey());
assertEquals("default_style", styleFilter.getDefaultValue());
assertEquals(
new HashSet<String>(Arrays.asList("default_style", "alternateStyle-1",
"alternateStyle-2")), new HashSet<String>(styleFilter.getLegalValues()));
layerInfoTileLayer.getInfo().setCachedStyles(Collections.singleton("alternateStyle-2"));
}
public void testGetDefaultParameterFilters() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
Map<String, String> defaultFilters = layerInfoTileLayer.getDefaultParameterFilters();
assertEquals(1, defaultFilters.size());
assertEquals("default_style", defaultFilters.get("STYLES"));
StyleInfo newDefaultStyle = new StyleInfoImpl(null);
newDefaultStyle.setName("newDefault");
layerInfo.setDefaultStyle(newDefaultStyle);
layerInfoTileLayer.resetParameterFilters();
defaultFilters = layerInfoTileLayer.getDefaultParameterFilters();
assertEquals(1, defaultFilters.size());
assertEquals("newDefault", defaultFilters.get("STYLES"));
}
public void testResetParameterFilters() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
layerInfoTileLayer.getInfo().setCachedStyles(Collections.singleton("alternateStyle-2"));
layerInfoTileLayer.resetParameterFilters();
List<ParameterFilter> parameterFilters = layerInfoTileLayer.getParameterFilters();
StringParameterFilter styleFilter = (StringParameterFilter) parameterFilters.get(0);
assertEquals(new HashSet<String>(Arrays.asList("default_style", "alternateStyle-2")),
new HashSet<String>(styleFilter.getLegalValues()));
}
public void testGetModifiableParameters() throws GeoWebCacheException {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
ParameterFilter stylesParamFilter = layerInfoTileLayer.getParameterFilters().get(0);
List<String> legalValues = stylesParamFilter.getLegalValues();
Map<String, String> requestParams;
Map<String, String> modifiedParams;
requestParams = Collections.singletonMap("sTyLeS", "");
modifiedParams = layerInfoTileLayer.getModifiableParameters(requestParams, "UTF-8");
assertEquals(0, modifiedParams.size());
for (String legalStyle : legalValues) {
requestParams = new HashMap<String, String>();
requestParams.put("sTyLeS", legalStyle);
modifiedParams = layerInfoTileLayer.getModifiableParameters(requestParams, "UTF-8");
if (legalStyle.equals(stylesParamFilter.getDefaultValue())) {
assertEquals(0, modifiedParams.size());
} else {
assertEquals(Collections.singletonMap("STYLES", legalStyle), modifiedParams);
}
}
}
public void testGetMetaInformation() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
layerGroupInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerGroup);
LayerMetaInformation metaInformation = layerInfoTileLayer.getMetaInformation();
assertNotNull(metaInformation);
String title = metaInformation.getTitle();
String description = metaInformation.getDescription();
List<String> keywords = metaInformation.getKeywords();
assertEquals(layerInfo.getResource().getTitle(), title);
assertEquals(layerInfo.getResource().getAbstract(), description);
assertEquals(layerInfo.getResource().getKeywords().size(), keywords.size());
for (String kw : keywords) {
assertTrue(layerInfo.getResource().getKeywords().contains(new Keyword(kw)));
}
metaInformation = layerGroupInfoTileLayer.getMetaInformation();
assertNotNull(metaInformation);
title = metaInformation.getTitle();
description = metaInformation.getDescription();
keywords = metaInformation.getKeywords();
// these properties are missing from LayerGroupInfo interface
assertEquals(layerGroup.getName(), title);
assertEquals("", description);
assertEquals(0, keywords.size());
}
public void testGetStyles() {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
layerGroupInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerGroup);
assertEquals("default_style", layerInfoTileLayer.getStyles());
assertNull(layerGroupInfoTileLayer.getStyles());
StyleInfo newDefaultStyle = new StyleInfoImpl(null);
newDefaultStyle.setName("newDefault");
layerInfo.setDefaultStyle(newDefaultStyle);
assertEquals("newDefault", layerInfoTileLayer.getStyles());
}
public void testGetGridSubsets() throws Exception {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
Map<String, GridSubset> gridSubsets = layerInfoTileLayer.getGridSubsets();
assertNotNull(gridSubsets);
assertEquals(2, gridSubsets.size());
layerInfoTileLayer.getInfo().setCachedGridSetIds(Collections.singleton("EPSG:900913"));
layerInfoTileLayer.getInfo().saveTo(layerInfo.getMetadata());
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
gridSubsets = layerInfoTileLayer.getGridSubsets();
assertNotNull(gridSubsets);
assertEquals(1, gridSubsets.size());
layerGroup.setBounds(layerInfo.getResource().getLatLonBoundingBox());
layerGroupInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerGroup);
gridSubsets = layerGroupInfoTileLayer.getGridSubsets();
assertNotNull(gridSubsets);
assertEquals(2, gridSubsets.size());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testGetFeatureInfo() throws Exception {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
ConveyorTile convTile = new ConveyorTile(null, null, null, null);
convTile.setTileLayer(layerInfoTileLayer);
convTile.setMimeType(MimeType.createFromFormat("image/png"));
convTile.setGridSetId("EPSG:4326");
convTile.servletReq = new MockHttpServletRequest();
BoundingBox bbox = new BoundingBox(0, 0, 10, 10);
Resource mockResult = mock(Resource.class);
ArgumentCaptor<Map> argument = ArgumentCaptor.forClass(Map.class);
Mockito.when(catalogConfig.dispatchOwsRequest(argument.capture(), (Cookie[]) anyObject()))
.thenReturn(mockResult);
Resource result = layerInfoTileLayer.getFeatureInfo(convTile, bbox, 100, 100, 50, 50);
assertSame(mockResult, result);
final Map<String, String> capturedParams = argument.getValue();
assertEquals("image/png", capturedParams.get("INFO_FORMAT"));
assertEquals("0.0,0.0,10.0,10.0", capturedParams.get("BBOX"));
assertEquals("test:MockLayerInfoName", capturedParams.get("QUERY_LAYERS"));
assertEquals("WMS", capturedParams.get("SERVICE"));
assertEquals("100", capturedParams.get("HEIGHT"));
assertEquals("100", capturedParams.get("WIDTH"));
assertEquals("GetFeatureInfo", capturedParams.get("REQUEST"));
assertEquals("default_style", capturedParams.get("STYLES"));
assertEquals("SE_XML", capturedParams.get("EXCEPTIONS"));
assertEquals("1.1.1", capturedParams.get("VERSION"));
assertEquals("image/png", capturedParams.get("FORMAT"));
assertEquals("test:MockLayerInfoName", capturedParams.get("LAYERS"));
assertEquals("EPSG:4326", capturedParams.get("SRS"));
assertEquals("50", capturedParams.get("X"));
assertEquals("50", capturedParams.get("Y"));
verify(catalogConfig, times(1)).dispatchOwsRequest((Map) anyObject(),
(Cookie[]) anyObject());
when(catalogConfig.dispatchOwsRequest((Map) anyObject(), (Cookie[]) anyObject()))
.thenThrow(new RuntimeException("mock exception"));
try {
layerInfoTileLayer.getFeatureInfo(convTile, bbox, 100, 100, 50, 50);
fail("Expected GeoWebCacheException");
} catch (GeoWebCacheException e) {
assertTrue(true);
}
}
public void testGetTilePreconditions() throws Exception {
StorageBroker storageBroker = mock(StorageBroker.class);
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
MockHttpServletRequest servletReq = new MockHttpServletRequest();
HttpServletResponse servletResp = new MockHttpServletResponse();
ConveyorTile tile = new ConveyorTile(storageBroker, layerInfoTileLayer.getName(),
servletReq, servletResp);
tile.setMimeType(MimeType.createFromFormat("image/gif"));
try {
layerInfoTileLayer.getTile(tile);
fail("Expected exception, requested mime is invalid for the layer");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("is not a supported format"));
}
tile.setMimeType(MimeType.createFromFormat("image/png"));
tile.setGridSetId("EPSG:2003");
try {
layerInfoTileLayer.getTile(tile);
fail("Expected IAE");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("gridset not found"));
}
long[] tileIndex = { 0, 0, 1 };
MimeType mimeType = MimeType.createFromFormat("image/png");
tile = new ConveyorTile(storageBroker, layerInfoTileLayer.getName(), "EPSG:900913",
tileIndex, mimeType, null, servletReq, servletResp);
try {
layerInfoTileLayer.getTile(tile);
fail("Expected outside coverage exception");
} catch (OutsideCoverageException e) {
assertTrue(true);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testGetTile() throws Exception {
Resource mockResult = mock(Resource.class);
ArgumentCaptor<Map> argument = ArgumentCaptor.forClass(Map.class);
Mockito.when(catalogConfig.dispatchOwsRequest(argument.capture(), (Cookie[]) anyObject()))
.thenReturn(mockResult);
BufferedImage image = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
RenderedImageMap fakeDispatchedMap = new RenderedImageMap(new WMSMapContent(), image,
"image/png");
RenderedImageMapResponse fakeResponseEncoder = mock(RenderedImageMapResponse.class);
MimeType mimeType = MimeType.createFromFormat("image/png");
when(catalogConfig.getResponseEncoder(eq(mimeType), (WebMap) anyObject())).thenReturn(
fakeResponseEncoder);
StorageBroker storageBroker = mock(StorageBroker.class);
when(storageBroker.get((TileObject) anyObject())).thenReturn(false);
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
MockHttpServletRequest servletReq = new MockHttpServletRequest();
HttpServletResponse servletResp = new MockHttpServletResponse();
long[] tileIndex = { 0, 0, 0 };
ConveyorTile tile = new ConveyorTile(storageBroker, layerInfoTileLayer.getName(),
"EPSG:4326", tileIndex, mimeType, null, servletReq, servletResp);
GeoServerTileLayer.WEB_MAP.set(fakeDispatchedMap);
ConveyorTile returned = layerInfoTileLayer.getTile(tile);
assertNotNull(returned);
assertNotNull(returned.getBlob());
assertEquals(CacheResult.MISS, returned.getCacheResult());
assertEquals(200, returned.getStatus());
verify(storageBroker, atLeastOnce()).get((TileObject) anyObject());
verify(catalogConfig, times(1)).getResponseEncoder(eq(mimeType),
isA(RenderedImageMap.class));
}
public void testGetMimeTypes() throws Exception {
layerInfoTileLayer = new GeoServerTileLayer(catalogConfig, layerInfo);
List<MimeType> mimeTypes = layerInfoTileLayer.getMimeTypes();
GWCConfig defaults = catalogConfig.getConfig();
assertEquals(defaults.getDefaultOtherCacheFormats().size(), mimeTypes.size());
layerInfoTileLayer.getInfo().setMimeFormats(Collections.singleton("image/gif"));
mimeTypes = layerInfoTileLayer.getMimeTypes();
assertEquals(1, mimeTypes.size());
assertEquals(MimeType.createFromFormat("image/gif"), mimeTypes.get(0));
}
}