[osrm] 04/22: Imported Upstream version 5.0.0+ds

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri Apr 29 22:44:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository osrm.

commit f42bc40499a2591351d12e73ffd9a40844c188f5
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Apr 29 23:13:17 2016 +0200

    Imported Upstream version 5.0.0+ds
---
 CHANGELOG.md                                   |  46 +++
 appveyor-build.bat                             |  13 +-
 features/bicycle/bridge.feature                |  26 +-
 features/car/bridge.feature                    |  26 +-
 features/guidance/end-of-road.feature          |  19 +-
 features/guidance/fork.feature                 |  71 ++++
 features/guidance/turn.feature                 | 529 +++++++++++++++++++++++++
 features/testbot/continue_straight.feature     |  92 +++++
 include/engine/api/json_factory.hpp            |  22 +-
 include/engine/api/route_api.hpp               |   8 +-
 include/engine/guidance/assemble_leg.hpp       | 100 ++++-
 include/engine/guidance/route_leg.hpp          |   4 +
 include/extractor/travel_mode.hpp              |   1 -
 include/server/api/table_parameter_grammar.hpp |  12 +-
 include/util/static_rtree.hpp                  |  14 +-
 include/util/vector_tile.hpp                   |  37 ++
 profiles/bicycle.lua                           |   2 -
 profiles/car.lua                               |   2 -
 src/engine/api/json_factory.cpp                |   4 +-
 src/engine/plugins/tile.cpp                    |  66 +--
 src/extractor/extractor.cpp                    |   5 +
 src/extractor/scripting_environment.cpp        |   1 -
 unit_tests/library/coordinates.hpp             |   7 +
 unit_tests/library/match.cpp                   |   7 +-
 unit_tests/library/route.cpp                   |  80 +++-
 unit_tests/library/table.cpp                   | 131 +++++-
 unit_tests/library/tile.cpp                    | 106 ++++-
 unit_tests/library/trip.cpp                    | 132 +++++-
 unit_tests/library/waypoint_check.hpp          |  24 ++
 unit_tests/server/parameters_io.hpp            |  59 +++
 unit_tests/server/parameters_parser.cpp        | 236 +++++------
 unit_tests/util/static_rtree.cpp               |  36 +-
 32 files changed, 1670 insertions(+), 248 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4430ff0..b324d15 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,49 @@
+# 5.0.0
+   Changes with regard 5.0.0 RC2:
+   - API:
+     - if `geometry=geojson` is passed the resulting geometry can be a LineString or Point
+       depending on how many coordinates are present.
+     - the removal of the summary field was revered. for `steps=flase` the field will always be an empty string.
+
+   Changes with regard to 4.9.1:
+   - API:
+     - BREAKING: Complete rewrite of the HTTP and library API. See detailed documentation in the wiki.
+     - BREAKING: The default coordinate order is now `longitude, latidue`. Exception: Polyline geometry
+         which follow the original Google specification of `latitdue, longitude`.
+     - BREAKING: Polyline geometries now use precision 5, instead of previously 6
+     - BREAKING: Removed GPX support
+     - New service `tile` which serves debug vector tiles of the road network
+     - Completely new engine for guidance generation:
+        - Support for highway ramps
+        - Support for different intersection types (end of street, forks, merges)
+        - Instruction post-processing to merge unimportant instructions
+        - Improved handling of roundabouts
+
+   - Tools:
+     - BREAKING: Renamed osrm-prepare to osrm-contract
+     - BREAKING: Removes profiles from osrm-contract, only needed in osrm-extract.
+     - Abort processing in osrm-extract if there are no snappable edges remaining.
+     - Added .properties file to osrm-extract ouput.
+     - Enables the use of multiple segment-speed-files on the osrm-contract command line
+
+   - Profile changes:
+     - Remove movable bridge mode
+     - Add `maxspeed=none` tag to car profile.
+     - A `side_road` tag support for the OSRM car profile.
+
+   - Fixes:
+     - Issue #2150: Prevents routing over delivery ways and nodes
+     - Issue #1972: Provide uninstall target
+     - Issue #2072: Disable alternatives by default and if core factor < 1.0
+     - Issue #1999: Fix unpacking for self-loop nodes not in core.
+
+   - Infrastructure:
+     - Cucumber test suit is now based on cucumber-js, removes Ruby as dependency
+     - Updated to mapbox/variant v1.1
+     - Updated to libosmium v2.6.1
+     - Remove GeoJSON based debugging output, replaced by debug tiles
+
+
 # 5.0.0 RC2
    - Profiles:
       - `properties.allow_uturns_at_via` -> `properties.continue_straight_at_waypoint` (value is inverted!)
diff --git a/appveyor-build.bat b/appveyor-build.bat
index 5dbdfa2..3ef305d 100644
--- a/appveyor-build.bat
+++ b/appveyor-build.bat
@@ -116,14 +116,17 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR
 
 SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
 
-ECHO running engine-tests.exe ...
-%Configuration%\unit_tests\engine-tests.exe
-IF %ERRORLEVEL% NEQ 0 GOTO ERROR
 ECHO running extractor-tests.exe ...
-%Configuration%\unit_tests\extractor-tests.exe
+unit_tests\%Configuration%\extractor-tests.exe
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+ECHO running engine-tests.exe ...
+unit_tests\%Configuration%\engine-tests.exe
 IF %ERRORLEVEL% NEQ 0 GOTO ERROR
 ECHO running util-tests.exe ...
-%Configuration%\unit_tests\util-tests.exe
+unit_tests\%Configuration%\util-tests.exe
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+ECHO running server-tests.exe ...
+unit_tests\%Configuration%\server-tests.exe
 IF %ERRORLEVEL% NEQ 0 GOTO ERROR
 
 IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
diff --git a/features/bicycle/bridge.feature b/features/bicycle/bridge.feature
index e691ae1..9e3873f 100644
--- a/features/bicycle/bridge.feature
+++ b/features/bicycle/bridge.feature
@@ -1,5 +1,5 @@
 @routing @bicycle @bridge
-Feature: Bicycle - Handle movable bridge
+Feature: Bicycle - Handle cycling
 
     Background:
         Given the profile "bicycle"
@@ -18,14 +18,14 @@ Feature: Bicycle - Handle movable bridge
 
         When I route I should get
             | from | to | route           | modes                                  |
-            | a    | g  | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling |
-            | b    | f  | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling |
-            | e    | c  | cde,cde         | movable bridge,movable bridge          |
-            | e    | b  | cde,abc,abc     | movable bridge,cycling,cycling         |
-            | e    | a  | cde,abc,abc     | movable bridge,cycling,cycling         |
-            | c    | e  | cde,cde         | movable bridge,movable bridge          |
-            | c    | f  | cde,efg,efg     | movable bridge,cycling,cycling         |
-            | c    | g  | cde,efg,efg     | movable bridge,cycling,cycling         |
+            | a    | g  | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
+            | b    | f  | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
+            | e    | c  | cde,cde         | cycling,cycling          |
+            | e    | b  | cde,abc,abc     | cycling,cycling,cycling         |
+            | e    | a  | cde,abc,abc     | cycling,cycling,cycling         |
+            | c    | e  | cde,cde         | cycling,cycling          |
+            | c    | f  | cde,efg,efg     | cycling,cycling,cycling         |
+            | c    | g  | cde,efg,efg     | cycling,cycling,cycling         |
 
     Scenario: Bicycle - Properly handle durations
         Given the node map
@@ -41,7 +41,7 @@ Feature: Bicycle - Handle movable bridge
 
         When I route I should get
             | from | to | route           | modes                                  | speed  |
-            | a    | g  | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling | 5 km/h |
-            | b    | f  | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling | 4 km/h |
-            | c    | e  | cde,cde         | movable bridge,movable bridge          | 2 km/h |
-            | e    | c  | cde,cde         | movable bridge,movable bridge          | 2 km/h |
+            | a    | g  | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 5 km/h |
+            | b    | f  | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 4 km/h |
+            | c    | e  | cde,cde         | cycling,cycling          | 2 km/h |
+            | e    | c  | cde,cde         | cycling,cycling          | 2 km/h |
diff --git a/features/car/bridge.feature b/features/car/bridge.feature
index 931f1d9..c1cb506 100644
--- a/features/car/bridge.feature
+++ b/features/car/bridge.feature
@@ -1,5 +1,5 @@
 @routing @car @bridge
-Feature: Car - Handle movable bridge
+Feature: Car - Handle driving
 
     Background:
         Given the profile "car"
@@ -18,14 +18,14 @@ Feature: Car - Handle movable bridge
 
         When I route I should get
             | from | to | route           | modes                                  |
-            | a    | g  | abc,cde,efg,efg | driving,movable bridge,driving,driving |
-            | b    | f  | abc,cde,efg,efg | driving,movable bridge,driving,driving |
-            | e    | c  | cde,cde         | movable bridge,movable bridge          |
-            | e    | b  | cde,abc,abc     | movable bridge,driving,driving         |
-            | e    | a  | cde,abc,abc     | movable bridge,driving,driving         |
-            | c    | e  | cde,cde         | movable bridge,movable bridge          |
-            | c    | f  | cde,efg,efg     | movable bridge,driving,driving         |
-            | c    | g  | cde,efg,efg     | movable bridge,driving,driving         |
+            | a    | g  | abc,cde,efg,efg | driving,driving,driving,driving |
+            | b    | f  | abc,cde,efg,efg | driving,driving,driving,driving |
+            | e    | c  | cde,cde         | driving,driving          |
+            | e    | b  | cde,abc,abc     | driving,driving,driving         |
+            | e    | a  | cde,abc,abc     | driving,driving,driving         |
+            | c    | e  | cde,cde         | driving,driving          |
+            | c    | f  | cde,efg,efg     | driving,driving,driving         |
+            | c    | g  | cde,efg,efg     | driving,driving,driving         |
 
     Scenario: Car - Properly handle durations
         Given the node map
@@ -41,7 +41,7 @@ Feature: Car - Handle movable bridge
 
         When I route I should get
             | from | to | route           | modes                                  | speed  |
-            | a    | g  | abc,cde,efg,efg | driving,movable bridge,driving,driving | 7 km/h |
-            | b    | f  | abc,cde,efg,efg | driving,movable bridge,driving,driving | 5 km/h |
-            | c    | e  | cde,cde         | movable bridge,movable bridge          | 2 km/h |
-            | e    | c  | cde,cde         | movable bridge,movable bridge          | 2 km/h |
+            | a    | g  | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h |
+            | b    | f  | abc,cde,efg,efg | driving,driving,driving,driving | 5 km/h |
+            | c    | e  | cde,cde         | driving,driving          | 2 km/h |
+            | e    | c  | cde,cde         | driving,driving          | 2 km/h |
diff --git a/features/guidance/end-of-road.feature b/features/guidance/end-of-road.feature
index 7f8231b..323f5df 100644
--- a/features/guidance/end-of-road.feature
+++ b/features/guidance/end-of-road.feature
@@ -21,7 +21,6 @@ Feature: End Of Road Instructions
             | a,c       | ab,cbd,cbd | depart,end of road left,arrive  |
             | a,d       | ab,cbd,cbd | depart,end of road right,arrive |
 
-
     Scenario: End of Road with three streets
         Given the node map
             |   |   | c |
@@ -104,3 +103,21 @@ Feature: End Of Road Instructions
             | waypoints | route      | turns                           |
             | a,c       | ab,cbd,cbd | depart,end of road left,arrive  |
             | a,d       | ab,cbd,cbd | depart,end of road right,arrive |
+
+    Scenario: End of Road with two ramps - prefer ramp over end of road
+        Given the node map
+            |   |   | c |
+            | a |   | b |
+            |   |   | d |
+
+        And the ways
+            | nodes  | highway       |
+            | ab     | primary       |
+            | bc     | motorway_link |
+            | bd     | motorway_link |
+
+       When I route I should get
+            | waypoints | route    | turns                    |
+            | a,c       | ab,bc,bc | depart,ramp left,arrive  |
+            | a,d       | ab,bd,bd | depart,ramp right,arrive |
+
diff --git a/features/guidance/fork.feature b/features/guidance/fork.feature
index 7b78a28..916799e 100644
--- a/features/guidance/fork.feature
+++ b/features/guidance/fork.feature
@@ -211,3 +211,74 @@ Feature: Fork Instructions
             | a,c       | ,,    | depart,fork slight left,arrive  |
             | a,d       | ,,    | depart,fork slight right,arrive |
 
