Files
lingniu-vehicle-ingest/vehicle-data-platform/apps/api/cmd/native-alarm-repair/main_test.go
T

109 lines
4.2 KiB
Go

package main
import (
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/DATA-DOG/go-sqlmock"
)
func expectSnapshot(mock sqlmock.Sqlmock, notified bool) {
mock.ExpectBegin()
mock.ExpectQuery(`SELECT \* FROM vehicle_alert_event`).WillReturnRows(sqlmock.NewRows([]string{"id", "rule_name", "status"}).AddRow("false-event", "车辆原生告警", "unprocessed").AddRow("real-event", "车辆原生告警", "processing"))
payload := func(flag string) string {
data := map[string]any{"gb32960.alarm.max_alarm_level": "0", "gb32960.alarm.general_alarm_flag": flag}
for _, key := range []string{"battery_faults", "motor_faults", "engine_faults", "other_faults"} {
data["gb32960.alarm."+key] = []string{}
}
b, _ := json.Marshal(data)
return string(b)
}
mock.ExpectQuery(`SELECT n.\* FROM vehicle_native_alarm_evidence`).WillReturnRows(sqlmock.NewRows([]string{"event_id", "fields_json"}).AddRow("false-event", payload("0x00300000")).AddRow("real-event", payload("0x00380800")))
mock.ExpectQuery(`SELECT a.\* FROM vehicle_alert_event_action`).WillReturnRows(sqlmock.NewRows([]string{"event_id", "action"}).AddRow("false-event", "trigger"))
mock.ExpectQuery(`SELECT s.\* FROM vehicle_native_alarm_state`).WillReturnRows(sqlmock.NewRows([]string{"vin", "active_event_id"}).AddRow("VIN1", "false-event"))
notifications := sqlmock.NewRows([]string{"id", "event_id"})
if notified {
notifications.AddRow(1, "false-event")
}
mock.ExpectQuery(`SELECT n.id,n.event_id`).WillReturnRows(notifications)
}
func TestRepairDryRunNeverWrites(t *testing.T) {
db, mock, _ := sqlmock.New()
defer db.Close()
expectSnapshot(mock, false)
mock.ExpectRollback()
if err := run(t.Context(), db, false, ""); err != nil {
t.Fatal(err)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatal(err)
}
}
func TestRepairBacksUpAndCorrectsOnlyNativeEvents(t *testing.T) {
db, mock, _ := sqlmock.New()
defer db.Close()
expectSnapshot(mock, false)
mock.ExpectExec(`UPDATE vehicle_native_alarm_state`).WithArgs("false-event").WillReturnResult(sqlmock.NewResult(0, 1))
mock.ExpectExec(`DELETE FROM vehicle_alert_event_action`).WithArgs("false-event").WillReturnResult(sqlmock.NewResult(0, 1))
mock.ExpectExec(`DELETE FROM vehicle_native_alarm_evidence`).WithArgs("false-event").WillReturnResult(sqlmock.NewResult(0, 1))
mock.ExpectExec(`DELETE FROM vehicle_alert_event WHERE id=\? AND rule_id='native-gb32960-alarm'`).WithArgs("false-event").WillReturnResult(sqlmock.NewResult(0, 1))
mock.ExpectExec(`UPDATE vehicle_alert_event SET rule_name=\?,version=version\+1 WHERE id=\? AND rule_id='native-gb32960-alarm'`).WithArgs("绝缘报警", "real-event").WillReturnResult(sqlmock.NewResult(0, 1))
mock.ExpectExec(`INSERT INTO vehicle_alert_event_action`).WithArgs("real-event", "processing", "processing").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
path := filepath.Join(t.TempDir(), "backup.json")
if err := run(t.Context(), db, true, path); err != nil {
t.Fatal(err)
}
data, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
var archive map[string]json.RawMessage
if err = json.Unmarshal(data, &archive); err != nil {
t.Fatal(err)
}
for _, key := range []string{"events", "evidence", "actions", "state"} {
if len(archive[key]) == 0 {
t.Fatalf("missing backup %s", key)
}
}
info, _ := os.Stat(path)
if info.Mode().Perm() != 0600 {
t.Fatal("backup permissions")
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatal(err)
}
}
func TestRepairRefusesToOverwriteBackup(t *testing.T) {
db, mock, _ := sqlmock.New()
defer db.Close()
expectSnapshot(mock, false)
mock.ExpectRollback()
path := filepath.Join(t.TempDir(), "backup.json")
if err := os.WriteFile(path, []byte("previous backup"), 0600); err != nil {
t.Fatal(err)
}
if err := run(t.Context(), db, true, path); err == nil {
t.Fatal("overwrote backup")
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatal(err)
}
}
func TestRepairRefusesToOrphanNotifications(t *testing.T) {
db, mock, _ := sqlmock.New()
defer db.Close()
expectSnapshot(mock, true)
mock.ExpectRollback()
if err := run(t.Context(), db, true, filepath.Join(t.TempDir(), "backup.json")); err == nil {
t.Fatal("deleted notified event")
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatal(err)
}
}