package admission_test import ( "context" "crypto/rand" "encoding/base64" "os" "testing" coreService "github.com/go-admin-team/go-admin-core/sdk/service" "gorm.io/driver/postgres" "gorm.io/gorm" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/admission" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/credential" deviceModels "git.ilapage.cn/ila/yovision/Sense/server/app/sense/device/models" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/onvif" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/rtsp" ) type onvifFixture struct{} func (onvifFixture) Profiles(context.Context, string, onvif.Credential) ([]onvif.Profile, error) { return []onvif.Profile{{Token: "main", Name: "主码流", Width: 1920, Height: 1080, Encoding: "H264", StreamURI: "rtsp://192.0.2.10/main"}, {Token: "sub", Name: "子码流", Width: 640, Height: 360, Encoding: "H264", StreamURI: "rtsp://192.0.2.10/sub"}}, nil } type rtspFixture struct{} func (rtspFixture) Verify(context.Context, string, rtsp.Credential) (rtsp.Result, error) { return rtsp.Result{Status: "ready", Detail: "合成 RTSP 可用"}, nil } func TestProfilesSurvivePostgreSQLReopen(t *testing.T) { dsn := os.Getenv("SENSE_ADMISSION_TEST_DATABASE_URL") if dsn == "" { t.Skip("set SENSE_ADMISSION_TEST_DATABASE_URL to an isolated PostgreSQL database") } db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { t.Fatal(err) } if err = db.AutoMigrate(&deviceModels.Device{}, &credential.DeviceCredential{}, &admission.Result{}, &admission.Profile{}); err != nil { t.Fatal(err) } deviceID := "issue66-postgres-device" db.Where("device_id = ?", deviceID).Delete(&admission.Profile{}) db.Where("device_id = ?", deviceID).Delete(&admission.Result{}) db.Where("device_id = ?", deviceID).Delete(&credential.DeviceCredential{}) db.Where("id = ?", deviceID).Delete(&deviceModels.Device{}) t.Cleanup(func() { db.Where("device_id = ?", deviceID).Delete(&admission.Profile{}) db.Where("device_id = ?", deviceID).Delete(&admission.Result{}) db.Where("device_id = ?", deviceID).Delete(&credential.DeviceCredential{}) db.Where("id = ?", deviceID).Delete(&deviceModels.Device{}) }) key := make([]byte, 32) if _, err = rand.Read(key); err != nil { t.Fatal(err) } t.Setenv(credential.EnvironmentKey, base64.StdEncoding.EncodeToString(key)) vault, _ := credential.NewVault(key) device := deviceModels.Device{ID: deviceID, Name: "重启持久化摄像机", Modality: deviceModels.ModalityVideo, Status: deviceModels.StatusPending, AdapterStatus: deviceModels.AdapterReady, Version: 1} if err = db.Create(&device).Error; err != nil { t.Fatal(err) } for _, purpose := range []string{credential.PurposeONVIF, credential.PurposeRTSP} { cipher, _ := vault.Encrypt(deviceID, purpose, "synthetic-user", "synthetic-password") if err = db.Create(&credential.DeviceCredential{DeviceID: deviceID, Purpose: purpose, Ciphertext: cipher, KeyVersion: credential.Version()}).Error; err != nil { t.Fatal(err) } } service := admission.Service{Service: coreService.Service{Orm: db}, ONVIF: onvifFixture{}, RTSP: rtspFixture{}} if _, err = service.Probe(context.Background(), admission.ProbeRequest{DeviceID: deviceID, Address: "http://192.0.2.10/onvif", Version: 1}); err != nil { t.Fatal(err) } reopened, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { t.Fatal(err) } restarted := admission.Service{Service: coreService.Service{Orm: reopened}} saved, err := restarted.Get(deviceID) if err != nil || saved.Status != "ready" || len(saved.Profiles) != 2 { t.Fatalf("saved=%#v err=%v", saved, err) } }