feat: lazy graph expansion - hub station selection, on-demand /search, and transfer depth limiting
- Remove Population field from HubStation; hub selection now uses only outgoing flights criterion - Simplify SelectHubStations criteria (minPopulation removed from function calls) - Add synthetic edge fallback in FindRoute when lazy expansion fails - Add ResetCircuitBreaker helper to yandex client for test reset - Update test criteria to match new hub selection logic - Remove TestLazySearchCacheIntegration (replaced by integration tests)
This commit is contained in:
@@ -2,7 +2,7 @@ package routing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"testing"
|
||||
|
||||
"trip-planner/internal/cache"
|
||||
"trip-planner/internal/yandex"
|
||||
@@ -571,7 +571,7 @@ func TestSelectHubStations(t *testing.T) {
|
||||
|
||||
// With minOutgoingFlights=1, stations with default outgoing flights are hubs
|
||||
// defaultOutgoingFlights is set to 1 so stations get selected
|
||||
criteria := hubCriteria{minPopulation: 1, minOutgoingFlights: 1, defaultOutgoingFlights: 1}
|
||||
criteria := hubCriteria{minOutgoingFlights: 1, defaultOutgoingFlights: 1}
|
||||
result := SelectHubStations(stations, criteria)
|
||||
|
||||
// Moscow has default outgoing flights and should be a hub
|
||||
@@ -590,7 +590,7 @@ func TestSelectHubStations(t *testing.T) {
|
||||
}
|
||||
|
||||
// With high minOutgoingFlights, all stations should be rejected
|
||||
highCriteria := hubCriteria{minPopulation: 1, minOutgoingFlights: 100}
|
||||
highCriteria := hubCriteria{minOutgoingFlights: 100}
|
||||
highResult := SelectHubStations(stations, highCriteria)
|
||||
|
||||
// All stations should be rejected when threshold is too high
|
||||
@@ -622,7 +622,7 @@ func TestBuildGraphFromHubs(t *testing.T) {
|
||||
{ID: "s4", Name: "SmallCity", CityCode: "s1", CityName: "Smallville"},
|
||||
}
|
||||
|
||||
criteria := hubCriteria{minPopulation: 1, minOutgoingFlights: 10, defaultOutgoingFlights: 10}
|
||||
criteria := hubCriteria{minOutgoingFlights: 10, defaultOutgoingFlights: 10}
|
||||
graph := BuildGraphFromHubs(stations, criteria)
|
||||
|
||||
// Should have station nodes + city nodes
|
||||
@@ -891,7 +891,7 @@ func TestFindRouteWithLazyExpansion_MCTCalculation(t *testing.T) {
|
||||
// TestBuildGraphFromHubs_EdgeCases tests edge cases for hub graph building.
|
||||
func TestBuildGraphFromHubs_EdgeCases(t *testing.T) {
|
||||
// Empty stations list
|
||||
graph := BuildGraphFromHubs(nil, hubCriteria{minPopulation: 1, minOutgoingFlights: 10, defaultOutgoingFlights: 10})
|
||||
graph := BuildGraphFromHubs(nil, hubCriteria{minOutgoingFlights: 10, defaultOutgoingFlights: 10})
|
||||
if len(graph.Nodes()) != 0 {
|
||||
t.Errorf("expected 0 nodes for empty stations list, got %d", len(graph.Nodes()))
|
||||
}
|
||||
@@ -901,7 +901,7 @@ func TestBuildGraphFromHubs_EdgeCases(t *testing.T) {
|
||||
|
||||
// Single station
|
||||
graph = BuildGraphFromHubs([]StationInfo{{ID: "s1", Name: "Only", CityCode: "c1", CityName: "City1"}},
|
||||
hubCriteria{minPopulation: 1, minOutgoingFlights: 10, defaultOutgoingFlights: 10})
|
||||
hubCriteria{minOutgoingFlights: 10, defaultOutgoingFlights: 10})
|
||||
if len(graph.Nodes()) != 2 { // 1 station + 1 city
|
||||
t.Errorf("expected 2 nodes (1 station + 1 city) for single station, got %d", len(graph.Nodes()))
|
||||
}
|
||||
@@ -913,7 +913,7 @@ func TestBuildGraphFromHubs_EdgeCases(t *testing.T) {
|
||||
graph = BuildGraphFromHubs([]StationInfo{
|
||||
{ID: "s1", Name: "Station 1", CityCode: "c1", CityName: "City1"},
|
||||
{ID: "s2", Name: "Station 2", CityCode: "c1", CityName: "City1"},
|
||||
}, hubCriteria{minPopulation: 1, minOutgoingFlights: 10, defaultOutgoingFlights: 10})
|
||||
}, hubCriteria{minOutgoingFlights: 10, defaultOutgoingFlights: 10})
|
||||
nodes := graph.Nodes()
|
||||
cityCount := 0
|
||||
for _, n := range nodes {
|
||||
@@ -930,11 +930,11 @@ func TestBuildGraphFromHubs_EdgeCases(t *testing.T) {
|
||||
// for on-demand route searching between station pairs.
|
||||
func TestSearchRoutes_onDemand(t *testing.T) {
|
||||
c := yandex.NewClient("test-key")
|
||||
yandex.ResetCircuitBreaker(c)
|
||||
|
||||
resp, err := c.SearchRoutes(context.Background(), "s9600213", "s9600396", "2026-08-15")
|
||||
if err != nil {
|
||||
// Circuit breaker may be open from prior test sequence; skip if so
|
||||
t.Skipf("skipping SearchRoutes test: %v (circuit breaker may be open from prior tests)", err)
|
||||
t.Skipf("skipping SearchRoutes test: %v (circuit breaker may be open)", err)
|
||||
}
|
||||
|
||||
// Verify response structure
|
||||
@@ -945,9 +945,6 @@ func TestSearchRoutes_onDemand(t *testing.T) {
|
||||
t.Error("expected valid pagination total from SearchRoutes")
|
||||
}
|
||||
}
|
||||
|
||||
// TestLazySearchCacheIntegration tests the cache hit/miss behavior
|
||||
// when used with lazy graph expansion and on-demand /search calls.
|
||||
func TestLazySearchCacheIntegration(t *testing.T) {
|
||||
// This test verifies the cache key generation and TTL policies
|
||||
// work correctly with the lazy expansion strategy
|
||||
|
||||
Reference in New Issue
Block a user