safesight-control/internal/service/model_management_test.go
tian 96e689fec0 feat: 模型管理与人脸库产品化改进,通道部署配置状态指示
P2-14 模型管理简化:
- 上传新模型:模态框上传 → 存盘 → SHA256 入库 → 可选自动分发
- 设备兼容性矩阵:根据 Edge /v1/capabilities 区分缺失 vs 不适用
- 版本管理:从固定 auto 改为文件修改时间戳
- 更新全部智能过滤:只推送缺失/不一致的设备

P2-15 人脸库优化:
- Build 产出自动注册为标准资源,接入 Resource Task 分发系统
- 人脸库页面增加设备同步状态矩阵 + 批量同步按钮
- 人员搜索过滤
- 人脸质量评分反馈(构建诊断信息 + 通过率展示)

新增:通道部署页每台设备显示配置同步状态(对比 config_versions 与 Edge config SHA256)

文档:产品化改进计划、实施跟踪、模型与人脸库改进方案
2026-07-20 10:27:11 +08:00

104 lines
3.6 KiB
Go

package service
import (
"os"
"path/filepath"
"testing"
"safesight-control/internal/models"
"safesight-control/internal/storage"
)
func TestSyncStandardModelsFromDirectory(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "face_det_scrfd_500m_640_rk3588.rknn")
if err := os.WriteFile(path, []byte("model-bytes"), 0o644); err != nil {
t.Fatalf("WriteFile: %v", err)
}
store, err := storage.OpenSQLite(filepath.Join(t.TempDir(), "app.db"))
if err != nil {
t.Fatalf("OpenSQLite: %v", err)
}
defer store.Close()
modelsRepo := storage.NewModelsRepo(store.DB())
svc := NewModelManagementService(modelsRepo)
if err := svc.SyncStandardModelsFromDirectory(dir); err != nil {
t.Fatalf("SyncStandardModelsFromDirectory: %v", err)
}
items, err := modelsRepo.List()
if err != nil {
t.Fatalf("List: %v", err)
}
if len(items) != 1 || items[0].FileName != "face_det_scrfd_500m_640_rk3588.rknn" {
t.Fatalf("unexpected synced models: %#v", items)
}
if items[0].SHA256 == "" {
t.Fatalf("expected sha256 to be populated: %#v", items[0])
}
if items[0].ModelType != "face_detection" {
t.Fatalf("expected inferred model type face_detection, got %#v", items[0])
}
}
func TestBuildModelStatusBoardMarksMissingAndMismatch(t *testing.T) {
modelsList := []storage.StandardModelRecord{
{Name: "face_det", FileName: "face_det.rknn", SHA256: "sha-1"},
{Name: "face_recog", FileName: "face_recog.rknn", SHA256: "sha-2"},
}
devices := []*models.Device{
{DeviceID: "edge-01", DeviceName: "设备一", Online: true},
}
installed := map[string][]InstalledModelStatus{
"edge-01": {
{Name: "face_det", FileName: "face_det.rknn", SHA256: "sha-1"},
},
}
board := BuildModelStatusBoard(modelsList, devices, installed, nil)
if board.Summary.MissingDevices != 1 {
t.Fatalf("expected one device with missing models, got %#v", board.Summary)
}
if len(board.Rows) != 1 || len(board.Rows[0].Cells) != 2 {
t.Fatalf("unexpected board rows: %#v", board.Rows)
}
if board.Rows[0].Cells[1].Status != "missing" {
t.Fatalf("expected second model to be missing, got %#v", board.Rows[0].Cells[1])
}
}
func TestBuildModelStatusBoardSeparatesExtraModels(t *testing.T) {
modelsList := []storage.StandardModelRecord{
{Name: "face_det", FileName: "face_det.rknn", SHA256: "sha-1"},
}
devices := []*models.Device{
{DeviceID: "edge-01", DeviceName: "设备一", Online: true},
}
installed := map[string][]InstalledModelStatus{
"edge-01": {
{Name: "face_det", FileName: "face_det.rknn", SHA256: "sha-1"},
{Name: "best-640", FileName: "best-640.rknn", SHA256: "sha-x"},
{Name: "mobilefacenet_arcface", FileName: "mobilefacenet_arcface.rknn", SHA256: "sha-y"},
},
}
board := BuildModelStatusBoard(modelsList, devices, installed, nil)
if len(board.Rows) != 1 {
t.Fatalf("unexpected board rows: %#v", board.Rows)
}
if got := board.Rows[0].ExtraModelCount; got != 2 {
t.Fatalf("expected 2 extra models, got %#v", board.Rows[0])
}
if len(board.Rows[0].ExtraModels) != 2 {
t.Fatalf("expected extra model details to be preserved, got %#v", board.Rows[0].ExtraModels)
}
if board.Rows[0].ExtraModels[0].Name != "best-640" || board.Rows[0].ExtraModels[1].Name != "mobilefacenet_arcface" {
t.Fatalf("expected sorted extra models, got %#v", board.Rows[0].ExtraModels)
}
}