+    Scenario: Non-Fork on complex intersection - left
+        Given the node map
+            |   |   |   |   | c |
+            | a |   | b |   |   |
+            |   | e |   |   | d |
+
+        And the ways
+            | nodes  | highway   |
+            | abc    | secondary |
+            | bd     | tertiary  |
+            | eb     | tertiary  |
+
+       When I route I should get
+            | waypoints | route     | turns                           |
+            | a,c       | abc,abc   | depart,arrive                   |
+            | a,d       | abc,bd,bd | depart,turn slight right,arrive |
+
+    Scenario: Non-Fork on complex intersection - right
+        Given the node map
+            |   | e |   |   | c |
+            | a |   | b |   |   |
+            |   |   |   |   | d |
+
+        And the ways
+            | nodes  | highway   |
+            | abd    | secondary |
+            | bc     | tertiary  |
+            | eb     | tertiary  |
+
+       When I route I should get
+            | waypoints | route     | turns                          |
+            | a,c       | abd,bc,bc | depart,turn slight left,arrive |
+            | a,d       | abd,abd   | depart,arrive                  |
+
+    @pr2275 @bug
+    Scenario: Tripple fork
+        Given the node map
+            |   |   |   |   |   |   |   |   | c |
+            | a |   | b |   | d |   |   |   |   |
+            |   |   |   |   |   |   |   |   | e |
+
+        And the ways
+            | nodes  | highway   |
+            | ab     | secondary |
+            | bc     | secondary |
+            | bd     | secondary |
+            | be     | secondary |
+
+       When I route I should get
+            | waypoints | route    | turns                           |
+            | a,c       | ab,bc,bc | depart,fork slight left,arrive  |
+            | a,d       | ab,bd,bd | depart,fork straight,arrive     |
+            | a,e       | ab,be,be | depart,fork slight right,arrive |
+
+    Scenario: Tripple fork -- middle obvious
+        Given the node map
+            |   |   |   |   | c |
+            | a |   | b |   | d |
+            |   |   |   |   | e |
+
+        And the ways
+            | nodes  | highway   |
+            | abd    | secondary |
+            | bc     | secondary |
+            | be     | secondary |
+
+       When I route I should get
+            | waypoints | route     | turns                           |
+            | a,c       | abd,bc,bc | depart,turn slight left,arrive  |
+            | a,d       | abd,abd   | depart,arrive                   |
+            | a,e       | abd,be,be | depart,turn slight right,arrive |
diff --git a/features/guidance/turn.feature b/features/guidance/turn.feature
index 3eb5fc3..20f4226 100644
--- a/features/guidance/turn.feature
+++ b/features/guidance/turn.feature
@@ -282,3 +282,532 @@ Feature: Simple Turns
             | h,c       | first,second,second  | depart,turn left,arrive      |
             | h,i       | first,first,first    | depart,continue uturn,arrive |
 
+    Scenario: Three Way Similar Sharp Turns
+        Given the node map
+            | a |   |   |   | b |
+            | c |   |   |   |   |
+            |   | d |   |   |   |
+
+        And the ways
+            | nodes | highway |
+            | ab    | primary |
+            | bc    | primary |
+            | bd    | primary |
+
+        When I route I should get
+            | waypoints | route    | turns                          |
+            | a,c       | ab,bc,bc | depart,turn sharp right,arrive |
+            | a,d       | ab,bd,bd | depart,turn sharp right,arrive |
+            | d,c       | bd,bc,bc | depart,turn sharp left,arrive  |
+            | d,a       | bd,ab,ab | depart,turn sharp left,arrive  |
+
+    Scenario: Left Turn Assignment (1)
+        Given the node map
+            |   |   |   |   | d |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                          |
+            | a,d       | abc,bd,bd | depart,turn slight left,arrive |
+
+    Scenario: Left Turn Assignment (2)
+        Given the node map
+            |   |   |   |   | d |
+            |   |   |   |   |   |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                   |
+            | a,d       | abc,bd,bd | depart,turn left,arrive |
+
+    Scenario: Left Turn Assignment (3)
+        Given the node map
+            |   |   |   | d |   |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                   |
+            | a,d       | abc,bd,bd | depart,turn left,arrive |
+
+    Scenario: Left Turn Assignment (4)
+        Given the node map
+            |   |   | d |   |   |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                   |
+            | a,d       | abc,bd,bd | depart,turn left,arrive |
+
+    Scenario: Left Turn Assignment (5)
+        Given the node map
+            |   | d |   |   |   |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                   |
+            | a,d       | abc,bd,bd | depart,turn left,arrive |
+
+    @bug @pr2275
+    Scenario: Left Turn Assignment (6)
+        Given the node map
+            | d |   |   |   |   |
+            |   |   |   |   |   |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                         |
+            | a,d       | abc,bd,bd | depart,turn sharp left,arrive |
+
+    Scenario: Left Turn Assignment (7)
+        Given the node map
+            | d |   |   |   |   |
+            | a |   | b |   | c |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                         |
+            | a,d       | abc,bd,bd | depart,turn sharp left,arrive |
+
+    Scenario: Right Turn Assignment (1)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   | d |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn slight right,arrive |
+
+    Scenario: Right Turn Assignment (2)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   |   |   |   | d |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                    |
+            | a,d       | abc,bd,bd | depart,turn right,arrive |
+
+    Scenario: Right Turn Assignment (3)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            |   |   |   | d |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                    |
+            | a,d       | abc,bd,bd | depart,turn right,arrive |
+
+    Scenario: Right Turn Assignment (4)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            |   |   | d |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                    |
+            | a,d       | abc,bd,bd | depart,turn right,arrive |
+
+    Scenario: Right Turn Assignment (5)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            |   | d |   |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                    |
+            | a,d       | abc,bd,bd | depart,turn right,arrive |
+
+    @bug @pr2275
+    Scenario: Right Turn Assignment (6)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            | d |   |   |   |   |
+
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                          |
+            | a,d       | abc,bd,bd | depart,turn sharp right,arrive |
+
+    Scenario: Right Turn Assignment (7)
+        Given the node map
+            |   |   | e |   |   |
+            | a |   | b |   | c |
+            | d |   |   |   |   |
+
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                          |
+            | a,d       | abc,bd,bd | depart,turn sharp right,arrive |
+
+   Scenario: Right Turn Assignment Two Turns
+        Given the node map
+            |   |   | f |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            | d | e |   |   |   |
+
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                          |
+            | a,d       | abc,bd,bd | depart,turn sharp right,arrive |
+            | a,e       | abc,be,be | depart,turn right,arrive       |
+
+   Scenario: Right Turn Assignment Two Turns (2)
+        Given the node map
+            |   |   | f | c |   |
+            | a |   | b |   |   |
+            |   |   |   |   | e |
+            |   |   |   | d |   |
+
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn right,arrive        |
+            | a,e       | abc,be,be | depart,turn slight right,arrive |
+
+   Scenario: Right Turn Assignment Two Turns (3)
+        Given the node map
+            |   |   | f |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   | e |
+            |   |   |   | d |   |
+
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn right,arrive        |
+            | a,e       | abc,be,be | depart,turn slight right,arrive |
+
+   Scenario: Right Turn Assignment Two Turns (4)
+        Given the node map
+            |   |   | f |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   |   | d |   | e |
+
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn right,arrive        |
+            | a,e       | abc,be,be | depart,turn slight right,arrive |
+
+   Scenario: Right Turn Assignment Three Turns
+        Given the node map
+            |   |   | g |   |   |
+            | a |   | b |   | c |
+            |   | d |   | f |   |
+            |   |   | e |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+            | bg    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn sharp right,arrive  |
+            | a,e       | abc,be,be | depart,turn right,arrive        |
+            | a,f       | abc,bf,bf | depart,turn slight right,arrive |
+
+    Scenario: Slight Turn involving Oneways
+        Given the node map
+            |   |   | a |   |   |
+            |   |   |   |   |   |
+            |   |   | b |   | e |
+            | d |   |   |   |   |
+            |   |   | c |   |   |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary | yes    |
+            | dbe   | primary | no     |
+
+        When I route I should get
+            | waypoints | route   | turns         |
+            | a,c       | abc,abc | depart,arrive |
+            | d,e       | dbe,dbe | depart,arrive |
+            | e,d       | dbe,dbe | depart,arrive |
+
+    @bug @pr2275
+    Scenario: Slight Turn involving Oneways
+        Given the node map
+            |   |   |   | a |   |
+            |   |   |   |   |   |
+            |   |   |   |   |   |
+            |   |   | b |   | e |
+            | d |   |   |   |   |
+            |   |   | c |   |   |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary | yes    |
+            | dbe   | primary | no     |
+
+        When I route I should get
+            | waypoints | route   | turns         |
+            | a,c       | abc,abc | depart,arrive |
+            | d,e       | dbe,dbe | depart,arrive |
+            | e,d       | dbe,dbe | depart,arrive |
+
+
+    Scenario: Slight Turn involving Oneways - Name Change
+        Given the node map
+            |   |   | a |   |   |
+            |   |   |   |   |   |
+            |   |   | b |   | e |
+            | d |   |   |   |   |
+            |   |   | c |   |   |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary | yes    |
+            | db    | primary | no     |
+            | be    | primary | no     |
+
+        When I route I should get
+            | waypoints | route    | turns                               |
+            | a,c       | abc,abc  | depart,arrive                       |
+            | d,e       | db,be,be | depart,new name slight right,arrive |
+            | e,d       | be,db,db | depart,new name slight left,arrive  |
+
+     Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 1
+        Given the node map
+            |   |   | g |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   | d | e | f |   |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary | no     |
+            | db    | primary | yes    |
+            | eb    | primary | no     |
+            | fb    | primary | no     |
+            | bg    | primary | no     |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,e       | abc,eb,eb | depart,turn right,arrive        |
+            | a,f       | abc,fb,fb | depart,turn slight right,arrive |
+
+     @bug @pr2275
+     Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 2
+        Given the node map
+            |   |   | g |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   | d | e | f |   |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary | no     |
+            | db    | primary | no     |
+            | eb    | primary | yes    |
+            | fb    | primary | no     |
+            | bg    | primary | no     |
+
+        When I route I should get
+            | waypoints | route     | turns                          |
+            | a,d       | abc,db,db | depart,turn sharp right,arrive |
+            | a,f       | abc,fb,fb | depart,turn right,arrive       |
+
+    Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 3
+        Given the node map
+            |   |   | g |   |   |
+            | a |   | b |   | c |
+            |   |   |   |   |   |
+            |   | d | e | f |   |
+
+        And the ways
+            | nodes | highway | oneway |
+            | abc   | primary | no     |
+            | db    | primary | no     |
+            | be    | primary | no     |
+            | fb    | primary | yes    |
+            | bg    | primary | no     |
+
+        When I route I should get
+            | waypoints | route     | turns                          |
+            | a,d       | abc,db,db | depart,turn sharp right,arrive |
+            | a,e       | abc,be,be | depart,turn right,arrive       |
+
+    Scenario: Conflicting Turns with well distinguished turn
+        Given the node map
+            | a |   |   | b |   |   | c |
+            |   |   |   |   |   |   |   |
+            | f |   |   |   |   |   | d |
+            |   |   |   |   |   |   | e |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn slight right,arrive |
+            | a,e       | abc,be,be | depart,turn right,arrive        |
+            | a,f       | abc,bf,bf | depart,turn sharp right,arrive  |
+
+    @bug @pr2275
+    Scenario: Conflicting Turns with well distinguished turn (back)
+        Given the node map
+            | a |   |   | b |   |   | c |
+            |   |   |   |   |   |   |   |
+            | d |   |   |   |   |   | f |
+            |   | e |   |   |   |   |   |
+
+        And the ways
+            | nodes | highway |
+            | abc   | primary |
+            | bd    | primary |
+            | be    | primary |
+            | bf    | primary |
+
+        When I route I should get
+            | waypoints | route     | turns                           |
+            | a,d       | abc,bd,bd | depart,turn sharp right,arrive  |
+            | a,e       | abc,be,be | depart,turn right,arrive        |
+            | a,f       | abc,bf,bf | depart,turn slight right,arrive |
+
diff --git a/features/testbot/continue_straight.feature b/features/testbot/continue_straight.feature
new file mode 100644
index 0000000..40fcbb4
--- /dev/null
+++ b/features/testbot/continue_straight.feature
@@ -0,0 +1,92 @@
+ at routing @continue_straight @via @testbot
+Feature: U-turns at via points
+
+    Background:
+        Given the profile "testbot"
+
+    Scenario: Continue straight at waypoints enabled by default
+        Given the node map
+            | a | b | c | d |
+            |   | e | f | g |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+            | be    |
+            | dg    |
+            | ef    |
+            | fg    |
+
+        When I route I should get
+            | waypoints | route                   |
+            | a,e,c     | ab,be,be,ef,fg,dg,cd,cd |
+
+    Scenario: Query parameter to disallow changing direction at all waypoints
+        Given the node map
+            | a | b | c | d |
+            |   | e | f | g |
+
+        And the query options
+            | continue_straight | false |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+            | be    |
+            | dg    |
+            | ef    |
+            | fg    |
+
+        When I route I should get
+            | waypoints | route             |
+            | a,e,c     | ab,be,be,be,bc,bc |
+
+    Scenario: Instructions at waypoints at u-turns
+        Given the node map
+            | a | b | c | d |
+            |   | e | f | g |
+
+        And the query options
+            | continue_straight | false |
+
+        And the ways
+            | nodes |
+            | ab    |
+            | bc    |
+            | cd    |
+            | be    |
+            | dg    |
+            | ef    |
+            | fg    |
+
+        When I route I should get
+            | waypoints | route             |
+            | a,e,c     | ab,be,be,be,bc,bc |
+
+    Scenario: u-turn mixed with non-uturn vias
+        Given the node map
+            | a | 1 | b | 3 | c | 5 | d |
+            |   |   | 2 |   |   |   | 4 |
+            |   |   | e |   | f |   | g |
+
+        And the query options
+            | continue_straight | false |
+
+        And the ways
+            | nodes | oneway |
+            | ab    | no     |
+            | bc    | no     |
+            | cd    | no     |
+            | be    | yes    |
+            | dg    | no     |
+            | ef    | no     |
+            | fg    | no     |
+
+        When I route I should get
+            | waypoints | route                                           |
+            | 1,2,3,4,5 | ab,be,be,be,ef,fg,dg,cd,bc,bc,bc,cd,dg,dg,dg,cd,cd |
+
diff --git a/include/engine/api/json_factory.hpp b/include/engine/api/json_factory.hpp
index 0b1e5f3..398fb68 100644
--- a/include/engine/api/json_factory.hpp
+++ b/include/engine/api/json_factory.hpp
@@ -48,13 +48,25 @@ template <typename ForwardIter> util::json::String makePolyline(ForwardIter begi
 }
 
 template <typename ForwardIter>
