- destination changed from generic 'Queens NY' to the real address, geocoded offline from the NY PBF (addr:street=46th Street, addr:housenumber=39-84, postcode 11104 -> 40.74707,-73.9181) - OSRM tree moved /tmp/osm-build -> /home/gmp/osm-build (durable); scripts default W to $HOME/osm-build; LD_LIBRARY_PATH export for the baked-in RPATH; cmake stub paths re-pointed - profile experiment: profiles/car-us.lua (US-tuned speed table on stock car.lua) -> Lincoln->Sunnyside 406 -> 377 min vs Valhalla 327; README documents the mechanism (motorway=90 x speed_reduction 0.8 = 72 km/h effective on untagged US interstates) - bench goldens re-recorded for both backends with new destination; both 26/26 PASS, integration tests pass on both routers
111 lines
3.7 KiB
Go
111 lines
3.7 KiB
Go
//go:build integration
|
|
|
|
// Integration tests hit a live router (hosted Valhalla by default, or a
|
|
// local OSRM via ROUTER_URL for the osrm backend). They verify the
|
|
// client plumbing and the stop_cost end-to-end on the real road network.
|
|
//
|
|
// Run: go test -tags integration ./...
|
|
package plan
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"maps/router/internal/geo"
|
|
"maps/router/internal/route"
|
|
)
|
|
|
|
func liveRouter(t *testing.T) route.Router {
|
|
backend := os.Getenv("ROUTER_BACKEND")
|
|
switch backend {
|
|
case "osrm":
|
|
return route.NewOSRM(os.Getenv("ROUTER_URL"))
|
|
default:
|
|
return route.NewValhalla("https://valhalla1.openstreetmap.de")
|
|
}
|
|
}
|
|
|
|
var (
|
|
lincoln = geo.Point{Lat: 44.054, Lon: -71.650}
|
|
sunnyside = geo.Point{Lat: 40.74707, Lon: -73.9181} // 39-84 46th St, Sunnyside 11104
|
|
)
|
|
|
|
func TestLiveDirectRoute(t *testing.T) {
|
|
t.Parallel()
|
|
r := liveRouter(t)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
|
|
defer cancel()
|
|
rt, err := r.Route(ctx, route.ProfileDrive, []geo.Point{lincoln, sunnyside})
|
|
if err != nil {
|
|
t.Fatalf("route: %v", err)
|
|
}
|
|
// Lincoln NH -> Sunnyside is a 5.25-5.75h drive (I-93/90/495/290).
|
|
// Anything outside this band means the backend or the dataset is wrong.
|
|
mins := rt.Duration / 60
|
|
if mins < 290 || mins > 430 {
|
|
t.Errorf("direct time = %.0f min, expected in [290, 430] (profile-dependent)", mins)
|
|
}
|
|
if rt.Distance < 480_000 || rt.Distance > 600_000 {
|
|
t.Errorf("distance = %.0f m, expected in [480km, 600km]", rt.Distance)
|
|
}
|
|
t.Logf("%s: %d min, %.0f km", r.Name(), int(mins), rt.Distance/1000)
|
|
}
|
|
|
|
// TestLiveRouteAvoidsBoston is the regression test for the user's
|
|
// "the router, not the model, knows the route" finding: the fastest
|
|
// Lincoln->Queens drive goes via I-90/I-495/I-290 (Worcester corridor),
|
|
// NOT through Boston.
|
|
func TestLiveRouteAvoidsBoston(t *testing.T) {
|
|
t.Parallel()
|
|
r := liveRouter(t)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
|
|
defer cancel()
|
|
rt, err := r.Route(ctx, route.ProfileDrive, []geo.Point{lincoln, sunnyside})
|
|
if err != nil {
|
|
t.Fatalf("route: %v", err)
|
|
}
|
|
boston := geo.Point{Lat: 42.36, Lon: -71.06}
|
|
var dist float64
|
|
if len(rt.Geometry) >= 2 {
|
|
dist = geo.DistToPolylineMeters(boston, rt.Geometry)
|
|
} else if !rt.BBox.Empty() {
|
|
dist = rt.BBox.DistMeters(boston)
|
|
t.Logf("using bbox distance (no geometry from backend)")
|
|
} else {
|
|
t.Skip("no geometry or bbox available")
|
|
}
|
|
if dist < 15_000 {
|
|
t.Errorf("route comes within %.1f km of Boston; expected the I-495/I-290 corridor (>= 15 km)", dist/1000)
|
|
}
|
|
t.Logf("Boston clearance: %.1f km", dist/1000)
|
|
}
|
|
|
|
// TestLiveStopCost exercises the full stop_cost pipeline on the real
|
|
// network: Cascade Falls (Worcester) sits on the I-495 corridor and
|
|
// must have a small detour; Mount Major (Alton NH) is far off it.
|
|
func TestLiveStopCost(t *testing.T) {
|
|
t.Parallel()
|
|
r := liveRouter(t)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second)
|
|
defer cancel()
|
|
|
|
cascade := geo.Point{Lat: 42.2767, Lon: -71.806}
|
|
mtmajor := geo.Point{Lat: 43.642, Lon: -71.156}
|
|
pts := []geo.Point{cascade, mtmajor, lincoln, sunnyside}
|
|
m, err := route.BuildMatrix(ctx, r, route.ProfileDrive, pts, 200*time.Millisecond)
|
|
if err != nil {
|
|
t.Fatalf("matrix: %v", err)
|
|
}
|
|
cascadeCost := StopCost(m, 0, Stop{ID: "cascade", DwellMin: 60})
|
|
majorCost := StopCost(m, 1, Stop{ID: "mtmajor", DwellMin: 120})
|
|
t.Logf("cascade detour = %d min; mtmajor detour = %d min", cascadeCost.DetourMin, majorCost.DetourMin)
|
|
if cascadeCost.DetourMin > 20 {
|
|
t.Errorf("Cascade Falls (on I-495 corridor) detour = %d min, want <= 20", cascadeCost.DetourMin)
|
|
}
|
|
if majorCost.DetourMin < 40 {
|
|
t.Errorf("Mount Major (off corridor) detour = %d min, want >= 40", majorCost.DetourMin)
|
|
}
|
|
}
|