trips/router/internal/plan/integration_test.go
Greg Pomerantz 916f9eb503 destination: 39-84 46th St, Sunnyside (OSM way 241831843); durable data location; profile-sensitivity experiment
- 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
2026-09-06 16:48:51 -04:00

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)
}
}