-util::json::Object makeGeoJSONLineString(ForwardIter begin, ForwardIter end)
+util::json::Object makeGeoJSONGeometry(ForwardIter begin, ForwardIter end)
 {
+    auto num_coordinates = std::distance(begin, end);
+    BOOST_ASSERT(num_coordinates != 0);
     util::json::Object geojson;
-    geojson.values["type"] = "LineString";
-    util::json::Array coordinates;
-    std::transform(begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
-    geojson.values["coordinates"] = std::move(coordinates);
+    if (num_coordinates > 1)
+    {
+        geojson.values["type"] = "LineString";
+        util::json::Array coordinates;
+        std::transform(begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
+        geojson.values["coordinates"] = std::move(coordinates);
+    }
+    else if (num_coordinates > 0)
+    {
+        geojson.values["type"] = "Point";
+        util::json::Array coordinates;
+        coordinates.values.push_back(detail::coordinateToLonLat(*begin));
+        geojson.values["coordinates"] = std::move(coordinates);
+    }
     return geojson;
 }
 
diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp
index f2b7a73..1907bee 100644
--- a/include/engine/api/route_api.hpp
+++ b/include/engine/api/route_api.hpp
@@ -69,7 +69,7 @@ class RouteAPI : public BaseAPI
         }
 
         BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
-        return json::makeGeoJSONLineString(begin, end);
+        return json::makeGeoJSONGeometry(begin, end);
     }
 
     util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
@@ -93,8 +93,8 @@ class RouteAPI : public BaseAPI
 
             auto leg_geometry = guidance::assembleGeometry(
                 BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom);
-            auto leg = guidance::assembleLeg(path_data, leg_geometry, phantoms.source_phantom,
-                                             phantoms.target_phantom, reversed_target);
+            auto leg = guidance::assembleLeg(facade, path_data, leg_geometry, phantoms.source_phantom,
+                                             phantoms.target_phantom, reversed_target, parameters.steps);
 
             if (parameters.steps)
             {
@@ -169,7 +169,7 @@ class RouteAPI : public BaseAPI
                                                leg_geometry.locations.begin() + step.geometry_end));
                     }
                     BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
-                    return static_cast<util::json::Value>(json::makeGeoJSONLineString(
+                    return static_cast<util::json::Value>(json::makeGeoJSONGeometry(
                         leg_geometry.locations.begin() + step.geometry_begin,
                         leg_geometry.locations.begin() + step.geometry_end));
                 });
diff --git a/include/engine/guidance/assemble_leg.hpp b/include/engine/guidance/assemble_leg.hpp
index b8d3dfe..6f8e6cb 100644
--- a/include/engine/guidance/assemble_leg.hpp
+++ b/include/engine/guidance/assemble_leg.hpp
@@ -1,6 +1,7 @@
 #ifndef ENGINE_GUIDANCE_ASSEMBLE_LEG_HPP_
 #define ENGINE_GUIDANCE_ASSEMBLE_LEG_HPP_
 
+#include "engine/datafacade/datafacade_base.hpp"
 #include "engine/guidance/leg_geometry.hpp"
 #include "engine/guidance/route_leg.hpp"
 #include "engine/guidance/route_step.hpp"
@@ -22,12 +23,86 @@ namespace engine
 {
 namespace guidance
 {
+namespace detail
+{
+const constexpr std::size_t MAX_USED_SEGMENTS = 2;
+struct NamedSegment
+{
+    EdgeWeight duration;
+    std::uint32_t position;
+    std::uint32_t name_id;
+};
+
+template <std::size_t SegmentNumber>
+std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathData> &route_data)
+{
+    // merges segments with same name id
+    const auto collapse_segments = [](std::vector<NamedSegment> &segments)
+    {
+        auto out = segments.begin();
+        auto end = segments.end();
+        for (auto in = segments.begin(); in != end; ++in)
+        {
+            if (in->name_id == out->name_id)
+            {
+                out->duration += in->duration;
+            }
+            else
+            {
+                ++out;
+                BOOST_ASSERT(out != end);
+                *out = *in;
+            }
+        }
+        return out;
+    };
+
+    std::vector<NamedSegment> segments(route_data.size());
+    std::uint32_t index = 0;
+    std::transform(
+        route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point)
+        {
+            return NamedSegment{point.duration_until_turn, index++, point.name_id};
+        });
+    // this makes sure that the segment with the lowest position comes first
+    std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
+              {
+                  return lhs.name_id < rhs.name_id ||
+                         (lhs.name_id == rhs.name_id && lhs.position < rhs.position);
+              });
+    auto new_end = collapse_segments(segments);
+    segments.resize(new_end - segments.begin());
+    // sort descending
+    std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
+              {
+                  return lhs.duration > rhs.duration;
+              });
+
+    // make sure the segments are sorted by position
+    segments.resize(std::min(segments.size(), SegmentNumber));
+    std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
+              {
+                  return lhs.position < rhs.position;
+              });
 
-inline RouteLeg assembleLeg(const std::vector<PathData> &route_data,
+    std::array<std::uint32_t, SegmentNumber> summary;
+    std::fill(summary.begin(), summary.end(), 0);
+    std::transform(segments.begin(), segments.end(), summary.begin(),
+                   [](const NamedSegment &segment)
+                   {
+                       return segment.name_id;
+                   });
+    return summary;
+}
+}
+
+inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
+                            const std::vector<PathData> &route_data,
                             const LegGeometry &leg_geometry,
                             const PhantomNode &source_node,
                             const PhantomNode &target_node,
-                            const bool target_traversed_in_reverse)
+                            const bool target_traversed_in_reverse,
+                            const bool needs_summary)
 {
     const auto target_duration =
         (target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight) /
@@ -70,7 +145,26 @@ inline RouteLeg assembleLeg(const std::vector<PathData> &route_data,
                     10.0;
     }
 
-    return RouteLeg{duration, distance, {}};
+    std::string summary;
+    if (needs_summary)
+    {
+        auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(route_data);
+
+        BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
+        BOOST_ASSERT(summary_array.begin() != summary_array.end());
+        summary = std::accumulate(std::next(summary_array.begin()), summary_array.end(),
+                                  facade.GetNameForID(summary_array.front()),
+                                  [&facade](std::string previous, const std::uint32_t name_id)
+                                  {
+                                      if (name_id != 0)
+                                      {
+                                          previous += ", " + facade.GetNameForID(name_id);
+                                      }
+                                      return previous;
+                                  });
+    }
+
+    return RouteLeg{duration, distance, summary, {}};
 }
 
 } // namespace guidance
diff --git a/include/engine/guidance/route_leg.hpp b/include/engine/guidance/route_leg.hpp
index f3b8de1..5ecca4f 100644
--- a/include/engine/guidance/route_leg.hpp
+++ b/include/engine/guidance/route_leg.hpp
@@ -3,6 +3,9 @@
 
 #include "engine/guidance/route_step.hpp"
 
+#include <boost/optional.hpp>
+
+#include <string>
 #include <vector>
 
 namespace osrm
@@ -16,6 +19,7 @@ struct RouteLeg
 {
     double duration;
     double distance;
+    std::string summary;
     std::vector<RouteStep> steps;
 };
 }
diff --git a/include/extractor/travel_mode.hpp b/include/extractor/travel_mode.hpp
index 7ec7bec..fa75c37 100644
--- a/include/extractor/travel_mode.hpp
+++ b/include/extractor/travel_mode.hpp
@@ -46,7 +46,6 @@ const constexpr osrm::extractor::TravelMode TRAVEL_MODE_WALKING = 3;
 const constexpr osrm::extractor::TravelMode TRAVEL_MODE_FERRY = 4;
 const constexpr osrm::extractor::TravelMode TRAVEL_MODE_TRAIN = 5;
 const constexpr osrm::extractor::TravelMode TRAVEL_MODE_PUSHING_BIKE = 6;
-const constexpr osrm::extractor::TravelMode TRAVEL_MODE_MOVABLE_BRIDGE = 7;
 // FIXME only for testbot.lua
 const constexpr osrm::extractor::TravelMode TRAVEL_MODE_STEPS_UP = 8;
 const constexpr osrm::extractor::TravelMode TRAVEL_MODE_STEPS_DOWN = 9;
diff --git a/include/server/api/table_parameter_grammar.hpp b/include/server/api/table_parameter_grammar.hpp
index 00fe703..b95b1b8 100644
--- a/include/server/api/table_parameter_grammar.hpp
+++ b/include/server/api/table_parameter_grammar.hpp
@@ -32,15 +32,11 @@ struct TableParametersGrammar final : public BaseParametersGrammar
         };
 // TODO: ulonglong -> size_t not only on Windows but on all 32 bit platforms; unsupported anyway as of now
 #ifdef WIN32
-        destinations_rule = (qi::lit("destinations=") > (qi::ulong_long % ";")[set_destiantions]) |
-                            qi::lit("destinations=all");
-        sources_rule =
-            (qi::lit("sources=") > (qi::ulong_long % ";")[set_sources]) | qi::lit("sources=all");
+        destinations_rule = qi::lit("destinations=all") | (qi::lit("destinations=") > (qi::ulong_long % ";")[set_destiantions]);
+        sources_rule = qi::lit("sources=all") | (qi::lit("sources=") > (qi::ulong_long % ";")[set_sources]);
 #else
