source: josm/trunk/test/unit/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyActionTest.java@ 18963

Last change on this file since 18963 was 18963, checked in by taylor.smock, 4 months ago

Fix #23444: NPE in org.openstreetmap.josm.gui.MapViewState$MapViewEastNorthPoint.<init>

This occurs when an incomplete way is loaded into JOSM (by an .osm file, for
example). This is fixed by checking to see if the way is usable (not incomplete,
not deleted, and more importantly for this ticket, no nodes are incomplete).

This additionally fixes some pmd issues and sonarlint issues.

  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions.mapmode;
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.assertTrue;
8
9import java.awt.Graphics2D;
10import java.awt.Point;
11import java.awt.event.MouseEvent;
12import java.awt.image.BufferedImage;
13
14import org.junit.jupiter.api.Test;
15import org.junit.jupiter.api.extension.RegisterExtension;
16import org.openstreetmap.josm.TestUtils;
17import org.openstreetmap.josm.actions.mapmode.ImproveWayAccuracyAction.State;
18import org.openstreetmap.josm.data.Bounds;
19import org.openstreetmap.josm.data.coor.ILatLon;
20import org.openstreetmap.josm.data.coor.LatLon;
21import org.openstreetmap.josm.data.osm.DataSet;
22import org.openstreetmap.josm.data.osm.Node;
23import org.openstreetmap.josm.data.osm.Way;
24import org.openstreetmap.josm.gui.MainApplication;
25import org.openstreetmap.josm.gui.MapFrame;
26import org.openstreetmap.josm.gui.MapView;
27import org.openstreetmap.josm.gui.layer.OsmDataLayer;
28import org.openstreetmap.josm.gui.util.GuiHelper;
29import org.openstreetmap.josm.testutils.annotations.Main;
30import org.openstreetmap.josm.testutils.annotations.Projection;
31import org.openstreetmap.josm.testutils.mockers.WindowlessMapViewStateMocker;
32import org.openstreetmap.josm.testutils.mockers.WindowlessNavigatableComponentMocker;
33
34import mockit.Mock;
35
36/**
37 * Unit tests for class {@link ImproveWayAccuracyAction}.
38 */
39@Projection
40class ImproveWayAccuracyActionTest {
41 @RegisterExtension
42 Main.MainExtension mainExtension = new Main.MainExtension().setMapViewMocker(SizedWindowlessMapViewStateMocker::new)
43 .setNavigableComponentMocker(SizedWindowlessNavigatableComponentMocker::new);
44
45 private static final int WIDTH = 800;
46 private static final int HEIGHT = 600;
47 private static class SizedWindowlessMapViewStateMocker extends WindowlessMapViewStateMocker {
48 @Mock
49 public int getWidth() {
50 return WIDTH;
51 }
52
53 @Mock
54 public int getHeight() {
55 return HEIGHT;
56 }
57 }
58
59 private static class SizedWindowlessNavigatableComponentMocker extends WindowlessNavigatableComponentMocker {
60 @Mock
61 public int getWidth() {
62 return WIDTH;
63 }
64
65 @Mock
66 public int getHeight() {
67 return HEIGHT;
68 }
69 }
70
71 private static MouseEvent generateEvent(MapView mapView, ILatLon location) {
72 final Point p = mapView.getPoint(location);
73 return new MouseEvent(mapView, 0, 0, 0, p.x, p.y, p.x, p.y, 1, false, MouseEvent.BUTTON1);
74 }
75
76 /**
77 * Unit test of {@link ImproveWayAccuracyAction#enterMode} and {@link ImproveWayAccuracyAction#exitMode}.
78 */
79 @Test
80 void testMode() {
81 OsmDataLayer layer = new OsmDataLayer(new DataSet(), "", null);
82 try {
83 MainApplication.getLayerManager().addLayer(layer);
84 ImproveWayAccuracyAction mapMode = new ImproveWayAccuracyAction();
85 MapFrame map = MainApplication.getMap();
86 MapMode oldMapMode = map.mapMode;
87 assertTrue(map.selectMapMode(mapMode));
88 assertEquals(mapMode, map.mapMode);
89 assertTrue(map.selectMapMode(oldMapMode));
90 } finally {
91 MainApplication.getLayerManager().removeLayer(layer);
92 }
93 }
94
95 /**
96 * Unit test of {@link State} enum.
97 */
98 @Test
99 void testEnumState() {
100 assertDoesNotThrow(() -> TestUtils.superficialEnumCodeCoverage(State.class));
101 }
102
103 @Test
104 void testNonRegression23444() {
105 final DataSet dataSet = new DataSet();
106 final OsmDataLayer layer = new OsmDataLayer(dataSet, "ImproveWayAccuracyActionT", null);
107 MainApplication.getLayerManager().addLayer(layer);
108 final ImproveWayAccuracyAction mapMode = new ImproveWayAccuracyAction();
109 final MapFrame map = MainApplication.getMap();
110 assertTrue(map.selectMapMode(mapMode));
111 assertEquals(mapMode, map.mapMode);
112 final Way testWay = TestUtils.newWay("", new Node(1, 1), new Node(2, 1),
113 new Node(3), new Node(4, 1), new Node(5, 1));
114 testWay.firstNode().setCoor(new LatLon(0, 0));
115 testWay.lastNode().setCoor(new LatLon(0.001, 0.001));
116 testWay.getNode(1).setCoor(new LatLon(0.0001, 0.0001));
117 testWay.getNode(3).setCoor(new LatLon(0.0009, 0.0009));
118 dataSet.addPrimitiveRecursive(testWay);
119 assertFalse(testWay.getNode(2).isLatLonKnown(), "The second node should not have valid coordinates");
120 final Graphics2D g2d = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB).createGraphics();
121 g2d.setClip(0, 0, WIDTH, HEIGHT);
122 try {
123 // If this fails, something else is wrong
124 assertDoesNotThrow(() -> map.mapView.paint(g2d), "The mapview should be able to handle a null coordinate node");
125 // Ensure that the test way is selected (and use the methods from the action to do so)
126 GuiHelper.runInEDTAndWaitWithException(() -> {
127 map.mapView.zoomTo(new Bounds(0, 0, 0.001, 0.001));
128 // Get the target way selected (note: not selected in dataset -- use mapMode.mapReleased for that)
129 mapMode.mouseMoved(generateEvent(map.mapView, testWay.getNode(1)));
130 });
131 // mouseMoved shouldn't cause the way to get selected
132 assertFalse(dataSet.getAllSelected().contains(testWay));
133
134 // Now check painting (where the problem should occur; the mapMode.paint call should be called as part of the map.mapView.paint call)
135 assertDoesNotThrow(() -> map.mapView.paint(g2d));
136 assertDoesNotThrow(() -> mapMode.paint(g2d, map.mapView, new Bounds(0, 0, 0.001, 0.001)));
137
138 // Finally, check painting during selection
139 GuiHelper.runInEDTAndWaitWithException(() -> {
140 // Set the way as selected
141 mapMode.mouseReleased(generateEvent(map.mapView, new LatLon(0.0001, 0.0001)));
142 // Set the mouse location (unset in mouseReleased call)
143 mapMode.mouseMoved(generateEvent(map.mapView, new LatLon(0.0001, 0.0001)));
144 });
145 // The way shouldn't be selected, since it isn't usable for the improve way tool
146 assertFalse(dataSet.getAllSelected().contains(testWay));
147 // Now check painting again (just in case)
148 assertDoesNotThrow(() -> map.paint(g2d));
149 assertDoesNotThrow(() -> mapMode.paint(g2d, map.mapView, new Bounds(0, 0, 0.001, 0.001)));
150 } finally {
151 g2d.dispose();
152 }
153 }
154}
Note: See TracBrowser for help on using the repository browser.