fix: materialize stationary yutong daily mileage
This commit is contained in:
@@ -323,6 +323,95 @@ func TestQueryRealtimeLocationLastRowsBuildsYutongSourceFromPeer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryRealtimeLocationLastRowsCanCarryStationaryYutongMileage(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("sqlmock.New() error = %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
loc := time.FixedZone("Asia/Shanghai", 8*3600)
|
||||
currentEventTime := time.Date(2026, 7, 19, 6, 5, 42, 0, loc)
|
||||
mock.ExpectQuery("(?s)SELECT.*l\\.event_time.*l\\.total_mileage_event_time < \\?.*COALESCE\\(l\\.speed_kmh, 0\\) = 0").
|
||||
WithArgs("YUTONG_MQTT", "2026-07-19", "2026-07-19", "2026-07-19").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"vin", "peer", "event_time", "total_mileage_km"}).
|
||||
AddRow("LMRKH9AC9R1004099", "mqtt://yutong/ytforward/shln/2", currentEventTime, 24245.0))
|
||||
|
||||
rows, err := queryRealtimeLocationLastRows(context.Background(), db, config{
|
||||
Location: loc,
|
||||
StationaryCarry: true,
|
||||
}, envelope.ProtocolYutongMQTT, "2026-07-19")
|
||||
if err != nil {
|
||||
t.Fatalf("queryRealtimeLocationLastRows() error = %v", err)
|
||||
}
|
||||
sourceRows := rows["LMRKH9AC9R1004099"]
|
||||
if len(sourceRows) != 1 {
|
||||
t.Fatalf("rows = %d, want 1", len(sourceRows))
|
||||
}
|
||||
if !sourceRows[0].TS.Equal(currentEventTime) || sourceRows[0].TotalKM != 24245 {
|
||||
t.Fatalf("stationary carry row = %#v", sourceRows[0])
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddRealtimeLocationFallbackStationaryCarryUsesTrustedHistoricalBaseline(t *testing.T) {
|
||||
mysqlDB, mysqlMock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("mysql sqlmock.New() error = %v", err)
|
||||
}
|
||||
defer mysqlDB.Close()
|
||||
tdDB, tdMock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("td sqlmock.New() error = %v", err)
|
||||
}
|
||||
defer tdDB.Close()
|
||||
|
||||
loc := time.FixedZone("Asia/Shanghai", 8*3600)
|
||||
vin := "LMRKH9AC5R1004133"
|
||||
currentTS := time.Date(2026, 7, 19, 10, 20, 20, 0, loc)
|
||||
previousTS := time.Date(2026, 7, 17, 8, 49, 55, 0, loc)
|
||||
sourceKey := stats.SourceKeyForSource(envelope.ProtocolYutongMQTT, "", vin, "mqtt", "PLATFORM", "yutong")
|
||||
mysqlMock.ExpectQuery("(?s)FROM vehicle_realtime_location l.*l\\.event_time.*l\\.total_mileage_event_time < \\?").
|
||||
WithArgs("YUTONG_MQTT", "2026-07-19", "2026-07-19", "2026-07-19").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"vin", "peer", "event_time", "total_mileage_km"}).
|
||||
AddRow(vin, "mqtt://yutong/ytforward/shln/4", currentTS, 55451.0))
|
||||
mysqlMock.ExpectQuery("(?s)SELECT latest_total_mileage_km, latest_event_time.*FROM vehicle_daily_mileage_source").
|
||||
WithArgs(vin, "2026-07-19", "YUTONG_MQTT", sourceKey).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"latest_total_mileage_km", "latest_event_time"}).AddRow(55466.0, previousTS))
|
||||
|
||||
aggregates := map[string]*metricAgg{}
|
||||
added, err := addRealtimeLocationFallbackAggregates(context.Background(), mysqlDB, tdDB, config{
|
||||
TDengineDatabase: "lingniu_vehicle_ts",
|
||||
DateFrom: "2026-07-19",
|
||||
DateTo: "2026-07-19",
|
||||
Protocols: []envelope.Protocol{envelope.ProtocolYutongMQTT},
|
||||
Location: loc,
|
||||
StationaryCarry: true,
|
||||
}, aggregates)
|
||||
if err != nil {
|
||||
t.Fatalf("addRealtimeLocationFallbackAggregates() error = %v", err)
|
||||
}
|
||||
if added != 1 || len(aggregates) != 1 {
|
||||
t.Fatalf("added=%d aggregates=%d", added, len(aggregates))
|
||||
}
|
||||
for _, agg := range aggregates {
|
||||
if agg.FirstKM != 55466 || agg.LatestKM != 55466 {
|
||||
t.Fatalf("stationary km range = %v -> %v", agg.FirstKM, agg.LatestKM)
|
||||
}
|
||||
if agg.QualityStatus != stats.QualityOK || agg.QualityReason != stats.QualityReasonStationaryCarry {
|
||||
t.Fatalf("quality = %s/%s", agg.QualityStatus, agg.QualityReason)
|
||||
}
|
||||
}
|
||||
if err := mysqlMock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("mysql sql expectations: %v", err)
|
||||
}
|
||||
if err := tdMock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("td sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddRealtimeLocationFallbackAggregatesUsesHistoricalBaseline(t *testing.T) {
|
||||
mysqlDB, mysqlMock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user