source: josm/trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/sort/WayConnectionTypeCalculatorTest.java@ 18870

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

See #16567: Update to JUnit 5

This converts most tests to use @Annotations. There are also some performance
improvements as it relates to tests.

  • Property svn:eol-style set to native
File size: 14.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation.sort;
3
4import static org.junit.jupiter.api.Assertions.assertEquals;
5import static org.junit.jupiter.api.Assertions.assertFalse;
6import static org.junit.jupiter.api.Assertions.assertTrue;
7
8import java.io.IOException;
9import java.io.InputStream;
10import java.nio.file.Files;
11import java.nio.file.Paths;
12import java.util.ArrayList;
13import java.util.Arrays;
14import java.util.Collections;
15import java.util.HashSet;
16import java.util.List;
17
18import org.junit.jupiter.api.BeforeEach;
19import org.junit.jupiter.api.Test;
20import org.openstreetmap.josm.data.osm.DataSet;
21import org.openstreetmap.josm.data.osm.Node;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.data.osm.Relation;
24import org.openstreetmap.josm.data.osm.Way;
25import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
26import org.openstreetmap.josm.io.IllegalDataException;
27import org.openstreetmap.josm.io.OsmReader;
28import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
29import org.openstreetmap.josm.testutils.annotations.Projection;
30
31/**
32 * Unit tests of {@link WayConnectionTypeCalculator} class.
33 */
34@BasicPreferences
35@Projection
36class WayConnectionTypeCalculatorTest {
37
38 private final RelationSorter sorter = new RelationSorter();
39 private final WayConnectionTypeCalculator wayConnectionTypeCalculator = new WayConnectionTypeCalculator();
40 private DataSet testDataset;
41
42 /**
43 * Load the test data set
44 * @throws IllegalDataException if an error was found while parsing the data
45 * @throws IOException in case of I/O error
46 */
47 @BeforeEach
48 public void loadData() throws IllegalDataException, IOException {
49 if (testDataset == null) {
50 try (InputStream fis = Files.newInputStream(Paths.get("nodist/data/relation_sort.osm"))) {
51 testDataset = OsmReader.parseDataSet(fis, NullProgressMonitor.INSTANCE);
52 }
53 }
54 }
55
56 private Relation getRelation(String testType) {
57 return testDataset.getRelations().stream().filter(r -> testType.equals(r.get("test"))).findFirst().orElse(null);
58 }
59
60 private String getConnections(List<WayConnectionType> connections) {
61 String[] result = new String[connections.size()];
62 for (int i = 0; i < result.length; i++) {
63 WayConnectionType wc = connections.get(i);
64
65 if (wc.isValid()) {
66 StringBuilder sb = new StringBuilder();
67 if (wc.isLoop) {
68 sb.append("L");
69 }
70 if (wc.isOnewayLoopForwardPart) {
71 sb.append("FP");
72 }
73 if (wc.isOnewayLoopBackwardPart) {
74 sb.append("BP");
75 }
76 if (wc.isOnewayHead) {
77 sb.append("H");
78 }
79 if (wc.isOnewayTail) {
80 sb.append("T");
81 }
82
83 if (sb.length() > 0) {
84 sb.append(" ");
85 }
86 sb.append(wc.direction);
87 result[i] = sb.toString();
88
89 } else {
90 result[i] = "I";
91 }
92
93 }
94 return Arrays.toString(result);
95 }
96
97 @Test
98 void testEmpty() {
99 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(new ArrayList<>()));
100 assertEquals("[]", actual);
101 }
102
103 // This cluster of tests checks the rendering before and after
104 // sorting of a few relations. Initially, these relations are
105 // intentionally not sorted to ensure the sorting has some work.
106
107 @Test
108 void testGeneric() {
109 Relation relation = getRelation("generic");
110 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(relation.getMembers()));
111 assertEquals("[NONE, NONE, FORWARD, FORWARD, NONE, NONE, NONE, I, I]", actual);
112 actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
113 assertEquals("[FORWARD, FORWARD, FORWARD, FORWARD, BACKWARD, BACKWARD, NONE, I, I]", actual);
114 }
115
116 @Test
117 void testAssociatedStreet() {
118 Relation relation = getRelation("associatedStreet");
119 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(relation.getMembers()));
120 assertEquals("[NONE, I, I, I, NONE, I]", actual);
121 actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
122 assertEquals("[FORWARD, FORWARD, I, I, I, I]", actual);
123 }
124
125 @Test
126 void testLoop() {
127 Relation relation = getRelation("loop");
128 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(relation.getMembers()));
129 assertEquals("[FPH FORWARD, FP FORWARD, NONE, FPH FORWARD, NONE, FPH FORWARD, NONE]", actual);
130 //TODO Sorting doesn't work well in this case
131 actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
132 assertEquals("[BACKWARD, BACKWARD, BACKWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD]", actual);
133 }
134
135 // The following cluster of tests checks various configurations
136 // involving split / dual carriageway routes (i.e. containing
137 // members with role=forward or role=backward). Again, these are
138 // intentionally not sorted.
139
140 @Test
141 void testThreeLoopsEndsLoop() {
142 Relation relation = getRelation("three-loops-ends-loop");
143 // Check the first way before sorting, otherwise the sorter
144 // might pick a different loop starting point than expected below
145 assertEquals("t5w1", relation.getMembers().get(0).getMember().get("name"));
146 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
147 String expected = "[" +
148 "L FORWARD, LFPH FORWARD, LFP FORWARD, LFP FORWARD, LBP BACKWARD, LBP BACKWARD, LBPT BACKWARD, " +
149 "L FORWARD, LFPH FORWARD, LFP FORWARD, LFP FORWARD, LBP BACKWARD, LBP BACKWARD, LBPT BACKWARD, " +
150 "LFPH FORWARD, LFP FORWARD, LFP FORWARD, LBP BACKWARD, LBP BACKWARD, LBPT BACKWARD, " +
151 "L FORWARD, L FORWARD" +
152 "]";
153 assertEquals(expected, actual);
154 }
155
156 @Test
157 void testThreeLoopsEndsWay() {
158 Relation relation = getRelation("three-loops-ends-way");
159 // Check the first way before sorting, otherwise the sorter
160 // might sort in reverse compared to what is expected below
161 assertEquals("t5w1", relation.getMembers().get(0).getMember().get("name"));
162 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
163 String expected = "[" +
164 "FORWARD, FPH FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD, " +
165 "FORWARD, FPH FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD, " +
166 "FPH FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD, " +
167 "FORWARD" +
168 "]";
169 assertEquals(expected, actual);
170 }
171
172 @Test
173 void testThreeLoopsEndsNode() {
174 Relation relation = getRelation("three-loops-ends-node");
175 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
176 String expected = "[" +
177 "FPH FORWARD, BP BACKWARD, BP BACKWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD, " +
178 "FORWARD, FPH FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD, " +
179 "FPH FORWARD, FP FORWARD, FP FORWARD, FP FORWARD, FP FORWARD, BPT BACKWARD" +
180 "]";
181 assertEquals(expected, actual);
182 }
183
184 @Test
185 void testOneLoopEndsSplit() {
186 Relation relation = getRelation("one-loop-ends-split");
187 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
188 String expected = "[" +
189 "FP FORWARD, FP FORWARD, BP BACKWARD, BPT BACKWARD, " +
190 "FORWARD, FPH FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BPT BACKWARD, " +
191 "FPH FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD" +
192 "]";
193 assertEquals(expected, actual);
194 }
195
196 @Test
197 void testNoLoopEndsSplit() {
198 Relation relation = getRelation("no-loop-ends-split");
199 // TODO: This is not yet sorted properly, so this route is
200 // presorted in the data file
201 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(relation.getMembers()));
202 String expected = "[" +
203 "FP FORWARD, FP FORWARD, BP BACKWARD, BPT BACKWARD, " +
204 "FPH FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD" +
205 "]";
206 assertEquals(expected, actual);
207 }
208
209 @Test
210 void testIncompleteLoops() {
211 Relation relation = getRelation("incomplete-loops");
212 // TODO: This is not yet sorted perfectly (might not be possible)
213 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
214 String expected = "[" +
215 "FORWARD, FPH FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, " +
216 "FORWARD, FPH FORWARD, FP FORWARD, FP FORWARD, FP FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, " +
217 "BACKWARD, FPH FORWARD, FP FORWARD, FP FORWARD" +
218 "]";
219 assertEquals(expected, actual);
220 }
221
222 @Test
223 void testParallelOneWay() {
224 Relation relation = getRelation("parallel-oneway");
225 // TODO: This is not always sorted properly, only when the right
226 // way is already at the top, so check that
227 assertEquals("t6w1a", relation.getMembers().get(0).getMember().get("name"));
228 String actual = getConnections(wayConnectionTypeCalculator.updateLinks(sorter.sortMembers(relation.getMembers())));
229 String expected = "[" +
230 "FP FORWARD, FP FORWARD, FP FORWARD, BP BACKWARD, BP BACKWARD, BP BACKWARD" +
231 "]";
232 assertEquals(expected, actual);
233 }
234
235 private void reverseWay(Way way) {
236 List<Node> nodes = way.getNodes();
237 Collections.reverse(nodes);
238 way.removeNodes(new HashSet<>(nodes));
239 for (Node node : nodes) {
240 way.addNode(node);
241 }
242 }
243
244 /**
245 * Test directional {@link WayConnectionTypeCalculator#computeNextWayConnection}
246 */
247 @Test
248 void testDirectionsOnewaysOnly() {
249 Relation relation = getRelation("direction");
250
251 // Check with only one wrong oneway
252 List<WayConnectionType> returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
253 for (int i = 0; i < 4; i++) {
254 assertTrue(returned.get(i).onewayFollowsPrevious);
255 assertTrue(returned.get(i).onewayFollowsNext);
256 }
257
258 assertTrue(returned.get(4).onewayFollowsPrevious);
259 assertFalse(returned.get(4).onewayFollowsNext);
260
261 assertFalse(returned.get(5).onewayFollowsPrevious);
262 assertFalse(returned.get(5).onewayFollowsNext);
263
264 assertFalse(returned.get(6).onewayFollowsPrevious);
265 assertTrue(returned.get(6).onewayFollowsNext);
266
267 // Reverse the last oneway
268 OsmPrimitive way7 = relation.getMemberPrimitivesList().get(6);
269 if (way7 instanceof Way) {
270 Way way = (Way) way7;
271 reverseWay(way);
272 returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
273 for (int i = 0; i < 4; i++) {
274 assertTrue(returned.get(i).onewayFollowsPrevious);
275 assertTrue(returned.get(i).onewayFollowsNext);
276 }
277
278 assertTrue(returned.get(4).onewayFollowsPrevious);
279 assertFalse(returned.get(4).onewayFollowsNext);
280
281 assertFalse(returned.get(5).onewayFollowsPrevious);
282 assertTrue(returned.get(5).onewayFollowsNext);
283
284 assertTrue(returned.get(6).onewayFollowsPrevious);
285 assertTrue(returned.get(6).onewayFollowsNext);
286 reverseWay(way);
287 }
288
289 // Reverse the wrong oneway
290 OsmPrimitive way6 = relation.getMemberPrimitivesList().get(5);
291 if (way6 instanceof Way) {
292 Way way = (Way) way6;
293 reverseWay(way);
294 returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
295 for (int i = 0; i < 7; i++) {
296 assertTrue(returned.get(i).onewayFollowsPrevious);
297 assertTrue(returned.get(i).onewayFollowsNext);
298 }
299 }
300
301 // Reverse everything
302 for (Way way : relation.getMemberPrimitives(Way.class)) {
303 reverseWay(way);
304 }
305 returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
306 for (int i = 0; i < 7; i++) {
307 assertTrue(returned.get(i).onewayFollowsPrevious);
308 assertTrue(returned.get(i).onewayFollowsNext);
309 }
310 }
311
312 /**
313 * Test directional {@link WayConnectionTypeCalculator#computeNextWayConnection}
314 */
315 @Test
316 void testDirectionsOnewayMix() {
317 Relation relation = getRelation("direction");
318
319 // Remove the oneway in the wrong direction
320 OsmPrimitive osm = relation.getMemberPrimitivesList().get(5);
321 osm.remove("oneway");
322 List<WayConnectionType> returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
323 for (WayConnectionType type : returned) {
324 assertTrue(type.onewayFollowsNext);
325 assertTrue(type.onewayFollowsPrevious);
326 }
327
328 // Check with a oneway=-1 tag without reversing the way
329 osm.put("oneway", "-1");
330 returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
331 for (WayConnectionType type : returned) {
332 assertTrue(type.onewayFollowsNext);
333 assertTrue(type.onewayFollowsPrevious);
334 }
335
336 // Check with oneways that converge onto a two-way
337 // TODO figure out a way to find this situation?
338 osm.remove("oneway");
339 OsmPrimitive way7 = relation.getMemberPrimitivesList().get(6);
340 way7.put("oneway", "-1");
341 returned = wayConnectionTypeCalculator.updateLinks(relation.getMembers());
342 for (int i = 0; i < returned.size() - 1; i++) {
343 WayConnectionType type = returned.get(i);
344 assertTrue(type.onewayFollowsNext);
345 assertTrue(type.onewayFollowsPrevious);
346 }
347 assertTrue(returned.get(6).onewayFollowsNext);
348 assertFalse(returned.get(6).onewayFollowsPrevious);
349 }
350}
Note: See TracBrowser for help on using the repository browser.