Index: trunk/src/org/openstreetmap/josm/data/validation/tests/Highways.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/Highways.java	(revision 6572)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/Highways.java	(revision 6573)
@@ -22,4 +22,5 @@
 import org.openstreetmap.josm.data.validation.Test;
 import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -36,4 +37,5 @@
     protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_MAXSPEED = 2705;
     protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_HIGHWAY = 2706;
+    protected static final int SOURCE_WRONG_LINK = 2707;
 
     /**
@@ -104,4 +106,5 @@
                 testSourceMaxspeed(w, true);
             }
+            testHighwayLink(w);
         }
     }
@@ -140,4 +143,29 @@
     }
 
+    public static boolean isHighwayLinkOkay(final Way way) {
+        final String highway = way.get("highway");
+        if (highway == null || !highway.endsWith("_link")) {
+            return true;
+        }
+
+        final HashSet<OsmPrimitive> referrers = new HashSet<OsmPrimitive>();
+        referrers.addAll(way.firstNode().getReferrers());
+        referrers.addAll(way.lastNode().getReferrers());
+
+        return Utils.exists(Utils.filteredCollection(referrers, Way.class), new Predicate<Way>() {
+            @Override
+            public boolean evaluate(final Way otherWay) {
+                return !way.equals(otherWay) && otherWay.hasTag("highway", highway, highway.replaceAll("_link$", ""));
+            }
+        });
+    }
+
+    private void testHighwayLink(final Way way) {
+        if (!isHighwayLinkOkay(way)) {
+            errors.add(new TestError(this, Severity.WARNING,
+                    tr("Highway link is not linked to adequate highway/link"), SOURCE_WRONG_LINK, way));
+        }
+    }
+
     private void testMissingPedestrianCrossing(Node n) {
         leftByPedestrians = false;
Index: trunk/src/org/openstreetmap/josm/tools/Predicates.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Predicates.java	(revision 6572)
+++ trunk/src/org/openstreetmap/josm/tools/Predicates.java	(revision 6573)
@@ -1,3 +1,5 @@
 package org.openstreetmap.josm.tools;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 
 import java.util.regex.Pattern;
@@ -46,3 +48,15 @@
         };
     }
+
+    /**
+     * Returns a {@link Predicate} executing {@link OsmPrimitive#hasTag(String, String...)}.
+     */
+    public static Predicate<OsmPrimitive> hasTag(final String key, final String... values) {
+        return new Predicate<OsmPrimitive>() {
+            @Override
+            public boolean evaluate(OsmPrimitive p) {
+                return p.hasTag(key, values);
+            }
+        };
+    }
 }
