1
0

service_dedup_test.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package sub
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "testing"
  6. "github.com/mhsanaei/3x-ui/v3/internal/database"
  7. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  8. )
  9. // TestGetSubs_DuplicateSettingsClients_Deduped reproduces #5134: multi-node
  10. // sync/import drift can leave the same client twice inside an inbound's
  11. // legacy settings.clients JSON while the normalized client_inbounds table
  12. // stays clean. The subscription output must still contain one profile per
  13. // (inbound, client).
  14. func TestGetSubs_DuplicateSettingsClients_Deduped(t *testing.T) {
  15. dbDir := t.TempDir()
  16. t.Setenv("XUI_DB_FOLDER", dbDir)
  17. if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
  18. t.Fatalf("InitDB: %v", err)
  19. }
  20. t.Cleanup(func() { _ = database.CloseDB() })
  21. const subId = "sub-dup"
  22. const email = "[email protected]"
  23. const uuid = "f1b9265f-26a8-4b75-9be2-c64a94b15de1"
  24. db := database.GetDB()
  25. settings := fmt.Sprintf(`{"clients": [
  26. {"id": %q, "email": %q, "subId": %q, "enable": true},
  27. {"id": %q, "email": %q, "subId": %q, "enable": true}
  28. ]}`, uuid, email, subId, uuid, email, subId)
  29. ib := &model.Inbound{
  30. UserId: 1,
  31. Tag: "dup-in",
  32. Enable: true,
  33. Port: 42001,
  34. Protocol: model.VLESS,
  35. Settings: settings,
  36. StreamSettings: `{"network": "tcp", "security": "none"}`,
  37. }
  38. if err := db.Create(ib).Error; err != nil {
  39. t.Fatalf("seed inbound: %v", err)
  40. }
  41. client := &model.ClientRecord{Email: email, SubID: subId, UUID: uuid, Enable: true}
  42. if err := db.Create(client).Error; err != nil {
  43. t.Fatalf("seed client: %v", err)
  44. }
  45. if err := db.Create(&model.ClientInbound{ClientId: client.Id, InboundId: ib.Id}).Error; err != nil {
  46. t.Fatalf("seed client_inbound: %v", err)
  47. }
  48. s := NewSubService(false, "-ieo")
  49. links, emails, _, _, err := s.GetSubs(subId, "sub.example.com")
  50. if err != nil {
  51. t.Fatalf("GetSubs: %v", err)
  52. }
  53. if len(links) != 1 {
  54. t.Fatalf("links = %d, want 1 (duplicate settings.clients entries must collapse)", len(links))
  55. }
  56. if len(emails) != 1 {
  57. t.Fatalf("emails = %d, want 1, got %v", len(emails), emails)
  58. }
  59. }