source: josm/trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java@ 10758

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

sonar - squid:S3578 - Test methods should comply with a naming convention

  • Property svn:eol-style set to native
File size: 31.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import static org.junit.Assert.assertEquals;
5import static org.junit.Assert.assertFalse;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertNotSame;
8import static org.junit.Assert.assertSame;
9import static org.junit.Assert.assertTrue;
10import static org.junit.Assert.fail;
11
12import java.io.StringWriter;
13import java.util.Arrays;
14import java.util.Calendar;
15import java.util.Date;
16import java.util.GregorianCalendar;
17
18import org.junit.After;
19import org.junit.Before;
20import org.junit.BeforeClass;
21import org.junit.Test;
22import org.openstreetmap.josm.JOSMFixture;
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.data.coor.LatLon;
25import org.openstreetmap.josm.data.projection.Projections;
26
27/**
28 * Unit tests for class {@link DataSetMerger}.
29 */
30public class DataSetMergerTest {
31
32 /**
33 * Setup test.
34 */
35 @BeforeClass
36 public static void init() {
37 JOSMFixture.createUnitTestFixture().init();
38 }
39
40 private DataSet my;
41 private DataSet their;
42
43 /**
44 * Setup test.
45 */
46 @Before
47 public void setUp() {
48 User.clearUserMap();
49 my = new DataSet();
50 my.setVersion("0.6");
51 their = new DataSet();
52 their.setVersion("0.6");
53 Main.setProjection(Projections.getProjectionByCode("EPSG:3857")); // Mercator
54 }
55
56 private void runConsistencyTests(DataSet ds) {
57 StringWriter writer = new StringWriter();
58 DatasetConsistencyTest test = new DatasetConsistencyTest(ds, writer);
59 test.checkReferrers();
60 test.checkCompleteWaysWithIncompleteNodes();
61 test.searchNodes();
62 test.searchWays();
63 test.referredPrimitiveNotInDataset();
64 test.checkZeroNodesWays();
65 String result = writer.toString();
66 if (!result.isEmpty())
67 fail(result);
68 }
69
70 @After
71 public void checkDatasets() {
72 runConsistencyTests(my);
73 runConsistencyTests(their);
74 }
75
76 /**
77 * two identical nodes, even in id and version. No confict expected.
78 *
79 * Can happen if data is loaded in two layers and then merged from one layer
80 * on the other.
81 */
82 @Test
83 public void testNodeSimpleIdenticalNoConflict() {
84 Node n = new Node(LatLon.ZERO);
85 n.setOsmId(1, 1);
86 n.setModified(false);
87 n.put("key1", "value1");
88 my.addPrimitive(n);
89
90 Node n1 = new Node(LatLon.ZERO);
91 n1.setOsmId(1, 1);
92 n1.setModified(false);
93 n1.put("key1", "value1");
94 their.addPrimitive(n1);
95
96
97 DataSetMerger visitor = new DataSetMerger(my, their);
98 visitor.merge();
99
100 Node n2 = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
101 assertTrue(visitor.getConflicts().isEmpty());
102 assertNotSame(n1, n2); // make sure we have a clone
103 assertEquals(1, n2.getId());
104 assertEquals(1, n2.getVersion());
105 assertFalse(n2.isModified());
106 assertEquals("value1", n2.get("key1"));
107
108 // merge target not modified after merging
109 assertFalse(n2.isModified());
110 }
111
112 /**
113 * two nodes, my is unmodified, their is updated and has a higher version
114 * => their version is going to be the merged version
115 */
116 @Test
117 public void testNodeSimpleLocallyUnmodifiedNoConflict() {
118 Node n = new Node(LatLon.ZERO);
119 n.setOsmId(1, 1);
120 n.setModified(false);
121 n.put("key1", "value1");
122 my.addPrimitive(n);
123
124 Node n1 = new Node(LatLon.ZERO);
125 n1.setOsmId(1, 2);
126 n1.setModified(false);
127 n1.put("key1", "value1-new");
128 n1.put("key2", "value2");
129 their.addPrimitive(n1);
130
131
132 DataSetMerger visitor = new DataSetMerger(my, their);
133 visitor.merge();
134
135 Node n2 = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
136 assertTrue(visitor.getConflicts().isEmpty());
137 assertSame(n, n2); // make sure the merged node is still the original node
138 assertSame(n2.getDataSet(), my);
139 assertEquals(1, n2.getId());
140 assertEquals(2, n2.getVersion());
141 assertFalse(n2.isModified());
142 assertEquals("value1-new", n2.get("key1"));
143 assertEquals("value2", n2.get("key2"));
144
145 // the merge target should not be modified
146 assertFalse(n2.isModified());
147 }
148
149 /**
150 * Node with same id, my is modified, their has a higher version
151 * => results in a conflict
152 *
153 * Use case: node which is modified locally and updated by another mapper on
154 * the server
155 */
156 @Test
157 public void testNodeSimpleTagConflict() {
158 Node n = new Node(LatLon.ZERO);
159 n.setOsmId(1, 1);
160 n.setModified(true);
161 n.put("key1", "value1");
162 n.put("key2", "value2");
163 my.addPrimitive(n);
164
165 Node n1 = new Node(LatLon.ZERO);
166 n1.setOsmId(1, 2);
167 n1.setModified(false);
168 n1.put("key1", "value1-new");
169
170 their.addPrimitive(n1);
171
172
173 DataSetMerger visitor = new DataSetMerger(my, their);
174 visitor.merge();
175
176 Node n2 = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
177 assertEquals(1, visitor.getConflicts().size());
178 assertSame(n, n2);
179 assertNotSame(n1, n2);
180 assertSame(n1.getDataSet(), their);
181 }
182
183 /**
184 * node with same id, my is deleted, their has a higher version
185 * => results in a conflict
186 *
187 * Use case: node which is deleted locally and updated by another mapper on
188 * the server
189 */
190 @Test
191 public void testNodeSimpleDeleteConflict() {
192 Node n = new Node(1, 1);
193 n.setCoor(LatLon.ZERO);
194 n.setDeleted(true);
195 n.put("key1", "value1");
196 my.addPrimitive(n);
197
198 Node n1 = new Node(LatLon.ZERO);
199 n1.setOsmId(1, 2);
200 n1.setModified(false);
201 n1.put("key1", "value1-new");
202 n1.put("key2", "value2");
203 their.addPrimitive(n1);
204
205
206 DataSetMerger visitor = new DataSetMerger(my, their);
207 visitor.merge();
208
209 Node n2 = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
210 assertEquals(1, visitor.getConflicts().size());
211 assertSame(n, n2);
212 assertNotSame(n1, n2);
213 assertSame(n1.getDataSet(), their);
214 }
215
216 /**
217 * My node is deleted, their node has the same id and version and is not deleted.
218 * => mine has precedence
219 */
220 @Test
221 public void testNodeSimpleDeleteConflict2() {
222 Node n = new Node(LatLon.ZERO);
223 n.setOsmId(1, 1);
224 n.setDeleted(true);
225 my.addPrimitive(n);
226
227 Node n1 = new Node(LatLon.ZERO);
228 n1.setOsmId(1, 1);
229 their.addPrimitive(n1);
230
231
232 DataSetMerger visitor = new DataSetMerger(my, their);
233 visitor.merge();
234
235 Node n2 = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
236 assertEquals(0, visitor.getConflicts().size());
237 assertTrue(n2.isVisible());
238 assertSame(n, n2);
239 assertSame(n.getDataSet(), my);
240 assertSame(n1.getDataSet(), their);
241 }
242
243 /**
244 * My and their node are new but semantically equal. My node is deleted.
245 *
246 * => Ignore my node, no conflict
247 */
248 @Test
249 public void testNodeSimpleDeleteConflict3() {
250 Node n = new Node(new LatLon(1, 1));
251 n.setDeleted(true);
252 my.addPrimitive(n);
253
254 Node n1 = new Node(new LatLon(1, 1));
255 their.addPrimitive(n1);
256
257
258 DataSetMerger visitor = new DataSetMerger(my, their);
259 visitor.merge();
260
261 assertEquals(0, visitor.getConflicts().size());
262 assertSame(n.getDataSet(), my);
263 assertSame(n1.getDataSet(), their);
264 }
265
266 /**
267 * My and their node are new but semantically equal. Both are deleted.
268 *
269 * => take mine
270 */
271 @Test
272 public void testNodeSimpleDeleteConflict4() {
273 Node n = new Node(new LatLon(1, 1));
274 n.setDeleted(true);
275 my.addPrimitive(n);
276
277 Node n1 = new Node(new LatLon(1, 1));
278 n1.setDeleted(true);
279 their.addPrimitive(n1);
280
281 DataSetMerger visitor = new DataSetMerger(my, their);
282 visitor.merge();
283
284 assertEquals(0, visitor.getConflicts().size());
285 Node n2 = (Node) my.getNodes().toArray()[0];
286 assertSame(n2, n);
287 assertTrue(n2.isDeleted());
288 }
289
290 /**
291 * their node has no assigned id (id == 0) and is semantically equal to one of my
292 * nodes with id == 0
293 *
294 * => merge it onto my node.
295 */
296 @Test
297 public void testNodeSimpleNoIdSemanticallyEqual() {
298
299 Calendar cal = GregorianCalendar.getInstance();
300 User myUser = User.createOsmUser(1111, "my");
301
302 User theirUser = User.createOsmUser(222, "their");
303
304 Node n = new Node();
305 n.setCoor(LatLon.ZERO);
306 n.put("key1", "value1");
307 n.setUser(myUser);
308 n.setTimestamp(cal.getTime());
309
310 my.addPrimitive(n);
311
312 Node n1 = new Node();
313 n1.setCoor(LatLon.ZERO);
314 n1.put("key1", "value1");
315 cal.add(Calendar.HOUR, 1);
316 Date timestamp = cal.getTime();
317 n1.setTimestamp(timestamp);
318 n1.setUser(theirUser);
319 their.addPrimitive(n1);
320
321 DataSetMerger visitor = new DataSetMerger(my, their);
322 visitor.merge();
323
324 Node n2 = my.getNodes().iterator().next();
325 assertEquals(0, visitor.getConflicts().size());
326 assertEquals("value1", n2.get("key1"));
327 assertEquals(n1.getRawTimestamp(), n2.getRawTimestamp());
328 assertEquals(theirUser, n2.getUser());
329 assertSame(n2, n);
330 assertNotSame(n2, n1);
331 assertSame(n2.getDataSet(), my);
332 }
333
334 /**
335 * my node is incomplete, their node is complete
336 *
337 * => merge it onto my node. My node becomes complete
338 */
339 @Test
340 public void testNodeSimpleIncompleteNode() {
341
342 Node n = new Node(1);
343 my.addPrimitive(n);
344
345 Node n1 = new Node();
346 n1.setCoor(LatLon.ZERO);
347 n1.setOsmId(1, 1);
348 n1.put("key1", "value1");
349 Date timestamp = new Date();
350 n1.setTimestamp(timestamp);
351 their.addPrimitive(n1);
352
353 DataSetMerger visitor = new DataSetMerger(my, their);
354 visitor.merge();
355
356 Node n2 = my.getNodes().iterator().next();
357 assertEquals(0, visitor.getConflicts().size());
358 assertEquals("value1", n2.get("key1"));
359 assertEquals(n1.getRawTimestamp(), n2.getRawTimestamp());
360 assertFalse(n2.isIncomplete());
361 assertSame(n2, n);
362 }
363
364 /**
365 * their way has a higher version and different tags. the nodes are the same. My
366 * way is not modified. Merge is possible. No conflict.
367 *
368 * => merge it onto my way.
369 */
370 @Test
371 public void testWaySimpleIdenticalNodesDifferentTags() {
372
373 // -- the target dataset
374
375 Node n1 = new Node();
376 n1.setCoor(LatLon.ZERO);
377 n1.setOsmId(1, 1);
378 my.addPrimitive(n1);
379
380 Node n2 = new Node();
381 n2.setCoor(LatLon.ZERO);
382 n2.setOsmId(2, 1);
383
384 my.addPrimitive(n2);
385
386 Way myWay = new Way();
387 myWay.setOsmId(3, 1);
388 myWay.put("key1", "value1");
389 myWay.addNode(n1);
390 myWay.addNode(n2);
391 my.addPrimitive(myWay);
392
393 // -- the source data set
394
395 Node n3 = new Node(LatLon.ZERO);
396 n3.setOsmId(1, 1);
397 their.addPrimitive(n3);
398
399 Node n4 = new Node(new LatLon(1, 1));
400 n4.setOsmId(2, 1);
401 their.addPrimitive(n4);
402
403 Way theirWay = new Way();
404 theirWay.setOsmId(3, 2);
405 theirWay.put("key1", "value1");
406 theirWay.put("key2", "value2");
407 theirWay.addNode(n3);
408 theirWay.addNode(n4);
409 their.addPrimitive(theirWay);
410
411
412 DataSetMerger visitor = new DataSetMerger(my, their);
413 visitor.merge();
414
415 // -- tests
416 Way merged = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
417 assertEquals(0, visitor.getConflicts().size());
418 assertEquals("value1", merged.get("key1"));
419 assertEquals("value2", merged.get("key2"));
420 assertEquals(3, merged.getId());
421 assertEquals(2, merged.getVersion());
422 assertEquals(2, merged.getNodesCount());
423 assertEquals(1, merged.getNode(0).getId());
424 assertEquals(2, merged.getNode(1).getId());
425 assertSame(merged, myWay);
426 assertSame(merged.getDataSet(), my);
427
428 Node mergedNode = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
429 assertSame(mergedNode, n1);
430 mergedNode = (Node) my.getPrimitiveById(2, OsmPrimitiveType.NODE);
431 assertSame(mergedNode, n2);
432
433 assertFalse(merged.isModified());
434 }
435
436 /**
437 * their way has a higher version and different tags. And it has more nodes. Two
438 * of the existing nodes are modified.
439 *
440 * => merge it onto my way, no conflict
441 */
442 @Test
443 public void testWaySimpleAdditionalNodesAndChangedNodes() {
444
445 // -- my data set
446
447 Node n1 = new Node(LatLon.ZERO);
448 n1.setOsmId(1, 1);
449 my.addPrimitive(n1);
450
451 Node n2 = new Node(new LatLon(1, 1));
452 n2.setOsmId(2, 1);
453 my.addPrimitive(n2);
454
455 Way myWay = new Way();
456 myWay.setOsmId(3, 1);
457 myWay.addNode(n1);
458 myWay.addNode(n2);
459 my.addPrimitive(myWay);
460
461 // --- their data set
462
463 Node n3 = new Node(LatLon.ZERO);
464 n3.setOsmId(1, 1);
465 their.addPrimitive(n3);
466
467 Node n5 = new Node(new LatLon(1, 1));
468 n5.setOsmId(4, 1);
469
470 their.addPrimitive(n5);
471
472 Node n4 = new Node(new LatLon(2, 2));
473 n4.setOsmId(2, 2);
474 n4.put("key1", "value1");
475 their.addPrimitive(n4);
476
477
478 Way theirWay = new Way();
479 theirWay.setOsmId(3, 2);
480 theirWay.addNode(n3);
481 theirWay.addNode(n5); // insert a node
482 theirWay.addNode(n4); // this one is updated
483 their.addPrimitive(theirWay);
484
485 DataSetMerger visitor = new DataSetMerger(my, their);
486 visitor.merge();
487
488 // -- tests
489 Way merged = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
490 assertEquals(0, visitor.getConflicts().size());
491 assertEquals(3, merged.getId());
492 assertEquals(2, merged.getVersion());
493 assertEquals(3, merged.getNodesCount());
494 assertEquals(1, merged.getNode(0).getId());
495 assertEquals(4, merged.getNode(1).getId());
496 assertEquals(2, merged.getNode(2).getId());
497 assertEquals("value1", merged.getNode(2).get("key1"));
498
499 assertSame(merged.getNode(0), n1);
500 assertNotSame(merged.getNode(1), n5); // must be clone of the original node in their
501 assertSame(merged.getNode(2), n2);
502
503 assertFalse(merged.isModified()); // the target wasn't modified before merging, it mustn't be after merging
504 }
505
506 /**
507 * their way has a higher version and different nodes. My way is modified.
508 *
509 * => merge onto my way not possible, create a conflict
510 */
511 @Test
512 public void testWaySimpleDifferentNodesAndMyIsModified() {
513
514 // -- the target dataset
515
516 Node n1 = new Node(LatLon.ZERO);
517 n1.setOsmId(1, 1);
518 my.addPrimitive(n1);
519
520 Node n2 = new Node(new LatLon(1, 1));
521 n2.setOsmId(2, 1);
522 my.addPrimitive(n2);
523
524 Way myWay = new Way();
525 myWay.setOsmId(3, 1);
526
527 myWay.addNode(n1);
528 myWay.addNode(n2);
529 myWay.setModified(true);
530 myWay.put("key1", "value1");
531 my.addPrimitive(myWay);
532
533 // -- the source dataset
534
535 Node n3 = new Node(LatLon.ZERO);
536 n3.setOsmId(1, 1);
537 their.addPrimitive(n3);
538
539 Node n5 = new Node(new LatLon(1, 1));
540 n5.setOsmId(4, 1);
541 their.addPrimitive(n5);
542
543 Node n4 = new Node(new LatLon(2, 2));
544 n4.setOsmId(2, 1);
545 n4.put("key1", "value1");
546 their.addPrimitive(n4);
547
548 Way theirWay = new Way();
549 theirWay.setOsmId(3, 2);
550
551 theirWay.addNode(n3);
552 theirWay.addNode(n5); // insert a node
553 theirWay.addNode(n4); // this one is updated
554 their.addPrimitive(theirWay);
555
556
557 DataSetMerger visitor = new DataSetMerger(my, their);
558 visitor.merge();
559
560 Way merged = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
561 assertEquals(1, visitor.getConflicts().size());
562 assertEquals(3, merged.getId());
563 assertEquals(1, merged.getVersion());
564 assertEquals(2, merged.getNodesCount());
565 assertEquals(1, merged.getNode(0).getId());
566 assertEquals(2, merged.getNode(1).getId());
567 assertEquals("value1", merged.get("key1"));
568 }
569
570 /**
571 * their way is not visible anymore.
572 *
573 * => conflict
574 */
575 @Test
576 public void testWaySimpleTheirVersionNotVisibleMyIsModified() {
577
578 Node mn1 = new Node(LatLon.ZERO);
579 mn1.setOsmId(1, 1);
580 my.addPrimitive(mn1);
581
582 Node mn2 = new Node(new LatLon(1, 1));
583 mn2.setOsmId(2, 1);
584 my.addPrimitive(mn2);
585
586 Way myWay = new Way();
587 myWay.setOsmId(3, 1);
588 myWay.addNode(mn1);
589 myWay.addNode(mn2);
590 myWay.setModified(true);
591 my.addPrimitive(myWay);
592
593 Way theirWay = new Way();
594 theirWay.setOsmId(3, 2);
595 theirWay.setVisible(false);
596 /* Invisible objects fetched from the server should be marked as "deleted".
597 * Otherwise it's an error.
598 */
599 theirWay.setDeleted(true);
600 their.addPrimitive(theirWay);
601
602 DataSetMerger visitor = new DataSetMerger(my, their);
603 visitor.merge();
604
605 Way merged = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
606 assertEquals(1, visitor.getConflicts().size());
607 assertTrue(visitor.getConflicts().hasConflictForMy(myWay));
608 assertTrue(visitor.getConflicts().hasConflictForTheir(theirWay));
609 assertEquals(myWay, merged);
610 }
611
612 /**
613 * my and their way have no ids, nodes they refer to have an id. but
614 * my and their way are semantically equal. so technical attributes of
615 * their way can be merged on my way. No conflict.
616 */
617 @Test
618 public void testWaySimpleTwoWaysWithNoIdNodesWithId() {
619
620 // -- my data set
621
622 Node n1 = new Node(LatLon.ZERO);
623 n1.setOsmId(1, 1);
624 my.addPrimitive(n1);
625
626 Node n2 = new Node(new LatLon(1, 1));
627 n2.setOsmId(2, 1);
628 my.addPrimitive(n2);
629
630 Way myWay = new Way();
631 myWay.addNode(n1);
632 myWay.addNode(n2);
633 my.addPrimitive(myWay);
634
635 // -- their data set
636
637 Node n3 = new Node(LatLon.ZERO);
638 n3.setOsmId(1, 1);
639 their.addPrimitive(n3);
640
641 Node n4 = new Node(new LatLon(1, 1));
642 n4.setOsmId(2, 1);
643 their.addPrimitive(n4);
644
645 Way theirWay = new Way();
646 theirWay.addNode(n3);
647 theirWay.addNode(n4);
648 User user = User.createOsmUser(1111, "their");
649 theirWay.setUser(user);
650 theirWay.setTimestamp(new Date());
651 their.addPrimitive(theirWay);
652
653 DataSetMerger visitor = new DataSetMerger(my, their);
654 visitor.merge();
655
656 // -- tests
657 Way merged = (Way) my.getWays().toArray()[0];
658 assertEquals(0, visitor.getConflicts().size());
659 assertEquals("their", merged.getUser().getName());
660 assertEquals(1111, merged.getUser().getId());
661 assertEquals(theirWay.getRawTimestamp(), merged.getRawTimestamp());
662 assertSame(merged, myWay);
663 assertSame(merged.getNode(0), n1);
664 assertSame(merged.getNode(1), n2);
665
666 assertFalse(merged.isModified());
667 }
668
669 /**
670 * my and their way have no ids, neither do the nodes they refer to. but
671 * my and their way are semantically equal. so technical attributes of
672 * their way can be merged on my way. No conflict.
673 */
674 @Test
675 public void testWaySimpleTwoWaysWithNoIdNodesWithoutId() {
676
677 // -- my data set
678
679 Node n1 = new Node(LatLon.ZERO);
680 my.addPrimitive(n1);
681
682 Node n2 = new Node(new LatLon(1, 1));
683 my.addPrimitive(n2);
684
685 Way myWay = new Way();
686 myWay.addNode(n1);
687 myWay.addNode(n2);
688 my.addPrimitive(myWay);
689
690 // -- their data set
691
692 Node n3 = new Node(LatLon.ZERO);
693 their.addPrimitive(n3);
694
695 Node n4 = new Node(new LatLon(1, 1));
696 their.addPrimitive(n4);
697
698 Way theirWay = new Way();
699 theirWay.addNode(n3);
700 theirWay.addNode(n4);
701 User user = User.createOsmUser(1111, "their");
702 theirWay.setUser(user);
703 theirWay.setTimestamp(new Date());
704 their.addPrimitive(theirWay);
705
706 DataSetMerger visitor = new DataSetMerger(my, their);
707 visitor.merge();
708
709 // -- tests
710 Way merged = (Way) my.getWays().toArray()[0];
711 assertEquals(0, visitor.getConflicts().size());
712 assertEquals("their", merged.getUser().getName());
713 assertEquals(1111, merged.getUser().getId());
714 assertEquals(theirWay.getRawTimestamp(), merged.getRawTimestamp());
715 assertSame(merged, myWay);
716 assertSame(merged.getNode(0), n1);
717 assertSame(merged.getNode(1), n2);
718
719 assertFalse(merged.isModified());
720 }
721
722 /**
723 * My dataset includes a deleted node.
724 * Their dataset includes a way with three nodes, the first one being my node.
725 *
726 * => the merged way should include all three nodes. Deleted node should have deleted=false and
727 * special conflict with isDeleted should exist
728 */
729 @Test
730 public void testWayComplexMergingADeletedNode() {
731
732 // -- my dataset
733
734 Node mn1 = new Node(LatLon.ZERO);
735 mn1.setOsmId(1, 1);
736 mn1.setDeleted(true);
737 my.addPrimitive(mn1);
738
739 Node tn1 = new Node(LatLon.ZERO);
740 tn1.setOsmId(1, 1);
741 their.addPrimitive(tn1);
742
743 Node tn2 = new Node(new LatLon(1, 1));
744 tn2.setOsmId(2, 1);
745 their.addPrimitive(tn2);
746
747 Node tn3 = new Node(new LatLon(2, 2));
748 tn3.setOsmId(3, 1);
749 their.addPrimitive(tn3);
750
751 // -- their data set
752 Way theirWay = new Way();
753 theirWay.setOsmId(4, 1);
754 theirWay.addNode(tn1);
755 theirWay.addNode(tn2);
756 theirWay.addNode(tn3);
757 theirWay.setUser(User.createOsmUser(1111, "their"));
758 theirWay.setTimestamp(new Date());
759 their.addPrimitive(theirWay);
760
761 DataSetMerger visitor = new DataSetMerger(my, their);
762 visitor.merge();
763
764 assertEquals(1, visitor.getConflicts().size());
765 assertTrue(visitor.getConflicts().get(0).isMyDeleted());
766
767 Way myWay = (Way) my.getPrimitiveById(4, OsmPrimitiveType.WAY);
768 assertEquals(3, myWay.getNodesCount());
769
770 Node n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
771 assertTrue(myWay.getNodes().contains(n));
772
773 assertFalse(myWay.isModified());
774 }
775
776 /**
777 * My dataset includes a deleted node.
778 * Their dataset includes a relation with three nodes, the first one being my node.
779 *
780 * => the merged relation should include all three nodes. There should be conflict for deleted
781 * node with isMyDeleted set
782 */
783 @Test
784 public void testRelationComplexMergingADeletedNode() {
785
786 Node mn1 = new Node(LatLon.ZERO);
787 mn1.setOsmId(1, 1);
788 mn1.setDeleted(true);
789 my.addPrimitive(mn1);
790
791 Node tn1 = new Node(LatLon.ZERO);
792 tn1.setOsmId(1, 1);
793 their.addPrimitive(tn1);
794
795 Node tn2 = new Node(new LatLon(1, 1));
796 tn2.setOsmId(2, 1);
797 their.addPrimitive(tn2);
798
799 Node tn3 = new Node(new LatLon(2, 2));
800 tn3.setOsmId(3, 1);
801 their.addPrimitive(tn3);
802
803 Relation theirRelation = new Relation();
804 theirRelation.setOsmId(4, 1);
805
806 theirRelation.addMember(new RelationMember("", tn1));
807 theirRelation.addMember(new RelationMember("", tn2));
808 theirRelation.addMember(new RelationMember("", tn3));
809 their.addPrimitive(theirRelation);
810
811 DataSetMerger visitor = new DataSetMerger(my, their);
812 visitor.merge();
813
814 Node n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
815 assertNotNull(n);
816
817 assertEquals(1, visitor.getConflicts().size());
818 assertTrue(visitor.getConflicts().hasConflictForMy(n));
819 assertTrue(visitor.getConflicts().get(0).isMyDeleted());
820
821 Relation r = (Relation) my.getPrimitiveById(4, OsmPrimitiveType.RELATION);
822 assertEquals(3, r.getMembersCount());
823
824 assertFalse(r.isModified());
825 }
826
827 /**
828 * Merge an incomplete way with two incomplete nodes into an empty dataset.
829 *
830 * Use case: a way loaded with a multiget, i.e. GET /api/0.6/ways?ids=123456
831 */
832 @Test
833 public void testNewIncompleteWay() {
834
835 Node n1 = new Node(1);
836 their.addPrimitive(n1);
837
838 Node n2 = new Node(2);
839 their.addPrimitive(n2);
840
841 Way w3 = new Way(3);
842 w3.setNodes(Arrays.asList(n1, n2));
843 their.addPrimitive(w3);
844 assertTrue(w3.isIncomplete());
845
846 DataSetMerger visitor = new DataSetMerger(my, their);
847 visitor.merge();
848
849 assertEquals(0, visitor.getConflicts().size());
850
851 OsmPrimitive p = my.getPrimitiveById(1, OsmPrimitiveType.NODE);
852 assertNotNull(p);
853 assertTrue(p.isIncomplete());
854 p = my.getPrimitiveById(2, OsmPrimitiveType.NODE);
855 assertNotNull(p);
856 assertTrue(p.isIncomplete());
857 p = my.getPrimitiveById(3, OsmPrimitiveType.WAY);
858 assertNotNull(p);
859 assertTrue(p.isIncomplete());
860
861 Way w = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
862 assertNotNull(w);
863 assertTrue(p.isIncomplete());
864 assertEquals(2, w.getNodesCount());
865 assertTrue(w.getNode(0).isIncomplete());
866 assertTrue(w.getNode(1).isIncomplete());
867 }
868
869 /**
870 * Merge an incomplete way with two incomplete nodes into a dataset where the way already exists as complete way.
871 *
872 * Use case: a way loaded with a multiget, i.e. GET /api/0.6/ways?ids=123456 after a "Update selection " of this way
873 */
874 @Test
875 public void testIncompleteWayOntoCompleteWay() {
876
877 // an incomplete node
878 Node n1 = new Node(1);
879 their.addPrimitive(n1);
880
881 // another incomplete node
882 Node n2 = new Node(2);
883 their.addPrimitive(n2);
884
885 // an incomplete way with two incomplete nodes
886 Way w3 = new Way(3);
887 w3.setNodes(Arrays.asList(n1, n2));
888 their.addPrimitive(w3);
889
890 Node n4 = new Node(LatLon.ZERO);
891 n4.setOsmId(1, 1);
892 my.addPrimitive(n4);
893
894 Node n5 = new Node(new LatLon(1, 1));
895 n5.setOsmId(2, 1);
896 my.addPrimitive(n5);
897
898 Way w6 = new Way(3, 1);
899 w6.setNodes(Arrays.asList(n4, n5));
900 my.addPrimitive(w6);
901
902 DataSetMerger visitor = new DataSetMerger(my, their);
903 visitor.merge();
904
905 assertEquals(0, visitor.getConflicts().size());
906
907 OsmPrimitive p = my.getPrimitiveById(1, OsmPrimitiveType.NODE);
908 assertNotNull(p);
909 assertFalse(p.isIncomplete());
910 p = my.getPrimitiveById(2, OsmPrimitiveType.NODE);
911 assertNotNull(p);
912 assertFalse(p.isIncomplete());
913 p = my.getPrimitiveById(3, OsmPrimitiveType.WAY);
914 assertNotNull(p);
915 assertFalse(p.isIncomplete());
916
917 Way w = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
918 assertNotNull(w);
919 assertFalse(p.isIncomplete());
920 assertEquals(2, w.getNodesCount());
921 assertFalse(w.getNode(0).isIncomplete());
922 assertFalse(w.getNode(1).isIncomplete());
923 }
924
925 /**
926 * merge to complete nodes onto an incomplete way with the same two nodes, but incomplete.
927 * => both the nodes and the way should be complete in the target dataset after merging
928 */
929 @Test
930 public void testTwoCompleteNodesOntoAnIncompleteWay() {
931
932 // -- source dataset
933
934 // an complete node
935 Node n1 = new Node(1, 1);
936 n1.setCoor(new LatLon(1, 1));
937 their.addPrimitive(n1);
938
939 // another complete node
940 Node n2 = new Node(2, 1);
941 n2.setCoor(new LatLon(2, 2));
942 their.addPrimitive(n2);
943
944 // --- target dataset
945
946 Node n4 = new Node(1);
947 my.addPrimitive(n4);
948
949 Node n5 = new Node(2);
950 my.addPrimitive(n5);
951
952 Way w6 = new Way(3, 1);
953 w6.addNode(n4);
954 w6.addNode(n5);
955 my.addPrimitive(w6);
956
957 //-- merge it
958 DataSetMerger visitor = new DataSetMerger(my, their);
959 visitor.merge();
960
961 // -- test it
962 assertEquals(0, visitor.getConflicts().size());
963
964 Node n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
965 assertNotNull(n);
966 assertFalse(n.isIncomplete());
967
968 n = (Node) my.getPrimitiveById(2, OsmPrimitiveType.NODE);
969 assertNotNull(n);
970 assertFalse(n.isIncomplete());
971
972 Way w = (Way) my.getPrimitiveById(3, OsmPrimitiveType.WAY);
973 assertNotNull(w);
974 assertFalse(w.hasIncompleteNodes());
975 assertTrue(w.isUsable());
976 assertEquals(2, w.getNodesCount());
977 assertEquals(1, w.getNode(0).getId());
978 assertEquals(2, w.getNode(1).getId());
979 }
980
981 /**
982 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/12599">Bug #12599</a>.
983 */
984 @Test
985 public void testTicket12599() {
986 // Server node: no modifications
987 Node n1 = new Node(1, 1);
988 n1.setCoor(LatLon.ZERO);
989 assertFalse(n1.isModified());
990 their.addPrimitive(n1);
991
992 // Local node: one modification: addition of an uninteresting tag
993 Node n1b = new Node(n1);
994 n1b.setModified(true);
995 n1b.put("note", "something");
996 assertTrue(n1b.isModified());
997 assertEquals(0, n1b.getInterestingTags().size());
998 my.addPrimitive(n1b);
999
1000 // Merge
1001 DataSetMerger visitor = new DataSetMerger(my, their);
1002 visitor.merge();
1003
1004 // Check that modification is still here
1005 Node n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
1006 assertNotNull(n);
1007 assertEquals("something", n.get("note"));
1008 assertTrue(n.isModified());
1009
1010 // Merge again
1011 visitor = new DataSetMerger(my, their);
1012 visitor.merge();
1013
1014 // Check that modification is still here
1015 n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
1016 assertNotNull(n);
1017 assertEquals("something", n.get("note"));
1018 assertTrue(n.isModified());
1019 }
1020
1021
1022 /**
1023 * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/12616">Bug #12616</a>.
1024 */
1025 @Test
1026 public void testTicket12616() {
1027 // Server node: no modifications
1028 Node n1 = new Node(1, 1);
1029 n1.setCoor(LatLon.ZERO);
1030 assertFalse(n1.isModified());
1031 their.addPrimitive(n1);
1032
1033 // Local node: one modification: move
1034 Node n1b = new Node(n1);
1035 n1b.setCoor(new LatLon(1, 1));
1036 n1b.setModified(true);
1037 assertTrue(n1b.isModified());
1038 assertEquals(new LatLon(1, 1), n1b.getCoor());
1039 my.addPrimitive(n1b);
1040
1041 // Merge
1042 DataSetMerger visitor = new DataSetMerger(my, their);
1043 visitor.merge();
1044
1045 // Check that modification is still here
1046 Node n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
1047 assertNotNull(n);
1048 assertEquals(new LatLon(1, 1), n.getCoor());
1049 assertTrue(n.isModified());
1050
1051 // Merge again
1052 visitor = new DataSetMerger(my, their);
1053 visitor.merge();
1054
1055 // Check that modification is still here
1056 n = (Node) my.getPrimitiveById(1, OsmPrimitiveType.NODE);
1057 assertNotNull(n);
1058 assertEquals(new LatLon(1, 1), n.getCoor());
1059 assertTrue(n.isModified());
1060 }
1061}
Note: See TracBrowser for help on using the repository browser.