96 lines
3.6 KiB
Go
96 lines
3.6 KiB
Go
package area
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func areaTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err = db.AutoMigrate(&Definition{}, &Version{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
statements := []string{
|
|
`CREATE TABLE sense_devices (id text primary key, name text, location text, status text)`,
|
|
`CREATE TABLE sense_admission_profiles (device_id text, token text, name text, width integer, height integer, encoding text, verification_status text)`,
|
|
`CREATE TABLE sense_media_routes (id text primary key, device_id text, profile_token text)`,
|
|
`INSERT INTO sense_devices VALUES ('device-1','东门摄像机','教学楼东门','active')`,
|
|
`INSERT INTO sense_admission_profiles VALUES ('device-1','main','主码流',1920,1080,'H264','ready')`,
|
|
`INSERT INTO sense_media_routes VALUES ('device-1:main','device-1','main')`,
|
|
}
|
|
for _, statement := range statements {
|
|
if err = db.Exec(statement).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
return db
|
|
}
|
|
|
|
func triangleRequest() UpsertRequest {
|
|
return UpsertRequest{Name: "操场危险区域", Kind: KindPolygon, RouteID: "device-1:main", Points: []Point{{0.1, 0.1}, {0.8, 0.1}, {0.5, 0.8}}, Enabled: true, UpdateBy: 7}
|
|
}
|
|
|
|
func TestVersionsAreAppendOnlyAndUseOptimisticConcurrency(t *testing.T) {
|
|
service := NewService(areaTestDB(t))
|
|
created, err := service.Create(context.Background(), triangleRequest())
|
|
if err != nil || created.Version != 1 || created.ProfileWidth != 1920 {
|
|
t.Fatalf("created=%+v err=%v", created, err)
|
|
}
|
|
request := triangleRequest()
|
|
request.Name = "操场危险区域(校准)"
|
|
request.ExpectedVersion = 1
|
|
updated, err := service.Update(context.Background(), created.ID, request)
|
|
if err != nil || updated.Version != 2 {
|
|
t.Fatalf("updated=%+v err=%v", updated, err)
|
|
}
|
|
if _, err = service.Update(context.Background(), created.ID, request); !errors.Is(err, ErrConflict) {
|
|
t.Fatalf("stale update err=%v", err)
|
|
}
|
|
versions, err := service.Versions(context.Background(), created.ID)
|
|
if err != nil || len(versions) != 2 || versions[0].Version != 2 || versions[1].Version != 1 || versions[0].SupersedesID != versions[1].ID {
|
|
t.Fatalf("versions=%+v err=%v", versions, err)
|
|
}
|
|
}
|
|
|
|
func TestProfileReplacementMarksOnlyChangedBindings(t *testing.T) {
|
|
db := areaTestDB(t)
|
|
service := NewService(db)
|
|
created, err := service.Create(context.Background(), triangleRequest())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err = MarkProfilesReplaced(db, "device-1", []ProfileSnapshot{{Token: "main", Width: 1920, Height: 1080, Encoding: "H264"}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
item, _ := service.Get(context.Background(), created.ID)
|
|
if item.NeedsRecalibration {
|
|
t.Fatal("unchanged profile was marked for recalibration")
|
|
}
|
|
if err = MarkProfilesReplaced(db, "device-1", []ProfileSnapshot{{Token: "main", Width: 1280, Height: 720, Encoding: "H264"}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
item, _ = service.Get(context.Background(), created.ID)
|
|
if !item.NeedsRecalibration {
|
|
t.Fatal("resolution change did not mark recalibration")
|
|
}
|
|
}
|
|
|
|
func TestListIsPaginatedAndDoesNotExposeMediaSecrets(t *testing.T) {
|
|
service := NewService(areaTestDB(t))
|
|
if _, err := service.Create(context.Background(), triangleRequest()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
items, total, err := service.List(context.Background(), PageRequest{Keyword: "操场", PageIndex: 1, PageSize: 10})
|
|
if err != nil || total != 1 || len(items) != 1 || items[0].RouteID != "device-1:main" {
|
|
t.Fatalf("items=%+v total=%d err=%v", items, total, err)
|
|
}
|
|
}
|