package org.geowebcache.service.wms;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.geowebcache.GeoWebCacheDispatcher;
import org.geowebcache.config.XMLGridSubset;
import org.geowebcache.conveyor.Conveyor;
import org.geowebcache.conveyor.ConveyorTile;
import org.geowebcache.filter.parameters.ParameterFilter;
import org.geowebcache.filter.parameters.RegexParameterFilter;
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.layer.wms.WMSLayer;
import org.geowebcache.mime.MimeType;
import org.geowebcache.stats.RuntimeStats;
import org.geowebcache.storage.StorageBroker;
import org.geowebcache.util.NullURLMangler;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.springframework.mock.web.MockHttpServletResponse;
public class WMSServiceTest extends TestCase {
private WMSService service;
private StorageBroker sb;
private TileLayerDispatcher tld;
private GridSetBroker gridsetBroker;
protected void setUp() throws Exception {
sb = mock(StorageBroker.class);
tld = mock(TileLayerDispatcher.class);
gridsetBroker = new GridSetBroker(true, true);
}
protected void tearDown() throws Exception {
}
/**
* Layer may be configured with mutliple GridSets for the same CRS, and should chose the best
* fit for the request
*/
public void testGetConveyorMultipleCrsMatchingGridSubsets() 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 {
GeoWebCacheDispatcher gwcd = mock(GeoWebCacheDispatcher.class);
when(gwcd.getServletPrefix()).thenReturn(null);
service = new WMSService(sb, tld, mock(RuntimeStats.class), new NullURLMangler(), gwcd);
@SuppressWarnings("unchecked")
Map<String, String[]> kvp = new CaseInsensitiveMap();
kvp.put("format", new String[]{"image/png"}
);
kvp.put("srs", new String[]{"EPSG:4326"});
kvp.put("width", new String[]{"256"});
kvp.put("height", new String[]{"256"});
kvp.put("layers", new String[]{"mockLayer"});
kvp.put("tiled", new String[]{"true"});
kvp.put("request", new String[]{"GetMap"});
List<String> gridSetNames = Arrays.asList("GlobalCRS84Pixel", "GlobalCRS84Scale",
"EPSG:4326");
TileLayer tileLayer = mockTileLayer("mockLayer", gridSetNames);
// make the request match a tile in the expected gridset
BoundingBox bounds;
bounds = tileLayer.getGridSubset(expectedGridset).boundsFromIndex(tileIndex);
kvp.put("bbox", new String[]{bounds.toString()});
HttpServletRequest req = mock(HttpServletRequest.class);
HttpServletResponse resp = mock(HttpServletResponse.class);
when(req.getCharacterEncoding()).thenReturn("UTF-8");
when(req.getParameterMap()).thenReturn(kvp);
ConveyorTile tileRequest = service.getConveyor(req, resp);
assertNotNull(tileRequest);
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 TileLayer mockTileLayer(String layerName, List<String> gridSetNames) throws Exception {
TileLayer tileLayer = mock(TileLayer.class);
when(tld.getTileLayer(eq(layerName))).thenReturn(tileLayer);
when(tileLayer.getName()).thenReturn(layerName);
when(tileLayer.isEnabled()).thenReturn(true);
when(tileLayer.isAdvertised()).thenReturn(true);
final MimeType mimeType1 = MimeType.createFromFormat("image/png");
final MimeType mimeType2 = MimeType.createFromFormat("image/jpeg");
when(tileLayer.getMimeTypes()).thenReturn(Arrays.asList(mimeType1, mimeType2));
Map<String, GridSubset> subsets = new HashMap<String, GridSubset>();
Map<SRS, List<GridSubset>> bySrs = new HashMap<SRS, List<GridSubset>>();
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);
List<GridSubset> list = bySrs.get(gridSet.getSrs());
if (list == null) {
list = new ArrayList<GridSubset>();
bySrs.put(gridSet.getSrs(), list);
}
list.add(gridSubSet);
when(tileLayer.getGridSubset(eq(gsetName))).thenReturn(gridSubSet);
}
for (SRS srs : bySrs.keySet()) {
List<GridSubset> list = 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;
}
public void testGetCap() throws Exception {
GeoWebCacheDispatcher gwcd = mock(GeoWebCacheDispatcher.class);
when(gwcd.getServletPrefix()).thenReturn(null);
service = new WMSService(sb, tld, mock(RuntimeStats.class), new NullURLMangler(), gwcd);
@SuppressWarnings("unchecked")
Map<String, String[]> kvp = new CaseInsensitiveMap();
kvp.put("service", new String[]{"WMS"});
kvp.put("version", new String[]{"1.1.1"});
kvp.put("request", new String[]{"GetCapabilities"});
HttpServletRequest req = mock(HttpServletRequest.class);
MockHttpServletResponse resp = new MockHttpServletResponse();
when(req.getCharacterEncoding()).thenReturn("UTF-8");
when(req.getParameterMap()).thenReturn(kvp);
List<String> gridSetNames = Arrays.asList("GlobalCRS84Pixel", "GlobalCRS84Scale","EPSG:4326");
TileLayer tileLayer = mockTileLayer("mockLayer", gridSetNames);
when(tld.getLayerList()).thenReturn(Arrays.asList(tileLayer));
ConveyorTile conv = service.getConveyor(req, resp);
assertNotNull(conv);
final String layerName = conv.getLayerId();
assertNull(layerName);
assertEquals(Conveyor.RequestHandler.SERVICE,conv.reqHandler);
WMSGetCapabilities wmsCap = new WMSGetCapabilities(tld, conv.servletReq,"http://localhost:8080", "/service/wms", new NullURLMangler());
wmsCap.writeResponse(conv.servletResp);
assertTrue(resp.containsHeader("content-disposition"));
assertEquals("inline;filename=wms-getcapabilities.xml", resp.getHeader("content-disposition"));
}
public void testGetCapEncoding() throws Exception {
GeoWebCacheDispatcher gwcd = mock(GeoWebCacheDispatcher.class);
when(gwcd.getServletPrefix()).thenReturn(null);
service = new WMSService(sb, tld, mock(RuntimeStats.class), new NullURLMangler(), gwcd);
@SuppressWarnings("unchecked")
Map<String, String[]> kvp = new CaseInsensitiveMap();
kvp.put("service", new String[]{"WMS"});
kvp.put("version", new String[]{"1.1.1"});
kvp.put("request", new String[]{"GetCapabilities"});
HttpServletRequest req = mock(HttpServletRequest.class);
MockHttpServletResponse resp = new MockHttpServletResponse();
when(req.getCharacterEncoding()).thenReturn("UTF-8");
when(req.getParameterMap()).thenReturn(kvp);
List<String> gridSetNames = Arrays.asList("GlobalCRS84Pixel", "GlobalCRS84Scale","EPSG:4326");
TileLayer tileLayer = mockTileLayer("möcklāyer😎", gridSetNames);
when(tld.getLayerList()).thenReturn(Arrays.asList(tileLayer));
ConveyorTile conv = service.getConveyor(req, resp);
assertNotNull(conv);
assertEquals(Conveyor.RequestHandler.SERVICE,conv.reqHandler);
WMSGetCapabilities wmsCap = new WMSGetCapabilities(tld, conv.servletReq,"http://localhost:8080", "/service/wms", new NullURLMangler());
wmsCap.writeResponse(conv.servletResp);
String capAsString = new String(resp.getContentAsByteArray(), StandardCharsets.UTF_8);
Assert.assertThat(capAsString, Matchers.containsString("möcklāyer😎"));
}
public void testGetConveyorWithParameters() throws Exception {
GeoWebCacheDispatcher gwcd = mock(GeoWebCacheDispatcher.class);
when(gwcd.getServletPrefix()).thenReturn(null);
service = new WMSService(sb, tld, mock(RuntimeStats.class), new NullURLMangler(), gwcd);
String layerName = "mockLayer";
String timeValue = "00:00";
@SuppressWarnings("unchecked")
Map<String, String[]> kvp = new CaseInsensitiveMap();
kvp.put("service", new String[]{"WMS"});
kvp.put("version", new String[]{"1.1.1"});
kvp.put("request", new String[]{"GetFeatureInfo"});
kvp.put("layers", new String[]{layerName});
kvp.put("time", new String[]{timeValue});
List<String> mimeFormats = new ArrayList<String>();
mimeFormats.add("image/png");
List<ParameterFilter> parameterFilters = new ArrayList<ParameterFilter>();
RegexParameterFilter filter = new RegexParameterFilter();
filter.setKey("time");
filter.setRegex("\\d{2}:\\d{2}");
parameterFilters.add(filter);
TileLayer tileLayer = new WMSLayer(layerName, null, null, layerName, mimeFormats, null,
parameterFilters, null, null, true);
when(tld.getTileLayer(layerName)).thenReturn(tileLayer);
HttpServletRequest req = mock(HttpServletRequest.class);
MockHttpServletResponse resp = new MockHttpServletResponse();
when(req.getCharacterEncoding()).thenReturn("UTF-8");
when(req.getParameterMap()).thenReturn(kvp);
ConveyorTile conv = service.getConveyor(req, resp);
assertNotNull(conv);
assertEquals(Conveyor.RequestHandler.SERVICE, conv.reqHandler);
assertNotNull(conv.getLayerId());
assertEquals(layerName, conv.getLayerId());
assertTrue(!conv.getFullParameters().isEmpty());
assertEquals(timeValue, conv.getFullParameters().get("TIME"));
}
}