passage_infer_test.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package parking
  2. import (
  3. "strings"
  4. "testing"
  5. "time"
  6. "github.com/glebarez/sqlite"
  7. "gorm.io/gorm"
  8. "wails-app/internal/dao"
  9. "wails-app/internal/global"
  10. common "wails-app/internal/model/common"
  11. )
  12. // newInferTestDB 每个用例独立的内存库,避免相互污染。
  13. func newInferTestDB(t *testing.T) {
  14. t.Helper()
  15. db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
  16. if err != nil {
  17. t.Fatalf("打开内存数据库失败: %v", err)
  18. }
  19. if err := db.AutoMigrate(&dao.VehicleRecord{}); err != nil {
  20. t.Fatalf("迁移表失败: %v", err)
  21. }
  22. oldDB := global.GVA_DB
  23. global.GVA_DB = db
  24. oldMinutes := global.GVA_CONFIG.System.InoutMinStayMinutes
  25. global.GVA_CONFIG.System.InoutMinStayMinutes = 1
  26. t.Cleanup(func() {
  27. global.GVA_DB = oldDB
  28. global.GVA_CONFIG.System.InoutMinStayMinutes = oldMinutes
  29. })
  30. }
  31. func TestInferInoutDirection_NoSessionMeansEntry(t *testing.T) {
  32. newInferTestDB(t)
  33. svc := &PassageService{}
  34. dir, err := svc.inferInoutDirection(common.PassageRequest{RFIDTag: "E280001"})
  35. if err != nil {
  36. t.Fatalf("无会话应推断为进场,却返回错误: %v", err)
  37. }
  38. if dir != "in" {
  39. t.Fatalf("期望方向 in,实际 %s", dir)
  40. }
  41. }
  42. func TestInferInoutDirection_ActiveSessionPastMinStayMeansExit(t *testing.T) {
  43. newInferTestDB(t)
  44. rec := dao.VehicleRecord{
  45. PlateNumber: "湘A11111", RFIDTag: "E280001",
  46. EntryTime: time.Now().Add(-5 * time.Minute),
  47. }
  48. if err := global.GVA_DB.Create(&rec).Error; err != nil {
  49. t.Fatalf("造会话数据失败: %v", err)
  50. }
  51. svc := &PassageService{}
  52. dir, err := svc.inferInoutDirection(common.PassageRequest{RFIDTag: "E280001"})
  53. if err != nil {
  54. t.Fatalf("停留已满最小值应推断为出场,却返回错误: %v", err)
  55. }
  56. if dir != "out" {
  57. t.Fatalf("期望方向 out,实际 %s", dir)
  58. }
  59. }
  60. func TestInferInoutDirection_DuplicateReadWithinMinStayIgnored(t *testing.T) {
  61. newInferTestDB(t)
  62. rec := dao.VehicleRecord{
  63. PlateNumber: "湘A22222", RFIDTag: "E280002",
  64. EntryTime: time.Now().Add(-30 * time.Second),
  65. }
  66. if err := global.GVA_DB.Create(&rec).Error; err != nil {
  67. t.Fatalf("造会话数据失败: %v", err)
  68. }
  69. svc := &PassageService{}
  70. _, err := svc.inferInoutDirection(common.PassageRequest{RFIDTag: "E280002"})
  71. if err == nil || !strings.Contains(err.Error(), "重复读卡忽略") {
  72. t.Fatalf("最小停留内重复读卡应被忽略,实际: %v", err)
  73. }
  74. }
  75. func TestInferInoutDirection_AmbiguousSessionsFailSafe(t *testing.T) {
  76. newInferTestDB(t)
  77. now := time.Now().Add(-10 * time.Minute)
  78. for _, rec := range []dao.VehicleRecord{
  79. {PlateNumber: "湘A33333", RFIDTag: "E280003", EntryTime: now},
  80. {PlateNumber: "湘A33334", RFIDTag: "E280003", EntryTime: now},
  81. } {
  82. if err := global.GVA_DB.Create(&rec).Error; err != nil {
  83. t.Fatalf("造会话数据失败: %v", err)
  84. }
  85. }
  86. svc := &PassageService{}
  87. _, err := svc.inferInoutDirection(common.PassageRequest{RFIDTag: "E280003"})
  88. if err == nil || !strings.Contains(err.Error(), "方向推断失败") {
  89. t.Fatalf("同卡多会话应保错退出,实际: %v", err)
  90. }
  91. }