source: josm/trunk/test/unit/org/openstreetmap/josm/gui/layer/GpxLayerTest.java@ 18037

Last change on this file since 18037 was 18008, checked in by Don-vip, 3 years ago

fix #21105 - see #17184 - make sure that most operations of GpxLayer are harmless after call to destroy()

  • Property svn:eol-style set to native
File size: 12.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer;
3
4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
5import static org.junit.jupiter.api.Assertions.assertEquals;
6import static org.junit.jupiter.api.Assertions.assertFalse;
7import static org.junit.jupiter.api.Assertions.assertNull;
8import static org.junit.jupiter.api.Assertions.assertThrows;
9import static org.junit.jupiter.api.Assertions.assertTrue;
10
11import java.awt.Color;
12import java.awt.Component;
13import java.io.IOException;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.HashMap;
17import java.util.Locale;
18import java.util.TimeZone;
19
20import javax.swing.JScrollPane;
21
22import org.junit.jupiter.api.BeforeEach;
23import org.junit.jupiter.api.Test;
24import org.junit.jupiter.api.extension.RegisterExtension;
25import org.openstreetmap.josm.TestUtils;
26import org.openstreetmap.josm.data.gpx.GpxData;
27import org.openstreetmap.josm.data.gpx.GpxTrack;
28import org.openstreetmap.josm.data.gpx.IGpxTrackSegment;
29import org.openstreetmap.josm.data.gpx.WayPoint;
30import org.openstreetmap.josm.data.osm.DataSet;
31import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
32import org.openstreetmap.josm.data.projection.CustomProjection;
33import org.openstreetmap.josm.data.projection.Projections;
34import org.openstreetmap.josm.gui.MainApplication;
35import org.openstreetmap.josm.gui.widgets.HtmlPanel;
36import org.openstreetmap.josm.io.GpxReaderTest;
37import org.openstreetmap.josm.testutils.JOSMTestRules;
38import org.openstreetmap.josm.tools.date.DateUtils;
39import org.xml.sax.SAXException;
40
41import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
42
43/**
44 * Unit tests of {@link GpxLayer} class.
45 */
46public class GpxLayerTest {
47
48 /**
49 * Setup tests
50 */
51 @RegisterExtension
52 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
53 public JOSMTestRules test = new JOSMTestRules().main().projection().i18n().metricSystem();
54
55 /**
56 * Setup test.
57 */
58 @BeforeEach
59 void setUp() {
60 Locale.setDefault(Locale.ROOT);
61 DateUtils.PROP_ISO_DATES.put(true);
62 }
63
64 private static String getHtml(GpxLayer layer) {
65 return ((HtmlPanel) ((JScrollPane) layer.getInfoComponent()).getViewport().getView()).getEditorPane().getText();
66 }
67
68 /**
69 * Returns minimal GPX data.
70 * @return minimal GPX data, with a single waypoint, a single track composed of a single segment
71 * @throws IOException if any I/O error occurs
72 * @throws SAXException if any SAX error occurs
73 */
74 public static GpxData getMinimalGpxData() throws IOException, SAXException {
75 return GpxReaderTest.parseGpxData(TestUtils.getTestDataRoot() + "minimal.gpx");
76 }
77
78 /**
79 * Returns minimal GPX layer.
80 * @return minimal GPX layer, with a single waypoint, a single track composed of a single segment
81 * @throws IOException if any I/O error occurs
82 * @throws SAXException if any SAX error occurs
83 */
84 public static GpxLayer getMinimalGpxLayer() throws IOException, SAXException {
85 return new GpxLayer(getMinimalGpxData(), "Bananas");
86 }
87
88 /**
89 * Unit test of {@link GpxLayer#GpxLayer}.
90 * @throws Exception if any error occurs
91 */
92 @Test
93 void testGpxLayer() throws Exception {
94 GpxLayer layer = new GpxLayer(new GpxData(), "foo", false);
95 GpxTrack trk = new GpxTrack(new ArrayList<IGpxTrackSegment>(), new HashMap<>());
96 trk.getExtensions().add("gpxd", "color", "#FF0000");
97 layer.data.addTrack(trk);
98
99 assertEquals("foo", layer.getName());
100 assertFalse(layer.isLocalFile());
101 assertEquals(layer.getColor(), Color.RED);
102 assertEquals("<html>1 track (0 segments), 0 routes, 0 waypoints<br>Length: < 0.01 m<br></html>", layer.getToolTipText());
103
104 GpxLayer layer2 = new GpxLayer(new GpxData(), "bar", true);
105 assertEquals("bar", layer2.getName());
106 assertTrue(layer2.isLocalFile());
107 assertNull(layer2.getColor());
108 assertEquals("<html>0 tracks (0 segments), 0 routes, 0 waypoints<br>Length: < 0.01 m<br></html>", layer2.getToolTipText());
109
110 assertTrue(layer.checkSaveConditions());
111 assertTrue(layer.isInfoResizable());
112 assertTrue(layer.isSavable());
113 assertTrue(layer.isMergable(layer2));
114
115 layer.projectionChanged(null, null);
116 layer.projectionChanged(null, Projections.getProjectionByCode("EPSG:3857"));
117 }
118
119 /**
120 * Unit test of {@link GpxLayer#getInfoComponent}.
121 * @throws Exception if any error occurs
122 */
123 @Test
124 void testGetInfoComponent() throws Exception {
125 assertEquals("<html>\n"+
126 " <head>\n" +
127 " <style type=\"text/css\">\n" +
128 " <!--\n" +
129 " td { padding-top: 4px; padding-bottom: 4px; padding-right: 16px; padding-left: 16px }\n" +
130 " -->\n" +
131 " </style>\n" +
132 " \n" +
133 " </head>\n" +
134 " <body>\n" +
135 " Length: 0.01 m<br>0 routes, 0 waypoints<br>\n" +
136 " </body>\n" +
137 "</html>\n",
138 getHtml(new GpxLayer(new GpxData())));
139
140 assertEquals("<html>\n"+
141 " <head>\n" +
142 " <style type=\"text/css\">\n" +
143 " <!--\n" +
144 " td { padding-top: 4px; padding-bottom: 4px; padding-right: 16px; padding-left: 16px }\n" +
145 " -->\n" +
146 " </style>\n" +
147 " \n" +
148 " </head>\n" +
149 " <body>\n" +
150 " Creator: MapSource 6.16.3<br>\n\n" +
151 " <table>\n" +
152 " <tr align=\"center\">\n" +
153 " <td colspan=\"5\">\n" +
154 " 1 track, 1 track segments\n" +
155 " </td>\n" +
156 " </tr>\n" +
157 " <tr align=\"center\">\n" +
158 " <td>\n" +
159 " Name\n" +
160 " </td>\n" +
161 " <td>\n" +
162 " Description\n" +
163 " </td>\n" +
164 " <td>\n" +
165 " Timespan\n" +
166 " </td>\n" +
167 " <td>\n" +
168 " Length\n" +
169 " </td>\n" +
170 " <td>\n" +
171 " Number of<br>Segments\n" +
172 " </td>\n" +
173 " <td>\n" +
174 " URL\n" +
175 " </td>\n" +
176 " </tr>\n" +
177 " <tr>\n" +
178 " <td>\n" +
179 " 2016-01-03 20:40:14\n" +
180 " </td>\n" +
181 " <td>\n" +
182 " \n" +
183 " </td>\n" +
184 " <td>\n" +
185 " 2016-01-03 11:59:58 &#8211; 12:00:00 (2.0 s)\n" +
186 " </td>\n" +
187 " <td>\n" +
188 " 12.0 m\n" +
189 " </td>\n" +
190 " <td>\n" +
191 " 1\n" +
192 " </td>\n" +
193 " <td>\n" +
194 " \n" +
195 " </td>\n" +
196 " </tr>\n" +
197 " </table>\n" +
198 " <br>\n" +
199 " <br>\n" +
200 " Length: 12.0 m<br>0 routes, 1 waypoint<br>\n" +
201 " </body>\n" +
202 "</html>\n",
203 getHtml(getMinimalGpxLayer()));
204 }
205
206 /**
207 * Unit test of {@link GpxLayer#getTimespanForTrack}.
208 * @throws Exception if any error occurs
209 */
210 @Test
211 void testGetTimespanForTrack() throws Exception {
212 assertEquals("", GpxLayer.getTimespanForTrack(
213 new GpxTrack(new ArrayList<Collection<WayPoint>>(), new HashMap<String, Object>())));
214
215 assertEquals("2016-01-03 11:59:58 \u2013 12:00:00 (2.0 s)", GpxLayer.getTimespanForTrack(getMinimalGpxData().tracks.iterator().next()));
216
217 TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
218 assertEquals("2016-01-03 12:59:58 \u2013 13:00:00 (2.0 s)", GpxLayer.getTimespanForTrack(getMinimalGpxData().tracks.iterator().next()));
219 }
220
221 /**
222 * Unit test of {@link GpxLayer#mergeFrom}.
223 * @throws Exception if any error occurs
224 */
225 @Test
226 void testMergeFrom() throws Exception {
227 GpxLayer layer = new GpxLayer(new GpxData());
228 assertTrue(layer.data.isEmpty());
229 layer.mergeFrom(getMinimalGpxLayer());
230 assertFalse(layer.data.isEmpty());
231 assertEquals(1, layer.data.tracks.size());
232 assertEquals(1, layer.data.waypoints.size());
233 }
234
235 /**
236 * Test that {@link GpxLayer#mergeFrom} throws IAE for invalid arguments
237 */
238 @Test
239 void testMergeFromIAE() {
240 assertThrows(IllegalArgumentException.class, () -> new GpxLayer(new GpxData()).mergeFrom(new OsmDataLayer(new DataSet(), "", null)));
241 }
242
243 /**
244 * Unit test of {@link GpxLayer#paint}.
245 * @throws Exception if any error occurs
246 */
247 @Test
248 void testPaint() throws Exception {
249 GpxLayer layer = getMinimalGpxLayer();
250 try {
251 MainApplication.getLayerManager().addLayer(layer);
252 assertTrue(layer.getMenuEntries().length > 0);
253 layer.paint(TestUtils.newGraphics(), MainApplication.getMap().mapView, layer.data.getMetaBounds());
254 } finally {
255 MainApplication.getLayerManager().removeLayer(layer);
256 }
257 }
258
259 /**
260 * Unit test of {@link GpxLayer#getChangesetSourceTag}.
261 */
262 @Test
263 void testGetChangesetSourceTag() {
264 assertEquals("survey", new GpxLayer(new GpxData(), "", true).getChangesetSourceTag());
265 assertNull(new GpxLayer(new GpxData(), "", false).getChangesetSourceTag());
266 }
267
268 /**
269 * Checks that potential operations that could be called after destroy() are harmless
270 */
271 @Test
272 void testRobustnessAfterDestroy() {
273 GpxData data = new GpxData();
274 GpxLayer layer = new GpxLayer(data, "1", false);
275 GpxLayer otherLayer = new GpxLayer(new GpxData(), "2", false);
276 assertEquals(data, layer.getData());
277 assertTrue(layer.isMergable(otherLayer));
278 assertTrue(layer.hasColor());
279 assertTrue(layer.isSavable());
280 assertTrue(layer.checkSaveConditions());
281 assertFalse(layer.isModified());
282 assertFalse(layer.requiresSaveToFile());
283 assertNull(layer.getChangesetSourceTag());
284 assertNull(layer.getAssociatedFile());
285
286 layer.destroy();
287
288 assertNull(layer.getData());
289 assertNull(layer.getColor());
290 assertFalse(layer.hasColor());
291 assertFalse(layer.isMergable(otherLayer));
292 assertFalse(layer.isSavable());
293 assertFalse(layer.checkSaveConditions());
294 assertFalse(layer.isModified());
295 assertFalse(layer.requiresSaveToFile());
296 assertNull(layer.getChangesetSourceTag());
297 assertNull(layer.getAssociatedFile());
298 Object infoComponent = layer.getInfoComponent();
299 assertTrue(infoComponent instanceof JScrollPane);
300 Component view = ((JScrollPane) infoComponent).getViewport().getView();
301 assertTrue(view instanceof HtmlPanel);
302 String text = ((HtmlPanel) view).getEditorPane().getText().trim();
303 assertTrue(text.startsWith("<html>"), text);
304 assertTrue(text.endsWith("</html>"), text);
305 assertEquals("<html><br></html>", layer.getToolTipText());
306 assertDoesNotThrow(() -> layer.jumpToNextMarker());
307 assertDoesNotThrow(() -> layer.jumpToPreviousMarker());
308 assertDoesNotThrow(() -> layer.visitBoundingBox(new BoundingXYVisitor()));
309 assertDoesNotThrow(() -> layer.filterTracksByDate(null, null, false));
310 assertDoesNotThrow(() -> layer.projectionChanged(new CustomProjection(), new CustomProjection()));
311 }
312}
Note: See TracBrowser for help on using the repository browser.