-        destinations_rule = (qi::lit("destinations=") > (qi::ulong_ % ";")[set_destiantions]) |
-                            qi::lit("destinations=all");
-        sources_rule =
-            (qi::lit("sources=") > (qi::ulong_ % ";")[set_sources]) | qi::lit("sources=all");
+        destinations_rule = qi::lit("destinations=all") | (qi::lit("destinations=") > (qi::ulong_ % ";")[set_destiantions]);
+        sources_rule = qi::lit("sources=all") | (qi::lit("sources=") > (qi::ulong_ % ";")[set_sources]);
 #endif
         table_rule = destinations_rule | sources_rule;
 
diff --git a/include/util/static_rtree.hpp b/include/util/static_rtree.hpp
index 32bd60b..2e5a988 100644
--- a/include/util/static_rtree.hpp
+++ b/include/util/static_rtree.hpp
@@ -441,6 +441,14 @@ class StaticRTree
                 // inspecting an actual road segment
                 auto &current_candidate = current_query_node.node.template get<CandidateSegment>();
 
+                // to allow returns of no-results if too restrictive filtering, this needs to be done here
+                // even though performance would indicate that we want to stop after adding the first candidate
+                if (terminate(results.size(), current_candidate))
+                {
+                    traversal_queue = std::priority_queue<QueryCandidate>{};
+                    break;
+                }
+
                 auto use_segment = filter(current_candidate);
                 if (!use_segment.first && !use_segment.second)
                 {
@@ -451,12 +459,6 @@ class StaticRTree
 
                 // store phantom node in result vector
                 results.push_back(std::move(current_candidate.data));
-
-                if (terminate(results.size(), current_candidate))
-                {
-                    traversal_queue = std::priority_queue<QueryCandidate>{};
-                    break;
-                }
             }
         }
 
diff --git a/include/util/vector_tile.hpp b/include/util/vector_tile.hpp
new file mode 100644
index 0000000..8d816da
--- /dev/null
+++ b/include/util/vector_tile.hpp
@@ -0,0 +1,37 @@
+#ifndef OSRM_UTIL_VECTOR_TILE_HPP
+#define OSRM_UTIL_VECTOR_TILE_HPP
+
+#include <cstdint>
+
+namespace osrm
+{
+namespace util
+{
+namespace vector_tile
+{
+
+const constexpr std::uint32_t LAYER_TAG = 3;
+const constexpr std::uint32_t NAME_TAG = 1;
+const constexpr std::uint32_t VERSION_TAG = 15;
+const constexpr std::uint32_t EXTEND_TAG = 5;
+const constexpr std::uint32_t FEATURE_TAG = 2;
+const constexpr std::uint32_t GEOMETRY_TAG = 3;
+const constexpr std::uint32_t VARIANT_TAG = 4;
+const constexpr std::uint32_t KEY_TAG = 3;
+const constexpr std::uint32_t ID_TAG = 1;
+const constexpr std::uint32_t GEOMETRY_TYPE_LINE = 2;
+const constexpr std::uint32_t FEATURE_ATTRIBUTES_TAG = 2;
+const constexpr std::uint32_t FEATURE_GEOMETRIES_TAG = 4;
+const constexpr std::uint32_t VARIANT_TYPE_UINT32 = 5;
+const constexpr std::uint32_t VARIANT_TYPE_BOOL = 7;
+const constexpr std::uint32_t VARIANT_TYPE_STRING = 1;
+const constexpr std::uint32_t VARIANT_TYPE_DOUBLE = 3;
+
+// Vector tiles are 4096 virtual pixels on each side
+const constexpr double EXTENT = 4096.0;
+const constexpr double BUFFER = 128.0;
+
+}
+}
+}
+#endif
diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua
index 84e02d8..644a254 100644
--- a/profiles/bicycle.lua
+++ b/profiles/bicycle.lua
@@ -234,8 +234,6 @@ function way_function (way, result)
     if duration and durationIsValid(duration) then
       result.duration = math.max( parseDuration(duration), 1 )
     end
-    result.forward_mode = mode.movable_bridge
-    result.backward_mode = mode.movable_bridge
     result.forward_speed = bridge_speed
     result.backward_speed = bridge_speed
   elseif route_speeds[route] then
diff --git a/profiles/car.lua b/profiles/car.lua
index 4033f31..ffe62ca 100644
--- a/profiles/car.lua
+++ b/profiles/car.lua
@@ -270,8 +270,6 @@ function way_function (way, result)
     if duration and durationIsValid(duration) then
       result.duration = max( parseDuration(duration), 1 )
     end
-    result.forward_mode = mode.movable_bridge
-    result.backward_mode = mode.movable_bridge
     result.forward_speed = bridge_speed
     result.backward_speed = bridge_speed
   end
diff --git a/src/engine/api/json_factory.cpp b/src/engine/api/json_factory.cpp
index b1f5da5..4d5ff9b 100644
--- a/src/engine/api/json_factory.cpp
+++ b/src/engine/api/json_factory.cpp
@@ -100,9 +100,6 @@ std::string modeToString(const extractor::TravelMode mode)
     case TRAVEL_MODE_PUSHING_BIKE:
         token = "pushing bike";
         break;
-    case TRAVEL_MODE_MOVABLE_BRIDGE:
-        token = "movable bridge";
-        break;
     case TRAVEL_MODE_STEPS_UP:
         token = "steps up";
         break;
@@ -197,6 +194,7 @@ util::json::Object makeRouteLeg(guidance::RouteLeg leg, util::json::Array steps)
     util::json::Object route_leg;
     route_leg.values["distance"] = std::round(leg.distance * 10) / 10.;
     route_leg.values["duration"] = std::round(leg.duration * 10) / 10.;
+    route_leg.values["summary"] = std::move(leg.summary);
     route_leg.values["steps"] = std::move(steps);
     return route_leg;
 }
diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp
index 87586ea..6ce85c7 100644
--- a/src/engine/plugins/tile.cpp
+++ b/src/engine/plugins/tile.cpp
@@ -3,6 +3,7 @@
 
 #include "util/coordinate_calculation.hpp"
 #include "util/web_mercator.hpp"
+#include "util/vector_tile.hpp"
 
 #include <boost/geometry.hpp>
 #include <boost/geometry/geometries/point_xy.hpp>
@@ -27,10 +28,6 @@ namespace plugins
 {
 namespace detail
 {
-// Vector tiles are 4096 virtual pixels on each side
-const constexpr double VECTOR_TILE_EXTENT = 4096.0;
-const constexpr double VECTOR_TILE_BUFFER = 128.0;
-
 // Simple container class for WGS84 coordinates
 template <typename T> struct Point final
 {
@@ -78,9 +75,9 @@ typedef boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>
 typedef boost::geometry::model::linestring<point_t> linestring_t;
 typedef boost::geometry::model::box<point_t> box_t;
 typedef boost::geometry::model::multi_linestring<linestring_t> multi_linestring_t;
-const static box_t clip_box(point_t(-detail::VECTOR_TILE_BUFFER, -detail::VECTOR_TILE_BUFFER),
-                            point_t(detail::VECTOR_TILE_EXTENT + detail::VECTOR_TILE_BUFFER,
-                                    detail::VECTOR_TILE_EXTENT + detail::VECTOR_TILE_BUFFER));
+const static box_t clip_box(point_t(-util::vector_tile::BUFFER, -util::vector_tile::BUFFER),
+                            point_t(util::vector_tile::EXTENT + util::vector_tile::BUFFER,
+                                    util::vector_tile::EXTENT + util::vector_tile::BUFFER));
 
 // from mapnik-vector-tile
 // Encodes a linestring using protobuf zigzag encoding
@@ -136,10 +133,10 @@ FixedLine coordinatesToTileLine(const util::Coordinate start,
         // convert lon/lat to tile coordinates
         const auto px = std::round(
             ((px_merc - tile_bbox.minx) * util::web_mercator::TILE_SIZE / tile_bbox.width()) *
-            detail::VECTOR_TILE_EXTENT / util::web_mercator::TILE_SIZE);
+            util::vector_tile::EXTENT / util::web_mercator::TILE_SIZE);
         const auto py = std::round(
             ((tile_bbox.maxy - py_merc) * util::web_mercator::TILE_SIZE / tile_bbox.height()) *
-            detail::VECTOR_TILE_EXTENT / util::web_mercator::TILE_SIZE);
+            util::vector_tile::EXTENT / util::web_mercator::TILE_SIZE);
 
         boost::geometry::append(unclipped_line, point_t(px, py));
     }
@@ -254,15 +251,15 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
     protozero::pbf_writer tile_writer{pbf_buffer};
     {
         // Add a layer object to the PBF stream.  3=='layer' from the vector tile spec (2.1)
-        protozero::pbf_writer layer_writer(tile_writer, 3);
+        protozero::pbf_writer layer_writer(tile_writer, util::vector_tile::LAYER_TAG);
         // TODO: don't write a layer if there are no features
 
-        layer_writer.add_uint32(15, 2); // version
+        layer_writer.add_uint32(util::vector_tile::VERSION_TAG, 2); // version
         // Field 1 is the "layer name" field, it's a string
-        layer_writer.add_string(1, "speeds"); // name
+        layer_writer.add_string(util::vector_tile::NAME_TAG, "speeds"); // name
         // Field 5 is the tile extent.  It's a uint32 and should be set to 4096
         // for normal vector tiles.
-        layer_writer.add_uint32(5, 4096); // extent
+        layer_writer.add_uint32(util::vector_tile::EXTEND_TAG, util::vector_tile::EXTENT); // extent
 
         // Begin the layer features block
         {
@@ -328,11 +325,13 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
                     // is_small
                     // boolean.  We onl serve up speeds from 0-139, so all we do is save the
                     // first
-                    protozero::pbf_writer feature_writer(layer_writer, 2);
+                    protozero::pbf_writer feature_writer(layer_writer,
+                                                         util::vector_tile::FEATURE_TAG);
                     // Field 3 is the "geometry type" field.  Value 2 is "line"
-                    feature_writer.add_enum(3, 2); // geometry type
+                    feature_writer.add_enum(util::vector_tile::GEOMETRY_TAG,
+                                            util::vector_tile::GEOMETRY_TYPE_LINE); // geometry type
                     // Field 1 for the feature is the "id" field.
-                    feature_writer.add_uint64(1, id++); // id
+                    feature_writer.add_uint64(util::vector_tile::ID_TAG, id++); // id
                     {
                         // When adding attributes to a feature, we have to write
                         // pairs of numbers.  The first value is the index in the
@@ -341,7 +340,8 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
                         // not writing the actual speed or bool value here, we're saving
                         // an index into the "values" array.  This means many features
                         // can share the same value data, leading to smaller tiles.
-                        protozero::packed_field_uint32 field(feature_writer, 2);
+                        protozero::packed_field_uint32 field(
+                            feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
 
                         field.add_element(0); // "speed" tag key offset
                         field.add_element(
@@ -358,7 +358,8 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
                     {
 
                         // Encode the geometry for the feature
-                        protozero::packed_field_uint32 geometry(feature_writer, 4);
+                        protozero::packed_field_uint32 geometry(
+                            feature_writer, util::vector_tile::FEATURE_GEOMETRIES_TAG);
                         encodeLinestring(tile_line, geometry, start_x, start_y);
                     }
                 };
@@ -405,10 +406,10 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
         // Field id 3 is the "keys" attribute
         // We need two "key" fields, these are referred to with 0 and 1 (their array indexes)
         // earlier
-        layer_writer.add_string(3, "speed");
-        layer_writer.add_string(3, "is_small");
-        layer_writer.add_string(3, "datasource");
-        layer_writer.add_string(3, "duration");
+        layer_writer.add_string(util::vector_tile::KEY_TAG, "speed");
+        layer_writer.add_string(util::vector_tile::KEY_TAG, "is_small");
+        layer_writer.add_string(util::vector_tile::KEY_TAG, "datasource");
+        layer_writer.add_string(util::vector_tile::KEY_TAG, "duration");
 
         // Now, we write out the possible speed value arrays and possible is_tiny
         // values.  Field type 4 is the "values" field.  It's a variable type field,
@@ -416,35 +417,36 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
         for (std::size_t i = 0; i < 128; i++)
         {
             // Writing field type 4 == variant type
-            protozero::pbf_writer values_writer(layer_writer, 4);
+            protozero::pbf_writer values_writer(layer_writer, util::vector_tile::VARIANT_TAG);
             // Attribute value 5 == uin64 type
-            values_writer.add_uint64(5, i);
+            values_writer.add_uint64(util::vector_tile::VARIANT_TYPE_UINT32, i);
         }
         {
-            protozero::pbf_writer values_writer(layer_writer, 4);
+            protozero::pbf_writer values_writer(layer_writer, util::vector_tile::VARIANT_TAG);
             // Attribute value 7 == bool type
-            values_writer.add_bool(7, true);
+            values_writer.add_bool(util::vector_tile::VARIANT_TYPE_BOOL, true);
         }
         {
-            protozero::pbf_writer values_writer(layer_writer, 4);
+            protozero::pbf_writer values_writer(layer_writer, util::vector_tile::VARIANT_TAG);
             // Attribute value 7 == bool type
-            values_writer.add_bool(7, false);
+            values_writer.add_bool(util::vector_tile::VARIANT_TYPE_BOOL, false);
         }
         for (std::size_t i = 0; i <= max_datasource_id; i++)
         {
             // Writing field type 4 == variant type
-            protozero::pbf_writer values_writer(layer_writer, 4);
+            protozero::pbf_writer values_writer(layer_writer, util::vector_tile::VARIANT_TAG);
             // Attribute value 1 == string type
-            values_writer.add_string(1, facade.GetDatasourceName(i));
+            values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING,
+                                     facade.GetDatasourceName(i));
         }
         for (auto weight : used_weights)
         {
             // Writing field type 4 == variant type
-            protozero::pbf_writer values_writer(layer_writer, 4);
+            protozero::pbf_writer values_writer(layer_writer, util::vector_tile::VARIANT_TAG);
             // Attribute value 2 == float type
             // Durations come out of OSRM in integer deciseconds, so we convert them
             // to seconds with a simple /10 for display
-            values_writer.add_double(3, weight / 10.);
+            values_writer.add_double(util::vector_tile::VARIANT_TYPE_DOUBLE, weight / 10.);
         }
     }
 
diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp
index 99f25ae..977a59c 100644
--- a/src/extractor/extractor.cpp
+++ b/src/extractor/extractor.cpp
@@ -555,6 +555,11 @@ void Extractor::BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
         in_iter++;
     }
     auto new_size = out_iter - node_based_edge_list.begin();
+    if (new_size == 0)
+    {
+        throw util::exception("There are no snappable edges left after processing.  Are you "
+                              "setting travel modes correctly in the profile?  Cannot continue.");
+    }
     node_based_edge_list.resize(new_size);
 
     TIMER_START(construction);
diff --git a/src/extractor/scripting_environment.cpp b/src/extractor/scripting_environment.cpp
index e3f9b6e..0840f7d 100644
--- a/src/extractor/scripting_environment.cpp
+++ b/src/extractor/scripting_environment.cpp
@@ -80,7 +80,6 @@ void ScriptingEnvironment::InitContext(ScriptingEnvironment::Context &context)
                              luabind::value("ferry", TRAVEL_MODE_FERRY),
                              luabind::value("train", TRAVEL_MODE_TRAIN),
                              luabind::value("pushing_bike", TRAVEL_MODE_PUSHING_BIKE),
-                             luabind::value("movable_bridge", TRAVEL_MODE_MOVABLE_BRIDGE),
                              luabind::value("steps_up", TRAVEL_MODE_STEPS_UP),
                              luabind::value("steps_down", TRAVEL_MODE_STEPS_DOWN),
                              luabind::value("river_up", TRAVEL_MODE_RIVER_UP),
diff --git a/unit_tests/library/coordinates.hpp b/unit_tests/library/coordinates.hpp
index 2ccc689..e2cb7e8 100644
--- a/unit_tests/library/coordinates.hpp
+++ b/unit_tests/library/coordinates.hpp
@@ -25,4 +25,11 @@ inline Locations get_locations_in_small_component()
             {Longitude{7.438190}, Latitude{43.747560}}};
 }
 
