package openplatform import ( "context" "encoding/json" "regexp" "strings" "testing" "time" "github.com/DATA-DOG/go-sqlmock" ) func TestBuildHydrogenDailyStatsUsesDirectValidBoundaries(t *testing.T) { base := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) values := hydrogenActiveTestSegment("LTEST32960VIN0001", "source-a", base, 10.5, 9.5) stats := BuildHydrogenDailyStats(values, "2026-07-01", 0.05, 20) if len(stats) != 1 { t.Fatalf("stats = %#v", stats) } stat := stats[0] if stat.ConsumptionKg != 1 || stat.FirstMassKg != 10.5 || stat.LastMassKg != 9.5 { t.Fatalf("stat = %#v", stat) } } func TestBuildHydrogenDailyStatsMergesSequentialSources(t *testing.T) { base := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) values := hydrogenActiveTestSegment("LTEST32960VIN0001", "source-a", base, 10, 9.6) for index := len(values) / 2; index < len(values); index++ { values[index].Source = "source-b" } stats := BuildHydrogenDailyStats(values, "2026-07-01", 0.05, 5) if len(stats) != 1 { t.Fatalf("stats = %#v", stats) } if stats[0].Source != "source-a" || stats[0].ConsumptionKg != 0.4 || stats[0].SampleCount != 10 { t.Fatalf("stat = %#v", stats[0]) } } func TestBuildHydrogenDailyStatsDeduplicatesSameEventAcrossSources(t *testing.T) { base := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) values := hydrogenActiveTestSegment("LTEST32960VIN0001", "source-a", base, 10, 9.6) duplicates := append([]HydrogenObservation(nil), values...) for index := range duplicates { duplicates[index].Source = "source-b" } stats := BuildHydrogenDailyStats(append(values, duplicates...), "2026-07-01", 0.05, 5) if len(stats) != 1 || stats[0].Source != "source-a" || stats[0].ConsumptionKg != 0.4 || stats[0].SampleCount != 10 { t.Fatalf("stats = %#v", stats) } } func TestBuildHydrogenDailyStatsOrderedMatchesUnorderedCalculation(t *testing.T) { base := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) values := hydrogenActiveTestSegment("LTEST32960VIN0001", "source-a", base, 10, 9.6) duplicates := append([]HydrogenObservation(nil), values...) for index := range duplicates { duplicates[index].Source = "source-b" } ordered := make([]HydrogenObservation, 0, len(values)+len(duplicates)) for index := range values { ordered = append(ordered, values[index], duplicates[index]) } stats := BuildHydrogenDailyStatsOrdered(ordered, "2026-07-01", 0.05, 5) if len(stats) != 1 || stats[0].ConsumptionKg != 0.4 || stats[0].SampleCount != 10 { t.Fatalf("stats = %#v", stats) } } func TestBuildHydrogenDailyStatsDoesNotReplaceBoundariesWithWholeDayMinimum(t *testing.T) { base := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) values := hydrogenActiveTestSegment("LTEST32960VIN0001", "source-a", base, 10, 9.8) values = append(values[:5], append([]HydrogenObservation{{ VIN: "LTEST32960VIN0001", Source: "source-a", ObservedAt: base.Add(5 * time.Second), MassKg: 9, NoiseKg: 0.05, RefuelThresholdKg: 1, FuelCellActive: true, FuelCellStateKnown: true, SOCPercent: 50, SOCKnown: true, MileageKm: 10, MileageKnown: true, VehicleState: 1, VehicleStateKnown: true, ChargeState: 3, ChargeStateKnown: true, RunningMode: 2, RunningModeKnown: true, }}, values[5:]...)...) for index := 6; index < len(values); index++ { values[index].ObservedAt = base.Add(time.Duration(index) * time.Second) } stats := BuildHydrogenDailyStats(values, "2026-07-01", 0.05, 5) if len(stats) != 1 || stats[0].ConsumptionKg != 0.2 { t.Fatalf("stats = %#v", stats) } } func TestHydrogenSegmentAccumulatorKeepsOnlyBoundedEndpointWindows(t *testing.T) { base := time.Now() accumulator := newHydrogenSegmentAccumulator(0.05, 20) for index := 0; index < 10000; index++ { accumulator.Add(HydrogenObservation{ ObservedAt: base.Add(time.Duration(index) * time.Second), MassKg: 20 - float64(index)/10000, NoiseKg: 0.05, RefuelThresholdKg: 1, FuelCellActive: true, FuelCellStateKnown: true, }) } if len(accumulator.segmentFirst) != hydrogenSegmentEndpointWindow || len(accumulator.segmentTail) != hydrogenSegmentEndpointWindow { t.Fatalf("first=%d tail=%d", len(accumulator.segmentFirst), len(accumulator.segmentTail)) } consumption, segments, _, _ := accumulator.Finalize() if consumption <= 0 || segments != 1 { t.Fatalf("consumption=%v segments=%d", consumption, segments) } } func TestBuildHydrogenDailyStatsRejectsInactivePressureFall(t *testing.T) { base := time.Date(2026, 8, 15, 0, 0, 0, 0, time.UTC) stats := BuildHydrogenDailyStats([]HydrogenObservation{ {VIN: "LTEST32960VIN0001", ObservedAt: base, MassKg: 10, PressureMPa: 28.2, VehicleState: 2, VehicleStateKnown: true}, {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(time.Minute), MassKg: 8, PressureMPa: 22, VehicleState: 2, VehicleStateKnown: true}, {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(2 * time.Minute), MassKg: 5, PressureMPa: 12.8, VehicleState: 2, VehicleStateKnown: true}, }, "2026-08-15", 0.05, 20) if len(stats) != 1 || stats[0].ConsumptionKg != 0 || stats[0].QualityStatus != "NO_DATA" { t.Fatalf("stats = %#v", stats) } } func hydrogenActiveTestSegment(vin, source string, start time.Time, startMass, endMass float64) []HydrogenObservation { values := make([]HydrogenObservation, 0, hydrogenSegmentEndpointWindow*2) for index := 0; index < hydrogenSegmentEndpointWindow*2; index++ { mass := startMass if index >= hydrogenSegmentEndpointWindow { mass = endMass } values = append(values, HydrogenObservation{ VIN: vin, Source: source, ObservedAt: start.Add(time.Duration(index) * time.Second), MassKg: mass, PressureMPa: mass, NoiseKg: 0.05, RefuelThresholdKg: 1, FuelCellActive: true, FuelCellStateKnown: true, SOCPercent: 50, SOCKnown: true, MileageKm: float64(index) * 2, MileageKnown: true, VehicleState: 1, VehicleStateKnown: true, ChargeState: 3, ChargeStateKnown: true, RunningMode: 2, RunningModeKnown: true, }) } return values } func TestExtractHydrogenMassSupportsCanonicalStringAndNumber(t *testing.T) { for _, encoded := range []string{ `{"gb32960.gd_fc_vehicle_info.hydrogen_mass_kg":"12.3"}`, `{"gb32960.gd_fc_vehicle_info.hydrogen_mass_kg":12.3}`, } { value, ok := ExtractHydrogenMass(encoded) if !ok || value != 12.3 { t.Fatalf("value=%v ok=%v for %s", value, ok, encoded) } } } func TestPressureHydrogenMassMatchesGuangdongVehicle(t *testing.T) { mass, ok := PressureHydrogenMassKg(16.4, 34, 380) if !ok || mass < 4.47 || mass > 4.49 { t.Fatalf("mass=%.3f ok=%v", mass, ok) } pressure, temperature, ok := ExtractHydrogenPressureTemperature(`{ "gb32960.fuel_cell.max_hydrogen_pressure_mpa":"16.4", "gb32960.fuel_cell.max_hydrogen_temperature_c":34, "gb32960.gd_fc_vehicle_info.hydrogen_mass_kg":99.9 }`) if !ok || pressure != 16.4 || temperature != 34 { t.Fatalf("pressure=%v temperature=%v ok=%v", pressure, temperature, ok) } } func TestExtractHydrogenPressureTemperatureRejectsPlaceholders(t *testing.T) { for _, encoded := range []string{ `{"gb32960.fuel_cell.max_hydrogen_pressure_mpa":0,"gb32960.fuel_cell.max_hydrogen_temperature_c":30}`, `{"gb32960.fuel_cell.max_hydrogen_pressure_mpa":22.8,"gb32960.fuel_cell.max_hydrogen_temperature_c":-40}`, } { if _, _, ok := ExtractHydrogenPressureTemperature(encoded); ok { t.Fatalf("pressure/temperature placeholder must be rejected: %s", encoded) } } } func TestExtractHydrogenFuelCellState(t *testing.T) { for _, test := range []struct { encoded string active bool known bool }{ {`{"gb32960.gd_fc_stack.engine_work_state":2}`, true, true}, {`{"gb32960.gd_fc_stack.engine_work_state":0}`, false, true}, {`{"gb32960.gd_fc_stack.engine_work_state":1}`, false, false}, {`{"gb32960.gd_fc_stack.engine_work_state":1,"gb32960.fuel_cell.fuel_cell_current_a":94.1}`, true, true}, {`{"gb32960.gd_fc_stack.engine_work_state":2,"gb32960.fuel_cell.fuel_cell_current_a":0}`, false, true}, {`{"gb32960.fuel_cell.fuel_cell_current_a":0.2}`, false, true}, {`{}`, false, false}, } { active, known := ExtractHydrogenFuelCellState(test.encoded) if active != test.active || known != test.known { t.Fatalf("encoded=%s active=%v known=%v", test.encoded, active, known) } } } func TestExtractHydrogenTelemetryReadsPressureTemperatureAndStateTogether(t *testing.T) { pressure, temperature, active, known, ok := ExtractHydrogenTelemetry(`{ "gb32960.fuel_cell.max_hydrogen_pressure_mpa":28.2, "gb32960.fuel_cell.max_hydrogen_temperature_c":35, "gb32960.gd_fc_stack.engine_work_state":2 }`) if !ok || pressure != 28.2 || temperature != 35 || !active || !known { t.Fatalf("pressure=%v temperature=%v active=%v known=%v ok=%v", pressure, temperature, active, known, ok) } } func TestExtractHydrogenTelemetryFastMatchesJSONDecoder(t *testing.T) { for _, encoded := range []string{ `{"gb32960.fuel_cell.max_hydrogen_pressure_mpa":28.2,"gb32960.fuel_cell.max_hydrogen_temperature_c":35,"gb32960.gd_fc_stack.engine_work_state":2}`, `{ "gb32960.fuel_cell.fuel_cell_current_a" : "0.5", "gb32960.fuel_cell.max_hydrogen_temperature_c" : "35", "gb32960.fuel_cell.max_hydrogen_pressure_mpa" : "28.2" }`, `{"unrelated":"gb32960.fuel_cell.max_hydrogen_pressure_mpa","gb32960.fuel_cell.max_hydrogen_pressure_mpa":28.2,"gb32960.fuel_cell.max_hydrogen_temperature_c":35}`, } { wantPressure, wantTemperature, wantActive, wantKnown, wantOK := ExtractHydrogenTelemetry(encoded) pressure, temperature, active, known, ok := extractHydrogenTelemetryFast(encoded) if pressure != wantPressure || temperature != wantTemperature || active != wantActive || known != wantKnown || ok != wantOK { t.Fatalf("fast=(%v,%v,%v,%v,%v) decoded=(%v,%v,%v,%v,%v) input=%s", pressure, temperature, active, known, ok, wantPressure, wantTemperature, wantActive, wantKnown, wantOK, encoded) } } } func TestHydrogenObservationQueryUsesEventTimeAndScopedVIN(t *testing.T) { loc := time.FixedZone("Asia/Shanghai", 8*3600) start := time.Date(2026, 8, 12, 0, 0, 0, 0, loc) query, err := buildHydrogenObservationQuery("lingniu_vehicle_ts", start, start.AddDate(0, 0, 1), "LB9A32A24R0LS1376") if err != nil { t.Fatal(err) } for _, want := range []string{ "CAST(event_time AS BIGINT)", "ts>='2026-08-12T00:00:00+08:00'", "ts<'2026-08-13T00:00:00+08:00'", "event_time>='2026-08-12T00:00:00+08:00'", "event_time<'2026-08-13T00:00:00+08:00'", "vin='LB9A32A24R0LS1376'", "protocol='GB32960'", "ORDER BY vin,event_time,source_endpoint,ts", } { if !strings.Contains(query, want) { t.Fatalf("query missing %q:\n%s", want, query) } } if strings.Contains(query, "CAST(ts AS BIGINT)") { t.Fatalf("received time must not become observation time:\n%s", query) } if strings.Contains(query, "YUTONG_MQTT") || strings.Contains(query, "JT808") { t.Fatalf("hydrogen query must only use GB32960 frames:\n%s", query) } if strings.Contains(query, "2026-08-05") || strings.Contains(query, "2026-08-20") { t.Fatalf("received-time window must not include delayed frames:\n%s", query) } } func TestHydrogenObservationVINQueryUsesSameDayGB32960Watermark(t *testing.T) { loc := time.FixedZone("Asia/Shanghai", 8*3600) start := time.Date(2026, 8, 12, 0, 0, 0, 0, loc) query, err := buildHydrogenObservationVINQuery("lingniu_vehicle_ts", start, start.AddDate(0, 0, 1)) if err != nil { t.Fatal(err) } for _, want := range []string{ "SELECT DISTINCT vin", "protocol='GB32960'", "ts>='2026-08-12T00:00:00+08:00'", "ts<'2026-08-13T00:00:00+08:00'", "event_time>='2026-08-12T00:00:00+08:00'", "event_time<'2026-08-13T00:00:00+08:00'", "ORDER BY vin", } { if !strings.Contains(query, want) { t.Fatalf("query missing %q:\n%s", want, query) } } if strings.Contains(query, "YUTONG_MQTT") || strings.Contains(query, "JT808") { t.Fatalf("VIN query must only use GB32960:\n%s", query) } } func TestLoadHydrogenObservationVINsFiltersMissingCapacity(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() mock.ExpectQuery("SELECT DISTINCT vin").WillReturnRows(sqlmock.NewRows([]string{"vin"}). AddRow("lb9a32a25r0ls1452"). AddRow("LB9A32A24R0LS1376")) loc := time.FixedZone("Asia/Shanghai", 8*3600) start := time.Date(2026, 8, 12, 0, 0, 0, 0, loc) vins, err := LoadHydrogenObservationVINs(context.Background(), db, "lingniu_vehicle_ts", start, start.AddDate(0, 0, 1), map[string]float64{ "LB9A32A25R0LS1452": 520, }) if err != nil || len(vins) != 1 || vins[0] != "LB9A32A25R0LS1452" { t.Fatalf("vins=%v err=%v", vins, err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } } func TestLoadHydrogenBrandVINsUsesExactBrandAndValidVINs(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() mock.ExpectQuery(regexp.QuoteMeta("SELECT UPPER(TRIM(vin))")). WithArgs("现代"). WillReturnRows(sqlmock.NewRows([]string{"vin"}). AddRow("lb9a32a25r0ls1452"). AddRow("invalid")) vins, err := LoadHydrogenBrandVINs(context.Background(), db, " 现代 ") if err != nil || len(vins) != 1 || vins[0] != "LB9A32A25R0LS1452" { t.Fatalf("vins=%v err=%v", vins, err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } } func TestHydrogenObservationDateRangeForAllUsesBoundedQueries(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() first := time.Date(2026, 6, 21, 8, 0, 0, 0, time.FixedZone("Asia/Shanghai", 8*3600)) last := time.Date(2026, 8, 18, 9, 0, 0, 0, time.FixedZone("Asia/Shanghai", 8*3600)) mock.ExpectQuery("ORDER BY event_time ASC LIMIT 1"). WillReturnRows(sqlmock.NewRows([]string{"event_time"}).AddRow(first)) mock.ExpectQuery("ORDER BY event_time DESC LIMIT 1"). WillReturnRows(sqlmock.NewRows([]string{"event_time"}).AddRow(last)) gotFirst, gotLast, found, err := HydrogenObservationDateRangeForAll(context.Background(), db, "lingniu_vehicle_ts") if err != nil || !found || !gotFirst.Equal(first) || !gotLast.Equal(last) { t.Fatalf("range first=%v last=%v found=%v err=%v", gotFirst, gotLast, found, err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } } func TestReplaceHydrogenDailyStatsForVINDeletesOnlyScopedVehicle(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() vin := "LB9A32A24R0LS1376" mock.ExpectBegin() mock.ExpectExec(regexp.QuoteMeta("DELETE FROM vehicle_open_daily_energy WHERE stat_date=? AND energy_type='HYDROGEN' AND vin=?")). WithArgs("2026-08-12", vin). WillReturnResult(sqlmock.NewResult(0, 1)) mock.ExpectExec(regexp.QuoteMeta("INSERT INTO vehicle_open_daily_energy(")). WithArgs(vin, "2026-08-12", "source-a", 8.691, 7.64, 10.515, 2803, 2, "OK", "", 8.691, sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), 0.0, 0.0, sqlmock.AnyArg(), sqlmock.AnyArg(), 0, 0, 0, "", sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectCommit() err = ReplaceHydrogenDailyStatsForVIN(context.Background(), db, "2026-08-12", vin, []HydrogenDailyStat{{ VIN: vin, Date: "2026-08-12", Source: "source-a", ConsumptionKg: 8.691, FirstMassKg: 7.64, LastMassKg: 10.515, SampleCount: 2803, RefuelCount: 2, QualityStatus: "OK", }}) if err != nil { t.Fatal(err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } } func TestReplaceHydrogenDailyStatsForVINsDeletesOnlyScopedBrandVehicles(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() vins := []string{"LB9A32A24R0LS1376", "LB9A32A25R0LS1452"} stat := HydrogenDailyStat{ VIN: vins[0], Date: "2026-08-12", Source: "source-a", ConsumptionKg: 2.5, FirstMassKg: 12, LastMassKg: 9.5, SampleCount: 500, QualityStatus: "OK", } mock.ExpectBegin() mock.ExpectExec(regexp.QuoteMeta("DELETE FROM vehicle_open_daily_energy WHERE stat_date=? AND energy_type='HYDROGEN' AND vin IN (?,?)")). WithArgs(stat.Date, vins[0], vins[1]). WillReturnResult(sqlmock.NewResult(0, 2)) mock.ExpectExec(regexp.QuoteMeta("INSERT INTO vehicle_open_daily_energy(")). WithArgs(stat.VIN, stat.Date, stat.Source, stat.ConsumptionKg, stat.FirstMassKg, stat.LastMassKg, stat.SampleCount, 0, stat.QualityStatus, "", stat.ConsumptionKg, sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), 0.0, 0.0, sqlmock.AnyArg(), sqlmock.AnyArg(), 0, 0, 0, "", sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectCommit() if err := ReplaceHydrogenDailyStatsForVINs(context.Background(), db, stat.Date, vins, []HydrogenDailyStat{stat}); err != nil { t.Fatal(err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } } func TestReplaceHydrogenDailyStatsAndSeedStreamIsAtomic(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() vin := "LB9A32A24R0LS1376" loc := time.FixedZone("Asia/Shanghai", 8*3600) first := HydrogenObservation{VIN: vin, Source: "source-a", ObservedAt: time.Date(2026, 8, 19, 8, 0, 0, 0, loc), MassKg: 12, TankCapacityLiter: 520, PressureMPa: 30, TemperatureC: 31, FuelCellActive: true, FuelCellStateKnown: true} last := HydrogenObservation{VIN: vin, Source: "source-b", ObservedAt: time.Date(2026, 8, 19, 11, 0, 0, 0, loc), MassKg: 9.4, TankCapacityLiter: 520, PressureMPa: 22, TemperatureC: 35, FuelCellActive: true, FuelCellStateKnown: true} stat := HydrogenDailyStat{ VIN: vin, Date: "2026-08-19", Source: "source-a", ConsumptionKg: 2.6, FirstMassKg: 12, LastMassKg: 9.4, CycleMinimumMassKg: 9.4, SampleCount: 500, RefuelCount: 1, EligibleIntervalCount: 460, QualifiedSegmentCount: 2, FirstObservation: first, LastObservation: last, QualityStatus: "OK", } mock.ExpectBegin() mock.ExpectExec(regexp.QuoteMeta("DELETE FROM vehicle_open_daily_energy WHERE stat_date=? AND energy_type='HYDROGEN'")). WithArgs("2026-08-19").WillReturnResult(sqlmock.NewResult(0, 3)) mock.ExpectExec(regexp.QuoteMeta("DELETE FROM vehicle_open_hydrogen_segment_stream_state WHERE stat_date=?")). WithArgs("2026-08-19").WillReturnResult(sqlmock.NewResult(0, 0)) mock.ExpectExec(regexp.QuoteMeta("INSERT INTO vehicle_open_daily_energy(")). WithArgs(vin, "2026-08-19", "source-a", 2.6, 12.0, 9.4, 500, 1, "OK", "", 2.6, sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), 0.0, 0.0, sqlmock.AnyArg(), sqlmock.AnyArg(), 0, 2, 0, "", sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectExec(regexp.QuoteMeta("INSERT INTO vehicle_open_hydrogen_segment_stream_state(")). WithArgs(vin, "2026-08-19", "source-a", 2.6, 2.6, 500, 1, 0, 460, 2, 9.4, last.ObservedAt, "", sqlmock.AnyArg(), "OK", ""). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectCommit() if err := ReplaceHydrogenDailyStatsAndSeedStream(context.Background(), db, "2026-08-19", []HydrogenDailyStat{stat}); err != nil { t.Fatal(err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } encoded, err := hydrogenSegmentStreamSeedJSON(stat) if err != nil { t.Fatal(err) } var state map[string]any if err := json.Unmarshal(encoded, &state); err != nil { t.Fatal(err) } if state["lastMassKg"] != 9.4 || state["finalizedHydrogenKg"] != 2.6 || state["lastEventTime"] == "" || state["algorithmVersion"] != trustedHydrogenAlgorithmVersion { t.Fatalf("seed state=%s", encoded) } } func TestReplaceHydrogenDailyStatsAndSeedStreamSkipsMissingWatermark(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatal(err) } defer db.Close() stat := HydrogenDailyStat{ VIN: "LB9A32A24R0LS1376", Date: "2026-09-04", Source: "source-a", QualityStatus: "NO_DATA", QualityReason: "有效运行分界点不足2条", } mock.ExpectBegin() mock.ExpectExec(regexp.QuoteMeta("DELETE FROM vehicle_open_daily_energy WHERE stat_date=? AND energy_type='HYDROGEN'")). WithArgs("2026-09-04").WillReturnResult(sqlmock.NewResult(0, 1)) mock.ExpectExec(regexp.QuoteMeta("DELETE FROM vehicle_open_hydrogen_segment_stream_state WHERE stat_date=?")). WithArgs("2026-09-04").WillReturnResult(sqlmock.NewResult(0, 0)) mock.ExpectExec(regexp.QuoteMeta("INSERT INTO vehicle_open_daily_energy(")). WithArgs(stat.VIN, stat.Date, stat.Source, 0.0, 0.0, 0.0, 0, 0, stat.QualityStatus, stat.QualityReason, 0.0, sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), 0.0, 0.0, sqlmock.AnyArg(), sqlmock.AnyArg(), 0, 0, 0, "", sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnResult(sqlmock.NewResult(1, 1)) mock.ExpectCommit() if err := ReplaceHydrogenDailyStatsAndSeedStream(context.Background(), db, stat.Date, []HydrogenDailyStat{stat}); err != nil { t.Fatal(err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatal(err) } }