service_sort_test.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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_OrdersBySubSortIndexThenId verifies that subscription output
  10. // lists inbound links ordered by sub_sort_index ASC, breaking ties by id ASC.
  11. // The same query feeds the raw body, the HTML sub page, and the JSON/Clash
  12. // formats, so asserting on GetSubs covers all of them.
  13. func TestGetSubs_OrdersBySubSortIndexThenId(t *testing.T) {
  14. dbDir := t.TempDir()
  15. t.Setenv("XUI_DB_FOLDER", dbDir)
  16. if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
  17. t.Fatalf("InitDB: %v", err)
  18. }
  19. t.Cleanup(func() { _ = database.CloseDB() })
  20. const subId = "sub-sort"
  21. db := database.GetDB()
  22. seed := []struct {
  23. tag string
  24. port int
  25. subSortIndex int
  26. email string
  27. uuid string
  28. }{
  29. // Created in this order on purpose: without the ORDER BY the links
  30. // would come out s3, s1, s2a, s2b (creation order).
  31. {"sort-3", 42101, 3, "[email protected]", "0d68a695-4be1-4d92-a9c3-8c0f1c2cf001"},
  32. {"sort-1", 42102, 1, "[email protected]", "0d68a695-4be1-4d92-a9c3-8c0f1c2cf002"},
  33. {"sort-2a", 42103, 2, "[email protected]", "0d68a695-4be1-4d92-a9c3-8c0f1c2cf003"},
  34. {"sort-2b", 42104, 2, "[email protected]", "0d68a695-4be1-4d92-a9c3-8c0f1c2cf004"},
  35. }
  36. for _, s := range seed {
  37. settings := fmt.Sprintf(`{"clients": [{"id": %q, "email": %q, "subId": %q, "enable": true}]}`, s.uuid, s.email, subId)
  38. ib := &model.Inbound{
  39. UserId: 1,
  40. Tag: s.tag,
  41. Enable: true,
  42. Port: s.port,
  43. Protocol: model.VLESS,
  44. Settings: settings,
  45. StreamSettings: `{"network": "tcp", "security": "none"}`,
  46. SubSortIndex: s.subSortIndex,
  47. }
  48. if err := db.Create(ib).Error; err != nil {
  49. t.Fatalf("seed inbound %s: %v", s.tag, err)
  50. }
  51. client := &model.ClientRecord{Email: s.email, SubID: subId, UUID: s.uuid, Enable: true}
  52. if err := db.Create(client).Error; err != nil {
  53. t.Fatalf("seed client %s: %v", s.email, err)
  54. }
  55. if err := db.Create(&model.ClientInbound{ClientId: client.Id, InboundId: ib.Id}).Error; err != nil {
  56. t.Fatalf("seed client_inbound %s: %v", s.email, err)
  57. }
  58. }
  59. s := NewSubService(false, "-ieo")
  60. links, emails, _, _, err := s.GetSubs(subId, "sub.example.com")
  61. if err != nil {
  62. t.Fatalf("GetSubs: %v", err)
  63. }
  64. if len(links) != len(seed) {
  65. t.Fatalf("links = %d, want %d", len(links), len(seed))
  66. }
  67. want := []string{"[email protected]", "[email protected]", "[email protected]", "[email protected]"}
  68. for i, email := range want {
  69. if emails[i] != email {
  70. t.Fatalf("emails order = %v, want %v (sub_sort_index ASC, id ASC)", emails, want)
  71. }
  72. }
  73. }