+inline Locations get_locations_in_big_component()
+{
+    return {{Longitude{7.415800}, Latitude{43.734132}},
+            {Longitude{7.417710}, Latitude{43.736721}},
+            {Longitude{7.421315}, Latitude{43.738814}}};
+}
+
 #endif
diff --git a/unit_tests/library/match.cpp b/unit_tests/library/match.cpp
index 37d36c2..b6b01ab 100644
--- a/unit_tests/library/match.cpp
+++ b/unit_tests/library/match.cpp
@@ -4,6 +4,7 @@
 #include "args.hpp"
 #include "fixture.hpp"
 #include "coordinates.hpp"
+#include "waypoint_check.hpp"
 
 #include "osrm/match_parameters.hpp"
 
@@ -46,12 +47,8 @@ BOOST_AUTO_TEST_CASE(test_match)
     {
         if (waypoint.is<mapbox::util::recursive_wrapper<util::json::Object>>())
         {
+            BOOST_CHECK(waypoint_check(waypoint));
             const auto &waypoint_object = waypoint.get<json::Object>();
-            const auto &waypoint_object_location = waypoint_object.values.at("location").get<json::Array>().values;
-            util::FloatLongitude lon(waypoint_object_location[0].get<json::Number>().value);
-            util::FloatLatitude lat(waypoint_object_location[1].get<json::Number>().value);
-            util::Coordinate location_coordinate(lon, lat);
-            BOOST_CHECK(location_coordinate.IsValid());
             const auto matchings_index = waypoint_object.values.at("matchings_index").get<json::Number>().value;
             const auto waypoint_index = waypoint_object.values.at("waypoint_index").get<json::Number>().value;
             const auto &route_legs = matchings[matchings_index].get<json::Object>().values.at("legs").get<json::Array>().values;
diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp
index f9aaae9..a090208 100644
--- a/unit_tests/library/route.cpp
+++ b/unit_tests/library/route.cpp
@@ -55,6 +55,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
                 json::Array{{json::Object{
                     {{"distance", 0.},
                      {"duration", 0.},
+                     {"summary", ""},
                      {"steps", json::Array{{json::Object{{{"duration", 0.},
                                                           {"distance", 0.},
                                                           {"geometry", "yw_jGupkl@??"},
@@ -153,6 +154,10 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates)
             const auto duration = leg_object.values.at("duration").get<json::Number>().value;
             BOOST_CHECK_EQUAL(duration, 0);
 
+            // nothing can be said about summary, empty or contains human readable summary
+            const auto summary = leg_object.values.at("summary").get<json::String>().value;
+            BOOST_CHECK(((void)summary, true));
+
             const auto &steps = leg_object.values.at("steps").get<json::Array>().values;
             BOOST_CHECK(!steps.empty());
 
@@ -237,9 +242,80 @@ BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component)
         const auto latitude = location[1].get<json::Number>().value;
         BOOST_CHECK(longitude >= -180. && longitude <= 180.);
         BOOST_CHECK(latitude >= -90. && latitude <= 90.);
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component)
+{
+    const auto args = get_args();
+    auto osrm = getOSRM(args.at(0));
+
+    using namespace osrm;
 
-        // TODO(daniel-j-h): we could do a Nearest request for each waypoint, verifying
-        // that we did indeed not snap to the input locations inside the small component.
+    const auto locations = get_locations_in_big_component();
+
+    RouteParameters params;
+    params.coordinates.push_back(locations.at(0));
+    params.coordinates.push_back(locations.at(1));
+    params.coordinates.push_back(locations.at(2));
+
+    json::Object result;
+    const auto rc = osrm.Route(params, result);
+    BOOST_CHECK(rc == Status::Ok);
+
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
+
+    for (const auto &waypoint : waypoints)
+    {
+        const auto &waypoint_object = waypoint.get<json::Object>();
+
+        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
+        const auto longitude = location[0].get<json::Number>().value;
+        const auto latitude = location[1].get<json::Number>().value;
+        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
+        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components)
+{
+    const auto args = get_args();
+    auto osrm = getOSRM(args.at(0));
+
+    using namespace osrm;
+
+    const auto big_component = get_locations_in_big_component();
+    const auto small_component = get_locations_in_small_component();
+
+    RouteParameters params;
+    params.coordinates.push_back(small_component.at(0));
+    params.coordinates.push_back(big_component.at(0));
+    params.coordinates.push_back(small_component.at(1));
+    params.coordinates.push_back(big_component.at(1));
+
+    json::Object result;
+    const auto rc = osrm.Route(params, result);
+    BOOST_CHECK(rc == Status::Ok);
+
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
+
+    for (const auto &waypoint : waypoints)
+    {
+        const auto &waypoint_object = waypoint.get<json::Object>();
+
+        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
+        const auto longitude = location[0].get<json::Number>().value;
+        const auto latitude = location[1].get<json::Number>().value;
+        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
+        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
     }
 }
 
diff --git a/unit_tests/library/table.cpp b/unit_tests/library/table.cpp
index bab5312..43b44a8 100644
--- a/unit_tests/library/table.cpp
+++ b/unit_tests/library/table.cpp
@@ -2,7 +2,9 @@
 #include <boost/test/test_case_template.hpp>
 
 #include "args.hpp"
+#include "coordinates.hpp"
 #include "fixture.hpp"
+#include "waypoint_check.hpp"
 
 #include "osrm/table_parameters.hpp"
 
@@ -14,7 +16,7 @@
 
 BOOST_AUTO_TEST_SUITE(table)
 
-BOOST_AUTO_TEST_CASE(test_table)
+BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_one_dest_matrix)
 {
     const auto args = get_args();
     BOOST_REQUIRE_EQUAL(args.size(), 1);
@@ -23,15 +25,138 @@ BOOST_AUTO_TEST_CASE(test_table)
 
     auto osrm = getOSRM(args[0]);
 
-    /*
     TableParameters params;
+    params.coordinates.push_back(get_dummy_location());
+    params.coordinates.push_back(get_dummy_location());
+    params.coordinates.push_back(get_dummy_location());
+    params.sources.push_back(0);
+    params.destinations.push_back(2);
 
     json::Object result;
 
     const auto rc = osrm.Table(params, result);
 
     BOOST_CHECK(rc == Status::Ok || rc == Status::Error);
-    */
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    // check that returned durations error is expected size and proportions
+    // this test expects a 1x1 matrix
+    const auto &durations_array = result.values.at("durations").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(durations_array.size(), params.sources.size());
+    for (unsigned int i = 0; i < durations_array.size(); i++)
+    {
+        const auto durations_matrix = durations_array[i].get<json::Array>().values;
+        BOOST_CHECK_EQUAL(durations_matrix.size(), params.sources.size()*params.destinations.size());
+    }
+    // check destinations array of waypoint objects
+    const auto &destinations_array = result.values.at("destinations").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(destinations_array.size(), params.destinations.size());
+    for (const auto &destination : destinations_array)
+    {
+        BOOST_CHECK(waypoint_check(destination));
+    }
+    // check sources array of waypoint objects
+    const auto &sources_array = result.values.at("sources").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(sources_array.size(), params.sources.size());
+    for (const auto &source : sources_array)
+    {
+        BOOST_CHECK(waypoint_check(source));
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_matrix)
+{
+    const auto args = get_args();
+    BOOST_REQUIRE_EQUAL(args.size(), 1);
+
+    using namespace osrm;
+
+    auto osrm = getOSRM(args[0]);
+
+    TableParameters params;
+    params.coordinates.push_back(get_dummy_location());
+    params.coordinates.push_back(get_dummy_location());
+    params.coordinates.push_back(get_dummy_location());
+    params.sources.push_back(0);
+
+    json::Object result;
+
+    const auto rc = osrm.Table(params, result);
+
+    BOOST_CHECK(rc == Status::Ok || rc == Status::Error);
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    // check that returned durations error is expected size and proportions
+    // this test expects a 1x3 matrix
+    const auto &durations_array = result.values.at("durations").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(durations_array.size(), params.sources.size());
+    for (unsigned int i = 0; i < durations_array.size(); i++)
+    {
+        const auto durations_matrix = durations_array[i].get<json::Array>().values;
+        BOOST_CHECK_EQUAL(durations_matrix[i].get<json::Number>().value, 0);
+        BOOST_CHECK_EQUAL(durations_matrix.size(), params.sources.size()*params.coordinates.size());
+    }
+    // check destinations array of waypoint objects
+    const auto &destinations_array = result.values.at("destinations").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(destinations_array.size(), params.coordinates.size());
+    for (const auto &destination : destinations_array)
+    {
+        BOOST_CHECK(waypoint_check(destination));
+    }
+    // check sources array of waypoint objects
+    const auto &sources_array = result.values.at("sources").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(sources_array.size(), params.sources.size());
+    for (const auto &source : sources_array)
+    {
+        BOOST_CHECK(waypoint_check(source));
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_table_three_coordinates_matrix)
+{
+    const auto args = get_args();
+    BOOST_REQUIRE_EQUAL(args.size(), 1);
+
+    using namespace osrm;
+
+    auto osrm = getOSRM(args[0]);
+
+    TableParameters params;
+    params.coordinates.push_back(get_dummy_location());
+    params.coordinates.push_back(get_dummy_location());
+    params.coordinates.push_back(get_dummy_location());
+
+    json::Object result;
+
+    const auto rc = osrm.Table(params, result);
+
+    BOOST_CHECK(rc == Status::Ok || rc == Status::Error);
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    // check that returned durations error is expected size and proportions
+    // this test expects a 3x3 matrix
+    const auto &durations_array = result.values.at("durations").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(durations_array.size(), params.coordinates.size());
+    for (unsigned int i = 0; i < durations_array.size(); i++)
+    {
+        const auto durations_matrix = durations_array[i].get<json::Array>().values;
+        BOOST_CHECK_EQUAL(durations_matrix[i].get<json::Number>().value, 0);
+        BOOST_CHECK_EQUAL(durations_matrix.size(), params.coordinates.size());
+    }
+    const auto &destinations_array = result.values.at("destinations").get<json::Array>().values;
+    for (const auto &destination : destinations_array)
+    {
+        BOOST_CHECK(waypoint_check(destination));
+    }
+    const auto &sources_array = result.values.at("sources").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(sources_array.size(), params.coordinates.size());
+    for (const auto &source : sources_array)
+    {
+        BOOST_CHECK(waypoint_check(source));
+    }
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/unit_tests/library/tile.cpp b/unit_tests/library/tile.cpp
index 2ca674b..6cacc30 100644
--- a/unit_tests/library/tile.cpp
+++ b/unit_tests/library/tile.cpp
@@ -12,6 +12,10 @@
 #include "osrm/status.hpp"
 #include "osrm/osrm.hpp"
 
+#include "util/vector_tile.hpp"
+
+#include <protozero/pbf_reader.hpp>
+
 BOOST_AUTO_TEST_SUITE(tile)
 
 BOOST_AUTO_TEST_CASE(test_tile)
@@ -21,11 +25,111 @@ BOOST_AUTO_TEST_CASE(test_tile)
 
     using namespace osrm;
 
-    TileParameters params{0, 0, 1};
+    // This tile should contain most of monaco
+    TileParameters params{17059, 11948, 15};
 
     std::string result;
     const auto rc = osrm.Tile(params, result);
     BOOST_CHECK(rc == Status::Ok);
+
+    BOOST_CHECK_GT(result.size(), 128);
+
+    protozero::pbf_reader tile_message(result);
+    tile_message.next();
+    BOOST_CHECK_EQUAL(tile_message.tag(), util::vector_tile::LAYER_TAG); // must be a layer
+    protozero::pbf_reader layer_message = tile_message.get_message();
+
+    const auto check_feature = [](protozero::pbf_reader feature_message) {
+        protozero::pbf_reader::const_uint32_iterator value_begin;
+        protozero::pbf_reader::const_uint32_iterator value_end;
+        feature_message.next(); // advance parser to first entry
+        BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::GEOMETRY_TAG);
+        BOOST_CHECK_EQUAL(feature_message.get_enum(), util::vector_tile::GEOMETRY_TYPE_LINE);
+
+        feature_message.next(); // advance to next entry
+        BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::ID_TAG);
+        feature_message.get_uint64(); // id
+
+        feature_message.next(); // advance to next entry
+        BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG);
+        // properties
+        std::tie(value_begin, value_end) = feature_message.get_packed_uint32();
+        BOOST_CHECK_EQUAL(std::distance(value_begin, value_end), 8);
+        auto iter = value_begin;
+        BOOST_CHECK_EQUAL(*iter++, 0); // speed key
+        BOOST_CHECK_LT(*iter++, 128); // speed value
+        BOOST_CHECK_EQUAL(*iter++, 1); // component key
+        // component value
+        BOOST_CHECK_GE(*iter, 128);
+        BOOST_CHECK_LE(*iter, 129);
+        iter++;
+        BOOST_CHECK_EQUAL(*iter++, 2); // data source key
+        *iter++; // skip value check, can be valud uint32
+        BOOST_CHECK_EQUAL(*iter++, 3); // duration key
+        BOOST_CHECK_GT(*iter++, 130); // duration value
+        BOOST_CHECK(iter == value_end);
+        // geometry
+        feature_message.next();
+        std::tie(value_begin, value_end) = feature_message.get_packed_uint32();
+        BOOST_CHECK_GT(std::distance(value_begin, value_end), 1);
+    };
+
+    const auto check_value = [](protozero::pbf_reader value) {
+        while (value.next())
+        {
+            switch(value.tag())
+            {
+                case util::vector_tile::VARIANT_TYPE_BOOL:
+                    value.get_bool();
+                    break;
+                case util::vector_tile::VARIANT_TYPE_DOUBLE:
+                    value.get_double();
+                    break;
+                case util::vector_tile::VARIANT_TYPE_STRING:
+                    value.get_string();
+                    break;
+                case util::vector_tile::VARIANT_TYPE_UINT32:
+                    value.get_uint32();
+                    break;
+            }
+        }
+    };
+
+    auto number_of_keys = 0u;
+    auto number_of_values = 0u;
+
+    while (layer_message.next())
+    {
+        switch(layer_message.tag())
+        {
+            case util::vector_tile::VERSION_TAG:
+                BOOST_CHECK_EQUAL(layer_message.get_uint32(), 2);
+                break;
+            case util::vector_tile::NAME_TAG:
+                BOOST_CHECK_EQUAL(layer_message.get_string(), "speeds");
+                break;
+            case util::vector_tile::EXTEND_TAG:
+                BOOST_CHECK_EQUAL(layer_message.get_uint32(), util::vector_tile::EXTENT);
+                break;
+            case util::vector_tile::FEATURE_TAG:
+                check_feature(layer_message.get_message());
+                break;
+            case util::vector_tile::KEY_TAG:
+                layer_message.get_string();
+                number_of_keys++;
+                break;
+            case util::vector_tile::VARIANT_TAG:
+                check_value(layer_message.get_message());
+                number_of_values++;
+                break;
+            default:
+                BOOST_CHECK(false); // invalid tag
+                break;
+        }
+    }
+
+    BOOST_CHECK_EQUAL(number_of_keys, 4);
+    BOOST_CHECK_GT(number_of_values, 128); // speed value resolution
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/unit_tests/library/trip.cpp b/unit_tests/library/trip.cpp
index 7bfd1c2..e630706 100644
--- a/unit_tests/library/trip.cpp
+++ b/unit_tests/library/trip.cpp
@@ -1,7 +1,8 @@
-#include <boost/test/unit_test.hpp>
 #include <boost/test/test_case_template.hpp>
+#include <boost/test/unit_test.hpp>
 
 #include "args.hpp"
+#include "coordinates.hpp"
 #include "fixture.hpp"
 
 #include "osrm/trip_parameters.hpp"
@@ -9,29 +10,144 @@
 #include "osrm/coordinate.hpp"
 #include "osrm/engine_config.hpp"
 #include "osrm/json_container.hpp"
-#include "osrm/status.hpp"
 #include "osrm/osrm.hpp"
+#include "osrm/status.hpp"
 
 BOOST_AUTO_TEST_SUITE(trip)
 
-BOOST_AUTO_TEST_CASE(test_trip)
+BOOST_AUTO_TEST_CASE(test_trip_response_for_locations_in_small_component)
+{
+    const auto args = get_args();
+    auto osrm = getOSRM(args.at(0));
+
+    using namespace osrm;
+
+    const auto locations = get_locations_in_small_component();
+
+    TripParameters params;
+    params.coordinates.push_back(locations.at(0));
+    params.coordinates.push_back(locations.at(1));
+    params.coordinates.push_back(locations.at(2));
+
+    json::Object result;
+    const auto rc = osrm.Trip(params, result);
+    BOOST_CHECK(rc == Status::Ok);
+
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
+
+    const auto &trips = result.values.at("trips").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(trips.size(), 1);
+
+    for (const auto &waypoint : waypoints)
+    {
+        const auto &waypoint_object = waypoint.get<json::Object>();
+
+        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
+        const auto longitude = location[0].get<json::Number>().value;
+        const auto latitude = location[1].get<json::Number>().value;
+        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
+        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
+
+        const auto trip = waypoint_object.values.at("trips_index").get<json::Number>().value;
+        const auto pos = waypoint_object.values.at("waypoint_index").get<json::Number>().value;
+        BOOST_CHECK(trip >= 0 && trip < trips.size());
+        BOOST_CHECK(pos >= 0 && pos < waypoints.size());
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_trip_response_for_locations_in_big_component)
 {
     const auto args = get_args();
-    BOOST_REQUIRE_EQUAL(args.size(), 1);
+    auto osrm = getOSRM(args.at(0));
 
     using namespace osrm;
 
-    auto osrm = getOSRM(args[0]);
+    const auto locations = get_locations_in_big_component();
 
-    /*
     TripParameters params;
+    params.coordinates.push_back(locations.at(0));
+    params.coordinates.push_back(locations.at(1));
+    params.coordinates.push_back(locations.at(2));
 
     json::Object result;
+    const auto rc = osrm.Trip(params, result);
+    BOOST_CHECK(rc == Status::Ok);
+
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
+
+    const auto &trips = result.values.at("trips").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(trips.size(), 1);
+
+    for (const auto &waypoint : waypoints)
+    {
+        const auto &waypoint_object = waypoint.get<json::Object>();
+
+        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
+        const auto longitude = location[0].get<json::Number>().value;
+        const auto latitude = location[1].get<json::Number>().value;
+        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
+        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
+
+        const auto trip = waypoint_object.values.at("trips_index").get<json::Number>().value;
+        const auto pos = waypoint_object.values.at("waypoint_index").get<json::Number>().value;
+        BOOST_CHECK(trip >= 0 && trip < trips.size());
+        BOOST_CHECK(pos >= 0 && pos < waypoints.size());
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_trip_response_for_locations_across_components)
+{
+    const auto args = get_args();
+    auto osrm = getOSRM(args.at(0));
 
+    using namespace osrm;
+
+    const auto small = get_locations_in_small_component();
+    const auto big = get_locations_in_big_component();
+
+    TripParameters params;
+    params.coordinates.push_back(small.at(0));
+    params.coordinates.push_back(big.at(0));
+    params.coordinates.push_back(small.at(1));
+    params.coordinates.push_back(big.at(1));
+
+    json::Object result;
     const auto rc = osrm.Trip(params, result);
+    BOOST_CHECK(rc == Status::Ok);
+
+    const auto code = result.values.at("code").get<json::String>().value;
+    BOOST_CHECK_EQUAL(code, "Ok");
+
+    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());
+
+    const auto &trips = result.values.at("trips").get<json::Array>().values;
+    BOOST_CHECK_EQUAL(trips.size(), 1);
+    // ^ First snapping, then SCC decomposition (see plugins/trip.cpp). Therefore only a single trip.
+
+    for (const auto &waypoint : waypoints)
+    {
+        const auto &waypoint_object = waypoint.get<json::Object>();
+
+        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
+        const auto longitude = location[0].get<json::Number>().value;
+        const auto latitude = location[1].get<json::Number>().value;
+        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
+        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
 
-    BOOST_CHECK(rc == Status::Ok || rc == Status::Error);
-    */
+        const auto trip = waypoint_object.values.at("trips_index").get<json::Number>().value;
+        const auto pos = waypoint_object.values.at("waypoint_index").get<json::Number>().value;
+        BOOST_CHECK(trip >= 0 && trip < trips.size());
+        BOOST_CHECK(pos >= 0 && pos < waypoints.size());
+    }
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/unit_tests/library/waypoint_check.hpp b/unit_tests/library/waypoint_check.hpp
new file mode 100644
index 0000000..7bf1797
--- /dev/null
+++ b/unit_tests/library/waypoint_check.hpp
@@ -0,0 +1,24 @@
+#ifndef OSRM_UNIT_TEST_WAYPOINT_CHECK
+#define OSRM_UNIT_TEST_WAYPOINT_CHECK
+
+#include "osrm/coordinate.hpp"
+#include "osrm/json_container.hpp"
+#include "util/exception.hpp"
+
+using namespace osrm;
+
+inline bool waypoint_check(json::Value waypoint)
+{
+    if (!waypoint.is<mapbox::util::recursive_wrapper<util::json::Object>>())
+    {
+        throw util::exception("Must pass in a waypoint object");
+    }
+    const auto waypoint_object = waypoint.get<json::Object>();
+    const auto waypoint_location = waypoint_object.values.at("location").get<json::Array>().values;
+    util::FloatLongitude lon(waypoint_location[0].get<json::Number>().value);
+    util::FloatLatitude lat(waypoint_location[1].get<json::Number>().value);
+    util::Coordinate location_coordinate(lon, lat);
+    return location_coordinate.IsValid();
+}
+
+#endif
diff --git a/unit_tests/server/parameters_io.hpp b/unit_tests/server/parameters_io.hpp
new file mode 100644
index 0000000..dd2bd6c
--- /dev/null
+++ b/unit_tests/server/parameters_io.hpp
@@ -0,0 +1,59 @@
+#ifndef OSRM_TEST_SERVER_PARAMETERS_IO
+#define OSRM_TEST_SERVER_PARAMETERS_IO
+
+#include "engine/api/route_parameters.hpp"
+#include "engine/bearing.hpp"
+
+#include <ostream>
+
+namespace osrm
+{
+namespace engine
+{
+namespace api
+{
+inline std::ostream &operator<<(std::ostream &out, api::RouteParameters::GeometriesType geometries)
+{
+    switch (geometries)
+    {
+    case api::RouteParameters::GeometriesType::GeoJSON:
+        out << "GeoJSON";
+        break;
+    case api::RouteParameters::GeometriesType::Polyline:
+        out << "Polyline";
+        break;
+    default:
+        BOOST_ASSERT_MSG(false, "GeometriesType not fully captured");
+    }
+    return out;
+}
+
+inline std::ostream &operator<<(std::ostream &out, api::RouteParameters::OverviewType overview)
+{
+    switch (overview)
+    {
+    case api::RouteParameters::OverviewType::False:
+        out << "False";
+        break;
+    case api::RouteParameters::OverviewType::Full:
+        out << "Full";
+        break;
+    case api::RouteParameters::OverviewType::Simplified:
+        out << "Simplified";
+        break;
+    default:
+        BOOST_ASSERT_MSG(false, "OverviewType not fully captured");
+    }
+    return out;
+}
+}
+
+inline std::ostream &operator<<(std::ostream &out, Bearing bearing)
+{
+    out << bearing.bearing << "," << bearing.range;
+    return out;
+}
+}
+}
+
+#endif
diff --git a/unit_tests/server/parameters_parser.cpp b/unit_tests/server/parameters_parser.cpp
index 1b5161f..ecf98f2 100644
--- a/unit_tests/server/parameters_parser.cpp
+++ b/unit_tests/server/parameters_parser.cpp
@@ -1,5 +1,7 @@
 #include "server/api/parameters_parser.hpp"
 
+#include "parameters_io.hpp"
+
 #include "engine/api/base_parameters.hpp"
 #include "engine/api/match_parameters.hpp"
 #include "engine/api/nearest_parameters.hpp"
@@ -8,56 +10,6 @@
 #include "engine/api/tile_parameters.hpp"
 #include "engine/api/trip_parameters.hpp"
 
-#include <fstream>
-
-namespace osrm
-{
-namespace engine
-{
-namespace api
-{
-std::ostream &operator<<(std::ostream &out, api::RouteParameters::GeometriesType geometries)
-{
-    switch (geometries)
-    {
-    case api::RouteParameters::GeometriesType::GeoJSON:
-        out << "GeoJSON";
-        break;
-    case api::RouteParameters::GeometriesType::Polyline:
-        out << "Polyline";
-        break;
-    default:
-        BOOST_ASSERT_MSG(false, "GeometriesType not fully captured");
-    }
-    return out;
-}
-std::ostream &operator<<(std::ostream &out, api::RouteParameters::OverviewType overview)
-{
-    switch (overview)
-    {
-    case api::RouteParameters::OverviewType::False:
-        out << "False";
-        break;
-    case api::RouteParameters::OverviewType::Full:
-        out << "Full";
-        break;
-    case api::RouteParameters::OverviewType::Simplified:
-        out << "Simplified";
-        break;
-    default:
-        BOOST_ASSERT_MSG(false, "OverviewType not fully captured");
-    }
-    return out;
-}
-}
-std::ostream &operator<<(std::ostream &out, Bearing bearing)
-{
-    out << bearing.bearing << "," << bearing.range;
-    return out;
-}
-}
-}
-
 #include <boost/optional/optional_io.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
@@ -69,55 +21,54 @@ BOOST_AUTO_TEST_SUITE(api_parameters_parser)
 
 using namespace osrm;
 using namespace osrm::server;
+using namespace osrm::server::api;
+using namespace osrm::engine::api;
 
 // returns distance to front
 template <typename ParameterT> std::size_t testInvalidOptions(std::string options)
 {
     auto iter = options.begin();
-    auto result = api::parseParameters<ParameterT>(iter, options.end());
+    auto result = parseParameters<ParameterT>(iter, options.end());
     BOOST_CHECK(!result);
     return std::distance(options.begin(), iter);
 }
 
 BOOST_AUTO_TEST_CASE(invalid_route_urls)
 {
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&bla=foo"), 22UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&bearings=foo"),
+                      32UL);
     BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&bla=foo"), 22UL);
-    BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&bearings=foo"),
-        32UL);
-    BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&continue_straight=foo"),
-        41UL);
-    BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&radiuses=foo"),
-        32UL);
-    BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&hints=foo"), 29UL);
-    BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&geometries=foo"),
-        22UL);
-    BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&overview=foo"),
-        22L);
+        testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&continue_straight=foo"), 41UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&radiuses=foo"),
+                      32UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&hints=foo"),
+                      29UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&geometries=foo"),
+                      22UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&overview=foo"),
+                      22L);
     BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::RouteParameters>("1,2;3,4?overview=false&alternatives=foo"),
-        36UL);
+        testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&alternatives=foo"), 36UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(""), 0);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3.4.unsupported"), 7);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4.json?nooptions"), 13);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4..json?nooptions"), 14);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4.0.json?nooptions"), 15);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(std::string{"1,2;3,4"} + '\0' + ".json"), 7);
+    BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(std::string{"1,2;3,"} + '\0'), 6);
+
+    //BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(), );
 }
 
 BOOST_AUTO_TEST_CASE(invalid_table_urls)
 {
-    BOOST_CHECK_EQUAL(testInvalidOptions<engine::api::TableParameters>("1,2;3,4?sources=1&bla=foo"),
-                      17UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<TableParameters>("1,2;3,4?sources=1&bla=foo"), 17UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<TableParameters>("1,2;3,4?destinations=1&bla=foo"), 22UL);
     BOOST_CHECK_EQUAL(
-        testInvalidOptions<engine::api::TableParameters>("1,2;3,4?destinations=1&bla=foo"), 22UL);
-    BOOST_CHECK_EQUAL(testInvalidOptions<engine::api::TableParameters>(
-                          "1,2;3,4?sources=1&destinations=1&bla=foo"),
-                      32UL);
-    BOOST_CHECK_EQUAL(testInvalidOptions<engine::api::TableParameters>("1,2;3,4?sources=foo"),
-                      16UL);
-    BOOST_CHECK_EQUAL(testInvalidOptions<engine::api::TableParameters>("1,2;3,4?destinations=foo"),
-                      21UL);
+        testInvalidOptions<TableParameters>("1,2;3,4?sources=1&destinations=1&bla=foo"), 32UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<TableParameters>("1,2;3,4?sources=foo"), 16UL);
+    BOOST_CHECK_EQUAL(testInvalidOptions<TableParameters>("1,2;3,4?destinations=foo"), 21UL);
 }
 
 BOOST_AUTO_TEST_CASE(valid_route_urls)
