feat: 重建 MediaMTX 生命周期与状态对账 (#67)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package media_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
"git.ilapage.cn/ila/yovision/Sense/server/app/sense/media"
|
||||
)
|
||||
|
||||
type readyController struct{}
|
||||
|
||||
func (readyController) Health(context.Context) error { return nil }
|
||||
func (readyController) Apply(context.Context, media.Source) error { return nil }
|
||||
func (readyController) Delete(context.Context, string) error { return nil }
|
||||
func (readyController) Status(context.Context, string) (media.PathStatus, error) {
|
||||
return media.PathStatus{Exists: true, Ready: true}, nil
|
||||
}
|
||||
|
||||
func TestPostgresColdStartRestoresDesiredRoute(t *testing.T) {
|
||||
dsn := os.Getenv("SENSE_MEDIA_TEST_DATABASE_URL")
|
||||
if dsn == "" {
|
||||
t.Skip("set SENSE_MEDIA_TEST_DATABASE_URL to run PostgreSQL media recovery")
|
||||
}
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = db.AutoMigrate(&media.Route{}, &admission.Profile{}, &credential.DeviceCredential{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
db.Exec("DROP TABLE IF EXISTS sense_media_routes, sense_admission_profiles, sense_device_credentials")
|
||||
})
|
||||
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)
|
||||
ciphertext, err := vault.Encrypt("device-pg", credential.PurposeRTSP, "synthetic-user", "synthetic-password")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = db.Create(&credential.DeviceCredential{DeviceID: "device-pg", Purpose: credential.PurposeRTSP, Ciphertext: ciphertext, KeyVersion: credential.Version()}).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = db.Create(&admission.Profile{DeviceID: "device-pg", Token: "main", Name: "Main", StreamURI: "rtsp://192.0.2.1/live", VerificationStatus: "ready", VerificationDetail: "synthetic"}).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
first := media.NewService(db, readyController{}, nil, media.RuntimeConfig{})
|
||||
if err = first.EnsureDevice(context.Background(), "device-pg"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
second := media.NewService(db.Session(&gorm.Session{NewDB: true}), readyController{}, nil, media.RuntimeConfig{})
|
||||
if err = second.ReconcileDue(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
items, err := second.List(context.Background())
|
||||
if err != nil || len(items) != 1 || items[0].Actual != "ready" {
|
||||
t.Fatalf("items=%#v err=%v", items, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user