package openplatform import ( "testing" "time" ) func TestBuildHydrogenDailyStatsSumsDropsAndIgnoresRefuelAndNoise(t *testing.T) { base := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) stats := BuildHydrogenDailyStats([]HydrogenObservation{ {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(3 * time.Hour), MassKg: 10.00}, {VIN: "LTEST32960VIN0001", ObservedAt: base, MassKg: 10.50}, {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(time.Hour), MassKg: 10.30}, {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(2 * time.Hour), MassKg: 11.90}, {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(4 * time.Hour), MassKg: 9.98}, }, "2026-07-01", 0.05, 5) if len(stats) != 1 { t.Fatalf("stats = %#v", stats) } stat := stats[0] if stat.ConsumptionKg != 2.1 || stat.RefuelCount != 1 || stat.SampleCount != 5 || stat.QualityStatus != "OK" { t.Fatalf("stat = %#v", stat) } } func TestBuildHydrogenDailyStatsMarksLargeDropSuspect(t *testing.T) { base := time.Now() stats := BuildHydrogenDailyStats([]HydrogenObservation{ {VIN: "LTEST32960VIN0001", ObservedAt: base, MassKg: 20}, {VIN: "LTEST32960VIN0001", ObservedAt: base.Add(time.Minute), MassKg: 1}, }, "2026-07-01", 0.05, 5) if len(stats) != 1 || stats[0].QualityStatus != "SUSPECT" || stats[0].ConsumptionKg != 0 { t.Fatalf("stats = %#v", stats) } } func TestBuildHydrogenDailyStatsDoesNotMixSources(t *testing.T) { base := time.Now() stats := BuildHydrogenDailyStats([]HydrogenObservation{ {VIN: "LTEST32960VIN0001", Source: "source-a", ObservedAt: base, MassKg: 10}, {VIN: "LTEST32960VIN0001", Source: "source-a", ObservedAt: base.Add(2 * time.Minute), MassKg: 9.8}, {VIN: "LTEST32960VIN0001", Source: "source-a", ObservedAt: base.Add(4 * time.Minute), MassKg: 9.6}, {VIN: "LTEST32960VIN0001", Source: "source-b", ObservedAt: base.Add(time.Minute), MassKg: 20}, {VIN: "LTEST32960VIN0001", Source: "source-b", ObservedAt: base.Add(3 * time.Minute), MassKg: 19.9}, }, "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 != 3 { t.Fatalf("stat = %#v", stats[0]) } } 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) } }