@@ -125,9 +76,9 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
     std::vector<util::Coordinate> coords_1 = {{util::FloatLongitude(1), util::FloatLatitude(2)},
                                               {util::FloatLongitude(3), util::FloatLatitude(4)}};
 
-    engine::api::RouteParameters reference_1{};
+    RouteParameters reference_1{};
     reference_1.coordinates = coords_1;
-    auto result_1 = api::parseParameters<engine::api::RouteParameters>("1,2;3,4");
+    auto result_1 = parseParameters<RouteParameters>("1,2;3,4");
     BOOST_CHECK(result_1);
     BOOST_CHECK_EQUAL(reference_1.steps, result_1->steps);
     BOOST_CHECK_EQUAL(reference_1.alternatives, result_1->alternatives);
@@ -138,11 +89,11 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
     CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
     CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates);
 
-    engine::api::RouteParameters reference_2{};
+    RouteParameters reference_2{};
     reference_2.alternatives = true;
     reference_2.steps = true;
     reference_2.coordinates = coords_1;
-    auto result_2 = api::parseParameters<engine::api::RouteParameters>(
+    auto result_2 = parseParameters<RouteParameters>(
         "1,2;3,4?steps=true&alternatives=true&geometries=polyline&overview=simplified");
     BOOST_CHECK(result_2);
     BOOST_CHECK_EQUAL(reference_2.steps, result_2->steps);
@@ -154,12 +105,12 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
     CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
     CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
 
-    engine::api::RouteParameters reference_3{
-        false, false, engine::api::RouteParameters::GeometriesType::GeoJSON,
-        engine::api::RouteParameters::OverviewType::False, true};
+    RouteParameters reference_3{false, false, RouteParameters::GeometriesType::GeoJSON,
+                                RouteParameters::OverviewType::False, true};
     reference_3.coordinates = coords_1;
     auto result_3 = api::parseParameters<engine::api::RouteParameters>(
-        "1,2;3,4?steps=false&alternatives=false&geometries=geojson&overview=false&continue_straight=true");
+        "1,2;3,4?steps=false&alternatives=false&geometries=geojson&overview=false&continue_"
+        "straight=true");
     BOOST_CHECK(result_3);
     BOOST_CHECK_EQUAL(reference_3.steps, result_3->steps);
     BOOST_CHECK_EQUAL(reference_3.alternatives, result_3->alternatives);
