Index: trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java	(revision 9922)
+++ trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java	(revision 9923)
@@ -146,41 +146,10 @@
         }
 
-        final List<Node> nodeList = new ArrayList<>();
-        final List<WayData> wayDataList = new ArrayList<>();
         final Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
 
         try {
-            // collect nodes and ways from the selection
-            for (OsmPrimitive p : sel) {
-                if (p instanceof Node) {
-                    nodeList.add((Node) p);
-                } else if (p instanceof Way) {
-                    wayDataList.add(new WayData((Way) p));
-                } else
-                    throw new InvalidUserInputException(tr("Selection must consist only of ways and nodes."));
-            }
-            if (wayDataList.isEmpty())
-                throw new InvalidUserInputException("usage");
-            else  {
-                if (nodeList.size() == 2 || nodeList.isEmpty()) {
-                    OrthogonalizeAction.rememberMovements.clear();
-                    final Collection<Command> commands = new LinkedList<>();
-
-                    if (nodeList.size() == 2) {  // fixed direction
-                        commands.addAll(orthogonalize(wayDataList, nodeList));
-                    } else if (nodeList.isEmpty()) {
-                        List<List<WayData>> groups = buildGroups(wayDataList);
-                        for (List<WayData> g: groups) {
-                            commands.addAll(orthogonalize(g, nodeList));
-                        }
-                    } else
-                        throw new IllegalStateException();
-
-                    Main.main.undoRedo.add(new SequenceCommand(tr("Orthogonalize"), commands));
-                    Main.map.repaint();
-
-                } else
-                    throw new InvalidUserInputException("usage");
-            }
+            final SequenceCommand command = orthogonalize(sel);
+            Main.main.undoRedo.add(new SequenceCommand(tr("Orthogonalize"), command));
+            Main.map.repaint();
         } catch (InvalidUserInputException ex) {
             String msg;
@@ -194,4 +163,48 @@
                     .setDuration(Notification.TIME_DEFAULT)
                     .show();
+        }
+    }
+
+    /**
+     * Rectifies the selection
+     * @param selection the selection which should be rectified
+     * @return a rectifying command
+     * @throws InvalidUserInputException if the selection is invalid
+     */
+    static SequenceCommand orthogonalize(Iterable<OsmPrimitive> selection) throws InvalidUserInputException {
+        final List<Node> nodeList = new ArrayList<>();
+        final List<WayData> wayDataList = new ArrayList<>();
+        // collect nodes and ways from the selection
+        for (OsmPrimitive p : selection) {
+            if (p instanceof Node) {
+                nodeList.add((Node) p);
+            } else if (p instanceof Way) {
+                wayDataList.add(new WayData((Way) p));
+            } else
+                throw new InvalidUserInputException(tr("Selection must consist only of ways and nodes."));
+        }
+        if (wayDataList.isEmpty()) {
+            throw new InvalidUserInputException("usage");
+        } else  {
+            if (nodeList.size() == 2 || nodeList.isEmpty()) {
+                OrthogonalizeAction.rememberMovements.clear();
+                final Collection<Command> commands = new LinkedList<>();
+
+                if (nodeList.size() == 2) {  // fixed direction
+                    commands.addAll(orthogonalize(wayDataList, nodeList));
+                } else if (nodeList.isEmpty()) {
+                    List<List<WayData>> groups = buildGroups(wayDataList);
+                    for (List<WayData> g: groups) {
+                        commands.addAll(orthogonalize(g, nodeList));
+                    }
+                } else {
+                    throw new IllegalStateException();
+                }
+
+                return new SequenceCommand(tr("Orthogonalize"), commands);
+
+            } else {
+                throw new InvalidUserInputException("usage");
+            }
         }
     }
@@ -580,5 +593,5 @@
      * Exception: unsuited user input
      */
