105 lines
3.6 KiB
Go
105 lines
3.6 KiB
Go
package platform
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"testing"
|
|
)
|
|
|
|
type countingStore struct {
|
|
*MockStore
|
|
vehiclesCalls int
|
|
vehicleRealtimeCalls int
|
|
overviewBatchCalls int
|
|
}
|
|
|
|
func newCountingStore() *countingStore {
|
|
return &countingStore{MockStore: NewMockStore()}
|
|
}
|
|
|
|
func (s *countingStore) Vehicles(ctx context.Context, query url.Values) (Page[VehicleRow], error) {
|
|
s.vehiclesCalls++
|
|
return s.MockStore.Vehicles(ctx, query)
|
|
}
|
|
|
|
func (s *countingStore) VehicleRealtime(ctx context.Context, query url.Values) (Page[VehicleRealtimeRow], error) {
|
|
s.vehicleRealtimeCalls++
|
|
return s.MockStore.VehicleRealtime(ctx, query)
|
|
}
|
|
|
|
func (s *countingStore) VehicleServiceOverviews(ctx context.Context, query VehicleOverviewBatchQuery) (Page[VehicleServiceOverview], error) {
|
|
s.overviewBatchCalls++
|
|
return s.MockStore.VehicleServiceOverviews(ctx, query)
|
|
}
|
|
|
|
func TestVehicleServiceOverviewUsesBatchDataPath(t *testing.T) {
|
|
store := newCountingStore()
|
|
service := NewService(store)
|
|
overview, err := service.VehicleServiceOverview(context.Background(), "粤AG18312", "")
|
|
if err != nil {
|
|
t.Fatalf("VehicleServiceOverview returned error: %v", err)
|
|
}
|
|
if overview.VIN != "LB9A32A24R0LS1426" {
|
|
t.Fatalf("expected canonical VIN from overview, got %+v", overview)
|
|
}
|
|
if store.overviewBatchCalls != 1 || store.vehiclesCalls != 0 || store.vehicleRealtimeCalls != 0 {
|
|
t.Fatalf("single overview should use one batch store call, batch=%d vehicles=%d realtime=%d", store.overviewBatchCalls, store.vehiclesCalls, store.vehicleRealtimeCalls)
|
|
}
|
|
}
|
|
|
|
func TestVehicleServiceOverviewsUsesBatchDataPath(t *testing.T) {
|
|
store := newCountingStore()
|
|
service := NewService(store)
|
|
page, err := service.VehicleServiceOverviews(context.Background(), VehicleOverviewBatchQuery{
|
|
Keywords: []string{"粤AG18312", "LMRKH9AC2R1004087"},
|
|
Limit: 200,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("VehicleServiceOverviews returned error: %v", err)
|
|
}
|
|
if page.Total != 2 || len(page.Items) != 2 {
|
|
t.Fatalf("expected two overview rows, got %+v", page)
|
|
}
|
|
if store.vehiclesCalls > 1 || store.vehicleRealtimeCalls > 1 {
|
|
t.Fatalf("batch overview should avoid per-keyword store calls, vehicles=%d realtime=%d", store.vehiclesCalls, store.vehicleRealtimeCalls)
|
|
}
|
|
}
|
|
|
|
func TestVehicleServiceSummaryCountsProtocolOnlineByProtocolSlot(t *testing.T) {
|
|
service := NewService(NewMockStore())
|
|
summary, err := service.VehicleServiceSummary(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("VehicleServiceSummary returned error: %v", err)
|
|
}
|
|
byProtocol := map[string]ProtocolStat{}
|
|
for _, protocol := range summary.Protocols {
|
|
byProtocol[protocol.Protocol] = protocol
|
|
}
|
|
gb32960 := byProtocol["GB32960"]
|
|
if gb32960.Total != 2 {
|
|
t.Fatalf("expected two GB32960 source slots, got %+v", gb32960)
|
|
}
|
|
if gb32960.Online != 1 {
|
|
t.Fatalf("GB32960 online count must use GB32960 source status only, got %+v", gb32960)
|
|
}
|
|
}
|
|
|
|
func TestCompleteProtocolStatsIncludesCanonicalSlots(t *testing.T) {
|
|
stats := completeProtocolStats([]ProtocolStat{{Protocol: "JT808", Online: 2, Total: 5}})
|
|
byProtocol := map[string]ProtocolStat{}
|
|
for _, stat := range stats {
|
|
byProtocol[stat.Protocol] = stat
|
|
}
|
|
for _, protocol := range canonicalVehicleProtocols {
|
|
if _, ok := byProtocol[protocol]; !ok {
|
|
t.Fatalf("canonical protocol %s should be present, got %+v", protocol, stats)
|
|
}
|
|
}
|
|
if byProtocol["JT808"].Online != 2 || byProtocol["JT808"].Total != 5 {
|
|
t.Fatalf("existing protocol stats should be preserved, got %+v", byProtocol["JT808"])
|
|
}
|
|
if byProtocol["GB32960"].Online != 0 || byProtocol["GB32960"].Total != 0 {
|
|
t.Fatalf("missing canonical protocol should be exposed as zero slot, got %+v", byProtocol["GB32960"])
|
|
}
|
|
}
|