@@ -180,16 +131,16 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
         engine::Hint::FromBase64("3gAAgP___"
                                  "39KAAAAHgAAACEAAAAAAAAAGAAAAE0BAABOAQAAGwAAAIAzcQBkUJsC1zNxAHBQmw"
                                  "IAAAEBl-Umfg==")};
-    engine::api::RouteParameters reference_4{false,
-                                             false,
-                                             engine::api::RouteParameters::GeometriesType::Polyline,
-                                             engine::api::RouteParameters::OverviewType::Simplified,
-                                             boost::optional<bool>{},
-                                             coords_1,
-                                             hints_4,
-                                             std::vector<boost::optional<double>>{},
-                                             std::vector<boost::optional<engine::Bearing>>{}};
-    auto result_4 = api::parseParameters<engine::api::RouteParameters>(
+    RouteParameters reference_4{false,
+                                false,
+                                RouteParameters::GeometriesType::Polyline,
+                                RouteParameters::OverviewType::Simplified,
+                                boost::optional<bool>{},
+                                coords_1,
+                                hints_4,
+                                std::vector<boost::optional<double>>{},
+                                std::vector<boost::optional<engine::Bearing>>{}};
+    auto result_4 = parseParameters<RouteParameters>(
         "1,2;3,4?steps=false&hints="
         "DAIAgP___38AAAAAAAAAAAIAAAAAAAAAEAAAAOgDAAD0AwAAGwAAAOUacQBQP5sCshpxAB0_mwIAAAEBl-Umfg==;"
         "cgAAgP___39jAAAADgAAACIAAABeAAAAkQAAANoDAABOAgAAGwAAAFVGcQCiRJsCR0VxAOZFmwIFAAEBl-Umfg==;"
@@ -207,17 +158,16 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
     std::vector<boost::optional<engine::Bearing>> bearings_4 = {
         boost::none, engine::Bearing{200, 10}, engine::Bearing{100, 5},
     };
-    engine::api::RouteParameters reference_5{false,
-                                             false,
-                                             engine::api::RouteParameters::GeometriesType::Polyline,
-                                             engine::api::RouteParameters::OverviewType::Simplified,
-                                             boost::optional<bool>{},
-                                             coords_1,
-                                             std::vector<boost::optional<engine::Hint>>{},
-                                             std::vector<boost::optional<double>>{},
-                                             bearings_4};
-    auto result_5 = api::parseParameters<engine::api::RouteParameters>(
-        "1,2;3,4?steps=false&bearings=;200,10;100,5");
+    RouteParameters reference_5{false,
+                                false,
+                                RouteParameters::GeometriesType::Polyline,
+                                RouteParameters::OverviewType::Simplified,
+                                boost::optional<bool>{},
+                                coords_1,
+                                std::vector<boost::optional<engine::Hint>>{},
+                                std::vector<boost::optional<double>>{},
+                                bearings_4};
+    auto result_5 = parseParameters<RouteParameters>("1,2;3,4?steps=false&bearings=;200,10;100,5");
     BOOST_CHECK(result_5);
     BOOST_CHECK_EQUAL(reference_5.steps, result_5->steps);
     BOOST_CHECK_EQUAL(reference_5.alternatives, result_5->alternatives);
@@ -232,10 +182,9 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
                                               {util::FloatLongitude(2), util::FloatLatitude(3)},
                                               {util::FloatLongitude(4), util::FloatLatitude(5)}};
 
-    engine::api::RouteParameters reference_6{};
+    RouteParameters reference_6{};
     reference_6.coordinates = coords_2;
-    auto result_6 =
-        api::parseParameters<engine::api::RouteParameters>("polyline(_ibE?_seK_seK_seK_seK)");
+    auto result_6 = parseParameters<RouteParameters>("polyline(_ibE?_seK_seK_seK_seK)");
     BOOST_CHECK(result_6);
     BOOST_CHECK_EQUAL(reference_6.steps, result_6->steps);
     BOOST_CHECK_EQUAL(reference_6.alternatives, result_6->alternatives);
@@ -245,6 +194,34 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
     CHECK_EQUAL_RANGE(reference_6.bearings, result_6->bearings);
     CHECK_EQUAL_RANGE(reference_6.radiuses, result_6->radiuses);
     CHECK_EQUAL_RANGE(reference_6.coordinates, result_6->coordinates);
+
+    auto result_7 = parseParameters<RouteParameters>("1,2;3,4?radiuses=;unlimited");
+    RouteParameters reference_7{};
+    reference_7.coordinates = coords_1;
+    reference_7.radiuses = {boost::none, boost::make_optional(std::numeric_limits<double>::infinity())};
+    BOOST_CHECK(result_7);
+    BOOST_CHECK_EQUAL(reference_7.steps, result_7->steps);
+    BOOST_CHECK_EQUAL(reference_7.alternatives, result_7->alternatives);
+    BOOST_CHECK_EQUAL(reference_7.geometries, result_7->geometries);
+    BOOST_CHECK_EQUAL(reference_7.overview, result_7->overview);
+    BOOST_CHECK_EQUAL(reference_7.continue_straight, result_7->continue_straight);
+    CHECK_EQUAL_RANGE(reference_7.bearings, result_7->bearings);
+    CHECK_EQUAL_RANGE(reference_7.radiuses, result_7->radiuses);
+    CHECK_EQUAL_RANGE(reference_7.coordinates, result_7->coordinates);
+
+    auto result_8 = parseParameters<RouteParameters>("1,2;3,4?radiuses=;");
+    RouteParameters reference_8{};
+    reference_8.coordinates = coords_1;
+    reference_8.radiuses = {boost::none, boost::none};
+    BOOST_CHECK(result_8);
+    CHECK_EQUAL_RANGE(reference_8.radiuses, result_8->radiuses);
+
+    auto result_9 = parseParameters<RouteParameters>("1,2?radiuses=");
+    RouteParameters reference_9{};
+    reference_9.coordinates = coords_1;
+    reference_9.radiuses = {boost::none};
+    BOOST_CHECK(result_9);
+    CHECK_EQUAL_RANGE(reference_9.radiuses, result_9->radiuses);
 }
 
 BOOST_AUTO_TEST_CASE(valid_table_urls)