-    private static class InvalidUserInputException extends Exception {
+    protected static class InvalidUserInputException extends Exception {
         InvalidUserInputException(String message) {
             super(message);
@@ -593,5 +606,5 @@
      * Exception: angle cannot be recognized as 0, 90, 180 or 270 degrees
      */
-    private static class RejectedAngleException extends Exception {
+    protected static class RejectedAngleException extends Exception {
         RejectedAngleException() {
             super();
Index: trunk/test/data/orthogonalize.osm
===================================================================
--- trunk/test/data/orthogonalize.osm	(revision 9923)
+++ trunk/test/data/orthogonalize.osm	(revision 9923)
@@ -0,0 +1,53 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version='0.6' upload='true' generator='JOSM'>
+  <node id='-444' action='modify' visible='true' lat='8.53882631502' lon='55.72982273659' />
+  <node id='-446' action='modify' visible='true' lat='8.53692765033' lon='55.73148512506' />
+  <node id='-448' action='modify' visible='true' lat='8.53901816563' lon='55.7313279173' />
+  <node id='-450' action='modify' visible='true' lat='8.53673579867' lon='55.72997994436' />
+  <node id='-452' action='modify' visible='true' lat='8.53609408724' lon='55.73073587955' />
+  <node id='-454' action='modify' visible='true' lat='8.5381846071' lon='55.73057867179' />
+  <node id='-456' action='modify' visible='true' lat='8.534711427' lon='55.73000670312'>
+    <tag k='entrance' v='yes' />
+    <tag k='name' v='ClosedWayWithReferenceNodes' />
+  </node>
+  <node id='-458' action='modify' visible='true' lat='8.53545899034' lon='55.7305284991' />
+  <node id='-460' action='modify' visible='true' lat='8.5395738703' lon='55.73034453257' />
+  <node id='-462' action='modify' visible='true' lat='8.53490327967' lon='55.73151188383' />
+  <node id='-464' action='modify' visible='true' lat='8.53748335805' lon='55.73050174033' />
+  <node id='-466' action='modify' visible='true' lat='8.53406971216' lon='55.73076263832'>
+    <tag k='entrance' v='yes' />
+    <tag k='name' v='ClosedWayWithReferenceNodes' />
+  </node>
+  <way id='-468' action='modify' visible='true'>
+    <nd ref='-444' />
+    <nd ref='-460' />
+    <nd ref='-448' />
+    <nd ref='-454' />
+    <nd ref='-444' />
+    <tag k='building' v='yes' />
+    <tag k='name' v='ClosedWay' />
+  </way>
+  <way id='-470' action='modify' visible='true'>
+    <nd ref='-450' />
+    <nd ref='-464' />
+    <nd ref='-446' />
+    <tag k='building' v='yes' />
+    <tag k='name' v='TwoWaysFormingClosedWay' />
+  </way>
+  <way id='-472' action='modify' visible='true'>
+    <nd ref='-456' />
+    <nd ref='-458' />
+    <nd ref='-462' />
+    <nd ref='-466' />
+    <nd ref='-456' />
+    <tag k='building' v='yes' />
+    <tag k='name' v='ClosedWayWithReferenceNodes' />
+  </way>
+  <way id='-474' action='modify' visible='true'>
+    <nd ref='-446' />
+    <nd ref='-452' />
+    <nd ref='-450' />
+    <tag k='building' v='yes' />
+    <tag k='name' v='TwoWaysFormingClosedWay' />
+  </way>
+</osm>
Index: trunk/test/unit/org/openstreetmap/josm/actions/OrthogonalizeActionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/OrthogonalizeActionTest.java	(revision 9923)
+++ trunk/test/unit/org/openstreetmap/josm/actions/OrthogonalizeActionTest.java	(revision 9923)
@@ -0,0 +1,61 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import java.io.FileInputStream;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.actions.search.SearchCompiler;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.io.OsmReader;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Unit tests for class {@link OsmDataLayer}.
+ */
+public class OrthogonalizeActionTest {
+
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init(false);
+    }
+
+    @Test(expected = OrthogonalizeAction.InvalidUserInputException.class)
+    public void testNoSelection() throws Exception {
+        performTest("nothing selected");
+    }
+
+    @Test
+    public void testClosedWay() throws Exception {
+        performTest("name=ClosedWay");
+    }
+
+    @Test
+    public void testTwoWaysFormingClosedWay() throws Exception {
+        performTest("name=TwoWaysFormingClosedWay");
+    }
+
+    @Test
+    public void testTwoRingsAtOnce() throws Exception {
+        performTest("name=ClosedWay OR name=TwoWaysFormingClosedWay");
+    }
+
+    @Test
+    public void testClosedWayWithReferenceNodes() throws Exception {
+        performTest("name=ClosedWayWithReferenceNodes");
+    }
+
+    void performTest(String search) throws Exception {
+        try (FileInputStream in = new FileInputStream(TestUtils.getTestDataRoot() + "orthogonalize.osm")) {
+            final DataSet ds = OsmReader.parseDataSet(in, null);
+            ds.setSelected(Utils.filter(ds.allPrimitives(), SearchCompiler.compile(search)));
+            OrthogonalizeAction.orthogonalize(ds.getSelected());
+        }
+    }
+}
