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

Last change on this file since 3283 was 3283, checked in by jttt, 14 years ago

Fix tests

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