@@ -252,9 +229,9 @@ BOOST_AUTO_TEST_CASE(valid_table_urls)
     std::vector<util::Coordinate> coords_1 = {{util::FloatLongitude(1), util::FloatLatitude(2)},
                                               {util::FloatLongitude(3), util::FloatLatitude(4)}};
 
-    engine::api::TableParameters reference_1{};
+    TableParameters reference_1{};
     reference_1.coordinates = coords_1;
-    auto result_1 = api::parseParameters<engine::api::TableParameters>("1,2;3,4");
+    auto result_1 = parseParameters<TableParameters>("1,2;3,4");
     BOOST_CHECK(result_1);
     CHECK_EQUAL_RANGE(reference_1.sources, result_1->sources);
     CHECK_EQUAL_RANGE(reference_1.destinations, result_1->destinations);
@@ -264,16 +241,23 @@ BOOST_AUTO_TEST_CASE(valid_table_urls)
 
     std::vector<std::size_t> sources_2 = {1, 2, 3};
     std::vector<std::size_t> destinations_2 = {4, 5};
-    engine::api::TableParameters reference_2{sources_2, destinations_2};
+    TableParameters reference_2{sources_2, destinations_2};
     reference_2.coordinates = coords_1;
-    auto result_2 = api::parseParameters<engine::api::TableParameters>(
-        "1,2;3,4?sources=1;2;3&destinations=4;5");
+    auto result_2 = parseParameters<TableParameters>("1,2;3,4?sources=1;2;3&destinations=4;5");
     BOOST_CHECK(result_2);
     CHECK_EQUAL_RANGE(reference_2.sources, result_2->sources);
     CHECK_EQUAL_RANGE(reference_2.destinations, result_2->destinations);
     CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings);
     CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
     CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
+
+    auto result_3 = parseParameters<TableParameters>("1,2;3,4?sources=all&destinations=all");
+    BOOST_CHECK(result_3);
+    CHECK_EQUAL_RANGE(reference_1.sources, result_3->sources);
+    CHECK_EQUAL_RANGE(reference_1.destinations, result_3->destinations);
+    CHECK_EQUAL_RANGE(reference_1.bearings, result_3->bearings);
+    CHECK_EQUAL_RANGE(reference_1.radiuses, result_3->radiuses);
+    CHECK_EQUAL_RANGE(reference_1.coordinates, result_3->coordinates);
 }
 
 BOOST_AUTO_TEST_CASE(valid_match_urls)
@@ -281,9 +265,9 @@ BOOST_AUTO_TEST_CASE(valid_match_urls)
     std::vector<util::Coordinate> coords_1 = {{util::FloatLongitude(1), util::FloatLatitude(2)},
                                               {util::FloatLongitude(3), util::FloatLatitude(4)}};
 
-    engine::api::MatchParameters reference_1{};
+    MatchParameters reference_1{};
     reference_1.coordinates = coords_1;
-    auto result_1 = api::parseParameters<engine::api::MatchParameters>("1,2;3,4");
+    auto result_1 = parseParameters<MatchParameters>("1,2;3,4");
     BOOST_CHECK(result_1);
     CHECK_EQUAL_RANGE(reference_1.timestamps, result_1->timestamps);
     CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
@@ -295,9 +279,9 @@ BOOST_AUTO_TEST_CASE(valid_nearest_urls)
 {
     std::vector<util::Coordinate> coords_1 = {{util::FloatLongitude(1), util::FloatLatitude(2)}};
 
-    engine::api::NearestParameters reference_1{};
+    NearestParameters reference_1{};
     reference_1.coordinates = coords_1;
-    auto result_1 = api::parseParameters<engine::api::NearestParameters>("1,2");
+    auto result_1 = parseParameters<NearestParameters>("1,2");
     BOOST_CHECK(result_1);
     BOOST_CHECK_EQUAL(reference_1.number_of_results, result_1->number_of_results);
     CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
@@ -307,8 +291,8 @@ BOOST_AUTO_TEST_CASE(valid_nearest_urls)
 
 BOOST_AUTO_TEST_CASE(valid_tile_urls)
 {
-    engine::api::TileParameters reference_1{1, 2, 3};
-    auto result_1 = api::parseParameters<engine::api::TileParameters>("tile(1,2,3).mvt");
+    TileParameters reference_1{1, 2, 3};
+    auto result_1 = parseParameters<TileParameters>("tile(1,2,3).mvt");
     BOOST_CHECK(result_1);
     BOOST_CHECK_EQUAL(reference_1.x, result_1->x);
     BOOST_CHECK_EQUAL(reference_1.y, result_1->y);
@@ -320,9 +304,9 @@ BOOST_AUTO_TEST_CASE(valid_trip_urls)
     std::vector<util::Coordinate> coords_1 = {{util::FloatLongitude(1), util::FloatLatitude(2)},
                                               {util::FloatLongitude(3), util::FloatLatitude(4)}};
 
-    engine::api::TripParameters reference_1{};
+    TripParameters reference_1{};
     reference_1.coordinates = coords_1;
-    auto result_1 = api::parseParameters<engine::api::TripParameters>("1,2;3,4");
+    auto result_1 = parseParameters<TripParameters>("1,2;3,4");
     BOOST_CHECK(result_1);
     CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
     CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
diff --git a/unit_tests/util/static_rtree.cpp b/unit_tests/util/static_rtree.cpp
index b3c2c9e..f8be130 100644
--- a/unit_tests/util/static_rtree.cpp
+++ b/unit_tests/util/static_rtree.cpp
@@ -230,10 +230,10 @@ void sampling_verify_rtree(RTreeT &rtree,
         auto lsnn_u = result_lsnn.back().u;
         auto lsnn_v = result_lsnn.back().v;
 
-        const double rtree_dist = coordinate_calculation::perpendicularDistance(
-            coords[rtree_u], coords[rtree_v], q);
-        const double lsnn_dist = coordinate_calculation::perpendicularDistance(
-            coords[lsnn_u], coords[lsnn_v], q);
+        const double rtree_dist =
+            coordinate_calculation::perpendicularDistance(coords[rtree_u], coords[rtree_v], q);
+        const double lsnn_dist =
+            coordinate_calculation::perpendicularDistance(coords[lsnn_u], coords[lsnn_v], q);
 
         BOOST_CHECK_CLOSE(rtree_dist, lsnn_dist, 0.0001);
     }
@@ -335,6 +335,34 @@ BOOST_AUTO_TEST_CASE(regression_test)
     BOOST_CHECK_EQUAL(result_ls.front().v, result_rtree.front().v);
 }
 
+// Bug: If you querry a point with a narrow radius, no result should be returned
+BOOST_AUTO_TEST_CASE(radius_regression_test)
+{
+    using Coord = std::pair<FloatLongitude, FloatLatitude>;
+    using Edge = std::pair<unsigned, unsigned>;
+    GraphFixture fixture(
+        {
+            Coord(FloatLongitude(0.0), FloatLatitude(0.0)),
+            Coord(FloatLongitude(10.0), FloatLatitude(10.0)),
+        },
+        {Edge(0, 1), Edge(1, 0)});
+
+    std::string leaves_path;
+    std::string nodes_path;
+    build_rtree<GraphFixture, MiniStaticRTree>("test_angle", &fixture, leaves_path, nodes_path);
+    MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);
+    MockDataFacade mockfacade;
+    engine::GeospatialQuery<MiniStaticRTree, MockDataFacade> query(rtree, fixture.coords,
+                                                                   mockfacade);
+
+    Coordinate input(FloatLongitude(5.2), FloatLatitude(5.0));
+
+    {
+        auto results = query.NearestPhantomNodesInRange(input, 0.01);
+        BOOST_CHECK_EQUAL(results.size(), 0);
+    }
+}
+
 BOOST_AUTO_TEST_CASE(bearing_tests)
 {
     using Coord = std::pair<FloatLongitude, FloatLatitude>;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osrm.git



More information about the Pkg-grass-devel mailing list