source: josm/trunk/test/unit/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreferenceTestIT.java@ 14519

Last change on this file since 14519 was 14519, checked in by Don-vip, 5 years ago

see #16073 - handle entries with several shapes (like French 'BDOrtho IGN')

  • Property svn:eol-style set to native
File size: 7.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.imagery;
3
4import static org.junit.Assert.assertTrue;
5
6import java.io.IOException;
7import java.net.URL;
8import java.util.ArrayList;
9import java.util.Collections;
10import java.util.HashSet;
11import java.util.List;
12import java.util.Map;
13import java.util.Set;
14import java.util.TreeMap;
15import java.util.stream.Collectors;
16
17import org.junit.Rule;
18import org.junit.Test;
19import org.openstreetmap.gui.jmapviewer.TileXY;
20import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
21import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
22import org.openstreetmap.gui.jmapviewer.tilesources.BingAerialTileSource;
23import org.openstreetmap.gui.jmapviewer.tilesources.ScanexTileSource;
24import org.openstreetmap.gui.jmapviewer.tilesources.TemplatedTMSTileSource;
25import org.openstreetmap.josm.data.coor.LatLon;
26import org.openstreetmap.josm.data.imagery.CoordinateConversion;
27import org.openstreetmap.josm.data.imagery.ImageryInfo;
28import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
29import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
30import org.openstreetmap.josm.data.imagery.Shape;
31import org.openstreetmap.josm.data.imagery.TemplatedWMSTileSource;
32import org.openstreetmap.josm.data.imagery.WMSEndpointTileSource;
33import org.openstreetmap.josm.data.imagery.WMTSTileSource;
34import org.openstreetmap.josm.data.imagery.WMTSTileSource.WMTSGetCapabilitiesException;
35import org.openstreetmap.josm.data.projection.Projection;
36import org.openstreetmap.josm.data.projection.ProjectionRegistry;
37import org.openstreetmap.josm.testutils.JOSMTestRules;
38import org.openstreetmap.josm.tools.Geometry;
39import org.openstreetmap.josm.tools.HttpClient;
40import org.openstreetmap.josm.tools.HttpClient.Response;
41import org.openstreetmap.josm.tools.Logging;
42import org.openstreetmap.josm.tools.Utils;
43
44import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
45
46/**
47 * Integration tests of {@link ImageryPreference} class.
48 */
49public class ImageryPreferenceTestIT {
50
51 /**
52 * Setup rule
53 */
54 @Rule
55 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
56 public JOSMTestRules test = new JOSMTestRules().https().projection().projectionNadGrids().timeout(10000*60);
57
58 private final Map<String, Map<ImageryInfo, List<String>>> errors = Collections.synchronizedMap(new TreeMap<>());
59 private final Set<String> workingURLs = Collections.synchronizedSet(new HashSet<>());
60
61 private boolean addError(ImageryInfo info, String error) {
62 return errors.computeIfAbsent(info.getCountryCode(), x -> Collections.synchronizedMap(new TreeMap<>()))
63 .computeIfAbsent(info, x -> Collections.synchronizedList(new ArrayList<>()))
64 .add(error);
65 }
66
67 private void checkUrl(ImageryInfo info, String url) {
68 if (url != null && !workingURLs.contains(url)) {
69 try {
70 Response response = HttpClient.create(new URL(url)).connect();
71 if (response.getResponseCode() >= 400) {
72 addError(info, url + " -> HTTP " + response.getResponseCode());
73 } else if (response.getResponseCode() >= 300) {
74 Logging.warn(url + " -> HTTP " + response.getResponseCode());
75 } else {
76 workingURLs.add(url);
77 }
78 response.disconnect();
79 } catch (IOException e) {
80 addError(info, url + " -> " + e);
81 }
82 }
83 }
84
85 private void checkTileUrl(ImageryInfo info, AbstractTileSource tileSource, ICoordinate center, int zoom)
86 throws IOException {
87 TileXY xy = tileSource.latLonToTileXY(center, zoom);
88 for (int i = 0; i < 3; i++) {
89 try {
90 checkUrl(info, tileSource.getTileUrl(zoom, xy.getXIndex(), xy.getYIndex()));
91 return;
92 } catch (IOException e) {
93 // Try up to three times max to allow Bing source to initialize itself
94 // and avoid random network errors
95 Logging.trace(e);
96 if (i == 2) {
97 throw e;
98 }
99 try {
100 Thread.sleep(500);
101 } catch (InterruptedException ex) {
102 Logging.warn(ex);
103 }
104 }
105 }
106 }
107
108 private static LatLon getCenter(ImageryBounds bounds) {
109 List<Shape> shapes = bounds.getShapes();
110 Projection proj = ProjectionRegistry.getProjection();
111 return shapes != null && shapes.size() > 1
112 ? proj.eastNorth2latlon(
113 Geometry.getCentroidEN(shapes.get(0).getPoints().stream()
114 .map(CoordinateConversion::coorToLL)
115 .map(proj::latlon2eastNorth)
116 .collect(Collectors.toList())))
117 : bounds.getCenter();
118 }
119
120 private void checkEntry(ImageryInfo info) {
121 Logging.info("Checking "+ info);
122
123 if (info.getAttributionImageRaw() != null && info.getAttributionImage() == null) {
124 addError(info, "Can't fetch attribution image: " + info.getAttributionImageRaw());
125 }
126
127 checkUrl(info, info.getAttributionImageURL());
128 checkUrl(info, info.getAttributionLinkURL());
129 String eula = info.getEulaAcceptanceRequired();
130 if (eula != null) {
131 checkUrl(info, eula.replaceAll("\\{lang\\}", ""));
132 }
133 checkUrl(info, info.getPermissionReferenceURL());
134 checkUrl(info, info.getTermsOfUseURL());
135
136 try {
137 ImageryBounds bounds = info.getBounds();
138 // Some imagery sources do not define tiles at (0,0). So pickup Greenwich Royal Observatory for global sources
139 ICoordinate center = CoordinateConversion.llToCoor(bounds != null ? getCenter(bounds) : new LatLon(51.47810, -0.00170));
140 AbstractTileSource tileSource = getTileSource(info);
141 checkTileUrl(info, tileSource, center, info.getMinZoom());
142 // checking max zoom for real is complex, see https://josm.openstreetmap.de/ticket/16073#comment:27
143 if (info.getMaxZoom() > 0) {
144 checkTileUrl(info, tileSource, center, Utils.clamp(12, info.getMinZoom() + 1, info.getMaxZoom()));
145 }
146 } catch (IOException | WMTSGetCapabilitiesException | IllegalArgumentException e) {
147 addError(info, e.toString());
148 }
149
150 for (ImageryInfo mirror : info.getMirrors()) {
151 checkEntry(mirror);
152 }
153 }
154
155 private static AbstractTileSource getTileSource(ImageryInfo info) throws IOException, WMTSGetCapabilitiesException {
156 switch (info.getImageryType()) {
157 case BING:
158 return new BingAerialTileSource(info);
159 case SCANEX:
160 return new ScanexTileSource(info);
161 case TMS:
162 return new TemplatedTMSTileSource(info);
163 case WMS:
164 return new TemplatedWMSTileSource(info, ProjectionRegistry.getProjection());
165 case WMS_ENDPOINT:
166 return new WMSEndpointTileSource(info, ProjectionRegistry.getProjection());
167 case WMTS:
168 return new WMTSTileSource(info, ProjectionRegistry.getProjection());
169 default:
170 throw new UnsupportedOperationException(info.toString());
171 }
172 }
173
174 /**
175 * Test that available imagery entries are valid.
176 * @throws Exception in case of error
177 */
178 @Test
179 public void testValidityOfAvailableImageryEntries() throws Exception {
180 ImageryLayerInfo.instance.load(false);
181 ImageryLayerInfo.instance.getDefaultLayers().parallelStream().forEach(this::checkEntry);
182 assertTrue(errors.toString().replaceAll("\\}, ", "\n\\}, ").replaceAll(", ImageryInfo\\{", "\n ,ImageryInfo\\{"),
183 errors.isEmpty());
184 }
185}
Note: See TracBrowser for help on using the repository browser.