Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWay.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWay.java	(revision 11440)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWay.java	(revision 11441)
@@ -31,14 +31,30 @@
     @Override
     public void visit(Way w) {
+        int last = w.getNodesCount();
+        if (last < 2)
+            return;
         Set<Node> nodes = new HashSet<>();
-        for (int i = 1; i < w.getNodesCount() - 1; i++) {
+        nodes.add(w.firstNode());
+        int countFirst = 0;
+        int countLast = 0;
+        for (int i = 1; i < last; i++) {
             Node n = w.getNode(i);
             if (nodes.contains(n)) {
-                errors.add(TestError.builder(this, Severity.WARNING, SELF_INTERSECT)
-                        .message(tr("Self-intersecting ways"))
-                        .primitives(w)
-                        .highlight(n)
-                        .build());
-                break;
+                boolean ok = false;
+                if (n == w.firstNode()) {
+                    if (countFirst++ == 0)
+                        ok = true;
+                } else if (i + 1 == last) {
+                    if (countLast++ == 0)
+                        ok = true;
+                }
+                if (!ok || countFirst + countLast > 1) {
+                    errors.add(TestError.builder(this, Severity.WARNING, SELF_INTERSECT)
+                            .message(tr("Self-intersecting ways"))
+                            .primitives(w)
+                            .highlight(n)
+                            .build());
+                    break;
+                }
             } else {
                 nodes.add(n);
Index: /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWayTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWayTest.java	(revision 11440)
+++ /trunk/test/unit/org/openstreetmap/josm/data/validation/tests/SelfIntersectingWayTest.java	(revision 11441)
@@ -25,17 +25,18 @@
     @BeforeClass
     public static void setUp() throws Exception {
-        JOSMFixture.createUnitTestFixture().init(true);
+        JOSMFixture.createUnitTestFixture().init(false);
     }
 
     private static List<Node> createNodes() {
         List<Node> nodes = new ArrayList<>();
-        for (int i = 0; i < 5; i++) {
+        for (int i = 0; i < 6; i++) {
             nodes.add(new Node(i+1));
         }
-        nodes.get(0).setCoor(new LatLon(34.2680878298, 133.56336369008));
-        nodes.get(1).setCoor(new LatLon(34.25096598132, 133.54891792012));
-        nodes.get(2).setCoor(new LatLon(34.24466741332, 133.56693544639));
-        nodes.get(3).setCoor(new LatLon(34.26815342405, 133.56066502976));
-        nodes.get(4).setCoor(new LatLon(34.26567411471, 133.56132705125));
+        nodes.get(0).setCoor(new LatLon(34.2680, 133.563));
+        nodes.get(1).setCoor(new LatLon(34.2509, 133.548));
+        nodes.get(2).setCoor(new LatLon(34.2446, 133.566));
+        nodes.get(3).setCoor(new LatLon(34.2681, 133.560));
+        nodes.get(4).setCoor(new LatLon(34.2656, 133.561));
+        nodes.get(5).setCoor(new LatLon(34.2655, 133.562));
         return nodes;
     }
@@ -86,4 +87,26 @@
 
     /**
+     * First node is identical to an inner node ("P"-Shape).
+     * This is considered okay.
+     */
+    @Test
+    public void testUnclosedWayFirstRepeated() {
+        List<Node> nodes = createNodes();
+
+        Way w = (Way) OsmUtils.createPrimitive("way ");
+        List<Node> wayNodes = new ArrayList<>();
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(1));
+        wayNodes.add(nodes.get(2));
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(3));
+        wayNodes.add(nodes.get(4));
+        w.setNodes(wayNodes);
+        SelfIntersectingWay test = new SelfIntersectingWay();
+        test.visit(w);
+        Assert.assertEquals(0, test.getErrors().size());
+    }
+
+    /**
      * Last node is identical to an inner node ("b"-Shape).
      * This is considered okay.
@@ -109,5 +132,5 @@
     /**
      * Both endpoints join at one inner node ("8"-shape).
-     * This is considered okay.
+     * This is considered to be an error.
      */
     @Test
@@ -127,5 +150,100 @@
         SelfIntersectingWay test = new SelfIntersectingWay();
         test.visit(w);
-        Assert.assertEquals(0, test.getErrors().size());
+        Assert.assertEquals(1, test.getErrors().size());
+        Assert.assertTrue(test.getErrors().iterator().next().getHighlighted().contains(nodes.get(0)));
+    }
+
+    /**
+     * Closed way contains a spike.
+     * This is considered to be an error.
+     */
+    @Test
+    public void testSpikeWithStartInClosedWay() {
+        List<Node> nodes = createNodes();
+
+        Way w = (Way) OsmUtils.createPrimitive("way ");
+        List<Node> wayNodes = new ArrayList<>();
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(1));
+        wayNodes.add(nodes.get(0)); // problem
+        wayNodes.add(nodes.get(3));
+        wayNodes.add(nodes.get(4));
+        wayNodes.add(nodes.get(0));
+        w.setNodes(wayNodes);
+        SelfIntersectingWay test = new SelfIntersectingWay();
+        test.visit(w);
+        Assert.assertEquals(1, test.getErrors().size());
+        Assert.assertTrue(test.getErrors().iterator().next().getHighlighted().contains(nodes.get(0)));
+    }
+
+    /**
+     * Closed way contains a spike.
+     * This is considered to be an error.
+     */
+    @Test
+    public void testSpikeWithEndInClosedWay() {
+        List<Node> nodes = createNodes();
+
+        Way w = (Way) OsmUtils.createPrimitive("way ");
+        List<Node> wayNodes = new ArrayList<>();
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(1));
+        wayNodes.add(nodes.get(2));
+        wayNodes.add(nodes.get(0)); // problem
+        wayNodes.add(nodes.get(3));
+        wayNodes.add(nodes.get(0));
+        w.setNodes(wayNodes);
+        SelfIntersectingWay test = new SelfIntersectingWay();
+        test.visit(w);
+        Assert.assertEquals(1, test.getErrors().size());
+        Assert.assertTrue(test.getErrors().iterator().next().getHighlighted().contains(nodes.get(0)));
+    }
+
+    /**
+     * Closed way contains a spike.
+     * This is considered to be an error.
+     */
+    @Test
+    public void testSpikeInClosedWay() {
+        List<Node> nodes = createNodes();
+
+        Way w = (Way) OsmUtils.createPrimitive("way ");
+        List<Node> wayNodes = new ArrayList<>();
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(1));
+        wayNodes.add(nodes.get(2));
+        wayNodes.add(nodes.get(3));
+        wayNodes.add(nodes.get(2));
+        wayNodes.add(nodes.get(0));
+        w.setNodes(wayNodes);
+        SelfIntersectingWay test = new SelfIntersectingWay();
+        test.visit(w);
+        Assert.assertEquals(1, test.getErrors().size());
+        Assert.assertTrue(test.getErrors().iterator().next().getHighlighted().contains(nodes.get(2)));
+    }
+
+    /**
+     * Closed way with barbell shape (a-b-c-a-d-e-f-d).
+     * This is considered to be an error.
+     */
+    @Test
+    public void testClosedWayBarbell() {
+        List<Node> nodes = createNodes();
+
+        Way w = (Way) OsmUtils.createPrimitive("way ");
+        List<Node> wayNodes = new ArrayList<>();
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(1));
+        wayNodes.add(nodes.get(2));
+        wayNodes.add(nodes.get(0));
+        wayNodes.add(nodes.get(3));
+        wayNodes.add(nodes.get(4));
+        wayNodes.add(nodes.get(5));
+        wayNodes.add(nodes.get(3));
+        w.setNodes(wayNodes);
+        SelfIntersectingWay test = new SelfIntersectingWay();
+        test.visit(w);
+        Assert.assertEquals(1, test.getErrors().size());
+        Assert.assertTrue(test.getErrors().iterator().next().getHighlighted().contains(nodes.get(3)));
     }
 
