setting_clash_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. package service
  2. import (
  3. "strings"
  4. "testing"
  5. "github.com/mhsanaei/3x-ui/v3/internal/database"
  6. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  7. )
  8. func TestValidateRegex(t *testing.T) {
  9. for _, pattern := range []string{"", `(?i)^jsonclient([ /]|$)`, `(?m)^general-purpose$`} {
  10. if err := ValidateRegex(pattern); err != nil {
  11. t.Errorf("ValidateRegex(%q) returned %v", pattern, err)
  12. }
  13. }
  14. for _, pattern := range []string{"[", strings.Repeat("a", 2049)} {
  15. if err := ValidateRegex(pattern); err == nil {
  16. t.Errorf("ValidateRegex(%q) accepted an invalid pattern", pattern)
  17. }
  18. }
  19. }
  20. func TestSubscriptionAutoDetectDefaultsWithoutStoredRows(t *testing.T) {
  21. setupSettingTestDB(t)
  22. keys := []string{"subClashAutoDetect", "subClashUserAgentRegex", "subJsonAutoDetect", "subJsonAlwaysArray", "subJsonUserAgentRegex"}
  23. if err := database.GetDB().Where("key IN ?", keys).Delete(&model.Setting{}).Error; err != nil {
  24. t.Fatal(err)
  25. }
  26. s := &SettingService{}
  27. clashEnabled, err := s.GetSubClashAutoDetect()
  28. if err != nil {
  29. t.Fatal(err)
  30. }
  31. jsonEnabled, err := s.GetSubJsonAutoDetect()
  32. if err != nil {
  33. t.Fatal(err)
  34. }
  35. jsonAlwaysArray, err := s.GetSubJsonAlwaysArray()
  36. if err != nil {
  37. t.Fatal(err)
  38. }
  39. clashRegex, err := s.GetSubClashUserAgentRegex()
  40. if err != nil {
  41. t.Fatal(err)
  42. }
  43. jsonRegex, err := s.GetSubJsonUserAgentRegex()
  44. if err != nil {
  45. t.Fatal(err)
  46. }
  47. if clashEnabled || jsonEnabled || jsonAlwaysArray {
  48. t.Fatalf("missing subscription flags must default off: clashAuto=%v jsonAuto=%v jsonAlwaysArray=%v", clashEnabled, jsonEnabled, jsonAlwaysArray)
  49. }
  50. if clashRegex != "" {
  51. t.Fatalf("missing Clash regex = %q, want empty inherited value", clashRegex)
  52. }
  53. if jsonRegex != "" {
  54. t.Fatalf("missing JSON regex = %q, want empty inherited value", jsonRegex)
  55. }
  56. var count int64
  57. if err := database.GetDB().Model(&model.Setting{}).Where("key IN ?", keys).Count(&count).Error; err != nil {
  58. t.Fatal(err)
  59. }
  60. if count != 0 {
  61. t.Fatalf("default lookup unexpectedly persisted %d setting rows", count)
  62. }
  63. }
  64. func TestUpdateAllSettingPreservesEmptyUserAgentRegexes(t *testing.T) {
  65. setupSettingTestDB(t)
  66. s := &SettingService{}
  67. settings, err := s.GetAllSetting()
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. settings.SubJsonUserAgentRegex = " "
  72. settings.SubClashUserAgentRegex = ""
  73. if err := s.UpdateAllSetting(settings, SecretClears{}); err != nil {
  74. t.Fatal(err)
  75. }
  76. for _, key := range []string{"subJsonUserAgentRegex", "subClashUserAgentRegex"} {
  77. var stored model.Setting
  78. if err := database.GetDB().Where("key = ?", key).First(&stored).Error; err != nil {
  79. t.Fatal(err)
  80. }
  81. if stored.Value != "" {
  82. t.Fatalf("%s stored value = %q, want empty inherited value", key, stored.Value)
  83. }
  84. }
  85. }
  86. func TestUpdateAllSettingPersistsClashSubscriptionSettings(t *testing.T) {
  87. setupSettingTestDB(t)
  88. s := &SettingService{}
  89. settings, err := s.GetAllSetting()
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. if settings.SubClashAutoDetect {
  94. t.Fatal("subClashAutoDetect default = true, want false")
  95. }
  96. if settings.SubJsonAutoDetect {
  97. t.Fatal("subJsonAutoDetect default = true, want false")
  98. }
  99. if settings.SubJsonAlwaysArray {
  100. t.Fatal("subJsonAlwaysArray default = true, want false")
  101. }
  102. if settings.SubJsonUserAgentRegex != "" {
  103. t.Fatalf("subJsonUserAgentRegex = %q, want empty inherited value", settings.SubJsonUserAgentRegex)
  104. }
  105. if settings.SubClashUserAgentRegex != "" {
  106. t.Fatalf("subClashUserAgentRegex = %q, want empty inherited value", settings.SubClashUserAgentRegex)
  107. }
  108. settings.SubClashAutoDetect = true
  109. settings.SubClashUserAgentRegex = `(?i)^custom-clash/`
  110. settings.SubJsonAutoDetect = true
  111. settings.SubJsonAlwaysArray = true
  112. settings.SubJsonUserAgentRegex = `(?i)^custom-json/`
  113. settings.SubJsonEnable = true
  114. settings.SubJsonPath = "/json-custom/"
  115. settings.SubJsonURI = "https://subscriptions.example.com/json-custom/"
  116. settings.SubClashEnable = true
  117. settings.SubClashPath = "/clash-custom/"
  118. settings.SubClashURI = "https://subscriptions.example.com/clash-custom/"
  119. settings.SubClashEnableRouting = true
  120. settings.SubClashRules = "GEOIP,private,DIRECT"
  121. if err := s.UpdateAllSetting(settings, SecretClears{}); err != nil {
  122. t.Fatal(err)
  123. }
  124. got, err := s.GetAllSetting()
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. if !got.SubClashEnable {
  129. t.Fatal("subClashEnable = false, want true")
  130. }
  131. if !got.SubClashAutoDetect {
  132. t.Fatal("subClashAutoDetect = false, want true")
  133. }
  134. if !got.SubJsonAutoDetect {
  135. t.Fatal("subJsonAutoDetect = false, want true")
  136. }
  137. if !got.SubJsonAlwaysArray {
  138. t.Fatal("subJsonAlwaysArray = false, want true")
  139. }
  140. if !got.SubJsonEnable {
  141. t.Fatal("subJsonEnable = false, want true")
  142. }
  143. if got.SubJsonPath != "/json-custom/" {
  144. t.Fatalf("subJsonPath = %q, want %q", got.SubJsonPath, "/json-custom/")
  145. }
  146. if got.SubJsonURI != "https://subscriptions.example.com/json-custom/" {
  147. t.Fatalf("subJsonURI = %q, want %q", got.SubJsonURI, "https://subscriptions.example.com/json-custom/")
  148. }
  149. if got.SubJsonUserAgentRegex != `(?i)^custom-json/` {
  150. t.Fatalf("subJsonUserAgentRegex = %q, want %q", got.SubJsonUserAgentRegex, `(?i)^custom-json/`)
  151. }
  152. if got.SubClashUserAgentRegex != `(?i)^custom-clash/` {
  153. t.Fatalf("subClashUserAgentRegex = %q, want %q", got.SubClashUserAgentRegex, `(?i)^custom-clash/`)
  154. }
  155. if got.SubClashPath != "/clash-custom/" {
  156. t.Fatalf("subClashPath = %q, want %q", got.SubClashPath, "/clash-custom/")
  157. }
  158. if got.SubClashURI != "https://subscriptions.example.com/clash-custom/" {
  159. t.Fatalf("subClashURI = %q, want %q", got.SubClashURI, "https://subscriptions.example.com/clash-custom/")
  160. }
  161. if !got.SubClashEnableRouting {
  162. t.Fatal("subClashEnableRouting = false, want true")
  163. }
  164. if got.SubClashRules != "GEOIP,private,DIRECT" {
  165. t.Fatalf("subClashRules = %q, want %q", got.SubClashRules, "GEOIP,private,DIRECT")
  166. }
  167. }
  168. func TestUpdateAllSettingRejectsInvalidClashUserAgentRegex(t *testing.T) {
  169. setupSettingTestDB(t)
  170. s := &SettingService{}
  171. settings, err := s.GetAllSetting()
  172. if err != nil {
  173. t.Fatal(err)
  174. }
  175. settings.SubClashUserAgentRegex = "["
  176. if err := s.UpdateAllSetting(settings, SecretClears{}); err == nil {
  177. t.Fatal("UpdateAllSetting accepted an invalid Clash/Mihomo User-Agent regex")
  178. }
  179. }
  180. func TestUpdateAllSettingRejectsInvalidJsonUserAgentRegex(t *testing.T) {
  181. setupSettingTestDB(t)
  182. s := &SettingService{}
  183. settings, err := s.GetAllSetting()
  184. if err != nil {
  185. t.Fatal(err)
  186. }
  187. settings.SubJsonUserAgentRegex = "["
  188. if err := s.UpdateAllSetting(settings, SecretClears{}); err == nil {
  189. t.Fatal("UpdateAllSetting accepted an invalid Xray JSON User-Agent regex")
  190. }
  191. }